diff --git a/src/basic/prioq.c b/src/basic/prioq.c index 559e5d124d..c15dcb26af 100644 --- a/src/basic/prioq.c +++ b/src/basic/prioq.c @@ -173,6 +173,16 @@ int prioq_put(Prioq *q, void *data, unsigned *idx) { return 0; } +int prioq_ensure_put(Prioq **q, compare_func_t compare_func, void *data, unsigned *idx) { + int r; + + r = prioq_ensure_allocated(q, compare_func); + if (r < 0) + return r; + + return prioq_put(*q, data, idx); +} + static void remove_item(Prioq *q, struct prioq_item *i) { struct prioq_item *l; diff --git a/src/basic/prioq.h b/src/basic/prioq.h index 7c76647611..508db88026 100644 --- a/src/basic/prioq.h +++ b/src/basic/prioq.h @@ -16,6 +16,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(Prioq*, prioq_free); int prioq_ensure_allocated(Prioq **q, compare_func_t compare_func); int prioq_put(Prioq *q, void *data, unsigned *idx); +int prioq_ensure_put(Prioq **q, compare_func_t compare_func, void *data, unsigned *idx); int prioq_remove(Prioq *q, void *data, unsigned *idx); int prioq_reshuffle(Prioq *q, void *data, unsigned *idx); diff --git a/src/libsystemd-network/lldp-neighbor.c b/src/libsystemd-network/lldp-neighbor.c index 342e490603..48c2142b1e 100644 --- a/src/libsystemd-network/lldp-neighbor.c +++ b/src/libsystemd-network/lldp-neighbor.c @@ -11,6 +11,9 @@ #include "unaligned.h" static void lldp_neighbor_id_hash_func(const LLDPNeighborID *id, struct siphash *state) { + assert(id); + assert(state); + siphash24_compress(id->chassis_id, id->chassis_id_size, state); siphash24_compress(&id->chassis_id_size, sizeof(id->chassis_id_size), state); siphash24_compress(id->port_id, id->port_id_size, state); @@ -18,16 +21,27 @@ static void lldp_neighbor_id_hash_func(const LLDPNeighborID *id, struct siphash } int lldp_neighbor_id_compare_func(const LLDPNeighborID *x, const LLDPNeighborID *y) { + assert(x); + assert(y); + return memcmp_nn(x->chassis_id, x->chassis_id_size, y->chassis_id, y->chassis_id_size) ?: memcmp_nn(x->port_id, x->port_id_size, y->port_id, y->port_id_size); } -DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(lldp_neighbor_hash_ops, LLDPNeighborID, lldp_neighbor_id_hash_func, lldp_neighbor_id_compare_func, - sd_lldp_neighbor, lldp_neighbor_unlink); +DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR( + lldp_neighbor_hash_ops, + LLDPNeighborID, + lldp_neighbor_id_hash_func, + lldp_neighbor_id_compare_func, + sd_lldp_neighbor, + lldp_neighbor_unlink); int lldp_neighbor_prioq_compare_func(const void *a, const void *b) { const sd_lldp_neighbor *x = a, *y = b; + assert(x); + assert(y); + return CMP(x->until, y->until); } @@ -41,8 +55,9 @@ _public_ sd_lldp_neighbor *sd_lldp_neighbor_ref(sd_lldp_neighbor *n) { return n; } -static void lldp_neighbor_free(sd_lldp_neighbor *n) { - assert(n); +static sd_lldp_neighbor *lldp_neighbor_free(sd_lldp_neighbor *n) { + if (!n) + return NULL; free(n->id.port_id); free(n->id.chassis_id); @@ -52,7 +67,7 @@ static void lldp_neighbor_free(sd_lldp_neighbor *n) { free(n->mud_url); free(n->chassis_id_as_string); free(n->port_id_as_string); - free(n); + return mfree(n); } _public_ sd_lldp_neighbor *sd_lldp_neighbor_unref(sd_lldp_neighbor *n) { diff --git a/src/libsystemd-network/lldp-network.c b/src/libsystemd-network/lldp-network.c index 43141b2d79..d11af3ebbb 100644 --- a/src/libsystemd-network/lldp-network.c +++ b/src/libsystemd-network/lldp-network.c @@ -56,15 +56,18 @@ int lldp_network_bind_raw_socket(int ifindex) { if (r < 0) return -errno; + /* customer bridge */ r = setsockopt(fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, sizeof(mreq)); if (r < 0) return -errno; + /* non TPMR bridge */ mreq.mr_address[ETH_ALEN - 1] = 0x03; r = setsockopt(fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, sizeof(mreq)); if (r < 0) return -errno; + /* nearest bridge */ mreq.mr_address[ETH_ALEN - 1] = 0x0E; r = setsockopt(fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, sizeof(mreq)); if (r < 0) diff --git a/src/libsystemd-network/sd-lldp-rx.c b/src/libsystemd-network/sd-lldp-rx.c index 8d9b132722..98bde8b306 100644 --- a/src/libsystemd-network/sd-lldp-rx.c +++ b/src/libsystemd-network/sd-lldp-rx.c @@ -147,11 +147,11 @@ static int lldp_rx_add_neighbor(sd_lldp_rx *lldp_rx, sd_lldp_neighbor *n) { /* Then, make room for at least one new neighbor */ lldp_rx_make_space(lldp_rx, 1); - r = hashmap_put(lldp_rx->neighbor_by_id, &n->id, n); + r = hashmap_ensure_put(&lldp_rx->neighbor_by_id, &lldp_neighbor_hash_ops, &n->id, n); if (r < 0) goto finish; - r = prioq_put(lldp_rx->neighbor_by_expiry, n, &n->prioq_idx); + r = prioq_ensure_put(&lldp_rx->neighbor_by_expiry, lldp_neighbor_prioq_compare_func, n, &n->prioq_idx); if (r < 0) { assert_se(hashmap_remove(lldp_rx->neighbor_by_id, &n->id) == n); goto finish; @@ -178,16 +178,12 @@ static int lldp_rx_handle_datagram(sd_lldp_rx *lldp_rx, sd_lldp_neighbor *n) { assert(n); r = lldp_neighbor_parse(n); - if (r == -EBADMSG) /* Ignore bad messages */ - return 0; if (r < 0) return r; r = lldp_rx_add_neighbor(lldp_rx, n); - if (r < 0) { - log_lldp_rx_errno(lldp_rx, r, "Failed to add datagram. Ignoring."); - return 0; - } + if (r < 0) + return log_lldp_rx_errno(lldp_rx, r, "Failed to add datagram. Ignoring."); log_lldp_rx(lldp_rx, "Successfully processed LLDP datagram."); return 0; @@ -209,8 +205,10 @@ static int lldp_rx_receive_datagram(sd_event_source *s, int fd, uint32_t revents } n = lldp_neighbor_new(space); - if (!n) - return -ENOMEM; + if (!n) { + log_oom_debug(); + return 0; + } length = recv(fd, LLDP_NEIGHBOR_RAW(n), n->raw_size, MSG_DONTWAIT); if (length < 0) { @@ -232,7 +230,8 @@ static int lldp_rx_receive_datagram(sd_event_source *s, int fd, uint32_t revents else triple_timestamp_get(&n->timestamp); - return lldp_rx_handle_datagram(lldp_rx, n); + (void) lldp_rx_handle_datagram(lldp_rx, n); + return 0; } static void lldp_rx_reset(sd_lldp_rx *lldp_rx) { @@ -243,6 +242,13 @@ static void lldp_rx_reset(sd_lldp_rx *lldp_rx) { lldp_rx->fd = safe_close(lldp_rx->fd); } +int sd_lldp_rx_is_running(sd_lldp_rx *lldp_rx) { + if (!lldp_rx) + return false; + + return lldp_rx->fd >= 0; +} + _public_ int sd_lldp_rx_start(sd_lldp_rx *lldp_rx) { int r; @@ -250,7 +256,7 @@ _public_ int sd_lldp_rx_start(sd_lldp_rx *lldp_rx) { assert_return(lldp_rx->event, -EINVAL); assert_return(lldp_rx->ifindex > 0, -EINVAL); - if (lldp_rx->fd >= 0) + if (sd_lldp_rx_is_running(lldp_rx)) return 0; assert(!lldp_rx->io_event_source); @@ -278,10 +284,7 @@ fail: } _public_ int sd_lldp_rx_stop(sd_lldp_rx *lldp_rx) { - if (!lldp_rx) - return 0; - - if (lldp_rx->fd < 0) + if (!sd_lldp_rx_is_running(lldp_rx)) return 0; log_lldp_rx(lldp_rx, "Stopping LLDP client"); @@ -296,7 +299,7 @@ _public_ int sd_lldp_rx_attach_event(sd_lldp_rx *lldp_rx, sd_event *event, int64 int r; assert_return(lldp_rx, -EINVAL); - assert_return(lldp_rx->fd < 0, -EBUSY); + assert_return(!sd_lldp_rx_is_running(lldp_rx), -EBUSY); assert_return(!lldp_rx->event, -EBUSY); if (event) @@ -313,10 +316,11 @@ _public_ int sd_lldp_rx_attach_event(sd_lldp_rx *lldp_rx, sd_event *event, int64 } _public_ int sd_lldp_rx_detach_event(sd_lldp_rx *lldp_rx) { - assert_return(lldp_rx, -EINVAL); - assert_return(lldp_rx->fd < 0, -EBUSY); + assert_return(!sd_lldp_rx_is_running(lldp_rx), -EBUSY); + lldp_rx->io_event_source = sd_event_source_disable_unref(lldp_rx->io_event_source); + lldp_rx->timer_event_source = sd_event_source_disable_unref(lldp_rx->timer_event_source); lldp_rx->event = sd_event_unref(lldp_rx->event); return 0; } @@ -339,7 +343,7 @@ _public_ int sd_lldp_rx_set_callback(sd_lldp_rx *lldp_rx, sd_lldp_rx_callback_t _public_ int sd_lldp_rx_set_ifindex(sd_lldp_rx *lldp_rx, int ifindex) { assert_return(lldp_rx, -EINVAL); assert_return(ifindex > 0, -EINVAL); - assert_return(lldp_rx->fd < 0, -EBUSY); + assert_return(!sd_lldp_rx_is_running(lldp_rx), -EBUSY); lldp_rx->ifindex = ifindex; return 0; @@ -363,11 +367,11 @@ const char *sd_lldp_rx_get_ifname(sd_lldp_rx *lldp_rx) { } static sd_lldp_rx *lldp_rx_free(sd_lldp_rx *lldp_rx) { - assert(lldp_rx); + if (!lldp_rx) + return NULL; lldp_rx_reset(lldp_rx); - sd_event_source_unref(lldp_rx->timer_event_source); sd_lldp_rx_detach_event(lldp_rx); lldp_rx_flush_neighbors(lldp_rx); @@ -382,7 +386,6 @@ DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_lldp_rx, sd_lldp_rx, lldp_rx_free); _public_ int sd_lldp_rx_new(sd_lldp_rx **ret) { _cleanup_(sd_lldp_rx_unrefp) sd_lldp_rx *lldp_rx = NULL; - int r; assert_return(ret, -EINVAL); @@ -397,23 +400,10 @@ _public_ int sd_lldp_rx_new(sd_lldp_rx **ret) { .capability_mask = UINT16_MAX, }; - lldp_rx->neighbor_by_id = hashmap_new(&lldp_neighbor_hash_ops); - if (!lldp_rx->neighbor_by_id) - return -ENOMEM; - - r = prioq_ensure_allocated(&lldp_rx->neighbor_by_expiry, lldp_neighbor_prioq_compare_func); - if (r < 0) - return r; - *ret = TAKE_PTR(lldp_rx); - return 0; } -static int neighbor_compare_func(sd_lldp_neighbor * const *a, sd_lldp_neighbor * const *b) { - return lldp_neighbor_id_compare_func(&(*a)->id, &(*b)->id); -} - static int on_timer_event(sd_event_source *s, uint64_t usec, void *userdata) { sd_lldp_rx *lldp_rx = userdata; int r; @@ -437,6 +427,7 @@ static int lldp_rx_start_timer(sd_lldp_rx *lldp_rx, sd_lldp_neighbor *neighbor) sd_lldp_neighbor *n; assert(lldp_rx); + assert(lldp_rx->event); if (neighbor) lldp_neighbor_start_ttl(neighbor); @@ -445,9 +436,6 @@ static int lldp_rx_start_timer(sd_lldp_rx *lldp_rx, sd_lldp_neighbor *neighbor) if (!n) return event_source_disable(lldp_rx->timer_event_source); - if (!lldp_rx->event) - return 0; - return event_reset_time(lldp_rx->event, &lldp_rx->timer_event_source, clock_boottime_or_monotonic(), n->until, 0, @@ -455,9 +443,19 @@ static int lldp_rx_start_timer(sd_lldp_rx *lldp_rx, sd_lldp_neighbor *neighbor) lldp_rx->event_priority, "lldp-rx-timer", true); } +static inline int neighbor_compare_func(sd_lldp_neighbor * const *a, sd_lldp_neighbor * const *b) { + assert(a); + assert(b); + assert(*a); + assert(*b); + + return lldp_neighbor_id_compare_func(&(*a)->id, &(*b)->id); +} + _public_ int sd_lldp_rx_get_neighbors(sd_lldp_rx *lldp_rx, sd_lldp_neighbor ***ret) { - sd_lldp_neighbor **l = NULL, *n; - int k = 0, r; + _cleanup_free_ sd_lldp_neighbor **l = NULL; + sd_lldp_neighbor *n; + int k = 0; assert_return(lldp_rx, -EINVAL); assert_return(ret, -EINVAL); @@ -471,12 +469,6 @@ _public_ int sd_lldp_rx_get_neighbors(sd_lldp_rx *lldp_rx, sd_lldp_neighbor ***r if (!l) return -ENOMEM; - r = lldp_rx_start_timer(lldp_rx, NULL); - if (r < 0) { - free(l); - return r; - } - HASHMAP_FOREACH(n, lldp_rx->neighbor_by_id) l[k++] = sd_lldp_neighbor_ref(n); @@ -484,7 +476,7 @@ _public_ int sd_lldp_rx_get_neighbors(sd_lldp_rx *lldp_rx, sd_lldp_neighbor ***r /* Return things in a stable order */ typesafe_qsort(l, k, neighbor_compare_func); - *ret = l; + *ret = TAKE_PTR(l); return k; } diff --git a/src/systemd/sd-lldp-rx.h b/src/systemd/sd-lldp-rx.h index 060c677f3d..4653626eee 100644 --- a/src/systemd/sd-lldp-rx.h +++ b/src/systemd/sd-lldp-rx.h @@ -50,6 +50,7 @@ sd_lldp_rx *sd_lldp_rx_unref(sd_lldp_rx *lldp_rx); int sd_lldp_rx_start(sd_lldp_rx *lldp_rx); int sd_lldp_rx_stop(sd_lldp_rx *lldp_rx); +int sd_lldp_rx_is_running(sd_lldp_rx *lldp_rx); int sd_lldp_rx_attach_event(sd_lldp_rx *lldp_rx, sd_event *event, int64_t priority); int sd_lldp_rx_detach_event(sd_lldp_rx *lldp_rx);