diff --git a/lcpng.c b/lcpng.c index b627d67..06b5f85 100644 --- a/lcpng.c +++ b/lcpng.c @@ -69,6 +69,22 @@ int lcp_set_default_ns(u8 *ns) { return 0; } +void +lcp_set_auto_subint (u8 is_auto) +{ + lcp_main_t *lcpm = &lcp_main; + + lcpm->auto_subint = (is_auto != 0); +} + +int +lcp_auto_subint (void) +{ + lcp_main_t *lcpm = &lcp_main; + + return lcpm->auto_subint; +} + /* * fd.io coding-style-patch-verification: ON * diff --git a/lcpng.h b/lcpng.h index 900f0a1..514d2c3 100644 --- a/lcpng.h +++ b/lcpng.h @@ -24,6 +24,7 @@ typedef struct lcp_main_s u16 msg_id_base; /* API message ID base */ u8 default_namespace[LCP_NS_LEN]; /* default namespace if set */ int default_ns_fd; + u8 auto_subint; /* Automatically create/delete LCP sub-interfaces */ /* Set when Unit testing */ u8 test_mode; } lcp_main_t; diff --git a/lcpng_if_sync.c b/lcpng_if_sync.c index 882e7e6..6d4a477 100644 --- a/lcpng_if_sync.c +++ b/lcpng_if_sync.c @@ -452,14 +452,16 @@ static clib_error_t * lcp_itf_interface_add_del (vnet_main_t *vnm, u32 sw_if_index, u32 is_create) { const vnet_sw_interface_t *sw; - const lcp_itf_pair_t *sup_lip; uword is_sub; is_sub = vnet_sw_interface_is_sub (vnm, sw_if_index); - LCP_ITF_PAIR_DBG ("interface_%s: [%u] sw %U is_sub %u", + LCP_ITF_PAIR_DBG ("interface_%s: [%u] sw %U is_sub %u auto-subint %u", is_create ? "add" : "del", sw_if_index, format_vnet_sw_if_index_name, vnet_get_main (), - sw_if_index, is_sub); + sw_if_index, is_sub, lcp_auto_subint ()); + + if (!lcp_auto_subint ()) + return NULL; sw = vnet_get_sw_interface_or_null (vnm, sw_if_index); if (!sw) @@ -472,21 +474,39 @@ lcp_itf_interface_add_del (vnet_main_t *vnm, u32 sw_if_index, u32 is_create) sw->sw_if_index, format_vnet_sw_if_index_name, vnet_get_main (), sw->sup_sw_if_index); - // If the parent has a LIP and we're in auto-create, create a LIP for this - // child - sup_lip = lcp_itf_pair_get (lcp_itf_pair_find_by_phy (sw->sup_sw_if_index)); - if (!sup_lip) - return NULL; + if (is_create) + { + const lcp_itf_pair_t *sup_lip; + u8 *name = 0; - LCP_ITF_PAIR_INFO ( - "interface_%s: %U has parent %U, enqueueing creation of LCP", - is_create ? "add" : "del", format_vnet_sw_if_index_name, vnet_get_main (), - sw->sw_if_index, format_lcp_itf_pair, sup_lip); + // If the parent has a LIP auto-create a LIP for this interface + sup_lip = + lcp_itf_pair_get (lcp_itf_pair_find_by_phy (sw->sup_sw_if_index)); + if (!sup_lip) + return NULL; - // We cannot create the interface here, because the previous interface for - // which this is a callback hasn't returned yet. - // lcp_itf_pair_create(sw->sw_if_index, (u8 *)"foo", LCP_ITF_HOST_TAP, - // sup_lip->lip_namespace, NULL); + name = format (name, "%s.%d", sup_lip->lip_host_name, sw->sub.id); + + LCP_ITF_PAIR_INFO ( + "interface_%s: %U has parent %U, auto-creating LCP with host-if %s", + is_create ? "add" : "del", format_vnet_sw_if_index_name, + vnet_get_main (), sw->sw_if_index, format_lcp_itf_pair, sup_lip, name); + + lcp_itf_pair_create (sw->sw_if_index, name, LCP_ITF_HOST_TAP, + sup_lip->lip_namespace, NULL); + + vec_free (name); + } + else + { + const lcp_itf_pair_t *lip; + + // If the interface has a LIP, auto-delete it + lip = lcp_itf_pair_get (lcp_itf_pair_find_by_phy (sw_if_index)); + if (!lip) + return NULL; + lcp_itf_pair_delete (sw_if_index); + } return NULL; } diff --git a/lcpng_interface.c b/lcpng_interface.c index 33b3af2..e76a993 100644 --- a/lcpng_interface.c +++ b/lcpng_interface.c @@ -420,10 +420,11 @@ lcp_itf_pair_del (u32 phy_sw_if_index) lip = lcp_itf_pair_get (lipi); - LCP_ITF_PAIR_INFO ("pair delete: {%U, %U, %s}", format_vnet_sw_if_index_name, - vnet_get_main (), lip->lip_phy_sw_if_index, - format_vnet_sw_if_index_name, vnet_get_main (), - lip->lip_host_sw_if_index, lip->lip_host_name); + LCP_ITF_PAIR_INFO ( + "pair_del: host:%U phy:%U host_if:%s vif:%d ns:%s", + format_vnet_sw_if_index_name, vnet_get_main (), lip->lip_host_sw_if_index, + format_vnet_sw_if_index_name, vnet_get_main (), lip->lip_phy_sw_if_index, + lip->lip_host_name, lip->lip_vif_index, lip->lip_namespace); /* invoke registered callbacks for pair deletion */ vec_foreach (vft, lcp_itf_vfts) @@ -463,7 +464,8 @@ lcp_itf_pair_del (u32 phy_sw_if_index) hash_unset (lip_db_by_vif, lip->lip_vif_index); vec_free (lip->lip_host_name); - vec_free (lip->lip_namespace); + if (lip->lip_namespace) + free (lip->lip_namespace); pool_put (lcp_itf_pair_pool, lip); return 0; @@ -474,24 +476,46 @@ lcp_itf_pair_delete_by_index (index_t lipi) { u32 host_sw_if_index; lcp_itf_pair_t *lip; - u8 *host_name; + u8 *host_name = 0; + char *ns = 0; lip = lcp_itf_pair_get (lipi); host_name = vec_dup (lip->lip_host_name); + ns = strdup ((const char *) lip->lip_namespace); host_sw_if_index = lip->lip_host_sw_if_index; lcp_itf_pair_del (lip->lip_phy_sw_if_index); if (vnet_sw_interface_is_sub (vnet_get_main (), host_sw_if_index)) { + int curr_ns_fd = -1; + int vif_ns_fd = -1; + if (ns) + { + curr_ns_fd = clib_netns_open (NULL /* self */); + vif_ns_fd = clib_netns_open ((u8 *) ns); + if (vif_ns_fd != -1) + clib_setns (vif_ns_fd); + } + lcp_netlink_del_link ((const char *) host_name); + if (vif_ns_fd != -1) + close (vif_ns_fd); + + if (curr_ns_fd != -1) + { + clib_setns (curr_ns_fd); + close (curr_ns_fd); + } + vnet_delete_sub_interface (host_sw_if_index); } else tap_delete_if (vlib_get_main (), host_sw_if_index); vec_free (host_name); + free (ns); } int @@ -524,29 +548,30 @@ lcp_itf_pair_walk (lcp_itf_pair_walk_cb_t cb, void *ctx) static clib_error_t * lcp_itf_pair_config (vlib_main_t *vm, unformat_input_t *input) { - u8 *phy; - u8 *ns; - u8 *netns; + u8 *default_ns; - phy = ns = netns = NULL; + default_ns = NULL; while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { - if (unformat (input, "netns %v", &netns)) + if (unformat (input, "default netns %v", &default_ns)) { - vec_add1 (netns, 0); - if (lcp_set_default_ns(netns) < 0) { - return clib_error_return( - 0, "lcpng namespace must be less than %d characters", - LCP_NS_LEN); - } - } + vec_add1 (default_ns, 0); + if (lcp_set_default_ns (default_ns) < 0) + { + return clib_error_return ( + 0, "linux-cp namespace must be less than %d characters", + LCP_NS_LEN); + } + } + else if (unformat (input, "lcp-auto-subint")) + lcp_set_auto_subint (1 /* is_auto */); else - return clib_error_return (0, "interfaces not found"); + return clib_error_return (0, "unknown input `%U'", + format_unformat_error, input); } - vec_free (phy); - vec_free (netns); + vec_free (default_ns); return NULL; } diff --git a/lcpng_interface.h b/lcpng_interface.h index c9fb4ee..b4a1ef1 100644 --- a/lcpng_interface.h +++ b/lcpng_interface.h @@ -164,6 +164,12 @@ lcp_itf_pair_find_by_host (u32 host_sw_if_index) return (lip_db_by_host[host_sw_if_index]); } +/** + * sub-interface auto creation/deletion for LCP + */ +void lcp_set_auto_subint (u8 is_auto); +int lcp_auto_subint (void); + typedef void (*lcp_itf_pair_add_cb_t) (lcp_itf_pair_t *); typedef void (*lcp_itf_pair_del_cb_t) (lcp_itf_pair_t *);