VOM: mroutes
[vpp.git] / src / vnet / lldp / lldp_output.c
index 8698ec9..9c171c5 100644 (file)
  */
 #include <vnet/lldp/lldp_node.h>
 
+static void
+lldp_build_mgmt_addr_tlv (u8 ** t0p, u8 subtype, u8 addr_len, u8 * addr,
+                         u32 if_index, u8 oid_len, u8 * oid)
+{
+  lldp_tlv_t *t = (lldp_tlv_t *) * t0p;
+
+  lldp_tlv_set_code (t, LLDP_TLV_NAME (mgmt_addr));
+  t->v[0] = addr_len + 1;      /* address string length */
+  t->v[1] = subtype;           /* address subtype */
+  clib_memcpy_fast (&(t->v[2]), addr, addr_len);       /* address */
+  t->v[addr_len + 2] = 2;      /* interface numbering subtype: ifIndex */
+  t->v[addr_len + 3] = (if_index >> 24) & 0xFF;        /* interface number */
+  t->v[addr_len + 4] = (if_index >> 16) & 0xFF;
+  t->v[addr_len + 5] = (if_index >> 8) & 0xFF;
+  t->v[addr_len + 6] = (if_index >> 0) & 0xFF;
+  t->v[addr_len + 7] = oid_len;        /* OID string length */
+
+  if (oid_len > 0)
+    clib_memcpy_fast ((u8 *) & (t->v[addr_len + 8]), oid, oid_len);
+
+  lldp_tlv_set_length (t, addr_len + oid_len + 8);
+  *t0p += STRUCT_SIZE_OF (lldp_tlv_t, head) + addr_len + oid_len + 8;
+}
+
 static void
 lldp_add_chassis_id (const vnet_hw_interface_t * hw, u8 ** t0p)
 {
@@ -27,7 +51,7 @@ lldp_add_chassis_id (const vnet_hw_interface_t * hw, u8 ** t0p)
   t->subtype = LLDP_CHASS_ID_SUBTYPE_NAME (mac_addr);
 
   const size_t addr_len = 6;
-  clib_memcpy (&t->id, hw->hw_address, addr_len);
+  clib_memcpy_fast (&t->id, hw->hw_address, addr_len);
   const size_t len =
     STRUCT_SIZE_OF (lldp_chassis_id_tlv_t, subtype) + addr_len;
   lldp_tlv_set_length ((lldp_tlv_t *) t, len);
@@ -43,7 +67,7 @@ lldp_add_port_id (const vnet_hw_interface_t * hw, u8 ** t0p)
   t->subtype = LLDP_PORT_ID_SUBTYPE_NAME (intf_name);
 
   const size_t name_len = vec_len (hw->name);
-  clib_memcpy (&t->id, hw->name, name_len);
+  clib_memcpy_fast (&t->id, hw->name, name_len);
   const size_t len = STRUCT_SIZE_OF (lldp_port_id_tlv_t, subtype) + name_len;
   lldp_tlv_set_length ((lldp_tlv_t *) t, len);
   *t0p += STRUCT_SIZE_OF (lldp_tlv_t, head) + len;
@@ -83,7 +107,7 @@ lldp_add_port_desc (const lldp_main_t * lm, lldp_intf_t * n, u8 ** t0p)
       lldp_tlv_t *t = (lldp_tlv_t *) * t0p;
       lldp_tlv_set_code (t, LLDP_TLV_NAME (port_desc));
       lldp_tlv_set_length (t, len);
-      clib_memcpy (t->v, n->port_desc, len);
+      clib_memcpy_fast (t->v, n->port_desc, len);
       *t0p += STRUCT_SIZE_OF (lldp_tlv_t, head) + len;
     }
 }
@@ -97,11 +121,55 @@ lldp_add_sys_name (const lldp_main_t * lm, u8 ** t0p)
       lldp_tlv_t *t = (lldp_tlv_t *) * t0p;
       lldp_tlv_set_code (t, LLDP_TLV_NAME (sys_name));
       lldp_tlv_set_length (t, len);
-      clib_memcpy (t->v, lm->sys_name, len);
+      clib_memcpy_fast (t->v, lm->sys_name, len);
       *t0p += STRUCT_SIZE_OF (lldp_tlv_t, head) + len;
     }
 }
 
