VPP-355: add PBB (802.1ah) tag rewrite
[vpp.git] / vnet / vnet / ethernet / format.c
index be456d5..4edef5a 100644 (file)
 #include <vlib/vlib.h>
 #include <vnet/ethernet/ethernet.h>
 
-u8 * format_ethernet_address (u8 * s, va_list * args)
+u8 *
+format_ethernet_address (u8 * s, va_list * args)
 {
-  ethernet_main_t * em = &ethernet_main;
-  u8 * a = va_arg (*args, u8 *);
+  ethernet_main_t *em = &ethernet_main;
+  u8 *a = va_arg (*args, u8 *);
 
   if (em->format_ethernet_address_16bit)
     return format (s, "%02x%02x.%02x%02x.%02x%02x",
@@ -53,11 +54,12 @@ u8 * format_ethernet_address (u8 * s, va_list * args)
                   a[0], a[1], a[2], a[3], a[4], a[5]);
 }
 
-u8 * format_ethernet_type (u8 * s, va_list * args)
+u8 *
+format_ethernet_type (u8 * s, va_list * args)
 {
   ethernet_type_t type = va_arg (*args, u32);
-  ethernet_main_t * em = &ethernet_main;
-  ethernet_type_info_t * t = ethernet_get_type_info (em, type);
+  ethernet_main_t *em = &ethernet_main;
+  ethernet_type_info_t *t = ethernet_get_type_info (em, type);
 
   if (t)
     s = format (s, "%s", t->name);
@@ -67,22 +69,72 @@ u8 * format_ethernet_type (u8 * s, va_list * args)
   return s;
 }
 
-u8 * format_ethernet_header_with_length (u8 * s, va_list * args)
+u8 *
+format_ethernet_vlan_tci (u8 * s, va_list * va)
 {
-  ethernet_max_header_t * m = va_arg (*args, ethernet_max_header_t *);
+  u32 vlan_tci = va_arg (*va, u32);
+
+  u32 vid = (vlan_tci & 0xfff);
+  u32 cfi = (vlan_tci >> 12) & 1;
+  u32 pri = (vlan_tci >> 13);
+
+  s = format (s, "%d", vid);
+  if (pri != 0)
+    s = format (s, " priority %d", pri);
+  if (cfi != 0)
+    s = format (s, " cfi");
+
+  return s;
+}
+
+u8 *
+format_ethernet_pbb (u8 * s, va_list * va)
+{
+  u32 b_tag = va_arg (*va, u32);
+  u32 i_tag = va_arg (*va, u32);
+  u32 vid = (b_tag & 0xfff);
+  u32 bdei = (b_tag >> 12) & 1;
+  u32 bpcp = (b_tag >> 13);
+  u32 sid = (i_tag & 0xffffff);
+  u8 ires = (i_tag >> 24) & 3;
+  u8 iuca = (i_tag >> 27) & 1;
+  u8 idei = (i_tag >> 28) & 1;
+  u8 ipcp = (i_tag >> 29);
+
+  s =
+    format (s, "B_tag %04X (vid %d, dei %d, pcp %d), ", b_tag, vid, bdei,
+           bpcp);
+  s =
+    format (s, "I_tag %08X (sid %d, res %d, dei %d, pcp %d)", i_tag, sid,
+           ires, iuca, idei, ipcp);
+
+  return s;
+}
+
+u8 *
+format_ethernet_header_with_length (u8 * s, va_list * args)
+{
+  ethernet_pbb_header_packed_t *ph =
+    va_arg (*args, ethernet_pbb_header_packed_t *);
+  ethernet_max_header_t *m = (ethernet_max_header_t *) ph;
   u32 max_header_bytes = va_arg (*args, u32);
-  ethernet_main_t * em = &ethernet_main;
-  ethernet_header_t * e = &m->ethernet;
-  ethernet_vlan_header_t * v;
+  ethernet_main_t *em = &ethernet_main;
+  ethernet_header_t *e = &m->ethernet;
+  ethernet_vlan_header_t *v;
   ethernet_type_t type = clib_net_to_host_u16 (e->type);
+  ethernet_type_t vlan_type[ARRAY_LEN (m->vlan)];
   u32 n_vlan = 0, i, header_bytes;
   uword indent;
 
-  while (type == ETHERNET_TYPE_VLAN
-        && n_vlan < ARRAY_LEN (m->vlan))
+  while ((type == ETHERNET_TYPE_VLAN || type == ETHERNET_TYPE_DOT1AD
+         || type == ETHERNET_TYPE_DOT1AH) && n_vlan < ARRAY_LEN (m->vlan))
     {
-      v = m->vlan + n_vlan;
-      type = clib_net_to_host_u16 (v->type);
+      vlan_type[n_vlan] = type;
+      if (type != ETHERNET_TYPE_DOT1AH)
+       {
+         v = m->vlan + n_vlan;
+         type = clib_net_to_host_u16 (v->type);
+       }
       n_vlan++;
     }
 
@@ -97,41 +149,47 @@ u8 * format_ethernet_header_with_length (u8 * s, va_list * args)
              format_ethernet_address, e->src_address,
              format_ethernet_address, e->dst_address);
 
