aboutsummaryrefslogtreecommitdiffstats
path: root/src/vnet/lldp
diff options
context:
space:
mode:
authorSteve Shin <jonshin@cisco.com>2017-10-11 13:55:16 -0700
committerJohn Lo <loj@cisco.com>2017-10-12 13:57:11 +0000
commit9a6fcef43c3263d6acb95aaca2dcd2eb86169a75 (patch)
tree3ca1f20feb1194c2b6af8be2eae70585afe4b57a /src/vnet/lldp
parent34acce2574311bcc149660729bde5fccf1045915 (diff)
LLDP: Add Management Address TLV
- Management Address TLV is added as per IEEE Std 802.1AB-2009. - Support of management ipv4/ipv6 addresses and OID. Change-Id: I57c14741774390809ce5a829cc087947424432c7 Signed-off-by: Steve Shin <jonshin@cisco.com>
Diffstat (limited to 'src/vnet/lldp')
-rw-r--r--src/vnet/lldp/lldp.api6
-rw-r--r--src/vnet/lldp/lldp.h4
-rw-r--r--src/vnet/lldp/lldp_api.c39
-rw-r--r--src/vnet/lldp/lldp_cli.c103
-rw-r--r--src/vnet/lldp/lldp_node.h8
-rw-r--r--src/vnet/lldp/lldp_output.c72
6 files changed, 207 insertions, 25 deletions
diff --git a/src/vnet/lldp/lldp.api b/src/vnet/lldp/lldp.api
index 8117ed41b9c..acc5f71a25d 100644
--- a/src/vnet/lldp/lldp.api
+++ b/src/vnet/lldp/lldp.api
@@ -37,6 +37,9 @@ autoreply define lldp_config
@param context - sender context, to match reply w/ request
@param sw_if_index - interface for which to enable/disable LLDP
@param port_desc - local port description
+ @param mgmt_ip4_addr - management ip4 address of the interface
+ @param mgmt_ip6_addr - management ip6 address of the interface
+ @param mgmt_oid - OID(Object Identifier) of the interface
@param enable - if non-zero enable, else disable
*/
autoreply define sw_interface_set_lldp
@@ -45,5 +48,8 @@ autoreply define sw_interface_set_lldp
u32 context;
u32 sw_if_index;
u8 port_desc[256];
+ u8 mgmt_ip4[4];
+ u8 mgmt_ip6[16];
+ u8 mgmt_oid[128];
u8 enable;
};
diff --git a/src/vnet/lldp/lldp.h b/src/vnet/lldp/lldp.h
index 473c2021abe..df03dcea6ce 100644
--- a/src/vnet/lldp/lldp.h
+++ b/src/vnet/lldp/lldp.h
@@ -26,7 +26,9 @@ typedef enum lldp_cfg_err
lldp_invalid_arg,
} lldp_cfg_err_t;
-lldp_cfg_err_t lldp_cfg_intf_set (u32 hw_if_index, u8 ** port_desc, int enable);
+lldp_cfg_err_t lldp_cfg_intf_set (u32 hw_if_index, u8 ** port_desc,
+ u8 **mgmt_ip4, u8 **mgmt_ip6, u8 **mgmt_oid, int enable);
lldp_cfg_err_t lldp_cfg_set (u8 ** host, int hold_time, int tx_interval);
+
#endif /* __included_lldp_h__ */
diff --git a/src/vnet/lldp/lldp_api.c b/src/vnet/lldp/lldp_api.c
index bdada8970a4..16904c1db89 100644
--- a/src/vnet/lldp/lldp_api.c
+++ b/src/vnet/lldp/lldp_api.c
@@ -56,8 +56,8 @@ vl_api_lldp_config_t_handler (vl_api_lldp_config_t * mp)
vec_validate (sys_name, strlen ((char *) mp->system_name) - 1);
strncpy ((char *) sys_name, (char *) mp->system_name, vec_len (sys_name));
- if (lldp_cfg_set (&sys_name, ntohl (mp->tx_hold),
- ntohl (mp->tx_interval)) != lldp_ok)
+ if (lldp_cfg_set (&sys_name, ntohl (mp->tx_hold), ntohl (mp->tx_interval))
+ != lldp_ok)
{
vec_free (sys_name);
rv = VNET_API_ERROR_INVALID_VALUE;
@@ -71,17 +71,46 @@ vl_api_sw_interface_set_lldp_t_handler (vl_api_sw_interface_set_lldp_t * mp)
{
vl_api_sw_interface_set_lldp_reply_t *rmp;
int rv = 0;
- u8 *port_desc = 0;
+ u8 *port_desc = 0, *mgmt_ip4 = 0, *mgmt_ip6 = 0, *mgmt_oid = 0;
+ u8 no_data[256];
- vec_validate (port_desc, strlen ((char *) mp->port_desc) - 1);
- strncpy ((char *) port_desc, (char *) mp->port_desc, vec_len (port_desc));
+ memset (no_data, 0, 256);
+
+ if (memcmp (mp->port_desc, no_data, strlen ((char *) mp->port_desc)) != 0)
+ {
+ vec_validate (port_desc, strlen ((char *) mp->port_desc) - 1);
+ strncpy ((char *) port_desc, (char *) mp->port_desc,
+ vec_len (port_desc));
+ }
+
+ if (memcmp (mp->mgmt_ip4, no_data, sizeof (mp->mgmt_ip4)) != 0)
+ {
+ vec_validate (mgmt_ip4, sizeof (mp->mgmt_ip4) - 1);
+ clib_memcpy (mgmt_ip4, mp->mgmt_ip4, vec_len (mgmt_ip4));
+ }
+
+ if (memcmp (mp->mgmt_ip6, no_data, sizeof (mp->mgmt_ip6)) != 0)
+ {
+ vec_validate (mgmt_ip6, sizeof (mp->mgmt_ip6) - 1);
+ clib_memcpy (mgmt_ip6, mp->mgmt_ip6, vec_len (mgmt_ip6));
+ }
+
+ if (memcmp (mp->mgmt_oid, no_data, strlen ((char *) mp->mgmt_oid)) != 0)
+ {
+ vec_validate (mgmt_oid, strlen ((char *) mp->mgmt_oid) - 1);
+ strncpy ((char *) mgmt_oid, (char *) mp->mgmt_oid, vec_len (mgmt_oid));
+ }
VALIDATE_SW_IF_INDEX (mp);
if (lldp_cfg_intf_set (ntohl (mp->sw_if_index), &port_desc,
+ &mgmt_ip4, &mgmt_ip6, &mgmt_oid,
mp->enable) != lldp_ok)
{
vec_free (port_desc);
+ vec_free (mgmt_ip4);
+ vec_free (mgmt_ip6);
+ vec_free (mgmt_oid);
rv = VNET_API_ERROR_INVALID_VALUE;
}
diff --git a/src/vnet/lldp/lldp_cli.c b/src/vnet/lldp/lldp_cli.c
index 1933ca8c9e9..ddedd137bed 100644
--- a/src/vnet/lldp/lldp_cli.c
+++ b/src/vnet/lldp/lldp_cli.c
@@ -43,7 +43,8 @@ lldp_cfg_err_to_clib_err (lldp_cfg_err_t e)
}
lldp_cfg_err_t
-lldp_cfg_intf_set (u32 hw_if_index, u8 ** port_desc, int enable)
+lldp_cfg_intf_set (u32 hw_if_index, u8 ** port_desc, u8 ** mgmt_ip4,
+ u8 ** mgmt_ip6, u8 ** mgmt_oid, int enable)
{
lldp_main_t *lm = &lldp_main;
vnet_main_t *vnm = lm->vnet_main;
@@ -72,6 +73,24 @@ lldp_cfg_intf_set (u32 hw_if_index, u8 ** port_desc, int enable)
*port_desc = NULL;
}
+ if (mgmt_ip4 && *mgmt_ip4)
+ {
+ n->mgmt_ip4 = *mgmt_ip4;
+ *mgmt_ip4 = NULL;
+ }
+
+ if (mgmt_ip6 && *mgmt_ip6)
+ {
+ n->mgmt_ip6 = *mgmt_ip6;
+ *mgmt_ip6 = NULL;
+ }
+
+ if (mgmt_oid && *mgmt_oid)
+ {
+ n->mgmt_oid = *mgmt_oid;
+ *mgmt_ip6 = NULL;
+ }
+
const vnet_sw_interface_t *sw =
vnet_get_sw_interface (lm->vnet_main, hi->sw_if_index);
if (sw->flags & (VNET_SW_INTERFACE_FLAG_ADMIN_UP |
@@ -98,6 +117,9 @@ lldp_intf_cmd (vlib_main_t * vm, unformat_input_t * input,
u32 sw_if_index = (u32) ~ 0;
int enable = 1;
u8 *port_desc = NULL;
+ u8 *mgmt_ip4 = NULL, *mgmt_ip6 = NULL, *mgmt_oid = NULL;
+ ip4_address_t ip4_addr;
+ ip6_address_t ip6_addr;
while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
{
@@ -111,6 +133,20 @@ lldp_intf_cmd (vlib_main_t * vm, unformat_input_t * input,
else if (unformat (input, "port-desc %s", &port_desc))
;
else
+ if (unformat (input, "mgmt-ip4 %U", unformat_ip4_address, &ip4_addr))
+ {
+ vec_validate (mgmt_ip4, sizeof (ip4_address_t) - 1);
+ clib_memcpy (mgmt_ip4, &ip4_addr, vec_len (mgmt_ip4));
+ }
+ else
+ if (unformat (input, "mgmt-ip6 %U", unformat_ip6_address, &ip6_addr))
+ {
+ vec_validate (mgmt_ip6, sizeof (ip6_address_t) - 1);
+ clib_memcpy (mgmt_ip6, &ip6_addr, vec_len (mgmt_ip6));
+ }
+ else if (unformat (input, "mgmt-oid %s", &mgmt_oid))
+ ;
+ else
break;
}
@@ -118,7 +154,9 @@ lldp_intf_cmd (vlib_main_t * vm, unformat_input_t * input,
return clib_error_return (0, "Interface name is invalid!");
return lldp_cfg_err_to_clib_err (lldp_cfg_intf_set (sw_if_index,
- &port_desc, enable));
+ &port_desc, &mgmt_ip4,
+ &mgmt_ip6, &mgmt_oid,
+ enable));
}
lldp_cfg_err_t
@@ -126,12 +164,14 @@ lldp_cfg_set (u8 ** host, int hold_time, int tx_interval)
{
lldp_main_t *lm = &lldp_main;
int reschedule = 0;
+
if (host && *host)
{
vec_free (lm->sys_name);
lm->sys_name = *host;
*host = NULL;
}
+
if (hold_time)
{
if (hold_time < LLDP_MIN_TX_HOLD || hold_time > LLDP_MAX_TX_HOLD)
@@ -144,6 +184,7 @@ lldp_cfg_set (u8 ** host, int hold_time, int tx_interval)
reschedule = 1;
}
}
+
if (tx_interval)
{
if (tx_interval < LLDP_MIN_TX_INTERVAL ||
@@ -157,11 +198,13 @@ lldp_cfg_set (u8 ** host, int hold_time, int tx_interval)
lm->msg_tx_interval = tx_interval;
}
}
+
if (reschedule)
{
vlib_process_signal_event (lm->vlib_main, lm->lldp_process_node_index,
LLDP_EVENT_RESCHEDULE, 0);
}
+
return lldp_ok;
}
@@ -220,7 +263,8 @@ out:
VLIB_CLI_COMMAND(set_interface_lldp_cmd, static) = {
.path = "set interface lldp",
.short_help = "set interface lldp <interface> | sw_if_index <idx>"
- " [port-desc <string>] [disable]",
+ " [port-desc <string>] [mgmt-ip4 <string>]"
+ " [mgmt-ip6 <string>] [mgmt-oid <string>] [disable]",
.function = lldp_intf_cmd,
};
@@ -491,6 +535,7 @@ format_lldp_intfs_detail (u8 * s, vlib_main_t * vm, const lldp_main_t * lm)
s = format (s, "Configured system name: %U\n", format_ascii_bytes,
lm->sys_name, vec_len (lm->sys_name));
}
+
s = format (s, "Configured tx-hold: %d\n", (int) lm->msg_tx_hold);
s = format (s, "Configured tx-interval: %d\n", (int) lm->msg_tx_interval);
s = format (s, "\nLLDP-enabled interface table:\n");
@@ -501,23 +546,44 @@ format_lldp_intfs_detail (u8 * s, vlib_main_t * vm, const lldp_main_t * lm)
n, lm->intfs, ({
hw = vnet_get_hw_interface(vnm, n->hw_if_index);
sw = vnet_get_sw_interface(lm->vnet_main, hw->sw_if_index);
+
+ s = format(s, "\nLocal Interface name: %s\n"
+ "Local Port Description: %s\n",
+ hw->name, n->port_desc);
+ if (n->mgmt_ip4)
+ {
+ s = format (s, "Local Management address: %U\n",
+ format_ip4_address, n->mgmt_ip4, vec_len (n->mgmt_ip4));
+ }
+
+ if (n->mgmt_ip6)
+ {
+ s = format (s, "Local Management address IPV6: %U\n",
+ format_ip6_address, n->mgmt_ip6, vec_len (n->mgmt_ip6));
+ }
+
+ if (n->mgmt_oid)
+ {
+ s = format (s, "Local Management address OID: %U\n",
+ format_ascii_bytes, n->mgmt_oid, vec_len (n->mgmt_oid));
+ }
+
/* Interface shutdown */
if (!(sw->flags & (VNET_SW_INTERFACE_FLAG_ADMIN_UP |
VNET_SW_INTERFACE_FLAG_BOND_SLAVE)))
{
- s = format(s, "\nInterface name: %s\nInterface/peer state: "
- "interface down\nLast packet sent: %U\n",
- hw->name, format_time_ago, n->last_sent, now);
+ s = format(s, "Interface/peer state: interface down\n"
+ "Last packet sent: %U\n",
+ format_time_ago, n->last_sent, now);
}
else if (now < n->last_heard + n->ttl)
{
s = format(s,
- "\nInterface name: %s\nPort Desc: %s\nInterface/peer "
- "state: active\nPeer chassis ID: %U\nRemote port ID:"
- " %U\nLast packet sent: %U\nLast packet received: %U\n",
- hw->name, n->port_desc, format_lldp_chassis_id,
- n->chassis_id_subtype, n->chassis_id,
- vec_len(n->chassis_id), 1,
+ "Interface/peer state: active\n"
+ "Peer chassis ID: %U\nRemote port ID: %U\n"
+ "Last packet sent: %U\nLast packet received: %U\n",
+ format_lldp_chassis_id, n->chassis_id_subtype,
+ n->chassis_id, vec_len(n->chassis_id), 1,
format_lldp_port_id, n->port_id_subtype, n->port_id,
vec_len(n->port_id), 1, format_time_ago, n->last_sent,
now, format_time_ago, n->last_heard, now);
@@ -525,13 +591,12 @@ format_lldp_intfs_detail (u8 * s, vlib_main_t * vm, const lldp_main_t * lm)
else
{
s = format(s,
- "\nInterface name: %s\nPort Desc: %s\nInterface/peer "
- "state: inactive(timeout)\nLast known peer chassis ID:"
- "%U\nLast known peer port ID: %U\nLast packet sent: "
- "%U\nLast packet received: %U\n",
- hw->name, n->port_desc, format_lldp_chassis_id,
- n->chassis_id_subtype, n->chassis_id,
- vec_len(n->chassis_id), 1,
+ "Interface/peer state: inactive(timeout)\n"
+ "Last known peer chassis ID: %U\n"
+ "Last known peer port ID: %U\nLast packet sent: %U\n"
+ "Last packet received: %U\n",
+ format_lldp_chassis_id, n->chassis_id_subtype,
+ n->chassis_id, vec_len(n->chassis_id), 1,
format_lldp_port_id, n->port_id_subtype, n->port_id,
vec_len(n->port_id), 1, format_time_ago, n->last_sent,
now, format_time_ago, n->last_heard, now);
diff --git a/src/vnet/lldp/lldp_node.h b/src/vnet/lldp/lldp_node.h
index 14a10e330de..eca1d12e169 100644
--- a/src/vnet/lldp/lldp_node.h
+++ b/src/vnet/lldp/lldp_node.h
@@ -46,6 +46,14 @@ typedef struct lldp_intf
/* Local info */
u8 *port_desc;
+ /* management ipv4 address */
+ u8 *mgmt_ip4;
+
+ /* management ipv6 address */
+ u8 *mgmt_ip6;
+
+ /* management object identifier */
+ u8 *mgmt_oid;
} lldp_intf_t;
typedef struct
diff --git a/src/vnet/lldp/lldp_output.c b/src/vnet/lldp/lldp_output.c
index 8698ec976ac..3714e8ff77e 100644
--- a/src/vnet/lldp/lldp_output.c
+++ b/src/vnet/lldp/lldp_output.c
@@ -19,6 +19,30 @@
#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 (&(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 ((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)
{
lldp_chassis_id_tlv_t *t = (lldp_chassis_id_tlv_t *) * t0p;
@@ -103,6 +127,50 @@ lldp_add_sys_name (const lldp_main_t * lm, u8 ** t0p)
}
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
+ addressis sent in one TLV.
+ */
+
+ lldp_build_mgmt_addr_tlv (t0p, 1, /* address subtype: Ipv4 */
+ 6, /* address string lenth */
+ 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 lenth */
+ 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 lenth */
+ 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)
{
lldp_tlv_t *t = (lldp_tlv_t *) * 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);
}
@@ -186,6 +255,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);
}
}