NetworkManager/src/libnm-lldp/nm-lldp-rx.h
Thomas Haller 630de288d2
lldp: add libnm-lldp as fork of systemd's sd_lldp_rx
We currently use the systemd LLDP client, which we consume by forking
systemd code. That is a maintenance burden, because it's not a
self-contained, stable library that we use. Hence there is a need for an
individual library or properly integrating the fork in our tree.

Optimally, we would create a new nettools project with an LLDP library.
That was not done because:

- nettools may want to be dual licensed with LGPL-2.1+ and Apache.
  Systemd code is LGPL-2.1+ so it is fine for NetworkManager but
  possibly not for nettools.

- nettools provides independent librares, as such they don't have an
  event loop, instead they expose an epoll file descriptor and the user
  needs to integrate it. Systemd and NetworkManager on the other hand
  have their established event loop (sd_event and GMainContext,
  respectively). It's simpler to implement the library on those terms,
  in particular porting the systemd library from sd_event to
  GMainContext.

- NetworkManager uses glib and has various helper utils. While it's
  possible to do without them, it's more work.

The main reason to not write a new NetworkManager-agnostic library from
scratch, is that it's much simpler to fork the systemd library and make
it part of NetworkManager, than making it a nettools library.

Do it.
2022-10-25 10:59:00 +02:00

124 lines
5.1 KiB
C

