diff options
Diffstat (limited to 'src/network/networkd-lldp-tx.c')
-rw-r--r-- | src/network/networkd-lldp-tx.c | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/src/network/networkd-lldp-tx.c b/src/network/networkd-lldp-tx.c new file mode 100644 index 0000000..fc9196f --- /dev/null +++ b/src/network/networkd-lldp-tx.c @@ -0,0 +1,137 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include <net/if.h> +#include <net/if_arp.h> + +#include "sd-lldp-tx.h" + +#include "networkd-link.h" +#include "networkd-lldp-tx.h" +#include "networkd-manager.h" +#include "parse-util.h" +#include "string-table.h" +#include "string-util.h" +#include "strv.h" + +static bool link_lldp_tx_enabled(Link *link) { + assert(link); + + if (link->flags & IFF_LOOPBACK) + return false; + + if (link->iftype != ARPHRD_ETHER) + return false; + + if (!link->network) + return false; + + if (link->kind && STR_IN_SET(link->kind, "bridge", "bond")) + return false; + + return link->network->lldp_multicast_mode >= 0 && + link->network->lldp_multicast_mode < _SD_LLDP_MULTICAST_MODE_MAX; +} + +int link_lldp_tx_configure(Link *link) { + int r; + + assert(link); + + if (!link_lldp_tx_enabled(link)) + return 0; + + if (link->lldp_tx) + return -EBUSY; + + r = sd_lldp_tx_new(&link->lldp_tx); + if (r < 0) + return r; + + r = sd_lldp_tx_attach_event(link->lldp_tx, link->manager->event, 0); + if (r < 0) + return r; + + r = sd_lldp_tx_set_ifindex(link->lldp_tx, link->ifindex); + if (r < 0) + return r; + + r = sd_lldp_tx_set_hwaddr(link->lldp_tx, &link->hw_addr.ether); + if (r < 0) + return r; + + assert(link->network); + + r = sd_lldp_tx_set_multicast_mode(link->lldp_tx, link->network->lldp_multicast_mode); + if (r < 0) + return r; + + r = sd_lldp_tx_set_capabilities(link->lldp_tx, + SD_LLDP_SYSTEM_CAPABILITIES_STATION | + SD_LLDP_SYSTEM_CAPABILITIES_BRIDGE | + SD_LLDP_SYSTEM_CAPABILITIES_ROUTER, + (link->network->ip_forward != ADDRESS_FAMILY_NO) ? + SD_LLDP_SYSTEM_CAPABILITIES_ROUTER : + SD_LLDP_SYSTEM_CAPABILITIES_STATION); + if (r < 0) + return r; + + r = sd_lldp_tx_set_port_description(link->lldp_tx, link->network->description); + if (r < 0) + return r; + + r = sd_lldp_tx_set_mud_url(link->lldp_tx, link->network->lldp_mudurl); + if (r < 0) + return r; + + return 0; +} + +static const char * const lldp_multicast_mode_table[_SD_LLDP_MULTICAST_MODE_MAX] = { + [SD_LLDP_MULTICAST_MODE_NEAREST_BRIDGE] = "nearest-bridge", + [SD_LLDP_MULTICAST_MODE_NON_TPMR_BRIDGE] = "non-tpmr-bridge", + [SD_LLDP_MULTICAST_MODE_CUSTOMER_BRIDGE] = "customer-bridge", +}; + +DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(lldp_multicast_mode, sd_lldp_multicast_mode_t); + +int config_parse_lldp_multicast_mode( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + sd_lldp_multicast_mode_t m, *mode = ASSERT_PTR(data); + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + + if (isempty(rvalue)) { + *mode = _SD_LLDP_MULTICAST_MODE_INVALID; + return 0; + } + + r = parse_boolean(rvalue); + if (r >= 0) { + *mode = r == 0 ? _SD_LLDP_MULTICAST_MODE_INVALID : SD_LLDP_MULTICAST_MODE_NEAREST_BRIDGE; + return 0; + } + + m = lldp_multicast_mode_from_string(rvalue); + if (m < 0) { + log_syntax(unit, LOG_WARNING, filename, line, m, + "Failed to parse %s=, ignoring assignment: %s", lvalue, rvalue); + return 0; + } + + *mode = m; + return 0; +} |