*/
#define _GNU_SOURCE
-#include <sched.h>
#include <fcntl.h>
#include <ctype.h>
#include <sys/socket.h>
#include <vnet/plugin/plugin.h>
#include <vnet/plugin/plugin.h>
+#include <vppinfra/linux/netns.h>
+
#include <vnet/ip/ip_punt_drop.h>
#include <vnet/fib/fib_table.h>
#include <vnet/adj/adj_mcast.h>
index_t *lip_db_by_phy;
u32 *lip_db_by_host;
+/**
+ * vector of virtual function table
+ */
+static lcp_itf_pair_vft_t *lcp_itf_vfts = NULL;
+
+void
+lcp_itf_pair_register_vft (lcp_itf_pair_vft_t *lcp_itf_vft)
+{
+ vec_add1 (lcp_itf_vfts, *lcp_itf_vft);
+}
+
#define LCP_ITF_PAIR_DBG(...) \
vlib_log_notice (lcp_itf_pair_logger, __VA_ARGS__);
else
s = format (s, " %U", format_vnet_sw_interface_name, vnm, swif_host);
- s = format (s, " %s %d type %s", lip->lip_host_name, lip->lip_vif_index,
+ s = format (s, " %v %d type %s", lip->lip_host_name, lip->lip_vif_index,
(lip->lip_host_type == LCP_ITF_HOST_TAP) ? "tap" : "tun");
if (lip->lip_namespace)
lip->lip_rewrite_len = adj->rewrite_header.data_bytes;
}
-int __clib_weak
-lcp_nl_drain_messages (void)
-{
- return 0;
-}
-
int
lcp_itf_pair_add (u32 host_sw_if_index, u32 phy_sw_if_index, u8 *host_name,
u32 host_index, lip_host_type_t host_type, u8 *ns)
if (lipi != INDEX_INVALID)
return VNET_API_ERROR_VALUE_EXIST;
- /*
- * Drain netlink messages before adding the new pair.
- * This avoids unnecessarily applying messages that were generated by
- * the creation of the tap/tun interface. By processing them before we
- * store the pair data, we will ensure that they are ignored.
- */
- lcp_nl_drain_messages ();
-
/*
* Create a new pair.
*/
lip->lip_host_type = host_type;
lip->lip_vif_index = host_index;
lip->lip_namespace = vec_dup (ns);
- lip->lip_create_ts = vlib_time_now (vlib_get_main ());
if (lip->lip_host_sw_if_index == ~0)
return 0;
0);
}
+ /* invoke registered callbacks for pair addition */
+ lcp_itf_pair_vft_t *vft;
+
+ vec_foreach (vft, lcp_itf_vfts)
+ {
+ if (vft->pair_add_fn)
+ vft->pair_add_fn (lip);
+ }
+
+ /* set timestamp when pair entered service */
+ lip->lip_create_ts = vlib_time_now (vlib_get_main ());
+
return 0;
}
ip_address_family_t af;
lcp_itf_pair_t *lip;
u32 lipi;
+ lcp_itf_pair_vft_t *vft;
lipi = lcp_itf_pair_find_by_phy (phy_sw_if_index);
format_vnet_sw_if_index_name, vnet_get_main (),
lip->lip_host_sw_if_index, lip->lip_host_name);
+ /* invoke registered callbacks for pair deletion */
+ vec_foreach (vft, lcp_itf_vfts)
+ {
+ if (vft->pair_del_fn)
+ vft->pair_del_fn (lip);
+ }
+
FOR_EACH_IP_ADDRESS_FAMILY (af)
ip_feature_enable_disable (af, N_SAFI, IP_FEATURE_INPUT,
lcp_itf_l3_feat_names[lip->lip_host_type][af],
}
lip_db_by_phy[phy_sw_if_index] = INDEX_INVALID;
- lip_db_by_phy[lip->lip_host_sw_if_index] = INDEX_INVALID;
+ lip_db_by_host[lip->lip_host_sw_if_index] = INDEX_INVALID;
+ hash_unset (lip_db_by_vif, lip->lip_vif_index);
vec_free (lip->lip_host_name);
vec_free (lip->lip_namespace);
return 1;
}
-static int
-lcp_itf_get_ns_fd (char *ns_name)
-{
- char ns_path[256] = "/proc/self/ns/net";
-
- if (ns_name)
- snprintf (ns_path, sizeof (ns_path) - 1, "/var/run/netns/%s", ns_name);
-
- return open (ns_path, O_RDONLY);
-}
-
static void
lcp_itf_set_vif_link_state (u32 vif_index, u8 up, u8 *ns)
{
if (ns)
{
- u8 *ns_path = 0;
-
- curr_ns_fd = open ("/proc/self/ns/net", O_RDONLY);
- ns_path = format (0, "/var/run/netns/%s%c", (char *) ns, 0);
- vif_ns_fd = open ((char *) ns_path, O_RDONLY);
+ curr_ns_fd = clib_netns_open (NULL /* self */);
+ vif_ns_fd = clib_netns_open (ns);
if (vif_ns_fd != -1)
- setns (vif_ns_fd, CLONE_NEWNET);
+ clib_setns (vif_ns_fd);
}
vnet_netlink_set_link_state (vif_index, up);
if (curr_ns_fd != -1)
{
- setns (curr_ns_fd, CLONE_NEWNET);
+ clib_setns (curr_ns_fd);
close (curr_ns_fd);
}
}
int
lcp_itf_pair_create (u32 phy_sw_if_index, u8 *host_if_name,
- lip_host_type_t host_if_type, u8 *ns)
+ lip_host_type_t host_if_type, u8 *ns,
+ u32 *host_sw_if_indexp)
{
vlib_main_t *vm;
vnet_main_t *vnm;
if (ns && ns[0] != 0)
{
- orig_ns_fd = lcp_itf_get_ns_fd (NULL);
- ns_fd = lcp_itf_get_ns_fd ((char *) ns);
+ orig_ns_fd = clib_netns_open (NULL /* self */);
+ ns_fd = clib_netns_open (ns);
if (orig_ns_fd == -1 || ns_fd == -1)
goto socket_close;
- setns (ns_fd, CLONE_NEWNET);
+ clib_setns (ns_fd);
}
vif_index = if_nametoindex ((const char *) host_if_name);
socket_close:
if (orig_ns_fd != -1)
{
- setns (orig_ns_fd, CLONE_NEWNET);
+ clib_setns (orig_ns_fd);
close (orig_ns_fd);
}
if (ns_fd != -1)
format_vnet_sw_if_index_name, vnet_get_main (),
host_sw_if_index, host_if_name);
+ if (host_sw_if_indexp)
+ *host_sw_if_indexp = host_sw_if_index;
+
return 0;
}
lipn = &lipn_names[*lipn_index];
lcp_itf_pair_create (lipn->lipn_phy_sw_if_index,
lipn->lipn_host_name, LCP_ITF_HOST_TAP,
- lipn->lipn_namespace);
+ lipn->lipn_namespace, NULL);
}
vec_reset_length (event_data);