aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--nsh-plugin/nsh/nsh.c157
1 files changed, 129 insertions, 28 deletions
diff --git a/nsh-plugin/nsh/nsh.c b/nsh-plugin/nsh/nsh.c
index 924eda2..12c8d6b 100644
--- a/nsh-plugin/nsh/nsh.c
+++ b/nsh-plugin/nsh/nsh.c
@@ -858,9 +858,12 @@ nsh_input_map (vlib_main_t * vm,
u32 next0 = NSH_INPUT_NEXT_DROP, next1 = NSH_INPUT_NEXT_DROP;
uword * entry0, *entry1;
nsh_header_t * hdr0 = 0, *hdr1 = 0;
+ u32 header_len0 = 0, header_len1 = 0;
u32 nsp_nsi0, nsp_nsi1;
u32 error0, error1;
nsh_map_t * map0 = 0, *map1 = 0;
+ nsh_header_t *encap_hdr0 = 0, *encap_hdr1 = 0;
+ u32 encap_hdr_len0 = 0, encap_hdr_len1 = 0;
/* Prefetch next iteration. */
{
@@ -890,73 +893,138 @@ nsh_input_map (vlib_main_t * vm,
b0 = vlib_get_buffer(vm, bi0);
hdr0 = vlib_buffer_get_current(b0);
+ header_len0 = hdr0->length * 4;
nsp_nsi0 = clib_net_to_host_u32(hdr0->nsp_nsi);
- entry0 = hash_get_mem(nm->nsh_mapping_by_key, &nsp_nsi0);
b1 = vlib_get_buffer(vm, bi1);
hdr1 = vlib_buffer_get_current(b1);
+ header_len1 = hdr1->length * 4;
nsp_nsi1 = clib_net_to_host_u32(hdr1->nsp_nsi);
- entry1 = hash_get_mem(nm->nsh_mapping_by_key, &nsp_nsi1);
+ /* Process packet 0 */
+ entry0 = hash_get_mem(nm->nsh_mapping_by_key, &nsp_nsi0);
if (PREDICT_FALSE(entry0 == 0))
{
error0 = NSH_INPUT_ERROR_NO_MAPPING;
goto trace0;
}
- if (PREDICT_FALSE(entry1 == 0))
- {
- error1 = NSH_INPUT_ERROR_NO_MAPPING;
- goto trace1;
- }
-
/* Entry should point to a mapping ...*/
map0 = pool_elt_at_index(nm->nsh_mappings, entry0[0]);
- map1 = pool_elt_at_index(nm->nsh_mappings, entry1[0]);
-
if (PREDICT_FALSE(map0 == 0))
{
error0 = NSH_INPUT_ERROR_NO_MAPPING;
goto trace0;
}
- if (PREDICT_FALSE(map1 == 0))
+ /* set up things for next node to transmit ie which node to handle it and where */
+ next0 = map0->next_node;
+ vnet_buffer(b0)->sw_if_index[VLIB_TX] = map0->sw_if_index;
+
+ if(PREDICT_FALSE(map0->nsh_action == NSH_ACTION_POP))
{
- error1 = NSH_INPUT_ERROR_NO_MAPPING;
- goto trace1;
+ /* Pop NSH header */
+ vlib_buffer_advance(b0, (word)header_len0);
+ goto trace0;
}
entry0 = hash_get_mem(nm->nsh_entry_by_key, &map0->mapped_nsp_nsi);
- entry1 = hash_get_mem(nm->nsh_entry_by_key, &map1->mapped_nsp_nsi);
-
if (PREDICT_FALSE(entry0 == 0))
{
error0 = NSH_INPUT_ERROR_NO_ENTRY;
goto trace0;
}
+
+ encap_hdr0 = pool_elt_at_index(nm->nsh_entries, entry0[0]);
+ encap_hdr_len0 = encap_hdr0->length * 4;
+
+ if(PREDICT_TRUE(map0->nsh_action == NSH_ACTION_SWAP))
+ {
+ /* Pop old NSH header */
+ vlib_buffer_advance(b0, (word)header_len0);
+
+ /* Push new NSH header */
+ vlib_buffer_advance(b0, -(word)encap_hdr_len0);
+ hdr0 = vlib_buffer_get_current(b0);
+ clib_memcpy(hdr0, encap_hdr0, (word)encap_hdr_len0);
+
+ goto trace0;
+ }
+
+ if(PREDICT_FALSE(map0->nsh_action == NSH_ACTION_PUSH))
+ {
+ /* Push new NSH header */
+ vlib_buffer_advance(b0, -(word)encap_hdr_len0);
+ hdr0 = vlib_buffer_get_current(b0);
+ clib_memcpy(hdr0, encap_hdr0, (word)encap_hdr_len0);
+ }
+
+ trace0: b0->error = error0 ? node->errors[error0] : 0;
+
+ if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
+ {
+ nsh_input_trace_t *tr = vlib_add_trace(vm, node, b0, sizeof(*tr));
+ tr->nsh_header = *hdr0;
+ }
+
+ /* Process packet 1 */
+ entry1 = hash_get_mem(nm->nsh_mapping_by_key, &nsp_nsi1);
if (PREDICT_FALSE(entry1 == 0))
{
- error1 = NSH_INPUT_ERROR_NO_ENTRY;
+ error1 = NSH_INPUT_ERROR_NO_MAPPING;
goto trace1;
}
- hdr0 = pool_elt_at_index(nm->nsh_entries, entry0[0]);
- hdr1 = pool_elt_at_index(nm->nsh_entries, entry1[0]);
+ /* Entry should point to a mapping ...*/
+ map1 = pool_elt_at_index(nm->nsh_mappings, entry1[0]);
+ if (PREDICT_FALSE(map1 == 0))
+ {
+ error1 = NSH_INPUT_ERROR_NO_MAPPING;
+ goto trace1;
+ }
/* set up things for next node to transmit ie which node to handle it and where */
- next0 = map0->next_node;
next1 = map1->next_node;
- vnet_buffer(b0)->sw_if_index[VLIB_TX] = map0->sw_if_index;
vnet_buffer(b1)->sw_if_index[VLIB_TX] = map1->sw_if_index;
- trace0: b0->error = error0 ? node->errors[error0] : 0;
+ if(PREDICT_FALSE(map1->nsh_action == NSH_ACTION_POP))
+ {
+ /* Pop NSH header */
+ vlib_buffer_advance(b1, (word)header_len1);
+ goto trace1;
+ }
- if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
+ entry1 = hash_get_mem(nm->nsh_entry_by_key, &map1->mapped_nsp_nsi);
+ if (PREDICT_FALSE(entry1 == 0))
{
- nsh_input_trace_t *tr = vlib_add_trace(vm, node, b0, sizeof(*tr));
- tr->nsh_header = *hdr0;
+ error1 = NSH_INPUT_ERROR_NO_ENTRY;
+ goto trace1;
}
+ encap_hdr1 = pool_elt_at_index(nm->nsh_entries, entry1[0]);
+ encap_hdr_len1 = encap_hdr1->length * 4;
+
+ if(PREDICT_TRUE(map1->nsh_action == NSH_ACTION_SWAP))
+ {
+ /* Pop old NSH header */
+ vlib_buffer_advance(b1, (word)header_len1);
+
+ /* Push new NSH header */
+ vlib_buffer_advance(b1, -(word)encap_hdr_len1);
+ hdr1 = vlib_buffer_get_current(b1);
+ clib_memcpy(hdr1, encap_hdr1, (word)encap_hdr_len1);
+
+ goto trace1;
+ }
+
+ if(PREDICT_FALSE(map1->nsh_action == NSH_ACTION_PUSH))
+ {
+ /* Push new NSH header */
+ vlib_buffer_advance(b1, -(word)encap_hdr_len1);
+ hdr1 = vlib_buffer_get_current(b1);
+ clib_memcpy(hdr1, encap_hdr1, (word)encap_hdr_len1);
+ }
+
trace1: b1->error = error1 ? node->errors[error1] : 0;
if (PREDICT_FALSE(b1->flags & VLIB_BUFFER_IS_TRACED))
@@ -977,9 +1045,12 @@ nsh_input_map (vlib_main_t * vm,
u32 next0 = NSH_INPUT_NEXT_DROP;
uword * entry0;
nsh_header_t * hdr0 = 0;
+ u32 header_len0 = 0;
u32 nsp_nsi0;
u32 error0;
nsh_map_t * map0 = 0;
+ nsh_header_t * encap_hdr0 = 0;
+ u32 encap_hdr_len0 = 0;
bi0 = from[0];
to_next[0] = bi0;
@@ -991,6 +1062,7 @@ nsh_input_map (vlib_main_t * vm,
b0 = vlib_get_buffer(vm, bi0);
hdr0 = vlib_buffer_get_current(b0);
+ header_len0 = hdr0->length * 4;
nsp_nsi0 = clib_net_to_host_u32(hdr0->nsp_nsi);
entry0 = hash_get_mem(nm->nsh_mapping_by_key, &nsp_nsi0);
@@ -1009,6 +1081,17 @@ nsh_input_map (vlib_main_t * vm,
goto trace00;
}
+ /* set up things for next node to transmit ie which node to handle it and where */
+ next0 = map0->next_node;
+ vnet_buffer(b0)->sw_if_index[VLIB_TX] = map0->sw_if_index;
+
+ if(PREDICT_FALSE(map0->nsh_action == NSH_ACTION_POP))
+ {
+ /* Pop NSH header */
+ vlib_buffer_advance(b0, (word)header_len0);
+ goto trace00;
+ }
+
entry0 = hash_get_mem(nm->nsh_entry_by_key, &map0->mapped_nsp_nsi);
if (PREDICT_FALSE(entry0 == 0))
@@ -1017,11 +1100,29 @@ nsh_input_map (vlib_main_t * vm,
goto trace00;
}
- hdr0 = pool_elt_at_index(nm->nsh_entries, entry0[0]);
+ encap_hdr0 = pool_elt_at_index(nm->nsh_entries, entry0[0]);
+ encap_hdr_len0 = encap_hdr0->length * 4;
- /* set up things for next node to transmit ie which node to handle it and where */
- next0 = map0->next_node;
- vnet_buffer(b0)->sw_if_index[VLIB_TX] = map0->sw_if_index;
+ if(PREDICT_TRUE(map0->nsh_action == NSH_ACTION_SWAP))
+ {
+ /* Pop old NSH header */
+ vlib_buffer_advance(b0, (word)header_len0);
+
+ /* Push new NSH header */
+ vlib_buffer_advance(b0, -(word)encap_hdr_len0);
+ hdr0 = vlib_buffer_get_current(b0);
+ clib_memcpy(hdr0, encap_hdr0, (word)encap_hdr_len0);
+
+ goto trace00;
+ }
+
+ if(PREDICT_TRUE(map0->nsh_action == NSH_ACTION_PUSH))
+ {
+ /* Push new NSH header */
+ vlib_buffer_advance(b0, -(word)encap_hdr_len0);
+ hdr0 = vlib_buffer_get_current(b0);
+ clib_memcpy(hdr0, encap_hdr0, (word)encap_hdr_len0);
+ }
trace00: b0->error = error0 ? node->errors[error0] : 0;