summaryrefslogtreecommitdiffstats
path: root/src/vnet
diff options
context:
space:
mode:
authorNeale Ranns <nranns@cisco.com>2017-08-12 02:12:00 -0700
committerNeale Ranns <nranns@cisco.com>2017-08-21 04:07:00 -0700
commit43161a873375ddf156cf6fbe8764bfc206b38fa0 (patch)
tree939e5455aaff68341d387b559f743dc049b03377 /src/vnet
parent352829f538783afe8609f09850f45536a4779b70 (diff)
PPPoE usses a midchain adjacency stack on an interface-tx DPO
1) introduce an interface-tx DPO. This is a simple wrapper around a sw_if_index. enhance DPO stacking functions to allow per-instance next-nodes and hence allow children to stack onto the interface per-instance tx node and not on 'interface-output'. 2) update PPPoE code to use ta midchain stack on a interface-tx DPO of the encap-interface. This remove the need for pppoe_encap node (which is replaced by the adj-midchain-tx) and interface-output node is no longer used (see above). Since PPPoE encap node is no longer needed, the PPPoE seesion does not need to be retrieved in the data-path, hence the cahce misses are removed. Change-Id: Id8b40f53daa14889a9c51d802e14fed7fba4399a Signed-off-by: Neale Ranns <nranns@cisco.com>
Diffstat (limited to 'src/vnet')
-rw-r--r--src/vnet/adj/adj_midchain.c126
-rw-r--r--src/vnet/dpo/dpo.c107
-rw-r--r--src/vnet/dpo/dpo.h19
-rw-r--r--src/vnet/dpo/interface_dpo.c446
-rw-r--r--src/vnet/dpo/interface_rx_dpo.c445
-rw-r--r--src/vnet/dpo/interface_rx_dpo.h (renamed from src/vnet/dpo/interface_dpo.h)34
-rw-r--r--src/vnet/dpo/interface_tx_dpo.c92
-rw-r--r--src/vnet/dpo/interface_tx_dpo.h33
-rw-r--r--src/vnet/fib/fib_path.c14
-rw-r--r--src/vnet/fib/fib_test.c14
10 files changed, 775 insertions, 555 deletions
diff --git a/src/vnet/adj/adj_midchain.c b/src/vnet/adj/adj_midchain.c
index a93a1c3e1b7..e9a510b004c 100644
--- a/src/vnet/adj/adj_midchain.c
+++ b/src/vnet/adj/adj_midchain.c
@@ -65,8 +65,7 @@ adj_midchain_tx_inline (vlib_main_t * vm,
/* set up to enqueue to our disposition with index = next_index */
vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
-
- while (n_left_from >= 4 && n_left_to_next > 2)
+ while (n_left_from >= 8 && n_left_to_next > 4)
{
u32 bi0, adj_index0, next0;
const ip_adjacency_t * adj0;
@@ -76,49 +75,75 @@ adj_midchain_tx_inline (vlib_main_t * vm,
const ip_adjacency_t * adj1;
const dpo_id_t *dpo1;
vlib_buffer_t * b1;
+ u32 bi2, adj_index2, next2;
+ const ip_adjacency_t * adj2;
+ const dpo_id_t *dpo2;
+ vlib_buffer_t * b2;
+ u32 bi3, adj_index3, next3;
+ const ip_adjacency_t * adj3;
+ const dpo_id_t *dpo3;
+ vlib_buffer_t * b3;
/* Prefetch next iteration. */
{
- vlib_buffer_t * p2, * p3;
-
- p2 = vlib_get_buffer (vm, from[2]);
- p3 = vlib_get_buffer (vm, from[3]);
-
- vlib_prefetch_buffer_header (p2, LOAD);
- vlib_prefetch_buffer_header (p3, LOAD);
-
- CLIB_PREFETCH (p2->data, CLIB_CACHE_LINE_BYTES, STORE);
- CLIB_PREFETCH (p3->data, CLIB_CACHE_LINE_BYTES, STORE);
+ vlib_buffer_t * p4, * p5;
+ vlib_buffer_t * p6, * p7;
+
+ p4 = vlib_get_buffer (vm, from[4]);
+ p5 = vlib_get_buffer (vm, from[5]);
+ p6 = vlib_get_buffer (vm, from[6]);
+ p7 = vlib_get_buffer (vm, from[7]);
+
+ vlib_prefetch_buffer_header (p4, LOAD);
+ vlib_prefetch_buffer_header (p5, LOAD);
+ vlib_prefetch_buffer_header (p6, LOAD);
+ vlib_prefetch_buffer_header (p7, LOAD);
}
bi0 = from[0];
to_next[0] = bi0;
bi1 = from[1];
to_next[1] = bi1;
+ bi2 = from[2];
+ to_next[2] = bi2;
+ bi3 = from[3];
+ to_next[3] = bi3;
- from += 2;
- to_next += 2;
- n_left_from -= 2;
- n_left_to_next -= 2;
+ from += 4;
+ to_next += 4;
+ n_left_from -= 4;
+ n_left_to_next -= 4;
b0 = vlib_get_buffer(vm, bi0);
b1 = vlib_get_buffer(vm, bi1);
+ b2 = vlib_get_buffer(vm, bi2);
+ b3 = vlib_get_buffer(vm, bi3);
/* Follow the DPO on which the midchain is stacked */
adj_index0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
adj_index1 = vnet_buffer(b1)->ip.adj_index[VLIB_TX];
+ adj_index2 = vnet_buffer(b2)->ip.adj_index[VLIB_TX];
+ adj_index3 = vnet_buffer(b3)->ip.adj_index[VLIB_TX];
adj0 = adj_get(adj_index0);
adj1 = adj_get(adj_index1);
+ adj2 = adj_get(adj_index2);
+ adj3 = adj_get(adj_index3);
dpo0 = &adj0->sub_type.midchain.next_dpo;
dpo1 = &adj1->sub_type.midchain.next_dpo;
+ dpo2 = &adj2->sub_type.midchain.next_dpo;
+ dpo3 = &adj3->sub_type.midchain.next_dpo;
next0 = dpo0->dpoi_next_node;
next1 = dpo1->dpoi_next_node;
+ next2 = dpo2->dpoi_next_node;
+ next3 = dpo3->dpoi_next_node;
- vnet_buffer(b1)->ip.adj_index[VLIB_TX] = dpo1->dpoi_index;
- vnet_buffer(b0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
+ vnet_buffer(b1)->ip.adj_index[VLIB_TX] = dpo1->dpoi_index;
+ vnet_buffer(b0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
+ vnet_buffer(b2)->ip.adj_index[VLIB_TX] = dpo2->dpoi_index;
+ vnet_buffer(b3)->ip.adj_index[VLIB_TX] = dpo3->dpoi_index;
if (interface_count)
{
@@ -134,6 +159,18 @@ adj_midchain_tx_inline (vlib_main_t * vm,
adj1->rewrite_header.sw_if_index,
1,
vlib_buffer_length_in_chain (vm, b1));
+ vlib_increment_combined_counter (im->combined_sw_if_counters
+ + VNET_INTERFACE_COUNTER_TX,
+ thread_index,
+ adj2->rewrite_header.sw_if_index,
+ 1,
+ vlib_buffer_length_in_chain (vm, b2));
+ vlib_increment_combined_counter (im->combined_sw_if_counters
+ + VNET_INTERFACE_COUNTER_TX,
+ thread_index,
+ adj3->rewrite_header.sw_if_index,
+ 1,
+ vlib_buffer_length_in_chain (vm, b3));
}
if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
@@ -148,11 +185,23 @@ adj_midchain_tx_inline (vlib_main_t * vm,
b1, sizeof (*tr));
tr->ai = adj_index1;
}
+ if (PREDICT_FALSE(b2->flags & VLIB_BUFFER_IS_TRACED))
+ {
+ adj_midchain_tx_trace_t *tr = vlib_add_trace (vm, node,
+ b2, sizeof (*tr));
+ tr->ai = adj_index2;
+ }
+ if (PREDICT_FALSE(b3->flags & VLIB_BUFFER_IS_TRACED))
+ {
+ adj_midchain_tx_trace_t *tr = vlib_add_trace (vm, node,
+ b3, sizeof (*tr));
+ tr->ai = adj_index3;
+ }
- vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
+ vlib_validate_buffer_enqueue_x4 (vm, node, next_index,
to_next, n_left_to_next,
- bi0, bi1,
- next0, next1);
+ bi0, bi1, bi2, bi3,
+ next0, next1, next2, next3);
}
while (n_left_from > 0 && n_left_to_next > 0)
{
@@ -175,7 +224,7 @@ adj_midchain_tx_inline (vlib_main_t * vm,
adj0 = adj_get(adj_index0);
dpo0 = &adj0->sub_type.midchain.next_dpo;
next0 = dpo0->dpoi_next_node;
- vnet_buffer(b0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
+ vnet_buffer(b0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
if (interface_count)
{
@@ -392,6 +441,17 @@ adj_nbr_midchain_get_tx_node (ip_adjacency_t *adj)
adj_midchain_tx_node.index);
}
+static u32
+adj_nbr_midchain_get_feature_node (ip_adjacency_t *adj)
+{
+ if (adj->ia_flags & ADJ_FLAG_MIDCHAIN_NO_COUNT)
+ {
+ return (adj_midchain_tx_no_count_feature_node[adj->ia_link]);
+ }
+
+ return (adj_midchain_tx_feature_node[adj->ia_link]);
+}
+
/**
* adj_midchain_setup
*
@@ -414,10 +474,7 @@ adj_midchain_setup (adj_index_t adj_index,
adj->ia_flags |= flags;
arc_index = adj_midchain_get_feature_arc_index_for_link_type (adj);
- feature_index = (flags & ADJ_FLAG_MIDCHAIN_NO_COUNT) ?
- adj_midchain_tx_no_count_feature_node[adj->ia_link] :
- adj_midchain_tx_feature_node[adj->ia_link];
-
+ feature_index = adj_nbr_midchain_get_feature_node(adj);
tx_node = adj_nbr_midchain_get_tx_node(adj);
vnet_feature_enable_disable_with_index (arc_index, feature_index,
@@ -432,8 +489,8 @@ adj_midchain_setup (adj_index_t adj_index,
* need to get to the stacked child's node.
*/
dpo_stack_from_node(tx_node,
- &adj->sub_type.midchain.next_dpo,
- drop_dpo_get(vnet_link_to_dpo_proto(adj->ia_link)));
+ &adj->sub_type.midchain.next_dpo,
+ drop_dpo_get(vnet_link_to_dpo_proto(adj->ia_link)));
}
/**
@@ -495,10 +552,9 @@ adj_nbr_midchain_unstack (adj_index_t adj_index)
* stack on the drop
*/
dpo_stack(DPO_ADJACENCY_MIDCHAIN,
- vnet_link_to_dpo_proto(adj->ia_link),
- &adj->sub_type.midchain.next_dpo,
- drop_dpo_get(vnet_link_to_dpo_proto(adj->ia_link)));
-
+ vnet_link_to_dpo_proto(adj->ia_link),
+ &adj->sub_type.midchain.next_dpo,
+ drop_dpo_get(vnet_link_to_dpo_proto(adj->ia_link)));
CLIB_MEMORY_BARRIER();
}
@@ -537,9 +593,9 @@ format_adj_midchain (u8* s, va_list *ap)
format_vnet_rewrite,
&adj->rewrite_header, sizeof (adj->rewrite_data), indent);
s = format (s, "\n%Ustacked-on:\n%U%U",
- format_white_space, indent,
- format_white_space, indent+2,
- format_dpo_id, &adj->sub_type.midchain.next_dpo, indent+2);
+ format_white_space, indent,
+ format_white_space, indent+2,
+ format_dpo_id, &adj->sub_type.midchain.next_dpo, indent+2);
return (s);
}
diff --git a/src/vnet/dpo/dpo.c b/src/vnet/dpo/dpo.c
index aa7708385a5..bd18b66bfd5 100644
--- a/src/vnet/dpo/dpo.c
+++ b/src/vnet/dpo/dpo.c
@@ -37,7 +37,8 @@
#include <vnet/dpo/classify_dpo.h>
#include <vnet/dpo/ip_null_dpo.h>
#include <vnet/dpo/replicate_dpo.h>
-#include <vnet/dpo/interface_dpo.h>
+#include <vnet/dpo/interface_rx_dpo.h>
+#include <vnet/dpo/interface_tx_dpo.h>
#include <vnet/dpo/mpls_disposition.h>
/**
@@ -275,6 +276,29 @@ dpo_is_adj (const dpo_id_t *dpo)
(dpo->dpoi_type == DPO_ADJACENCY_GLEAN));
}
+static u32 *
+dpo_default_get_next_node (const dpo_id_t *dpo)
+{
+ u32 *node_indices = NULL;
+ const char *node_name;
+ u32 ii = 0;
+
+ node_name = dpo_nodes[dpo->dpoi_type][dpo->dpoi_proto][ii];
+ while (NULL != node_name)
+ {
+ vlib_node_t *node;
+
+ node = vlib_get_node_by_name(vlib_get_main(), (u8*) node_name);
+ ASSERT(NULL != node);
+ vec_add1(node_indices, node->index);
+
+ ++ii;
+ node_name = dpo_nodes[dpo->dpoi_type][dpo->dpoi_proto][ii];
+ }
+
+ return (node_indices);
+}
+
void
dpo_register (dpo_type_t type,
const dpo_vft_t *vft,
@@ -282,6 +306,10 @@ dpo_register (dpo_type_t type,
{
vec_validate(dpo_vfts, type);
dpo_vfts[type] = *vft;
+ if (NULL == dpo_vfts[type].dv_get_next_node)
+ {
+ dpo_vfts[type].dv_get_next_node = dpo_default_get_next_node;
+ }
vec_validate(dpo_nodes, type);
dpo_nodes[type] = nodes;
@@ -340,24 +368,25 @@ dpo_get_next_node (dpo_type_t child_type,
*/
if (~0 == dpo_edges[child_type][child_proto][parent_type][parent_proto])
{
- vlib_node_t *parent_node, *child_node;
+ vlib_node_t *child_node;
+ u32 *parent_indices;
vlib_main_t *vm;
- u32 edge ,pp, cc;
+ u32 edge, *pi, cc;
vm = vlib_get_main();
- vlib_worker_thread_barrier_sync(vm);
-
+ ASSERT(NULL != dpo_vfts[parent_type].dv_get_next_node);
ASSERT(NULL != dpo_nodes[child_type]);
ASSERT(NULL != dpo_nodes[child_type][child_proto]);
- ASSERT(NULL != dpo_nodes[parent_type]);
- ASSERT(NULL != dpo_nodes[parent_type][parent_proto]);
cc = 0;
+ parent_indices = dpo_vfts[parent_type].dv_get_next_node(parent_dpo);
+
+ vlib_worker_thread_barrier_sync(vm);
/*
- * create a graph arc from each of the parent's registered node types,
- * to each of the childs.
+ * create a graph arc from each of the child's registered node types,
+ * to each of the parent's.
*/
while (NULL != dpo_nodes[child_type][child_proto][cc])
{
@@ -365,17 +394,9 @@ dpo_get_next_node (dpo_type_t child_type,
vlib_get_node_by_name(vm,
(u8*) dpo_nodes[child_type][child_proto][cc]);
- pp = 0;
-
- while (NULL != dpo_nodes[parent_type][parent_proto][pp])
+ vec_foreach(pi, parent_indices)
{
- parent_node =
- vlib_get_node_by_name(vm,
- (u8*) dpo_nodes[parent_type][parent_proto][pp]);
-
- edge = vlib_node_add_next(vm,
- child_node->index,
- parent_node->index);
+ edge = vlib_node_add_next(vm, child_node->index, *pi);
if (~0 == dpo_edges[child_type][child_proto][parent_type][parent_proto])
{
@@ -385,12 +406,12 @@ dpo_get_next_node (dpo_type_t child_type,
{
ASSERT(dpo_edges[child_type][child_proto][parent_type][parent_proto] == edge);
}
- pp++;
}
cc++;
}
vlib_worker_thread_barrier_release(vm);
+ vec_free(parent_indices);
}
return (dpo_edges[child_type][child_proto][parent_type][parent_proto]);
@@ -451,38 +472,39 @@ dpo_stack_from_node (u32 child_node_index,
dpo_id_t *dpo,
const dpo_id_t *parent)
{
- dpo_proto_t parent_proto;
- vlib_node_t *parent_node;
dpo_type_t parent_type;
+ u32 *parent_indices;
vlib_main_t *vm;
- u32 edge;
+ u32 edge, *pi;
+ edge = 0;
parent_type = parent->dpoi_type;
- parent_proto = parent->dpoi_proto;
-
vm = vlib_get_main();
- ASSERT(NULL != dpo_nodes[parent_type]);
- ASSERT(NULL != dpo_nodes[parent_type][parent_proto]);
+ ASSERT(NULL != dpo_vfts[parent_type].dv_get_next_node);
+ parent_indices = dpo_vfts[parent_type].dv_get_next_node(parent);
+ ASSERT(parent_indices);
- parent_node =
- vlib_get_node_by_name(vm, (u8*) dpo_nodes[parent_type][parent_proto][0]);
-
- edge = vlib_node_get_next(vm,
- child_node_index,
- parent_node->index);
-
- if (~0 == edge)
+ /*
+ * This loop is purposefully written with the worker thread lock in the
+ * inner loop because;
+ * 1) the likelihood that the edge does not exist is smaller
+ * 2) the likelihood there is more than one node is even smaller
+ * so we are optimising for not need to take the lock
+ */
+ vec_foreach(pi, parent_indices)
{
- vlib_worker_thread_barrier_sync(vm);
+ edge = vlib_node_get_next(vm, child_node_index, *pi);
- edge = vlib_node_add_next(vm,
- child_node_index,
- parent_node->index);
+ if (~0 == edge)
+ {
+ vlib_worker_thread_barrier_sync(vm);
- vlib_worker_thread_barrier_release(vm);
- }
+ edge = vlib_node_add_next(vm, child_node_index, *pi);
+ vlib_worker_thread_barrier_release(vm);
+ }
+ }
dpo_stack_i(edge, dpo, parent);
}
@@ -498,7 +520,8 @@ dpo_module_init (vlib_main_t * vm)
lookup_dpo_module_init();
ip_null_dpo_module_init();
replicate_module_init();
- interface_dpo_module_init();
+ interface_rx_dpo_module_init();
+ interface_tx_dpo_module_init();
mpls_disp_dpo_module_init();
return (NULL);
diff --git a/src/vnet/dpo/dpo.h b/src/vnet/dpo/dpo.h
index 42fc51d4b6c..33562968272 100644
--- a/src/vnet/dpo/dpo.h
+++ b/src/vnet/dpo/dpo.h
@@ -112,7 +112,8 @@ typedef enum dpo_type_t_ {
DPO_MPLS_LABEL,
DPO_MPLS_DISPOSITION,
DPO_MFIB_ENTRY,
- DPO_INTERFACE,
+ DPO_INTERFACE_RX,
+ DPO_INTERFACE_TX,
DPO_LAST,
} __attribute__((packed)) dpo_type_t;
@@ -138,7 +139,8 @@ typedef enum dpo_type_t_ {
[DPO_MPLS_LABEL] = "dpo-mpls-label", \
[DPO_MPLS_DISPOSITION] = "dpo-mpls-diposition", \
[DPO_MFIB_ENTRY] = "dpo-mfib_entry", \
- [DPO_INTERFACE] = "dpo-interface" \
+ [DPO_INTERFACE_RX] = "dpo-interface-rx", \
+ [DPO_INTERFACE_TX] = "dpo-interface-tx" \
}
/**
@@ -332,6 +334,12 @@ typedef void (*dpo_unlock_fn_t)(dpo_id_t *dpo);
typedef void (*dpo_mem_show_t)(void);
/**
+ * @brief Given a DPO instance return a vector of node indices that
+ * the type/instance will use.
+ */
+typedef u32* (*dpo_get_next_node_t)(const dpo_id_t *dpo);
+
+/**
* @brief A virtual function table regisitered for a DPO type
*/
typedef struct dpo_vft_t_
@@ -352,6 +360,13 @@ typedef struct dpo_vft_t_
* A show memory usage function
*/
dpo_mem_show_t dv_mem_show;
+ /**
+ * A function to get the next VLIB node given an instance
+ * of the DPO. If this is null, then the node's name MUST be
+ * retreiveable from the nodes names array passed in the register
+ * function
+ */
+ dpo_get_next_node_t dv_get_next_node;
} dpo_vft_t;
diff --git a/src/vnet/dpo/interface_dpo.c b/src/vnet/dpo/interface_dpo.c
deleted file mode 100644
index 780bfa2a293..00000000000
--- a/src/vnet/dpo/interface_dpo.c
+++ /dev/null
@@ -1,446 +0,0 @@
-/*
- * Copyright (c) 2016 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <vnet/dpo/interface_dpo.h>
-#include <vnet/fib/fib_node.h>
-
-/*
- * The 'DB' of interface DPOs.
- * There is only one per-interface per-protocol, so this is a per-interface
- * vector
- */
-static index_t *interface_dpo_db[DPO_PROTO_NUM];
-
-static interface_dpo_t *
-interface_dpo_alloc (void)
-{
- interface_dpo_t *ido;
-
- pool_get(interface_dpo_pool, ido);
-
- return (ido);
-}
-
-static inline interface_dpo_t *
-interface_dpo_get_from_dpo (const dpo_id_t *dpo)
-{
- ASSERT(DPO_INTERFACE == dpo->dpoi_type);
-
- return (interface_dpo_get(dpo->dpoi_index));
-}
-
-static inline index_t
-interface_dpo_get_index (interface_dpo_t *ido)
-{
- return (ido - interface_dpo_pool);
-}
-
-static void
-interface_dpo_lock (dpo_id_t *dpo)
-{
- interface_dpo_t *ido;
-
- ido = interface_dpo_get_from_dpo(dpo);
- ido->ido_locks++;
-}
-
-static void
-interface_dpo_unlock (dpo_id_t *dpo)
-{
- interface_dpo_t *ido;
-
- ido = interface_dpo_get_from_dpo(dpo);
- ido->ido_locks--;
-
- if (0 == ido->ido_locks)
- {
- interface_dpo_db[ido->ido_proto][ido->ido_sw_if_index] =
- INDEX_INVALID;
- pool_put(interface_dpo_pool, ido);
- }
-}
-
-/*
- * interface_dpo_add_or_lock
- *
- * Add/create and lock a new or lock an existing for the interface DPO
- * on the interface and protocol given
- */
-void
-interface_dpo_add_or_lock (dpo_proto_t proto,
- u32 sw_if_index,
- dpo_id_t *dpo)
-{
- interface_dpo_t *ido;
-
- vec_validate_init_empty(interface_dpo_db[proto],
- sw_if_index,
- INDEX_INVALID);
-
- if (INDEX_INVALID == interface_dpo_db[proto][sw_if_index])
- {
- ido = interface_dpo_alloc();
-
- ido->ido_sw_if_index = sw_if_index;
- ido->ido_proto = proto;
-
- interface_dpo_db[proto][sw_if_index] =
- interface_dpo_get_index(ido);
- }
- else
- {
- ido = interface_dpo_get(interface_dpo_db[proto][sw_if_index]);
- }
-
- dpo_set(dpo, DPO_INTERFACE, proto, interface_dpo_get_index(ido));
-}
-
-
-static clib_error_t *
-interface_dpo_interface_state_change (vnet_main_t * vnm,
- u32 sw_if_index,
- u32 flags)
-{
- /*
- */
- return (NULL);
-}
-
-VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION(
- interface_dpo_interface_state_change);
-
-/**
- * @brief Registered callback for HW interface state changes
- */
-static clib_error_t *
-interface_dpo_hw_interface_state_change (vnet_main_t * vnm,
- u32 hw_if_index,
- u32 flags)
-{
- return (NULL);
-}
-
-VNET_HW_INTERFACE_LINK_UP_DOWN_FUNCTION(
- interface_dpo_hw_interface_state_change);
-
-static clib_error_t *
-interface_dpo_interface_delete (vnet_main_t * vnm,
- u32 sw_if_index,
- u32 is_add)
-{
- return (NULL);
-}
-
-VNET_SW_INTERFACE_ADD_DEL_FUNCTION(
- interface_dpo_interface_delete);
-
-u8*
-format_interface_dpo (u8* s, va_list *ap)
-{
- index_t index = va_arg(*ap, index_t);
- CLIB_UNUSED(u32 indent) = va_arg(*ap, u32);
- vnet_main_t * vnm = vnet_get_main();
- interface_dpo_t *ido = interface_dpo_get(index);
-
- return (format(s, "%U-dpo: %U",
- format_vnet_sw_interface_name,
- vnm,
- vnet_get_sw_interface(vnm, ido->ido_sw_if_index),
- format_dpo_proto, ido->ido_proto));
-}
-
-static void
-interface_dpo_mem_show (void)
-{
- fib_show_memory_usage("Interface",
- pool_elts(interface_dpo_pool),
- pool_len(interface_dpo_pool),
- sizeof(interface_dpo_t));
-}
-
-
-const static dpo_vft_t interface_dpo_vft = {
- .dv_lock = interface_dpo_lock,
- .dv_unlock = interface_dpo_unlock,
- .dv_format = format_interface_dpo,
- .dv_mem_show = interface_dpo_mem_show,
-};
-
-/**
- * @brief The per-protocol VLIB graph nodes that are assigned to a glean
- * object.
- *
- * this means that these graph nodes are ones from which a glean is the
- * parent object in the DPO-graph.
- */
-const static char* const interface_dpo_ip4_nodes[] =
-{
- "interface-dpo-ip4",
- NULL,
-};
-const static char* const interface_dpo_ip6_nodes[] =
-{
- "interface-dpo-ip4",
- NULL,
-};
-const static char* const interface_dpo_l2_nodes[] =
-{
- "interface-dpo-l2",
- NULL,
-};
-
-const static char* const * const interface_dpo_nodes[DPO_PROTO_NUM] =
-{
- [DPO_PROTO_IP4] = interface_dpo_ip4_nodes,
- [DPO_PROTO_IP6] = interface_dpo_ip6_nodes,
- [DPO_PROTO_ETHERNET] = interface_dpo_l2_nodes,
- [DPO_PROTO_MPLS] = NULL,
-};
-
-void
-interface_dpo_module_init (void)
-{
- dpo_register(DPO_INTERFACE,
- &interface_dpo_vft,
- interface_dpo_nodes);
-}
-
-/**
- * @brief Interface DPO trace data
- */
-typedef struct interface_dpo_trace_t_
-{
- u32 sw_if_index;
-} interface_dpo_trace_t;
-
-typedef enum interface_dpo_next_t_
-{
- INTERFACE_DPO_DROP = 0,
- INTERFACE_DPO_INPUT = 1,
-} interface_dpo_next_t;
-
-always_inline uword
-interface_dpo_inline (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- vlib_frame_t * from_frame)
-{
- u32 n_left_from, next_index, * from, * to_next;
- u32 thread_index = vlib_get_thread_index ();
- vnet_interface_main_t *im;
-
- im = &vnet_get_main ()->interface_main;
- from = vlib_frame_vector_args (from_frame);
- n_left_from = from_frame->n_vectors;
-
- next_index = node->cached_next_index;
-
- while (n_left_from > 0)
- {
- u32 n_left_to_next;
-
- vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
-
- while (n_left_from >= 4 && n_left_to_next > 2)
- {
- const interface_dpo_t *ido0, *ido1;
- u32 bi0, idoi0, bi1, idoi1;
- vlib_buffer_t *b0, *b1;
-
- bi0 = from[0];
- to_next[0] = bi0;
- bi1 = from[1];
- to_next[1] = bi1;
- from += 2;
- to_next += 2;
- n_left_from -= 2;
- n_left_to_next -= 2;
-
- b0 = vlib_get_buffer (vm, bi0);
- b1 = vlib_get_buffer (vm, bi1);
-
- idoi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
- idoi1 = vnet_buffer(b1)->ip.adj_index[VLIB_TX];
- ido0 = interface_dpo_get(idoi0);
- ido1 = interface_dpo_get(idoi1);
-
- vnet_buffer(b0)->sw_if_index[VLIB_RX] = ido0->ido_sw_if_index;
- vnet_buffer(b1)->sw_if_index[VLIB_RX] = ido1->ido_sw_if_index;
-
- vlib_increment_combined_counter (im->combined_sw_if_counters
- + VNET_INTERFACE_COUNTER_RX,
- thread_index,
- ido0->ido_sw_if_index,
- 1,
- vlib_buffer_length_in_chain (vm, b0));
- vlib_increment_combined_counter (im->combined_sw_if_counters
- + VNET_INTERFACE_COUNTER_RX,
- thread_index,
- ido1->ido_sw_if_index,
- 1,
- vlib_buffer_length_in_chain (vm, b1));
-
- if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
- {
- interface_dpo_trace_t *tr0;
-
- tr0 = vlib_add_trace (vm, node, b0, sizeof (*tr0));
- tr0->sw_if_index = ido0->ido_sw_if_index;
- }
- if (PREDICT_FALSE(b1->flags & VLIB_BUFFER_IS_TRACED))
- {
- interface_dpo_trace_t *tr1;
-
- tr1 = vlib_add_trace (vm, node, b1, sizeof (*tr1));
- tr1->sw_if_index = ido1->ido_sw_if_index;
- }
-
- vlib_validate_buffer_enqueue_x2(vm, node, next_index, to_next,
- n_left_to_next, bi0, bi1,
- INTERFACE_DPO_INPUT,
- INTERFACE_DPO_INPUT);
- }
-
- while (n_left_from > 0 && n_left_to_next > 0)
- {
- const interface_dpo_t * ido0;
- vlib_buffer_t * b0;
- u32 bi0, idoi0;
-
- bi0 = from[0];
- to_next[0] = bi0;
- from += 1;
- to_next += 1;
- n_left_from -= 1;
- n_left_to_next -= 1;
-
- b0 = vlib_get_buffer (vm, bi0);
-
- idoi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
- ido0 = interface_dpo_get(idoi0);
-
- /* Swap the RX interface of the packet to the one the
- * interface DPR represents */
- vnet_buffer(b0)->sw_if_index[VLIB_RX] = ido0->ido_sw_if_index;
-
- /* Bump the interface's RX coutners */
- vlib_increment_combined_counter (im->combined_sw_if_counters
- + VNET_INTERFACE_COUNTER_RX,
- thread_index,
- ido0->ido_sw_if_index,
- 1,
- vlib_buffer_length_in_chain (vm, b0));
-
- if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
- {
- interface_dpo_trace_t *tr;
-
- tr = vlib_add_trace (vm, node, b0, sizeof (*tr));
- tr->sw_if_index = ido0->ido_sw_if_index;
- }
-
- vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next,
- n_left_to_next, bi0,
- INTERFACE_DPO_INPUT);
- }
- vlib_put_next_frame (vm, node, next_index, n_left_to_next);
- }
- return from_frame->n_vectors;
-}
-
-static u8 *
-format_interface_dpo_trace (u8 * s, va_list * args)
-{
- CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
- CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
- interface_dpo_trace_t * t = va_arg (*args, interface_dpo_trace_t *);
- uword indent = format_get_indent (s);
- s = format (s, "%U sw_if_index:%d",
- format_white_space, indent,
- t->sw_if_index);
- return s;
-}
-
-static uword
-interface_dpo_ip4 (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- vlib_frame_t * from_frame)
-{
- return (interface_dpo_inline(vm, node, from_frame));
-}
-
-static uword
-interface_dpo_ip6 (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- vlib_frame_t * from_frame)
-{
- return (interface_dpo_inline(vm, node, from_frame));
-}
-
-static uword
-interface_dpo_l2 (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- vlib_frame_t * from_frame)
-{
- return (interface_dpo_inline(vm, node, from_frame));
-}
-
-VLIB_REGISTER_NODE (interface_dpo_ip4_node) = {
- .function = interface_dpo_ip4,
- .name = "interface-dpo-ip4",
- .vector_size = sizeof (u32),
- .format_trace = format_interface_dpo_trace,
-
- .n_next_nodes = 2,
- .next_nodes = {
- [INTERFACE_DPO_DROP] = "ip4-drop",
- [INTERFACE_DPO_INPUT] = "ip4-input",
- },
-};
-
-VLIB_NODE_FUNCTION_MULTIARCH (interface_dpo_ip4_node,
- interface_dpo_ip4)
-
-VLIB_REGISTER_NODE (interface_dpo_ip6_node) = {
- .function = interface_dpo_ip6,
- .name = "interface-dpo-ip6",
- .vector_size = sizeof (u32),
- .format_trace = format_interface_dpo_trace,
-
- .n_next_nodes = 2,
- .next_nodes = {
- [INTERFACE_DPO_DROP] = "ip6-drop",
- [INTERFACE_DPO_INPUT] = "ip6-input",
- },
-};
-
-VLIB_NODE_FUNCTION_MULTIARCH (interface_dpo_ip6_node,
- interface_dpo_ip6)
-
-VLIB_REGISTER_NODE (interface_dpo_l2_node) = {
- .function = interface_dpo_l2,
- .name = "interface-dpo-l2",
- .vector_size = sizeof (u32),
- .format_trace = format_interface_dpo_trace,
-
- .n_next_nodes = 2,
- .next_nodes = {
- [INTERFACE_DPO_DROP] = "error-drop",
- [INTERFACE_DPO_INPUT] = "l2-input",
- },
-};
-
-VLIB_NODE_FUNCTION_MULTIARCH (interface_dpo_l2_node,
- interface_dpo_l2)
-
diff --git a/src/vnet/dpo/interface_rx_dpo.c b/src/vnet/dpo/interface_rx_dpo.c
new file mode 100644
index 00000000000..a624f514564
--- /dev/null
+++ b/src/vnet/dpo/interface_rx_dpo.c
@@ -0,0 +1,445 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <vnet/dpo/interface_rx_dpo.h>
+#include <vnet/fib/fib_node.h>
+
+/*
+ * The 'DB' of interface DPOs.
+ * There is only one per-interface per-protocol, so this is a per-interface
+ * vector
+ */
+static index_t *interface_rx_dpo_db[DPO_PROTO_NUM];
+
+static interface_rx_dpo_t *
+interface_rx_dpo_alloc (void)
+{
+ interface_rx_dpo_t *ido;
+
+ pool_get(interface_rx_dpo_pool, ido);
+
+ return (ido);
+}
+
+static inline interface_rx_dpo_t *
+interface_rx_dpo_get_from_dpo (const dpo_id_t *dpo)
+{
+ ASSERT(DPO_INTERFACE_RX == dpo->dpoi_type);
+
+ return (interface_rx_dpo_get(dpo->dpoi_index));
+}
+
+static inline index_t
+interface_rx_dpo_get_index (interface_rx_dpo_t *ido)
+{
+ return (ido - interface_rx_dpo_pool);
+}
+
+static void
+interface_rx_dpo_lock (dpo_id_t *dpo)
+{
+ interface_rx_dpo_t *ido;
+
+ ido = interface_rx_dpo_get_from_dpo(dpo);
+ ido->ido_locks++;
+}
+
+static void
+interface_rx_dpo_unlock (dpo_id_t *dpo)
+{
+ interface_rx_dpo_t *ido;
+
+ ido = interface_rx_dpo_get_from_dpo(dpo);
+ ido->ido_locks--;
+
+ if (0 == ido->ido_locks)
+ {
+ interface_rx_dpo_db[ido->ido_proto][ido->ido_sw_if_index] =
+ INDEX_INVALID;
+ pool_put(interface_rx_dpo_pool, ido);
+ }
+}
+
+/*
+ * interface_rx_dpo_add_or_lock
+ *
+ * Add/create and lock a new or lock an existing for the interface DPO
+ * on the interface and protocol given
+ */
+void
+interface_rx_dpo_add_or_lock (dpo_proto_t proto,
+ u32 sw_if_index,
+ dpo_id_t *dpo)
+{
+ interface_rx_dpo_t *ido;
+
+ vec_validate_init_empty(interface_rx_dpo_db[proto],
+ sw_if_index,
+ INDEX_INVALID);
+
+ if (INDEX_INVALID == interface_rx_dpo_db[proto][sw_if_index])
+ {
+ ido = interface_rx_dpo_alloc();
+
+ ido->ido_sw_if_index = sw_if_index;
+ ido->ido_proto = proto;
+
+ interface_rx_dpo_db[proto][sw_if_index] =
+ interface_rx_dpo_get_index(ido);
+ }
+ else
+ {
+ ido = interface_rx_dpo_get(interface_rx_dpo_db[proto][sw_if_index]);
+ }
+
+ dpo_set(dpo, DPO_INTERFACE_RX, proto, interface_rx_dpo_get_index(ido));
+}
+
+
+static clib_error_t *
+interface_rx_dpo_interface_state_change (vnet_main_t * vnm,
+ u32 sw_if_index,
+ u32 flags)
+{
+ /*
+ */
+ return (NULL);
+}
+
+VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION(
+ interface_rx_dpo_interface_state_change);
+
+/**
+ * @brief Registered callback for HW interface state changes
+ */
+static clib_error_t *
+interface_rx_dpo_hw_interface_state_change (vnet_main_t * vnm,
+ u32 hw_if_index,
+ u32 flags)
+{
+ return (NULL);
+}
+
+VNET_HW_INTERFACE_LINK_UP_DOWN_FUNCTION(
+ interface_rx_dpo_hw_interface_state_change);
+
+static clib_error_t *
+interface_rx_dpo_interface_delete (vnet_main_t * vnm,
+ u32 sw_if_index,
+ u32 is_add)
+{
+ return (NULL);
+}
+
+VNET_SW_INTERFACE_ADD_DEL_FUNCTION(
+ interface_rx_dpo_interface_delete);
+
+u8*
+format_interface_rx_dpo (u8* s, va_list *ap)
+{
+ index_t index = va_arg(*ap, index_t);
+ CLIB_UNUSED(u32 indent) = va_arg(*ap, u32);
+ vnet_main_t * vnm = vnet_get_main();
+ interface_rx_dpo_t *ido = interface_rx_dpo_get(index);
+
+ return (format(s, "%U-dpo: %U",
+ format_vnet_sw_interface_name,
+ vnm,
+ vnet_get_sw_interface(vnm, ido->ido_sw_if_index),
+ format_dpo_proto, ido->ido_proto));
+}
+
+static void
+interface_rx_dpo_mem_show (void)
+{
+ fib_show_memory_usage("Interface",
+ pool_elts(interface_rx_dpo_pool),
+ pool_len(interface_rx_dpo_pool),
+ sizeof(interface_rx_dpo_t));
+}
+
+
+const static dpo_vft_t interface_rx_dpo_vft = {
+ .dv_lock = interface_rx_dpo_lock,
+ .dv_unlock = interface_rx_dpo_unlock,
+ .dv_format = format_interface_rx_dpo,
+ .dv_mem_show = interface_rx_dpo_mem_show,
+};
+
+/**
+ * @brief The per-protocol VLIB graph nodes that are assigned to a glean
+ * object.
+ *
+ * this means that these graph nodes are ones from which a glean is the
+ * parent object in the DPO-graph.
+ */
+const static char* const interface_rx_dpo_ip4_nodes[] =
+{
+ "interface-rx-dpo-ip4",
+ NULL,
+};
+const static char* const interface_rx_dpo_ip6_nodes[] =
+{
+ "interface-rx-dpo-ip6",
+ NULL,
+};
+const static char* const interface_rx_dpo_l2_nodes[] =
+{
+ "interface-rx-dpo-l2",
+ NULL,
+};
+
+const static char* const * const interface_rx_dpo_nodes[DPO_PROTO_NUM] =
+{
+ [DPO_PROTO_IP4] = interface_rx_dpo_ip4_nodes,
+ [DPO_PROTO_IP6] = interface_rx_dpo_ip6_nodes,
+ [DPO_PROTO_ETHERNET] = interface_rx_dpo_l2_nodes,
+ [DPO_PROTO_MPLS] = NULL,
+};
+
+void
+interface_rx_dpo_module_init (void)
+{
+ dpo_register(DPO_INTERFACE_RX,
+ &interface_rx_dpo_vft,
+ interface_rx_dpo_nodes);
+}
+
+/**
+ * @brief Interface DPO trace data
+ */
+typedef struct interface_rx_dpo_trace_t_
+{
+ u32 sw_if_index;
+} interface_rx_dpo_trace_t;
+
+typedef enum interface_rx_dpo_next_t_
+{
+ INTERFACE_RX_DPO_DROP = 0,
+ INTERFACE_RX_DPO_INPUT = 1,
+} interface_rx_dpo_next_t;
+
+always_inline uword
+interface_rx_dpo_inline (vlib_main_t * vm,
+ vlib_node_runtime_t * node,
+ vlib_frame_t * from_frame)
+{
+ u32 n_left_from, next_index, * from, * to_next;
+ u32 thread_index = vlib_get_thread_index ();
+ vnet_interface_main_t *im;
+
+ im = &vnet_get_main ()->interface_main;
+ from = vlib_frame_vector_args (from_frame);
+ n_left_from = from_frame->n_vectors;
+
+ next_index = node->cached_next_index;
+
+ while (n_left_from > 0)
+ {
+ u32 n_left_to_next;
+
+ vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
+
+ while (n_left_from >= 4 && n_left_to_next > 2)
+ {
+ const interface_rx_dpo_t *ido0, *ido1;
+ u32 bi0, idoi0, bi1, idoi1;
+ vlib_buffer_t *b0, *b1;
+
+ bi0 = from[0];
+ to_next[0] = bi0;
+ bi1 = from[1];
+ to_next[1] = bi1;
+ from += 2;
+ to_next += 2;
+ n_left_from -= 2;
+ n_left_to_next -= 2;
+
+ b0 = vlib_get_buffer (vm, bi0);
+ b1 = vlib_get_buffer (vm, bi1);
+
+ idoi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
+ idoi1 = vnet_buffer(b1)->ip.adj_index[VLIB_TX];
+ ido0 = interface_rx_dpo_get(idoi0);
+ ido1 = interface_rx_dpo_get(idoi1);
+
+ vnet_buffer(b0)->sw_if_index[VLIB_RX] = ido0->ido_sw_if_index;
+ vnet_buffer(b1)->sw_if_index[VLIB_RX] = ido1->ido_sw_if_index;
+
+ vlib_increment_combined_counter (im->combined_sw_if_counters
+ + VNET_INTERFACE_COUNTER_RX,
+ thread_index,
+ ido0->ido_sw_if_index,
+ 1,
+ vlib_buffer_length_in_chain (vm, b0));
+ vlib_increment_combined_counter (im->combined_sw_if_counters
+ + VNET_INTERFACE_COUNTER_RX,
+ thread_index,
+ ido1->ido_sw_if_index,
+ 1,
+ vlib_buffer_length_in_chain (vm, b1));
+
+ if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
+ {
+ interface_rx_dpo_trace_t *tr0;
+
+ tr0 = vlib_add_trace (vm, node, b0, sizeof (*tr0));
+ tr0->sw_if_index = ido0->ido_sw_if_index;
+ }
+ if (PREDICT_FALSE(b1->flags & VLIB_BUFFER_IS_TRACED))
+ {
+ interface_rx_dpo_trace_t *tr1;
+
+ tr1 = vlib_add_trace (vm, node, b1, sizeof (*tr1));
+ tr1->sw_if_index = ido1->ido_sw_if_index;
+ }
+
+ vlib_validate_buffer_enqueue_x2(vm, node, next_index, to_next,
+ n_left_to_next, bi0, bi1,
+ INTERFACE_RX_DPO_INPUT,
+ INTERFACE_RX_DPO_INPUT);
+ }
+
+ while (n_left_from > 0 && n_left_to_next > 0)
+ {
+ const interface_rx_dpo_t * ido0;
+ vlib_buffer_t * b0;
+ u32 bi0, idoi0;
+
+ bi0 = from[0];
+ to_next[0] = bi0;
+ from += 1;
+ to_next += 1;
+ n_left_from -= 1;
+ n_left_to_next -= 1;
+
+ b0 = vlib_get_buffer (vm, bi0);
+
+ idoi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
+ ido0 = interface_rx_dpo_get(idoi0);
+
+ /* Swap the RX interface of the packet to the one the
+ * interface DPR represents */
+ vnet_buffer(b0)->sw_if_index[VLIB_RX] = ido0->ido_sw_if_index;
+
+ /* Bump the interface's RX coutners */
+ vlib_increment_combined_counter (im->combined_sw_if_counters
+ + VNET_INTERFACE_COUNTER_RX,
+ thread_index,
+ ido0->ido_sw_if_index,
+ 1,
+ vlib_buffer_length_in_chain (vm, b0));
+
+ if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
+ {
+ interface_rx_dpo_trace_t *tr;
+
+ tr = vlib_add_trace (vm, node, b0, sizeof (*tr));
+ tr->sw_if_index = ido0->ido_sw_if_index;
+ }
+
+ vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next,
+ n_left_to_next, bi0,
+ INTERFACE_RX_DPO_INPUT);
+ }
+ vlib_put_next_frame (vm, node, next_index, n_left_to_next);
+ }
+ return from_frame->n_vectors;
+}
+
+static u8 *
+format_interface_rx_dpo_trace (u8 * s, va_list * args)
+{
+ CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
+ CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
+ interface_rx_dpo_trace_t * t = va_arg (*args, interface_rx_dpo_trace_t *);
+ uword indent = format_get_indent (s);
+ s = format (s, "%U sw_if_index:%d",
+ format_white_space, indent,
+ t->sw_if_index);
+ return s;
+}
+
+static uword
+interface_rx_dpo_ip4 (vlib_main_t * vm,
+ vlib_node_runtime_t * node,
+ vlib_frame_t * from_frame)
+{
+ return (interface_rx_dpo_inline(vm, node, from_frame));
+}
+
+static uword
+interface_rx_dpo_ip6 (vlib_main_t * vm,
+ vlib_node_runtime_t * node,
+ vlib_frame_t * from_frame)
+{
+ return (interface_rx_dpo_inline(vm, node, from_frame));
+}
+
+static uword
+interface_rx_dpo_l2 (vlib_main_t * vm,
+ vlib_node_runtime_t * node,
+ vlib_frame_t * from_frame)
+{
+ return (interface_rx_dpo_inline(vm, node, from_frame));
+}
+
+VLIB_REGISTER_NODE (interface_rx_dpo_ip4_node) = {
+ .function = interface_rx_dpo_ip4,
+ .name = "interface-rx-dpo-ip4",
+ .vector_size = sizeof (u32),
+ .format_trace = format_interface_rx_dpo_trace,
+
+ .n_next_nodes = 2,
+ .next_nodes = {
+ [INTERFACE_RX_DPO_DROP] = "ip4-drop",
+ [INTERFACE_RX_DPO_INPUT] = "ip4-input",
+ },
+};
+
+VLIB_NODE_FUNCTION_MULTIARCH (interface_rx_dpo_ip4_node,
+ interface_rx_dpo_ip4)
+
+VLIB_REGISTER_NODE (interface_rx_dpo_ip6_node) = {
+ .function = interface_rx_dpo_ip6,
+ .name = "interface-rx-dpo-ip6",
+ .vector_size = sizeof (u32),
+ .format_trace = format_interface_rx_dpo_trace,
+
+ .n_next_nodes = 2,
+ .next_nodes = {
+ [INTERFACE_RX_DPO_DROP] = "ip6-drop",
+ [INTERFACE_RX_DPO_INPUT] = "ip6-input",
+ },
+};
+
+VLIB_NODE_FUNCTION_MULTIARCH (interface_rx_dpo_ip6_node,
+ interface_rx_dpo_ip6)
+
+VLIB_REGISTER_NODE (interface_rx_dpo_l2_node) = {
+ .function = interface_rx_dpo_l2,
+ .name = "interface-rx-dpo-l2",
+ .vector_size = sizeof (u32),
+ .format_trace = format_interface_rx_dpo_trace,
+
+ .n_next_nodes = 2,
+ .next_nodes = {
+ [INTERFACE_RX_DPO_DROP] = "error-drop",
+ [INTERFACE_RX_DPO_INPUT] = "l2-input",
+ },
+};
+
+VLIB_NODE_FUNCTION_MULTIARCH (interface_rx_dpo_l2_node,
+ interface_rx_dpo_l2)
diff --git a/src/vnet/dpo/interface_dpo.h b/src/vnet/dpo/interface_rx_dpo.h
index 1538dfbbf06..edecce08675 100644
--- a/src/vnet/dpo/interface_dpo.h
+++ b/src/vnet/dpo/interface_rx_dpo.h
@@ -12,17 +12,19 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-/**
- * @brief
- * The data-path object representing interfaceing the packet, i.e. it's for-us
- */
-#ifndef __INTERFACE_DPO_H__
-#define __INTERFACE_DPO_H__
+#ifndef __INTERFACE_RX_DPO_H__
+#define __INTERFACE_RX_DPO_H__
#include <vnet/dpo/dpo.h>
-typedef struct interface_dpo_t_
+/**
+ * @brief
+ * The data-path object representing a change of receive interface.
+ * If a packet encounters an object of this type in the data-path, it's
+ * RX interface is changed.
+ */
+typedef struct interface_rx_dpo_t_
{
/**
* The Software interface index that the packets will be given
@@ -45,23 +47,23 @@ typedef struct interface_dpo_t_
* number of locks.
*/
u16 ido_locks;
-} interface_dpo_t;
+} interface_rx_dpo_t;
-extern void interface_dpo_add_or_lock (dpo_proto_t proto,
- u32 sw_if_index,
- dpo_id_t *dpo);
+extern void interface_rx_dpo_add_or_lock (dpo_proto_t proto,
+ u32 sw_if_index,
+ dpo_id_t *dpo);
-extern void interface_dpo_module_init(void);
+extern void interface_rx_dpo_module_init(void);
/**
* @brief pool of all interface DPOs
*/
-interface_dpo_t *interface_dpo_pool;
+interface_rx_dpo_t *interface_rx_dpo_pool;
-static inline interface_dpo_t *
-interface_dpo_get (index_t index)
+static inline interface_rx_dpo_t *
+interface_rx_dpo_get (index_t index)
{
- return (pool_elt_at_index(interface_dpo_pool, index));
+ return (pool_elt_at_index(interface_rx_dpo_pool, index));
}
#endif
diff --git a/src/vnet/dpo/interface_tx_dpo.c b/src/vnet/dpo/interface_tx_dpo.c
new file mode 100644
index 00000000000..f7c8bfda85b
--- /dev/null
+++ b/src/vnet/dpo/interface_tx_dpo.c
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <vnet/dpo/interface_tx_dpo.h>
+#include <vnet/adj/rewrite.h>
+
+/*
+ * We do not lock nor unlock these DPOs since there is nothing to lock
+ * all we do is construct DPO object wrappers around a sw_if_index
+ */
+static void
+interface_tx_dpo_lock (dpo_id_t *dpo)
+{
+}
+
+static void
+interface_tx_dpo_unlock (dpo_id_t *dpo)
+{
+}
+
+/*
+ * interface_tx_dpo_add_or_lock
+ *
+ * construct DPO object wrappers around a sw_if_index
+ */
+void
+interface_tx_dpo_add_or_lock (dpo_proto_t proto,
+ u32 sw_if_index,
+ dpo_id_t *dpo)
+{
+ dpo_set(dpo, DPO_INTERFACE_TX, proto, sw_if_index);
+}
+
+u8*
+format_interface_tx_dpo (u8* s, va_list *ap)
+{
+ index_t index = va_arg(*ap, index_t);
+ CLIB_UNUSED(u32 indent) = va_arg(*ap, u32);
+ vnet_main_t * vnm = vnet_get_main();
+
+ return (format(s, "%U-dpo:",
+ format_vnet_sw_interface_name,
+ vnm,
+ vnet_get_sw_interface(vnm, index)));
+}
+
+static void
+interface_tx_dpo_mem_show (void)
+{
+}
+
+u32*
+interface_tx_dpo_get_next_node (const dpo_id_t *dpo)
+{
+ u32 *node_indices = NULL;
+
+ /*
+ * return the interface's TX node for the wrapped sw_if_index
+ */
+ vec_add1(node_indices,
+ vnet_tx_node_index_for_sw_interface(vnet_get_main(),
+ dpo->dpoi_index));
+
+ return (node_indices);
+}
+
+const static dpo_vft_t interface_tx_dpo_vft = {
+ .dv_lock = interface_tx_dpo_lock,
+ .dv_unlock = interface_tx_dpo_unlock,
+ .dv_format = format_interface_tx_dpo,
+ .dv_mem_show = interface_tx_dpo_mem_show,
+ .dv_get_next_node = interface_tx_dpo_get_next_node,
+};
+
+void
+interface_tx_dpo_module_init (void)
+{
+ dpo_register(DPO_INTERFACE_TX, &interface_tx_dpo_vft, NULL);
+}
+
diff --git a/src/vnet/dpo/interface_tx_dpo.h b/src/vnet/dpo/interface_tx_dpo.h
new file mode 100644
index 00000000000..0c560adaaa4
--- /dev/null
+++ b/src/vnet/dpo/interface_tx_dpo.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * @brief
+ * The data-path object representing transmitting the packet on a n interface.
+ * This is a convenient DPO wrapper around a simple interface transmit and thus
+ * allows us to represent direct interface transmit in the DPO model.
+ */
+
+#ifndef __INTERFACE_TX_DPO_H__
+#define __INTERFACE_TX_DPO_H__
+
+#include <vnet/dpo/dpo.h>
+
+extern void interface_tx_dpo_add_or_lock (dpo_proto_t proto,
+ u32 sw_if_index,
+ dpo_id_t *dpo);
+
+extern void interface_tx_dpo_module_init(void);
+
+#endif
diff --git a/src/vnet/fib/fib_path.c b/src/vnet/fib/fib_path.c
index 58050ccb307..cf5a463d53c 100644
--- a/src/vnet/fib/fib_path.c
+++ b/src/vnet/fib/fib_path.c
@@ -21,7 +21,7 @@
#include <vnet/dpo/receive_dpo.h>
#include <vnet/dpo/load_balance_map.h>
#include <vnet/dpo/lookup_dpo.h>
-#include <vnet/dpo/interface_dpo.h>
+#include <vnet/dpo/interface_rx_dpo.h>
#include <vnet/dpo/mpls_disposition.h>
#include <vnet/adj/adj.h>
@@ -1707,9 +1707,9 @@ fib_path_resolve (fib_node_index_t path_index)
/*
* Resolve via a receive DPO.
*/
- interface_dpo_add_or_lock(path->fp_nh_proto,
- path->intf_rx.fp_interface,
- &path->fp_dpo);
+ interface_rx_dpo_add_or_lock(path->fp_nh_proto,
+ path->intf_rx.fp_interface,
+ &path->fp_dpo);
break;
}
case FIB_PATH_TYPE_EXCLUSIVE:
@@ -2041,9 +2041,9 @@ fib_path_contribute_forwarding (fib_node_index_t path_index,
/*
* Create the adj needed for sending IP multicast traffic
*/
- interface_dpo_add_or_lock(fib_forw_chain_type_to_dpo_proto(fct),
- path->attached.fp_interface,
- dpo);
+ interface_rx_dpo_add_or_lock(fib_forw_chain_type_to_dpo_proto(fct),
+ path->attached.fp_interface,
+ dpo);
break;
case FIB_PATH_TYPE_RECEIVE:
case FIB_PATH_TYPE_SPECIAL:
diff --git a/src/vnet/fib/fib_test.c b/src/vnet/fib/fib_test.c
index 7ca4cb3a1d7..6867cca8959 100644
--- a/src/vnet/fib/fib_test.c
+++ b/src/vnet/fib/fib_test.c
@@ -25,7 +25,7 @@
#include <vnet/dpo/receive_dpo.h>
#include <vnet/dpo/ip_null_dpo.h>
#include <vnet/bfd/bfd_main.h>
-#include <vnet/dpo/interface_dpo.h>
+#include <vnet/dpo/interface_rx_dpo.h>
#include <vnet/dpo/replicate_dpo.h>
#include <vnet/mpls/mpls.h>
@@ -407,7 +407,7 @@ fib_test_validate_rep_v (const replicate_t *rep,
}
break;
case FT_REP_INTF:
- FIB_TEST_LB((DPO_INTERFACE == dpo->dpoi_type),
+ FIB_TEST_LB((DPO_INTERFACE_RX == dpo->dpoi_type),
"bucket %d stacks on %U",
bucket,
format_dpo_type, dpo->dpoi_type);
@@ -589,7 +589,7 @@ fib_test_validate_lb_v (const load_balance_t *lb,
exp->adj.adj);
break;
case FT_LB_INTF:
- FIB_TEST_I((DPO_INTERFACE == dpo->dpoi_type),
+ FIB_TEST_I((DPO_INTERFACE_RX == dpo->dpoi_type),
"bucket %d stacks on %U",
bucket,
format_dpo_type, dpo->dpoi_type);
@@ -8523,7 +8523,7 @@ lfib_test (void)
*/
dpo_id_t idpo = DPO_INVALID;
- interface_dpo_add_or_lock(DPO_PROTO_IP4,
+ interface_rx_dpo_add_or_lock(DPO_PROTO_IP4,
tm->hw[0]->sw_if_index,
&idpo);
@@ -8667,9 +8667,9 @@ lfib_test (void)
FIB_TEST(lb_count == pool_elts(load_balance_pool),
"Load-balance resources freed %d of %d",
lb_count, pool_elts(load_balance_pool));
- FIB_TEST(0 == pool_elts(interface_dpo_pool),
- "interface_dpo resources freed %d of %d",
- 0, pool_elts(interface_dpo_pool));
+ FIB_TEST(0 == pool_elts(interface_rx_dpo_pool),
+ "interface_rx_dpo resources freed %d of %d",
+ 0, pool_elts(interface_rx_dpo_pool));
return (0);
}