summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJohn Lo <loj@cisco.com>2018-01-18 12:44:50 -0500
committerJohn Lo <loj@cisco.com>2018-01-18 18:52:46 -0500
commit7f5bec647c9dc743c015d461d040e63a77fd0a08 (patch)
tree5feb7e1555be7c93d2d1c1ca1ad9fdfda77e7759 /src
parentec941ecb86bbce237b1c3d6c20ab17b4471d7cff (diff)
Sub-Interface deletion not cleanup hash's properly (VPP-1136)
On deleting sub-interfaces, functions vnet_delete_sub_interface() and vnet_delete_hw_interface() are not cleaning up sub-interface related hash tables and memory properly. Change-Id: I17c7c4b2078c062c77bfe48889beb677610035ca Signed-off-by: John Lo <loj@cisco.com>
Diffstat (limited to 'src')
-rw-r--r--src/vnet/ethernet/interface.c17
-rw-r--r--src/vnet/interface.c15
-rw-r--r--src/vppinfra/hash.h10
3 files changed, 24 insertions, 18 deletions
diff --git a/src/vnet/ethernet/interface.c b/src/vnet/ethernet/interface.c
index 3e78a49d62b..801c99f824d 100644
--- a/src/vnet/ethernet/interface.c
+++ b/src/vnet/ethernet/interface.c
@@ -737,29 +737,26 @@ int
vnet_delete_sub_interface (u32 sw_if_index)
{
vnet_main_t *vnm = vnet_get_main ();
+ vnet_sw_interface_t *si = vnet_get_sw_interface (vnm, sw_if_index);
int rv = 0;
if (pool_is_free_index (vnm->interface_main.sw_interfaces, sw_if_index))
return VNET_API_ERROR_INVALID_SW_IF_INDEX;
-
- vnet_interface_main_t *im = &vnm->interface_main;
- vnet_sw_interface_t *si = vnet_get_sw_interface (vnm, sw_if_index);
-
if (si->type == VNET_SW_INTERFACE_TYPE_SUB ||
si->type == VNET_SW_INTERFACE_TYPE_P2P)
{
- vnet_sw_interface_t *si = vnet_get_sw_interface (vnm, sw_if_index);
+ vnet_interface_main_t *im = &vnm->interface_main;
+ vnet_hw_interface_t *hi = vnet_get_sup_hw_interface (vnm, sw_if_index);
u64 sup_and_sub_key =
((u64) (si->sup_sw_if_index) << 32) | (u64) si->sub.id;
-
- hash_unset_mem (im->sw_if_index_by_sup_and_sub, &sup_and_sub_key);
+ hash_unset_mem_free (&im->sw_if_index_by_sup_and_sub, &sup_and_sub_key);
+ hash_unset (hi->sub_interface_sw_if_index_by_id, si->sub.id);
vnet_delete_sw_interface (vnm, sw_if_index);
}
else
- {
- rv = VNET_API_ERROR_INVALID_SUB_SW_IF_INDEX;
- }
+ rv = VNET_API_ERROR_INVALID_SUB_SW_IF_INDEX;
+
return rv;
}
diff --git a/src/vnet/interface.c b/src/vnet/interface.c
index 82eccc12436..3ae2a8d8bf2 100644
--- a/src/vnet/interface.c
+++ b/src/vnet/interface.c
@@ -704,6 +704,7 @@ vnet_register_interface (vnet_main_t * vnm,
char *tx_node_name, *output_node_name;
pool_get (im->hw_interfaces, hw);
+ memset (hw, 0, sizeof (*hw));
hw_index = hw - im->hw_interfaces;
hw->hw_if_index = hw_index;
@@ -904,19 +905,25 @@ vnet_delete_hw_interface (vnet_main_t * vnm, u32 hw_if_index)
/* Call delete callbacks. */
call_hw_interface_add_del_callbacks (vnm, hw_if_index, /* is_create */ 0);
- /* Delete software interface corresponding to hardware interface. */
- vnet_delete_sw_interface (vnm, hw->sw_if_index);
-
/* Delete any sub-interfaces. */
{
u32 id, sw_if_index;
/* *INDENT-OFF* */
- hash_foreach (id, sw_if_index, hw->sub_interface_sw_if_index_by_id, ({
+ hash_foreach (id, sw_if_index, hw->sub_interface_sw_if_index_by_id,
+ ({
+ vnet_sw_interface_t *si = vnet_get_sw_interface (vnm, sw_if_index);
+ u64 sup_and_sub_key =
+ ((u64) (si->sup_sw_if_index) << 32) | (u64) si->sub.id;
+ hash_unset_mem_free (&im->sw_if_index_by_sup_and_sub, &sup_and_sub_key);
vnet_delete_sw_interface (vnm, sw_if_index);
}));
+ hash_free (hw->sub_interface_sw_if_index_by_id);
/* *INDENT-ON* */
}
+ /* Delete software interface corresponding to hardware interface. */
+ vnet_delete_sw_interface (vnm, hw->sw_if_index);
+
{
vnet_hw_interface_nodes_t *dn;
diff --git a/src/vppinfra/hash.h b/src/vppinfra/hash.h
index 6206dd2a486..21986ea774c 100644
--- a/src/vppinfra/hash.h
+++ b/src/vppinfra/hash.h
@@ -294,10 +294,12 @@ always_inline void
hash_unset_mem_free (uword ** h, void *key)
{
hash_pair_t *hp = hash_get_pair_mem (*h, key);
- ASSERT (hp);
- key = uword_to_pointer (hp->key, void *);
- hash_unset_mem (*h, key);
- clib_mem_free (key);
+ if (PREDICT_TRUE (hp != NULL))
+ {
+ key = uword_to_pointer (hp->key, void *);
+ hash_unset_mem (*h, key);
+ clib_mem_free (key);
+ }
}
/* internal routine to free a hash table */