-  for (i = 0; i < n_vlan; i++)
+  if (type != ETHERNET_TYPE_DOT1AH)
     {
-      u32 v = clib_net_to_host_u16 (m->vlan[i].priority_cfi_and_id);
-      u32 vid = (v & 0xfff);
-      u32 cfi = (v >> 12) & 1;
-      u32 pri = (v >> 13);
-
-      s = format (s, " vlan %d", vid);
-      if (pri != 0)
-       s = format (s, " priority %d", pri);
-      if (cfi != 0)
-       s = format (s, " cfi");
-    }
+      for (i = 0; i < n_vlan; i++)
+       {
+         u32 v = clib_net_to_host_u16 (m->vlan[i].priority_cfi_and_id);
+         if (*vlan_type == ETHERNET_TYPE_VLAN)
+           s = format (s, " 802.1q vlan %U", format_ethernet_vlan_tci, v);
+         else
+           s = format (s, " 802.1ad vlan %U", format_ethernet_vlan_tci, v);
+       }
 
-  if (max_header_bytes != 0 && header_bytes < max_header_bytes)
+      if (max_header_bytes != 0 && header_bytes < max_header_bytes)
+       {
+         ethernet_type_info_t *ti;
+         vlib_node_t *node = 0;
+
+         ti = ethernet_get_type_info (em, type);
+         if (ti && ti->node_index != ~0)
+           node = vlib_get_node (em->vlib_main, ti->node_index);
+         if (node && node->format_buffer)
+           s = format (s, "\n%U%U",
+                       format_white_space, indent,
+                       node->format_buffer, (void *) m + header_bytes,
+                       max_header_bytes - header_bytes);
+       }
+    }
+  else
     {
-      ethernet_type_info_t * ti;
-      vlib_node_t * node = 0;
-
-      ti = ethernet_get_type_info (em, type);
-      if (ti && ti->node_index != ~0)
-          node = vlib_get_node (em->vlib_main, ti->node_index);
-      if (node && node->format_buffer)
-       s = format (s, "\n%U%U",
-                   format_white_space, indent,
-                   node->format_buffer, (void *) m + header_bytes,
-                   max_header_bytes - header_bytes);
+      s = format (s, "\n%UPBB header : %U", format_white_space, indent,
+                 format_ethernet_pbb,
+                 clib_net_to_host_u16 (ph->priority_dei_id),
+                 clib_net_to_host_u32 (ph->priority_dei_uca_res_sid));
     }
 
   return s;
 }
 
-u8 * format_ethernet_header (u8 * s, va_list * args)
+u8 *
+format_ethernet_header (u8 * s, va_list * args)
 {
-  ethernet_max_header_t * m = va_arg (*args, ethernet_max_header_t *);
+  ethernet_max_header_t *m = va_arg (*args, ethernet_max_header_t *);
   return format (s, "%U", format_ethernet_header_with_length, m, 0);
 }
 
