Cache a 'has-features' flag on the adjacency for faster access. Reclaim the node_inde... 61/5761/4
authorNeale Ranns <nranns@wasa-ucs-11.cisco.com>
Wed, 15 Mar 2017 16:34:25 +0000 (12:34 -0400)
committerDamjan Marion <dmarion.lists@gmail.com>
Fri, 17 Mar 2017 11:35:39 +0000 (11:35 +0000)
before:
  ip4-rewrite * * * *  2.66e1  256.00
after:
  ip4-rewrite * * * *  2.40e1  256.00

Change-Id: Ic397150727cad38811564777419ad6bd26b8a3a6
Signed-off-by: Neale Ranns <nranns@wasa-ucs-11.cisco.com>
12 files changed:
src/vnet/adj/adj.c
src/vnet/adj/adj.h
src/vnet/adj/adj_mcast.c
src/vnet/adj/adj_midchain.c
src/vnet/adj/adj_nbr.c
src/vnet/feature/feature.c
src/vnet/ip/ip4_forward.c
src/vnet/ip/ip6_forward.c
src/vnet/ip/lookup.c
src/vnet/mpls/mpls_output.c
src/vnet/rewrite.c
src/vnet/rewrite.h

index 4ed4999..f3d483a 100644 (file)
@@ -135,16 +135,6 @@ format_ip_adjacency (u8 * s, va_list * args)
         vlib_get_combined_counter(&adjacency_counters, adj_index, &counts);
         s = format (s, "\n counts:[%Ld:%Ld]", counts.packets, counts.bytes);
        s = format (s, "\n locks:%d", adj->ia_node.fn_locks);
-       s = format (s, " node:[%d]:%U",
-                   adj->rewrite_header.node_index,
-                   format_vlib_node_name, vlib_get_main(),
-                   adj->rewrite_header.node_index);
-       s = format (s, " next:[%d]:%U",
-                   adj->rewrite_header.next_index,
-                   format_vlib_next_node_name,
-                   vlib_get_main(),
-                   adj->rewrite_header.node_index,
-                   adj->rewrite_header.next_index);
        s = format(s, "\n children:\n  ");
        s = fib_node_children_format(adj->ia_node.fn_children, s);
     }
@@ -271,6 +261,78 @@ adj_child_remove (adj_index_t adj_index,
                           sibling_index);
 }
 
+/*
+ * Context for the walk to update the cached feture flags.
+ */
+typedef struct adj_feature_update_t_
+{
+    u8 arc;
+    u8 enable;
+} adj_feature_update_ctx_t;
+
+static adj_walk_rc_t
+adj_feature_update_walk_cb (adj_index_t ai,
+                            void *arg)
+{
+    adj_feature_update_ctx_t *ctx = arg;
+    ip_adjacency_t *adj;
+
+    adj = adj_get(ai);
+
+    /*
+     * this ugly mess matches the feature arc that is changing with affected
+     * adjacencies
+     */
+    if (((ctx->arc == ip6_main.lookup_main.output_feature_arc_index) &&
+         (VNET_LINK_IP6 == adj->ia_link)) ||
+        ((ctx->arc == ip4_main.lookup_main.output_feature_arc_index) &&
+         (VNET_LINK_IP4 == adj->ia_link)) ||
+        ((ctx->arc == mpls_main.output_feature_arc_index) &&
+         (VNET_LINK_MPLS == adj->ia_link)))
+    {
+        if (ctx->enable)
+            adj->rewrite_header.flags |= VNET_REWRITE_HAS_FEATURES;
+        else
+            adj->rewrite_header.flags &= ~VNET_REWRITE_HAS_FEATURES;
+    }
+    return (ADJ_WALK_RC_CONTINUE);
+}
+
+void
+adj_feature_update (u32 sw_if_index,
+                    u8 arc_index,
+                    u8 is_enable)
+{
+    /*
+     * Walk all the adjacencies on the interface to update the cached
+     * 'has-features' flag
+     */
+    adj_feature_update_ctx_t ctx = {
+        .arc = arc_index,
+        .enable = is_enable,
+    };
+    adj_walk (sw_if_index, adj_feature_update_walk_cb, &ctx);
+}
+
+/**
+ * @brief Walk the Adjacencies on a given interface
+ */
+void
+adj_walk (u32 sw_if_index,
+          adj_walk_cb_t cb,
+          void *ctx)
+{
+    /*
+     * walk all the neighbor adjacencies
+     */
+    fib_protocol_t proto;
+
+    FOR_EACH_FIB_IP_PROTOCOL(proto)
+    {
+        adj_nbr_walk(sw_if_index, proto, cb, ctx);
+    }
+}
+
 /**
  * @brief Return the link type of the adjacency
  */
