summaryrefslogtreecommitdiffstats
path: root/src/vnet/adj
diff options
context:
space:
mode:
authorNeale Ranns <nranns@cisco.com>2020-03-31 09:21:29 -0400
committerDamjan Marion <dmarion@me.com>2020-05-04 17:09:34 +0000
commit4ec36c5535849a4e456ed99b57968d54d5e03b62 (patch)
tree47c807c525858db02f7d1e0e4df32b14441ed5c8 /src/vnet/adj
parentb723ccf95ffd8581be15e0752eac2c5f7233b340 (diff)
fib: midchain adjacency optimisations
Type: improvement - inline some common encap fixup functions into the midchain rewrite node so we don't incur the cost of the virtual function call - change the copy 'guess' from ethernet_header (which will never happen) to an ip4 header - add adj-midchain-tx to multiarch sources - don't run adj-midchain-tx as a feature, instead put this node as the adj's next and at the end of the feature arc. - cache the feature arc config index (to save the cache miss going to fetch it) - don't check if features are enabled when taking the arc (since we know they are) the last two changes will also benefit normal adjacencies taking the arc (i.e. for NAT, ACLs, etc) for IPSec: - don't run esp_encrypt as a feature, instead when required insert this node into the adj's next and into the end of the feature arc. this implies that encrypt is always 'the last feature' run, which is symmetric with decrypt always being the first. - esp_encrpyt for tunnels has adj-midchain-tx as next node Change-Id: Ida0af56a704302cf2d7797ded5f118a781e8acb7 Signed-off-by: Neale Ranns <nranns@cisco.com>
Diffstat (limited to 'src/vnet/adj')
-rw-r--r--src/vnet/adj/adj.c9
-rw-r--r--src/vnet/adj/adj.h84
-rw-r--r--src/vnet/adj/adj_delegate.c14
-rw-r--r--src/vnet/adj/adj_delegate.h7
-rw-r--r--src/vnet/adj/adj_dp.h66
-rw-r--r--src/vnet/adj/adj_internal.h3
-rw-r--r--src/vnet/adj/adj_l2.c44
-rw-r--r--src/vnet/adj/adj_midchain.c546
-rw-r--r--src/vnet/adj/adj_midchain.h23
-rw-r--r--src/vnet/adj/adj_nbr.c11
-rw-r--r--src/vnet/adj/rewrite.c2
-rw-r--r--src/vnet/adj/rewrite.h19
12 files changed, 483 insertions, 345 deletions
diff --git a/src/vnet/adj/adj.c b/src/vnet/adj/adj.c
index c601e6bd19d..2fb77fe78d3 100644
--- a/src/vnet/adj/adj.c
+++ b/src/vnet/adj/adj.c
@@ -79,6 +79,7 @@ adj_alloc (fib_protocol_t proto)
adj->ia_nh_proto = proto;
adj->ia_flags = 0;
+ adj->ia_cfg_index = 0;
adj->rewrite_header.sw_if_index = ~0;
adj->rewrite_header.flags = 0;
adj->lookup_next_index = 0;
@@ -399,10 +400,18 @@ adj_feature_update_walk_cb (adj_index_t ai,
((ctx->arc == mpls_main.output_feature_arc_index) &&
(VNET_LINK_MPLS == adj->ia_link)))
{
+ vnet_feature_main_t *fm = &feature_main;
+ vnet_feature_config_main_t *cm;
+
+ cm = &fm->feature_config_mains[ctx->arc];
+
if (ctx->enable)
adj->rewrite_header.flags |= VNET_REWRITE_HAS_FEATURES;
else
adj->rewrite_header.flags &= ~VNET_REWRITE_HAS_FEATURES;
+
+ adj->ia_cfg_index = vec_elt (cm->config_index_by_sw_if_index,
+ adj->rewrite_header.sw_if_index);
}
return (ADJ_WALK_RC_CONTINUE);
}
diff --git a/src/vnet/adj/adj.h b/src/vnet/adj/adj.h
index e22e7ecd58a..a53122711a8 100644
--- a/src/vnet/adj/adj.h
+++ b/src/vnet/adj/adj.h
@@ -181,6 +181,10 @@ typedef enum adj_attr_t_
* If the midchain were to stack on its FIB entry a loop would form.
*/
ADJ_ATTR_MIDCHAIN_LOOPED,
+ /**
+ * the fixup function is standard IP4o4 header
+ */
+ ADJ_ATTR_MIDCHAIN_FIXUP_IP4O4_HDR,
} adj_attr_t;
#define ADJ_ATTR_NAMES { \
@@ -188,11 +192,12 @@ typedef enum adj_attr_t_
[ADJ_ATTR_MIDCHAIN_NO_COUNT] = "midchain-no-count", \
[ADJ_ATTR_MIDCHAIN_IP_STACK] = "midchain-ip-stack", \
[ADJ_ATTR_MIDCHAIN_LOOPED] = "midchain-looped", \
+ [ADJ_ATTR_MIDCHAIN_FIXUP_IP4O4_HDR] = "midchain-ip4o4-hdr-fixup", \
}
-#define FOR_EACH_ADJ_ATTR(_attr) \
- for (_attr = ADJ_ATTR_SYNC_WALK_ACTIVE; \
- _attr <= ADJ_ATTR_MIDCHAIN_LOOPED; \
+#define FOR_EACH_ADJ_ATTR(_attr) \
+ for (_attr = ADJ_ATTR_SYNC_WALK_ACTIVE; \
+ _attr <= ADJ_ATTR_MIDCHAIN_FIXUP_IP4O4_HDR; \
_attr++)
/**
@@ -205,6 +210,7 @@ typedef enum adj_flags_t_
ADJ_FLAG_MIDCHAIN_NO_COUNT = (1 << ADJ_ATTR_MIDCHAIN_NO_COUNT),
ADJ_FLAG_MIDCHAIN_IP_STACK = (1 << ADJ_ATTR_MIDCHAIN_IP_STACK),
ADJ_FLAG_MIDCHAIN_LOOPED = (1 << ADJ_ATTR_MIDCHAIN_LOOPED),
+ ADJ_FLAG_MIDCHAIN_FIXUP_IP4O4_HDR = (1 << ADJ_ATTR_MIDCHAIN_FIXUP_IP4O4_HDR),
} __attribute__ ((packed)) adj_flags_t;
/**
@@ -227,32 +233,10 @@ typedef struct ip_adjacency_t_
* has 8 byte alignment requirements.
*/
fib_node_t ia_node;
-
- /**
- * Next hop after ip4-lookup.
- * This is not accessed in the rewrite nodes.
- * 1-bytes
- */
- ip_lookup_next_t lookup_next_index;
-
- /**
- * link/ether-type
- * 1 bytes
- */
- vnet_link_t ia_link;
-
/**
- * The protocol of the neighbor/peer. i.e. the protocol with
- * which to interpret the 'next-hop' attributes of the sub-types.
- * 1-bytes
+ * feature [arc] config index
*/
- fib_protocol_t ia_nh_proto;
-
- /**
- * Flags on the adjacency
- * 1-bytes
- */
- adj_flags_t ia_flags;
+ u32 ia_cfg_index;
union
{
@@ -298,6 +282,10 @@ typedef struct ip_adjacency_t_
* loop detection.
*/
fib_node_index_t fei;
+
+ /** spare space */
+ u8 __ia_midchain_pad[4];
+
} midchain;
/**
* IP_LOOKUP_NEXT_GLEAN
@@ -315,12 +303,14 @@ typedef struct ip_adjacency_t_
CLIB_CACHE_LINE_ALIGN_MARK (cacheline1);
- /* Rewrite in second/third cache lines */
+ /** Rewrite in second and third cache lines */
VNET_DECLARE_REWRITE;
/**
* more control plane members that do not fit on the first cacheline
*/
+ CLIB_CACHE_LINE_ALIGN_MARK (cacheline3);
+
/**
* A sorted vector of delegates
*/
@@ -330,6 +320,37 @@ typedef struct ip_adjacency_t_
* The VLIB node in which this adj is used to forward packets
*/
u32 ia_node_index;
+
+ /**
+ * Next hop after ip4-lookup.
+ * This is not accessed in the rewrite nodes.
+ * 1-bytes
+ */
+ ip_lookup_next_t lookup_next_index;
+
+ /**
+ * link/ether-type
+ * 1 bytes
+ */
+ vnet_link_t ia_link;
+
+ /**
+ * The protocol of the neighbor/peer. i.e. the protocol with
+ * which to interpret the 'next-hop' attributes of the sub-types.
+ * 1-bytes
+ */
+ fib_protocol_t ia_nh_proto;
+
+ /**
+ * Flags on the adjacency
+ * 1-bytes
+ */
+ adj_flags_t ia_flags;
+
+ /**
+ * Free space on the fourth cacheline (not used in the DP)
+ */
+ u8 __ia_pad[48];
} ip_adjacency_t;
STATIC_ASSERT ((STRUCT_OFFSET_OF (ip_adjacency_t, cacheline0) == 0),
@@ -337,6 +358,13 @@ STATIC_ASSERT ((STRUCT_OFFSET_OF (ip_adjacency_t, cacheline0) == 0),
STATIC_ASSERT ((STRUCT_OFFSET_OF (ip_adjacency_t, cacheline1) ==
CLIB_CACHE_LINE_BYTES),
"IP adjacency cacheline 1 is more than one cacheline size offset");
+#if defined __x86_64__
+STATIC_ASSERT ((STRUCT_OFFSET_OF (ip_adjacency_t, cacheline3) ==
+ 3 * CLIB_CACHE_LINE_BYTES),
+ "IP adjacency cacheline 3 is more than one cacheline size offset");
+/* An adj fits into 4 cachelines on your average machine */
+STATIC_ASSERT_SIZEOF (ip_adjacency_t, 4 * 64);
+#endif
/**
* @brief
diff --git a/src/vnet/adj/adj_delegate.c b/src/vnet/adj/adj_delegate.c
index 87a83fb4239..8f590461b20 100644
--- a/src/vnet/adj/adj_delegate.c
+++ b/src/vnet/adj/adj_delegate.c
@@ -125,6 +125,20 @@ adj_delegate_add (ip_adjacency_t *adj,
}
void
+adj_delegate_adj_modified (ip_adjacency_t *adj)
+{
+ adj_delegate_t *aed;
+
+ vec_foreach(aed, adj->ia_delegates)
+ {
+ if (ad_vfts[aed->ad_type].adv_adj_modified)
+ {
+ ad_vfts[aed->ad_type].adv_adj_modified(aed);
+ }
+ }
+}
+
+void
adj_delegate_adj_deleted (ip_adjacency_t *adj)
{
adj_delegate_t *aed;
diff --git a/src/vnet/adj/adj_delegate.h b/src/vnet/adj/adj_delegate.h
index d49c6661c19..c83a00cd271 100644
--- a/src/vnet/adj/adj_delegate.h
+++ b/src/vnet/adj/adj_delegate.h
@@ -83,11 +83,18 @@ typedef u8 * (*adj_delegate_format_t)(const adj_delegate_t *aed, u8 *s);
typedef void (*adj_delegate_adj_created_t)(adj_index_t ai);
/**
+ * Indication that the adjacency has been modified.
+ * the delegate.
+ */
+typedef void (*adj_delegate_adj_modified_t)(adj_delegate_t *aed);
+
+/**
* An ADJ delegate virtual function table
*/
typedef struct adj_delegate_vft_t_ {
adj_delegate_format_t adv_format;
adj_delegate_adj_deleted_t adv_adj_deleted;
+ adj_delegate_adj_modified_t adv_adj_modified;
adj_delegate_adj_created_t adv_adj_created;
} adj_delegate_vft_t;
diff --git a/src/vnet/adj/adj_dp.h b/src/vnet/adj/adj_dp.h
new file mode 100644
index 00000000000..27c0581fcfb
--- /dev/null
+++ b/src/vnet/adj/adj_dp.h
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+
+#ifndef __ADJ_DP_H__
+#define __ADJ_DP_H__
+
+#include <vnet/adj/adj.h>
+#include <vnet/tunnel/tunnel_dp.h>
+
+static_always_inline void
+adj_midchain_ipip44_fixup (vlib_main_t * vm,
+ const ip_adjacency_t * adj,
+ vlib_buffer_t * b)
+{
+ tunnel_encap_decap_flags_t flags;
+ ip4_header_t *ip4;
+
+ flags = pointer_to_uword (adj->sub_type.midchain.fixup_data);
+
+ ip4 = vlib_buffer_get_current (b);
+ ip4->length = clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b));
+
+ if (PREDICT_TRUE(TUNNEL_ENCAP_DECAP_FLAG_NONE == flags))
+ {
+ ip_csum_t sum;
+ u16 old,new;
+
+ old = 0;
+ new = ip4->length;
+
+ sum = ip4->checksum;
+ sum = ip_csum_update (sum, old, new, ip4_header_t, length);
+ ip4->checksum = ip_csum_fold (sum);
+ }
+ else
+ {
+ tunnel_encap_fixup_4o4 (flags, ip4 + 1, ip4);
+ ip4->checksum = ip4_header_checksum (ip4);
+ }
+}
+
+static_always_inline void
+adj_midchain_fixup (vlib_main_t *vm,
+ const ip_adjacency_t *adj,
+ vlib_buffer_t * b)
+{
+ if (PREDICT_TRUE(adj->rewrite_header.flags & VNET_REWRITE_FIXUP_IP4_O_4))
+ adj_midchain_ipip44_fixup (vm, adj, b);
+ else if (adj->sub_type.midchain.fixup_func)
+ adj->sub_type.midchain.fixup_func
+ (vm, adj, b, adj->sub_type.midchain.fixup_data);
+}
+
+#endif
diff --git a/src/vnet/adj/adj_internal.h b/src/vnet/adj/adj_internal.h
index c4dda51324c..11214932a3a 100644
--- a/src/vnet/adj/adj_internal.h
+++ b/src/vnet/adj/adj_internal.h
@@ -53,7 +53,7 @@ adj_get_rewrite_node (vnet_link_t linkt)
case VNET_LINK_MPLS:
return (mpls_output_node.index);
case VNET_LINK_ETHERNET:
- return (adj_l2_rewrite_node.index);
+ return (adj_l2_rewrite_node.index);
case VNET_LINK_NSH:
return (adj_nsh_rewrite_node.index);
case VNET_LINK_ARP:
@@ -138,6 +138,7 @@ extern int adj_bfd_is_up (adj_index_t ai);
*/
extern void adj_delegate_adj_deleted(ip_adjacency_t *adj);
extern void adj_delegate_adj_created(ip_adjacency_t *adj);
+extern void adj_delegate_adj_modified(ip_adjacency_t *adj);
extern u8* adj_delegate_format(u8* s, ip_adjacency_t *adj);
#endif
diff --git a/src/vnet/adj/adj_l2.c b/src/vnet/adj/adj_l2.c
index a289158c7f3..5413eca6212 100644
--- a/src/vnet/adj/adj_l2.c
+++ b/src/vnet/adj/adj_l2.c
@@ -48,7 +48,8 @@ always_inline uword
adj_l2_rewrite_inline (vlib_main_t * vm,
vlib_node_runtime_t * node,
vlib_frame_t * frame,
- int is_midchain)
+ int is_midchain,
+ int do_counters)
{
u32 * from = vlib_frame_vector_args (frame);
u32 n_left_from, n_left_to_next, * to_next, next_index;
@@ -67,7 +68,7 @@ adj_l2_rewrite_inline (vlib_main_t * vm,
ip_adjacency_t * adj0;
vlib_buffer_t * p0;
char *h0;
- u32 pi0, rw_len0, adj_index0, next0 = 0;
+ u32 pi0, rw_len0, len0, adj_index0, next0 = 0;
u32 tx_sw_if_index0;
pi0 = to_next[0] = from[0];
@@ -83,29 +84,30 @@ adj_l2_rewrite_inline (vlib_main_t * vm,
adj0 = adj_get (adj_index0);
- /* Guess we are only writing on simple Ethernet header. */
+ /* Guess we are writing on ip4 header. */
vnet_rewrite_one_header (adj0[0], h0,
- sizeof (ethernet_header_t));
+ //sizeof (gre_header_t) +
+ sizeof (ip4_header_t));
/* Update packet buffer attributes/set output interface. */
rw_len0 = adj0[0].rewrite_header.data_bytes;
vnet_buffer(p0)->ip.save_rewrite_length = rw_len0;
vnet_buffer(p0)->sw_if_index[VLIB_TX] = adj0->rewrite_header.sw_if_index;
+ len0 = vlib_buffer_length_in_chain (vm, p0);
/* since we are coming out of the L2 world, where the vlib_buffer
* union is used for other things, make sure it is clean for
* MPLS from now on.
*/
vnet_buffer(p0)->mpls.first = 0;
- vlib_increment_combined_counter(&adjacency_counters,
- thread_index,
- adj_index0,
- /* packet increment */ 0,
- /* byte increment */ rw_len0);
+ if (do_counters)
+ vlib_increment_combined_counter(&adjacency_counters,
+ thread_index,
+ adj_index0,
+ 0, len0);
/* Check MTU of outgoing interface. */
- if (PREDICT_TRUE((vlib_buffer_length_in_chain (vm, p0) <=
- adj0[0].rewrite_header.max_l3_packet_bytes)))
+ if (PREDICT_TRUE(len0 <= adj0[0].rewrite_header.max_l3_packet_bytes))
{
/* Don't adjust the buffer for ttl issue; icmp-error node wants
* to see the IP header */
@@ -126,7 +128,15 @@ adj_l2_rewrite_inline (vlib_main_t * vm,
* Follow the feature ARC. this will result eventually in
* the midchain-tx node
*/
- vnet_feature_arc_start(em->output_feature_arc_index, tx_sw_if_index0, &next0, p0);
+ if (PREDICT_FALSE (adj0->rewrite_header.flags &
+ VNET_REWRITE_HAS_FEATURES))
+ vnet_feature_arc_start_w_cfg_index (
+ em->output_feature_arc_index,
+ tx_sw_if_index0,
+ &next0, p0,
+ adj0->ia_cfg_index);
+ else
+ next0 = adj0[0].rewrite_header.next_index;
}
else
{
@@ -156,14 +166,20 @@ VLIB_NODE_FN (adj_l2_rewrite_node) (vlib_main_t * vm,
vlib_node_runtime_t * node,
vlib_frame_t * frame)
{
- return adj_l2_rewrite_inline (vm, node, frame, 0);
+ if (adj_are_counters_enabled ())
+ return adj_l2_rewrite_inline (vm, node, frame, 0, 1);
+ else
+ return adj_l2_rewrite_inline (vm, node, frame, 0, 0);
}
VLIB_NODE_FN (adj_l2_midchain_node) (vlib_main_t * vm,
vlib_node_runtime_t * node,
vlib_frame_t * frame)
{
- return adj_l2_rewrite_inline (vm, node, frame, 1);
+ if (adj_are_counters_enabled ())
+ return adj_l2_rewrite_inline (vm, node, frame, 1, 1);
+ else
+ return adj_l2_rewrite_inline (vm, node, frame, 1, 0);
}
VLIB_REGISTER_NODE (adj_l2_rewrite_node) = {
diff --git a/src/vnet/adj/adj_midchain.c b/src/vnet/adj/adj_midchain.c
index 88648fea0a9..4741ec9a953 100644
--- a/src/vnet/adj/adj_midchain.c
+++ b/src/vnet/adj/adj_midchain.c
@@ -25,14 +25,6 @@
#include <vnet/fib/fib_entry.h>
/**
- * The two midchain tx feature node indices
- */
-static u32 adj_midchain_tx_feature_node[VNET_LINK_NUM];
-static u32 adj_midchain_tx_no_count_feature_node[VNET_LINK_NUM];
-
-static u32 *adj_midchain_feat_count_per_sw_if_index[VNET_LINK_NUM];
-
-/**
* @brief Trace data for packets traversing the midchain tx node
*/
typedef struct adj_midchain_tx_trace_t_
@@ -49,203 +41,158 @@ adj_midchain_tx_inline (vlib_main_t * vm,
vlib_frame_t * frame,
int interface_count)
{
- u32 * from, * to_next, n_left_from, n_left_to_next;
- u32 next_index;
+ vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b;
+ u16 nexts[VLIB_FRAME_SIZE], *next;
+ u32 * from, n_left, thread_index;
vnet_main_t *vnm = vnet_get_main ();
vnet_interface_main_t *im = &vnm->interface_main;
- u32 thread_index = vm->thread_index;
- /* Vector of buffer / pkt indices we're supposed to process */
+ thread_index = vm->thread_index;
+ n_left = frame->n_vectors;
from = vlib_frame_vector_args (frame);
- /* Number of buffers / pkts */
- n_left_from = frame->n_vectors;
+ vlib_get_buffers (vm, from, bufs, n_left);
- /* Speculatively send the first buffer to the last disposition we used */
- next_index = node->cached_next_index;
+ next = nexts;
+ b = bufs;
- while (n_left_from > 0)
+ while (n_left > 8)
{
- /* 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);
+ u32 adj_index0, adj_index1, adj_index2, adj_index3;
+ const ip_adjacency_t *adj0, *adj1, *adj2, *adj3;
+ const dpo_id_t *dpo0, *dpo1, *dpo2, *dpo3;
- while (n_left_from >= 8 && n_left_to_next > 4)
- {
- const ip_adjacency_t *adj0, *adj1, *adj2, *adj3;
- const dpo_id_t *dpo0, *dpo1, *dpo2, *dpo3;
- vlib_buffer_t * b0, *b1, *b2, *b3;
- u32 bi0, adj_index0, next0;
- u32 bi1, adj_index1, next1;
- u32 bi2, adj_index2, next2;
- u32 bi3, adj_index3, next3;
-
- /* Prefetch next iteration. */
- {
- 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 += 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(b2)->ip.adj_index[VLIB_TX] = dpo2->dpoi_index;
- vnet_buffer(b3)->ip.adj_index[VLIB_TX] = dpo3->dpoi_index;
-
- if (interface_count)
- {
- vlib_increment_combined_counter (im->combined_sw_if_counters
- + VNET_INTERFACE_COUNTER_TX,
- thread_index,
- adj0->rewrite_header.sw_if_index,
- 1,
- vlib_buffer_length_in_chain (vm, b0));
- vlib_increment_combined_counter (im->combined_sw_if_counters
- + VNET_INTERFACE_COUNTER_TX,
- thread_index,
- 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))
- {
- adj_midchain_tx_trace_t *tr = vlib_add_trace (vm, node,
- b0, sizeof (*tr));
- tr->ai = adj_index0;
- }
- if (PREDICT_FALSE(b1->flags & VLIB_BUFFER_IS_TRACED))
- {
- adj_midchain_tx_trace_t *tr = vlib_add_trace (vm, node,
- 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_x4 (vm, node, next_index,
- to_next, n_left_to_next,
- bi0, bi1, bi2, bi3,
- next0, next1, next2, next3);
- }
- while (n_left_from > 0 && n_left_to_next > 0)
- {
- u32 bi0, adj_index0, next0;
- const ip_adjacency_t * adj0;
- const dpo_id_t *dpo0;
- vlib_buffer_t * b0;
-
- 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);
-
- /* Follow the DPO on which the midchain is stacked */
- adj_index0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
- 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;
-
- if (interface_count)
- {
- vlib_increment_combined_counter (im->combined_sw_if_counters
- + VNET_INTERFACE_COUNTER_TX,
- thread_index,
- adj0->rewrite_header.sw_if_index,
- 1,
- vlib_buffer_length_in_chain (vm, b0));
- }
-
- if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
- {
- adj_midchain_tx_trace_t *tr = vlib_add_trace (vm, node,
- b0, sizeof (*tr));
- tr->ai = adj_index0;
- }
-
- vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
- to_next, n_left_to_next,
- bi0, next0);
- }
+ /* Prefetch next iteration. */
+ {
+ vlib_prefetch_buffer_header (b[4], LOAD);
+ vlib_prefetch_buffer_header (b[5], LOAD);
+ vlib_prefetch_buffer_header (b[6], LOAD);
+ vlib_prefetch_buffer_header (b[7], LOAD);
+ }
- vlib_put_next_frame (vm, node, next_index, n_left_to_next);
+ /* Follow the DPO on which the midchain is stacked */
+ adj_index0 = vnet_buffer(b[0])->ip.adj_index[VLIB_TX];
+ adj_index1 = vnet_buffer(b[1])->ip.adj_index[VLIB_TX];
+ adj_index2 = vnet_buffer(b[2])->ip.adj_index[VLIB_TX];
+ adj_index3 = vnet_buffer(b[3])->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;
+
+ next[0] = dpo0->dpoi_next_node;
+ next[1] = dpo1->dpoi_next_node;
+ next[2] = dpo2->dpoi_next_node;
+ next[3] = dpo3->dpoi_next_node;
+
+ vnet_buffer(b[0])->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
+ vnet_buffer(b[1])->ip.adj_index[VLIB_TX] = dpo1->dpoi_index;
+ vnet_buffer(b[2])->ip.adj_index[VLIB_TX] = dpo2->dpoi_index;
+ vnet_buffer(b[3])->ip.adj_index[VLIB_TX] = dpo3->dpoi_index;
+
+ if (interface_count)
+ {
+ vlib_increment_combined_counter (im->combined_sw_if_counters
+ + VNET_INTERFACE_COUNTER_TX,
+ thread_index,
+ adj0->rewrite_header.sw_if_index,
+ 1,
+ vlib_buffer_length_in_chain (vm, b[0]));
+ vlib_increment_combined_counter (im->combined_sw_if_counters
+ + VNET_INTERFACE_COUNTER_TX,
+ thread_index,
+ adj1->rewrite_header.sw_if_index,
+ 1,
+ vlib_buffer_length_in_chain (vm, b[1]));
+ 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, b[2]));
+ 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, b[3]));
+ }
+
+ if (PREDICT_FALSE(node->flags & VLIB_NODE_FLAG_TRACE))
+ {
+ if (PREDICT_FALSE(b[0]->flags & VLIB_BUFFER_IS_TRACED))
+ {
+ adj_midchain_tx_trace_t *tr = vlib_add_trace (vm, node,
+ b[0], sizeof (*tr));
+ tr->ai = adj_index0;
+ }
+ if (PREDICT_FALSE(b[1]->flags & VLIB_BUFFER_IS_TRACED))
+ {
+ adj_midchain_tx_trace_t *tr = vlib_add_trace (vm, node,
+ b[1], sizeof (*tr));
+ tr->ai = adj_index1;
+ }
+ if (PREDICT_FALSE(b[2]->flags & VLIB_BUFFER_IS_TRACED))
+ {
+ adj_midchain_tx_trace_t *tr = vlib_add_trace (vm, node,
+ b[2], sizeof (*tr));
+ tr->ai = adj_index2;
+ }
+ if (PREDICT_FALSE(b[3]->flags & VLIB_BUFFER_IS_TRACED))
+ {
+ adj_midchain_tx_trace_t *tr = vlib_add_trace (vm, node,
+ b[3], sizeof (*tr));
+ tr->ai = adj_index3;
+ }
+ }
+ n_left -= 4;
+ b += 4;
+ next += 4;
}
+ while (n_left)
+ {
+ const ip_adjacency_t * adj0;
+ const dpo_id_t *dpo0;
+ u32 adj_index0;
+
+ /* Follow the DPO on which the midchain is stacked */
+ adj_index0 = vnet_buffer(b[0])->ip.adj_index[VLIB_TX];
+ adj0 = adj_get(adj_index0);
+ dpo0 = &adj0->sub_type.midchain.next_dpo;
+ next[0] = dpo0->dpoi_next_node;
+ vnet_buffer(b[0])->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
+
+ if (interface_count)
+ {
+ vlib_increment_combined_counter (im->combined_sw_if_counters
+ + VNET_INTERFACE_COUNTER_TX,
+ thread_index,
+ adj0->rewrite_header.sw_if_index,
+ 1,
+ vlib_buffer_length_in_chain (vm, b[0]));
+ }
+
+ if (PREDICT_FALSE(b[0]->flags & VLIB_BUFFER_IS_TRACED))
+ {
+ adj_midchain_tx_trace_t *tr = vlib_add_trace (vm, node,
+ b[0], sizeof (*tr));
+ tr->ai = adj_index0;
+ }
+
+ n_left -= 1;
+ b += 1;
+ next += 1;
+ }
+
+ vlib_buffer_enqueue_to_next (vm, node, from, nexts, frame->n_vectors);
+
return frame->n_vectors;
}
@@ -271,7 +218,7 @@ adj_midchain_tx (vlib_main_t * vm,
return (adj_midchain_tx_inline(vm, node, frame, 1));
}
-VLIB_REGISTER_NODE (adj_midchain_tx_node, static) = {
+VLIB_REGISTER_NODE (adj_midchain_tx_node) = {
.function = adj_midchain_tx,
.name = "adj-midchain-tx",
.vector_size = sizeof (u32),
@@ -292,79 +239,44 @@ adj_midchain_tx_no_count (vlib_main_t * vm,
return (adj_midchain_tx_inline(vm, node, frame, 0));
}
-VLIB_REGISTER_NODE (adj_midchain_tx_no_count_node, static) = {
+VLIB_REGISTER_NODE (adj_midchain_tx_no_count_node) = {
.function = adj_midchain_tx_no_count,
.name = "adj-midchain-tx-no-count",
.vector_size = sizeof (u32),
.format_trace = format_adj_midchain_tx_trace,
-
- .n_next_nodes = 1,
- .next_nodes = {
- [0] = "error-drop",
- },
+ .sibling_of = "adj-midchain-tx",
};
-VNET_FEATURE_INIT (adj_midchain_tx_ip4, static) = {
- .arc_name = "ip4-output",
- .node_name = "adj-midchain-tx",
- .runs_before = VNET_FEATURES ("interface-output"),
- .feature_index_ptr = &adj_midchain_tx_feature_node[VNET_LINK_IP4],
-};
-VNET_FEATURE_INIT (adj_midchain_tx_no_count_ip4, static) = {
- .arc_name = "ip4-output",
- .node_name = "adj-midchain-tx-no-count",
- .runs_before = VNET_FEATURES ("interface-output"),
- .feature_index_ptr = &adj_midchain_tx_no_count_feature_node[VNET_LINK_IP4],
-};
-VNET_FEATURE_INIT (adj_midchain_tx_ip6, static) = {
- .arc_name = "ip6-output",
- .node_name = "adj-midchain-tx",
- .runs_before = VNET_FEATURES ("interface-output"),
- .feature_index_ptr = &adj_midchain_tx_feature_node[VNET_LINK_IP6],
-};
-VNET_FEATURE_INIT (adj_midchain_tx_no_count_ip6, static) = {
- .arc_name = "ip6-output",
- .node_name = "adj-midchain-tx-no-count",
- .runs_before = VNET_FEATURES ("interface-output"),
- .feature_index_ptr = &adj_midchain_tx_no_count_feature_node[VNET_LINK_IP6],
-};
-VNET_FEATURE_INIT (adj_midchain_tx_mpls, static) = {
- .arc_name = "mpls-output",
- .node_name = "adj-midchain-tx",
- .runs_before = VNET_FEATURES ("interface-output"),
- .feature_index_ptr = &adj_midchain_tx_feature_node[VNET_LINK_MPLS],
-};
-VNET_FEATURE_INIT (adj_midchain_tx_no_count_mpls, static) = {
- .arc_name = "mpls-output",
- .node_name = "adj-midchain-tx-no-count",
- .runs_before = VNET_FEATURES ("interface-output"),
- .feature_index_ptr = &adj_midchain_tx_no_count_feature_node[VNET_LINK_MPLS],
-};
-VNET_FEATURE_INIT (adj_midchain_tx_ethernet, static) = {
- .arc_name = "ethernet-output",
- .node_name = "adj-midchain-tx",
- .runs_before = VNET_FEATURES ("error-drop"),
- .feature_index_ptr = &adj_midchain_tx_feature_node[VNET_LINK_ETHERNET],
-};
-VNET_FEATURE_INIT (adj_midchain_tx_no_count_ethernet, static) = {
- .arc_name = "ethernet-output",
- .node_name = "adj-midchain-tx-no-count",
- .runs_before = VNET_FEATURES ("error-drop"),
- .feature_index_ptr = &adj_midchain_tx_no_count_feature_node[VNET_LINK_ETHERNET],
-};
-VNET_FEATURE_INIT (adj_midchain_tx_nsh, static) = {
- .arc_name = "nsh-output",
- .node_name = "adj-midchain-tx",
- .runs_before = VNET_FEATURES ("error-drop"),
- .feature_index_ptr = &adj_midchain_tx_feature_node[VNET_LINK_NSH],
-};
-VNET_FEATURE_INIT (adj_midchain_tx_no_count_nsh, static) = {
- .arc_name = "nsh-output",
- .node_name = "adj-midchain-tx-no-count",
- .runs_before = VNET_FEATURES ("error-drop"),
- .feature_index_ptr = &adj_midchain_tx_no_count_feature_node[VNET_LINK_NSH],
-};
+#ifndef CLIB_MARCH_VARIANT
+
+u8
+adj_is_midchain (adj_index_t ai)
+{
+ ip_adjacency_t *adj;
+
+ adj = adj_get(ai);
+
+ switch (adj->lookup_next_index)
+ {
+ case IP_LOOKUP_NEXT_MIDCHAIN:
+ case IP_LOOKUP_NEXT_MCAST_MIDCHAIN:
+ return (1);
+ case IP_LOOKUP_NEXT_ARP:
+ case IP_LOOKUP_NEXT_GLEAN:
+ case IP_LOOKUP_NEXT_BCAST:
+ case IP_LOOKUP_NEXT_MCAST:
+ case IP_LOOKUP_NEXT_DROP:
+ case IP_LOOKUP_NEXT_PUNT:
+ case IP_LOOKUP_NEXT_LOCAL:
+ case IP_LOOKUP_NEXT_REWRITE:
+ case IP_LOOKUP_NEXT_ICMP_ERROR:
+ case IP_LOOKUP_N_NEXT:
+ return (0);
+ }
+
+ return (0);
+}
static inline u32
adj_get_midchain_node (vnet_link_t link)
@@ -436,17 +348,6 @@ 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
*
@@ -455,20 +356,17 @@ adj_nbr_midchain_get_feature_node (ip_adjacency_t *adj)
void
adj_midchain_teardown (ip_adjacency_t *adj)
{
- u32 feature_index;
- u8 arc_index;
+ vlib_main_t *vm = vlib_get_main();
dpo_reset(&adj->sub_type.midchain.next_dpo);
- arc_index = adj_midchain_get_feature_arc_index_for_link_type (adj);
- feature_index = adj_nbr_midchain_get_feature_node(adj);
-
- if (0 == --adj_midchain_feat_count_per_sw_if_index[adj->ia_link][adj->rewrite_header.sw_if_index])
- {
- vnet_feature_enable_disable_with_index (arc_index, feature_index,
- adj->rewrite_header.sw_if_index,
- 0, 0, 0);
- }
+ vlib_worker_thread_barrier_sync(vm);
+ vnet_feature_modify_end_node(
+ adj_midchain_get_feature_arc_index_for_link_type (adj),
+ adj->rewrite_header.sw_if_index,
+ vlib_get_node_by_name (vlib_get_main(),
+ (u8*) "interface-output")->index);
+ vlib_worker_thread_barrier_release(vm);
}
/**
@@ -482,9 +380,9 @@ adj_midchain_setup (adj_index_t adj_index,
const void *data,
adj_flags_t flags)
{
- u32 feature_index, tx_node;
+ vlib_main_t *vm = vlib_get_main();
ip_adjacency_t *adj;
- u8 arc_index;
+ u32 tx_node;
ASSERT(ADJ_INDEX_INVALID != adj_index);
@@ -495,19 +393,23 @@ adj_midchain_setup (adj_index_t adj_index,
adj->sub_type.midchain.fei = FIB_NODE_INDEX_INVALID;
adj->ia_flags |= flags;
- arc_index = adj_midchain_get_feature_arc_index_for_link_type (adj);
- feature_index = adj_nbr_midchain_get_feature_node(adj);
- tx_node = adj_nbr_midchain_get_tx_node(adj);
-
- vec_validate (adj_midchain_feat_count_per_sw_if_index[adj->ia_link],
- adj->rewrite_header.sw_if_index);
-
- if (0 == adj_midchain_feat_count_per_sw_if_index[adj->ia_link][adj->rewrite_header.sw_if_index]++)
+ if (flags & ADJ_FLAG_MIDCHAIN_FIXUP_IP4O4_HDR)
{
- vnet_feature_enable_disable_with_index (arc_index, feature_index,
- adj->rewrite_header.sw_if_index,
- 1 /* enable */, 0, 0);
+ adj->rewrite_header.flags |= VNET_REWRITE_FIXUP_IP4_O_4;
}
+ else
+ {
+ adj->rewrite_header.flags &= ~VNET_REWRITE_FIXUP_IP4_O_4;
+ }
+
+ tx_node = adj_nbr_midchain_get_tx_node(adj);
+
+ vlib_worker_thread_barrier_sync(vm);
+ vnet_feature_modify_end_node(
+ adj_midchain_get_feature_arc_index_for_link_type (adj),
+ adj->rewrite_header.sw_if_index,
+ tx_node);
+ vlib_worker_thread_barrier_release(vm);
/*
* stack the midchain on the drop so it's ready to forward in the adj-midchain-tx.
@@ -561,6 +463,58 @@ adj_nbr_midchain_update_rewrite (adj_index_t adj_index,
rewrite);
}
+void
+adj_nbr_midchain_update_next_node (adj_index_t adj_index,
+ u32 next_node)
+{
+ ip_adjacency_t *adj;
+ vlib_main_t * vm;
+
+ ASSERT(ADJ_INDEX_INVALID != adj_index);
+
+ adj = adj_get(adj_index);
+ vm = vlib_get_main();
+
+ vlib_worker_thread_barrier_sync(vm);
+
+ adj->rewrite_header.next_index = vlib_node_add_next(vlib_get_main(),
+ adj->ia_node_index,
+ next_node);
+
+ vnet_feature_modify_end_node(
+ adj_midchain_get_feature_arc_index_for_link_type (adj),
+ adj->rewrite_header.sw_if_index,
+ next_node);
+
+ vlib_worker_thread_barrier_release(vm);
+}
+
+void
+adj_nbr_midchain_reset_next_node(adj_index_t adj_index)
+{
+ ip_adjacency_t *adj;
+ vlib_main_t * vm;
+
+ ASSERT(ADJ_INDEX_INVALID != adj_index);
+
+ adj = adj_get(adj_index);
+ vm = vlib_get_main();
+
+ vlib_worker_thread_barrier_sync(vm);
+
+ adj->rewrite_header.next_index =
+ vlib_node_add_next(vlib_get_main(),
+ adj->ia_node_index,
+ adj_nbr_midchain_get_tx_node(adj));
+
+ vnet_feature_modify_end_node(
+ adj_midchain_get_feature_arc_index_for_link_type (adj),
+ adj->rewrite_header.sw_if_index,
+ adj_nbr_midchain_get_tx_node(adj));
+
+ vlib_worker_thread_barrier_release(vm);
+}
+
/**
* adj_nbr_midchain_unstack
*
@@ -810,3 +764,5 @@ adj_midchain_module_init (void)
{
dpo_register(DPO_ADJACENCY_MIDCHAIN, &adj_midchain_dpo_vft, midchain_nodes);
}
+
+#endif
diff --git a/src/vnet/adj/adj_midchain.h b/src/vnet/adj/adj_midchain.h
index 1f5deaecd95..5fb0ee8efb3 100644
--- a/src/vnet/adj/adj_midchain.h
+++ b/src/vnet/adj/adj_midchain.h
@@ -52,6 +52,27 @@ extern void adj_nbr_midchain_update_rewrite(adj_index_t adj_index,
/**
* @brief
+ * Return the adjacency's next node to its default value
+ *
+ * @param adj_index
+ * The index of the neighbour adjacency.
+ */
+extern void adj_nbr_midchain_reset_next_node(adj_index_t adj_index);
+
+/**
+ * @brief
+ * Update the VLIB node to which packets are sent post processing
+ *
+ * @param adj_index
+ * The index of the neighbour adjacency.
+ *
+ * @param node node-index to send to
+ */
+extern void adj_nbr_midchain_update_next_node(adj_index_t adj_index,
+ u32 node_index);
+
+/**
+ * @brief
* [re]stack a midchain. 'Stacking' is the act of forming parent-child
* relationships in the data-plane graph. Do NOT use this function to
* stack on a DPO type that might form a loop.
@@ -139,4 +160,6 @@ extern void adj_midchain_delegate_restack(adj_index_t ai);
*/
extern void adj_midchain_delegate_unstack(adj_index_t ai);
+extern u8 adj_is_midchain (adj_index_t ai);
+
#endif
diff --git a/src/vnet/adj/adj_nbr.c b/src/vnet/adj/adj_nbr.c
index 7acdccc72b0..8604bf73dd6 100644
--- a/src/vnet/adj/adj_nbr.c
+++ b/src/vnet/adj/adj_nbr.c
@@ -168,9 +168,16 @@ adj_nbr_evaluate_feature (adj_index_t ai)
{
feature_count = fm->feature_count_by_sw_if_index[arc_index][sw_if_index];
if (feature_count > 0)
+ {
+ vnet_feature_config_main_t *cm;
+
adj->rewrite_header.flags |= VNET_REWRITE_HAS_FEATURES;
- }
+ cm = &fm->feature_config_mains[arc_index];
+ adj->ia_cfg_index = vec_elt (cm->config_index_by_sw_if_index,
+ sw_if_index);
+ }
+ }
return;
}
@@ -521,6 +528,7 @@ adj_nbr_update_rewrite_internal (ip_adjacency_t *adj,
walk_adj->ia_flags &= ~ADJ_FLAG_SYNC_WALK_ACTIVE;
}
+ adj_delegate_adj_modified(adj);
adj_unlock(ai);
adj_unlock(walk_ai);
}
@@ -578,7 +586,6 @@ adj_nbr_walk_cb (BVT(clib_bihash_kv) * kvp,
{
adj_walk_ctx_t *ctx = arg;
- // FIXME: can't stop early...
if (ADJ_WALK_RC_STOP == ctx->awc_cb(kvp->value, ctx->awc_ctx))
return (BIHASH_WALK_STOP);
return (BIHASH_WALK_CONTINUE);
diff --git a/src/vnet/adj/rewrite.c b/src/vnet/adj/rewrite.c
index c8508c4b37a..fc2df9af109 100644
--- a/src/vnet/adj/rewrite.c
+++ b/src/vnet/adj/rewrite.c
@@ -60,7 +60,7 @@ format_vnet_rewrite (u8 * s, va_list * args)
s = format (s, "DELETED:%d", rw->sw_if_index);
}
- s = format (s, " mtu:%d", rw->max_l3_packet_bytes);
+ s = format (s, " mtu:%d next:%d", rw->max_l3_packet_bytes, rw->next_index);
/* Format rewrite string. */
if (rw->data_bytes > 0)
diff --git a/src/vnet/adj/rewrite.h b/src/vnet/adj/rewrite.h
index 5c1d24ea890..c23edbe1f60 100644
--- a/src/vnet/adj/rewrite.h
+++ b/src/vnet/adj/rewrite.h
@@ -55,10 +55,15 @@ typedef enum vnet_rewrite_flags_t_
* This adjacency/interface has output features configured
*/
VNET_REWRITE_HAS_FEATURES = (1 << 0),
+
+ /**
+ * this adj performs IP4 over IP4 fixup
+ */
+ VNET_REWRITE_FIXUP_IP4_O_4 = (1 << 1),
} __attribute__ ((packed)) vnet_rewrite_flags_t;
-/* *INDENT-OFF* */
-typedef CLIB_PACKED (struct {
+typedef struct vnet_rewrite_header_t_
+{
/* Interface to mark re-written packets with. */
u32 sw_if_index;
@@ -83,8 +88,7 @@ typedef CLIB_PACKED (struct {
/* Rewrite string starting at end and going backwards. */
u8 data[0];
-}) vnet_rewrite_header_t;
-/* *INDENT-ON* */
+} __clib_packed vnet_rewrite_header_t;
/**
* At 16 bytes of rewrite herader we have enought space left for a IPv6
@@ -114,6 +118,13 @@ STATIC_ASSERT (sizeof (vnet_rewrite_header_t) <= 16,
sizeof (vnet_rewrite_header_t)]; \
}
+typedef struct __rewrite_unused_t__
+{
+ VNET_DECLARE_REWRITE;
+} __rewrite_unused_t;
+
+STATIC_ASSERT_SIZEOF (__rewrite_unused_t, 128);
+
always_inline void
vnet_rewrite_clear_data_internal (vnet_rewrite_header_t * rw, int max_size)
{