/* SPDX-License-Identifier: LGPL-2.1-or-later */
#ifndef __NM_LLDP_RX_H__
#define __NM_LLDP_RX_H__
#include "nm-lldp.h"
typedef struct _NMLldpRX NMLldpRX;
typedef struct _NMLldpNeighbor NMLldpNeighbor;
typedef enum {
NM_LLDP_RX_EVENT_ADDED,
NM_LLDP_RX_EVENT_REMOVED,
NM_LLDP_RX_EVENT_UPDATED,
NM_LLDP_RX_EVENT_REFRESHED,
_NM_LLDP_RX_EVENT_MAX,
_NM_LLDP_RX_EVENT_INVALID = -EINVAL,
} NMLldpRXEvent;
const char *nm_lldp_rx_event_to_string(NMLldpRXEvent e) _nm_pure;
typedef struct {
/* The spec calls this an "MSAP identifier" */
const void *chassis_id;
size_t chassis_id_size;
const void *port_id;
size_t port_id_size;
} NMLldpNeighborID;
guint nm_lldp_neighbor_id_hash(const NMLldpNeighborID *id);
int nm_lldp_neighbor_id_cmp(const NMLldpNeighborID *x, const NMLldpNeighborID *y);
gboolean nm_lldp_neighbor_id_equal(const NMLldpNeighborID *x, const NMLldpNeighborID *y);
typedef void (*NMLldpRXCallback)(NMLldpRX *lldp_rx,
NMLldpRXEvent event,
NMLldpNeighbor *n,
void *userdata);
typedef struct {
int ifindex;
guint neighbors_max;
const char *log_ifname;
const char *log_uuid;
NMLldpRXCallback callback;
void *userdata;
/* In order to deal nicely with bridges that send back our own packets, allow one address to be filtered, so
* that our own can be filtered out here. */
NMEtherAddr filter_address;
uint16_t capability_mask;
bool has_capability_mask : 1;
} NMLldpRXConfig;
NMLldpRX *nm_lldp_rx_new(const NMLldpRXConfig *config);
NMLldpRX *nm_lldp_rx_ref(NMLldpRX *lldp_rx);
void nm_lldp_rx_unref(NMLldpRX *lldp_rx);
NM_AUTO_DEFINE_FCN(NMLldpRX *, nm_lldp_rx_unrefp, nm_lldp_rx_unref);
int nm_lldp_rx_start(NMLldpRX *lldp_rx);
int nm_lldp_rx_stop(NMLldpRX *lldp_rx);
gboolean nm_lldp_rx_is_running(NMLldpRX *lldp_rx);
/* Controls how much and what to store in the neighbors database */
NMLldpNeighbor **nm_lldp_rx_get_neighbors(NMLldpRX *lldp_rx, guint *out_len);
/*****************************************************************************/
NMLldpNeighbor *nm_lldp_neighbor_new_from_raw(const void *raw, size_t raw_size);
NMLldpNeighbor *nm_lldp_neighbor_ref(NMLldpNeighbor *n);
NMLldpNeighbor *nm_lldp_neighbor_unref(NMLldpNeighbor *n);
NM_AUTO_DEFINE_FCN(NMLldpNeighbor *, nm_lldp_neighbor_unrefp, nm_lldp_neighbor_unref);
int nm_lldp_neighbor_cmp(const NMLldpNeighbor *a, const NMLldpNeighbor *b);
static inline gboolean
nm_lldp_neighbor_equal(const NMLldpNeighbor *a, const NMLldpNeighbor *b)
{
return nm_lldp_neighbor_cmp(a, b) == 0;
}
/*****************************************************************************/
static inline const NMLldpNeighborID *
nm_lldp_neighbor_get_id(NMLldpNeighbor *lldp_neigbor)
{
return (const NMLldpNeighborID *) ((gconstpointer) lldp_neigbor);
}
/* Access to LLDP frame metadata */
int nm_lldp_neighbor_get_source_address(NMLldpNeighbor *n, NMEtherAddr *address);
int nm_lldp_neighbor_get_destination_address(NMLldpNeighbor *n, NMEtherAddr *address);
int nm_lldp_neighbor_get_timestamp_usec(NMLldpNeighbor *n, gint64 *out_usec);
int nm_lldp_neighbor_get_raw(NMLldpNeighbor *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. */
int
nm_lldp_neighbor_get_chassis_id(NMLldpNeighbor *n, uint8_t *type, const void **ret, size_t *size);
const char *nm_lldp_neighbor_get_chassis_id_as_string(NMLldpNeighbor *n);
int nm_lldp_neighbor_get_port_id(NMLldpNeighbor *n, uint8_t *type, const void **ret, size_t *size);
const char *nm_lldp_neighbor_get_port_id_as_string(NMLldpNeighbor *n);
int nm_lldp_neighbor_get_ttl(NMLldpNeighbor *n, uint16_t *ret_sec);
int nm_lldp_neighbor_get_system_name(NMLldpNeighbor *n, const char **ret);
int nm_lldp_neighbor_get_system_description(NMLldpNeighbor *n, const char **ret);
int nm_lldp_neighbor_get_port_description(NMLldpNeighbor *n, const char **ret);
int nm_lldp_neighbor_get_mud_url(NMLldpNeighbor *n, const char **ret);
int nm_lldp_neighbor_get_system_capabilities(NMLldpNeighbor *n, uint16_t *ret);
int nm_lldp_neighbor_get_enabled_capabilities(NMLldpNeighbor *n, uint16_t *ret);
/* Low-level, iterative TLV access. This is for everything else, it iteratively goes through all available TLVs
* (including the ones covered with the calls above), and allows multiple TLVs for the same fields. */
int nm_lldp_neighbor_tlv_rewind(NMLldpNeighbor *n);
int nm_lldp_neighbor_tlv_next(NMLldpNeighbor *n);
int nm_lldp_neighbor_tlv_get_type(NMLldpNeighbor *n, uint8_t *type);
int nm_lldp_neighbor_tlv_is_type(NMLldpNeighbor *n, uint8_t type);
int nm_lldp_neighbor_tlv_get_oui(NMLldpNeighbor *n, uint8_t oui[static 3], uint8_t *subtype);
int nm_lldp_neighbor_tlv_is_oui(NMLldpNeighbor *n, const uint8_t oui[static 3], uint8_t subtype);
int nm_lldp_neighbor_tlv_get_raw(NMLldpNeighbor *n, const void **ret, size_t *size);
#endif /* __NM_LLDP_RX_H__ */