index fcc5890..271fdbc 100644 (file)
@@ -96,6 +96,12 @@ extern u32 adj_get_sw_if_index (adj_index_t ai);
  */
 extern const u8* adj_get_rewrite (adj_index_t ai);
 
+/**
+ * @brief Notify the adjacency subsystem that the features settings for
+ * an interface have changed
+ */
+extern void adj_feature_update (u32 sw_if_index, u8 arc_index, u8 is_enable);
+
 /**
  * @brief
  * The global adjacnecy pool. Exposed for fast/inline data-plane access
index 1345aed..a3ba4d6 100644 (file)
@@ -256,15 +256,13 @@ format_adj_mcast (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();
     ip_adjacency_t * adj = adj_get(index);
 
     s = format(s, "%U-mcast: ",
                format_fib_protocol, adj->ia_nh_proto);
     s = format (s, "%U",
                format_vnet_rewrite,
-               vnm->vlib_main, &adj->rewrite_header,
-                sizeof (adj->rewrite_data), 0);
+                &adj->rewrite_header, sizeof (adj->rewrite_data), 0);
 
     return (s);
 }
index 7d31565..55b5e44 100644 (file)
@@ -501,7 +501,6 @@ format_adj_midchain (u8* s, va_list *ap)
 {
     index_t index = va_arg(*ap, index_t);
     u32 indent = va_arg(*ap, u32);
-    vnet_main_t * vnm = vnet_get_main();
     ip_adjacency_t * adj = adj_get(index);
 
     s = format (s, "%U", format_vnet_link, adj->ia_link);
@@ -509,8 +508,7 @@ format_adj_midchain (u8* s, va_list *ap)
                format_ip46_address, &adj->sub_type.nbr.next_hop);
     s = format (s, " %U",
                format_vnet_rewrite,
-               vnm->vlib_main, &adj->rewrite_header,
-               sizeof (adj->rewrite_data), indent);
+               &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,
index 9e8073d..9ef3651 100644 (file)
@@ -433,7 +433,6 @@ adj_nbr_update_rewrite_internal (ip_adjacency_t *adj,
        vnet_rewrite_clear_data_internal(&adj->rewrite_header,
                                         sizeof(adj->rewrite_data));
     }
-    adj->rewrite_header.node_index = this_node;
     adj->rewrite_header.next_index = vlib_node_add_next(vlib_get_main(),
                                                         this_node,
                                                         next_node);
@@ -971,7 +970,6 @@ format_adj_nbr (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();
     ip_adjacency_t * adj = adj_get(index);
 
     s = format (s, "%U", format_vnet_link, adj->ia_link);
@@ -980,7 +978,7 @@ format_adj_nbr (u8* s, va_list *ap)
                adj_proto_to_46(adj->ia_nh_proto));
     s = format (s, "%U",
                format_vnet_rewrite,
-               vnm->vlib_main, &adj->rewrite_header, sizeof (adj->rewrite_data), 0);
+               &adj->rewrite_header, sizeof (adj->rewrite_data), 0);
 
     return (s);
 }
index 80ef08d..5a4be02 100644 (file)
@@ -14,6 +14,7 @@
  */
 
 #include <vnet/feature/feature.h>
+#include <vnet/adj/adj.h>
 
 vnet_feature_main_t feature_main;
 