+static void
+lldp_add_mgmt_addr (const lldp_intf_t * n, const vnet_hw_interface_t * hw,
+                   u8 ** t0p)
+{
+  const size_t len_ip4 = vec_len (n->mgmt_ip4);
+  const size_t len_ip6 = vec_len (n->mgmt_ip6);
+
+  if (!(len_ip4 | len_ip6))
+    {
+      /*
+         If no management address is configured, the interface port's MAC
+         address is sent in one TLV.
+       */
+
+      lldp_build_mgmt_addr_tlv (t0p, 1,        /* address subtype: Ipv4 */
+                               6,      /* address string length */
+                               hw->hw_address, /* address */
+                               hw->hw_if_index,        /* if index */
+                               vec_len (n->mgmt_oid),  /* OID length */
+                               n->mgmt_oid);   /* OID */
+      return;
+    }
+
+  if (len_ip4)
+    {
+      lldp_build_mgmt_addr_tlv (t0p, 1,        /* address subtype: Ipv4 */
+                               len_ip4,        /* address string length */
+                               n->mgmt_ip4,    /* address */
+                               hw->hw_if_index,        /* if index */
+                               vec_len (n->mgmt_oid),  /* OID length */
+                               n->mgmt_oid);   /* OID */
+    }
+
+  if (len_ip6)
+    {
+      lldp_build_mgmt_addr_tlv (t0p, 2,        /* address subtype: Ipv6 */
+                               len_ip6,        /* address string length */
+                               n->mgmt_ip6,    /* address */
+                               hw->hw_if_index,        /* if index */
+                               vec_len (n->mgmt_oid),  /* OID length */
+                               n->mgmt_oid);   /* OID */
+    }
+}
+
 static void
 lldp_add_pdu_end (u8 ** t0p)
 {
@@ -120,6 +188,7 @@ lldp_add_tlvs (lldp_main_t * lm, vnet_hw_interface_t * hw, u8 ** t0p,
   lldp_add_ttl (lm, t0p, shutdown);
   lldp_add_port_desc (lm, n, t0p);
   lldp_add_sys_name (lm, t0p);
+  lldp_add_mgmt_addr (n, hw, t0p);
   lldp_add_pdu_end (t0p);
 }
 
@@ -151,7 +220,8 @@ lldp_send_ethernet (lldp_main_t * lm, lldp_intf_t * n, int shutdown)
   /* Add the interface's ethernet source address */
   hw = vnet_get_hw_interface (vnm, n->hw_if_index);
 
-  clib_memcpy (h0->src_address, hw->hw_address, vec_len (hw->hw_address));
+  clib_memcpy_fast (h0->src_address, hw->hw_address,
+                   vec_len (hw->hw_address));
 
   u8 *data = ((u8 *) h0) + sizeof (*h0);
   t0 = data;
@@ -186,6 +256,9 @@ lldp_delete_intf (lldp_main_t * lm, lldp_intf_t * n)
       vec_free (n->chassis_id);
       vec_free (n->port_id);
       vec_free (n->port_desc);
+      vec_free (n->mgmt_ip4);
+      vec_free (n->mgmt_ip6);
+      vec_free (n->mgmt_oid);
       pool_put (lm->intfs, n);
     }
 }
@@ -199,7 +272,7 @@ lldp_template_init (vlib_main_t * vm)
   {
     ethernet_header_t h;
 
-    memset (&h, 0, sizeof (h));
+    clib_memset (&h, 0, sizeof (h));
 
     /*
      * Send to 01:80:C2:00:00:0E - propagation constrained to a single
@@ -208,8 +281,8 @@ lldp_template_init (vlib_main_t * vm)
     h.dst_address[0] = 0x01;
     h.dst_address[1] = 0x80;
     h.dst_address[2] = 0xC2;
-    /* h.dst_address[3] = 0x00; (memset) */
-    /* h.dst_address[4] = 0x00; (memset) */
+    /* h.dst_address[3] = 0x00; (clib_memset) */
+    /* h.dst_address[4] = 0x00; (clib_memset) */
     h.dst_address[5] = 0x0E;
 
     /* leave src address blank (fill in at send time) */