diff --git a/recipes-daemons/lldpd/files/0001-lldpd-client-add-show-interfaces-cmd-from-upstream.patch b/recipes-daemons/lldpd/files/0001-lldpd-client-add-show-interfaces-cmd-from-upstream.patch new file mode 100644 index 0000000..51a185f --- /dev/null +++ b/recipes-daemons/lldpd/files/0001-lldpd-client-add-show-interfaces-cmd-from-upstream.patch @@ -0,0 +1,296 @@ +From 0e355867f211a922c5b21ddbbb073eb2c35430b9 Mon Sep 17 00:00:00 2001 +From: "Sar Ashki, Babak" +Date: Mon, 24 Feb 2020 06:01:03 -0800 +Subject: [PATCH] lldpd client add show interfaces cmd from upstream + +commit a54f6012efff77c966f533b8ef35b8627e3c8212 +--- + src/client/client.h | 2 + + src/client/display.c | 99 ++++++++++++++++++++++++++++++++++------- + src/client/lldpcli.8.in | 20 +++++++++ + src/client/show.c | 44 ++++++++++++++++++ + src/daemon/lldpd.c | 1 + + 5 files changed, 151 insertions(+), 15 deletions(-) + +diff --git a/src/client/client.h b/src/client/client.h +index e3ee352..8da3e3f 100644 +--- a/src/client/client.h ++++ b/src/client/client.h +@@ -131,6 +131,8 @@ void display_interfaces_stats(lldpctl_conn_t *, struct writer *, + struct cmd_env *); + void display_interface_stats(lldpctl_conn_t *, struct writer *, + lldpctl_atom_t *); ++void display_local_interfaces(lldpctl_conn_t *, struct writer *, ++ struct cmd_env *, int, int); + + + +diff --git a/src/client/display.c b/src/client/display.c +index cbd0e31..2769890 100644 +--- a/src/client/display.c ++++ b/src/client/display.c +@@ -349,7 +349,8 @@ display_port(struct writer *w, lldpctl_atom_t *port, int details) + + tag_datatag(w, "descr", "PortDescr", + lldpctl_atom_get_str(port, lldpctl_k_port_descr)); +- if (details) ++ if (details && ++ lldpctl_atom_get_int(port, lldpctl_k_port_ttl) > 0) + tag_datatag(w, "ttl", "TTL", + lldpctl_atom_get_str(port, lldpctl_k_port_ttl)); + +@@ -473,6 +474,38 @@ display_port(struct writer *w, lldpctl_atom_t *port, int details) + tag_end(w); + } + ++static void ++display_local_ttl(struct writer *w, lldpctl_conn_t *conn, int details) ++{ ++ char *ttl; ++ long int tx_hold; ++ long int tx_interval; ++ ++ lldpctl_atom_t *configuration; ++ configuration = lldpctl_get_configuration(conn); ++ if (!configuration) { ++ log_warnx("lldpctl", "not able to get configuration. %s", ++ lldpctl_last_strerror(conn)); ++ return; ++ } ++ ++ tx_hold = lldpctl_atom_get_int(configuration, lldpctl_k_config_tx_hold); ++ tx_interval = lldpctl_atom_get_int(configuration, lldpctl_k_config_tx_interval); ++ ++ if (asprintf(&ttl, "%lu", tx_hold*tx_interval) == -1) { ++ log_warnx("lldpctl", "not enough memory to build TTL."); ++ goto end; ++ } ++ ++ tag_start(w, "ttl", "TTL"); ++ tag_attr(w, "ttl", "", ttl); ++ tag_end(w); ++ free(ttl); ++end: ++ lldpctl_atom_dec_ref(configuration); ++ return; ++} ++ + static void + display_vlans(struct writer *w, lldpctl_atom_t *port) + { +@@ -582,43 +615,51 @@ display_local_chassis(lldpctl_conn_t *conn, struct writer *w, + + void + display_interface(lldpctl_conn_t *conn, struct writer *w, int hidden, +- lldpctl_atom_t *iface, lldpctl_atom_t *neighbor, int details, int protocol) ++ lldpctl_atom_t *iface, lldpctl_atom_t *port, int details, int protocol) + { ++ int local = 0; ++ + if (!hidden && +- lldpctl_atom_get_int(neighbor, lldpctl_k_port_hidden)) ++ lldpctl_atom_get_int(port, lldpctl_k_port_hidden)) + return; + + /* user might have specified protocol to filter on display */ + if ((protocol != LLDPD_MODE_MAX) && +- (protocol != lldpctl_atom_get_int(neighbor, lldpctl_k_port_protocol))) ++ (protocol != lldpctl_atom_get_int(port, lldpctl_k_port_protocol))) + return; + +- lldpctl_atom_t *chassis = lldpctl_atom_get(neighbor, lldpctl_k_port_chassis); ++ /* Infer local / remote port from the port index (remote == 0) */ ++ local = lldpctl_atom_get_int(port, lldpctl_k_port_index)>0?1:0; ++ ++ lldpctl_atom_t *chassis = lldpctl_atom_get(port, lldpctl_k_port_chassis); + + tag_start(w, "interface", "Interface"); + tag_attr(w, "name", "", + lldpctl_atom_get_str(iface, lldpctl_k_interface_name)); + tag_attr(w, "via" , "via", +- lldpctl_atom_get_str(neighbor, lldpctl_k_port_protocol)); ++ lldpctl_atom_get_str(port, lldpctl_k_port_protocol)); + if (details > DISPLAY_BRIEF) { +- tag_attr(w, "rid" , "RID", +- lldpctl_atom_get_str(chassis, lldpctl_k_chassis_index)); ++ if (!local) ++ tag_attr(w, "rid" , "RID", ++ lldpctl_atom_get_str(chassis, lldpctl_k_chassis_index)); + tag_attr(w, "age" , "Time", +- display_age(lldpctl_atom_get_int(neighbor, lldpctl_k_port_age))); ++ display_age(lldpctl_atom_get_int(port, lldpctl_k_port_age))); + } + + display_chassis(w, chassis, details); +- display_port(w, neighbor, details); ++ display_port(w, port, details); ++ if (details && local) ++ display_local_ttl(w, conn, details); + if (details == DISPLAY_DETAILS) { +- display_vlans(w, neighbor); +- display_ppvids(w, neighbor); +- display_pids(w, neighbor); +- display_med(w, neighbor, chassis); ++ display_vlans(w, port); ++ display_ppvids(w, port); ++ display_pids(w, port); ++ display_med(w, port, chassis); + } + + lldpctl_atom_dec_ref(chassis); + +- display_custom_tlvs(w, neighbor); ++ display_custom_tlvs(w, port); + + tag_end(w); + } +@@ -675,6 +716,34 @@ display_interfaces(lldpctl_conn_t *conn, struct writer *w, + tag_end(w); + } + ++ ++/** ++ * Display information about local interfaces. ++ * ++ * @param conn Connection to lldpd. ++ * @param w Writer. ++ * @param hidden Whatever to show hidden ports. ++ * @param env Environment from which we may find the list of ports. ++ * @param details Level of details we need (DISPLAY_*). ++ */ ++void ++display_local_interfaces(lldpctl_conn_t *conn, struct writer *w, ++ struct cmd_env *env, ++ int hidden, int details) ++{ ++ lldpctl_atom_t *iface; ++ int protocol = LLDPD_MODE_MAX; ++ ++ tag_start(w, "lldp", "LLDP interfaces"); ++ while ((iface = cmd_iterate_on_interfaces(conn, env))) { ++ lldpctl_atom_t *port; ++ port = lldpctl_get_port(iface); ++ display_interface(conn, w, hidden, iface, port, details, protocol); ++ lldpctl_atom_dec_ref(port); ++ } ++ tag_end(w); ++ } ++ + void + display_stat(struct writer *w, const char *tag, const char *descr, + long unsigned int cnt) +diff --git a/src/client/lldpcli.8.in b/src/client/lldpcli.8.in +index 1a20fa8..8a4123e 100644 +--- a/src/client/lldpcli.8.in ++++ b/src/client/lldpcli.8.in +@@ -134,6 +134,26 @@ one or several ports, the information displayed is limited to the + given list of ports. + .Ed + ++.Cd show interfaces ++.Op ports Ar ethX Op ,... ++.Op Cd details | summary ++.Op Cd hidden ++.Bd -ragged -offset XXXXXX ++Display information about each local interface known by ++.Xr lldpd 8 ++daemon. With ++.Cd summary , ++only the name and the port description of each local interface will be ++displayed. On the other hand, with ++.Cd details , ++all available information will be displayed, giving a verbose ++view. When using ++.Cd hidden , ++also display local ports hidden by the smart filter. When specifying ++one or several ports, the information displayed is limited to the ++given list of ports. ++.Ed ++ + .Cd show chassis + .Op Cd details | summary + .Bd -ragged -offset XXXXXX +diff --git a/src/client/show.c b/src/client/show.c +index fa704b8..8ba8acb 100644 +--- a/src/client/show.c ++++ b/src/client/show.c +@@ -48,6 +48,35 @@ cmd_show_neighbors(struct lldpctl_conn_t *conn, struct writer *w, + return 1; + } + ++/** ++ * Show interfaces. ++ * ++ * The environment will contain the following keys: ++ * - C{ports} list of ports we want to restrict showing. ++ * - C{hidden} if we should show hidden ports. ++ * - C{summary} if we want to show only a summary ++ * - C{detailed} for a detailed overview ++ */ ++static int ++cmd_show_interfaces(struct lldpctl_conn_t *conn, struct writer *w, ++ struct cmd_env *env, void *arg) ++{ ++ log_debug("lldpctl", "show interfaces data (%s) %s hidden interfaces", ++ cmdenv_get(env, "summary")?"summary": ++ cmdenv_get(env, "detailed")?"detailed": ++ "normal", cmdenv_get(env, "hidden")?"with":"without"); ++ if (cmdenv_get(env, "ports")) ++ log_debug("lldpctl", "restrict to the following ports: %s", ++ cmdenv_get(env, "ports")); ++ ++ display_local_interfaces(conn, w, env, !!cmdenv_get(env, "hidden"), ++ cmdenv_get(env, "summary")?DISPLAY_BRIEF: ++ cmdenv_get(env, "detailed")?DISPLAY_DETAILS: ++ DISPLAY_NORMAL); ++ ++ return 1; ++} ++ + /** + * Show chassis. + * +@@ -286,6 +315,12 @@ register_commands_show(struct cmd_node *root) + "Show neighbors data", + NULL, NULL, NULL); + ++ struct cmd_node *interfaces = commands_new( ++ show, ++ "interfaces", ++ "Show interfaces data", ++ NULL, NULL, NULL); ++ + struct cmd_node *chassis = commands_new( + show, + "chassis", +@@ -306,6 +341,15 @@ register_commands_show(struct cmd_node *root) + + register_common_commands(neighbors, 1); + ++ /* Interfaces data */ ++ commands_new(interfaces, ++ NEWLINE, ++ "Show interfaces data", ++ NULL, cmd_show_interfaces, NULL); ++ ++ cmd_restrict_ports(interfaces); ++ register_common_commands(interfaces, 0); ++ + /* Chassis data */ + commands_new(chassis, + NEWLINE, +diff --git a/src/daemon/lldpd.c b/src/daemon/lldpd.c +index 97df38e..8ce38a9 100644 +--- a/src/daemon/lldpd.c ++++ b/src/daemon/lldpd.c +@@ -1037,6 +1037,7 @@ lldpd_send(struct lldpd_hardware *hardware) + cfg->g_protocols[i].name); + cfg->g_protocols[i].send(cfg, + hardware); ++ hardware->h_lport.p_protocol = cfg->g_protocols[i].mode; + sent++; + break; + } +-- +2.23.0 + diff --git a/recipes-daemons/lldpd/files/0002-Clear-station-bit-if-any-other-capability-is-enabled.patch b/recipes-daemons/lldpd/files/0002-Clear-station-bit-if-any-other-capability-is-enabled.patch new file mode 100644 index 0000000..47b73da --- /dev/null +++ b/recipes-daemons/lldpd/files/0002-Clear-station-bit-if-any-other-capability-is-enabled.patch @@ -0,0 +1,27 @@ +From 461e728e8bd71529c09a113f2610766be61aa50a Mon Sep 17 00:00:00 2001 +From: "Sar Ashki, Babak" +Date: Mon, 24 Feb 2020 05:06:57 -0800 +Subject: [PATCH 2/2] Clear station bit if any other capability is enabled + +From stx.3.0 b2ed14edc66c7876cd9239a346b92630403e996c +--- + src/daemon/interfaces.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/src/daemon/interfaces.c b/src/daemon/interfaces.c +index d004c70..b870a46 100644 +--- a/src/daemon/interfaces.c ++++ b/src/daemon/interfaces.c +@@ -328,6 +328,9 @@ interfaces_helper_chassis(struct lldpd *cfg, + if ((LOCAL_CHASSIS(cfg)->c_cap_available & LLDP_CAP_STATION) && + (LOCAL_CHASSIS(cfg)->c_cap_enabled == 0)) + LOCAL_CHASSIS(cfg)->c_cap_enabled = LLDP_CAP_STATION; ++ else if (LOCAL_CHASSIS(cfg)->c_cap_enabled != LLDP_CAP_STATION) ++ LOCAL_CHASSIS(cfg)->c_cap_enabled &= ~LLDP_CAP_STATION; ++ + + if (LOCAL_CHASSIS(cfg)->c_id != NULL && + LOCAL_CHASSIS(cfg)->c_id_subtype == LLDP_CHASSISID_SUBTYPE_LLADDR) +-- +2.23.0 + diff --git a/recipes-daemons/lldpd/files/i40e-lldp-configure.sh b/recipes-daemons/lldpd/files/i40e-lldp-configure.sh new file mode 100644 index 0000000..4a5e8a4 --- /dev/null +++ b/recipes-daemons/lldpd/files/i40e-lldp-configure.sh @@ -0,0 +1,141 @@ +#!/bin/bash +################################################################################ +# Copyright (c) 2016 Wind River Systems, Inc. +# +# SPDX-License-Identifier: Apache-2.0 +# +################################################################################ + +# Certain i40e network devices (XL710 Fortville) have an internal firmware LLDP +# agent enabled by default. This can prevent LLDP PDUs from being processed by +# the driver and any upper layer agents. +# +# This script allows a user to enable and disable the internal LLDP agent. +# +# Note: debugfs must be enabled in the kernel +# +# To enable: +# ./i40e-lldp-configure.sh start +# +# To disable: +# ./i40e-lldp-configure.sh stop + +PROGNAME=$(basename $0) +DEBUGFS_PATH=/sys/kernel/debug +DEBUGFS_I40_DEVICES_PATH=$DEBUGFS_PATH/i40e +LLDP_COMMAND=lldp + +function log { + local MSG="${PROGNAME}: $1" + logger -p notice "${MSG}" +} + +function err { + local MSG="${PROGNAME}: $1" + logger -p error "${MSG}" +} + +function configure_device { + local DEVICE=$1 + local ACTION=$2 + local DEVICE_PATH=${DEBUGFS_I40_DEVICES}/${DEVICE} + + if [ ! -d ${DEVICE_PATH} ]; then + return 1 + fi + + echo "${LLDP_COMMAND} ${ACTION}" > ${DEVICE_PATH}/command + RET=$? + + if [ ${RET} -ne 0 ]; then + err "Failed to ${ACTION} internal LLDP agent for device ${DEVICE}" + return ${RET} + fi + + log "${ACTION} internal LLDP agent for device ${DEVICE}" + return ${RET} +} + +function is_debugfs_mounted { + if grep -qs "${DEBUGFS_PATH}" /proc/mounts; then + return 0 + fi + return 1 +} + +function mount_debugfs { + mount -t debugfs none ${DEBUGFS_PATH} +} + +function unmount_debugfs { + umount ${DEBUGFS_PATH} +} + +function scan_devices { + local ACTION=$1 + local DEBUGFS_MOUNTED="false" + local DEVICES=${DEBUGFS_I40_DEVICES_PATH}/* + + if is_debugfs_mounted; then + DEBUGFS_MOUNTED="true" + fi + + if [ ${DEBUGFS_MOUNTED} = "false" ]; then + mount_debugfs + RET=$? + if [ ${RET} -ne 0 ]; then + err "Failed to mount debugfs" + return ${RET} + fi + log "Mounted debugfs" + fi + + for DEVICE in $DEVICES; do + configure_device ${DEVICE} ${ACTION} + done + + if [ ${DEBUGFS_MOUNTED} = "false" ]; then + unmount_debugfs + RET=$? + if [ ${RET} -ne 0 ]; then + err "Failed to unmount debugfs" + return ${RET} + fi + log "Unmounted debugfs" + fi + + return 0 +} + +function start { + scan_devices start + return $? +} + +function stop { + scan_devices stop + return $? +} + +function status { + return 0 +} + +case "$1" in + start) + start + ;; + stop) + stop + ;; + restart) + stop + start + ;; + status) + status + ;; + *) + echo "Usage: $0 {start|stop|restart|status}" + exit 1 +esac diff --git a/recipes-daemons/lldpd/files/lldpd-clear-station.patch b/recipes-daemons/lldpd/files/lldpd-clear-station.patch new file mode 100644 index 0000000..6ab09f0 --- /dev/null +++ b/recipes-daemons/lldpd/files/lldpd-clear-station.patch @@ -0,0 +1,39 @@ +From b2ed14edc66c7876cd9239a346b92630403e996c Mon Sep 17 00:00:00 2001 +From: Steven Webster +Date: Sun, 18 Jun 2017 22:23:49 -0400 +Subject: [PATCH 1/1] Clear station bit if any other capability is enabled + +--- + src/daemon/interfaces.c | 2 ++ + src/daemon/lldpd.c | 2 ++ + 2 files changed, 4 insertions(+) + +diff --git a/src/daemon/interfaces.c b/src/daemon/interfaces.c +index ec81721..4923049 100644 +--- a/src/daemon/interfaces.c ++++ b/src/daemon/interfaces.c +@@ -309,6 +309,8 @@ interfaces_helper_chassis(struct lldpd *cfg, + if ((LOCAL_CHASSIS(cfg)->c_cap_available & LLDP_CAP_STATION) && + (LOCAL_CHASSIS(cfg)->c_cap_enabled == 0)) + LOCAL_CHASSIS(cfg)->c_cap_enabled = LLDP_CAP_STATION; ++ else if (LOCAL_CHASSIS(cfg)->c_cap_enabled != LLDP_CAP_STATION) ++ LOCAL_CHASSIS(cfg)->c_cap_enabled &= ~LLDP_CAP_STATION; + + if (LOCAL_CHASSIS(cfg)->c_id != NULL && + LOCAL_CHASSIS(cfg)->c_id_subtype == LLDP_CHASSISID_SUBTYPE_LLADDR) +diff --git a/src/daemon/lldpd.c b/src/daemon/lldpd.c +index c815705..dac633f 100644 +--- a/src/daemon/lldpd.c ++++ b/src/daemon/lldpd.c +@@ -1152,6 +1152,8 @@ lldpd_update_localchassis(struct lldpd *cfg) + if ((LOCAL_CHASSIS(cfg)->c_cap_available & LLDP_CAP_STATION) && + (LOCAL_CHASSIS(cfg)->c_cap_enabled == 0)) + LOCAL_CHASSIS(cfg)->c_cap_enabled = LLDP_CAP_STATION; ++ else if (LOCAL_CHASSIS(cfg)->c_cap_enabled != LLDP_CAP_STATION) ++ LOCAL_CHASSIS(cfg)->c_cap_enabled &= ~LLDP_CAP_STATION; + + /* Set chassis ID if needed. This is only done if chassis ID + has not been set previously (with the MAC address of an +-- +1.8.3.1 + diff --git a/recipes-daemons/lldpd/files/lldpd-create-run-dir.patch b/recipes-daemons/lldpd/files/lldpd-create-run-dir.patch new file mode 100644 index 0000000..a4e9d00 --- /dev/null +++ b/recipes-daemons/lldpd/files/lldpd-create-run-dir.patch @@ -0,0 +1,12 @@ +Index: lldpd-0.9.0/src/daemon/lldpd.service.in +=================================================================== +--- lldpd-0.9.0.orig/src/daemon/lldpd.service.in ++++ lldpd-0.9.0/src/daemon/lldpd.service.in +@@ -9,6 +9,7 @@ Type=notify + NotifyAccess=main + EnvironmentFile=-/etc/default/lldpd + EnvironmentFile=-/etc/sysconfig/lldpd ++ExecStartPre=/bin/mkdir -p /var/run/lldpd + ExecStart=@sbindir@/lldpd $DAEMON_ARGS $LLDPD_OPTIONS + Restart=on-failure + diff --git a/recipes-daemons/lldpd/files/lldpd-i40e-disable.patch b/recipes-daemons/lldpd/files/lldpd-i40e-disable.patch new file mode 100644 index 0000000..1262e94 --- /dev/null +++ b/recipes-daemons/lldpd/files/lldpd-i40e-disable.patch @@ -0,0 +1,12 @@ +Index: lldpd-0.9.0/src/daemon/lldpd.service.in +=================================================================== +--- lldpd-0.9.0.orig/src/daemon/lldpd.service.in ++++ lldpd-0.9.0/src/daemon/lldpd.service.in +@@ -10,6 +10,7 @@ + EnvironmentFile=-/etc/default/lldpd + EnvironmentFile=-/etc/sysconfig/lldpd + ExecStartPre=/bin/mkdir -p /var/run/lldpd ++ExecStartPre=/etc/init.d/i40e-lldp-configure.sh stop + ExecStart=@sbindir@/lldpd $DAEMON_ARGS $LLDPD_OPTIONS + Restart=on-failure + \ No newline at end of file diff --git a/recipes-daemons/lldpd/files/lldpd-interface-show.patch b/recipes-daemons/lldpd/files/lldpd-interface-show.patch new file mode 100644 index 0000000..8fb52a0 --- /dev/null +++ b/recipes-daemons/lldpd/files/lldpd-interface-show.patch @@ -0,0 +1,206 @@ +--- + src/client/client.h | 2 + + src/client/display.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++- + src/client/show.c | 44 ++++++++++++++++++++++++++++++++++++++ + src/lib/atoms/port.c | 7 ++++++ + src/lib/lldpctl.h | 1 + 5 files changed, 112 insertions(+), 1 deletion(-) + +--- a/src/client/client.h ++++ b/src/client/client.h +@@ -115,6 +115,8 @@ char* totag(const char *); + #define DISPLAY_DETAILS 3 + void display_interfaces(lldpctl_conn_t *, struct writer *, + struct cmd_env *, int, int); ++void display_local_interfaces(lldpctl_conn_t *, struct writer *, ++ struct cmd_env *, int, int); + void display_interface(lldpctl_conn_t *, struct writer *, int, + lldpctl_atom_t *, lldpctl_atom_t *, int, int); + void display_local_chassis(lldpctl_conn_t *, struct writer *, +--- a/src/client/display.c ++++ b/src/client/display.c +@@ -344,12 +344,23 @@ display_port(struct writer *w, lldpctl_a + tag_datatag(w, "descr", "PortDescr", + lldpctl_atom_get_str(port, lldpctl_k_port_descr)); + ++ tag_datatag(w, "ttl", "Ttl", ++ lldpctl_atom_get_str(port, lldpctl_k_port_ttl)); ++ + /* Dot3 */ + if (details == DISPLAY_DETAILS) { + tag_datatag(w, "mfs", "MFS", + lldpctl_atom_get_str(port, lldpctl_k_port_dot3_mfs)); +- tag_datatag(w, "aggregation", "Port is aggregated. PortAggregID", ++ ++ long int lag_id = lldpctl_atom_get_int(port, ++ lldpctl_k_port_dot3_aggregid); ++ tag_start(w, "link-aggregation", "LinkAgg"); ++ tag_attr(w, "supported", "supported", "yes"); ++ tag_attr(w, "enabled", "enabled", ++ (lag_id > 0)?"yes":"no"); ++ tag_datatag(w, "aggregation", "PortAggregID", + lldpctl_atom_get_str(port, lldpctl_k_port_dot3_aggregid)); ++ tag_end(w); + + long int autoneg_support, autoneg_enabled, autoneg_advertised; + autoneg_support = lldpctl_atom_get_int(port, +@@ -663,6 +674,52 @@ display_interfaces(lldpctl_conn_t *conn, + lldpctl_atom_dec_ref(port); + } + tag_end(w); ++} ++ ++/** ++ * Display information about local interfaces. ++ * ++ * @param conn Connection to lldpd. ++ * @param w Writer. ++ * @param hidden Whatever to show hidden ports. ++ * @param env Environment from which we may find the list of ports. ++ * @param details Level of details we need (DISPLAY_*). ++ */ ++void ++display_local_interfaces(lldpctl_conn_t *conn, struct writer *w, ++ struct cmd_env *env, ++ int hidden, int details) ++{ ++ lldpctl_atom_t *iface; ++ int protocol = LLDPD_MODE_MAX; ++ const char *proto_str; ++ ++ /* user might have specified protocol to filter display results */ ++ proto_str = cmdenv_get(env, "protocol"); ++ ++ if (proto_str) { ++ log_debug("display", "filter protocol: %s ", proto_str); ++ ++ protocol = 0; ++ for (lldpctl_map_t *protocol_map = ++ lldpctl_key_get_map(lldpctl_k_port_protocol); ++ protocol_map->string; ++ protocol_map++) { ++ if (!strcasecmp(proto_str, protocol_map->string)) { ++ protocol = protocol_map->value; ++ break; ++ } ++ } ++ } ++ ++ tag_start(w, "lldp", "LLDP interfaces"); ++ while ((iface = cmd_iterate_on_interfaces(conn, env))) { ++ lldpctl_atom_t *port; ++ port = lldpctl_get_port(iface); ++ display_interface(conn, w, hidden, iface, port, details, protocol); ++ lldpctl_atom_dec_ref(port); ++ } ++ tag_end(w); + } + + void +--- a/src/client/show.c ++++ b/src/client/show.c +@@ -48,6 +48,35 @@ cmd_show_neighbors(struct lldpctl_conn_t + } + + /** ++ * Show interfaces. ++ * ++ * The environment will contain the following keys: ++ * - C{ports} list of ports we want to restrict showing. ++ * - C{hidden} if we should show hidden ports. ++ * - C{summary} if we want to show only a summary ++ * - C{detailed} for a detailed overview ++ */ ++static int ++cmd_show_interfaces(struct lldpctl_conn_t *conn, struct writer *w, ++ struct cmd_env *env, void *arg) ++{ ++ log_debug("lldpctl", "show interfaces data (%s) %s hidden interfaces", ++ cmdenv_get(env, "summary")?"summary": ++ cmdenv_get(env, "detailed")?"detailed": ++ "normal", cmdenv_get(env, "hidden")?"with":"without"); ++ if (cmdenv_get(env, "ports")) ++ log_debug("lldpctl", "restrict to the following ports: %s", ++ cmdenv_get(env, "ports")); ++ ++ display_local_interfaces(conn, w, env, !!cmdenv_get(env, "hidden"), ++ cmdenv_get(env, "summary")?DISPLAY_BRIEF: ++ cmdenv_get(env, "detailed")?DISPLAY_DETAILS: ++ DISPLAY_NORMAL); ++ ++ return 1; ++} ++ ++/** + * Show chassis. + * + * The environment will contain the following keys: +@@ -269,6 +298,12 @@ register_commands_show(struct cmd_node * + "Show neighbors data", + NULL, NULL, NULL); + ++ struct cmd_node *interfaces = commands_new( ++ show, ++ "interfaces", ++ "Show interfaces data", ++ NULL, NULL, NULL); ++ + struct cmd_node *chassis = commands_new( + show, + "chassis", +@@ -289,6 +324,15 @@ register_commands_show(struct cmd_node * + + register_common_commands(neighbors, 1); + ++ /* Interfaces data */ ++ commands_new(interfaces, ++ NEWLINE, ++ "Show interfaces data", ++ NULL, cmd_show_interfaces, NULL); ++ ++ cmd_restrict_ports(interfaces); ++ register_common_commands(interfaces, 0); ++ + /* Chassis data */ + commands_new(chassis, + NEWLINE, +--- a/src/lib/atoms/port.c ++++ b/src/lib/atoms/port.c +@@ -19,6 +19,7 @@ + #include + #include + #include ++#include + + #include "lldpctl.h" + #include "../log.h" +@@ -544,6 +545,7 @@ _lldpctl_atom_get_int_port(lldpctl_atom_ + (struct _lldpctl_atom_port_t *)atom; + struct lldpd_port *port = p->port; + struct lldpd_hardware *hardware = p->hardware; ++ time_t now = time(NULL); + + /* Local port only */ + if (hardware != NULL) { +@@ -585,6 +587,11 @@ _lldpctl_atom_get_int_port(lldpctl_atom_ + return port->p_id_subtype; + case lldpctl_k_port_hidden: + return port->p_hidden_in; ++ case lldpctl_k_port_ttl: ++ if (port->p_lastupdate > 0) ++ return (port->p_chassis->c_ttl - (now - port->p_lastupdate)); ++ else ++ return port->p_chassis->c_ttl; + #ifdef ENABLE_DOT3 + case lldpctl_k_port_dot3_mfs: + if (port->p_mfs > 0) +--- a/src/lib/lldpctl.h ++++ b/src/lib/lldpctl.h +@@ -674,6 +674,7 @@ typedef enum { + lldpctl_k_port_hidden, /**< `(I)` Is this port hidden (or should it be displayed?)? */ + lldpctl_k_port_status, /**< `(IS,WO)` Operational status of this (local) port */ + lldpctl_k_port_chassis, /**< `(A)` Chassis associated to the port */ ++ lldpctl_k_port_ttl, /**< `(I)` The port ttl. */ + + lldpctl_k_port_dot3_mfs = 1300, /**< `(I)` MFS */ + lldpctl_k_port_dot3_aggregid, /**< `(I)` Port aggregation ID */ diff --git a/recipes-daemons/lldpd/files/lldpd.default b/recipes-daemons/lldpd/files/lldpd.default new file mode 100644 index 0000000..2364c02 --- /dev/null +++ b/recipes-daemons/lldpd/files/lldpd.default @@ -0,0 +1,2 @@ +# Uncomment to start SNMP subagent and enable CDP, SONMP and EDP protocol +#DAEMON_ARGS="-x -c -s -e" \ No newline at end of file diff --git a/recipes-daemons/lldpd/files/lldpd.init b/recipes-daemons/lldpd/files/lldpd.init new file mode 100644 index 0000000..c910f0d --- /dev/null +++ b/recipes-daemons/lldpd/files/lldpd.init @@ -0,0 +1,117 @@ +#! /bin/sh +### BEGIN INIT INFO +# Provides: lldpd +# Required-Start: $remote_fs $network $syslog +# Required-Stop: $network $remote_fs $syslog +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: LLDP daemon +# Description: lldpd is a 802.1AB implementation, a L2 network +# discovery protocol. It also supports CDP, EDP and +# various other protocols. +### END INIT INFO + +# Do NOT "set -e" + +# PATH should only include /usr/* if it runs after the mountnfs.sh script +PATH=/sbin:/usr/sbin:/bin:/usr/bin +DESC="LLDP daemon" +NAME=lldpd +DAEMON=/usr/sbin/$NAME +DAEMON_ARGS="" +PIDFILE=/var/run/$NAME.pid +SCRIPTNAME=/etc/init.d/$NAME +CHROOT=/var/run/$NAME + +# Exit if the package is not installed +[ -x "$DAEMON" ] || exit 0 + +# Read configuration variable file if it is present +[ -r /etc/default/$NAME ] && . /etc/default/$NAME + +# Create the chroot directory if not present +[ -d "$CHROOT" ] || mkdir -p $CHROOT + +# LSB log_* functions +. /lib/lsb/init-functions + +if [ ! -d "$CHROOT" ]; then + mkdir -p $CHROOT +fi + + +do_start() +{ + start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \ + || return 1 + start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \ + $DAEMON_ARGS \ + || return 2 +} + +do_stop() +{ + start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME + RETVAL="$?" + [ "$RETVAL" = 2 ] && return 2 + start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON + [ "$?" = 2 ] && return 2 + rm -f $PIDFILE + return "$RETVAL" +} + +do_reload() { + start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME + return 0 +} + +case "$1" in + start) + [ "$VERBOSE" != no ] && log_begin_msg "Starting $DESC" "$NAME" + do_start + case "$?" in + 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; + 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; + esac + ;; + stop) + [ "$VERBOSE" != no ] && log_begin_msg "Stopping $DESC" "$NAME" + do_stop + case "$?" in + 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; + 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; + esac + ;; + reload) + log_begin_msg "Reloading $DESC" "$NAME" + do_reload + log_end_msg $? + ;; + restart|force-reload) + log_begin_msg "Restarting $DESC" "$NAME" + do_stop + case "$?" in + 0|1) + do_start + case "$?" in + 0) log_end_msg 0 ;; + 1) log_end_msg 1 ;; # Old process is still running + *) log_end_msg 1 ;; # Failed to start + esac + ;; + *) + # Failed to stop + log_end_msg 1 + ;; + esac + ;; + status) + status_of_proc $DAEMON $NAME -p $PIDFILE && exit 0 || exit $? + ;; + *) + echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload|status}" >&2 + exit 3 + ;; +esac + +: \ No newline at end of file diff --git a/recipes-daemons/lldpd/lldpd_%.bbappend b/recipes-daemons/lldpd/lldpd_%.bbappend new file mode 100644 index 0000000..aff976a --- /dev/null +++ b/recipes-daemons/lldpd/lldpd_%.bbappend @@ -0,0 +1,24 @@ +FILESEXTRAPATHS_prepend := "${THISDIR}/patches:${THISDIR}/files:" + +SRC_URI += " \ + file://0001-lldpd-client-add-show-interfaces-cmd-from-upstream.patch \ + file://0002-Clear-station-bit-if-any-other-capability-is-enabled.patch \ + file://i40e-lldp-configure.sh \ + " + +# TODO: +# Check Yocto handling of i40e firmware? +# See i40e-lldp-configure.sh and lldpd-i40e-disable.patch + +# file://lldpd.init +# lldpd-create-run-dir.patch + +do_install_append() { + cd ${S} + install -d -m 0755 ${D}/${sysconfdir}/init.d + install -m 0755 ${WORKDIR}/i40e-lldp-configure.sh ${D}/${sysconfdir}/init.d/ +} + +FILES_${PN}_append = " \ + ${sysconfdir}/init.d/i40e-lldp-configure.sh \ + "