diff options
author | Alexander V. Chernikov <melifaro@FreeBSD.org> | 2023-02-09 14:53:44 +0000 |
---|---|---|
committer | Alexander V. Chernikov <melifaro@FreeBSD.org> | 2023-02-20 14:33:28 +0000 |
commit | 72467b39f1db794f2ac54ac9baa1de3166507c6b (patch) | |
tree | cd8c9603e22b687bf6a35c705e66e2212c55df53 /tests | |
parent | ac40ea6fbb4e6af98a4540fc8fd5a3e824cb181d (diff) | |
download | src-72467b39f1db794f2ac54ac9baa1de3166507c6b.tar.gz src-72467b39f1db794f2ac54ac9baa1de3166507c6b.zip |
netlink: return optional metadata with the operation result.
Some operations like interface creation may need to return metadata
- in this case, interface name - back to the caller if the operation
is successful.
This change implements attaching an `NLMSGERR_ATTR_COOKIE` nla to the
operation reply message via `nlmsg_report_cookie()`.
Additionally, on successful interface creation, interface index and
interface name are returned in the `IFLA_NEW_IFINDEX` and `IFLA_IFNAME
TLVs, encapsulated in the `NLMSGERR_ATTR_COOKIE`.
Reviewed By: pauamma
Differential Revision: https://reviews.freebsd.org/D38283
MFC after: 1 week
(cherry picked from commit 25c2dd2f2c6c6144d59d463c95f0471301d6efaa)
Diffstat (limited to 'tests')
-rw-r--r-- | tests/atf_python/sys/net/netlink.py | 134 | ||||
-rw-r--r-- | tests/sys/netlink/test_rtnl_iface.py | 35 |
2 files changed, 109 insertions, 60 deletions
diff --git a/tests/atf_python/sys/net/netlink.py b/tests/atf_python/sys/net/netlink.py index 57c8582627cf..ba7d41c7cbf8 100644 --- a/tests/atf_python/sys/net/netlink.py +++ b/tests/atf_python/sys/net/netlink.py @@ -950,58 +950,68 @@ def prepare_attrs_map(attrs: List[AttrDescr]) -> Dict[str, Dict]: return ret -rtnl_route_attrs = [ - AttrDescr(RtattrType.RTA_DST, NlAttrIp), - AttrDescr(RtattrType.RTA_SRC, NlAttrIp), - AttrDescr(RtattrType.RTA_IIF, NlAttrIfindex), - AttrDescr(RtattrType.RTA_OIF, NlAttrIfindex), - AttrDescr(RtattrType.RTA_GATEWAY, NlAttrTable), - AttrDescr(RtattrType.RTA_VIA, NlAttrVia), - AttrDescr(RtattrType.RTA_NH_ID, NlAttrNhId), - AttrDescr( - RtattrType.RTA_METRICS, - NlAttrNested, - [ - AttrDescr(NlRtaxType.RTAX_MTU, NlAttrU32), - ], - ), -] - -nldone_attrs = [] - -nlerr_attrs = [ - AttrDescr(NlErrattrType.NLMSGERR_ATTR_MSG, NlAttrStr), - AttrDescr(NlErrattrType.NLMSGERR_ATTR_OFFS, NlAttrU32), -] - -rtnl_ifla_attrs = [ - AttrDescr(IflattrType.IFLA_ADDRESS, NlAttrMac), - AttrDescr(IflattrType.IFLA_BROADCAST, NlAttrMac), - AttrDescr(IflattrType.IFLA_IFNAME, NlAttrStr), - AttrDescr(IflattrType.IFLA_MTU, NlAttrU32), - AttrDescr(IflattrType.IFLA_PROMISCUITY, NlAttrU32), - AttrDescr(IflattrType.IFLA_OPERSTATE, NlAttrU8), - AttrDescr(IflattrType.IFLA_CARRIER, NlAttrU8), - AttrDescr(IflattrType.IFLA_IFALIAS, NlAttrStr), - AttrDescr(IflattrType.IFLA_STATS64, NlAttrIfStats), - AttrDescr( - IflattrType.IFLA_LINKINFO, - NlAttrNested, - [ - AttrDescr(IflinkInfo.IFLA_INFO_KIND, NlAttrStr), - AttrDescr(IflinkInfo.IFLA_INFO_DATA, NlAttr), - ], - ), -] - -rtnl_ifa_attrs = [ - AttrDescr(IfattrType.IFA_ADDRESS, NlAttrIp), - AttrDescr(IfattrType.IFA_LOCAL, NlAttrIp), - AttrDescr(IfattrType.IFA_LABEL, NlAttrStr), - AttrDescr(IfattrType.IFA_BROADCAST, NlAttrIp), - AttrDescr(IfattrType.IFA_ANYCAST, NlAttrIp), - AttrDescr(IfattrType.IFA_FLAGS, NlAttrU32), -] +rtnl_route_attrs = prepare_attrs_map( + [ + AttrDescr(RtattrType.RTA_DST, NlAttrIp), + AttrDescr(RtattrType.RTA_SRC, NlAttrIp), + AttrDescr(RtattrType.RTA_IIF, NlAttrIfindex), + AttrDescr(RtattrType.RTA_OIF, NlAttrIfindex), + AttrDescr(RtattrType.RTA_GATEWAY, NlAttrTable), + AttrDescr(RtattrType.RTA_VIA, NlAttrVia), + AttrDescr(RtattrType.RTA_NH_ID, NlAttrNhId), + AttrDescr( + RtattrType.RTA_METRICS, + NlAttrNested, + [ + AttrDescr(NlRtaxType.RTAX_MTU, NlAttrU32), + ], + ), + ] +) + +nldone_attrs = prepare_attrs_map([]) + +nlerr_attrs = prepare_attrs_map( + [ + AttrDescr(NlErrattrType.NLMSGERR_ATTR_MSG, NlAttrStr), + AttrDescr(NlErrattrType.NLMSGERR_ATTR_OFFS, NlAttrU32), + AttrDescr(NlErrattrType.NLMSGERR_ATTR_COOKIE, NlAttr), + ] +) + +rtnl_ifla_attrs = prepare_attrs_map( + [ + AttrDescr(IflattrType.IFLA_ADDRESS, NlAttrMac), + AttrDescr(IflattrType.IFLA_BROADCAST, NlAttrMac), + AttrDescr(IflattrType.IFLA_IFNAME, NlAttrStr), + AttrDescr(IflattrType.IFLA_MTU, NlAttrU32), + AttrDescr(IflattrType.IFLA_PROMISCUITY, NlAttrU32), + AttrDescr(IflattrType.IFLA_OPERSTATE, NlAttrU8), + AttrDescr(IflattrType.IFLA_CARRIER, NlAttrU8), + AttrDescr(IflattrType.IFLA_IFALIAS, NlAttrStr), + AttrDescr(IflattrType.IFLA_STATS64, NlAttrIfStats), + AttrDescr(IflattrType.IFLA_NEW_IFINDEX, NlAttrU32), + AttrDescr( + IflattrType.IFLA_LINKINFO, + NlAttrNested, + [ + AttrDescr(IflinkInfo.IFLA_INFO_KIND, NlAttrStr), + AttrDescr(IflinkInfo.IFLA_INFO_DATA, NlAttr), + ], + ), + ] +) + +rtnl_ifa_attrs = prepare_attrs_map( + [ + AttrDescr(IfattrType.IFA_ADDRESS, NlAttrIp), + AttrDescr(IfattrType.IFA_LOCAL, NlAttrIp), + AttrDescr(IfattrType.IFA_LABEL, NlAttrStr), + AttrDescr(IfattrType.IFA_BROADCAST, NlAttrIp), + AttrDescr(IfattrType.IFA_ANYCAST, NlAttrIp), + AttrDescr(IfattrType.IFA_FLAGS, NlAttrU32), + ] +) class BaseNetlinkMessage(object): @@ -1140,7 +1150,7 @@ class StdNetlinkMessage(BaseNetlinkMessage): raise return self - def _parse_attrs(self, data: bytes, attr_map): + def parse_attrs(self, data: bytes, attr_map): ret = [] off = 0 while len(data) - off >= 4: @@ -1157,7 +1167,7 @@ class StdNetlinkMessage(BaseNetlinkMessage): val = v["ad"].cls.from_bytes(data[off : off + nla_len], v["ad"].val) if "child" in v: # nested - attrs, _ = self._parse_attrs(data[off : off + nla_len], v["child"]) + attrs, _ = self.parse_attrs(data[off : off + nla_len], v["child"]) val = NlAttrNested(raw_nla_type, attrs) else: # unknown attribute @@ -1167,7 +1177,7 @@ class StdNetlinkMessage(BaseNetlinkMessage): return ret, off def parse_nla_list(self, data: bytes) -> List[NlAttr]: - return self._parse_attrs(data, self.nl_attrs_map) + return self.parse_attrs(data, self.nl_attrs_map) def print_message(self): self.print_nl_header(self.nl_hdr) @@ -1178,7 +1188,7 @@ class StdNetlinkMessage(BaseNetlinkMessage): class NetlinkDoneMessage(StdNetlinkMessage): messages = [NlMsgType.NLMSG_DONE.value] - nl_attrs_map = prepare_attrs_map(nldone_attrs) + nl_attrs_map = nldone_attrs @property def error_code(self): @@ -1197,7 +1207,7 @@ class NetlinkDoneMessage(StdNetlinkMessage): class NetlinkErrorMessage(StdNetlinkMessage): messages = [NlMsgType.NLMSG_ERROR.value] - nl_attrs_map = prepare_attrs_map(nlerr_attrs) + nl_attrs_map = nlerr_attrs @property def error_code(self): @@ -1217,6 +1227,10 @@ class NetlinkErrorMessage(StdNetlinkMessage): return nla.u32 return None + @property + def cookie(self): + return self.get_nla(NlErrattrType.NLMSGERR_ATTR_COOKIE) + def parse_base_header(self, data): if len(data) < sizeof(Nlmsgerr): raise ValueError("length less than nlmsgerr header") @@ -1257,7 +1271,7 @@ class NetlinkRtMessage(BaseNetlinkRtMessage): NlRtMsgType.RTM_DELROUTE.value, NlRtMsgType.RTM_GETROUTE.value, ] - nl_attrs_map = prepare_attrs_map(rtnl_route_attrs) + nl_attrs_map = rtnl_route_attrs def __init__(self, helper, nlm_type): super().__init__(helper, nlm_type) @@ -1297,7 +1311,7 @@ class NetlinkIflaMessage(BaseNetlinkRtMessage): NlRtMsgType.RTM_DELLINK.value, NlRtMsgType.RTM_GETLINK.value, ] - nl_attrs_map = prepare_attrs_map(rtnl_ifla_attrs) + nl_attrs_map = rtnl_ifla_attrs def __init__(self, helper, nlm_type): super().__init__(helper, nlm_type) @@ -1329,7 +1343,7 @@ class NetlinkIfaMessage(BaseNetlinkRtMessage): NlRtMsgType.RTM_DELADDR.value, NlRtMsgType.RTM_GETADDR.value, ] - nl_attrs_map = prepare_attrs_map(rtnl_ifa_attrs) + nl_attrs_map = rtnl_ifa_attrs def __init__(self, helper, nlm_type): super().__init__(helper, nlm_type) diff --git a/tests/sys/netlink/test_rtnl_iface.py b/tests/sys/netlink/test_rtnl_iface.py index 7cff592b1676..ecc932c6213e 100644 --- a/tests/sys/netlink/test_rtnl_iface.py +++ b/tests/sys/netlink/test_rtnl_iface.py @@ -17,6 +17,7 @@ from atf_python.sys.net.netlink import NlmBaseFlags from atf_python.sys.net.netlink import NlmNewFlags from atf_python.sys.net.netlink import NlMsgType from atf_python.sys.net.netlink import NlRtMsgType +from atf_python.sys.net.netlink import rtnl_ifla_attrs from atf_python.sys.net.vnet import SingleVnetTestTemplate @@ -92,6 +93,40 @@ class TestRtNlIface(NetlinkTestTemplate, SingleVnetTestTemplate): self.get_interface_byname("lo10") @pytest.mark.require_user("root") + def test_create_iface_plain_retvals(self): + """Tests loopback creation w/o any parameters""" + 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, "lo10")) + msg.add_nla( + NlAttrNested( + IflattrType.IFLA_LINKINFO, + [ + NlAttrStrn(IflinkInfo.IFLA_INFO_KIND, "lo"), + ], + ) + ) + + rx_msg = self.get_reply(msg) + assert rx_msg.is_type(NlMsgType.NLMSG_ERROR) + assert rx_msg.error_code == 0 + assert rx_msg.cookie is not None + nla_list, _ = rx_msg.parse_attrs(bytes(rx_msg.cookie)[4:], rtnl_ifla_attrs) + nla_map = {n.nla_type: n for n in nla_list} + assert IflattrType.IFLA_IFNAME.value in nla_map + assert nla_map[IflattrType.IFLA_IFNAME.value].text == "lo10" + assert IflattrType.IFLA_NEW_IFINDEX.value in nla_map + assert nla_map[IflattrType.IFLA_NEW_IFINDEX.value].u32 > 0 + + lo_msg = self.get_interface_byname("lo10") + assert ( + lo_msg.base_hdr.ifi_index == nla_map[IflattrType.IFLA_NEW_IFINDEX.value].u32 + ) + + @pytest.mark.require_user("root") def test_create_iface_attrs(self): """Tests interface creation with additional properties""" flags = NlmNewFlags.NLM_F_EXCL.value | NlmNewFlags.NLM_F_CREATE.value |