aboutsummaryrefslogtreecommitdiffstats
path: root/src/vnet
diff options
context:
space:
mode:
authorJohn Lo <loj@cisco.com>2018-01-23 19:21:34 -0500
committerDave Barach <openvpp@barachs.net>2018-01-24 13:56:45 +0000
commite5453d0fa29f39a7f78a7e22815566a7f4c9e5ef (patch)
tree805b3d5ad2ca314a99d9460b202c483b4ae5550a /src/vnet
parentd95c39e87bf9d21b2a9d4c49fdf7ebca2a5eab3d (diff)
Improve tunnel interface creation performance
Modify interface creation to allow creation of tunnel interfaces without dedicated per tunnel output and tx nodes which are not used for most tunnel types. Also changed interface-output node function vnet_per_buffer_interface_output() so it does not rely on hw_if_index as the next node index which is not flexible nor efficient for large scale tunnel interfaces. The improvenemts are done for VXLAN, VXLAN-GPE, GENEVE and GTPU tunnels. GRE tunnel is still using per tunnel output nodes which will be changed in a separate patch with other GRE enhencements. Change-Id: I4123c01c0d2ead814417a867adb8c8a407e4df55 Signed-off-by: John Lo <loj@cisco.com>
Diffstat (limited to 'src/vnet')
-rw-r--r--src/vnet/geneve/geneve.c19
-rw-r--r--src/vnet/interface.c50
-rw-r--r--src/vnet/interface.h4
-rw-r--r--src/vnet/interface_funcs.h8
-rw-r--r--src/vnet/interface_output.c29
-rw-r--r--src/vnet/vxlan-gpe/vxlan_gpe.c18
-rw-r--r--src/vnet/vxlan/vxlan.c29
7 files changed, 81 insertions, 76 deletions
diff --git a/src/vnet/geneve/geneve.c b/src/vnet/geneve/geneve.c
index 6bc4b67d10d..1fe73e44cdd 100644
--- a/src/vnet/geneve/geneve.c
+++ b/src/vnet/geneve/geneve.c
@@ -82,14 +82,6 @@ format_geneve_name (u8 * s, va_list * args)
return format (s, "geneve_tunnel%d", dev_instance);
}
-static uword
-dummy_interface_tx (vlib_main_t * vm,
- vlib_node_runtime_t * node, vlib_frame_t * frame)
-{
- clib_warning ("you shouldn't be here, leaking buffers...");
- return frame->n_vectors;
-}
-
static clib_error_t *
geneve_interface_admin_up_down (vnet_main_t * vnm, u32 hw_if_index, u32 flags)
{
@@ -105,7 +97,6 @@ VNET_DEVICE_CLASS (geneve_device_class, static) = {
.name = "GENEVE",
.format_device_name = format_geneve_name,
.format_tx_trace = format_geneve_encap_trace,
- .tx_function = dummy_interface_tx,
.admin_up_down_function = geneve_interface_admin_up_down,
};
/* *INDENT-ON* */
@@ -465,6 +456,11 @@ int vnet_geneve_add_del_tunnel
hi = vnet_get_hw_interface (vnm, hw_if_index);
}
+ /* Set geneve tunnel output node */
+ u32 encap_index = !is_ip6 ?
+ geneve4_encap_node.index : geneve6_encap_node.index;
+ vnet_set_interface_output_node (vnm, hw_if_index, encap_index);
+
t->hw_if_index = hw_if_index;
t->sw_if_index = sw_if_index = hi->sw_if_index;
@@ -484,8 +480,6 @@ int vnet_geneve_add_del_tunnel
fib_node_init (&t->node, FIB_NODE_TYPE_GENEVE_TUNNEL);
fib_prefix_t tun_remote_pfx;
- u32 encap_index = !is_ip6 ?
- geneve4_encap_node.index : geneve6_encap_node.index;
vnet_flood_class_t flood_class = VNET_FLOOD_CLASS_TUNNEL_NORMAL;
fib_prefix_from_ip46_addr (&t->remote, &tun_remote_pfx);
@@ -576,9 +570,6 @@ int vnet_geneve_add_del_tunnel
flood_class = VNET_FLOOD_CLASS_TUNNEL_MASTER;
}
- /* Set geneve tunnel output node */
- hi->output_node_index = encap_index;
-
vnet_get_sw_interface (vnet_get_main (), sw_if_index)->flood_class =
flood_class;
}
diff --git a/src/vnet/interface.c b/src/vnet/interface.c
index 3ae2a8d8bf2..a34bb7931ae 100644
--- a/src/vnet/interface.c
+++ b/src/vnet/interface.c
@@ -746,6 +746,9 @@ vnet_register_interface (vnet_main_t * vnm,
hw->max_l3_packet_bytes[VLIB_RX] = ~0;
hw->max_l3_packet_bytes[VLIB_TX] = ~0;
+ if (dev_class->tx_function == 0)
+ goto no_output_nodes; /* No output/tx nodes to create */
+
tx_node_name = (char *) format (0, "%v-tx", hw->name);
output_node_name = (char *) format (0, "%v-output", hw->name);
@@ -882,6 +885,7 @@ vnet_register_interface (vnet_main_t * vnm,
setup_output_node (vm, hw->output_node_index, hw_class);
setup_tx_node (vm, hw->tx_node_index, dev_class);
+no_output_nodes:
/* Call all up/down callbacks with zero flags when interface is created. */
vnet_sw_interface_set_flags_helper (vnm, hw->sw_if_index, /* flags */ 0,
VNET_INTERFACE_SET_FLAGS_HELPER_IS_CREATE);
@@ -897,7 +901,8 @@ vnet_delete_hw_interface (vnet_main_t * vnm, u32 hw_if_index)
vnet_interface_main_t *im = &vnm->interface_main;
vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, hw_if_index);
vlib_main_t *vm = vnm->vlib_main;
-
+ vnet_device_class_t *dev_class = vnet_get_device_class (vnm,
+ hw->dev_class_index);
/* If it is up, mark it down. */
if (hw->flags != 0)
vnet_hw_interface_set_flags (vnm, hw_if_index, /* flags */ 0);
@@ -924,28 +929,31 @@ vnet_delete_hw_interface (vnet_main_t * vnm, u32 hw_if_index)
/* Delete software interface corresponding to hardware interface. */
vnet_delete_sw_interface (vnm, hw->sw_if_index);
- {
- vnet_hw_interface_nodes_t *dn;
+ if (dev_class->tx_function)
+ {
+ /* Put output/tx nodes into recycle pool */
+ vnet_hw_interface_nodes_t *dn;
- /* *INDENT-OFF* */
- foreach_vlib_main ({
- vnet_interface_output_runtime_t *rt =
- vlib_node_get_runtime_data (this_vlib_main, hw->output_node_index);
-
- /* Mark node runtime as deleted so output node (if called)
- * will drop packets. */
- rt->is_deleted = 1;
- });
- /* *INDENT-ON* */
+ /* *INDENT-OFF* */
+ foreach_vlib_main
+ ({
+ vnet_interface_output_runtime_t *rt =
+ vlib_node_get_runtime_data (this_vlib_main, hw->output_node_index);
+
+ /* Mark node runtime as deleted so output node (if called)
+ * will drop packets. */
+ rt->is_deleted = 1;
+ });
+ /* *INDENT-ON* */
- vlib_node_rename (vm, hw->output_node_index,
- "interface-%d-output-deleted", hw_if_index);
- vlib_node_rename (vm, hw->tx_node_index, "interface-%d-tx-deleted",
- hw_if_index);
- vec_add2 (im->deleted_hw_interface_nodes, dn, 1);
- dn->tx_node_index = hw->tx_node_index;
- dn->output_node_index = hw->output_node_index;
- }
+ vlib_node_rename (vm, hw->output_node_index,
+ "interface-%d-output-deleted", hw_if_index);
+ vlib_node_rename (vm, hw->tx_node_index, "interface-%d-tx-deleted",
+ hw_if_index);
+ vec_add2 (im->deleted_hw_interface_nodes, dn, 1);
+ dn->tx_node_index = hw->tx_node_index;
+ dn->output_node_index = hw->output_node_index;
+ }
hash_unset_mem (im->hw_interface_by_name, hw->name);
vec_free (hw->name);
diff --git a/src/vnet/interface.h b/src/vnet/interface.h
index 5ca489db32d..2c2dc670a01 100644
--- a/src/vnet/interface.h
+++ b/src/vnet/interface.h
@@ -444,6 +444,10 @@ typedef struct vnet_hw_interface_t
/* Software index for this hardware interface. */
u32 sw_if_index;
+ /* Next index in interface-output node for this interface
+ used by node function vnet_per_buffer_interface_output() */
+ u32 output_node_next_index;
+
/* Maximum transmit rate for this interface in bits/sec. */
f64 max_rate_bits_per_sec;
diff --git a/src/vnet/interface_funcs.h b/src/vnet/interface_funcs.h
index 1f22e80f314..ac50e7cd6ca 100644
--- a/src/vnet/interface_funcs.h
+++ b/src/vnet/interface_funcs.h
@@ -160,6 +160,14 @@ u32 vnet_register_interface (vnet_main_t * vnm,
u32 dev_instance,
u32 hw_class_index, u32 hw_instance);
+/**
+ * Set interface output node - for interface registered without its output/tx
+ * nodes created because its VNET_DEVICE_CLASS did not specify any tx_function.
+ * This is typically the case for tunnel interfaces.
+ */
+void vnet_set_interface_output_node (vnet_main_t * vnm,
+ u32 hw_if_index, u32 node_index);
+
/* Creates a software interface given template. */
clib_error_t *vnet_create_sw_interface (vnet_main_t * vnm,
vnet_sw_interface_t * template,
diff --git a/src/vnet/interface_output.c b/src/vnet/interface_output.c
index e40f75bc833..563f6149708 100644
--- a/src/vnet/interface_output.c
+++ b/src/vnet/interface_output.c
@@ -513,8 +513,8 @@ vnet_per_buffer_interface_output (vlib_main_t * vm,
vnet_buffer (b1)->sw_if_index
[VLIB_TX]);
- next0 = hi0->hw_if_index;
- next1 = hi1->hw_if_index;
+ next0 = hi0->output_node_next_index;
+ next1 = hi1->output_node_next_index;
vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next,
n_left_to_next, bi0, bi1, next0,
@@ -541,7 +541,7 @@ vnet_per_buffer_interface_output (vlib_main_t * vm,
vnet_buffer (b0)->sw_if_index
[VLIB_TX]);
- next0 = hi0->hw_if_index;
+ next0 = hi0->output_node_next_index;
vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
n_left_to_next, bi0, next0);
@@ -1104,12 +1104,13 @@ vnet_per_buffer_interface_output_hw_interface_add_del (vnet_main_t * vnm,
vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index);
u32 next_index;
- next_index = vlib_node_add_next_with_slot
- (vnm->vlib_main, vnet_per_buffer_interface_output_node.index,
- hi->output_node_index,
- /* next_index */ hw_if_index);
+ if (hi->output_node_index == 0)
+ return 0;
- ASSERT (next_index == hw_if_index);
+ next_index = vlib_node_add_next
+ (vnm->vlib_main, vnet_per_buffer_interface_output_node.index,
+ hi->output_node_index);
+ hi->output_node_next_index = next_index;
return 0;
}
@@ -1117,6 +1118,18 @@ vnet_per_buffer_interface_output_hw_interface_add_del (vnet_main_t * vnm,
VNET_HW_INTERFACE_ADD_DEL_FUNCTION
(vnet_per_buffer_interface_output_hw_interface_add_del);
+void
+vnet_set_interface_output_node (vnet_main_t * vnm,
+ u32 hw_if_index, u32 node_index)
+{
+ ASSERT (node_index);
+ vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index);
+ u32 next_index = vlib_node_add_next
+ (vnm->vlib_main, vnet_per_buffer_interface_output_node.index, node_index);
+ hi->output_node_next_index = next_index;
+ hi->output_node_index = node_index;
+}
+
static clib_error_t *
pcap_drop_trace_command_fn (vlib_main_t * vm,
unformat_input_t * input,
diff --git a/src/vnet/vxlan-gpe/vxlan_gpe.c b/src/vnet/vxlan-gpe/vxlan_gpe.c
index 918a982d70d..af5dd190693 100644
--- a/src/vnet/vxlan-gpe/vxlan_gpe.c
+++ b/src/vnet/vxlan-gpe/vxlan_gpe.c
@@ -120,14 +120,6 @@ format_vxlan_gpe_name (u8 * s, va_list * args)
return format (s, "vxlan_gpe_tunnel%d", dev_instance);
}
-static uword
-dummy_interface_tx (vlib_main_t * vm,
- vlib_node_runtime_t * node, vlib_frame_t * frame)
-{
- clib_warning ("you shouldn't be here, leaking buffers...");
- return frame->n_vectors;
-}
-
/**
* @brief CLI function for VXLAN GPE admin up/down
*
@@ -154,7 +146,6 @@ VNET_DEVICE_CLASS (vxlan_gpe_device_class,static) = {
.name = "VXLAN_GPE",
.format_device_name = format_vxlan_gpe_name,
.format_tx_trace = format_vxlan_gpe_encap_trace,
- .tx_function = dummy_interface_tx,
.admin_up_down_function = vxlan_gpe_interface_admin_up_down,
};
/* *INDENT-ON* */
@@ -600,9 +591,12 @@ int vnet_vxlan_gpe_add_del_tunnel
(vnm, vxlan_gpe_device_class.index, t - ngm->tunnels,
vxlan_gpe_hw_class.index, t - ngm->tunnels);
hi = vnet_get_hw_interface (vnm, hw_if_index);
- hi->output_node_index = vxlan_gpe_encap_node.index;
}
+ /* Set vxlan-gpe tunnel output node */
+ u32 encap_index = vxlan_gpe_encap_node.index;
+ vnet_set_interface_output_node (vnm, hw_if_index, encap_index);
+
t->hw_if_index = hw_if_index;
t->sw_if_index = sw_if_index = hi->sw_if_index;
vec_validate_init_empty (ngm->tunnel_index_by_sw_if_index, sw_if_index,
@@ -620,7 +614,6 @@ int vnet_vxlan_gpe_add_del_tunnel
VNET_SW_INTERFACE_FLAG_ADMIN_UP);
fib_node_init (&t->node, FIB_NODE_TYPE_VXLAN_GPE_TUNNEL);
fib_prefix_t tun_remote_pfx;
- u32 encap_index = vxlan_gpe_encap_node.index;
vnet_flood_class_t flood_class = VNET_FLOOD_CLASS_TUNNEL_NORMAL;
fib_prefix_from_ip46_addr (&t->remote, &tun_remote_pfx);
@@ -711,9 +704,6 @@ int vnet_vxlan_gpe_add_del_tunnel
flood_class = VNET_FLOOD_CLASS_TUNNEL_MASTER;
}
- /* Set vxlan tunnel output node */
- hi->output_node_index = encap_index;
-
vnet_get_sw_interface (vnet_get_main (), sw_if_index)->flood_class =
flood_class;
}
diff --git a/src/vnet/vxlan/vxlan.c b/src/vnet/vxlan/vxlan.c
index edd8733741b..b0a186e2c05 100644
--- a/src/vnet/vxlan/vxlan.c
+++ b/src/vnet/vxlan/vxlan.c
@@ -79,14 +79,6 @@ static u8 * format_vxlan_name (u8 * s, va_list * args)
return format (s, "vxlan_tunnel%d", dev_instance);
}
-static uword dummy_interface_tx (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- vlib_frame_t * frame)
-{
- clib_warning ("you shouldn't be here, leaking buffers...");
- return frame->n_vectors;
-}
-
static clib_error_t *
vxlan_interface_admin_up_down (vnet_main_t * vnm, u32 hw_if_index, u32 flags)
{
@@ -101,7 +93,6 @@ VNET_DEVICE_CLASS (vxlan_device_class,static) = {
.name = "VXLAN",
.format_device_name = format_vxlan_name,
.format_tx_trace = format_vxlan_encap_trace,
- .tx_function = dummy_interface_tx,
.admin_up_down_function = vxlan_interface_admin_up_down,
};
@@ -423,17 +414,22 @@ int vnet_vxlan_add_del_tunnel
(&im->sw_if_counters[VNET_INTERFACE_COUNTER_DROP], sw_if_index);
vnet_interface_counter_unlock(im);
}
- else
+ else
{
hw_if_index = vnet_register_interface
(vnm, vxlan_device_class.index, t - vxm->tunnels,
vxlan_hw_class.index, t - vxm->tunnels);
hi = vnet_get_hw_interface (vnm, hw_if_index);
}
-
+
+ /* Set vxlan tunnel output node */
+ u32 encap_index = !is_ip6 ?
+ vxlan4_encap_node.index : vxlan6_encap_node.index;
+ vnet_set_interface_output_node (vnm, hw_if_index, encap_index);
+
t->hw_if_index = hw_if_index;
t->sw_if_index = sw_if_index = hi->sw_if_index;
-
+
vec_validate_init_empty (vxm->tunnel_index_by_sw_if_index, sw_if_index, ~0);
vxm->tunnel_index_by_sw_if_index[sw_if_index] = t - vxm->tunnels;
@@ -441,16 +437,14 @@ int vnet_vxlan_add_del_tunnel
vec_validate (l2im->configs, sw_if_index);
l2im->configs[sw_if_index].feature_bitmap = L2INPUT_FEAT_DROP;
l2im->configs[sw_if_index].bd_index = 0;
-
+
vnet_sw_interface_t * si = vnet_get_sw_interface (vnm, sw_if_index);
si->flags &= ~VNET_SW_INTERFACE_FLAG_HIDDEN;
- vnet_sw_interface_set_flags (vnm, sw_if_index,
+ vnet_sw_interface_set_flags (vnm, sw_if_index,
VNET_SW_INTERFACE_FLAG_ADMIN_UP);
fib_node_init(&t->node, FIB_NODE_TYPE_VXLAN_TUNNEL);
fib_prefix_t tun_dst_pfx;
- u32 encap_index = !is_ip6 ?
- vxlan4_encap_node.index : vxlan6_encap_node.index;
vnet_flood_class_t flood_class = VNET_FLOOD_CLASS_TUNNEL_NORMAL;
fib_prefix_from_ip46_addr(&t->dst, &tun_dst_pfx);
@@ -542,9 +536,6 @@ int vnet_vxlan_add_del_tunnel
flood_class = VNET_FLOOD_CLASS_TUNNEL_MASTER;
}
- /* Set vxlan tunnel output node */
- hi->output_node_index = encap_index;
-
vnet_get_sw_interface (vnet_get_main(), sw_if_index)->flood_class = flood_class;
}
else