diff --git a/sys/netlink/netlink_snl_route_parsers.h b/sys/netlink/netlink_snl_route_parsers.h --- a/sys/netlink/netlink_snl_route_parsers.h +++ b/sys/netlink/netlink_snl_route_parsers.h @@ -166,6 +166,7 @@ uint8_t ifla_carrier; uint32_t ifla_mtu; char *ifla_ifname; + char *iflaf_orig_ifname; struct nlattr *ifla_address; struct nlattr *ifla_broadcast; char *ifla_ifalias; @@ -175,6 +176,11 @@ #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_IFNAME, .off = _OUT(iflaf_orig_ifname), .cb = snl_attr_get_string }, +}; +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_get_nla }, { .type = IFLA_BROADCAST, .off = _OUT(ifla_broadcast), .cb = snl_attr_get_nla }, @@ -185,6 +191,7 @@ { .type = IFLA_STATS64, .off = _OUT(ifla_stats64), .cb = snl_attr_copy_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 }, @@ -273,8 +280,8 @@ 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, &snl_rtm_neigh_parser, - &snl_rtm_addr_parser, + &_link_fbsd_parser, &snl_rtm_link_parser, &snl_rtm_link_parser_simple, + &snl_rtm_neigh_parser, &snl_rtm_addr_parser, }; #endif diff --git a/sys/netlink/route/iface.c b/sys/netlink/route/iface.c --- a/sys/netlink/route/iface.c +++ b/sys/netlink/route/iface.c @@ -298,6 +298,14 @@ 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) { + nlattr_add_string(nw, IFLAF_ORIG_IFNAME, if_getorigname(ifp)); + + nlattr_set_len(nw, off); + } + get_stats(nw, ifp); uint32_t val = (ifp->if_flags & IFF_PROMISC) != 0; diff --git a/sys/netlink/route/interface.h b/sys/netlink/route/interface.h --- a/sys/netlink/route/interface.h +++ b/sys/netlink/route/interface.h @@ -142,10 +142,18 @@ 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_MAX +}; +#define IFLAF_MAX (__IFLAF_MAX - 1) + /* * Attributes that can be used as filters: * IFLA_IFNAME, IFLA_GROUP, IFLA_ALT_IFNAME diff --git a/tests/atf_python/sys/netlink/attrs.py b/tests/atf_python/sys/netlink/attrs.py --- a/tests/atf_python/sys/netlink/attrs.py +++ b/tests/atf_python/sys/netlink/attrs.py @@ -85,6 +85,13 @@ def nla_len(self): return align4(len(b"".join([bytes(nla) for nla in self.nla_list]))) + 4 + def get_nla(self, nla_type): + nla_type_raw = enum_or_int(nla_type) + for nla in self.nla_list: + if nla.nla_type == nla_type_raw: + return nla + return None + def print_attr(self, prepend=""): if self._enum is not None: type_str = self._enum.name diff --git a/tests/atf_python/sys/netlink/netlink_route.py b/tests/atf_python/sys/netlink/netlink_route.py --- a/tests/atf_python/sys/netlink/netlink_route.py +++ b/tests/atf_python/sys/netlink/netlink_route.py @@ -346,6 +346,20 @@ IFLA_ALT_IFNAME = auto() IFLA_PERM_ADDRESS = auto() IFLA_PROTO_DOWN_REASON = auto() + IFLA_PARENT_DEV_NAME = auto() + IFLA_PARENT_DEV_BUS_NAME = auto() + IFLA_GRO_MAX_SIZE = auto() + IFLA_TSO_MAX_SEGS = auto() + IFLA_ALLMULTI = auto() + IFLA_DEVLINK_PORT = auto() + IFLA_GSO_IPV4_MAX_SIZE = auto() + IFLA_GRO_IPV4_MAX_SIZE = auto() + IFLA_FREEBSD = auto() + + +class IflfattrType(Enum): + IFLAF_UNSPEC = 0 + IFLAF_ORIG_IFNAME = 1 class IflinkInfo(Enum): @@ -565,6 +579,13 @@ AttrDescr(IflinkInfo.IFLA_INFO_DATA, NlAttr), ], ), + AttrDescr( + IflattrType.IFLA_FREEBSD, + NlAttrNested, + [ + AttrDescr(IflfattrType.IFLAF_ORIG_IFNAME, NlAttrStr), + ], + ), ] ) diff --git a/tests/sys/netlink/test_rtnl_iface.py b/tests/sys/netlink/test_rtnl_iface.py --- a/tests/sys/netlink/test_rtnl_iface.py +++ b/tests/sys/netlink/test_rtnl_iface.py @@ -3,6 +3,7 @@ import pytest from atf_python.sys.netlink.netlink_route import IflattrType +from atf_python.sys.netlink.netlink_route import IflfattrType from atf_python.sys.netlink.netlink_route import IflinkInfo from atf_python.sys.netlink.netlink_route import IfLinkInfoDataVlan from atf_python.sys.netlink.netlink_route import NetlinkIflaMessage @@ -242,6 +243,36 @@ assert rx_msg.is_type(NlMsgType.NLMSG_ERROR) assert rx_msg.error_code == errno.ENODEV + @pytest.mark.require_user("root") + def test_dump_iface(self): + """Tests interface dummp provides correct properties""" + ifname = "lo10" + ifkind = "lo" + + flags = NlmNewFlags.NLM_F_EXCL.value | NlmNewFlags.NLM_F_CREATE.value + msg = NetlinkIflaMessage(self.helper, NlRtMsgType.RTM_NEWLINK.value) + msg.nl_hdr.nlmsg_flags = ( + flags | NlmBaseFlags.NLM_F_ACK.value | NlmBaseFlags.NLM_F_REQUEST.value + ) + msg.add_nla(NlAttrStr(IflattrType.IFLA_IFNAME, ifname)) + msg.add_nla( + NlAttrNested( + IflattrType.IFLA_LINKINFO, + [ + NlAttrStrn(IflinkInfo.IFLA_INFO_KIND, ifkind), + ], + ) + ) + + rx_msg = self.get_reply(msg) + assert rx_msg.is_type(NlMsgType.NLMSG_ERROR) + assert rx_msg.error_code == 0 + + rx_msg = self.get_interface_byname(ifname) + assert rx_msg.get_nla(IflattrType.IFLA_IFNAME).text == ifname + fnla = rx_msg.get_nla(IflattrType.IFLA_FREEBSD) + assert fnla.get_nla(IflfattrType.IFLAF_ORIG_IFNAME).text == ifname + @pytest.mark.require_user("root") def test_dump_ifaces_many(self): """Tests if interface dummp is not missing interfaces"""