ILA: Add direction option to disable ila2sir or sir2ila 28/2028/1
authorPierre Pfister <ppfister@cisco.com>
Wed, 20 Jul 2016 07:39:38 +0000 (08:39 +0100)
committerPierre Pfister <ppfister@cisco.com>
Wed, 20 Jul 2016 07:39:38 +0000 (08:39 +0100)
In a ILA router use case as described by the draft, it is proposed
to disable ILA to SIR translation and do SIR to ILA only.

Change-Id: I8d0980bb75c8d925c1d1aa4563030919dd220620
Signed-off-by: Pierre Pfister <ppfister@cisco.com>
plugins/ila-plugin/ila/ila.c
plugins/ila-plugin/ila/ila.h

index 88ea58e..69fbb82 100644 (file)
@@ -49,9 +49,10 @@ typedef struct {
   u32 adj_index;
 } ila_ila2sir_trace_t;
 
-static ila_entry_t ila_default_entry = {
+static ila_entry_t ila_sir2ila_default_entry = {
   .csum_mode = ILA_CSUM_MODE_NO_ACTION,
   .type = ILA_TYPE_IID,
+  .dir = ILA_DIR_ILA2SIR, //Will pass the packet with no
 };
 
 u8 *
@@ -64,6 +65,18 @@ format_half_ip6_address (u8 * s, va_list * va)
 
 }
 
+u8 *
+format_ila_direction (u8 * s, va_list * args)
+{
+  ila_direction_t t = va_arg (*args, ila_direction_t);
+#define _(i,n,st) \
+  if (t == ILA_DIR_##i) \
+    return format(s, st);
+  ila_foreach_direction
+#undef _
+    return format (s, "invalid_ila_direction");
+}
+
 static u8 *
 format_csum_mode (u8 * s, va_list * va)
 {
@@ -79,7 +92,7 @@ format_csum_mode (u8 * s, va_list * va)
       ila_csum_foreach_type
 #undef _
     default:
-      txt = "(unknown)";
+      txt = "invalid_ila_csum_mode";
       break;
     }
   return format (s, txt);
@@ -94,7 +107,7 @@ format_ila_type (u8 * s, va_list * args)
     return format(s, st);
   ila_foreach_type
 #undef _
-    return format (s, "invalid type");
+    return format (s, "invalid_ila_type");
 }
 
 static u8 *
@@ -105,27 +118,29 @@ format_ila_entry (u8 * s, va_list * va)
 
   if (!e)
     {
-      return format (s, "%-15s%=40s%=40s%+16s%+18s", "Type", "SIR Address",
-                    "ILA Address", "Adjacency Index", "Checksum Mode");
+      return format (s, "%-15s%=40s%=40s%+16s%+18s%+11s", "Type", "SIR Address",
+                    "ILA Address", "Adjacency Index", "Checksum Mode", "Direction");
 
     }
   else if (vnm)
     {
       if (e->ila_adj_index == ~0)
        {
-         return format (s, "%-15U%=40U%=40U%16s%18U",
+         return format (s, "%-15U%=40U%=40U%16s%18U%11U",
                         format_ila_type, e->type,
                         format_ip6_address, &e->sir_address,
                         format_ip6_address, &e->ila_address,
-                        "n/a", format_csum_mode, e->csum_mode);
+                        "n/a", format_csum_mode, e->csum_mode,
+                        format_ila_direction, e->dir);
        }
       else
        {
-         return format (s, "%-15U%=40U%=40U%16d%18U",
+         return format (s, "%-15U%=40U%=40U%16d%18U%11U",
                         format_ila_type, e->type,
                         format_ip6_address, &e->sir_address,
                         format_ip6_address, &e->ila_address,
-                        e->ila_adj_index, format_csum_mode, e->csum_mode);
+                        e->ila_adj_index, format_csum_mode, e->csum_mode,
+                        format_ila_direction, e->dir);
        }
     }
 
@@ -144,6 +159,22 @@ format_ila_ila2sir_trace (u8 * s, va_list * args)
                 &t->initial_dst);
 }
 
+static uword
+unformat_ila_direction (unformat_input_t * input, va_list * args)
+{
+  ila_direction_t *result = va_arg (*args, ila_direction_t *);
+#define _(i,n,s) \
+  if (unformat(input, s)) \
+      { \
+        *result = ILA_DIR_##i; \
+        return 1;\
+      }
+
+  ila_foreach_direction
+#undef _
+    return 0;
+}
+
 static uword
 unformat_ila_type (unformat_input_t * input, va_list * args)
 {
@@ -228,6 +259,7 @@ ila_ila2sir (vlib_main_t * vm,
          ila_entry_t *ie0, *ie1;
          ip6_header_t *ip60, *ip61;
          ila_adj_data_t *ad0, *ad1;
+         ip6_address_t *sir_address0, *sir_address1;
 
          {
            vlib_buffer_t *p2, *p3;
@@ -252,6 +284,8 @@ ila_ila2sir (vlib_main_t * vm,
          p1 = vlib_get_buffer (vm, pi1);
          ip60 = vlib_buffer_get_current (p0);
          ip61 = vlib_buffer_get_current (p1);
+         sir_address0 = &ip60->dst_address;
+         sir_address1 = &ip61->dst_address;
          adj0 =
            ip_get_adjacency (lm, vnet_buffer (p0)->ip.adj_index[VLIB_TX]);
          adj1 =
@@ -279,10 +313,12 @@ ila_ila2sir (vlib_main_t * vm,
              tr->adj_index = vnet_buffer (p1)->ip.adj_index[VLIB_TX];
            }
 
-         ip60->dst_address.as_u64[0] = ie0->sir_address.as_u64[0];
-         ip60->dst_address.as_u64[1] = ie0->sir_address.as_u64[1];
-         ip61->dst_address.as_u64[0] = ie1->sir_address.as_u64[0];
-         ip61->dst_address.as_u64[1] = ie1->sir_address.as_u64[1];
+         sir_address0 = (ie0->dir != ILA_DIR_SIR2ILA) ? &ie0->sir_address : sir_address0;
+         sir_address1 = (ie1->dir != ILA_DIR_SIR2ILA) ? &ie1->sir_address : sir_address1;
+         ip60->dst_address.as_u64[0] = sir_address0->as_u64[0];
+         ip60->dst_address.as_u64[1] = sir_address0->as_u64[1];
+         ip61->dst_address.as_u64[0] = sir_address1->as_u64[0];
+         ip61->dst_address.as_u64[1] = sir_address1->as_u64[1];
 
          vnet_buffer (p0)->ip.adj_index[VLIB_TX] = ie0->ila_adj_index;
          vnet_buffer (p1)->ip.adj_index[VLIB_TX] = ie1->ila_adj_index;
@@ -302,6 +338,7 @@ ila_ila2sir (vlib_main_t * vm,
          ila_adj_data_t *ad0;
          ila_entry_t *ie0;
          ip6_header_t *ip60;
+         ip6_address_t *sir_address0;
 
          pi0 = to_next[0] = from[0];
          from += 1;
@@ -311,6 +348,7 @@ ila_ila2sir (vlib_main_t * vm,
 
          p0 = vlib_get_buffer (vm, pi0);
          ip60 = vlib_buffer_get_current (p0);
+         sir_address0 = &ip60->dst_address;
          adj0 =
            ip_get_adjacency (lm, vnet_buffer (p0)->ip.adj_index[VLIB_TX]);
          ad0 = (ila_adj_data_t *) & adj0->opaque;
@@ -325,8 +363,9 @@ ila_ila2sir (vlib_main_t * vm,
              tr->adj_index = vnet_buffer (p0)->ip.adj_index[VLIB_TX];
            }
 
-         ip60->dst_address.as_u64[0] = ie0->sir_address.as_u64[0];
-         ip60->dst_address.as_u64[1] = ie0->sir_address.as_u64[1];
+         sir_address0 = (ie0->dir != ILA_DIR_SIR2ILA) ? &ie0->sir_address : sir_address0;
+         ip60->dst_address.as_u64[0] = sir_address0->as_u64[0];
+         ip60->dst_address.as_u64[1] = sir_address0->as_u64[1];
          vnet_buffer (p0)->ip.adj_index[VLIB_TX] = ie0->ila_adj_index;
 
          vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
@@ -402,8 +441,9 @@ ila_sir2ila (vlib_main_t * vm,
          u32 next1 = ILA_SIR2ILA_NEXT_DROP;
          BVT (clib_bihash_kv) kv0, value0;
          BVT (clib_bihash_kv) kv1, value1;
-         ila_entry_t *ie0 = &ila_default_entry;
-         ila_entry_t *ie1 = &ila_default_entry;
+         ila_entry_t *ie0 = &ila_sir2ila_default_entry;
+         ila_entry_t *ie1 = &ila_sir2ila_default_entry;
+         ip6_address_t *ila_address0, *ila_address1;
 
          {
            vlib_buffer_t *p2, *p3;
@@ -428,6 +468,8 @@ ila_sir2ila (vlib_main_t * vm,
          p1 = vlib_get_buffer (vm, pi1);
          ip60 = vlib_buffer_get_current (p0);
          ip61 = vlib_buffer_get_current (p1);
+         ila_address0 = &ip60->dst_address;
+         ila_address1 = &ip61->dst_address;
          kv0.key[0] = ip60->dst_address.as_u64[0];
          kv0.key[1] = ip60->dst_address.as_u64[1];
          kv0.key[2] = 0;
@@ -435,20 +477,24 @@ ila_sir2ila (vlib_main_t * vm,
          kv1.key[1] = ip61->dst_address.as_u64[1];
          kv1.key[2] = 0;
 
-         if ((BV (clib_bihash_search)
-              (&ilm->id_to_entry_table, &kv0, &value0)) == 0)
-           ie0 = &ilm->entries[value0.value];
+         if (PREDICT_TRUE((BV (clib_bihash_search)
+             (&ilm->id_to_entry_table, &kv0, &value0)) == 0)) {
+             ie0 = &ilm->entries[value0.value];
+             ila_address0 = (ie0->dir != ILA_DIR_ILA2SIR) ? &ie0->ila_address : ila_address0;
+         }
 
          if ((BV (clib_bihash_search)
-              (&ilm->id_to_entry_table, &kv1, &value1)) == 0)
+              (&ilm->id_to_entry_table, &kv1, &value1)) == 0) {
            ie1 = &ilm->entries[value1.value];
+           ila_address1 = (ie1->dir != ILA_DIR_ILA2SIR) ? &ie1->ila_address : ila_address1;
+         }
 
          if (PREDICT_FALSE (p0->flags & VLIB_BUFFER_IS_TRACED))
            {
              ila_sir2ila_trace_t *tr =
                vlib_add_trace (vm, node, p0, sizeof (*tr));
              tr->ila_index =
-               (ie0 != &ila_default_entry) ? (ie0 - ilm->entries) : ~0;
+               (ie0 != &ila_sir2ila_default_entry) ? (ie0 - ilm->entries) : ~0;
              tr->initial_dst = ip60->dst_address;
            }
 
@@ -457,14 +503,14 @@ ila_sir2ila (vlib_main_t * vm,
              ila_sir2ila_trace_t *tr =
                vlib_add_trace (vm, node, p1, sizeof (*tr));
              tr->ila_index =
-               (ie1 != &ila_default_entry) ? (ie1 - ilm->entries) : ~0;
+               (ie1 != &ila_sir2ila_default_entry) ? (ie1 - ilm->entries) : ~0;
              tr->initial_dst = ip61->dst_address;
            }
 
-         ip60->dst_address.as_u64[0] = ie0->ila_address.as_u64[0];
-         ip60->dst_address.as_u64[1] = ie0->ila_address.as_u64[1];
-         ip61->dst_address.as_u64[0] = ie1->ila_address.as_u64[0];
-         ip61->dst_address.as_u64[1] = ie1->ila_address.as_u64[1];
+         ip60->dst_address.as_u64[0] = ila_address0->as_u64[0];
+         ip60->dst_address.as_u64[1] = ila_address0->as_u64[1];
+         ip61->dst_address.as_u64[0] = ila_address1->as_u64[0];
+         ip61->dst_address.as_u64[1] = ila_address1->as_u64[1];
 
          vnet_get_config_data (&cm->config_main,
                                &p0->current_config_index, &next0, 0);
@@ -485,7 +531,8 @@ ila_sir2ila (vlib_main_t * vm,
          ip6_header_t *ip60;
          u32 next0 = ILA_SIR2ILA_NEXT_DROP;
          BVT (clib_bihash_kv) kv0, value0;
-         ila_entry_t *ie0 = &ila_default_entry;
+         ila_entry_t *ie0 = &ila_sir2ila_default_entry;
+         ip6_address_t *ila_address0;
 
          pi0 = to_next[0] = from[0];
          from += 1;
@@ -495,26 +542,30 @@ ila_sir2ila (vlib_main_t * vm,
 
          p0 = vlib_get_buffer (vm, pi0);
          ip60 = vlib_buffer_get_current (p0);
+         ila_address0 = &ip60->dst_address;
+
          kv0.key[0] = ip60->dst_address.as_u64[0];
          kv0.key[1] = ip60->dst_address.as_u64[1];
          kv0.key[2] = 0;
 
-         if ((BV (clib_bihash_search)
-              (&ilm->id_to_entry_table, &kv0, &value0)) == 0)
+         if (PREDICT_TRUE((BV (clib_bihash_search)
+              (&ilm->id_to_entry_table, &kv0, &value0)) == 0)) {
            ie0 = &ilm->entries[value0.value];
+           ila_address0 = (ie0->dir != ILA_DIR_ILA2SIR) ? &ie0->ila_address : ila_address0;
+         }
 
          if (PREDICT_FALSE (p0->flags & VLIB_BUFFER_IS_TRACED))
            {
              ila_sir2ila_trace_t *tr =
                vlib_add_trace (vm, node, p0, sizeof (*tr));
              tr->ila_index =
-               (ie0 != &ila_default_entry) ? (ie0 - ilm->entries) : ~0;
+               (ie0 != &ila_sir2ila_default_entry) ? (ie0 - ilm->entries) : ~0;
              tr->initial_dst = ip60->dst_address;
            }
 
          //This operation should do everything for any type (except vnid4 obviously)
-         ip60->dst_address.as_u64[0] = ie0->ila_address.as_u64[0];
-         ip60->dst_address.as_u64[1] = ie0->ila_address.as_u64[1];
+         ip60->dst_address.as_u64[0] = ila_address0->as_u64[0];
+         ip60->dst_address.as_u64[1] = ila_address0->as_u64[1];
 
          vnet_get_config_data (&cm->config_main,
                                &p0->current_config_index, &next0, 0);
@@ -591,6 +642,7 @@ ila_add_del_entry (ila_add_del_entry_args_t * args)
       e->sir_address = args->sir_address;
       e->ila_adj_index = args->local_adj_index;
       e->csum_mode = args->csum_mode;
+      e->dir = args->dir;
 
       //Construct ILA address
       switch (e->type)
@@ -782,6 +834,7 @@ ila_entry_command_fn (vlib_main_t * vm,
   args.type = ILA_TYPE_IID;
   args.csum_mode = ILA_CSUM_MODE_NO_ACTION;
   args.local_adj_index = ~0;
+  args.dir = ILA_DIR_BIDIR;
 
   if (!unformat_user (input, unformat_line_input, line_input))
     return 0;
@@ -813,6 +866,9 @@ ila_entry_command_fn (vlib_main_t * vm,
        if (unformat
            (line_input, "next-hop %U", unformat_ip6_address, &next_hop))
        next_hop_set = 1;
+      else if (unformat
+             (line_input, "direction %U", unformat_ila_direction, &args.dir))
+           ;
       else if (unformat (line_input, "del"))
        args.is_del = 1;
       else
@@ -853,7 +909,7 @@ VLIB_CLI_COMMAND (ila_entry_command, static) =
 {
   .path = "ila entry",
   .short_help = "ila entry [type <type>] [sir-address <address>] [locator <locator>] [vnid <hex-vnid>]"
-    " [adj-index <adj-index>] [next-hop <next-hop>]"
+    " [adj-index <adj-index>] [next-hop <next-hop>] [direction (bidir|sir2ila|ila2sir)]"
     " [csum-mode (no-action|neutral-map|transport-adjust)] [del]",
   .function = ila_entry_command_fn,
 };
index c2650c1..b800fdd 100644 (file)
@@ -47,12 +47,24 @@ typedef enum {
   ILA_CSUM_N_TYPES
 } ila_csum_mode_t;
 
+#define ila_foreach_direction \
+_(BIDIR, 0, "bidir") \
+_(SIR2ILA, 1, "sir2ila") \
+_(ILA2SIR, 2, "ila2sir")
+
+typedef enum {
+#define _(i,n,s) ILA_DIR_##i = n,
+  ila_foreach_direction
+#undef _
+} ila_direction_t;
+
 typedef struct {
   ila_type_t type;
   ip6_address_t sir_address;
   ip6_address_t ila_address;
   u32 ila_adj_index;
   ila_csum_mode_t csum_mode;
+  ila_direction_t dir;
 } ila_entry_t;
 
 typedef struct {
@@ -79,6 +91,7 @@ typedef struct {
   u32 vnid;
   u32 local_adj_index;
   ila_csum_mode_t csum_mode;
+  ila_direction_t dir;
   u8 is_del;
 } ila_add_del_entry_args_t;