@@ -229,6 +230,7 @@ vnet_feature_enable_disable_with_index (u8 arc_index, u32 feature_index,
   fm->sw_if_index_has_features[arc_index] =
     clib_bitmap_set (fm->sw_if_index_has_features[arc_index], sw_if_index,
                     (feature_count > 0));
+  adj_feature_update (sw_if_index, arc_index, (feature_count > 0));
 
   fm->feature_count_by_sw_if_index[arc_index][sw_if_index] = feature_count;
   return 0;
index 5472428..34bc6c5 100644 (file)
@@ -1232,7 +1232,6 @@ format_ip4_rewrite_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 *);
   ip4_forward_next_trace_t *t = va_arg (*args, ip4_forward_next_trace_t *);
-  vnet_main_t *vnm = vnet_get_main ();
   uword indent = format_get_indent (s);
 
   s = format (s, "tx_sw_if_index %d dpo-idx %d : %U flow hash: 0x%08x",
@@ -1241,7 +1240,7 @@ format_ip4_rewrite_trace (u8 * s, va_list * args)
   s = format (s, "\n%U%U",
              format_white_space, indent,
              format_ip_adjacency_packet_data,
-             vnm, t->dpo_index, t->packet_data, sizeof (t->packet_data));
+             t->dpo_index, t->packet_data, sizeof (t->packet_data));
   return s;
 }
 
@@ -2507,8 +2506,10 @@ ip4_rewrite_inline (vlib_main_t * vm,
              tx_sw_if_index0 = adj0[0].rewrite_header.sw_if_index;
              vnet_buffer (p0)->sw_if_index[VLIB_TX] = tx_sw_if_index0;
 
-             vnet_feature_arc_start (lm->output_feature_arc_index,
-                                     tx_sw_if_index0, &next0, p0);
+             if (PREDICT_FALSE
+                 (adj0[0].rewrite_header.flags & VNET_REWRITE_HAS_FEATURES))
+               vnet_feature_arc_start (lm->output_feature_arc_index,
+                                       tx_sw_if_index0, &next0, p0);
            }
          if (PREDICT_TRUE (error1 == IP4_ERROR_NONE))
            {
@@ -2519,8 +2520,10 @@ ip4_rewrite_inline (vlib_main_t * vm,
              tx_sw_if_index1 = adj1[0].rewrite_header.sw_if_index;
              vnet_buffer (p1)->sw_if_index[VLIB_TX] = tx_sw_if_index1;
 
-             vnet_feature_arc_start (lm->output_feature_arc_index,
-                                     tx_sw_if_index1, &next1, p1);
+             if (PREDICT_FALSE
+                 (adj1[0].rewrite_header.flags & VNET_REWRITE_HAS_FEATURES))
+               vnet_feature_arc_start (lm->output_feature_arc_index,
+                                       tx_sw_if_index1, &next1, p1);
            }
 
          /* Guess we are only writing on simple Ethernet header. */
@@ -2671,8 +2674,10 @@ ip4_rewrite_inline (vlib_main_t * vm,
                  adj0->sub_type.midchain.fixup_func (vm, adj0, p0);
                }
 
-             vnet_feature_arc_start (lm->output_feature_arc_index,
-                                     tx_sw_if_index0, &next0, p0);
+             if (PREDICT_FALSE
+                 (adj0[0].rewrite_header.flags & VNET_REWRITE_HAS_FEATURES))
+               vnet_feature_arc_start (lm->output_feature_arc_index,
+                                       tx_sw_if_index0, &next0, p0);
 
            }
 
index b80c757..0b8691b 100644 (file)
@@ -961,7 +961,6 @@ format_ip6_rewrite_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 *);
   ip6_forward_next_trace_t *t = va_arg (*args, ip6_forward_next_trace_t *);
-  vnet_main_t *vnm = vnet_get_main ();
   uword indent = format_get_indent (s);
 
   s = format (s, "tx_sw_if_index %d adj-idx %d : %U flow hash: 0x%08x",
@@ -970,7 +969,7 @@ format_ip6_rewrite_trace (u8 * s, va_list * args)
   s = format (s, "\n%U%U",
              format_white_space, indent,
              format_ip_adjacency_packet_data,
-             vnm, t->adj_index, t->packet_data, sizeof (t->packet_data));
+             t->adj_index, t->packet_data, sizeof (t->packet_data));
   return s;
 }
 
