netlink: provide original interface lladdr in the interface dump.

* Store lladdr in the FreeBSD-specific IFLAF_ORIG_HWADDR attr
* Do not export empty IFLA_ADDRESS for interfaces w/o lladdrs.

MFC after:	2 weeks
This commit is contained in:
Alexander V. Chernikov 2023-05-10 09:49:34 +00:00
parent 30d0fc6f33
commit 3c851dc19b
3 changed files with 40 additions and 3 deletions

View file

@ -202,10 +202,16 @@ struct snl_parsed_link {
char *ifla_ifalias;
uint32_t ifla_promiscuity;
struct rtnl_link_stats64 *ifla_stats64;
struct nlattr *iflaf_orig_hwaddr;
};
#define _IN(_field) offsetof(struct ifinfomsg, _field)
#define _OUT(_field) offsetof(struct snl_parsed_link, _field)
static const struct snl_attr_parser _nla_p_link_fbsd[] = {
{ .type = IFLAF_ORIG_HWADDR, .off = _OUT(iflaf_orig_hwaddr), .cb = snl_attr_dup_nla },
};
SNL_DECLARE_ATTR_PARSER(_link_fbsd_parser, _nla_p_link_fbsd);
static const struct snl_attr_parser _nla_p_link[] = {
{ .type = IFLA_ADDRESS, .off = _OUT(ifla_address), .cb = snl_attr_dup_nla },
{ .type = IFLA_BROADCAST, .off = _OUT(ifla_broadcast), .cb = snl_attr_dup_nla },
@ -216,6 +222,7 @@ static const struct snl_attr_parser _nla_p_link[] = {
{ .type = IFLA_STATS64, .off = _OUT(ifla_stats64), .cb = snl_attr_dup_struct },
{ .type = IFLA_PROMISCUITY, .off = _OUT(ifla_promiscuity), .cb = snl_attr_get_uint32 },
{ .type = IFLA_CARRIER, .off = _OUT(ifla_carrier), .cb = snl_attr_get_uint8 },
{ .type = IFLA_FREEBSD, .arg = &_link_fbsd_parser, .cb = snl_attr_get_nested },
};
static const struct snl_field_parser _fp_p_link[] = {
{.off_in = _IN(ifi_index), .off_out = _OUT(ifi_index), .cb = snl_field_get_uint32 },
@ -394,7 +401,7 @@ SNL_DECLARE_PARSER_EXT(snl_nhmsg_parser, struct nhmsg, _fp_p_nh, _nla_p_nh, _cb_
static const struct snl_hdr_parser *snl_all_route_parsers[] = {
&_metrics_mp_nh_parser, &_mpath_nh_parser, &_metrics_parser, &snl_rtm_route_parser,
&snl_rtm_link_parser, &snl_rtm_link_parser_simple,
&_link_fbsd_parser, &snl_rtm_link_parser, &snl_rtm_link_parser_simple,
&_neigh_fbsd_parser, &snl_rtm_neigh_parser,
&_addr_fbsd_parser, &snl_rtm_addr_parser, &_nh_fbsd_parser, &snl_nhmsg_parser,
};

View file

@ -194,6 +194,17 @@ get_operstate(struct ifnet *ifp, struct if_state *pstate)
}
}
static void
get_hwaddr(struct nl_writer *nw, struct ifnet *ifp)
{
struct ifreq ifr = {};
if (if_gethwaddr(ifp, &ifr) == 0) {
nlattr_add(nw, IFLAF_ORIG_HWADDR, if_getaddrlen(ifp),
ifr.ifr_addr.sa_data);
}
}
static unsigned
ifp_flags_to_netlink(const struct ifnet *ifp)
{
@ -281,8 +292,10 @@ dump_iface(struct nl_writer *nw, struct ifnet *ifp, const struct nlmsghdr *hdr,
nlattr_add_u8(nw, IFLA_PROTO_DOWN, val);
nlattr_add_u8(nw, IFLA_LINKMODE, val);
*/
if ((ifp->if_addr != NULL)) {
dump_sa(nw, IFLA_ADDRESS, ifp->if_addr->ifa_addr);
if (if_getaddrlen(ifp) != 0) {
struct ifaddr *ifa = if_getifaddr(ifp);
dump_sa(nw, IFLA_ADDRESS, ifa->ifa_addr);
}
if ((ifp->if_broadcastaddr != NULL)) {
@ -300,6 +313,14 @@ dump_iface(struct nl_writer *nw, struct ifnet *ifp, const struct nlmsghdr *hdr,
if (ifp->if_description != NULL)
nlattr_add_string(nw, IFLA_IFALIAS, ifp->if_description);
/* Store FreeBSD-specific attributes */
int off = nlattr_add_nested(nw, IFLA_FREEBSD);
if (off != 0) {
get_hwaddr(nw, ifp);
nlattr_set_len(nw, off);
}
get_stats(nw, ifp);
uint32_t val = (ifp->if_flags & IFF_PROMISC) != 0;

View file

@ -142,10 +142,19 @@ enum {
IFLA_DEVLINK_PORT,
IFLA_GSO_IPV4_MAX_SIZE,
IFLA_GRO_IPV4_MAX_SIZE,
IFLA_FREEBSD,
__IFLA_MAX
};
#define IFLA_MAX (__IFLA_MAX - 1)
enum {
IFLAF_UNSPEC = 0,
IFLAF_ORIG_IFNAME = 1, /* string, original interface name at creation */
IFLAF_ORIG_HWADDR = 2, /* binary, original hardware address */
__IFLAF_MAX
};
#define IFLAF_MAX (__IFLAF_MAX - 1)
/*
* Attributes that can be used as filters:
* IFLA_IFNAME, IFLA_GROUP, IFLA_ALT_IFNAME