mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-08-25 13:50:12 +03:00
network: use sd-lldp-tx
This commit is contained in:
@ -210,7 +210,7 @@ static void link_free_engines(Link *link) {
|
||||
link->dhcp_lease = sd_dhcp_lease_unref(link->dhcp_lease);
|
||||
|
||||
link->lldp_rx = sd_lldp_rx_unref(link->lldp_rx);
|
||||
link_lldp_emit_stop(link);
|
||||
link->lldp_tx = sd_lldp_tx_unref(link->lldp_tx);
|
||||
|
||||
ndisc_flush(link);
|
||||
|
||||
@ -377,7 +377,11 @@ int link_stop_engines(Link *link, bool may_keep_dhcp) {
|
||||
|
||||
k = sd_lldp_rx_stop(link->lldp_rx);
|
||||
if (k < 0)
|
||||
r = log_link_warning_errno(link, k, "Could not stop LLDP: %m");
|
||||
r = log_link_warning_errno(link, k, "Could not stop LLDP Rx: %m");
|
||||
|
||||
k = sd_lldp_tx_stop(link->lldp_tx);
|
||||
if (k < 0)
|
||||
r = log_link_warning_errno(link, k, "Could not stop LLDP Tx: %m");
|
||||
|
||||
k = sd_ipv4ll_stop(link->ipv4ll);
|
||||
if (k < 0)
|
||||
@ -403,7 +407,6 @@ int link_stop_engines(Link *link, bool may_keep_dhcp) {
|
||||
if (k < 0)
|
||||
r = log_link_warning_errno(link, k, "Could not stop IPv6 Router Advertisement: %m");
|
||||
|
||||
link_lldp_emit_stop(link);
|
||||
return r;
|
||||
}
|
||||
|
||||
@ -686,9 +689,11 @@ static int link_acquire_dynamic_conf(Link *link) {
|
||||
return r;
|
||||
}
|
||||
|
||||
r = link_lldp_emit_start(link);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Failed to start LLDP transmission: %m");
|
||||
if (link->lldp_tx) {
|
||||
r = sd_lldp_tx_start(link->lldp_tx);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Failed to start LLDP transmission: %m");
|
||||
}
|
||||
|
||||
if (link->lldp_rx) {
|
||||
r = sd_lldp_rx_start(link->lldp_rx);
|
||||
@ -1162,6 +1167,10 @@ static int link_configure(Link *link) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = link_lldp_tx_configure(link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = link_drop_foreign_config(link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -2105,7 +2114,13 @@ static int link_update_hardware_address(Link *link, sd_netlink_message *message)
|
||||
if (link->lldp_rx) {
|
||||
r = sd_lldp_rx_set_filter_address(link->lldp_rx, &link->hw_addr.ether);
|
||||
if (r < 0)
|
||||
return log_link_debug_errno(link, r, "Could not update MAC address for LLDP: %m");
|
||||
return log_link_debug_errno(link, r, "Could not update MAC address for LLDP Rx: %m");
|
||||
}
|
||||
|
||||
if (link->lldp_tx) {
|
||||
r = sd_lldp_tx_set_hwaddr(link->lldp_tx, &link->hw_addr.ether);
|
||||
if (r < 0)
|
||||
return log_link_debug_errno(link, r, "Could not update MAC address for LLDP Tx: %m");
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -2269,7 +2284,13 @@ static int link_update_name(Link *link, sd_netlink_message *message) {
|
||||
if (link->lldp_rx) {
|
||||
r = sd_lldp_rx_set_ifname(link->lldp_rx, link->ifname);
|
||||
if (r < 0)
|
||||
return log_link_debug_errno(link, r, "Failed to update interface name in LLDP: %m");
|
||||
return log_link_debug_errno(link, r, "Failed to update interface name in LLDP Rx: %m");
|
||||
}
|
||||
|
||||
if (link->lldp_tx) {
|
||||
r = sd_lldp_tx_set_ifname(link->lldp_tx, link->ifname);
|
||||
if (r < 0)
|
||||
return log_link_debug_errno(link, r, "Failed to update interface name in LLDP Tx: %m");
|
||||
}
|
||||
|
||||
if (link->ipv4ll) {
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "sd-ipv4acd.h"
|
||||
#include "sd-ipv4ll.h"
|
||||
#include "sd-lldp-rx.h"
|
||||
#include "sd-lldp-tx.h"
|
||||
#include "sd-ndisc.h"
|
||||
#include "sd-radv.h"
|
||||
#include "sd-netlink.h"
|
||||
@ -175,8 +176,7 @@ typedef struct Link {
|
||||
char *lldp_file;
|
||||
|
||||
/* This is about LLDP transmission */
|
||||
unsigned lldp_tx_fast; /* The LLDP txFast counter (See 802.1ab-2009, section 9.2.5.18) */
|
||||
sd_event_source *lldp_emit_event_source;
|
||||
sd_lldp_tx *lldp_tx;
|
||||
|
||||
Hashmap *bound_by_links;
|
||||
Hashmap *bound_to_links;
|
||||
|
@ -56,12 +56,13 @@ static void lldp_rx_handler(sd_lldp_rx *lldp_rx, sd_lldp_rx_event_t event, sd_ll
|
||||
|
||||
(void) link_lldp_save(link);
|
||||
|
||||
if (link_lldp_emit_enabled(link) && event == SD_LLDP_RX_EVENT_ADDED) {
|
||||
if (link->lldp_tx && event == SD_LLDP_RX_EVENT_ADDED) {
|
||||
/* If we received information about a new neighbor, restart the LLDP "fast" logic */
|
||||
|
||||
log_link_debug(link, "Received LLDP datagram from previously unknown neighbor, restarting 'fast' LLDP transmission.");
|
||||
|
||||
r = link_lldp_emit_start(link);
|
||||
(void) sd_lldp_tx_stop(link->lldp_tx);
|
||||
r = sd_lldp_tx_start(link->lldp_tx);
|
||||
if (r < 0)
|
||||
log_link_warning_errno(link, r, "Failed to restart LLDP transmission: %m");
|
||||
}
|
||||
|
@ -1,48 +1,19 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <endian.h>
|
||||
#include <inttypes.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_arp.h>
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "env-file.h"
|
||||
#include "fd-util.h"
|
||||
#include "hostname-util.h"
|
||||
#include "missing_network.h"
|
||||
#include "sd-lldp-tx.h"
|
||||
|
||||
#include "networkd-link.h"
|
||||
#include "networkd-lldp-tx.h"
|
||||
#include "networkd-manager.h"
|
||||
#include "parse-util.h"
|
||||
#include "random-util.h"
|
||||
#include "socket-util.h"
|
||||
#include "string-table.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
#include "unaligned.h"
|
||||
|
||||
/* The LLDP spec calls this "txFastInit", see 9.2.5.19 */
|
||||
#define LLDP_TX_FAST_INIT 4U
|
||||
|
||||
/* The LLDP spec calls this "msgTxHold", see 9.2.5.6 */
|
||||
#define LLDP_TX_HOLD 4U
|
||||
|
||||
/* The jitter range to add, see 9.2.2. */
|
||||
#define LLDP_JITTER_USEC (400U * USEC_PER_MSEC)
|
||||
|
||||
/* The LLDP spec calls this msgTxInterval, but we subtract half the jitter off it. */
|
||||
#define LLDP_TX_INTERVAL_USEC (30U * USEC_PER_SEC - LLDP_JITTER_USEC / 2)
|
||||
|
||||
/* The LLDP spec calls this msgFastTx, but we subtract half the jitter off it. */
|
||||
#define LLDP_FAST_TX_USEC (1U * USEC_PER_SEC - LLDP_JITTER_USEC / 2)
|
||||
|
||||
static const struct ether_addr lldp_multicast_addr[_LLDP_EMIT_MAX] = {
|
||||
[LLDP_EMIT_NEAREST_BRIDGE] = {{ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x0e }},
|
||||
[LLDP_EMIT_NON_TPMR_BRIDGE] = {{ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03 }},
|
||||
[LLDP_EMIT_CUSTOMER_BRIDGE] = {{ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 }},
|
||||
};
|
||||
|
||||
bool link_lldp_emit_enabled(Link *link) {
|
||||
static bool link_lldp_tx_enabled(Link *link) {
|
||||
assert(link);
|
||||
|
||||
if (link->flags & IFF_LOOPBACK)
|
||||
@ -57,366 +28,109 @@ bool link_lldp_emit_enabled(Link *link) {
|
||||
if (link->kind && STR_IN_SET(link->kind, "bridge", "bond"))
|
||||
return false;
|
||||
|
||||
return link->network->lldp_emit != LLDP_EMIT_NO;
|
||||
return link->network->lldp_multicast_mode >= 0 &&
|
||||
link->network->lldp_multicast_mode < _SD_LLDP_MULTICAST_MODE_MAX;
|
||||
}
|
||||
|
||||
static int lldp_write_tlv_header(uint8_t **p, uint8_t id, size_t sz) {
|
||||
assert(p);
|
||||
|
||||
if (id > 127)
|
||||
return -EBADMSG;
|
||||
if (sz > 511)
|
||||
return -ENOBUFS;
|
||||
|
||||
(*p)[0] = (id << 1) | !!(sz & 256);
|
||||
(*p)[1] = sz & 255;
|
||||
|
||||
*p = *p + 2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lldp_make_packet(
|
||||
LLDPEmit mode,
|
||||
const struct ether_addr *hwaddr,
|
||||
const char *machine_id,
|
||||
const char *ifname,
|
||||
uint16_t ttl,
|
||||
const char *port_description,
|
||||
const char *hostname,
|
||||
const char *pretty_hostname,
|
||||
uint16_t system_capabilities,
|
||||
uint16_t enabled_capabilities,
|
||||
char *mud,
|
||||
void **ret, size_t *sz) {
|
||||
|
||||
size_t machine_id_length, ifname_length, port_description_length = 0, hostname_length = 0,
|
||||
pretty_hostname_length = 0, mud_length = 0;
|
||||
_cleanup_free_ void *packet = NULL;
|
||||
struct ether_header *h;
|
||||
uint8_t *p;
|
||||
size_t l;
|
||||
int r;
|
||||
|
||||
assert(mode > LLDP_EMIT_NO);
|
||||
assert(mode < _LLDP_EMIT_MAX);
|
||||
assert(hwaddr);
|
||||
assert(machine_id);
|
||||
assert(ifname);
|
||||
assert(ret);
|
||||
assert(sz);
|
||||
|
||||
machine_id_length = strlen(machine_id);
|
||||
ifname_length = strlen(ifname);
|
||||
|
||||
if (port_description)
|
||||
port_description_length = strlen(port_description);
|
||||
|
||||
if (hostname)
|
||||
hostname_length = strlen(hostname);
|
||||
|
||||
if (pretty_hostname)
|
||||
pretty_hostname_length = strlen(pretty_hostname);
|
||||
|
||||
if (mud)
|
||||
mud_length = strlen(mud);
|
||||
|
||||
l = sizeof(struct ether_header) +
|
||||
/* Chassis ID */
|
||||
2 + 1 + machine_id_length +
|
||||
/* Port ID */
|
||||
2 + 1 + ifname_length +
|
||||
/* TTL */
|
||||
2 + 2 +
|
||||
/* System Capabilities */
|
||||
2 + 4 +
|
||||
/* End */
|
||||
2;
|
||||
|
||||
/* Port Description */
|
||||
if (port_description)
|
||||
l += 2 + port_description_length;
|
||||
|
||||
/* System Name */
|
||||
if (hostname)
|
||||
l += 2 + hostname_length;
|
||||
|
||||
/* System Description */
|
||||
if (pretty_hostname)
|
||||
l += 2 + pretty_hostname_length;
|
||||
|
||||
/* MUD URL */
|
||||
if (mud)
|
||||
l += 2 + sizeof(SD_LLDP_OUI_IANA_MUD) + mud_length;
|
||||
|
||||
packet = malloc(l);
|
||||
if (!packet)
|
||||
return -ENOMEM;
|
||||
|
||||
h = (struct ether_header*) packet;
|
||||
h->ether_type = htobe16(ETHERTYPE_LLDP);
|
||||
memcpy(h->ether_dhost, lldp_multicast_addr + mode, ETH_ALEN);
|
||||
memcpy(h->ether_shost, hwaddr, ETH_ALEN);
|
||||
|
||||
p = (uint8_t*) packet + sizeof(struct ether_header);
|
||||
|
||||
r = lldp_write_tlv_header(&p, SD_LLDP_TYPE_CHASSIS_ID, 1 + machine_id_length);
|
||||
if (r < 0)
|
||||
return r;
|
||||
*(p++) = SD_LLDP_CHASSIS_SUBTYPE_LOCALLY_ASSIGNED;
|
||||
p = mempcpy(p, machine_id, machine_id_length);
|
||||
|
||||
r = lldp_write_tlv_header(&p, SD_LLDP_TYPE_PORT_ID, 1 + ifname_length);
|
||||
if (r < 0)
|
||||
return r;
|
||||
*(p++) = SD_LLDP_PORT_SUBTYPE_INTERFACE_NAME;
|
||||
p = mempcpy(p, ifname, ifname_length);
|
||||
|
||||
r = lldp_write_tlv_header(&p, SD_LLDP_TYPE_TTL, 2);
|
||||
if (r < 0)
|
||||
return r;
|
||||
unaligned_write_be16(p, ttl);
|
||||
p += 2;
|
||||
|
||||
if (port_description) {
|
||||
r = lldp_write_tlv_header(&p, SD_LLDP_TYPE_PORT_DESCRIPTION, port_description_length);
|
||||
if (r < 0)
|
||||
return r;
|
||||
p = mempcpy(p, port_description, port_description_length);
|
||||
}
|
||||
|
||||
if (hostname) {
|
||||
r = lldp_write_tlv_header(&p, SD_LLDP_TYPE_SYSTEM_NAME, hostname_length);
|
||||
if (r < 0)
|
||||
return r;
|
||||
p = mempcpy(p, hostname, hostname_length);
|
||||
}
|
||||
|
||||
if (pretty_hostname) {
|
||||
r = lldp_write_tlv_header(&p, SD_LLDP_TYPE_SYSTEM_DESCRIPTION, pretty_hostname_length);
|
||||
if (r < 0)
|
||||
return r;
|
||||
p = mempcpy(p, pretty_hostname, pretty_hostname_length);
|
||||
}
|
||||
|
||||
if (mud) {
|
||||
/*
|
||||
* +--------+--------+----------+---------+--------------
|
||||
* |TLV Type| len | OUI |subtype | MUDString
|
||||
* | =127 | |= 00 00 5E| = 1 |
|
||||
* |(7 bits)|(9 bits)|(3 octets)|(1 octet)|(1-255 octets)
|
||||
* +--------+--------+----------+---------+--------------
|
||||
* where:
|
||||
|
||||
* o TLV Type = 127 indicates a vendor-specific TLV
|
||||
* o len = indicates the TLV string length
|
||||
* o OUI = 00 00 5E is the organizationally unique identifier of IANA
|
||||
* o subtype = 1 (as assigned by IANA for the MUDstring)
|
||||
* o MUDstring = the length MUST NOT exceed 255 octets
|
||||
*/
|
||||
|
||||
r = lldp_write_tlv_header(&p, SD_LLDP_TYPE_PRIVATE, sizeof(SD_LLDP_OUI_IANA_MUD) + mud_length);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
p = mempcpy(p, SD_LLDP_OUI_IANA_MUD, sizeof(SD_LLDP_OUI_IANA_MUD));
|
||||
p = mempcpy(p, mud, mud_length);
|
||||
}
|
||||
|
||||
r = lldp_write_tlv_header(&p, SD_LLDP_TYPE_SYSTEM_CAPABILITIES, 4);
|
||||
if (r < 0)
|
||||
return r;
|
||||
unaligned_write_be16(p, system_capabilities);
|
||||
p += 2;
|
||||
unaligned_write_be16(p, enabled_capabilities);
|
||||
p += 2;
|
||||
|
||||
r = lldp_write_tlv_header(&p, SD_LLDP_TYPE_END, 0);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
assert(p == (uint8_t*) packet + l);
|
||||
|
||||
*ret = TAKE_PTR(packet);
|
||||
*sz = l;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lldp_send_packet(
|
||||
int ifindex,
|
||||
const struct ether_addr *address,
|
||||
const void *packet,
|
||||
size_t packet_size) {
|
||||
|
||||
union sockaddr_union sa = {
|
||||
.ll.sll_family = AF_PACKET,
|
||||
.ll.sll_protocol = htobe16(ETHERTYPE_LLDP),
|
||||
.ll.sll_ifindex = ifindex,
|
||||
.ll.sll_halen = ETH_ALEN,
|
||||
};
|
||||
|
||||
_cleanup_close_ int fd = -1;
|
||||
ssize_t l;
|
||||
|
||||
assert(ifindex > 0);
|
||||
assert(address);
|
||||
assert(packet || packet_size <= 0);
|
||||
|
||||
memcpy(sa.ll.sll_addr, address, ETH_ALEN);
|
||||
|
||||
fd = socket(AF_PACKET, SOCK_RAW|SOCK_CLOEXEC, IPPROTO_RAW);
|
||||
if (fd < 0)
|
||||
return -errno;
|
||||
|
||||
l = sendto(fd, packet, packet_size, MSG_NOSIGNAL, &sa.sa, sizeof(sa.ll));
|
||||
if (l < 0)
|
||||
return -errno;
|
||||
|
||||
if ((size_t) l != packet_size)
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int link_send_lldp(Link *link) {
|
||||
_cleanup_free_ char *hostname = NULL, *pretty_hostname = NULL;
|
||||
_cleanup_free_ void *packet = NULL;
|
||||
size_t packet_size = 0;
|
||||
sd_id128_t machine_id;
|
||||
uint16_t caps;
|
||||
usec_t ttl;
|
||||
int link_lldp_tx_configure(Link *link) {
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
|
||||
if (!link->network || link->network->lldp_emit == LLDP_EMIT_NO)
|
||||
if (!link_lldp_tx_enabled(link))
|
||||
return 0;
|
||||
|
||||
assert(link->network->lldp_emit < _LLDP_EMIT_MAX);
|
||||
if (link->lldp_tx)
|
||||
return -EBUSY;
|
||||
|
||||
r = sd_id128_get_machine(&machine_id);
|
||||
r = sd_lldp_tx_new(&link->lldp_tx);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
(void) gethostname_strict(&hostname);
|
||||
(void) parse_env_file(NULL, "/etc/machine-info", "PRETTY_HOSTNAME", &pretty_hostname);
|
||||
|
||||
assert_cc(LLDP_TX_INTERVAL_USEC * LLDP_TX_HOLD + 1 <= (UINT16_MAX - 1) * USEC_PER_SEC);
|
||||
ttl = DIV_ROUND_UP(LLDP_TX_INTERVAL_USEC * LLDP_TX_HOLD + 1, USEC_PER_SEC);
|
||||
|
||||
caps = (link->network && link->network->ip_forward != ADDRESS_FAMILY_NO) ?
|
||||
SD_LLDP_SYSTEM_CAPABILITIES_ROUTER :
|
||||
SD_LLDP_SYSTEM_CAPABILITIES_STATION;
|
||||
|
||||
r = lldp_make_packet(link->network->lldp_emit,
|
||||
&link->hw_addr.ether,
|
||||
SD_ID128_TO_STRING(machine_id),
|
||||
link->ifname,
|
||||
(uint16_t) ttl,
|
||||
link->network ? link->network->description : NULL,
|
||||
hostname,
|
||||
pretty_hostname,
|
||||
SD_LLDP_SYSTEM_CAPABILITIES_STATION|SD_LLDP_SYSTEM_CAPABILITIES_BRIDGE|SD_LLDP_SYSTEM_CAPABILITIES_ROUTER,
|
||||
caps,
|
||||
link->network ? link->network->lldp_mud : NULL,
|
||||
&packet, &packet_size);
|
||||
r = sd_lldp_tx_attach_event(link->lldp_tx, link->manager->event, 0);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return lldp_send_packet(link->ifindex, lldp_multicast_addr + link->network->lldp_emit, packet, packet_size);
|
||||
}
|
||||
|
||||
static int on_lldp_timer(sd_event_source *s, usec_t t, void *userdata) {
|
||||
Link *link = userdata;
|
||||
usec_t delay;
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
assert(userdata);
|
||||
|
||||
log_link_debug(link, "Sending LLDP packet...");
|
||||
|
||||
r = link_send_lldp(link);
|
||||
r = sd_lldp_tx_set_ifindex(link->lldp_tx, link->ifindex);
|
||||
if (r < 0)
|
||||
log_link_debug_errno(link, r, "Failed to send LLDP packet, ignoring: %m");
|
||||
return r;
|
||||
|
||||
if (link->lldp_tx_fast > 0)
|
||||
link->lldp_tx_fast--;
|
||||
|
||||
delay = link->lldp_tx_fast > 0 ? LLDP_FAST_TX_USEC : LLDP_TX_INTERVAL_USEC;
|
||||
delay = usec_add(delay, (usec_t) random_u64() % LLDP_JITTER_USEC);
|
||||
|
||||
r = sd_event_source_set_time_relative(s, delay);
|
||||
r = sd_lldp_tx_set_hwaddr(link->lldp_tx, &link->hw_addr.ether);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Failed to restart LLDP timer: %m");
|
||||
return r;
|
||||
|
||||
r = sd_event_source_set_enabled(s, SD_EVENT_ONESHOT);
|
||||
r = sd_lldp_tx_set_multicast_mode(link->lldp_tx, link->network->lldp_multicast_mode);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Failed to enable LLDP timer: %m");
|
||||
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 && 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;
|
||||
}
|
||||
|
||||
int link_lldp_emit_start(Link *link) {
|
||||
usec_t next;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
|
||||
if (!link_lldp_emit_enabled(link)) {
|
||||
link_lldp_emit_stop(link);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Starts the LLDP transmission in "fast" mode. If it is already started, turns "fast" mode back on again. */
|
||||
|
||||
link->lldp_tx_fast = LLDP_TX_FAST_INIT;
|
||||
|
||||
next = usec_add(usec_add(now(clock_boottime_or_monotonic()), LLDP_FAST_TX_USEC),
|
||||
(usec_t) random_u64() % LLDP_JITTER_USEC);
|
||||
|
||||
if (link->lldp_emit_event_source) {
|
||||
usec_t old;
|
||||
|
||||
/* Lower the timeout, maybe */
|
||||
r = sd_event_source_get_time(link->lldp_emit_event_source, &old);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (old <= next)
|
||||
return 0;
|
||||
|
||||
return sd_event_source_set_time(link->lldp_emit_event_source, next);
|
||||
} else {
|
||||
r = sd_event_add_time(
|
||||
link->manager->event,
|
||||
&link->lldp_emit_event_source,
|
||||
clock_boottime_or_monotonic(),
|
||||
next,
|
||||
0,
|
||||
on_lldp_timer,
|
||||
link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
(void) sd_event_source_set_description(link->lldp_emit_event_source, "lldp-tx");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void link_lldp_emit_stop(Link *link) {
|
||||
assert(link);
|
||||
|
||||
link->lldp_emit_event_source = sd_event_source_disable_unref(link->lldp_emit_event_source);
|
||||
}
|
||||
|
||||
static const char * const lldp_emit_table[_LLDP_EMIT_MAX] = {
|
||||
[LLDP_EMIT_NO] = "no",
|
||||
[LLDP_EMIT_NEAREST_BRIDGE] = "nearest-bridge",
|
||||
[LLDP_EMIT_NON_TPMR_BRIDGE] = "non-tpmr-bridge",
|
||||
[LLDP_EMIT_CUSTOMER_BRIDGE] = "customer-bridge",
|
||||
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_WITH_BOOLEAN(lldp_emit, LLDPEmit, LLDP_EMIT_NEAREST_BRIDGE);
|
||||
DEFINE_CONFIG_PARSE_ENUM_WITH_DEFAULT(config_parse_lldp_emit, lldp_emit, LLDPEmit, LLDP_EMIT_NO, "Failed to parse LLDP emission setting");
|
||||
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 = data;
|
||||
int r;
|
||||
|
||||
assert(filename);
|
||||
assert(section);
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
assert(mode);
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -1,24 +1,10 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "conf-parser.h"
|
||||
|
||||
typedef struct Link Link;
|
||||
|
||||
typedef enum LLDPEmit {
|
||||
LLDP_EMIT_NO,
|
||||
LLDP_EMIT_NEAREST_BRIDGE,
|
||||
LLDP_EMIT_NON_TPMR_BRIDGE,
|
||||
LLDP_EMIT_CUSTOMER_BRIDGE,
|
||||
_LLDP_EMIT_MAX,
|
||||
_LLDP_EMIT_INVALID = -EINVAL,
|
||||
} LLDPEmit;
|
||||
int link_lldp_tx_configure(Link *link);
|
||||
|
||||
bool link_lldp_emit_enabled(Link *link);
|
||||
int link_lldp_emit_start(Link *link);
|
||||
void link_lldp_emit_stop(Link *link);
|
||||
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_lldp_emit);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_lldp_mud);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_lldp_multicast_mode);
|
||||
|
@ -20,6 +20,7 @@ _Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"")
|
||||
#include "networkd-dhcp6.h"
|
||||
#include "networkd-ipv4ll.h"
|
||||
#include "networkd-ipv6-proxy-ndp.h"
|
||||
#include "networkd-lldp-tx.h"
|
||||
#include "networkd-ndisc.h"
|
||||
#include "networkd-network.h"
|
||||
#include "networkd-neighbor.h"
|
||||
@ -104,7 +105,7 @@ Network.IPv4LLRoute, config_parse_bool,
|
||||
Network.DefaultRouteOnDevice, config_parse_bool, 0, offsetof(Network, default_route_on_device)
|
||||
Network.IPv6Token, config_parse_address_generation_type, 0, 0
|
||||
Network.LLDP, config_parse_lldp_mode, 0, offsetof(Network, lldp_mode)
|
||||
Network.EmitLLDP, config_parse_lldp_emit, 0, offsetof(Network, lldp_emit)
|
||||
Network.EmitLLDP, config_parse_lldp_multicast_mode, 0, offsetof(Network, lldp_multicast_mode)
|
||||
Network.Address, config_parse_address, 0, 0
|
||||
Network.Gateway, config_parse_gateway, 0, 0
|
||||
Network.Domains, config_parse_domains, 0, 0
|
||||
@ -348,7 +349,7 @@ IPv6Prefix.Assign, config_parse_prefix_assign,
|
||||
IPv6Prefix.RouteMetric, config_parse_prefix_metric, 0, 0
|
||||
IPv6RoutePrefix.Route, config_parse_route_prefix, 0, 0
|
||||
IPv6RoutePrefix.LifetimeSec, config_parse_route_prefix_lifetime, 0, 0
|
||||
LLDP.MUDURL, config_parse_mud_url, 0, offsetof(Network, lldp_mud)
|
||||
LLDP.MUDURL, config_parse_mud_url, 0, offsetof(Network, lldp_mudurl)
|
||||
CAN.BitRate, config_parse_can_bitrate, 0, offsetof(Network, can_bitrate)
|
||||
CAN.SamplePoint, config_parse_permille, 0, offsetof(Network, can_sample_point)
|
||||
CAN.TimeQuantaNSec, config_parse_can_time_quanta, 0, offsetof(Network, can_time_quanta_ns)
|
||||
|
@ -432,6 +432,7 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
|
||||
.multicast_router = _MULTICAST_ROUTER_INVALID,
|
||||
|
||||
.lldp_mode = LLDP_MODE_ROUTERS_ONLY,
|
||||
.lldp_multicast_mode = _SD_LLDP_MULTICAST_MODE_INVALID,
|
||||
|
||||
.dns_default_route = -1,
|
||||
.llmnr = RESOLVE_SUPPORT_YES,
|
||||
@ -690,7 +691,7 @@ static Network *network_free(Network *network) {
|
||||
|
||||
set_free_free(network->dnssec_negative_trust_anchors);
|
||||
|
||||
free(network->lldp_mud);
|
||||
free(network->lldp_mudurl);
|
||||
|
||||
ordered_hashmap_free(network->dhcp_client_send_options);
|
||||
ordered_hashmap_free(network->dhcp_client_send_vendor_options);
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
#include "sd-bus.h"
|
||||
#include "sd-device.h"
|
||||
#include "sd-lldp-tx.h"
|
||||
|
||||
#include "bridge.h"
|
||||
#include "condition.h"
|
||||
@ -17,7 +18,6 @@
|
||||
#include "networkd-dhcp4.h"
|
||||
#include "networkd-dhcp6.h"
|
||||
#include "networkd-lldp-rx.h"
|
||||
#include "networkd-lldp-tx.h"
|
||||
#include "networkd-ndisc.h"
|
||||
#include "networkd-radv.h"
|
||||
#include "networkd-sysctl.h"
|
||||
@ -325,8 +325,8 @@ struct Network {
|
||||
|
||||
/* LLDP support */
|
||||
LLDPMode lldp_mode; /* LLDP reception */
|
||||
LLDPEmit lldp_emit; /* LLDP transmission */
|
||||
char *lldp_mud; /* LLDP MUD URL */
|
||||
sd_lldp_multicast_mode_t lldp_multicast_mode; /* LLDP transmission */
|
||||
char *lldp_mudurl; /* LLDP MUD URL */
|
||||
|
||||
OrderedHashmap *addresses_by_section;
|
||||
Hashmap *routes_by_section;
|
||||
|
Reference in New Issue
Block a user