@@ -139,11 +197,11 @@ u8 * format_ethernet_header (u8 * s, va_list * args)
 static uword
 unformat_ethernet_address_unix (unformat_input_t * input, va_list * args)
 {
-  u8 * result = va_arg (*args, u8 *);
+  u8 *result = va_arg (*args, u8 *);
   u32 i, a[6];
 
-  if (! unformat (input, "%_%x:%x:%x:%x:%x:%x%_",
-                 &a[0], &a[1], &a[2], &a[3], &a[4], &a[5]))
+  if (!unformat (input, "%_%x:%x:%x:%x:%x:%x%_",
+                &a[0], &a[1], &a[2], &a[3], &a[4], &a[5]))
     return 0;
 
   /* Check range. */
@@ -161,10 +219,10 @@ unformat_ethernet_address_unix (unformat_input_t * input, va_list * args)
 static uword
 unformat_ethernet_address_cisco (unformat_input_t * input, va_list * args)
 {
-  u8 * result = va_arg (*args, u8 *);
+  u8 *result = va_arg (*args, u8 *);
   u32 i, a[3];
 
-  if (! unformat (input, "%_%x.%x.%x%_", &a[0], &a[1], &a[2]))
+  if (!unformat (input, "%_%x.%x.%x%_", &a[0], &a[1], &a[2]))
     return 0;
 
   /* Check range. */
@@ -186,7 +244,7 @@ unformat_ethernet_address_cisco (unformat_input_t * input, va_list * args)
 uword
 unformat_ethernet_address (unformat_input_t * input, va_list * args)
 {
-  u8 * result = va_arg (*args, u8 *);
+  u8 *result = va_arg (*args, u8 *);
   return (unformat_user (input, unformat_ethernet_address_unix, result)
          || unformat_user (input, unformat_ethernet_address_cisco, result));
 }
@@ -196,13 +254,12 @@ uword
 unformat_ethernet_type_host_byte_order (unformat_input_t * input,
                                        va_list * args)
 {
-  u16 * result = va_arg (*args, u16 *);
-  ethernet_main_t * em = &ethernet_main;
+  u16 *result = va_arg (*args, u16 *);
+  ethernet_main_t *em = &ethernet_main;
   int type, i;
 
   /* Numeric type. */
-  if (unformat (input, "0x%x", &type)
-      || unformat (input, "%d", &type))
+  if (unformat (input, "0x%x", &type) || unformat (input, "%d", &type))
     {
       if (type >= (1 << 16))
        return 0;
@@ -214,7 +271,7 @@ unformat_ethernet_type_host_byte_order (unformat_input_t * input,
   if (unformat_user (input, unformat_vlib_number_by_name,
                     em->type_info_by_name, &i))
     {
-      ethernet_type_info_t * ti = vec_elt_at_index (em->type_infos, i);
+      ethernet_type_info_t *ti = vec_elt_at_index (em->type_infos, i);
       *result = ti->type;
       return 1;
     }
@@ -226,27 +283,27 @@ uword
 unformat_ethernet_type_net_byte_order (unformat_input_t * input,
                                       va_list * args)
 {
-  u16 * result = va_arg (*args, u16 *);
-  if (! unformat_user (input, unformat_ethernet_type_host_byte_order, result))
+  u16 *result = va_arg (*args, u16 *);
+  if (!unformat_user (input, unformat_ethernet_type_host_byte_order, result))
     return 0;
 
-  *result = clib_host_to_net_u16 ((u16) *result);
+  *result = clib_host_to_net_u16 ((u16) * result);
   return 1;
 }
 
 uword
 unformat_ethernet_header (unformat_input_t * input, va_list * args)
 {
-  u8 ** result = va_arg (*args, u8 **);
-  ethernet_max_header_t _m, * m = &_m;
-  ethernet_header_t * e = &m->ethernet;
+  u8 **result = va_arg (*args, u8 **);
+  ethernet_max_header_t _m, *m = &_m;
+  ethernet_header_t *e = &m->ethernet;
   u16 type;
   u32 n_vlan;
 
-  if (! unformat (input, "%U: %U -> %U",
-                 unformat_ethernet_type_host_byte_order, &type,
-                 unformat_ethernet_address, &e->src_address,
-                 unformat_ethernet_address, &e->dst_address))
+  if (!unformat (input, "%U: %U -> %U",
+                unformat_ethernet_type_host_byte_order, &type,
+                unformat_ethernet_address, &e->src_address,
+                unformat_ethernet_address, &e->dst_address))
     return 0;
 
   n_vlan = 0;
@@ -254,7 +311,7 @@ unformat_ethernet_header (unformat_input_t * input, va_list * args)
     {
       u32 id, priority;
 
-      if (! unformat_user (input, unformat_vlib_number, &id)
+      if (!unformat_user (input, unformat_vlib_number, &id)
          || id >= ETHERNET_N_VLAN)
        return 0;
 
@@ -290,12 +347,20 @@ unformat_ethernet_header (unformat_input_t * input, va_list * args)
 
   /* Add header to result. */
   {
-    void * p;
+    void *p;
     u32 n_bytes = sizeof (e[0]) + n_vlan * sizeof (m->vlan[0]);
 
     vec_add2 (*result, p, n_bytes);
-    memcpy (p, m, n_bytes);
+    clib_memcpy (p, m, n_bytes);
   }
-  
+
   return 1;
 }
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */