Add NSH TTL support 82/8582/2 v18.01-rc0
authorHongjun Ni <[email protected]>
Thu, 28 Sep 2017 17:03:31 +0000 (01:03 +0800)
committerHongjun Ni <[email protected]>
Fri, 29 Sep 2017 15:11:36 +0000 (23:11 +0800)
Change-Id: Id2f8236cc997d08c53217fc92881b8bbf2c2f429
Signed-off-by: Hongjun Ni <[email protected]>
nsh-plugin/nsh/nsh.api
nsh-plugin/nsh/nsh.c
nsh-plugin/nsh/nsh.h
nsh-plugin/nsh/nsh_packet.h

index 1ef3c7b..6beed00 100644 (file)
@@ -7,6 +7,7 @@
     @param nsp_nsi - Key for nsh_header_t entry to map to. : 24bit NSP 8bit NSI 
     @param md_type - metadata type [1|2] - only MDType1 supported today
     @param ver_o_c - version, O-bit and C-bit (see nsh_packet.h)
+    @param ttl - indicates the maximum SFF hops for an SFP
     @param length - header length in n x 32bits, should be 6 for MDtype1
     @param next_protocol - next protocol encapsulated behind NSH header: 1=Ethernet, 2=IP4, 3=IP6
     @param c1 - 32bit Metadata type1 field (context1)
@@ -22,6 +23,7 @@ define nsh_add_del_entry {
     u32 nsp_nsi;
     u8 md_type;
     u8 ver_o_c;
+    u8 ttl;
     u8 length;
     u8 next_protocol;
     u32 c1;
@@ -55,6 +57,7 @@ define nsh_entry_details {
     u32 nsp_nsi;
     u8 md_type;
     u8 ver_o_c;
+    u8 ttl;
     u8 length;
     u8 next_protocol;
     u32 c1;
index 8e4ce58..0bbccc0 100644 (file)
@@ -250,7 +250,8 @@ u8 * format_nsh_header (u8 * s, va_list * args)
   nsh_md2_data_t * nsh_md2 = (nsh_md2_data_t *)(nsh_base + 1);
   opt0 = (nsh_md2_data_t *)nsh_md2;
   limit0 = (nsh_md2_data_t *) ((u8 *) nsh_md2 +
-                              (nsh_base->length*4-sizeof(nsh_base_header_t)) );
+                              ((nsh_base->length & NSH_LEN_MASK)*4
+                               -sizeof(nsh_base_header_t)) );
 
   s = format (s, "nsh ver %d ", (nsh_base->ver_o_c>>6));
   if (nsh_base->ver_o_c & NSH_O_BIT)
@@ -259,8 +260,12 @@ u8 * format_nsh_header (u8 * s, va_list * args)
   if (nsh_base->ver_o_c & NSH_C_BIT)
     s = format (s, "C-set ");
 
+  s = format (s, "ttl %d ", (nsh_base->ver_o_c & NSH_TTL_H4_MASK)<<2 |
+              (nsh_base->length & NSH_TTL_L2_MASK)>>6);
+
   s = format (s, "len %d (%d bytes) md_type %d next_protocol %d\n",
-             nsh_base->length, nsh_base->length * 4,
+             (nsh_base->length & NSH_LEN_MASK),
+             (nsh_base->length & NSH_LEN_MASK) * 4,
              nsh_base->md_type, nsh_base->next_protocol);
 
   s = format (s, "  service path %d service index %d\n",
@@ -905,6 +910,7 @@ int nsh_header_rewrite(nsh_entry_t *nsh_entry)
 
   nsh_base = (nsh_base_header_t *) rw;
   nsh_base->ver_o_c = nsh_entry->nsh_base.ver_o_c;
+  nsh_base->length= nsh_entry->nsh_base.length;
   nsh_base->md_type = nsh_entry->nsh_base.md_type;
   nsh_base->next_protocol = nsh_entry->nsh_base.next_protocol;
   nsh_base->nsp_nsi = clib_host_to_net_u32(nsh_entry->nsh_base.nsp_nsi);
@@ -963,7 +969,8 @@ next_tlv_md2:
     }
 
   nsh_entry->rewrite = rw;
-  nsh_base->length = nsh_entry->rewrite_size >> 2;
+  nsh_base->length = (nsh_base->length & NSH_TTL_L2_MASK) |
+                     ((nsh_entry->rewrite_size >> 2) & NSH_LEN_MASK);
 
   return 0;
 }
@@ -1067,6 +1074,7 @@ nsh_add_del_entry_command_fn (vlib_main_t * vm,
   unformat_input_t _line_input, * line_input = &_line_input;
   u8 is_add = 1;
   u8 ver_o_c = 0;
+  u8 ttl = 63;
   u8 length = 0;
   u8 md_type = 0;
   u8 next_protocol = 1; /* default: ip4 */
@@ -1105,6 +1113,8 @@ nsh_add_del_entry_command_fn (vlib_main_t * vm,
       ver_o_c |= (tmp & 1) << 5;
     else if (unformat (line_input, "c-bit %d", &tmp))
       ver_o_c |= (tmp & 1) << 4;
+    else if (unformat (line_input, "ttl %d", &ttl))
+      ver_o_c |= (ttl & NSH_LEN_MASK) >> 2;
     else if (unformat (line_input, "md-type %d", &tmp))
       md_type = tmp;
     else if (unformat(line_input, "next-ip4"))
@@ -1197,6 +1207,7 @@ nsh_add_del_entry_command_fn (vlib_main_t * vm,
       a->nsh_entry.tlvs_len = cur_len;
       length += (cur_len >> 2);
     }
+  length = (length & NSH_LEN_MASK) | ((ttl & 0x3) << 6);
 
 #define _(x) a->nsh_entry.nsh_base.x = x;
   foreach_copy_nsh_base_hdr_field;
@@ -1219,7 +1230,7 @@ nsh_add_del_entry_command_fn (vlib_main_t * vm,
 VLIB_CLI_COMMAND (create_nsh_entry_command, static) = {
   .path = "create nsh entry",
   .short_help =
-  "create nsh entry {nsp <nn> nsi <nn>} [md-type <nn>]"
+  "create nsh entry {nsp <nn> nsi <nn>} [ttl <nn>] [md-type <nn>]"
   "  [c1 <nn> c2 <nn> c3 <nn> c4 <nn>] [tlv-ioam-trace] [del]\n",
   .function = nsh_add_del_entry_command_fn,
 };
@@ -1237,8 +1248,8 @@ static void vl_api_nsh_add_del_entry_t_handler
   u8 * data = 0;
 
   a->is_add = mp->is_add;
-  a->nsh_entry.nsh_base.ver_o_c = mp->ver_o_c;
-  a->nsh_entry.nsh_base.length = mp->length;
+  a->nsh_entry.nsh_base.ver_o_c = (mp->ver_o_c & 0xF0)|((mp->ttl & NSH_LEN_MASK)>>2);
+  a->nsh_entry.nsh_base.length = (mp->length & NSH_LEN_MASK) | ((mp->ttl & 0x3) << 6);
   a->nsh_entry.nsh_base.md_type = mp->md_type;
   a->nsh_entry.nsh_base.next_protocol = mp->next_protocol;
   a->nsh_entry.nsh_base.nsp_nsi = ntohl(mp->nsp_nsi);
@@ -1278,7 +1289,9 @@ static void send_nsh_entry_details
 
     rmp->_vl_msg_id = ntohs((VL_API_NSH_ENTRY_DETAILS)+nm->msg_id_base);
     rmp->ver_o_c = t->nsh_base.ver_o_c;
-    rmp->length = t->nsh_base.length;
+    rmp->ttl = (t->nsh_base.ver_o_c & NSH_TTL_H4_MASK)<<2 |
+               (t->nsh_base.length & NSH_TTL_L2_MASK)>>6;
+    rmp->length = t->nsh_base.length & NSH_LEN_MASK;
     rmp->md_type = t->nsh_base.md_type;
     rmp->next_protocol = t->nsh_base.next_protocol;
     rmp->nsp_nsi = htonl(t->nsh_base.nsp_nsi);
@@ -1506,8 +1519,8 @@ next_tlv_md2:
 
   /* update nsh header's length */
   nsh_base = (nsh_base_header_t *)nsh_entry->rewrite;
-  nsh_base->length = (nsh_entry->rewrite_size >> 2);
-
+  nsh_base->length = (nsh_base->length & NSH_TTL_L2_MASK) |
+                     ((nsh_entry->rewrite_size >> 2) & NSH_LEN_MASK);
   return;
 }
 
@@ -1574,7 +1587,8 @@ next_tlv_md2:
 
   /* update nsh header's length */
   nsh_base = (nsh_base_header_t *)nsh_entry->rewrite;
-  nsh_base->length = (nsh_entry->rewrite_size >> 2);
+  nsh_base->length = (nsh_base->length & NSH_TTL_L2_MASK) |
+                     ((nsh_entry->rewrite_size >> 2) & NSH_LEN_MASK);
   return;
 }
 
@@ -1652,6 +1666,7 @@ nsh_input_map (vlib_main_t * vm,
          nsh_base_header_t * hdr0 = 0, *hdr1 = 0;
          u32 header_len0 = 0, header_len1 = 0;
          u32 nsp_nsi0, nsp_nsi1;
+         u32 ttl0, ttl1;
          u32 error0, error1;
          nsh_map_t * map0 = 0, *map1 = 0;
          nsh_entry_t * nsh_entry0 = 0, *nsh_entry1 = 0;
@@ -1695,7 +1710,15 @@ nsh_input_map (vlib_main_t * vm,
           if(node_type == NSH_INPUT_TYPE)
             {
               nsp_nsi0 = hdr0->nsp_nsi;
-              header_len0 = hdr0->length * 4;
+              header_len0 = (hdr0->length & NSH_LEN_MASK) * 4;
+              ttl0 = (hdr0->ver_o_c & NSH_TTL_H4_MASK)<<2 |
+                     (hdr0->length & NSH_TTL_L2_MASK)>>6;
+              ttl0 = ttl0 - 1;
+                     if (PREDICT_FALSE(ttl0 == 0))
+                       {
+                         error0 = NSH_NODE_ERROR_INVALID_TTL;
+                         goto trace0;
+                       }
             }
           else if(node_type == NSH_CLASSIFIER_TYPE)
             {
@@ -1742,7 +1765,15 @@ nsh_input_map (vlib_main_t * vm,
           if(node_type == NSH_INPUT_TYPE)
            {
              nsp_nsi1 = hdr1->nsp_nsi;
-             header_len1 = hdr1->length * 4;
+             header_len1 = (hdr1->length & NSH_LEN_MASK) * 4;
+              ttl1 = (hdr1->ver_o_c & NSH_TTL_H4_MASK)<<2 |
+                     (hdr1->length & NSH_TTL_L2_MASK)>>6;
+              ttl1 = ttl1 - 1;
+                     if (PREDICT_FALSE(ttl1 == 0))
+                       {
+                         error1 = NSH_NODE_ERROR_INVALID_TTL;
+                         goto trace1;
+                       }
            }
           else if(node_type == NSH_CLASSIFIER_TYPE)
             {
@@ -1886,7 +1917,7 @@ nsh_input_map (vlib_main_t * vm,
           if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
             {
               nsh_input_trace_t *tr = vlib_add_trace(vm, node, b0, sizeof(*tr));
-              clib_memcpy ( &(tr->trace_data), hdr0, (hdr0->length*4) );
+              clib_memcpy ( &(tr->trace_data), hdr0, ((hdr0->length & NSH_LEN_MASK)*4) );
             }
 
          /* Process packet 1 */
@@ -1990,7 +2021,7 @@ nsh_input_map (vlib_main_t * vm,
          if (PREDICT_FALSE(b1->flags & VLIB_BUFFER_IS_TRACED))
            {
              nsh_input_trace_t *tr = vlib_add_trace(vm, node, b1, sizeof(*tr));
-             clib_memcpy ( &(tr->trace_data), hdr1, (hdr1->length*4) );
+             clib_memcpy ( &(tr->trace_data), hdr1, ((hdr1->length & NSH_LEN_MASK)*4) );
            }
 
          vlib_validate_buffer_enqueue_x2(vm, node, next_index, to_next,
@@ -2007,6 +2038,7 @@ nsh_input_map (vlib_main_t * vm,
          nsh_base_header_t * hdr0 = 0;
          u32 header_len0 = 0;
          u32 nsp_nsi0;
+         u32 ttl0;
          u32 error0;
          nsh_map_t * map0 = 0;
          nsh_entry_t * nsh_entry0 = 0;
@@ -2032,7 +2064,15 @@ nsh_input_map (vlib_main_t * vm,
           if(node_type == NSH_INPUT_TYPE)
             {
               nsp_nsi0 = hdr0->nsp_nsi;
-              header_len0 = hdr0->length * 4;
+              header_len0 = (hdr0->length & NSH_LEN_MASK) * 4;
+              ttl0 = (hdr0->ver_o_c & NSH_TTL_H4_MASK)<<2 |
+                     (hdr0->length & NSH_TTL_L2_MASK)>>6;
+              ttl0 = ttl0 - 1;
+                     if (PREDICT_FALSE(ttl0 == 0))
+                       {
+                         error0 = NSH_NODE_ERROR_INVALID_TTL;
+                         goto trace00;
+                       }
             }
           else if(node_type == NSH_CLASSIFIER_TYPE)
             {
@@ -2177,7 +2217,7 @@ nsh_input_map (vlib_main_t * vm,
          if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
            {
              nsh_input_trace_t *tr = vlib_add_trace(vm, node, b0, sizeof(*tr));
-             clib_memcpy ( &(tr->trace_data[0]), hdr0, (hdr0->length*4) );
+             clib_memcpy ( &(tr->trace_data[0]), hdr0, ((hdr0->length & NSH_LEN_MASK)*4) );
            }
 
          vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next,
index 8605fc7..d763f87 100644 (file)
@@ -186,6 +186,7 @@ _(NO_ENTRY, "no entry for nsh key") \
 _(NO_PROXY, "no proxy for transport key") \
 _(INVALID_NEXT_PROTOCOL, "invalid next protocol") \
 _(INVALID_OPTIONS, "invalid md2 options") \
+_(INVALID_TTL, "ttl equals zero") \
 
 typedef enum {
 #define _(sym,str) NSH_NODE_ERROR_##sym,
index 101652a..9d6237a 100644 (file)
@@ -22,7 +22,7 @@
  *  0                   1                   2                   3
  *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *  |Ver|O|C|R|R|R|R|R|R|   Length  |    MD Type    | Next Protocol |
+ *  |Ver|O|C|    TTL    |   Length  |    MD Type    | Next Protocol |
  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  * 
  * 
@@ -69,8 +69,8 @@
  */
 
 typedef CLIB_PACKED(struct {
-  u8 ver_o_c;
-  u8 length;
+  u8 ver_o_c; //TTL: high 4 bit
+  u8 length;  //TTL: low 2 bit
   u8 md_type;
   u8 next_protocol;
   u32 nsp_nsi; // nsp 24 bits, nsi 8 bits
@@ -104,6 +104,10 @@ typedef CLIB_PACKED(struct {
 #define NSH_O_BIT (1<<5)
 #define NSH_C_BIT (1<<4)
 
+#define NSH_TTL_H4_MASK 0xF
+#define NSH_TTL_L2_MASK 0xC0
+#define NSH_LEN_MASK 0x3F
+
 /* Network byte order shift / mask */
 #define NSH_NSI_MASK 0xFF
 #define NSH_NSP_MASK (0x00FFFFFF)