Skip to content

Commit 2e21792

Browse files
committed
vnet: fix reuse of deleted interfaces
Reusing deleted interface nodes from a different device class can yield an assertion failure (and crash in prod) when the TX node slots differ, for example when reusing Loopback (ethernet-input at 0, l2-input at 1) with a BVI (forced l2-input at slot 0), or the other way around. Reuse deleted interface nodes only from the same device class. Type: fix Change-Id: I3b6bdd3d2e3f1efdaa68e8ac6691dcef8bedabf4 Signed-off-By: pim@ipng.nl
1 parent 6ad56de commit 2e21792

2 files changed

Lines changed: 16 additions & 5 deletions

File tree

src/vnet/interface.c

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -831,7 +831,7 @@ vnet_register_interface (vnet_main_t * vnm,
831831
vlib_main_t *vm = vnm->vlib_main;
832832
vnet_feature_config_main_t *fcm;
833833
vnet_config_main_t *cm;
834-
u32 hw_index, i;
834+
u32 hw_index, i, recycle_index;
835835
vlib_node_t *if_out_node =
836836
vlib_get_node (vm, vnet_interface_output_node.index);
837837

@@ -883,14 +883,23 @@ vnet_register_interface (vnet_main_t * vnm,
883883
if (dev_class->tx_function == 0 && dev_class->tx_fn_registrations == 0)
884884
goto no_output_nodes; /* No output/tx nodes to create */
885885

886-
/* If we have previously deleted interface nodes, re-use them. */
887-
if (vec_len (im->deleted_hw_interface_nodes) > 0)
886+
/* Re-use deleted nodes only from the same device class: classes wire tx
887+
* next-node slots differently and a reused node keeps its graph. */
888+
recycle_index = ~0;
889+
vec_foreach_index (i, im->deleted_hw_interface_nodes)
890+
if (im->deleted_hw_interface_nodes[i].dev_class_index == dev_class_index)
891+
{
892+
recycle_index = i;
893+
break;
894+
}
895+
896+
if (recycle_index != ~0)
888897
{
889898
vnet_hw_interface_nodes_t *hn;
890899
vlib_node_t *node;
891900
vlib_node_runtime_t *nrt;
892901

893-
hn = vec_end (im->deleted_hw_interface_nodes) - 1;
902+
hn = vec_elt_at_index (im->deleted_hw_interface_nodes, recycle_index);
894903

895904
hw->tx_node_index = hn->tx_node_index;
896905
hw->output_node_index = hn->output_node_index;
@@ -950,7 +959,7 @@ vnet_register_interface (vnet_main_t * vnm,
950959
VLIB_NODE_RUNTIME_PERF_RESET);
951960
}
952961

953-
vec_dec_len (im->deleted_hw_interface_nodes, 1);
962+
vec_delete (im->deleted_hw_interface_nodes, 1, recycle_index);
954963
}
955964
else
956965
{
@@ -1112,6 +1121,7 @@ vnet_delete_hw_interface (vnet_main_t * vnm, u32 hw_if_index)
11121121
vec_add2 (im->deleted_hw_interface_nodes, dn, 1);
11131122
dn->tx_node_index = hw->tx_node_index;
11141123
dn->output_node_index = hw->output_node_index;
1124+
dn->dev_class_index = hw->dev_class_index;
11151125
}
11161126
hash_unset_mem (im->hw_interface_by_name, hw->name);
11171127
vec_free (hw->name);

src/vnet/interface.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1070,6 +1070,7 @@ typedef struct
10701070
{
10711071
u32 output_node_index;
10721072
u32 tx_node_index;
1073+
u32 dev_class_index;
10731074
} vnet_hw_interface_nodes_t;
10741075

10751076
typedef struct

0 commit comments

Comments
 (0)