From 3f9fdd98463bd926fc78a2b366875c929058e2db Mon Sep 17 00:00:00 2001 From: Neale Ranns Date: Fri, 18 Sep 2020 12:58:40 +0000 Subject: lldp: Move to plugin Type: refactor Change-Id: Ifd770ff4850e63474bf4682ad463021b03786b4b Signed-off-by: Neale Ranns --- src/plugins/lisp/lisp-cp/control_main.c | 27 ++ src/plugins/lldp/CMakeLists.txt | 32 ++ src/plugins/lldp/FEATURE.yaml | 8 + src/plugins/lldp/dir.dox | 18 + src/plugins/lldp/lldp.api | 58 +++ src/plugins/lldp/lldp.h | 34 ++ src/plugins/lldp/lldp_api.c | 159 +++++++ src/plugins/lldp/lldp_cli.c | 731 ++++++++++++++++++++++++++++++++ src/plugins/lldp/lldp_doc.md | 86 ++++ src/plugins/lldp/lldp_input.c | 302 +++++++++++++ src/plugins/lldp/lldp_node.c | 341 +++++++++++++++ src/plugins/lldp/lldp_node.h | 156 +++++++ src/plugins/lldp/lldp_output.c | 308 ++++++++++++++ src/plugins/lldp/lldp_protocol.h | 142 +++++++ src/plugins/lldp/lldp_test.c | 147 +++++++ src/vat/api_format.c | 105 ----- src/vnet/CMakeLists.txt | 18 - src/vnet/lldp/FEATURE.yaml | 8 - src/vnet/lldp/dir.dox | 18 - src/vnet/lldp/lldp.api | 58 --- src/vnet/lldp/lldp.h | 34 -- src/vnet/lldp/lldp_api.c | 179 -------- src/vnet/lldp/lldp_cli.c | 731 -------------------------------- src/vnet/lldp/lldp_doc.md | 86 ---- src/vnet/lldp/lldp_input.c | 302 ------------- src/vnet/lldp/lldp_node.c | 341 --------------- src/vnet/lldp/lldp_node.h | 156 ------- src/vnet/lldp/lldp_output.c | 308 -------------- src/vnet/lldp/lldp_protocol.h | 142 ------- src/vnet/vnet_all_api_h.h | 1 - src/vpp/api/custom_dump.c | 43 -- 31 files changed, 2549 insertions(+), 2530 deletions(-) create mode 100644 src/plugins/lisp/lisp-cp/control_main.c create mode 100644 src/plugins/lldp/CMakeLists.txt create mode 100644 src/plugins/lldp/FEATURE.yaml create mode 100644 src/plugins/lldp/dir.dox create mode 100644 src/plugins/lldp/lldp.api create mode 100644 src/plugins/lldp/lldp.h create mode 100644 src/plugins/lldp/lldp_api.c create mode 100644 src/plugins/lldp/lldp_cli.c create mode 100644 src/plugins/lldp/lldp_doc.md create mode 100644 src/plugins/lldp/lldp_input.c create mode 100644 src/plugins/lldp/lldp_node.c create mode 100644 src/plugins/lldp/lldp_node.h create mode 100644 src/plugins/lldp/lldp_output.c create mode 100644 src/plugins/lldp/lldp_protocol.h create mode 100644 src/plugins/lldp/lldp_test.c delete mode 100644 src/vnet/lldp/FEATURE.yaml delete mode 100644 src/vnet/lldp/dir.dox delete mode 100644 src/vnet/lldp/lldp.api delete mode 100644 src/vnet/lldp/lldp.h delete mode 100644 src/vnet/lldp/lldp_api.c delete mode 100644 src/vnet/lldp/lldp_cli.c delete mode 100644 src/vnet/lldp/lldp_doc.md delete mode 100644 src/vnet/lldp/lldp_input.c delete mode 100644 src/vnet/lldp/lldp_node.c delete mode 100644 src/vnet/lldp/lldp_node.h delete mode 100644 src/vnet/lldp/lldp_output.c delete mode 100644 src/vnet/lldp/lldp_protocol.h (limited to 'src') diff --git a/src/plugins/lisp/lisp-cp/control_main.c b/src/plugins/lisp/lisp-cp/control_main.c new file mode 100644 index 00000000000..0fa85deda9e --- /dev/null +++ b/src/plugins/lisp/lisp-cp/control_main.c @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +lisp_cp_main_t lisp_control_main; + + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/src/plugins/lldp/CMakeLists.txt b/src/plugins/lldp/CMakeLists.txt new file mode 100644 index 00000000000..98df0bb0199 --- /dev/null +++ b/src/plugins/lldp/CMakeLists.txt @@ -0,0 +1,32 @@ +# Copyright (c) 2020 Cisco and/or its affiliates. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +add_vpp_plugin(lldp + SOURCES + lldp_input.c + lldp_node.c + lldp_output.c + lldp_cli.c + lldp_api.c + + API_FILES + lldp.api + + INSTALL_HEADERS + lldp_protocol.h + lldp.h + + API_TEST_SOURCES + lldp_test.c +) diff --git a/src/plugins/lldp/FEATURE.yaml b/src/plugins/lldp/FEATURE.yaml new file mode 100644 index 00000000000..feda51ad4de --- /dev/null +++ b/src/plugins/lldp/FEATURE.yaml @@ -0,0 +1,8 @@ +--- +name: Link Layer Discovery Protocol +maintainer: Klement Sekera +features: + - link layer discovery protocol implementation +description: "Link Layer Discovery Protocol (LLDP) implementation" +state: production +properties: [API, CLI, STATS, MULTITHREAD] diff --git a/src/plugins/lldp/dir.dox b/src/plugins/lldp/dir.dox new file mode 100644 index 00000000000..84870f81901 --- /dev/null +++ b/src/plugins/lldp/dir.dox @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + @dir src/vnet/lldp + @brief Link Layer Discovery Protocol (LLDP) implementation +*/ diff --git a/src/plugins/lldp/lldp.api b/src/plugins/lldp/lldp.api new file mode 100644 index 00000000000..6be060b0dd1 --- /dev/null +++ b/src/plugins/lldp/lldp.api @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2017 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +option version = "2.0.0"; + +import "vnet/interface_types.api"; +import "vnet/ip/ip_types.api"; + +/** \brief configure global parameter for LLDP + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request + @param system_name - VPP system name + @param tx_hold - multiplier for tx_interval when setting time-to-live (TTL) + value in the LLDP packets + @param tx_interval - time interval, in seconds, between each LLDP frames +*/ +autoreply define lldp_config +{ + u32 client_index; + u32 context; + u32 tx_hold; + u32 tx_interval; + string system_name[]; +}; + +/** \brief Interface set LLDP request + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request + @param sw_if_index - interface for which to enable/disable LLDP + @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 + @param port_desc - local port description +*/ +autoreply define sw_interface_set_lldp +{ + u32 client_index; + u32 context; + vl_api_interface_index_t sw_if_index; + vl_api_ip4_address_t mgmt_ip4; + vl_api_ip6_address_t mgmt_ip6; + u8 mgmt_oid[128]; + bool enable [default=true]; + string port_desc[]; +}; diff --git a/src/plugins/lldp/lldp.h b/src/plugins/lldp/lldp.h new file mode 100644 index 00000000000..df03dcea6ce --- /dev/null +++ b/src/plugins/lldp/lldp.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2017 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file + * @brief LLDP external definition + */ +#ifndef __included_lldp_h__ +#define __included_lldp_h__ + +typedef enum lldp_cfg_err +{ + lldp_ok, + lldp_not_supported, + lldp_invalid_arg, +} lldp_cfg_err_t; + +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/plugins/lldp/lldp_api.c b/src/plugins/lldp/lldp_api.c new file mode 100644 index 00000000000..69eab6949c4 --- /dev/null +++ b/src/plugins/lldp/lldp_api.c @@ -0,0 +1,159 @@ +/* + *------------------------------------------------------------------ + * lldp_api.c - lldp api + * + * Copyright (c) 2017 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------ + */ + +#include +#include + +#include +#include +#include + +#include +#include +#include + +/* define message IDs */ +#include +#include +#include + +/** + * Base message ID fot the plugin + */ +static u32 lldp_base_msg_id; +#define REPLY_MSG_ID_BASE lldp_base_msg_id + +#include + +static void +vl_api_lldp_config_t_handler (vl_api_lldp_config_t * mp) +{ + vl_api_lldp_config_reply_t *rmp; + int rv = 0; + u8 *sys_name = 0; + + sys_name = vl_api_from_api_to_new_vec (mp, &mp->system_name); + + 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; + } + + REPLY_MACRO (VL_API_LLDP_CONFIG_REPLY); +} + +static void +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 *mgmt_oid = 0, *mgmt_ip4 = 0, *mgmt_ip6 = 0; + char *port_desc = 0; + u8 no_data[128] = { 0 }; + ip4_address_t ip4; + ip6_address_t ip6; + + if (vl_api_string_len (&mp->port_desc) > 0) + { + port_desc = vl_api_from_api_to_new_c_string (&mp->port_desc); + } + + ip4_address_decode (mp->mgmt_ip4, &ip4); + + if (ip4.as_u32 != 0) + { + vec_validate (mgmt_ip4, sizeof (ip4_address_t) - 1); + clib_memcpy (mgmt_ip4, &ip4, vec_len (mgmt_ip4)); + } + + ip6_address_decode (mp->mgmt_ip6, &ip6); + + if (!ip6_address_is_zero (&ip6)) + { + vec_validate (mgmt_ip6, sizeof (ip6_address_t) - 1); + clib_memcpy (mgmt_ip6, &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), (u8 **) & 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; + } + + BAD_SW_IF_INDEX_LABEL; + + REPLY_MACRO (VL_API_SW_INTERFACE_SET_LLDP_REPLY); +} + + +/* + * * lldp_api_hookup + * * Add vpe's API message handlers to the table. + * * vlib has already mapped shared memory and + * * added the client registration handlers. + * * See .../vlib-api/vlibmemory/memclnt_vlib.c:memclnt_process() + * */ +#include + +static clib_error_t * +lldp_api_hookup (vlib_main_t * vm) +{ + /* + * Set up the (msg_name, crc, message-id) table + */ + lldp_base_msg_id = setup_message_id_table (); + + return 0; +} + +VLIB_API_INIT_FUNCTION (lldp_api_hookup); + +#include +#include + +/* *INDENT-OFF* */ +VLIB_PLUGIN_REGISTER () = { + .version = VPP_BUILD_VER, + .description = "Link Layer Discovery Protocol (LLDP)", +}; +/* *INDENT-ON* */ + + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/src/plugins/lldp/lldp_cli.c b/src/plugins/lldp/lldp_cli.c new file mode 100644 index 00000000000..2a0891a2e48 --- /dev/null +++ b/src/plugins/lldp/lldp_cli.c @@ -0,0 +1,731 @@ +/* + * Copyright (c) 2011-2016 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * @brief LLDP CLI handling + * + */ +#include +#include +#include +#include + +#ifndef ETHER_ADDR_LEN +#include +#endif + +static clib_error_t * +lldp_cfg_err_to_clib_err (lldp_cfg_err_t e) +{ + + switch (e) + { + case lldp_ok: + return 0; + case lldp_not_supported: + return clib_error_return (0, "not supported"); + case lldp_invalid_arg: + return clib_error_return (0, "invalid argument"); + } + return 0; +} + +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_main_t *lm = &lldp_main; + vnet_main_t *vnm = lm->vnet_main; + ethernet_main_t *em = ðernet_main; + const vnet_hw_interface_t *hi; + const ethernet_interface_t *eif; + + if (pool_is_free_index (vnm->interface_main.hw_interfaces, hw_if_index)) + { + return lldp_invalid_arg; + } + + hi = vnet_get_hw_interface (vnm, hw_if_index); + eif = ethernet_get_interface (em, hw_if_index); + if (!eif) + { + return lldp_not_supported; + } + + if (enable) + { + lldp_intf_t *n = lldp_get_intf (lm, hw_if_index); + if (n) + { + /* already enabled */ + return lldp_ok; + } + n = lldp_create_intf (lm, hw_if_index); + + if (port_desc && *port_desc) + { + n->port_desc = *port_desc; + *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_oid = 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)) + { + lldp_schedule_intf (lm, n); + } + } + else + { + lldp_intf_t *n = lldp_get_intf (lm, hi->sw_if_index); + lldp_delete_intf (lm, n); + } + + return lldp_ok; +} + +static clib_error_t * +lldp_intf_cmd (vlib_main_t * vm, unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + lldp_main_t *lm = &lldp_main; + vnet_main_t *vnm = lm->vnet_main; + 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) + { + if (unformat (input, "sw_if_index %d", &sw_if_index)) + ; + if (unformat + (input, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index)) + ; + else if (unformat (input, "disable")) + enable = 0; + 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; + } + + if (sw_if_index == (u32) ~ 0) + 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, &mgmt_ip4, + &mgmt_ip6, &mgmt_oid, + enable)); +} + +lldp_cfg_err_t +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) + { + return lldp_invalid_arg; + } + if (lm->msg_tx_hold != hold_time) + { + lm->msg_tx_hold = hold_time; + reschedule = 1; + } + } + + if (tx_interval) + { + if (tx_interval < LLDP_MIN_TX_INTERVAL || + tx_interval > LLDP_MAX_TX_INTERVAL) + { + return lldp_invalid_arg; + } + if (lm->msg_tx_interval != tx_interval) + { + reschedule = 1; + 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; +} + +static clib_error_t * +lldp_cfg_cmd (vlib_main_t * vm, unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + int hold_time = 0; + int tx_interval = 0; + u8 *host = NULL; + clib_error_t *ret = NULL; + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "system-name %s", &host)) + { + } + else if (unformat (input, "tx-hold %d", &hold_time)) + { + if (hold_time < LLDP_MIN_TX_HOLD || hold_time > LLDP_MAX_TX_HOLD) + { + ret = + clib_error_return (0, + "invalid tx-hold `%d' (out of range <%d,%d>)", + hold_time, LLDP_MIN_TX_HOLD, + LLDP_MAX_TX_HOLD); + goto out; + } + } + else if (unformat (input, "tx-interval %d", &tx_interval)) + { + if (tx_interval < LLDP_MIN_TX_INTERVAL || + tx_interval > LLDP_MAX_TX_INTERVAL) + { + ret = + clib_error_return (0, + "invalid tx-interval `%d' (out of range <%d,%d>)", + tx_interval, LLDP_MIN_TX_INTERVAL, + LLDP_MAX_TX_INTERVAL); + goto out; + } + } + else + { + break; + } + } + ret = + lldp_cfg_err_to_clib_err (lldp_cfg_set (&host, hold_time, tx_interval)); +out: + vec_free (host); + return ret; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND(set_interface_lldp_cmd, static) = { + .path = "set interface lldp", + .short_help = "set interface lldp | sw_if_index " + " [port-desc ] [mgmt-ip4 ]" + " [mgmt-ip6 ] [mgmt-oid ] [disable]", + .function = lldp_intf_cmd, +}; + +VLIB_CLI_COMMAND(set_lldp_cmd, static) = { + .path = "set lldp", + .short_help = "set lldp [system-name ] [tx-hold ] " + "[tx-interval ]", + .function = lldp_cfg_cmd, +}; +/* *INDENT-ON* */ + +static const char * +lldp_chassis_id_subtype_str (lldp_chassis_id_subtype_t t) +{ + switch (t) + { +#define F(num, val, str) \ + case num: \ + return str; + foreach_chassis_id_subtype (F) +#undef F + } + return "unknown chassis subtype"; +} + +static const char * +lldp_port_id_subtype_str (lldp_port_id_subtype_t t) +{ + switch (t) + { +#define F(num, val, str) \ + case num: \ + return str; + foreach_port_id_subtype (F) +#undef F + } + return "unknown port subtype"; +} + +/* + * format port id subtype&value + * + * @param va - 1st argument - unsigned - port id subtype + * @param va - 2nd argument - u8* - port id + * @param va - 3rd argument - unsigned - port id length + * @param va - 4th argument - int - 1 for detailed output, 0 for simple + */ +u8 * +format_lldp_port_id (u8 * s, va_list * va) +{ + const lldp_port_id_subtype_t subtype = va_arg (*va, unsigned); + const u8 *id = va_arg (*va, u8 *); + const unsigned len = va_arg (*va, unsigned); + const int detail = va_arg (*va, int); + if (!id) + { + return s; + } + switch (subtype) + { + case LLDP_PORT_ID_SUBTYPE_NAME (intf_alias): + /* fallthrough */ + case LLDP_PORT_ID_SUBTYPE_NAME (port_comp): + /* fallthrough */ + case LLDP_PORT_ID_SUBTYPE_NAME (local): + /* fallthrough */ + case LLDP_PORT_ID_SUBTYPE_NAME (intf_name): + if (detail) + { + s = format (s, "%U(%s)", format_ascii_bytes, id, len, + lldp_port_id_subtype_str (subtype)); + } + else + { + s = format (s, "%U", format_ascii_bytes, id, len); + } + break; + case LLDP_PORT_ID_SUBTYPE_NAME (mac_addr): + if (ETHER_ADDR_LEN == len) + { + if (detail) + { + s = format (s, "%U(%s)", format_mac_address, id, + lldp_port_id_subtype_str (subtype)); + } + else + { + s = format (s, "%U", format_mac_address, id); + } + break; + } + /* fallthrough */ + case LLDP_PORT_ID_SUBTYPE_NAME (net_addr): + /* TODO */ + /* fallthrough */ + default: + if (detail) + { + s = format (s, "%U(%s)", format_hex_bytes, id, len, + lldp_port_id_subtype_str (subtype)); + } + else + { + s = format (s, "%U", format_hex_bytes, id, len); + } + break; + } + return s; +} + +/* + * format chassis id subtype&value + * + * @param s format string + * @param va - 1st argument - unsigned - chassis id subtype + * @param va - 2nd argument - u8* - chassis id + * @param va - 3rd argument - unsigned - chassis id length + * @param va - 4th argument - int - 1 for detailed output, 0 for simple + */ +u8 * +format_lldp_chassis_id (u8 * s, va_list * va) +{ + const lldp_chassis_id_subtype_t subtype = + va_arg (*va, lldp_chassis_id_subtype_t); + const u8 *id = va_arg (*va, u8 *); + const unsigned len = va_arg (*va, unsigned); + const int detail = va_arg (*va, int); + if (!id) + { + return s; + } + switch (subtype) + { + case LLDP_CHASS_ID_SUBTYPE_NAME (chassis_comp): + /* fallthrough */ + case LLDP_CHASS_ID_SUBTYPE_NAME (intf_alias): + /* fallthrough */ + case LLDP_CHASS_ID_SUBTYPE_NAME (port_comp): + /* fallthrough */ + case LLDP_PORT_ID_SUBTYPE_NAME (local): + /* fallthrough */ + case LLDP_CHASS_ID_SUBTYPE_NAME (intf_name): + if (detail) + { + s = format (s, "%U(%s)", format_ascii_bytes, id, len, + lldp_chassis_id_subtype_str (subtype)); + } + else + { + s = format (s, "%U", format_ascii_bytes, id, len); + } + break; + case LLDP_CHASS_ID_SUBTYPE_NAME (mac_addr): + if (ETHER_ADDR_LEN == len) + { + if (detail) + { + s = format (s, "%U(%s)", format_mac_address, id, + lldp_chassis_id_subtype_str (subtype)); + } + else + { + s = format (s, "%U", format_mac_address, id); + } + break; + } + /* fallthrough */ + case LLDP_CHASS_ID_SUBTYPE_NAME (net_addr): + /* TODO */ + default: + if (detail) + { + s = format (s, "%U(%s)", format_hex_bytes, id, len, + lldp_chassis_id_subtype_str (subtype)); + } + else + { + s = format (s, "%U", format_hex_bytes, id, len); + } + break; + } + return s; +} + +/* + * convert a tlv code to human-readable string + */ +static const char * +lldp_tlv_code_str (lldp_tlv_code_t t) +{ + switch (t) + { +#define F(n, t, s) \ + case n: \ + return s; + foreach_lldp_tlv_type (F) +#undef F + } + return "unknown lldp tlv"; +} + +/* + * format a single LLDP TLV + * + * @param s format string + * @param va variable list - pointer to lldp_tlv_t is expected + */ +u8 * +format_lldp_tlv (u8 * s, va_list * va) +{ + const lldp_tlv_t *tlv = va_arg (*va, lldp_tlv_t *); + if (!tlv) + { + return s; + } + u16 l = lldp_tlv_get_length (tlv); + switch (lldp_tlv_get_code (tlv)) + { + case LLDP_TLV_NAME (chassis_id): + s = format (s, "%U", format_lldp_chassis_id, + ((lldp_chassis_id_tlv_t *) tlv)->subtype, + ((lldp_chassis_id_tlv_t *) tlv)->id, + l - STRUCT_SIZE_OF (lldp_chassis_id_tlv_t, subtype), 1); + break; + case LLDP_TLV_NAME (port_id): + s = format (s, "%U", format_lldp_port_id, + ((lldp_port_id_tlv_t *) tlv)->subtype, + ((lldp_port_id_tlv_t *) tlv)->id, + l - STRUCT_SIZE_OF (lldp_port_id_tlv_t, subtype), 1); + break; + case LLDP_TLV_NAME (ttl): + s = format (s, "%d", ntohs (((lldp_ttl_tlv_t *) tlv)->ttl)); + break; + case LLDP_TLV_NAME (sys_name): + /* fallthrough */ + case LLDP_TLV_NAME (sys_desc): + s = format (s, "%U", format_ascii_bytes, tlv->v, l); + break; + default: + s = format (s, "%U", format_hex_bytes, tlv->v, l); + } + + return s; +} + +static u8 * +format_time_ago (u8 * s, va_list * va) +{ + f64 ago = va_arg (*va, double); + f64 now = va_arg (*va, double); + if (ago < 0.01) + { + return format (s, "never"); + } + return format (s, "%.1fs ago", now - ago); +} + +static u8 * +format_lldp_intfs_detail (u8 * s, vlib_main_t * vm, const lldp_main_t * lm) +{ + vnet_main_t *vnm = &vnet_main; + const lldp_intf_t *n; + const vnet_hw_interface_t *hw; + const vnet_sw_interface_t *sw; + s = format (s, "LLDP configuration:\n"); + if (lm->sys_name) + { + 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"); + f64 now = vlib_time_now (vm); + + /* *INDENT-OFF* */ + pool_foreach( + 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)) + { + 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, + "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); + } + else + { + s = format(s, + "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); + } + })); + /* *INDENT-ON* */ + return s; +} + +static u8 * +format_lldp_intfs (u8 * s, va_list * va) +{ + vlib_main_t *vm = va_arg (*va, vlib_main_t *); + const lldp_main_t *lm = va_arg (*va, lldp_main_t *); + const int detail = va_arg (*va, int); + vnet_main_t *vnm = &vnet_main; + const lldp_intf_t *n; + + if (detail) + { + return format_lldp_intfs_detail (s, vm, lm); + } + + f64 now = vlib_time_now (vm); + s = format (s, "%-25s %-25s %-25s %=15s %=15s %=10s\n", "Local interface", + "Peer chassis ID", "Remote port ID", "Last heard", "Last sent", + "Status"); + + /* *INDENT-OFF* */ + pool_foreach( + n, lm->intfs, ({ + const vnet_hw_interface_t *hw = + vnet_get_hw_interface(vnm, n->hw_if_index); + const vnet_sw_interface_t *sw = + vnet_get_sw_interface(lm->vnet_main, hw->sw_if_index); + /* Interface shutdown */ + if (!(sw->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP)) + continue; + if (now < n->last_heard + n->ttl) + { + s = format(s, "%-25s %-25U %-25U %=15U %=15U %=10s\n", hw->name, + format_lldp_chassis_id, n->chassis_id_subtype, + n->chassis_id, vec_len(n->chassis_id), 0, + format_lldp_port_id, n->port_id_subtype, n->port_id, + vec_len(n->port_id), 0, format_time_ago, n->last_heard, + now, format_time_ago, n->last_sent, now, "active"); + } + else + { + s = format(s, "%-25s %-25s %-25s %=15U %=15U %=10s\n", hw->name, + "", "", format_time_ago, n->last_heard, now, + format_time_ago, n->last_sent, now, "inactive"); + } + })); + /* *INDENT-ON* */ + return s; +} + +static clib_error_t * +show_lldp (vlib_main_t * vm, unformat_input_t * input, + CLIB_UNUSED (vlib_cli_command_t * lmd)) +{ + lldp_main_t *lm = &lldp_main; + + if (unformat (input, "detail")) + { + vlib_cli_output (vm, "%U\n", format_lldp_intfs, vm, lm, 1); + } + else + { + vlib_cli_output (vm, "%U\n", format_lldp_intfs, vm, lm, 0); + } + return 0; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND(show_lldp_command, static) = { + .path = "show lldp", + .short_help = "show lldp [detail]", + .function = show_lldp, +}; +/* *INDENT-ON* */ + +/* + * packet trace format function, very similar to + * lldp_packet_scan except that we call the per TLV format + * functions instead of the per TLV processing functions + */ +u8 * +lldp_input_format_trace (u8 * s, va_list * args) +{ + CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *); + CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); + const lldp_input_trace_t *t = va_arg (*args, lldp_input_trace_t *); + const u8 *cur; + const lldp_tlv_t *tlv; + cur = t->data; + while (((cur + lldp_tlv_get_length ((lldp_tlv_t *) cur)) < + t->data + t->len)) + { + tlv = (lldp_tlv_t *) cur; + if (cur == t->data) + { + s = format (s, "TLV #%d(%s): %U\n", lldp_tlv_get_code (tlv), + lldp_tlv_code_str (lldp_tlv_get_code (tlv)), + format_lldp_tlv, tlv); + } + else + { + s = format (s, " TLV #%d(%s): %U\n", lldp_tlv_get_code (tlv), + lldp_tlv_code_str (lldp_tlv_get_code (tlv)), + format_lldp_tlv, tlv); + } + cur += STRUCT_SIZE_OF (lldp_tlv_t, head) + lldp_tlv_get_length (tlv); + } + + return s; +} + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/src/plugins/lldp/lldp_doc.md b/src/plugins/lldp/lldp_doc.md new file mode 100644 index 00000000000..717de898c4e --- /dev/null +++ b/src/plugins/lldp/lldp_doc.md @@ -0,0 +1,86 @@ +# VPP Link Layer Discovery Protocol (LLDP) implementation {#lldp_doc} + +This is a memo intended to contain documentation of the VPP LLDP implementation +Everything that is not directly obvious should come here. + + +## LLDP +LLDP is a link layer protocol to advertise the capabilities and current status of the system. + +There are 2 nodes handling LLDP + +1.) input-node which processes incoming packets and updates the local database +2.) process-node which is responsible for sending out LLDP packets from VPP side + + +### Configuration + +LLDP has a global configuration and a per-interface enable setting. + +Global configuration is modified using the "set lldp" command + +set lldp [system-name ] [tx-hold ] [tx-interval ] + +system-name: the name of the VPP system sent to peers in the system-name TLV +tx-hold: multiplier for tx-interval when setting time-to-live (TTL) value in the LLDP packets (TTL = tx-hold * tx-interval + 1, if TTL > 65535, then TTL = 65535) +tx-interval: time interval between sending out LLDP packets + +Per interface setting is done using the "set interface lldp" command + +set interface lldp | if_index [port-desc ] [disable] + +interface: the name of the interface for which to enable/disable LLDP +if_index: sw interface index can be used if interface name is not used. +port-desc: port description +disable: LLDP feature can be enabled or disabled per interface. + +### Configuration example + +Configure system-name as "VPP" and transmit interval to 10 seconds: + +set lldp system-name VPP tx-interval 10 + +Enable LLDP on interface TenGigabitEthernet5/0/1 with port description + +set interface lldp TenGigabitEthernet5/0/1 port-desc vtf:eth0 + + +### Operational data + +The list of LLDP-enabled interfaces which are up can be shown using "show lldp" command + +Example: +DBGvpp# show lldp +Local interface Peer chassis ID Remote port ID Last heard Last sent Status +GigabitEthernet2/0/1 never 27.0s ago inactive +TenGigabitEthernet5/0/1 8c:60:4f:dd:ca:52 Eth1/3/3 20.1s ago 18.3s ago active + +All LLDP configuration data with all LLDP-enabled interfaces can be shown using "show lldp detail" command + +Example: +DBGvpp# show lldp detail +LLDP configuration: +Configured system name: vpp +Configured tx-hold: 4 +Configured tx-interval: 30 + +LLDP-enabled interface table: + +Interface name: GigabitEthernet2/0/1 +Interface/peer state: inactive(timeout) +Last known peer chassis ID: +Last known peer port ID: +Last packet sent: 12.4s ago +Last packet received: never + +Interface name: GigabitEthernet2/0/2 +Interface/peer state: interface down +Last packet sent: never + +Interface name: TenGigabitEthernet5/0/1 +Interface/peer state: active +Peer chassis ID: 8c:60:4f:dd:ca:52(MAC address) +Remote port ID: Eth1/3/3(Locally assigned) +Last packet sent: 3.6s ago +Last packet received: 5.5s ago + diff --git a/src/plugins/lldp/lldp_input.c b/src/plugins/lldp/lldp_input.c new file mode 100644 index 00000000000..327ef10f9de --- /dev/null +++ b/src/plugins/lldp/lldp_input.c @@ -0,0 +1,302 @@ +/* + * Copyright (c) 2011-2016 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file + * @brief LLDP packet parsing implementation + */ +#include +#include +#include + +typedef struct +{ + u32 hw_if_index; + u8 chassis_id_len; + u8 chassis_id_subtype; + u8 portid_len; + u8 portid_subtype; + u16 ttl; + u8 data[0]; /* this contains both chassis id (chassis_id_len bytes) and port + id (portid_len bytes) */ +} lldp_intf_update_t; + +static void +lldp_rpc_update_peer_cb (const lldp_intf_update_t * a) +{ + ASSERT (vlib_get_thread_index () == 0); + + lldp_intf_t *n = lldp_get_intf (&lldp_main, a->hw_if_index); + if (!n) + { + /* LLDP turned off for this interface, ignore the update */ + return; + } + const u8 *chassis_id = a->data; + const u8 *portid = a->data + a->chassis_id_len; + + if (n->chassis_id) + { + _vec_len (n->chassis_id) = 0; + } + vec_add (n->chassis_id, chassis_id, a->chassis_id_len); + n->chassis_id_subtype = a->chassis_id_subtype; + if (n->port_id) + { + _vec_len (n->port_id) = 0; + } + vec_add (n->port_id, portid, a->portid_len); + n->port_id_subtype = a->portid_subtype; + n->ttl = a->ttl; + n->last_heard = vlib_time_now (lldp_main.vlib_main); +} + +static void +lldp_rpc_update_peer (u32 hw_if_index, const u8 * chid, u8 chid_len, + u8 chid_subtype, const u8 * portid, + u8 portid_len, u8 portid_subtype, u16 ttl) +{ + const size_t data_size = + sizeof (lldp_intf_update_t) + chid_len + portid_len; + u8 data[data_size]; + lldp_intf_update_t *u = (lldp_intf_update_t *) data; + u->hw_if_index = hw_if_index; + u->chassis_id_len = chid_len; + u->chassis_id_subtype = chid_subtype; + u->ttl = ttl; + u->portid_len = portid_len; + u->portid_subtype = portid_subtype; + clib_memcpy (u->data, chid, chid_len); + clib_memcpy (u->data + chid_len, portid, portid_len); + vl_api_rpc_call_main_thread (lldp_rpc_update_peer_cb, data, data_size); +} + +lldp_tlv_code_t +lldp_tlv_get_code (const lldp_tlv_t * tlv) +{ + return tlv->head.byte1 >> 1; +} + +void +lldp_tlv_set_code (lldp_tlv_t * tlv, lldp_tlv_code_t code) +{ + tlv->head.byte1 = (tlv->head.byte1 & 1) + (code << 1); +} + +u16 +lldp_tlv_get_length (const lldp_tlv_t * tlv) +{ + return (((u16) (tlv->head.byte1 & 1)) << 8) + tlv->head.byte2; +} + +void +lldp_tlv_set_length (lldp_tlv_t * tlv, u16 length) +{ + tlv->head.byte2 = length & ((1 << 8) - 1); + if (length > (1 << 8) - 1) + { + tlv->head.byte1 |= 1; + } + else + { + tlv->head.byte1 &= (1 << 8) - 2; + } +} + +lldp_main_t lldp_main; + +static int +lldp_packet_scan (u32 hw_if_index, const lldp_tlv_t * pkt) +{ + const lldp_tlv_t *tlv = pkt; + +#define TLV_VIOLATES_PKT_BOUNDARY(pkt, tlv) \ + (((((u8 *)tlv) + sizeof (lldp_tlv_t)) > ((u8 *)pkt + vec_len (pkt))) || \ + ((((u8 *)tlv) + lldp_tlv_get_length (tlv)) > ((u8 *)pkt + vec_len (pkt)))) + + /* first tlv is always chassis id, followed by port id and ttl tlvs */ + if (TLV_VIOLATES_PKT_BOUNDARY (pkt, tlv) || + LLDP_TLV_NAME (chassis_id) != lldp_tlv_get_code (tlv)) + { + return LLDP_ERROR_BAD_TLV; + } + + u16 l = lldp_tlv_get_length (tlv); + if (l < STRUCT_SIZE_OF (lldp_chassis_id_tlv_t, subtype) + + LLDP_MIN_CHASS_ID_LEN || + l > STRUCT_SIZE_OF (lldp_chassis_id_tlv_t, subtype) + + LLDP_MAX_CHASS_ID_LEN) + { + return LLDP_ERROR_BAD_TLV; + } + + u8 chid_subtype = ((lldp_chassis_id_tlv_t *) tlv)->subtype; + u8 *chid = ((lldp_chassis_id_tlv_t *) tlv)->id; + u8 chid_len = l - STRUCT_SIZE_OF (lldp_chassis_id_tlv_t, subtype); + + tlv = (lldp_tlv_t *) ((u8 *) tlv + STRUCT_SIZE_OF (lldp_tlv_t, head) + l); + + if (TLV_VIOLATES_PKT_BOUNDARY (pkt, tlv) || + LLDP_TLV_NAME (port_id) != lldp_tlv_get_code (tlv)) + { + return LLDP_ERROR_BAD_TLV; + } + l = lldp_tlv_get_length (tlv); + if (l < STRUCT_SIZE_OF (lldp_port_id_tlv_t, subtype) + + LLDP_MIN_PORT_ID_LEN || + l > STRUCT_SIZE_OF (lldp_chassis_id_tlv_t, subtype) + + LLDP_MAX_PORT_ID_LEN) + { + return LLDP_ERROR_BAD_TLV; + } + + u8 portid_subtype = ((lldp_port_id_tlv_t *) tlv)->subtype; + u8 *portid = ((lldp_port_id_tlv_t *) tlv)->id; + u8 portid_len = l - STRUCT_SIZE_OF (lldp_port_id_tlv_t, subtype); + + tlv = (lldp_tlv_t *) ((u8 *) tlv + STRUCT_SIZE_OF (lldp_tlv_t, head) + l); + + if (TLV_VIOLATES_PKT_BOUNDARY (pkt, tlv) || + LLDP_TLV_NAME (ttl) != lldp_tlv_get_code (tlv)) + { + return LLDP_ERROR_BAD_TLV; + } + l = lldp_tlv_get_length (tlv); + if (l != STRUCT_SIZE_OF (lldp_ttl_tlv_t, ttl)) + { + return LLDP_ERROR_BAD_TLV; + } + u16 ttl = ntohs (((lldp_ttl_tlv_t *) tlv)->ttl); + tlv = (lldp_tlv_t *) ((u8 *) tlv + STRUCT_SIZE_OF (lldp_tlv_t, head) + l); + while (!TLV_VIOLATES_PKT_BOUNDARY (pkt, tlv) && + LLDP_TLV_NAME (pdu_end) != lldp_tlv_get_code (tlv)) + { + switch (lldp_tlv_get_code (tlv)) + { +#define F(num, type, str) \ + case LLDP_TLV_NAME (type): \ + /* ignore optional TLV */ \ + break; + foreach_lldp_optional_tlv_type (F); +#undef F + default: + return LLDP_ERROR_BAD_TLV; + } + tlv = (lldp_tlv_t *) ((u8 *) tlv + STRUCT_SIZE_OF (lldp_tlv_t, head) + + lldp_tlv_get_length (tlv)); + } + /* last tlv is pdu_end */ + if (TLV_VIOLATES_PKT_BOUNDARY (pkt, tlv) || + LLDP_TLV_NAME (pdu_end) != lldp_tlv_get_code (tlv) || + 0 != lldp_tlv_get_length (tlv)) + { + return LLDP_ERROR_BAD_TLV; + } + lldp_rpc_update_peer (hw_if_index, chid, chid_len, chid_subtype, portid, + portid_len, portid_subtype, ttl); + return LLDP_ERROR_NONE; +} + +lldp_intf_t * +lldp_get_intf (lldp_main_t * lm, u32 hw_if_index) +{ + uword *p = hash_get (lm->intf_by_hw_if_index, hw_if_index); + + if (p) + { + return pool_elt_at_index (lm->intfs, p[0]); + } + return NULL; +} + +lldp_intf_t * +lldp_create_intf (lldp_main_t * lm, u32 hw_if_index) +{ + + uword *p; + lldp_intf_t *n; + p = hash_get (lm->intf_by_hw_if_index, hw_if_index); + + if (p == 0) + { + pool_get (lm->intfs, n); + clib_memset (n, 0, sizeof (*n)); + n->hw_if_index = hw_if_index; + hash_set (lm->intf_by_hw_if_index, n->hw_if_index, n - lm->intfs); + } + else + { + n = pool_elt_at_index (lm->intfs, p[0]); + } + return n; +} + +/* + * lldp input routine + */ +lldp_error_t +lldp_input (vlib_main_t * vm, vlib_buffer_t * b0, u32 bi0) +{ + lldp_main_t *lm = &lldp_main; + lldp_error_t e; + + /* find our interface */ + vnet_sw_interface_t *sw_interface = vnet_get_sw_interface (lm->vnet_main, + vnet_buffer + (b0)->sw_if_index + [VLIB_RX]); + lldp_intf_t *n = lldp_get_intf (lm, sw_interface->hw_if_index); + + if (!n) + { + /* lldp disabled on this interface, we're done */ + return LLDP_ERROR_DISABLED; + } + + /* Actually scan the packet */ + e = lldp_packet_scan (sw_interface->hw_if_index, + vlib_buffer_get_current (b0)); + + return e; +} + +/* + * setup function + */ +static clib_error_t * +lldp_init (vlib_main_t * vm) +{ + clib_error_t *error; + lldp_main_t *lm = &lldp_main; + + if ((error = vlib_call_init_function (vm, lldp_template_init))) + return error; + + lm->vlib_main = vm; + lm->vnet_main = vnet_get_main (); + lm->msg_tx_hold = 4; /* default value per IEEE 802.1AB-2009 */ + lm->msg_tx_interval = 30; /* default value per IEEE 802.1AB-2009 */ + + return 0; +} + +VLIB_INIT_FUNCTION (lldp_init); + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/src/plugins/lldp/lldp_node.c b/src/plugins/lldp/lldp_node.c new file mode 100644 index 00000000000..dbb54af91f0 --- /dev/null +++ b/src/plugins/lldp/lldp_node.c @@ -0,0 +1,341 @@ +/* + * Copyright (c) 2011-2016 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file + * @brief LLDP nodes implementation + */ +#include +#include +#include + +/* set this to 1 to turn on debug prints via clib_warning() */ +#define LLDP_DEBUG (0) + +static vlib_node_registration_t lldp_process_node; + +#define F(sym, string) static char LLDP_ERR_##sym##_STR[] = string; +foreach_lldp_error (F); +#undef F + +/* + * packet counter strings + * Dump these counters via the "show error" CLI command + */ +static char *lldp_error_strings[] = { +#define F(sym, string) LLDP_ERR_##sym##_STR, + foreach_lldp_error (F) +#undef F +}; + +/* + * We actually send all lldp pkts to the "error" node after scanning + * them, so the graph node has only one next-index. The "error-drop" + * node automatically bumps our per-node packet counters for us. + */ +typedef enum +{ + LLDP_INPUT_NEXT_NORMAL, + LLDP_INPUT_N_NEXT, +} lldp_next_t; + +/* + * Process a frame of lldp packets + * Expect 1 packet / frame + */ +static uword +lldp_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, + vlib_frame_t * frame) +{ + u32 n_left_from, *from; + lldp_input_trace_t *t0; + + from = vlib_frame_vector_args (frame); /* array of buffer indices */ + n_left_from = frame->n_vectors; /* number of buffer indices */ + + while (n_left_from > 0) + { + u32 bi0; + vlib_buffer_t *b0; + u32 next0, error0; + + bi0 = from[0]; + b0 = vlib_get_buffer (vm, bi0); + + next0 = LLDP_INPUT_NEXT_NORMAL; + + /* scan this lldp pkt. error0 is the counter index to bump */ + error0 = lldp_input (vm, b0, bi0); + b0->error = node->errors[error0]; + + /* If this pkt is traced, snapshot the data */ + if (b0->flags & VLIB_BUFFER_IS_TRACED) + { + int len; + t0 = vlib_add_trace (vm, node, b0, sizeof (*t0)); + len = (b0->current_length < sizeof (t0->data)) ? b0->current_length + : sizeof (t0->data); + t0->len = len; + clib_memcpy_fast (t0->data, vlib_buffer_get_current (b0), len); + } + /* push this pkt to the next graph node, always error-drop */ + vlib_set_next_frame_buffer (vm, node, next0, bi0); + + from += 1; + n_left_from -= 1; + } + + return frame->n_vectors; +} + +/* + * lldp input graph node declaration + */ +/* *INDENT-OFF* */ +VLIB_REGISTER_NODE(lldp_input_node, static) = { + .function = lldp_node_fn, + .name = "lldp-input", + .vector_size = sizeof(u32), + .type = VLIB_NODE_TYPE_INTERNAL, + + .n_errors = LLDP_N_ERROR, + .error_strings = lldp_error_strings, + + .format_trace = lldp_input_format_trace, + + .n_next_nodes = LLDP_INPUT_N_NEXT, + .next_nodes = + { + [LLDP_INPUT_NEXT_NORMAL] = "error-drop", + }, +}; +/* *INDENT-ON* */ + +/* + * lldp process node function + */ +static uword +lldp_process (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f) +{ + lldp_main_t *lm = &lldp_main; + f64 timeout = 0; + uword event_type, *event_data = 0; + + /* So we can send events to the lldp process */ + lm->lldp_process_node_index = lldp_process_node.index; + + /* with ethernet input */ + ethernet_register_input_type (vm, ETHERNET_TYPE_802_1_LLDP /* LLDP */ , + lldp_input_node.index); + + while (1) + { + if (vec_len (lm->intfs_timeouts)) + { +#if LLDP_DEBUG + clib_warning ("DEBUG: wait for event with timeout %f", timeout); +#endif + (void) vlib_process_wait_for_event_or_clock (vm, timeout); + } + else + { +#if LLDP_DEBUG + clib_warning ("DEBUG: wait for event without timeout"); +#endif + (void) vlib_process_wait_for_event (vm); + } + event_type = vlib_process_get_events (vm, &event_data); + switch (event_type) + { + case ~0: /* no events => timeout */ + /* nothing to do here */ + break; + case LLDP_EVENT_RESCHEDULE: + /* nothing to do here - reschedule is done automatically after + * each event or timeout */ + break; + default: + clib_warning ("BUG: event type 0x%wx", event_type); + break; + } + if (!vec_len (lm->intfs_timeouts)) + { + continue; + } + /* send packet(s) and schedule another timeout */ + const f64 now = vlib_time_now (lm->vlib_main); + while (1) + { + lldp_intf_t *n = pool_elt_at_index (lm->intfs, + lm->intfs_timeouts + [lm->intfs_timeouts_idx]); + if (n->last_sent < 0.01 || now > n->last_sent + lm->msg_tx_interval) + { +#if LLDP_DEBUG + clib_warning ("send packet to lldp %p, if idx %d", n, + n->hw_if_index); +#endif + lldp_send_ethernet (lm, n, 0); + ++lm->intfs_timeouts_idx; + if (lm->intfs_timeouts_idx >= vec_len (lm->intfs_timeouts)) + { + lm->intfs_timeouts_idx = 0; + } + continue; + } + else + { + timeout = n->last_sent + lm->msg_tx_interval - now; + break; + } + } +#if LLDP_DEBUG + clib_warning ("DEBUG: timeout set to %f", timeout); + u8 *s = NULL; + u32 i; + vec_foreach_index (i, lm->intfs_timeouts) + { + if (i == lm->intfs_timeouts_idx) + { + s = format (s, " [%d]", lm->intfs_timeouts[i]); + } + else + { + s = format (s, " %d", lm->intfs_timeouts[i]); + } + } + clib_warning ("DEBUG: timeout schedule: %s", s); + vec_free (s); +#endif + if (event_data) + { + _vec_len (event_data) = 0; + } + } + + return 0; +} + +/* + * lldp process node declaration + */ +/* *INDENT-OFF* */ +VLIB_REGISTER_NODE(lldp_process_node, static) = { + .function = lldp_process, + .type = VLIB_NODE_TYPE_PROCESS, + .name = "lldp-process", +}; +/* *INDENT-ON* */ + +void +lldp_schedule_intf (lldp_main_t * lm, lldp_intf_t * n) +{ + const int idx = n - lm->intfs; + u32 v; + vec_foreach_index (v, lm->intfs_timeouts) + { + if (lm->intfs_timeouts[v] == idx) + { + /* already scheduled */ + return; + } + } + n->last_sent = 0; /* ensure that a packet is sent out immediately */ + /* put the interface at the current position in the timeouts - it + * will timeout immediately */ + vec_insert (lm->intfs_timeouts, 1, lm->intfs_timeouts_idx); + lm->intfs_timeouts[lm->intfs_timeouts_idx] = n - lm->intfs; + vlib_process_signal_event (lm->vlib_main, lm->lldp_process_node_index, + LLDP_EVENT_RESCHEDULE, 0); +#if LLDP_DEBUG + clib_warning ("DEBUG: schedule interface %p, if idx %d", n, n->hw_if_index); +#endif +} + +void +lldp_unschedule_intf (lldp_main_t * lm, lldp_intf_t * n) +{ + if (!n) + { + return; + } +#if LLDP_DEBUG + clib_warning ("DEBUG: unschedule interface %p, if idx %d", n, + n->hw_if_index); +#endif + const int idx = n - lm->intfs; + u32 v; + /* remove intf index from timeouts vector */ + vec_foreach_index (v, lm->intfs_timeouts) + { + if (lm->intfs_timeouts[v] == idx) + { + vec_delete (lm->intfs_timeouts, 1, v); + break; + } + } + /* wrap current timeout index to first element if needed */ + if (lm->intfs_timeouts_idx >= vec_len (lm->intfs_timeouts)) + { + lm->intfs_timeouts_idx = 0; + } + vlib_process_signal_event (lm->vlib_main, lm->lldp_process_node_index, + LLDP_EVENT_RESCHEDULE, 0); +} + +static clib_error_t * +lldp_sw_interface_up_down (vnet_main_t * vnm, u32 sw_if_index, u32 flags) +{ + lldp_main_t *lm = &lldp_main; + vnet_hw_interface_t *hi = vnet_get_sup_hw_interface (vnm, sw_if_index); + lldp_intf_t *n = lldp_get_intf (lm, hi->hw_if_index); + if (n) + { + if (!(flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP)) + { + /* FIXME - the packet sent here isn't send properly - need to find a + * way to send the packet before interface goes down */ + lldp_send_ethernet (lm, n, 1); + lldp_unschedule_intf (lm, n); + } + } + return 0; +} + +VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION (lldp_sw_interface_up_down); + +static clib_error_t * +lldp_hw_interface_up_down (vnet_main_t * vnm, u32 hw_if_index, u32 flags) +{ + lldp_main_t *lm = &lldp_main; + lldp_intf_t *n = lldp_get_intf (lm, hw_if_index); + if (n) + { + if (flags & VNET_HW_INTERFACE_FLAG_LINK_UP) + { + lldp_schedule_intf (lm, n); + } + } + return 0; +} + +VNET_HW_INTERFACE_LINK_UP_DOWN_FUNCTION (lldp_hw_interface_up_down); + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/src/plugins/lldp/lldp_node.h b/src/plugins/lldp/lldp_node.h new file mode 100644 index 00000000000..887a70f137f --- /dev/null +++ b/src/plugins/lldp/lldp_node.h @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2011-2016 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file + * @brief LLDP global declarations + */ +#ifndef __included_lldp_node_h__ +#define __included_lldp_node_h__ + +#include +#include +#include +#include +#include + +#include + +typedef struct lldp_intf +{ + /* hw interface index */ + u32 hw_if_index; + + /* Timers */ + f64 last_heard; + f64 last_sent; + + /* Info received from peer */ + u8 *chassis_id; + u8 *port_id; + u16 ttl; + lldp_port_id_subtype_t port_id_subtype; + lldp_chassis_id_subtype_t chassis_id_subtype; + + /* 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 +{ + /* pool of lldp-enabled interface context data */ + lldp_intf_t *intfs; + + /* rapidly find an interface by vlib hw interface index */ + uword *intf_by_hw_if_index; + + /* Background process node index */ + u32 lldp_process_node_index; + + /* interface idxs (into intfs pool) in the order of timing out */ + u32 *intfs_timeouts; + + /* index of the interface which will time out next */ + u32 intfs_timeouts_idx; + + /* packet template for sending out packets */ + vlib_packet_template_t packet_template; + + /* convenience variables */ + vlib_main_t *vlib_main; + vnet_main_t *vnet_main; + + /* system name advertised over LLDP (default is none) */ + u8 *sys_name; + + /* IEEE Std 802.1AB-2009: + * 9.2.5.6 msgTxHold + * This variable is used, as a multiplier of msgTxInterval, to determine the + * value of txTTL that is carried in LLDP frames transmitted by the LLDP + * agent. The recommended default value of msgTxHold is 4; this value can + * be changed by management to any value in the range 1 through 100. + */ + u8 msg_tx_hold; + + /* IEEE Std 802.1AB-2009: + * 9.2.5.7 msgTxInterval + * This variable defines the time interval in timer ticks between + * transmissions during normal transmission periods (i.e., txFast is zero). + * The recommended default value for msgTxInterval is 30 s; this value can + * be changed by management to any value in the range 1 through 3600. + */ + u16 msg_tx_interval; +} lldp_main_t; + +#define LLDP_MIN_TX_HOLD (1) +#define LLDP_MAX_TX_HOLD (100) +#define LLDP_MIN_TX_INTERVAL (1) +#define LLDP_MAX_TX_INTERVAL (3600) + +extern lldp_main_t lldp_main; + +/* Packet counters */ +#define foreach_lldp_error(F) \ + F(NONE, "good lldp packets (processed)") \ + F(CACHE_HIT, "good lldp packets (cache hit)") \ + F(BAD_TLV, "lldp packets with bad TLVs") \ + F(DISABLED, "lldp packets received on disabled interfaces") + +typedef enum +{ +#define F(sym, str) LLDP_ERROR_##sym, + foreach_lldp_error (F) +#undef F + LLDP_N_ERROR, +} lldp_error_t; + +/* lldp packet trace capture */ +typedef struct +{ + u32 len; + u8 data[400]; +} lldp_input_trace_t; + +typedef enum +{ + LLDP_EVENT_RESCHEDULE = 1, +} lldp_process_event_t; + +lldp_intf_t *lldp_get_intf (lldp_main_t * lm, u32 hw_if_index); +lldp_intf_t *lldp_create_intf (lldp_main_t * lm, u32 hw_if_index); +void lldp_delete_intf (lldp_main_t * lm, lldp_intf_t * n); +lldp_error_t lldp_input (vlib_main_t * vm, vlib_buffer_t * b0, u32 bi0); +u8 *lldp_input_format_trace (u8 * s, va_list * args); +void lldp_send_ethernet (lldp_main_t * lm, lldp_intf_t * n, int shutdown); +void lldp_schedule_intf (lldp_main_t * lm, lldp_intf_t * n); +void lldp_unschedule_intf (lldp_main_t * lm, lldp_intf_t * n); + +#endif /* __included_lldp_node_h__ */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/src/plugins/lldp/lldp_output.c b/src/plugins/lldp/lldp_output.c new file mode 100644 index 00000000000..dc03faf4d5c --- /dev/null +++ b/src/plugins/lldp/lldp_output.c @@ -0,0 +1,308 @@ +/* + * Copyright (c) 2011-2016 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file + * @brief LLDP packet generation implementation + */ +#include + +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) +{ + lldp_chassis_id_tlv_t *t = (lldp_chassis_id_tlv_t *) * t0p; + + lldp_tlv_set_code ((lldp_tlv_t *) t, LLDP_TLV_NAME (chassis_id)); + t->subtype = LLDP_CHASS_ID_SUBTYPE_NAME (mac_addr); + + const size_t addr_len = 6; + 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); + *t0p += STRUCT_SIZE_OF (lldp_tlv_t, head) + len; +} + +static void +lldp_add_port_id (const vnet_hw_interface_t * hw, u8 ** t0p) +{ + lldp_port_id_tlv_t *t = (lldp_port_id_tlv_t *) * t0p; + + lldp_tlv_set_code ((lldp_tlv_t *) t, LLDP_TLV_NAME (port_id)); + t->subtype = LLDP_PORT_ID_SUBTYPE_NAME (intf_name); + + const size_t name_len = vec_len (hw->name); + 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; +} + +static void +lldp_add_ttl (const lldp_main_t * lm, u8 ** t0p, int shutdown) +{ + lldp_ttl_tlv_t *t = (lldp_ttl_tlv_t *) * t0p; + lldp_tlv_set_code ((lldp_tlv_t *) t, LLDP_TLV_NAME (ttl)); + if (shutdown) + { + t->ttl = 0; + } + else + { + if ((size_t) lm->msg_tx_interval * lm->msg_tx_hold + 1 > (1 << 16) - 1) + { + t->ttl = htons ((1 << 16) - 1); + } + else + { + t->ttl = htons (lm->msg_tx_hold * lm->msg_tx_interval + 1); + } + } + const size_t len = STRUCT_SIZE_OF (lldp_ttl_tlv_t, ttl); + lldp_tlv_set_length ((lldp_tlv_t *) t, len); + *t0p += STRUCT_SIZE_OF (lldp_tlv_t, head) + len; +} + +static void +lldp_add_port_desc (const lldp_main_t * lm, lldp_intf_t * n, u8 ** t0p) +{ + const size_t len = vec_len (n->port_desc); + if (len) + { + 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_fast (t->v, n->port_desc, len); + *t0p += STRUCT_SIZE_OF (lldp_tlv_t, head) + len; + } +} + +static void +lldp_add_sys_name (const lldp_main_t * lm, u8 ** t0p) +{ + const size_t len = vec_len (lm->sys_name); + if (len) + { + 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_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) +{ + lldp_tlv_t *t = (lldp_tlv_t *) * t0p; + lldp_tlv_set_code (t, LLDP_TLV_NAME (pdu_end)); + lldp_tlv_set_length (t, 0); + *t0p += STRUCT_SIZE_OF (lldp_tlv_t, head); +} + +static void +lldp_add_tlvs (lldp_main_t * lm, vnet_hw_interface_t * hw, u8 ** t0p, + int shutdown, lldp_intf_t * n) +{ + lldp_add_chassis_id (hw, t0p); + lldp_add_port_id (hw, 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); +} + +/* + * send a lldp pkt on an ethernet interface + */ +void +lldp_send_ethernet (lldp_main_t * lm, lldp_intf_t * n, int shutdown) +{ + u32 *to_next; + ethernet_header_t *h0; + vnet_hw_interface_t *hw; + u32 bi0; + vlib_buffer_t *b0; + u8 *t0; + vlib_frame_t *f; + vlib_main_t *vm = lm->vlib_main; + vnet_main_t *vnm = lm->vnet_main; + + /* + * see lldp_template_init() to understand what's already painted + * into the buffer by the packet template mechanism + */ + h0 = vlib_packet_template_get_packet (vm, &lm->packet_template, &bi0); + + if (!h0) + return; + + /* Add the interface's ethernet source address */ + hw = vnet_get_hw_interface (vnm, n->hw_if_index); + + clib_memcpy_fast (h0->src_address, hw->hw_address, + vec_len (hw->hw_address)); + + u8 *data = ((u8 *) h0) + sizeof (*h0); + t0 = data; + + /* add TLVs */ + lldp_add_tlvs (lm, hw, &t0, shutdown, n); + + /* Set the outbound packet length */ + b0 = vlib_get_buffer (vm, bi0); + b0->current_length = sizeof (*h0) + t0 - data; + + /* And the outbound interface */ + vnet_buffer (b0)->sw_if_index[VLIB_TX] = hw->sw_if_index; + + /* And output the packet on the correct interface */ + f = vlib_get_frame_to_node (vm, hw->output_node_index); + to_next = vlib_frame_vector_args (f); + to_next[0] = bi0; + f->n_vectors = 1; + + vlib_put_frame_to_node (vm, hw->output_node_index, f); + n->last_sent = vlib_time_now (vm); +} + +void +lldp_delete_intf (lldp_main_t * lm, lldp_intf_t * n) +{ + if (n) + { + lldp_unschedule_intf (lm, n); + hash_unset (lm->intf_by_hw_if_index, n->hw_if_index); + 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); + } +} + +static clib_error_t * +lldp_template_init (vlib_main_t * vm) +{ + lldp_main_t *lm = &lldp_main; + + /* Create the ethernet lldp packet template */ + { + ethernet_header_t h; + + clib_memset (&h, 0, sizeof (h)); + + /* + * Send to 01:80:C2:00:00:0E - propagation constrained to a single + * physical link - stopped by all type of bridge + */ + h.dst_address[0] = 0x01; + h.dst_address[1] = 0x80; + h.dst_address[2] = 0xC2; + /* 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) */ + + h.type = htons (ETHERNET_TYPE_802_1_LLDP); + + vlib_packet_template_init (vm, &lm->packet_template, + /* data */ &h, sizeof (h), + /* alloc chunk size */ 8, "lldp-ethernet"); + } + + return 0; +} + +VLIB_INIT_FUNCTION (lldp_template_init); + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/src/plugins/lldp/lldp_protocol.h b/src/plugins/lldp/lldp_protocol.h new file mode 100644 index 00000000000..e641b26e20d --- /dev/null +++ b/src/plugins/lldp/lldp_protocol.h @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2011-2016 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef __included_lldp_protocol_h__ +#define __included_lldp_protocol_h__ +/** + * @file + * @brief LLDP protocol declarations + */ +#include + +/* + * optional TLV codes. + */ +#define foreach_lldp_optional_tlv_type(F) \ + F (4, port_desc, "Port Description") \ + F (5, sys_name, "System name") \ + F (6, sys_desc, "System Description") \ + F (7, sys_caps, "System Capabilities") \ + F (8, mgmt_addr, "Management Address") \ + F (127, org_spec, "Organizationally Specific TLV") + +/* + * all TLV codes. + */ +#define foreach_lldp_tlv_type(F) \ + F (0, pdu_end, "End of LLDPDU") \ + F (1, chassis_id, "Chassis ID") \ + F (2, port_id, "Port ID") \ + F (3, ttl, "Time To Live") \ + foreach_lldp_optional_tlv_type (F) + +#define LLDP_TLV_NAME(t) LLDP_TLV_##t + +typedef enum +{ +#define F(n, t, s) LLDP_TLV_NAME (t) = n, + foreach_lldp_tlv_type (F) +#undef F +} lldp_tlv_code_t; + +struct lldp_tlv_head +{ + u8 byte1; /* contains TLV code in the upper 7 bits + MSB of length */ + u8 byte2; /* contains the lower bits of length */ +}; + +/* *INDENT-OFF* */ +typedef CLIB_PACKED (struct { + struct lldp_tlv_head head; + u8 v[0]; +}) lldp_tlv_t; +/* *INDENT-ON* */ + +lldp_tlv_code_t lldp_tlv_get_code (const lldp_tlv_t * tlv); +void lldp_tlv_set_code (lldp_tlv_t * tlv, lldp_tlv_code_t code); +u16 lldp_tlv_get_length (const lldp_tlv_t * tlv); +void lldp_tlv_set_length (lldp_tlv_t * tlv, u16 length); + +#define foreach_chassis_id_subtype(F) \ + F (0, reserved, "Reserved") \ + F (1, chassis_comp, "Chassis component") \ + F (2, intf_alias, "Interface alias") \ + F (3, port_comp, "Port component") \ + F (4, mac_addr, "MAC address") \ + F (5, net_addr, "Network address") \ + F (6, intf_name, "Interface name") \ + F (7, local, "Locally assigned") + +#define LLDP_CHASS_ID_SUBTYPE_NAME(t) LLDP_CHASS_ID_SUBTYPE_##t +#define LLDP_MIN_CHASS_ID_LEN (1) +#define LLDP_MAX_CHASS_ID_LEN (255) + +typedef enum +{ +#define F(n, t, s) LLDP_CHASS_ID_SUBTYPE_NAME (t) = n, + foreach_chassis_id_subtype (F) +#undef F +} lldp_chassis_id_subtype_t; + +/* *INDENT-OFF* */ +typedef CLIB_PACKED (struct { + struct lldp_tlv_head head; + u8 subtype; + u8 id[0]; +}) lldp_chassis_id_tlv_t; +/* *INDENT-ON* */ + +#define foreach_port_id_subtype(F) \ + F (0, reserved, "Reserved") \ + F (1, intf_alias, "Interface alias") \ + F (2, port_comp, "Port component") \ + F (3, mac_addr, "MAC address") \ + F (4, net_addr, "Network address") \ + F (5, intf_name, "Interface name") \ + F (6, agent_circuit_id, "Agent circuit ID") \ + F (7, local, "Locally assigned") + +#define LLDP_PORT_ID_SUBTYPE_NAME(t) LLDP_PORT_ID_SUBTYPE_##t +#define LLDP_MIN_PORT_ID_LEN (1) +#define LLDP_MAX_PORT_ID_LEN (255) + +typedef enum +{ +#define F(n, t, s) LLDP_PORT_ID_SUBTYPE_NAME (t) = n, + foreach_port_id_subtype (F) +#undef F +} lldp_port_id_subtype_t; + +/* *INDENT-OFF* */ +typedef CLIB_PACKED (struct { + struct lldp_tlv_head head; + u8 subtype; + u8 id[0]; +}) lldp_port_id_tlv_t; + +typedef CLIB_PACKED (struct { + struct lldp_tlv_head head; + u16 ttl; +}) lldp_ttl_tlv_t; +/* *INDENT-ON* */ + +#endif /* __included_lldp_protocol_h__ */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/src/plugins/lldp/lldp_test.c b/src/plugins/lldp/lldp_test.c new file mode 100644 index 00000000000..661487c7835 --- /dev/null +++ b/src/plugins/lldp/lldp_test.c @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2015 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include +#include +#include + +/* define message IDs */ +#include +#include + +typedef struct +{ + /* API message ID base */ + u16 msg_id_base; + vat_main_t *vat_main; +} lldp_test_main_t; + +lldp_test_main_t lldp_test_main; + +#define __plugin_msg_base lldp_test_main.msg_id_base +#include + +/* Macro to finish up custom dump fns */ +#define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__) +#define FINISH \ + vec_add1 (s, 0); \ + vl_print (handle, (char *)s); \ + vec_free (s); \ + return handle; + +static int +api_lldp_config (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_lldp_config_t *mp; + int tx_hold = 0; + int tx_interval = 0; + u8 *sys_name = NULL; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "system-name %s", &sys_name)) + ; + else if (unformat (i, "tx-hold %d", &tx_hold)) + ; + else if (unformat (i, "tx-interval %d", &tx_interval)) + ; + else + { + clib_warning ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + vec_add1 (sys_name, 0); + + M (LLDP_CONFIG, mp); + mp->tx_hold = htonl (tx_hold); + mp->tx_interval = htonl (tx_interval); + vl_api_vec_to_api_string (sys_name, &mp->system_name); + vec_free (sys_name); + + S (mp); + W (ret); + return ret; +} + +static int +api_sw_interface_set_lldp (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_sw_interface_set_lldp_t *mp; + u32 sw_if_index = ~0; + u32 enable = 1; + u8 *port_desc = NULL, *mgmt_oid = NULL; + ip4_address_t ip4_addr; + ip6_address_t ip6_addr; + int ret; + + clib_memset (&ip4_addr, 0, sizeof (ip4_addr)); + clib_memset (&ip6_addr, 0, sizeof (ip6_addr)); + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "disable")) + enable = 0; + else + if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index)) + ; + else if (unformat (i, "sw_if_index %d", &sw_if_index)) + ; + else if (unformat (i, "port-desc %s", &port_desc)) + ; + else if (unformat (i, "mgmt-ip4 %U", unformat_ip4_address, &ip4_addr)) + ; + else if (unformat (i, "mgmt-ip6 %U", unformat_ip6_address, &ip6_addr)) + ; + else if (unformat (i, "mgmt-oid %s", &mgmt_oid)) + ; + else + break; + } + + if (sw_if_index == ~0) + { + errmsg ("missing interface name or sw_if_index"); + return -99; + } + + /* Construct the API message */ + vec_add1 (port_desc, 0); + vec_add1 (mgmt_oid, 0); + M (SW_INTERFACE_SET_LLDP, mp); + mp->sw_if_index = ntohl (sw_if_index); + mp->enable = enable; + vl_api_vec_to_api_string (port_desc, &mp->port_desc); + clib_memcpy (mp->mgmt_oid, mgmt_oid, vec_len (mgmt_oid)); + clib_memcpy (mp->mgmt_ip4, &ip4_addr, sizeof (ip4_addr)); + clib_memcpy (mp->mgmt_ip6, &ip6_addr, sizeof (ip6_addr)); + vec_free (port_desc); + vec_free (mgmt_oid); + + S (mp); + W (ret); + return ret; +} + +#include diff --git a/src/vat/api_format.c b/src/vat/api_format.c index 765f4f4e7da..0d0ec59d1f8 100644 --- a/src/vat/api_format.c +++ b/src/vat/api_format.c @@ -5196,8 +5196,6 @@ _(sw_interface_add_del_mac_address_reply) \ _(hw_interface_set_mtu_reply) \ _(p2p_ethernet_add_reply) \ _(p2p_ethernet_del_reply) \ -_(lldp_config_reply) \ -_(sw_interface_set_lldp_reply) \ _(tcp_configure_src_addresses_reply) \ _(session_rule_add_del_reply) \ _(ip_container_proxy_add_del_reply) \ @@ -5492,8 +5490,6 @@ _(HW_INTERFACE_SET_MTU_REPLY, hw_interface_set_mtu_reply) \ _(SW_INTERFACE_GET_TABLE_REPLY, sw_interface_get_table_reply) \ _(P2P_ETHERNET_ADD_REPLY, p2p_ethernet_add_reply) \ _(P2P_ETHERNET_DEL_REPLY, p2p_ethernet_del_reply) \ -_(LLDP_CONFIG_REPLY, lldp_config_reply) \ -_(SW_INTERFACE_SET_LLDP_REPLY, sw_interface_set_lldp_reply) \ _(TCP_CONFIGURE_SRC_ADDRESSES_REPLY, tcp_configure_src_addresses_reply) \ _(APP_NAMESPACE_ADD_DEL_REPLY, app_namespace_add_del_reply) \ _(SESSION_RULE_ADD_DEL_REPLY, session_rule_add_del_reply) \ @@ -19265,104 +19261,6 @@ api_p2p_ethernet_del (vat_main_t * vam) return ret; } -static int -api_lldp_config (vat_main_t * vam) -{ - unformat_input_t *i = vam->input; - vl_api_lldp_config_t *mp; - int tx_hold = 0; - int tx_interval = 0; - u8 *sys_name = NULL; - int ret; - - while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) - { - if (unformat (i, "system-name %s", &sys_name)) - ; - else if (unformat (i, "tx-hold %d", &tx_hold)) - ; - else if (unformat (i, "tx-interval %d", &tx_interval)) - ; - else - { - clib_warning ("parse error '%U'", format_unformat_error, i); - return -99; - } - } - - vec_add1 (sys_name, 0); - - M (LLDP_CONFIG, mp); - mp->tx_hold = htonl (tx_hold); - mp->tx_interval = htonl (tx_interval); - vl_api_vec_to_api_string (sys_name, &mp->system_name); - vec_free (sys_name); - - S (mp); - W (ret); - return ret; -} - -static int -api_sw_interface_set_lldp (vat_main_t * vam) -{ - unformat_input_t *i = vam->input; - vl_api_sw_interface_set_lldp_t *mp; - u32 sw_if_index = ~0; - u32 enable = 1; - u8 *port_desc = NULL, *mgmt_oid = NULL; - ip4_address_t ip4_addr; - ip6_address_t ip6_addr; - int ret; - - clib_memset (&ip4_addr, 0, sizeof (ip4_addr)); - clib_memset (&ip6_addr, 0, sizeof (ip6_addr)); - - while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) - { - if (unformat (i, "disable")) - enable = 0; - else - if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index)) - ; - else if (unformat (i, "sw_if_index %d", &sw_if_index)) - ; - else if (unformat (i, "port-desc %s", &port_desc)) - ; - else if (unformat (i, "mgmt-ip4 %U", unformat_ip4_address, &ip4_addr)) - ; - else if (unformat (i, "mgmt-ip6 %U", unformat_ip6_address, &ip6_addr)) - ; - else if (unformat (i, "mgmt-oid %s", &mgmt_oid)) - ; - else - break; - } - - if (sw_if_index == ~0) - { - errmsg ("missing interface name or sw_if_index"); - return -99; - } - - /* Construct the API message */ - vec_add1 (port_desc, 0); - vec_add1 (mgmt_oid, 0); - M (SW_INTERFACE_SET_LLDP, mp); - mp->sw_if_index = ntohl (sw_if_index); - mp->enable = enable; - vl_api_vec_to_api_string (port_desc, &mp->port_desc); - clib_memcpy (mp->mgmt_oid, mgmt_oid, vec_len (mgmt_oid)); - clib_memcpy (mp->mgmt_ip4, &ip4_addr, sizeof (ip4_addr)); - clib_memcpy (mp->mgmt_ip6, &ip6_addr, sizeof (ip6_addr)); - vec_free (port_desc); - vec_free (mgmt_oid); - - S (mp); - W (ret); - return ret; -} - static int api_tcp_configure_src_addresses (vat_main_t * vam) { @@ -20797,9 +20695,6 @@ _(hw_interface_set_mtu, " | hw_if_index mtu ") \ _(sw_interface_get_table, " | sw_if_index [ipv6]") \ _(p2p_ethernet_add, " | sw_if_index remote_mac sub_id ") \ _(p2p_ethernet_del, " | sw_if_index remote_mac ") \ -_(lldp_config, "system-name tx-hold tx-interval ") \ -_(sw_interface_set_lldp, " | sw_if_index [port-desc ]\n" \ - " [mgmt-ip4 ] [mgmt-ip6 ] [mgmt-oid ] [disable]") \ _(tcp_configure_src_addresses, "first-last [vrf ]") \ _(sock_init_shm, "size ") \ _(app_namespace_add_del, "[add] id secret sw_if_index ")\ diff --git a/src/vnet/CMakeLists.txt b/src/vnet/CMakeLists.txt index a2b965bed33..8c315ce5d73 100644 --- a/src/vnet/CMakeLists.txt +++ b/src/vnet/CMakeLists.txt @@ -361,24 +361,6 @@ list(APPEND VNET_HEADERS list(APPEND VNET_MULTIARCH_SOURCES bonding/node.c bonding/device.c) list(APPEND VNET_API_FILES bonding/bond.api) -############################################################################## -# Layer 2 / LLDP -############################################################################## -list(APPEND VNET_SOURCES - lldp/lldp_input.c - lldp/lldp_node.c - lldp/lldp_output.c - lldp/lldp_cli.c - lldp/lldp_api.c -) - -list(APPEND VNET_HEADERS - lldp/lldp_protocol.h - lldp/lldp.h -) - -list(APPEND VNET_API_FILES lldp/lldp.api) - ############################################################################## # Layer 2/3 "classify" ############################################################################## diff --git a/src/vnet/lldp/FEATURE.yaml b/src/vnet/lldp/FEATURE.yaml deleted file mode 100644 index feda51ad4de..00000000000 --- a/src/vnet/lldp/FEATURE.yaml +++ /dev/null @@ -1,8 +0,0 @@ ---- -name: Link Layer Discovery Protocol -maintainer: Klement Sekera -features: - - link layer discovery protocol implementation -description: "Link Layer Discovery Protocol (LLDP) implementation" -state: production -properties: [API, CLI, STATS, MULTITHREAD] diff --git a/src/vnet/lldp/dir.dox b/src/vnet/lldp/dir.dox deleted file mode 100644 index 84870f81901..00000000000 --- a/src/vnet/lldp/dir.dox +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/** - @dir src/vnet/lldp - @brief Link Layer Discovery Protocol (LLDP) implementation -*/ diff --git a/src/vnet/lldp/lldp.api b/src/vnet/lldp/lldp.api deleted file mode 100644 index 6be060b0dd1..00000000000 --- a/src/vnet/lldp/lldp.api +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2017 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -option version = "2.0.0"; - -import "vnet/interface_types.api"; -import "vnet/ip/ip_types.api"; - -/** \brief configure global parameter for LLDP - @param client_index - opaque cookie to identify the sender - @param context - sender context, to match reply w/ request - @param system_name - VPP system name - @param tx_hold - multiplier for tx_interval when setting time-to-live (TTL) - value in the LLDP packets - @param tx_interval - time interval, in seconds, between each LLDP frames -*/ -autoreply define lldp_config -{ - u32 client_index; - u32 context; - u32 tx_hold; - u32 tx_interval; - string system_name[]; -}; - -/** \brief Interface set LLDP request - @param client_index - opaque cookie to identify the sender - @param context - sender context, to match reply w/ request - @param sw_if_index - interface for which to enable/disable LLDP - @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 - @param port_desc - local port description -*/ -autoreply define sw_interface_set_lldp -{ - u32 client_index; - u32 context; - vl_api_interface_index_t sw_if_index; - vl_api_ip4_address_t mgmt_ip4; - vl_api_ip6_address_t mgmt_ip6; - u8 mgmt_oid[128]; - bool enable [default=true]; - string port_desc[]; -}; diff --git a/src/vnet/lldp/lldp.h b/src/vnet/lldp/lldp.h deleted file mode 100644 index df03dcea6ce..00000000000 --- a/src/vnet/lldp/lldp.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2017 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/** - * @file - * @brief LLDP external definition - */ -#ifndef __included_lldp_h__ -#define __included_lldp_h__ - -typedef enum lldp_cfg_err -{ - lldp_ok, - lldp_not_supported, - lldp_invalid_arg, -} lldp_cfg_err_t; - -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 deleted file mode 100644 index ecb75bcac4b..00000000000 --- a/src/vnet/lldp/lldp_api.c +++ /dev/null @@ -1,179 +0,0 @@ -/* - *------------------------------------------------------------------ - * lldp_api.c - lldp api - * - * Copyright (c) 2017 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------ - */ - -#include -#include - -#include -#include -#include - -#include -#include -#include - -#include - -#define vl_typedefs /* define message structures */ -#include -#undef vl_typedefs - -#define vl_endianfun /* define message structures */ -#include -#undef vl_endianfun - -/* instantiate all the print functions we know about */ -#define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__) -#define vl_printfun -#include -#undef vl_printfun - -#include - -#define foreach_vpe_api_msg \ -_(LLDP_CONFIG, lldp_config) \ -_(SW_INTERFACE_SET_LLDP, sw_interface_set_lldp) - -static void -vl_api_lldp_config_t_handler (vl_api_lldp_config_t * mp) -{ - vl_api_lldp_config_reply_t *rmp; - int rv = 0; - u8 *sys_name = 0; - - sys_name = vl_api_from_api_to_new_vec (mp, &mp->system_name); - - 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; - } - - REPLY_MACRO (VL_API_LLDP_CONFIG_REPLY); -} - -static void -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 *mgmt_oid = 0, *mgmt_ip4 = 0, *mgmt_ip6 = 0; - char *port_desc = 0; - u8 no_data[128] = { 0 }; - ip4_address_t ip4; - ip6_address_t ip6; - - if (vl_api_string_len (&mp->port_desc) > 0) - { - port_desc = vl_api_from_api_to_new_c_string (&mp->port_desc); - } - - ip4_address_decode (mp->mgmt_ip4, &ip4); - - if (ip4.as_u32 != 0) - { - vec_validate (mgmt_ip4, sizeof (ip4_address_t) - 1); - clib_memcpy (mgmt_ip4, &ip4, vec_len (mgmt_ip4)); - } - - ip6_address_decode (mp->mgmt_ip6, &ip6); - - if (!ip6_address_is_zero (&ip6)) - { - vec_validate (mgmt_ip6, sizeof (ip6_address_t) - 1); - clib_memcpy (mgmt_ip6, &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), (u8 **) & 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; - } - - BAD_SW_IF_INDEX_LABEL; - - REPLY_MACRO (VL_API_SW_INTERFACE_SET_LLDP_REPLY); -} - - -/* - * * lldp_api_hookup - * * Add vpe's API message handlers to the table. - * * vlib has already mapped shared memory and - * * added the client registration handlers. - * * See .../vlib-api/vlibmemory/memclnt_vlib.c:memclnt_process() - * */ -#define vl_msg_name_crc_list -#include -#undef vl_msg_name_crc_list - -static void -setup_message_id_table (api_main_t * am) -{ -#define _(id,n,crc) vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id); - foreach_vl_msg_name_crc_lldp; -#undef _ -} - -static clib_error_t * -lldp_api_hookup (vlib_main_t * vm) -{ - api_main_t *am = vlibapi_get_main (); - -#define _(N,n) \ - vl_msg_api_set_handlers(VL_API_##N, #n, \ - vl_api_##n##_t_handler, \ - vl_noop_handler, \ - vl_api_##n##_t_endian, \ - vl_api_##n##_t_print, \ - sizeof(vl_api_##n##_t), 1); - foreach_vpe_api_msg; -#undef _ - - /* - * * Set up the (msg_name, crc, message-id) table - * */ - setup_message_id_table (am); - - return 0; -} - -VLIB_API_INIT_FUNCTION (lldp_api_hookup); - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vnet/lldp/lldp_cli.c b/src/vnet/lldp/lldp_cli.c deleted file mode 100644 index 5f63e4a2e4f..00000000000 --- a/src/vnet/lldp/lldp_cli.c +++ /dev/null @@ -1,731 +0,0 @@ -/* - * Copyright (c) 2011-2016 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file - * @brief LLDP CLI handling - * - */ -#include -#include -#include -#include - -#ifndef ETHER_ADDR_LEN -#include -#endif - -static clib_error_t * -lldp_cfg_err_to_clib_err (lldp_cfg_err_t e) -{ - - switch (e) - { - case lldp_ok: - return 0; - case lldp_not_supported: - return clib_error_return (0, "not supported"); - case lldp_invalid_arg: - return clib_error_return (0, "invalid argument"); - } - return 0; -} - -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_main_t *lm = &lldp_main; - vnet_main_t *vnm = lm->vnet_main; - ethernet_main_t *em = ðernet_main; - const vnet_hw_interface_t *hi; - const ethernet_interface_t *eif; - - if (pool_is_free_index (vnm->interface_main.hw_interfaces, hw_if_index)) - { - return lldp_invalid_arg; - } - - hi = vnet_get_hw_interface (vnm, hw_if_index); - eif = ethernet_get_interface (em, hw_if_index); - if (!eif) - { - return lldp_not_supported; - } - - if (enable) - { - lldp_intf_t *n = lldp_get_intf (lm, hw_if_index); - if (n) - { - /* already enabled */ - return lldp_ok; - } - n = lldp_create_intf (lm, hw_if_index); - - if (port_desc && *port_desc) - { - n->port_desc = *port_desc; - *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_oid = 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)) - { - lldp_schedule_intf (lm, n); - } - } - else - { - lldp_intf_t *n = lldp_get_intf (lm, hi->sw_if_index); - lldp_delete_intf (lm, n); - } - - return lldp_ok; -} - -static clib_error_t * -lldp_intf_cmd (vlib_main_t * vm, unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - lldp_main_t *lm = &lldp_main; - vnet_main_t *vnm = lm->vnet_main; - 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) - { - if (unformat (input, "sw_if_index %d", &sw_if_index)) - ; - if (unformat - (input, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index)) - ; - else if (unformat (input, "disable")) - enable = 0; - 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; - } - - if (sw_if_index == (u32) ~ 0) - 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, &mgmt_ip4, - &mgmt_ip6, &mgmt_oid, - enable)); -} - -lldp_cfg_err_t -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) - { - return lldp_invalid_arg; - } - if (lm->msg_tx_hold != hold_time) - { - lm->msg_tx_hold = hold_time; - reschedule = 1; - } - } - - if (tx_interval) - { - if (tx_interval < LLDP_MIN_TX_INTERVAL || - tx_interval > LLDP_MAX_TX_INTERVAL) - { - return lldp_invalid_arg; - } - if (lm->msg_tx_interval != tx_interval) - { - reschedule = 1; - 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; -} - -static clib_error_t * -lldp_cfg_cmd (vlib_main_t * vm, unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - int hold_time = 0; - int tx_interval = 0; - u8 *host = NULL; - clib_error_t *ret = NULL; - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (input, "system-name %s", &host)) - { - } - else if (unformat (input, "tx-hold %d", &hold_time)) - { - if (hold_time < LLDP_MIN_TX_HOLD || hold_time > LLDP_MAX_TX_HOLD) - { - ret = - clib_error_return (0, - "invalid tx-hold `%d' (out of range <%d,%d>)", - hold_time, LLDP_MIN_TX_HOLD, - LLDP_MAX_TX_HOLD); - goto out; - } - } - else if (unformat (input, "tx-interval %d", &tx_interval)) - { - if (tx_interval < LLDP_MIN_TX_INTERVAL || - tx_interval > LLDP_MAX_TX_INTERVAL) - { - ret = - clib_error_return (0, - "invalid tx-interval `%d' (out of range <%d,%d>)", - tx_interval, LLDP_MIN_TX_INTERVAL, - LLDP_MAX_TX_INTERVAL); - goto out; - } - } - else - { - break; - } - } - ret = - lldp_cfg_err_to_clib_err (lldp_cfg_set (&host, hold_time, tx_interval)); -out: - vec_free (host); - return ret; -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND(set_interface_lldp_cmd, static) = { - .path = "set interface lldp", - .short_help = "set interface lldp | sw_if_index " - " [port-desc ] [mgmt-ip4 ]" - " [mgmt-ip6 ] [mgmt-oid ] [disable]", - .function = lldp_intf_cmd, -}; - -VLIB_CLI_COMMAND(set_lldp_cmd, static) = { - .path = "set lldp", - .short_help = "set lldp [system-name ] [tx-hold ] " - "[tx-interval ]", - .function = lldp_cfg_cmd, -}; -/* *INDENT-ON* */ - -static const char * -lldp_chassis_id_subtype_str (lldp_chassis_id_subtype_t t) -{ - switch (t) - { -#define F(num, val, str) \ - case num: \ - return str; - foreach_chassis_id_subtype (F) -#undef F - } - return "unknown chassis subtype"; -} - -static const char * -lldp_port_id_subtype_str (lldp_port_id_subtype_t t) -{ - switch (t) - { -#define F(num, val, str) \ - case num: \ - return str; - foreach_port_id_subtype (F) -#undef F - } - return "unknown port subtype"; -} - -/* - * format port id subtype&value - * - * @param va - 1st argument - unsigned - port id subtype - * @param va - 2nd argument - u8* - port id - * @param va - 3rd argument - unsigned - port id length - * @param va - 4th argument - int - 1 for detailed output, 0 for simple - */ -u8 * -format_lldp_port_id (u8 * s, va_list * va) -{ - const lldp_port_id_subtype_t subtype = va_arg (*va, unsigned); - const u8 *id = va_arg (*va, u8 *); - const unsigned len = va_arg (*va, unsigned); - const int detail = va_arg (*va, int); - if (!id) - { - return s; - } - switch (subtype) - { - case LLDP_PORT_ID_SUBTYPE_NAME (intf_alias): - /* fallthrough */ - case LLDP_PORT_ID_SUBTYPE_NAME (port_comp): - /* fallthrough */ - case LLDP_PORT_ID_SUBTYPE_NAME (local): - /* fallthrough */ - case LLDP_PORT_ID_SUBTYPE_NAME (intf_name): - if (detail) - { - s = format (s, "%U(%s)", format_ascii_bytes, id, len, - lldp_port_id_subtype_str (subtype)); - } - else - { - s = format (s, "%U", format_ascii_bytes, id, len); - } - break; - case LLDP_PORT_ID_SUBTYPE_NAME (mac_addr): - if (ETHER_ADDR_LEN == len) - { - if (detail) - { - s = format (s, "%U(%s)", format_mac_address, id, - lldp_port_id_subtype_str (subtype)); - } - else - { - s = format (s, "%U", format_mac_address, id); - } - break; - } - /* fallthrough */ - case LLDP_PORT_ID_SUBTYPE_NAME (net_addr): - /* TODO */ - /* fallthrough */ - default: - if (detail) - { - s = format (s, "%U(%s)", format_hex_bytes, id, len, - lldp_port_id_subtype_str (subtype)); - } - else - { - s = format (s, "%U", format_hex_bytes, id, len); - } - break; - } - return s; -} - -/* - * format chassis id subtype&value - * - * @param s format string - * @param va - 1st argument - unsigned - chassis id subtype - * @param va - 2nd argument - u8* - chassis id - * @param va - 3rd argument - unsigned - chassis id length - * @param va - 4th argument - int - 1 for detailed output, 0 for simple - */ -u8 * -format_lldp_chassis_id (u8 * s, va_list * va) -{ - const lldp_chassis_id_subtype_t subtype = - va_arg (*va, lldp_chassis_id_subtype_t); - const u8 *id = va_arg (*va, u8 *); - const unsigned len = va_arg (*va, unsigned); - const int detail = va_arg (*va, int); - if (!id) - { - return s; - } - switch (subtype) - { - case LLDP_CHASS_ID_SUBTYPE_NAME (chassis_comp): - /* fallthrough */ - case LLDP_CHASS_ID_SUBTYPE_NAME (intf_alias): - /* fallthrough */ - case LLDP_CHASS_ID_SUBTYPE_NAME (port_comp): - /* fallthrough */ - case LLDP_PORT_ID_SUBTYPE_NAME (local): - /* fallthrough */ - case LLDP_CHASS_ID_SUBTYPE_NAME (intf_name): - if (detail) - { - s = format (s, "%U(%s)", format_ascii_bytes, id, len, - lldp_chassis_id_subtype_str (subtype)); - } - else - { - s = format (s, "%U", format_ascii_bytes, id, len); - } - break; - case LLDP_CHASS_ID_SUBTYPE_NAME (mac_addr): - if (ETHER_ADDR_LEN == len) - { - if (detail) - { - s = format (s, "%U(%s)", format_mac_address, id, - lldp_chassis_id_subtype_str (subtype)); - } - else - { - s = format (s, "%U", format_mac_address, id); - } - break; - } - /* fallthrough */ - case LLDP_CHASS_ID_SUBTYPE_NAME (net_addr): - /* TODO */ - default: - if (detail) - { - s = format (s, "%U(%s)", format_hex_bytes, id, len, - lldp_chassis_id_subtype_str (subtype)); - } - else - { - s = format (s, "%U", format_hex_bytes, id, len); - } - break; - } - return s; -} - -/* - * convert a tlv code to human-readable string - */ -static const char * -lldp_tlv_code_str (lldp_tlv_code_t t) -{ - switch (t) - { -#define F(n, t, s) \ - case n: \ - return s; - foreach_lldp_tlv_type (F) -#undef F - } - return "unknown lldp tlv"; -} - -/* - * format a single LLDP TLV - * - * @param s format string - * @param va variable list - pointer to lldp_tlv_t is expected - */ -u8 * -format_lldp_tlv (u8 * s, va_list * va) -{ - const lldp_tlv_t *tlv = va_arg (*va, lldp_tlv_t *); - if (!tlv) - { - return s; - } - u16 l = lldp_tlv_get_length (tlv); - switch (lldp_tlv_get_code (tlv)) - { - case LLDP_TLV_NAME (chassis_id): - s = format (s, "%U", format_lldp_chassis_id, - ((lldp_chassis_id_tlv_t *) tlv)->subtype, - ((lldp_chassis_id_tlv_t *) tlv)->id, - l - STRUCT_SIZE_OF (lldp_chassis_id_tlv_t, subtype), 1); - break; - case LLDP_TLV_NAME (port_id): - s = format (s, "%U", format_lldp_port_id, - ((lldp_port_id_tlv_t *) tlv)->subtype, - ((lldp_port_id_tlv_t *) tlv)->id, - l - STRUCT_SIZE_OF (lldp_port_id_tlv_t, subtype), 1); - break; - case LLDP_TLV_NAME (ttl): - s = format (s, "%d", ntohs (((lldp_ttl_tlv_t *) tlv)->ttl)); - break; - case LLDP_TLV_NAME (sys_name): - /* fallthrough */ - case LLDP_TLV_NAME (sys_desc): - s = format (s, "%U", format_ascii_bytes, tlv->v, l); - break; - default: - s = format (s, "%U", format_hex_bytes, tlv->v, l); - } - - return s; -} - -static u8 * -format_time_ago (u8 * s, va_list * va) -{ - f64 ago = va_arg (*va, double); - f64 now = va_arg (*va, double); - if (ago < 0.01) - { - return format (s, "never"); - } - return format (s, "%.1fs ago", now - ago); -} - -static u8 * -format_lldp_intfs_detail (u8 * s, vlib_main_t * vm, const lldp_main_t * lm) -{ - vnet_main_t *vnm = &vnet_main; - const lldp_intf_t *n; - const vnet_hw_interface_t *hw; - const vnet_sw_interface_t *sw; - s = format (s, "LLDP configuration:\n"); - if (lm->sys_name) - { - 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"); - f64 now = vlib_time_now (vm); - - /* *INDENT-OFF* */ - pool_foreach( - 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)) - { - 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, - "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); - } - else - { - s = format(s, - "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); - } - })); - /* *INDENT-ON* */ - return s; -} - -static u8 * -format_lldp_intfs (u8 * s, va_list * va) -{ - vlib_main_t *vm = va_arg (*va, vlib_main_t *); - const lldp_main_t *lm = va_arg (*va, lldp_main_t *); - const int detail = va_arg (*va, int); - vnet_main_t *vnm = &vnet_main; - const lldp_intf_t *n; - - if (detail) - { - return format_lldp_intfs_detail (s, vm, lm); - } - - f64 now = vlib_time_now (vm); - s = format (s, "%-25s %-25s %-25s %=15s %=15s %=10s\n", "Local interface", - "Peer chassis ID", "Remote port ID", "Last heard", "Last sent", - "Status"); - - /* *INDENT-OFF* */ - pool_foreach( - n, lm->intfs, ({ - const vnet_hw_interface_t *hw = - vnet_get_hw_interface(vnm, n->hw_if_index); - const vnet_sw_interface_t *sw = - vnet_get_sw_interface(lm->vnet_main, hw->sw_if_index); - /* Interface shutdown */ - if (!(sw->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP)) - continue; - if (now < n->last_heard + n->ttl) - { - s = format(s, "%-25s %-25U %-25U %=15U %=15U %=10s\n", hw->name, - format_lldp_chassis_id, n->chassis_id_subtype, - n->chassis_id, vec_len(n->chassis_id), 0, - format_lldp_port_id, n->port_id_subtype, n->port_id, - vec_len(n->port_id), 0, format_time_ago, n->last_heard, - now, format_time_ago, n->last_sent, now, "active"); - } - else - { - s = format(s, "%-25s %-25s %-25s %=15U %=15U %=10s\n", hw->name, - "", "", format_time_ago, n->last_heard, now, - format_time_ago, n->last_sent, now, "inactive"); - } - })); - /* *INDENT-ON* */ - return s; -} - -static clib_error_t * -show_lldp (vlib_main_t * vm, unformat_input_t * input, - CLIB_UNUSED (vlib_cli_command_t * lmd)) -{ - lldp_main_t *lm = &lldp_main; - - if (unformat (input, "detail")) - { - vlib_cli_output (vm, "%U\n", format_lldp_intfs, vm, lm, 1); - } - else - { - vlib_cli_output (vm, "%U\n", format_lldp_intfs, vm, lm, 0); - } - return 0; -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND(show_lldp_command, static) = { - .path = "show lldp", - .short_help = "show lldp [detail]", - .function = show_lldp, -}; -/* *INDENT-ON* */ - -/* - * packet trace format function, very similar to - * lldp_packet_scan except that we call the per TLV format - * functions instead of the per TLV processing functions - */ -u8 * -lldp_input_format_trace (u8 * s, va_list * args) -{ - CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *); - CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); - const lldp_input_trace_t *t = va_arg (*args, lldp_input_trace_t *); - const u8 *cur; - const lldp_tlv_t *tlv; - cur = t->data; - while (((cur + lldp_tlv_get_length ((lldp_tlv_t *) cur)) < - t->data + t->len)) - { - tlv = (lldp_tlv_t *) cur; - if (cur == t->data) - { - s = format (s, "TLV #%d(%s): %U\n", lldp_tlv_get_code (tlv), - lldp_tlv_code_str (lldp_tlv_get_code (tlv)), - format_lldp_tlv, tlv); - } - else - { - s = format (s, " TLV #%d(%s): %U\n", lldp_tlv_get_code (tlv), - lldp_tlv_code_str (lldp_tlv_get_code (tlv)), - format_lldp_tlv, tlv); - } - cur += STRUCT_SIZE_OF (lldp_tlv_t, head) + lldp_tlv_get_length (tlv); - } - - return s; -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vnet/lldp/lldp_doc.md b/src/vnet/lldp/lldp_doc.md deleted file mode 100644 index 717de898c4e..00000000000 --- a/src/vnet/lldp/lldp_doc.md +++ /dev/null @@ -1,86 +0,0 @@ -# VPP Link Layer Discovery Protocol (LLDP) implementation {#lldp_doc} - -This is a memo intended to contain documentation of the VPP LLDP implementation -Everything that is not directly obvious should come here. - - -## LLDP -LLDP is a link layer protocol to advertise the capabilities and current status of the system. - -There are 2 nodes handling LLDP - -1.) input-node which processes incoming packets and updates the local database -2.) process-node which is responsible for sending out LLDP packets from VPP side - - -### Configuration - -LLDP has a global configuration and a per-interface enable setting. - -Global configuration is modified using the "set lldp" command - -set lldp [system-name ] [tx-hold ] [tx-interval ] - -system-name: the name of the VPP system sent to peers in the system-name TLV -tx-hold: multiplier for tx-interval when setting time-to-live (TTL) value in the LLDP packets (TTL = tx-hold * tx-interval + 1, if TTL > 65535, then TTL = 65535) -tx-interval: time interval between sending out LLDP packets - -Per interface setting is done using the "set interface lldp" command - -set interface lldp | if_index [port-desc ] [disable] - -interface: the name of the interface for which to enable/disable LLDP -if_index: sw interface index can be used if interface name is not used. -port-desc: port description -disable: LLDP feature can be enabled or disabled per interface. - -### Configuration example - -Configure system-name as "VPP" and transmit interval to 10 seconds: - -set lldp system-name VPP tx-interval 10 - -Enable LLDP on interface TenGigabitEthernet5/0/1 with port description - -set interface lldp TenGigabitEthernet5/0/1 port-desc vtf:eth0 - - -### Operational data - -The list of LLDP-enabled interfaces which are up can be shown using "show lldp" command - -Example: -DBGvpp# show lldp -Local interface Peer chassis ID Remote port ID Last heard Last sent Status -GigabitEthernet2/0/1 never 27.0s ago inactive -TenGigabitEthernet5/0/1 8c:60:4f:dd:ca:52 Eth1/3/3 20.1s ago 18.3s ago active - -All LLDP configuration data with all LLDP-enabled interfaces can be shown using "show lldp detail" command - -Example: -DBGvpp# show lldp detail -LLDP configuration: -Configured system name: vpp -Configured tx-hold: 4 -Configured tx-interval: 30 - -LLDP-enabled interface table: - -Interface name: GigabitEthernet2/0/1 -Interface/peer state: inactive(timeout) -Last known peer chassis ID: -Last known peer port ID: -Last packet sent: 12.4s ago -Last packet received: never - -Interface name: GigabitEthernet2/0/2 -Interface/peer state: interface down -Last packet sent: never - -Interface name: TenGigabitEthernet5/0/1 -Interface/peer state: active -Peer chassis ID: 8c:60:4f:dd:ca:52(MAC address) -Remote port ID: Eth1/3/3(Locally assigned) -Last packet sent: 3.6s ago -Last packet received: 5.5s ago - diff --git a/src/vnet/lldp/lldp_input.c b/src/vnet/lldp/lldp_input.c deleted file mode 100644 index cfae30e32ca..00000000000 --- a/src/vnet/lldp/lldp_input.c +++ /dev/null @@ -1,302 +0,0 @@ -/* - * Copyright (c) 2011-2016 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/** - * @file - * @brief LLDP packet parsing implementation - */ -#include -#include -#include - -typedef struct -{ - u32 hw_if_index; - u8 chassis_id_len; - u8 chassis_id_subtype; - u8 portid_len; - u8 portid_subtype; - u16 ttl; - u8 data[0]; /* this contains both chassis id (chassis_id_len bytes) and port - id (portid_len bytes) */ -} lldp_intf_update_t; - -static void -lldp_rpc_update_peer_cb (const lldp_intf_update_t * a) -{ - ASSERT (vlib_get_thread_index () == 0); - - lldp_intf_t *n = lldp_get_intf (&lldp_main, a->hw_if_index); - if (!n) - { - /* LLDP turned off for this interface, ignore the update */ - return; - } - const u8 *chassis_id = a->data; - const u8 *portid = a->data + a->chassis_id_len; - - if (n->chassis_id) - { - _vec_len (n->chassis_id) = 0; - } - vec_add (n->chassis_id, chassis_id, a->chassis_id_len); - n->chassis_id_subtype = a->chassis_id_subtype; - if (n->port_id) - { - _vec_len (n->port_id) = 0; - } - vec_add (n->port_id, portid, a->portid_len); - n->port_id_subtype = a->portid_subtype; - n->ttl = a->ttl; - n->last_heard = vlib_time_now (lldp_main.vlib_main); -} - -static void -lldp_rpc_update_peer (u32 hw_if_index, const u8 * chid, u8 chid_len, - u8 chid_subtype, const u8 * portid, - u8 portid_len, u8 portid_subtype, u16 ttl) -{ - const size_t data_size = - sizeof (lldp_intf_update_t) + chid_len + portid_len; - u8 data[data_size]; - lldp_intf_update_t *u = (lldp_intf_update_t *) data; - u->hw_if_index = hw_if_index; - u->chassis_id_len = chid_len; - u->chassis_id_subtype = chid_subtype; - u->ttl = ttl; - u->portid_len = portid_len; - u->portid_subtype = portid_subtype; - clib_memcpy (u->data, chid, chid_len); - clib_memcpy (u->data + chid_len, portid, portid_len); - vl_api_rpc_call_main_thread (lldp_rpc_update_peer_cb, data, data_size); -} - -lldp_tlv_code_t -lldp_tlv_get_code (const lldp_tlv_t * tlv) -{ - return tlv->head.byte1 >> 1; -} - -void -lldp_tlv_set_code (lldp_tlv_t * tlv, lldp_tlv_code_t code) -{ - tlv->head.byte1 = (tlv->head.byte1 & 1) + (code << 1); -} - -u16 -lldp_tlv_get_length (const lldp_tlv_t * tlv) -{ - return (((u16) (tlv->head.byte1 & 1)) << 8) + tlv->head.byte2; -} - -void -lldp_tlv_set_length (lldp_tlv_t * tlv, u16 length) -{ - tlv->head.byte2 = length & ((1 << 8) - 1); - if (length > (1 << 8) - 1) - { - tlv->head.byte1 |= 1; - } - else - { - tlv->head.byte1 &= (1 << 8) - 2; - } -} - -lldp_main_t lldp_main; - -static int -lldp_packet_scan (u32 hw_if_index, const lldp_tlv_t * pkt) -{ - const lldp_tlv_t *tlv = pkt; - -#define TLV_VIOLATES_PKT_BOUNDARY(pkt, tlv) \ - (((((u8 *)tlv) + sizeof (lldp_tlv_t)) > ((u8 *)pkt + vec_len (pkt))) || \ - ((((u8 *)tlv) + lldp_tlv_get_length (tlv)) > ((u8 *)pkt + vec_len (pkt)))) - - /* first tlv is always chassis id, followed by port id and ttl tlvs */ - if (TLV_VIOLATES_PKT_BOUNDARY (pkt, tlv) || - LLDP_TLV_NAME (chassis_id) != lldp_tlv_get_code (tlv)) - { - return LLDP_ERROR_BAD_TLV; - } - - u16 l = lldp_tlv_get_length (tlv); - if (l < STRUCT_SIZE_OF (lldp_chassis_id_tlv_t, subtype) + - LLDP_MIN_CHASS_ID_LEN || - l > STRUCT_SIZE_OF (lldp_chassis_id_tlv_t, subtype) + - LLDP_MAX_CHASS_ID_LEN) - { - return LLDP_ERROR_BAD_TLV; - } - - u8 chid_subtype = ((lldp_chassis_id_tlv_t *) tlv)->subtype; - u8 *chid = ((lldp_chassis_id_tlv_t *) tlv)->id; - u8 chid_len = l - STRUCT_SIZE_OF (lldp_chassis_id_tlv_t, subtype); - - tlv = (lldp_tlv_t *) ((u8 *) tlv + STRUCT_SIZE_OF (lldp_tlv_t, head) + l); - - if (TLV_VIOLATES_PKT_BOUNDARY (pkt, tlv) || - LLDP_TLV_NAME (port_id) != lldp_tlv_get_code (tlv)) - { - return LLDP_ERROR_BAD_TLV; - } - l = lldp_tlv_get_length (tlv); - if (l < STRUCT_SIZE_OF (lldp_port_id_tlv_t, subtype) + - LLDP_MIN_PORT_ID_LEN || - l > STRUCT_SIZE_OF (lldp_chassis_id_tlv_t, subtype) + - LLDP_MAX_PORT_ID_LEN) - { - return LLDP_ERROR_BAD_TLV; - } - - u8 portid_subtype = ((lldp_port_id_tlv_t *) tlv)->subtype; - u8 *portid = ((lldp_port_id_tlv_t *) tlv)->id; - u8 portid_len = l - STRUCT_SIZE_OF (lldp_port_id_tlv_t, subtype); - - tlv = (lldp_tlv_t *) ((u8 *) tlv + STRUCT_SIZE_OF (lldp_tlv_t, head) + l); - - if (TLV_VIOLATES_PKT_BOUNDARY (pkt, tlv) || - LLDP_TLV_NAME (ttl) != lldp_tlv_get_code (tlv)) - { - return LLDP_ERROR_BAD_TLV; - } - l = lldp_tlv_get_length (tlv); - if (l != STRUCT_SIZE_OF (lldp_ttl_tlv_t, ttl)) - { - return LLDP_ERROR_BAD_TLV; - } - u16 ttl = ntohs (((lldp_ttl_tlv_t *) tlv)->ttl); - tlv = (lldp_tlv_t *) ((u8 *) tlv + STRUCT_SIZE_OF (lldp_tlv_t, head) + l); - while (!TLV_VIOLATES_PKT_BOUNDARY (pkt, tlv) && - LLDP_TLV_NAME (pdu_end) != lldp_tlv_get_code (tlv)) - { - switch (lldp_tlv_get_code (tlv)) - { -#define F(num, type, str) \ - case LLDP_TLV_NAME (type): \ - /* ignore optional TLV */ \ - break; - foreach_lldp_optional_tlv_type (F); -#undef F - default: - return LLDP_ERROR_BAD_TLV; - } - tlv = (lldp_tlv_t *) ((u8 *) tlv + STRUCT_SIZE_OF (lldp_tlv_t, head) + - lldp_tlv_get_length (tlv)); - } - /* last tlv is pdu_end */ - if (TLV_VIOLATES_PKT_BOUNDARY (pkt, tlv) || - LLDP_TLV_NAME (pdu_end) != lldp_tlv_get_code (tlv) || - 0 != lldp_tlv_get_length (tlv)) - { - return LLDP_ERROR_BAD_TLV; - } - lldp_rpc_update_peer (hw_if_index, chid, chid_len, chid_subtype, portid, - portid_len, portid_subtype, ttl); - return LLDP_ERROR_NONE; -} - -lldp_intf_t * -lldp_get_intf (lldp_main_t * lm, u32 hw_if_index) -{ - uword *p = hash_get (lm->intf_by_hw_if_index, hw_if_index); - - if (p) - { - return pool_elt_at_index (lm->intfs, p[0]); - } - return NULL; -} - -lldp_intf_t * -lldp_create_intf (lldp_main_t * lm, u32 hw_if_index) -{ - - uword *p; - lldp_intf_t *n; - p = hash_get (lm->intf_by_hw_if_index, hw_if_index); - - if (p == 0) - { - pool_get (lm->intfs, n); - clib_memset (n, 0, sizeof (*n)); - n->hw_if_index = hw_if_index; - hash_set (lm->intf_by_hw_if_index, n->hw_if_index, n - lm->intfs); - } - else - { - n = pool_elt_at_index (lm->intfs, p[0]); - } - return n; -} - -/* - * lldp input routine - */ -lldp_error_t -lldp_input (vlib_main_t * vm, vlib_buffer_t * b0, u32 bi0) -{ - lldp_main_t *lm = &lldp_main; - lldp_error_t e; - - /* find our interface */ - vnet_sw_interface_t *sw_interface = vnet_get_sw_interface (lm->vnet_main, - vnet_buffer - (b0)->sw_if_index - [VLIB_RX]); - lldp_intf_t *n = lldp_get_intf (lm, sw_interface->hw_if_index); - - if (!n) - { - /* lldp disabled on this interface, we're done */ - return LLDP_ERROR_DISABLED; - } - - /* Actually scan the packet */ - e = lldp_packet_scan (sw_interface->hw_if_index, - vlib_buffer_get_current (b0)); - - return e; -} - -/* - * setup function - */ -static clib_error_t * -lldp_init (vlib_main_t * vm) -{ - clib_error_t *error; - lldp_main_t *lm = &lldp_main; - - if ((error = vlib_call_init_function (vm, lldp_template_init))) - return error; - - lm->vlib_main = vm; - lm->vnet_main = vnet_get_main (); - lm->msg_tx_hold = 4; /* default value per IEEE 802.1AB-2009 */ - lm->msg_tx_interval = 30; /* default value per IEEE 802.1AB-2009 */ - - return 0; -} - -VLIB_INIT_FUNCTION (lldp_init); - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vnet/lldp/lldp_node.c b/src/vnet/lldp/lldp_node.c deleted file mode 100644 index 043ca9f01b5..00000000000 --- a/src/vnet/lldp/lldp_node.c +++ /dev/null @@ -1,341 +0,0 @@ -/* - * Copyright (c) 2011-2016 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/** - * @file - * @brief LLDP nodes implementation - */ -#include -#include -#include - -/* set this to 1 to turn on debug prints via clib_warning() */ -#define LLDP_DEBUG (0) - -static vlib_node_registration_t lldp_process_node; - -#define F(sym, string) static char LLDP_ERR_##sym##_STR[] = string; -foreach_lldp_error (F); -#undef F - -/* - * packet counter strings - * Dump these counters via the "show error" CLI command - */ -static char *lldp_error_strings[] = { -#define F(sym, string) LLDP_ERR_##sym##_STR, - foreach_lldp_error (F) -#undef F -}; - -/* - * We actually send all lldp pkts to the "error" node after scanning - * them, so the graph node has only one next-index. The "error-drop" - * node automatically bumps our per-node packet counters for us. - */ -typedef enum -{ - LLDP_INPUT_NEXT_NORMAL, - LLDP_INPUT_N_NEXT, -} lldp_next_t; - -/* - * Process a frame of lldp packets - * Expect 1 packet / frame - */ -static uword -lldp_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - u32 n_left_from, *from; - lldp_input_trace_t *t0; - - from = vlib_frame_vector_args (frame); /* array of buffer indices */ - n_left_from = frame->n_vectors; /* number of buffer indices */ - - while (n_left_from > 0) - { - u32 bi0; - vlib_buffer_t *b0; - u32 next0, error0; - - bi0 = from[0]; - b0 = vlib_get_buffer (vm, bi0); - - next0 = LLDP_INPUT_NEXT_NORMAL; - - /* scan this lldp pkt. error0 is the counter index to bump */ - error0 = lldp_input (vm, b0, bi0); - b0->error = node->errors[error0]; - - /* If this pkt is traced, snapshot the data */ - if (b0->flags & VLIB_BUFFER_IS_TRACED) - { - int len; - t0 = vlib_add_trace (vm, node, b0, sizeof (*t0)); - len = (b0->current_length < sizeof (t0->data)) ? b0->current_length - : sizeof (t0->data); - t0->len = len; - clib_memcpy_fast (t0->data, vlib_buffer_get_current (b0), len); - } - /* push this pkt to the next graph node, always error-drop */ - vlib_set_next_frame_buffer (vm, node, next0, bi0); - - from += 1; - n_left_from -= 1; - } - - return frame->n_vectors; -} - -/* - * lldp input graph node declaration - */ -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE(lldp_input_node, static) = { - .function = lldp_node_fn, - .name = "lldp-input", - .vector_size = sizeof(u32), - .type = VLIB_NODE_TYPE_INTERNAL, - - .n_errors = LLDP_N_ERROR, - .error_strings = lldp_error_strings, - - .format_trace = lldp_input_format_trace, - - .n_next_nodes = LLDP_INPUT_N_NEXT, - .next_nodes = - { - [LLDP_INPUT_NEXT_NORMAL] = "error-drop", - }, -}; -/* *INDENT-ON* */ - -/* - * lldp process node function - */ -static uword -lldp_process (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f) -{ - lldp_main_t *lm = &lldp_main; - f64 timeout = 0; - uword event_type, *event_data = 0; - - /* So we can send events to the lldp process */ - lm->lldp_process_node_index = lldp_process_node.index; - - /* with ethernet input */ - ethernet_register_input_type (vm, ETHERNET_TYPE_802_1_LLDP /* LLDP */ , - lldp_input_node.index); - - while (1) - { - if (vec_len (lm->intfs_timeouts)) - { -#if LLDP_DEBUG - clib_warning ("DEBUG: wait for event with timeout %f", timeout); -#endif - (void) vlib_process_wait_for_event_or_clock (vm, timeout); - } - else - { -#if LLDP_DEBUG - clib_warning ("DEBUG: wait for event without timeout"); -#endif - (void) vlib_process_wait_for_event (vm); - } - event_type = vlib_process_get_events (vm, &event_data); - switch (event_type) - { - case ~0: /* no events => timeout */ - /* nothing to do here */ - break; - case LLDP_EVENT_RESCHEDULE: - /* nothing to do here - reschedule is done automatically after - * each event or timeout */ - break; - default: - clib_warning ("BUG: event type 0x%wx", event_type); - break; - } - if (!vec_len (lm->intfs_timeouts)) - { - continue; - } - /* send packet(s) and schedule another timeout */ - const f64 now = vlib_time_now (lm->vlib_main); - while (1) - { - lldp_intf_t *n = pool_elt_at_index (lm->intfs, - lm->intfs_timeouts - [lm->intfs_timeouts_idx]); - if (n->last_sent < 0.01 || now > n->last_sent + lm->msg_tx_interval) - { -#if LLDP_DEBUG - clib_warning ("send packet to lldp %p, if idx %d", n, - n->hw_if_index); -#endif - lldp_send_ethernet (lm, n, 0); - ++lm->intfs_timeouts_idx; - if (lm->intfs_timeouts_idx >= vec_len (lm->intfs_timeouts)) - { - lm->intfs_timeouts_idx = 0; - } - continue; - } - else - { - timeout = n->last_sent + lm->msg_tx_interval - now; - break; - } - } -#if LLDP_DEBUG - clib_warning ("DEBUG: timeout set to %f", timeout); - u8 *s = NULL; - u32 i; - vec_foreach_index (i, lm->intfs_timeouts) - { - if (i == lm->intfs_timeouts_idx) - { - s = format (s, " [%d]", lm->intfs_timeouts[i]); - } - else - { - s = format (s, " %d", lm->intfs_timeouts[i]); - } - } - clib_warning ("DEBUG: timeout schedule: %s", s); - vec_free (s); -#endif - if (event_data) - { - _vec_len (event_data) = 0; - } - } - - return 0; -} - -/* - * lldp process node declaration - */ -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE(lldp_process_node, static) = { - .function = lldp_process, - .type = VLIB_NODE_TYPE_PROCESS, - .name = "lldp-process", -}; -/* *INDENT-ON* */ - -void -lldp_schedule_intf (lldp_main_t * lm, lldp_intf_t * n) -{ - const int idx = n - lm->intfs; - u32 v; - vec_foreach_index (v, lm->intfs_timeouts) - { - if (lm->intfs_timeouts[v] == idx) - { - /* already scheduled */ - return; - } - } - n->last_sent = 0; /* ensure that a packet is sent out immediately */ - /* put the interface at the current position in the timeouts - it - * will timeout immediately */ - vec_insert (lm->intfs_timeouts, 1, lm->intfs_timeouts_idx); - lm->intfs_timeouts[lm->intfs_timeouts_idx] = n - lm->intfs; - vlib_process_signal_event (lm->vlib_main, lm->lldp_process_node_index, - LLDP_EVENT_RESCHEDULE, 0); -#if LLDP_DEBUG - clib_warning ("DEBUG: schedule interface %p, if idx %d", n, n->hw_if_index); -#endif -} - -void -lldp_unschedule_intf (lldp_main_t * lm, lldp_intf_t * n) -{ - if (!n) - { - return; - } -#if LLDP_DEBUG - clib_warning ("DEBUG: unschedule interface %p, if idx %d", n, - n->hw_if_index); -#endif - const int idx = n - lm->intfs; - u32 v; - /* remove intf index from timeouts vector */ - vec_foreach_index (v, lm->intfs_timeouts) - { - if (lm->intfs_timeouts[v] == idx) - { - vec_delete (lm->intfs_timeouts, 1, v); - break; - } - } - /* wrap current timeout index to first element if needed */ - if (lm->intfs_timeouts_idx >= vec_len (lm->intfs_timeouts)) - { - lm->intfs_timeouts_idx = 0; - } - vlib_process_signal_event (lm->vlib_main, lm->lldp_process_node_index, - LLDP_EVENT_RESCHEDULE, 0); -} - -static clib_error_t * -lldp_sw_interface_up_down (vnet_main_t * vnm, u32 sw_if_index, u32 flags) -{ - lldp_main_t *lm = &lldp_main; - vnet_hw_interface_t *hi = vnet_get_sup_hw_interface (vnm, sw_if_index); - lldp_intf_t *n = lldp_get_intf (lm, hi->hw_if_index); - if (n) - { - if (!(flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP)) - { - /* FIXME - the packet sent here isn't send properly - need to find a - * way to send the packet before interface goes down */ - lldp_send_ethernet (lm, n, 1); - lldp_unschedule_intf (lm, n); - } - } - return 0; -} - -VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION (lldp_sw_interface_up_down); - -static clib_error_t * -lldp_hw_interface_up_down (vnet_main_t * vnm, u32 hw_if_index, u32 flags) -{ - lldp_main_t *lm = &lldp_main; - lldp_intf_t *n = lldp_get_intf (lm, hw_if_index); - if (n) - { - if (flags & VNET_HW_INTERFACE_FLAG_LINK_UP) - { - lldp_schedule_intf (lm, n); - } - } - return 0; -} - -VNET_HW_INTERFACE_LINK_UP_DOWN_FUNCTION (lldp_hw_interface_up_down); - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vnet/lldp/lldp_node.h b/src/vnet/lldp/lldp_node.h deleted file mode 100644 index f9bc9599827..00000000000 --- a/src/vnet/lldp/lldp_node.h +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (c) 2011-2016 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/** - * @file - * @brief LLDP global declarations - */ -#ifndef __included_lldp_node_h__ -#define __included_lldp_node_h__ - -#include -#include -#include -#include -#include - -#include - -typedef struct lldp_intf -{ - /* hw interface index */ - u32 hw_if_index; - - /* Timers */ - f64 last_heard; - f64 last_sent; - - /* Info received from peer */ - u8 *chassis_id; - u8 *port_id; - u16 ttl; - lldp_port_id_subtype_t port_id_subtype; - lldp_chassis_id_subtype_t chassis_id_subtype; - - /* 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 -{ - /* pool of lldp-enabled interface context data */ - lldp_intf_t *intfs; - - /* rapidly find an interface by vlib hw interface index */ - uword *intf_by_hw_if_index; - - /* Background process node index */ - u32 lldp_process_node_index; - - /* interface idxs (into intfs pool) in the order of timing out */ - u32 *intfs_timeouts; - - /* index of the interface which will time out next */ - u32 intfs_timeouts_idx; - - /* packet template for sending out packets */ - vlib_packet_template_t packet_template; - - /* convenience variables */ - vlib_main_t *vlib_main; - vnet_main_t *vnet_main; - - /* system name advertised over LLDP (default is none) */ - u8 *sys_name; - - /* IEEE Std 802.1AB-2009: - * 9.2.5.6 msgTxHold - * This variable is used, as a multiplier of msgTxInterval, to determine the - * value of txTTL that is carried in LLDP frames transmitted by the LLDP - * agent. The recommended default value of msgTxHold is 4; this value can - * be changed by management to any value in the range 1 through 100. - */ - u8 msg_tx_hold; - - /* IEEE Std 802.1AB-2009: - * 9.2.5.7 msgTxInterval - * This variable defines the time interval in timer ticks between - * transmissions during normal transmission periods (i.e., txFast is zero). - * The recommended default value for msgTxInterval is 30 s; this value can - * be changed by management to any value in the range 1 through 3600. - */ - u16 msg_tx_interval; -} lldp_main_t; - -#define LLDP_MIN_TX_HOLD (1) -#define LLDP_MAX_TX_HOLD (100) -#define LLDP_MIN_TX_INTERVAL (1) -#define LLDP_MAX_TX_INTERVAL (3600) - -extern lldp_main_t lldp_main; - -/* Packet counters */ -#define foreach_lldp_error(F) \ - F(NONE, "good lldp packets (processed)") \ - F(CACHE_HIT, "good lldp packets (cache hit)") \ - F(BAD_TLV, "lldp packets with bad TLVs") \ - F(DISABLED, "lldp packets received on disabled interfaces") - -typedef enum -{ -#define F(sym, str) LLDP_ERROR_##sym, - foreach_lldp_error (F) -#undef F - LLDP_N_ERROR, -} lldp_error_t; - -/* lldp packet trace capture */ -typedef struct -{ - u32 len; - u8 data[400]; -} lldp_input_trace_t; - -typedef enum -{ - LLDP_EVENT_RESCHEDULE = 1, -} lldp_process_event_t; - -lldp_intf_t *lldp_get_intf (lldp_main_t * lm, u32 hw_if_index); -lldp_intf_t *lldp_create_intf (lldp_main_t * lm, u32 hw_if_index); -void lldp_delete_intf (lldp_main_t * lm, lldp_intf_t * n); -lldp_error_t lldp_input (vlib_main_t * vm, vlib_buffer_t * b0, u32 bi0); -u8 *lldp_input_format_trace (u8 * s, va_list * args); -void lldp_send_ethernet (lldp_main_t * lm, lldp_intf_t * n, int shutdown); -void lldp_schedule_intf (lldp_main_t * lm, lldp_intf_t * n); -void lldp_unschedule_intf (lldp_main_t * lm, lldp_intf_t * n); - -#endif /* __included_lldp_node_h__ */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vnet/lldp/lldp_output.c b/src/vnet/lldp/lldp_output.c deleted file mode 100644 index 9c171c5da7b..00000000000 --- a/src/vnet/lldp/lldp_output.c +++ /dev/null @@ -1,308 +0,0 @@ -/* - * Copyright (c) 2011-2016 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/** - * @file - * @brief LLDP packet generation implementation - */ -#include - -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) -{ - lldp_chassis_id_tlv_t *t = (lldp_chassis_id_tlv_t *) * t0p; - - lldp_tlv_set_code ((lldp_tlv_t *) t, LLDP_TLV_NAME (chassis_id)); - t->subtype = LLDP_CHASS_ID_SUBTYPE_NAME (mac_addr); - - const size_t addr_len = 6; - 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); - *t0p += STRUCT_SIZE_OF (lldp_tlv_t, head) + len; -} - -static void -lldp_add_port_id (const vnet_hw_interface_t * hw, u8 ** t0p) -{ - lldp_port_id_tlv_t *t = (lldp_port_id_tlv_t *) * t0p; - - lldp_tlv_set_code ((lldp_tlv_t *) t, LLDP_TLV_NAME (port_id)); - t->subtype = LLDP_PORT_ID_SUBTYPE_NAME (intf_name); - - const size_t name_len = vec_len (hw->name); - 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; -} - -static void -lldp_add_ttl (const lldp_main_t * lm, u8 ** t0p, int shutdown) -{ - lldp_ttl_tlv_t *t = (lldp_ttl_tlv_t *) * t0p; - lldp_tlv_set_code ((lldp_tlv_t *) t, LLDP_TLV_NAME (ttl)); - if (shutdown) - { - t->ttl = 0; - } - else - { - if ((size_t) lm->msg_tx_interval * lm->msg_tx_hold + 1 > (1 << 16) - 1) - { - t->ttl = htons ((1 << 16) - 1); - } - else - { - t->ttl = htons (lm->msg_tx_hold * lm->msg_tx_interval + 1); - } - } - const size_t len = STRUCT_SIZE_OF (lldp_ttl_tlv_t, ttl); - lldp_tlv_set_length ((lldp_tlv_t *) t, len); - *t0p += STRUCT_SIZE_OF (lldp_tlv_t, head) + len; -} - -static void -lldp_add_port_desc (const lldp_main_t * lm, lldp_intf_t * n, u8 ** t0p) -{ - const size_t len = vec_len (n->port_desc); - if (len) - { - 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_fast (t->v, n->port_desc, len); - *t0p += STRUCT_SIZE_OF (lldp_tlv_t, head) + len; - } -} - -static void -lldp_add_sys_name (const lldp_main_t * lm, u8 ** t0p) -{ - const size_t len = vec_len (lm->sys_name); - if (len) - { - 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_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) -{ - lldp_tlv_t *t = (lldp_tlv_t *) * t0p; - lldp_tlv_set_code (t, LLDP_TLV_NAME (pdu_end)); - lldp_tlv_set_length (t, 0); - *t0p += STRUCT_SIZE_OF (lldp_tlv_t, head); -} - -static void -lldp_add_tlvs (lldp_main_t * lm, vnet_hw_interface_t * hw, u8 ** t0p, - int shutdown, lldp_intf_t * n) -{ - lldp_add_chassis_id (hw, t0p); - lldp_add_port_id (hw, 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); -} - -/* - * send a lldp pkt on an ethernet interface - */ -void -lldp_send_ethernet (lldp_main_t * lm, lldp_intf_t * n, int shutdown) -{ - u32 *to_next; - ethernet_header_t *h0; - vnet_hw_interface_t *hw; - u32 bi0; - vlib_buffer_t *b0; - u8 *t0; - vlib_frame_t *f; - vlib_main_t *vm = lm->vlib_main; - vnet_main_t *vnm = lm->vnet_main; - - /* - * see lldp_template_init() to understand what's already painted - * into the buffer by the packet template mechanism - */ - h0 = vlib_packet_template_get_packet (vm, &lm->packet_template, &bi0); - - if (!h0) - return; - - /* Add the interface's ethernet source address */ - hw = vnet_get_hw_interface (vnm, n->hw_if_index); - - clib_memcpy_fast (h0->src_address, hw->hw_address, - vec_len (hw->hw_address)); - - u8 *data = ((u8 *) h0) + sizeof (*h0); - t0 = data; - - /* add TLVs */ - lldp_add_tlvs (lm, hw, &t0, shutdown, n); - - /* Set the outbound packet length */ - b0 = vlib_get_buffer (vm, bi0); - b0->current_length = sizeof (*h0) + t0 - data; - - /* And the outbound interface */ - vnet_buffer (b0)->sw_if_index[VLIB_TX] = hw->sw_if_index; - - /* And output the packet on the correct interface */ - f = vlib_get_frame_to_node (vm, hw->output_node_index); - to_next = vlib_frame_vector_args (f); - to_next[0] = bi0; - f->n_vectors = 1; - - vlib_put_frame_to_node (vm, hw->output_node_index, f); - n->last_sent = vlib_time_now (vm); -} - -void -lldp_delete_intf (lldp_main_t * lm, lldp_intf_t * n) -{ - if (n) - { - lldp_unschedule_intf (lm, n); - hash_unset (lm->intf_by_hw_if_index, n->hw_if_index); - 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); - } -} - -static clib_error_t * -lldp_template_init (vlib_main_t * vm) -{ - lldp_main_t *lm = &lldp_main; - - /* Create the ethernet lldp packet template */ - { - ethernet_header_t h; - - clib_memset (&h, 0, sizeof (h)); - - /* - * Send to 01:80:C2:00:00:0E - propagation constrained to a single - * physical link - stopped by all type of bridge - */ - h.dst_address[0] = 0x01; - h.dst_address[1] = 0x80; - h.dst_address[2] = 0xC2; - /* 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) */ - - h.type = htons (ETHERNET_TYPE_802_1_LLDP); - - vlib_packet_template_init (vm, &lm->packet_template, - /* data */ &h, sizeof (h), - /* alloc chunk size */ 8, "lldp-ethernet"); - } - - return 0; -} - -VLIB_INIT_FUNCTION (lldp_template_init); - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vnet/lldp/lldp_protocol.h b/src/vnet/lldp/lldp_protocol.h deleted file mode 100644 index e641b26e20d..00000000000 --- a/src/vnet/lldp/lldp_protocol.h +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (c) 2011-2016 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef __included_lldp_protocol_h__ -#define __included_lldp_protocol_h__ -/** - * @file - * @brief LLDP protocol declarations - */ -#include - -/* - * optional TLV codes. - */ -#define foreach_lldp_optional_tlv_type(F) \ - F (4, port_desc, "Port Description") \ - F (5, sys_name, "System name") \ - F (6, sys_desc, "System Description") \ - F (7, sys_caps, "System Capabilities") \ - F (8, mgmt_addr, "Management Address") \ - F (127, org_spec, "Organizationally Specific TLV") - -/* - * all TLV codes. - */ -#define foreach_lldp_tlv_type(F) \ - F (0, pdu_end, "End of LLDPDU") \ - F (1, chassis_id, "Chassis ID") \ - F (2, port_id, "Port ID") \ - F (3, ttl, "Time To Live") \ - foreach_lldp_optional_tlv_type (F) - -#define LLDP_TLV_NAME(t) LLDP_TLV_##t - -typedef enum -{ -#define F(n, t, s) LLDP_TLV_NAME (t) = n, - foreach_lldp_tlv_type (F) -#undef F -} lldp_tlv_code_t; - -struct lldp_tlv_head -{ - u8 byte1; /* contains TLV code in the upper 7 bits + MSB of length */ - u8 byte2; /* contains the lower bits of length */ -}; - -/* *INDENT-OFF* */ -typedef CLIB_PACKED (struct { - struct lldp_tlv_head head; - u8 v[0]; -}) lldp_tlv_t; -/* *INDENT-ON* */ - -lldp_tlv_code_t lldp_tlv_get_code (const lldp_tlv_t * tlv); -void lldp_tlv_set_code (lldp_tlv_t * tlv, lldp_tlv_code_t code); -u16 lldp_tlv_get_length (const lldp_tlv_t * tlv); -void lldp_tlv_set_length (lldp_tlv_t * tlv, u16 length); - -#define foreach_chassis_id_subtype(F) \ - F (0, reserved, "Reserved") \ - F (1, chassis_comp, "Chassis component") \ - F (2, intf_alias, "Interface alias") \ - F (3, port_comp, "Port component") \ - F (4, mac_addr, "MAC address") \ - F (5, net_addr, "Network address") \ - F (6, intf_name, "Interface name") \ - F (7, local, "Locally assigned") - -#define LLDP_CHASS_ID_SUBTYPE_NAME(t) LLDP_CHASS_ID_SUBTYPE_##t -#define LLDP_MIN_CHASS_ID_LEN (1) -#define LLDP_MAX_CHASS_ID_LEN (255) - -typedef enum -{ -#define F(n, t, s) LLDP_CHASS_ID_SUBTYPE_NAME (t) = n, - foreach_chassis_id_subtype (F) -#undef F -} lldp_chassis_id_subtype_t; - -/* *INDENT-OFF* */ -typedef CLIB_PACKED (struct { - struct lldp_tlv_head head; - u8 subtype; - u8 id[0]; -}) lldp_chassis_id_tlv_t; -/* *INDENT-ON* */ - -#define foreach_port_id_subtype(F) \ - F (0, reserved, "Reserved") \ - F (1, intf_alias, "Interface alias") \ - F (2, port_comp, "Port component") \ - F (3, mac_addr, "MAC address") \ - F (4, net_addr, "Network address") \ - F (5, intf_name, "Interface name") \ - F (6, agent_circuit_id, "Agent circuit ID") \ - F (7, local, "Locally assigned") - -#define LLDP_PORT_ID_SUBTYPE_NAME(t) LLDP_PORT_ID_SUBTYPE_##t -#define LLDP_MIN_PORT_ID_LEN (1) -#define LLDP_MAX_PORT_ID_LEN (255) - -typedef enum -{ -#define F(n, t, s) LLDP_PORT_ID_SUBTYPE_NAME (t) = n, - foreach_port_id_subtype (F) -#undef F -} lldp_port_id_subtype_t; - -/* *INDENT-OFF* */ -typedef CLIB_PACKED (struct { - struct lldp_tlv_head head; - u8 subtype; - u8 id[0]; -}) lldp_port_id_tlv_t; - -typedef CLIB_PACKED (struct { - struct lldp_tlv_head head; - u16 ttl; -}) lldp_ttl_tlv_t; -/* *INDENT-ON* */ - -#endif /* __included_lldp_protocol_h__ */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vnet/vnet_all_api_h.h b/src/vnet/vnet_all_api_h.h index 88eaa851136..9daf5e95b4d 100644 --- a/src/vnet/vnet_all_api_h.h +++ b/src/vnet/vnet_all_api_h.h @@ -44,7 +44,6 @@ #include #include #include -#include #include #include #include diff --git a/src/vpp/api/custom_dump.c b/src/vpp/api/custom_dump.c index 87729721fea..46beb685810 100644 --- a/src/vpp/api/custom_dump.c +++ b/src/vpp/api/custom_dump.c @@ -3410,47 +3410,6 @@ static void *vl_api_app_namespace_add_del_t_print FINISH; } -static void *vl_api_sw_interface_set_lldp_t_print - (vl_api_sw_interface_set_lldp_t * mp, void *handle) -{ - u8 *s; - u8 null_data[256]; - - clib_memset (null_data, 0, sizeof (null_data)); - - s = format (0, "SCRIPT: sw_interface_set_lldp "); - s = format (s, "sw_if_index %d ", (mp->sw_if_index)); - - if (memcmp (&mp->port_desc, null_data, sizeof (mp->port_desc))) - s = format (s, "port_desc %s ", mp->port_desc); - - if (memcmp (mp->mgmt_ip4, null_data, sizeof (mp->mgmt_ip4))) - s = format (s, "mgmt_ip4 %U ", format_ip4_address, mp->mgmt_ip4); - - if (memcmp (mp->mgmt_ip6, null_data, sizeof (mp->mgmt_ip6))) - s = format (s, "mgmt_ip6 %U ", format_ip6_address, mp->mgmt_ip6); - - if (memcmp (mp->mgmt_oid, null_data, sizeof (mp->mgmt_oid))) - s = format (s, "mgmt_oid %s ", mp->mgmt_oid); - - if (mp->enable == 0) - s = format (s, "disable "); - - FINISH; -} - -static void *vl_api_lldp_config_t_print - (vl_api_lldp_config_t * mp, void *handle) -{ - u8 *s; - - s = format (0, "SCRIPT: lldp_config "); - s = format (s, "system_name %s ", mp->system_name); - s = format (s, "tx_hold %d ", (mp->tx_hold)); - s = format (s, "tx_interval %d ", (mp->tx_interval)); - FINISH; -} - static void *vl_api_session_rule_add_del_t_print (vl_api_session_rule_add_del_t * mp, void *handle) { @@ -3717,8 +3676,6 @@ _(P2P_ETHERNET_ADD, p2p_ethernet_add) \ _(P2P_ETHERNET_DEL, p2p_ethernet_del) \ _(TCP_CONFIGURE_SRC_ADDRESSES, tcp_configure_src_addresses) \ _(APP_NAMESPACE_ADD_DEL, app_namespace_add_del) \ -_(LLDP_CONFIG, lldp_config) \ -_(SW_INTERFACE_SET_LLDP, sw_interface_set_lldp) \ _(SESSION_RULE_ADD_DEL, session_rule_add_del) \ _(OUTPUT_ACL_SET_INTERFACE, output_acl_set_interface) \ _(QOS_RECORD_ENABLE_DISABLE, qos_record_enable_disable) \ -- cgit 1.2.3-korg