diff options
author | Lennart Poettering <lennart@poettering.net> | 2016-05-30 22:11:47 +0200 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2016-06-06 19:59:07 +0200 |
commit | 16fed825d60ca1efa57d0b9231842cda9aae7a68 (patch) | |
tree | f6ced70b32a666143b3852f2afafba90edcfa10a /src | |
parent | e475d10c1be86f3c060cee86ddd6e1617608bdd8 (diff) |
sd-lldp: take triple timestamp when reading LLDP packets
It's a good idea to store away the recption time of LLDP packets in the
neighbor object, simply because the LLDP data only has a validity of a certain
amount of time.
Hence, let's record the timestamp when we receive the datagram and expose an
API for it. Also, automatically expire LLDP neighbors based on this new
timestamp.
Diffstat (limited to 'src')
-rw-r--r-- | src/libsystemd-network/lldp-neighbor.c | 26 | ||||
-rw-r--r-- | src/libsystemd-network/lldp-neighbor.h | 2 | ||||
-rw-r--r-- | src/libsystemd-network/sd-lldp.c | 8 | ||||
-rw-r--r-- | src/systemd/sd-lldp.h | 1 |
4 files changed, 34 insertions, 3 deletions
diff --git a/src/libsystemd-network/lldp-neighbor.c b/src/libsystemd-network/lldp-neighbor.c index 6a716430e3..c14126b60a 100644 --- a/src/libsystemd-network/lldp-neighbor.c +++ b/src/libsystemd-network/lldp-neighbor.c @@ -360,9 +360,16 @@ end_marker: void lldp_neighbor_start_ttl(sd_lldp_neighbor *n) { assert(n); - if (n->ttl > 0) - n->until = usec_add(now(clock_boottime_or_monotonic()), n->ttl * USEC_PER_SEC); - else + if (n->ttl > 0) { + usec_t base; + + /* Use the packet's timestamp if there is one known */ + base = triple_timestamp_by_clock(&n->timestamp, clock_boottime_or_monotonic()); + if (base <= 0 || base == USEC_INFINITY) + base = now(clock_boottime_or_monotonic()); /* Otherwise, take the current time */ + + n->until = usec_add(base, n->ttl * USEC_PER_SEC); + } else n->until = 0; if (n->lldp) @@ -792,3 +799,16 @@ _public_ int sd_lldp_neighbor_tlv_get_raw(sd_lldp_neighbor *n, const void **ret, return 0; } + +int sd_lldp_neighbor_get_timestamp(sd_lldp_neighbor *n, clockid_t clock, uint64_t *ret) { + assert_return(n, -EINVAL); + assert_return(TRIPLE_TIMESTAMP_HAS_CLOCK(clock), -EOPNOTSUPP); + assert_return(clock_supported(clock), -EOPNOTSUPP); + assert_return(ret, -EINVAL); + + if (!triple_timestamp_is_set(&n->timestamp)) + return -ENODATA; + + *ret = triple_timestamp_by_clock(&n->timestamp, clock); + return 0; +} diff --git a/src/libsystemd-network/lldp-neighbor.h b/src/libsystemd-network/lldp-neighbor.h index f203bfa604..27a27055f1 100644 --- a/src/libsystemd-network/lldp-neighbor.h +++ b/src/libsystemd-network/lldp-neighbor.h @@ -43,6 +43,8 @@ struct sd_lldp_neighbor { sd_lldp *lldp; unsigned n_ref; + triple_timestamp timestamp; + usec_t until; unsigned prioq_idx; diff --git a/src/libsystemd-network/sd-lldp.c b/src/libsystemd-network/sd-lldp.c index 9d4587c80e..223a5ac02f 100644 --- a/src/libsystemd-network/sd-lldp.c +++ b/src/libsystemd-network/sd-lldp.c @@ -138,6 +138,7 @@ static int lldp_add_neighbor(sd_lldp *lldp, sd_lldp_neighbor *n) { if (lldp_neighbor_equal(n, old)) { /* Is this equal, then restart the TTL counter, but don't do anyting else. */ + old->timestamp = n->timestamp; lldp_start_timer(lldp, old); lldp_callback(lldp, SD_LLDP_EVENT_REFRESHED, old); return 0; @@ -202,6 +203,7 @@ static int lldp_receive_datagram(sd_event_source *s, int fd, uint32_t revents, v _cleanup_(sd_lldp_neighbor_unrefp) sd_lldp_neighbor *n = NULL; ssize_t space, length; sd_lldp *lldp = userdata; + struct timespec ts; assert(fd >= 0); assert(lldp); @@ -223,6 +225,12 @@ static int lldp_receive_datagram(sd_event_source *s, int fd, uint32_t revents, v return -EINVAL; } + /* Try to get the timestamp of this packet if it is known */ + if (ioctl(fd, SIOCGSTAMPNS, &ts) >= 0) + triple_timestamp_from_realtime(&n->timestamp, timespec_load(&ts)); + else + triple_timestamp_get(&n->timestamp); + return lldp_handle_datagram(lldp, n); } diff --git a/src/systemd/sd-lldp.h b/src/systemd/sd-lldp.h index 5772d5794a..617e0f1e17 100644 --- a/src/systemd/sd-lldp.h +++ b/src/systemd/sd-lldp.h @@ -145,6 +145,7 @@ sd_lldp_neighbor *sd_lldp_neighbor_unref(sd_lldp_neighbor *n); /* Access to LLDP frame metadata */ int sd_lldp_neighbor_get_source_address(sd_lldp_neighbor *n, struct ether_addr* address); int sd_lldp_neighbor_get_destination_address(sd_lldp_neighbor *n, struct ether_addr* address); +int sd_lldp_neighbor_get_timestamp(sd_lldp_neighbor *n, clockid_t clock, uint64_t *ret); int sd_lldp_neighbor_get_raw(sd_lldp_neighbor *n, const void **ret, size_t *size); /* High-level, direct, parsed out field access. These fields exist at most once, hence may be queried directly. */ |