@@ -2054,8 +2053,10 @@ ip6_rewrite_inline (vlib_main_t * vm,
              vnet_buffer (p0)->sw_if_index[VLIB_TX] = tx_sw_if_index0;
              next0 = adj0[0].rewrite_header.next_index;
 
-             vnet_feature_arc_start (lm->output_feature_arc_index,
-                                     tx_sw_if_index0, &next0, p0);
+             if (PREDICT_FALSE
+                 (adj0[0].rewrite_header.flags & VNET_REWRITE_HAS_FEATURES))
+               vnet_feature_arc_start (lm->output_feature_arc_index,
+                                       tx_sw_if_index0, &next0, p0);
            }
          if (PREDICT_TRUE (error1 == IP6_ERROR_NONE))
            {
@@ -2066,8 +2067,10 @@ ip6_rewrite_inline (vlib_main_t * vm,
              vnet_buffer (p1)->sw_if_index[VLIB_TX] = tx_sw_if_index1;
              next1 = adj1[0].rewrite_header.next_index;
 
-             vnet_feature_arc_start (lm->output_feature_arc_index,
-                                     tx_sw_if_index1, &next1, p1);
+             if (PREDICT_FALSE
+                 (adj1[0].rewrite_header.flags & VNET_REWRITE_HAS_FEATURES))
+               vnet_feature_arc_start (lm->output_feature_arc_index,
+                                       tx_sw_if_index1, &next1, p1);
            }
 
          /* Guess we are only writing on simple Ethernet header. */
@@ -2182,8 +2185,10 @@ ip6_rewrite_inline (vlib_main_t * vm,
              vnet_buffer (p0)->sw_if_index[VLIB_TX] = tx_sw_if_index0;
              next0 = adj0[0].rewrite_header.next_index;
 
-             vnet_feature_arc_start (lm->output_feature_arc_index,
-                                     tx_sw_if_index0, &next0, p0);
+             if (PREDICT_FALSE
+                 (adj0[0].rewrite_header.flags & VNET_REWRITE_HAS_FEATURES))
+               vnet_feature_arc_start (lm->output_feature_arc_index,
+                                       tx_sw_if_index0, &next0, p0);
            }
 
          if (is_midchain)
index 9ae269c..dabfa01 100644 (file)
@@ -291,7 +291,6 @@ format_ip_lookup_next (u8 * s, va_list * args)
 u8 *
 format_ip_adjacency_packet_data (u8 * s, va_list * args)
 {
-  vnet_main_t *vnm = va_arg (*args, vnet_main_t *);
   u32 adj_index = va_arg (*args, u32);
   u8 *packet_data = va_arg (*args, u8 *);
   u32 n_packet_data_bytes = va_arg (*args, u32);
@@ -300,10 +299,9 @@ format_ip_adjacency_packet_data (u8 * s, va_list * args)
   switch (adj->lookup_next_index)
     {
     case IP_LOOKUP_NEXT_REWRITE:
-      s = format (s, "%U",
-                 format_vnet_rewrite_header,
-                 vnm->vlib_main, &adj->rewrite_header, packet_data,
-                 n_packet_data_bytes);
+    case IP_LOOKUP_NEXT_MCAST:
+      s =
+       format (s, "%U", format_hex_bytes, packet_data, n_packet_data_bytes);
       break;
 
     default:
index c06cf91..cf35400 100644 (file)
@@ -35,7 +35,6 @@ format_mpls_output_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 *);
   mpls_output_trace_t * t = va_arg (*args, mpls_output_trace_t *);
-  vnet_main_t * vnm = vnet_get_main();
   uword indent = format_get_indent (s);
 
   s = format (s, "adj-idx %d : %U flow hash: 0x%08x",
@@ -45,8 +44,7 @@ format_mpls_output_trace (u8 * s, va_list * args)
   s = format (s, "\n%U%U",
               format_white_space, indent,
               format_ip_adjacency_packet_data,
-              vnm, t->adj_index,
-              t->packet_data, sizeof (t->packet_data));
+              t->adj_index, t->packet_data, sizeof (t->packet_data));
   return s;
 }
 
@@ -59,12 +57,14 @@ mpls_output_inline (vlib_main_t * vm,
   u32 n_left_from, next_index, * from, * to_next, cpu_index;
   vlib_node_runtime_t * error_node;
   u32 n_left_to_next;
+  mpls_main_t *mm;
 
   cpu_index = os_get_cpu_number();
   error_node = vlib_node_get_runtime (vm, mpls_output_node.index);
   from = vlib_frame_vector_args (from_frame);
   n_left_from = from_frame->n_vectors;
   next_index = node->cached_next_index;
+  mm = &mpls_main;
 
   while (n_left_from > 0)
     {
@@ -154,10 +154,10 @@ mpls_output_inline (vlib_main_t * vm,
               next0 = adj0[0].rewrite_header.next_index;
               error0 = IP4_ERROR_NONE;
 
-              if (is_midchain)
-                {
-                  adj0->sub_type.midchain.fixup_func(vm, adj0, p0);
-                }
+              if (PREDICT_FALSE(adj0[0].rewrite_header.flags & VNET_REWRITE_HAS_FEATURES))
+                vnet_feature_arc_start (mm->output_feature_arc_index,
+                                        adj0[0].rewrite_header.sw_if_index,
+                                        &next0, p0);
             }
           else
             {
@@ -175,16 +175,21 @@ mpls_output_inline (vlib_main_t * vm,
               next1 = adj1[0].rewrite_header.next_index;
               error1 = IP4_ERROR_NONE;
 
-              if (is_midchain)
-                {
-                  adj1->sub_type.midchain.fixup_func(vm, adj1, p1);
-                }
+              if (PREDICT_FALSE(adj1[0].rewrite_header.flags & VNET_REWRITE_HAS_FEATURES))
+                vnet_feature_arc_start (mm->output_feature_arc_index,
+                                        adj1[0].rewrite_header.sw_if_index,
+                                        &next1, p1);
             }
           else
             {
               error1 = IP4_ERROR_MTU_EXCEEDED;
               next1 = MPLS_OUTPUT_NEXT_DROP;
             }
+          if (is_midchain)
+          {
+              adj0->sub_type.midchain.fixup_func(vm, adj0, p0);
+              adj1->sub_type.midchain.fixup_func(vm, adj1, p1);
+          }
 
           p0->error = error_node->errors[error0];
           p1->error = error_node->errors[error1];
@@ -254,17 +259,22 @@ mpls_output_inline (vlib_main_t * vm,
               next0 = adj0[0].rewrite_header.next_index;
               error0 = IP4_ERROR_NONE;
 
-             if (is_midchain)
-               {
-                 adj0->sub_type.midchain.fixup_func(vm, adj0, p0);
-               }
+              if (PREDICT_FALSE(adj0[0].rewrite_header.flags & VNET_REWRITE_HAS_FEATURES))
+                vnet_feature_arc_start (mm->output_feature_arc_index,
+                                        adj0[0].rewrite_header.sw_if_index,
+                                        &next0, p0);
             }
           else
             {
               error0 = IP4_ERROR_MTU_EXCEEDED;
               next0 = MPLS_OUTPUT_NEXT_DROP;
             }
-         p0->error = error_node->errors[error0];
+          if (is_midchain)
+          {
+              adj0->sub_type.midchain.fixup_func(vm, adj0, p0);
+          }
+
+          p0->error = error_node->errors[error0];
 
          from += 1;
          n_left_from -= 1;
index 8925ad6..c4a171c 100644 (file)
@@ -67,14 +67,10 @@ vnet_rewrite_copy_slow_path (vnet_rewrite_data_t * p0,
 u8 *
 format_vnet_rewrite (u8 * s, va_list * args)
 {
-  vlib_main_t *vm = va_arg (*args, vlib_main_t *);
   vnet_rewrite_header_t *rw = va_arg (*args, vnet_rewrite_header_t *);
   u32 max_data_bytes = va_arg (*args, u32);
   CLIB_UNUSED (uword indent) = va_arg (*args, u32);
   vnet_main_t *vnm = vnet_get_main ();
-  vlib_node_t *next;
-
-  next = vlib_get_next_node (vm, rw->node_index, rw->next_index);
 
   if (rw->sw_if_index != ~0)
     {
@@ -85,108 +81,17 @@ format_vnet_rewrite (u8 * s, va_list * args)
       else
        s = format (s, "DELETED");
     }
-  else
-    s = format (s, "%v: ", next->name);
 
   /* Format rewrite string. */
   if (rw->data_bytes > 0)
 
     s = format (s, "%U",
-               next->format_buffer ? next->format_buffer : format_hex_bytes,
+               format_hex_bytes,
                rw->data + max_data_bytes - rw->data_bytes, rw->data_bytes);
 
   return s;
 }
 
-u8 *
-format_vnet_rewrite_header (u8 * s, va_list * args)
-{
-  vlib_main_t *vm = va_arg (*args, vlib_main_t *);
-  vnet_rewrite_header_t *rw = va_arg (*args, vnet_rewrite_header_t *);
-  u8 *packet_data = va_arg (*args, u8 *);
-  u32 packet_data_bytes = va_arg (*args, u32);
-  vlib_node_t *next;
-
-  next = vlib_get_next_node (vm, rw->node_index, rw->next_index);
-
-  /* Format rewrite string. */
-  s = format (s, "%U",
-             next->format_buffer ? next->format_buffer : format_hex_bytes,
-             packet_data, packet_data_bytes);
-
-  return s;
-}
-
-uword
-unformat_vnet_rewrite (unformat_input_t * input, va_list * args)
-{
-  vlib_main_t *vm = va_arg (*args, vlib_main_t *);
-  vnet_rewrite_header_t *rw = va_arg (*args, vnet_rewrite_header_t *);
-  u32 max_data_bytes = va_arg (*args, u32);
-  vnet_main_t *vnm = vnet_get_main ();
-  vlib_node_t *next;
-  u32 next_index, sw_if_index, max_packet_bytes, error;
-  u8 *rw_data;
-
-  rw_data = 0;
-  sw_if_index = ~0;
-  max_packet_bytes = ~0;
-  error = 1;
-
-  /* Parse sw interface. */
-  if (unformat (input, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index))
-    {
-      vnet_hw_interface_t *hi;
-
-      hi = vnet_get_sup_hw_interface (vnm, sw_if_index);
-
-      next_index = hi->output_node_index;
-      max_packet_bytes = hi->max_l3_packet_bytes[VLIB_RX];
-    }
-
-  else if (unformat (input, "%U", unformat_vlib_node, vm, &next_index))
-    ;
-
-  else
-    goto done;
-
-  next = vlib_get_node (vm, next_index);
-
-  if (next->unformat_buffer
-      && unformat_user (input, next->unformat_buffer, &rw_data))
-    ;
-
-  else if (unformat_user (input, unformat_hex_string, &rw_data)
-          || unformat (input, "0x%U", unformat_hex_string, &rw_data))
-    ;
-
-  else
-    goto done;
-
-  /* Re-write does not fit. */
-  if (vec_len (rw_data) >= max_data_bytes)
-    goto done;
-
-  {
-    u32 tmp;
-
-    if (unformat (input, "mtu %d", &tmp)
-       && tmp < (1 << BITS (rw->max_l3_packet_bytes)))
-      max_packet_bytes = tmp;
-  }
-
-  error = 0;
-  rw->sw_if_index = sw_if_index;
-  rw->max_l3_packet_bytes = max_packet_bytes;
-  rw->next_index = vlib_node_add_next (vm, rw->node_index, next_index);
-  vnet_rewrite_set_data_internal (rw, max_data_bytes, rw_data,
-                                 vec_len (rw_data));
-
-done:
-  vec_free (rw_data);
-  return error == 0;
-}
-
 u32
 vnet_tx_node_index_for_sw_interface (vnet_main_t * vnm, u32 sw_if_index)
 {
@@ -200,7 +105,6 @@ vnet_rewrite_init (vnet_main_t * vnm,
                   u32 this_node, u32 next_node, vnet_rewrite_header_t * rw)
 {
   rw->sw_if_index = sw_if_index;
-  rw->node_index = this_node;
   rw->next_index = vlib_node_add_next (vnm->vlib_main, this_node, next_node);
   rw->max_l3_packet_bytes =
     vnet_sw_interface_get_mtu (vnm, sw_if_index, VLIB_TX);
@@ -249,7 +153,6 @@ vnet_rewrite_for_tunnel (vnet_main_t * vnm,
    * ipX-forward, this will be interpreted as a FIB number.
    */
   rw->sw_if_index = tx_sw_if_index;
-  rw->node_index = rewrite_node_index;
   rw->next_index = vlib_node_add_next (vnm->vlib_main, rewrite_node_index,
                                       post_rewrite_node_index);
   rw->max_l3_packet_bytes = (u16) ~ 0; /* we can't know at this point */
@@ -284,7 +187,6 @@ unserialize_vnet_rewrite (serialize_main_t * m, va_list * va)
   u8 *p;
 
   /* It is up to user to fill these in. */
-  rw->node_index = ~0;
   rw->next_index = ~0;
 
   unserialize_integer (m, &rw->sw_if_index, sizeof (rw->sw_if_index));
index ce2bce3..8435a72 100644 (file)
 /* Consider using vector types for speed? */
 typedef uword vnet_rewrite_data_t;
 
+/**
+ * Flags associated with the rewrite/adjacency
+ */
+typedef enum vnet_rewrite_flags_t_
+{
+  /**
+   * This adjacency/interface has output features configured
+   */
+  VNET_REWRITE_HAS_FEATURES = (1 << 0),
+} __attribute__ ((packed)) vnet_rewrite_flags_t;
+
 /* *INDENT-OFF* */
 typedef CLIB_PACKED (struct {
   /* Interface to mark re-written packets with. */
   u32 sw_if_index;
 
-  /* Packet processing node where rewrite happens. */
-  u32 node_index;
-
   /* Next node to feed after packet rewrite is done. */
   u16 next_index;
 
@@ -64,6 +72,11 @@ typedef CLIB_PACKED (struct {
      Used for MTU check after packet rewrite. */
   u16 max_l3_packet_bytes;
 
+  u16 unused1;
+  u8  unused2;
+
+  vnet_rewrite_flags_t flags;
+
   /* When dynamically writing a multicast destination L2 addresss
    * this is the offset within the address to start writing n
    * bytes of the IP mcast address */
@@ -79,6 +92,13 @@ typedef CLIB_PACKED (struct {
 }) vnet_rewrite_header_t;
 /* *INDENT-ON* */
 
+/**
+ * At 16 bytes of rewrite herader we have enought space left for a IPv6
+ * (40 bytes) + LISP-GPE (8 bytes) in the cache line
+ */
+STATIC_ASSERT (sizeof (vnet_rewrite_header_t) <= 16,
+              "Rewrite header too big");
+
 /*
   Helper macro for declaring rewrite string w/ given max-size.
 
@@ -317,11 +337,7 @@ u8 *vnet_build_rewrite_for_sw_interface (struct vnet_main_t *vnm,
 void vnet_update_adjacency_for_sw_interface (struct vnet_main_t *vnm,
                                             u32 sw_if_index, u32 ai);
 
-/* Parser for unformat header & rewrite string. */
-unformat_function_t unformat_vnet_rewrite;
-
 format_function_t format_vnet_rewrite;
-format_function_t format_vnet_rewrite_header;
 
 serialize_function_t serialize_vnet_rewrite, unserialize_vnet_rewrite;