From nobody Sat Apr 08 19:45:05 2023 X-Original-To: dev-commits-src-branches@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4Pv5LB0Hb0z44nY4; Sat, 8 Apr 2023 19:45:06 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4Pv5L96Dgtz44gQ; Sat, 8 Apr 2023 19:45:05 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1680983105; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=e/FjXQkK4w/3B+9Fk2oVULiHLSJ9IWsQsGv9m/d7Cmc=; b=CGnG4BK9LbwsJLUQLaUfeGOwWTFm8NihgY8LIbnP3gOkNjf8MdKVGC8CI2o1FfdHoIEBzU dZLp+QOCD0Qk0rcLh/nD/QknoRBWUgPagnyk8pq4C3f+uHqrkcsEkLQ98t/PfS/EZFFxsj r6xml/KfWBaJesSFwGA7U+y26cMNPsctr5EUuqoIc9TOqzX5MFrr4zIAlYMJRH9RlDBLlW gAPiepg7p0XhUwLYKSZQhvWY6a8LcLrHeZ8uosElpCiq5sdJIMjjlkCTj03LXhC0YiI+85 XKqG3RbK47i/t7pDunLHGI7eFLp8vVEM1O+LL4NssIV+Sw8PUBqJNA5LEfssBw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1680983105; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=e/FjXQkK4w/3B+9Fk2oVULiHLSJ9IWsQsGv9m/d7Cmc=; b=ORW95L8NMiL4g+bZvBzO71MQB92B+CrUglUR+jDzRHcVbjJ7vr0lxTsDb+CUm7HShPhTwp SYFjLbIiGFLGLgLzAk1IhsvN6pwZVoB8gQDwVm9nG3sQ3AilKD/dEfrO4HSlKS5tzE7MZC veU4zzi7T/sy6BJjDjuwW1NSsw577/cVknXI5hgWIM+OdNPMcTvsVbXO18YNohyEvqMfxo kIubVZxS8Fx/Uw8M3oW7frY7KFqyP5XV7z8png2tMLST6z7xmsTkgJnOL3jSdG7l0EWeLd S0yeTc0wvh16q4Lvf3t8MHzbUqhZDqP4Bvgc9jwgXdohs2HWvqP2ucf8tv5xJQ== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1680983105; a=rsa-sha256; cv=none; b=UpJc20IXcS583ZC85+J5DSIO2dTUuU+kwS47ztfBMMNgPWxphx3OhfOxaQmgSJkLH1725F TkeZ3Hfr/8GY3mSZt6th8T4UgDWzMvRMAGVMFvPAxYy9qRyVt5PlNWce6JERQzpo1T1/Sv TsR22dxrwWvCU729M5mn7FqDIf+L1hCBI0s04jgfjUzXCDo2EHxB7VAa80yZWmBlRQFbcP LkErRZxcw4/CnQkpUCSNuoonu18I5uucfebZ5bZmDeFM28bUD1iORs/x9iJw1GvBcAwsRL XNfHJmLHFHctGcaKmlnGMg260BrCCIFwpHwHANgp++J4NN4vf+KrJxJfJhmz6g== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4Pv5L95JZNzfxZ; Sat, 8 Apr 2023 19:45:05 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 338Jj5vC018985; Sat, 8 Apr 2023 19:45:05 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 338Jj5Ew018984; Sat, 8 Apr 2023 19:45:05 GMT (envelope-from git) Date: Sat, 8 Apr 2023 19:45:05 GMT Message-Id: <202304081945.338Jj5Ew018984@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: "Alexander V. Chernikov" Subject: git: b18abe2e1f22 - stable/13 - tests: add more netlink tests for neighbors/routes List-Id: Commits to the stable branches of the FreeBSD src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-branches List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-branches@freebsd.org X-BeenThere: dev-commits-src-branches@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: melifaro X-Git-Repository: src X-Git-Refname: refs/heads/stable/13 X-Git-Reftype: branch X-Git-Commit: b18abe2e1f22394717d4847f2c7b491929cee92b Auto-Submitted: auto-generated X-ThisMailContainsUnwantedMimeParts: N The branch stable/13 has been updated by melifaro: URL: https://cgit.FreeBSD.org/src/commit/?id=b18abe2e1f22394717d4847f2c7b491929cee92b commit b18abe2e1f22394717d4847f2c7b491929cee92b Author: Alexander V. Chernikov AuthorDate: 2023-03-07 17:30:35 +0000 Commit: Alexander V. Chernikov CommitDate: 2023-04-08 19:15:16 +0000 tests: add more netlink tests for neighbors/routes Differential Revision: https://reviews.freebsd.org/D38912 MFC after: 2 weeks (cherry picked from commit c57dfd92c876fabc04e94945dd9534468520bbbf) --- tests/atf_python/sys/net/netlink.py | 121 ++++++++++++++++++++++++++++++----- tests/sys/netlink/Makefile | 1 + tests/sys/netlink/test_rtnl_neigh.py | 53 +++++++++++++++ tests/sys/netlink/test_rtnl_route.py | 23 +++++++ 4 files changed, 183 insertions(+), 15 deletions(-) diff --git a/tests/atf_python/sys/net/netlink.py b/tests/atf_python/sys/net/netlink.py index ec5a7feef317..bfbf3217d52a 100644 --- a/tests/atf_python/sys/net/netlink.py +++ b/tests/atf_python/sys/net/netlink.py @@ -29,6 +29,12 @@ def align4(val: int) -> int: return roundup2(val, 4) +def enum_or_int(val) -> int: + if isinstance(val, Enum): + return val.value + return val + + class SockaddrNl(Structure): _fields_ = [ ("nl_len", c_ubyte), @@ -125,8 +131,8 @@ class NlRtMsgType(Enum): RTM_DELROUTE = 25 RTM_GETROUTE = 26 RTM_NEWNEIGH = 28 - RTM_DELNEIGH = 27 - RTM_GETNEIGH = 28 + RTM_DELNEIGH = 29 + RTM_GETNEIGH = 30 RTM_NEWRULE = 32 RTM_DELRULE = 33 RTM_GETRULE = 34 @@ -491,6 +497,39 @@ class IfattrType(Enum): IFA_TARGET_NETNSID = auto() +class NdMsg(Structure): + _fields_ = [ + ("ndm_family", c_ubyte), + ("ndm_pad1", c_ubyte), + ("ndm_pad2", c_ubyte), + ("ndm_ifindex", c_uint), + ("ndm_state", c_ushort), + ("ndm_flags", c_ubyte), + ("ndm_type", c_ubyte), + ] + + +class NdAttrType(Enum): + NDA_UNSPEC = 0 + NDA_DST = 1 + NDA_LLADDR = 2 + NDA_CACHEINFO = 3 + NDA_PROBES = 4 + NDA_VLAN = 5 + NDA_PORT = 6 + NDA_VNI = 7 + NDA_IFINDEX = 8 + NDA_MASTER = 9 + NDA_LINK_NETNSID = 10 + NDA_SRC_VNI = 11 + NDA_PROTOCOL = 12 + NDA_NH_ID = 13 + NDA_FDB_EXT_ATTRS = 14 + NDA_FLAGS_EXT = 15 + NDA_NDM_STATE_MASK = 16 + NDA_NDM_FLAGS_MASK = 17 + + class GenlMsgHdr(Structure): _fields_ = [ ("cmd", c_ubyte), @@ -702,7 +741,7 @@ class NlAttrNested(NlAttr): class NlAttrU32(NlAttr): def __init__(self, nla_type, val): - self.u32 = val + self.u32 = enum_or_int(val) super().__init__(nla_type, b"") @property @@ -729,7 +768,7 @@ class NlAttrU32(NlAttr): class NlAttrU16(NlAttr): def __init__(self, nla_type, val): - self.u16 = val + self.u16 = enum_or_int(val) super().__init__(nla_type, b"") @property @@ -756,7 +795,7 @@ class NlAttrU16(NlAttr): class NlAttrU8(NlAttr): def __init__(self, nla_type, val): - self.u8 = val + self.u8 = enum_or_int(val) super().__init__(nla_type, b"") @property @@ -842,6 +881,11 @@ class NlAttrIfindex(NlAttrU32): return " iface=if#{}".format(self.u32) +class NlAttrMac(NlAttr): + def _print_attr_value(self): + return ["{:02}".format(int(d)) for d in data[4:]].join(":") + + class NlAttrTable(NlAttrU32): def _print_attr_value(self): return " rtable={}".format(self.u32) @@ -1067,26 +1111,44 @@ rtnl_ifa_attrs = prepare_attrs_map( ) +rtnl_nd_attrs = prepare_attrs_map( + [ + AttrDescr(NdAttrType.NDA_DST, NlAttrIp), + AttrDescr(NdAttrType.NDA_IFINDEX, NlAttrIfindex), + AttrDescr(NdAttrType.NDA_FLAGS_EXT, NlAttrU32), + AttrDescr(NdAttrType.NDA_LLADDR, NlAttrMac), + ] +) + + class BaseNetlinkMessage(object): def __init__(self, helper, nlmsg_type): - self.nlmsg_type = nlmsg_type + self.nlmsg_type = enum_or_int(nlmsg_type) self.ut = unittest.TestCase() self.nla_list = [] self._orig_data = None self.helper = helper self.nl_hdr = Nlmsghdr( - nlmsg_type=nlmsg_type, nlmsg_seq=helper.get_seq(), nlmsg_pid=helper.pid + nlmsg_type=self.nlmsg_type, nlmsg_seq=helper.get_seq(), nlmsg_pid=helper.pid ) self.base_hdr = None + def set_request(self, need_ack=True): + self.add_nlflags([NlmBaseFlags.NLM_F_REQUEST]) + if need_ack: + self.add_nlflags([NlmBaseFlags.NLM_F_ACK]) + + def add_nlflags(self, flags: List): + int_flags = 0 + for flag in flags: + int_flags |= enum_or_int(flag) + self.nl_hdr.nlmsg_flags |= int_flags + def add_nla(self, nla): self.nla_list.append(nla) def _get_nla(self, nla_list, nla_type): - if isinstance(nla_type, Enum): - nla_type_raw = nla_type.value - else: - nla_type_raw = nla_type + nla_type_raw = enum_or_int(nla_type) for nla in nla_list: if nla.nla_type == nla_type_raw: return nla @@ -1102,10 +1164,7 @@ class BaseNetlinkMessage(object): return Nlmsghdr.from_buffer_copy(data), sizeof(Nlmsghdr) def is_type(self, nlmsg_type): - if isinstance(nlmsg_type, Enum): - nlmsg_type_raw = nlmsg_type.value - else: - nlmsg_type_raw = nlmsg_type + nlmsg_type_raw = enum_or_int(nlmsg_type) return nlmsg_type_raw == self.nl_hdr.nlmsg_type def is_reply(self, hdr): @@ -1422,6 +1481,37 @@ class NetlinkIfaMessage(BaseNetlinkRtMessage): ) +class NetlinkNdMessage(BaseNetlinkRtMessage): + messages = [ + NlRtMsgType.RTM_NEWNEIGH.value, + NlRtMsgType.RTM_DELNEIGH.value, + NlRtMsgType.RTM_GETNEIGH.value, + ] + nl_attrs_map = rtnl_nd_attrs + + def __init__(self, helper, nlm_type): + super().__init__(helper, nlm_type) + self.base_hdr = NdMsg() + + def parse_base_header(self, data): + if len(data) < sizeof(NdMsg): + raise ValueError("length less than NdMsg header") + nd_hdr = NdMsg.from_buffer_copy(data) + return (nd_hdr, sizeof(NdMsg)) + + def print_base_header(self, hdr, prepend=""): + family = self.helper.get_af_name(hdr.ndm_family) + print( + "{}family={}, ndm_ifindex={}, ndm_state={}, ndm_flags={}".format( # noqa: E501 + prepend, + family, + hdr.ndm_ifindex, + hdr.ndm_state, + hdr.ndm_flags, + ) + ) + + class Nlsock: def __init__(self, family, helper): self.helper = helper @@ -1435,6 +1525,7 @@ class Nlsock: NetlinkRtMessage, NetlinkIflaMessage, NetlinkIfaMessage, + NetlinkNdMessage, NetlinkDoneMessage, NetlinkErrorMessage, ] diff --git a/tests/sys/netlink/Makefile b/tests/sys/netlink/Makefile index cbec7b2d8b5d..16559f0e9d3d 100644 --- a/tests/sys/netlink/Makefile +++ b/tests/sys/netlink/Makefile @@ -9,6 +9,7 @@ ATF_TESTS_C += test_snl test_snl_generic ATF_TESTS_PYTEST += test_nl_core.py ATF_TESTS_PYTEST += test_rtnl_iface.py ATF_TESTS_PYTEST += test_rtnl_ifaddr.py +ATF_TESTS_PYTEST += test_rtnl_neigh.py ATF_TESTS_PYTEST += test_rtnl_route.py CFLAGS+= -I${.CURDIR:H:H:H} diff --git a/tests/sys/netlink/test_rtnl_neigh.py b/tests/sys/netlink/test_rtnl_neigh.py new file mode 100644 index 000000000000..6d6f95098d14 --- /dev/null +++ b/tests/sys/netlink/test_rtnl_neigh.py @@ -0,0 +1,53 @@ +import socket +import pytest + +from atf_python.sys.net.netlink import NdAttrType +from atf_python.sys.net.netlink import NetlinkNdMessage +from atf_python.sys.net.netlink import NetlinkTestTemplate +from atf_python.sys.net.netlink import NlConst +from atf_python.sys.net.netlink import NlRtMsgType +from atf_python.sys.net.vnet import SingleVnetTestTemplate + + +class TestRtNlNeigh(NetlinkTestTemplate, SingleVnetTestTemplate): + def setup_method(self, method): + method_name = method.__name__ + if "4" in method_name: + self.IPV4_PREFIXES = ["192.0.2.1/24"] + if "6" in method_name: + self.IPV6_PREFIXES = ["2001:db8::1/64"] + super().setup_method(method) + self.setup_netlink(NlConst.NETLINK_ROUTE) + + def filter_iface(self, family, num_items): + epair_ifname = self.vnet.iface_alias_map["if1"].name + epair_ifindex = socket.if_nametoindex(epair_ifname) + + msg = NetlinkNdMessage(self.helper, NlRtMsgType.RTM_GETNEIGH) + msg.set_request() + msg.base_hdr.ndm_family = family + msg.base_hdr.ndm_ifindex = epair_ifindex + self.write_message(msg) + + ret = [] + for rx_msg in self.read_msg_list( + msg.nl_hdr.nlmsg_seq, NlRtMsgType.RTM_NEWNEIGH + ): + ifname = socket.if_indextoname(rx_msg.base_hdr.ndm_ifindex) + family = rx_msg.base_hdr.ndm_family + assert ifname == epair_ifname + assert family == family + assert rx_msg.get_nla(NdAttrType.NDA_DST) is not None + assert rx_msg.get_nla(NdAttrType.NDA_LLADDR) is not None + ret.append(rx_msg) + assert len(ret) == num_items + + @pytest.mark.timeout(5) + def test_6_filter_iface(self): + """Tests that listing outputs all nd6 records""" + return self.filter_iface(socket.AF_INET6, 2) + + @pytest.mark.timeout(5) + def test_4_filter_iface(self): + """Tests that listing outputs all arp records""" + return self.filter_iface(socket.AF_INET, 1) diff --git a/tests/sys/netlink/test_rtnl_route.py b/tests/sys/netlink/test_rtnl_route.py index 71125343166a..b64fce57a518 100644 --- a/tests/sys/netlink/test_rtnl_route.py +++ b/tests/sys/netlink/test_rtnl_route.py @@ -2,9 +2,11 @@ import ipaddress import socket import pytest +from atf_python.sys.net.tools import ToolsHelper from atf_python.sys.net.netlink import NetlinkRtMessage from atf_python.sys.net.netlink import NetlinkTestTemplate from atf_python.sys.net.netlink import NlAttrIp +from atf_python.sys.net.netlink import NlAttrU32 from atf_python.sys.net.netlink import NlConst from atf_python.sys.net.netlink import NlmBaseFlags from atf_python.sys.net.netlink import NlmGetFlags @@ -22,6 +24,27 @@ class TestRtNlRoute(NetlinkTestTemplate, SingleVnetTestTemplate): super().setup_method(method) self.setup_netlink(NlConst.NETLINK_ROUTE) + @pytest.mark.timeout(5) + def test_add_route6_ll_gw(self): + epair_ifname = self.vnet.iface_alias_map["if1"].name + epair_ifindex = socket.if_nametoindex(epair_ifname) + + msg = NetlinkRtMessage(self.helper, NlRtMsgType.RTM_NEWROUTE) + msg.set_request() + msg.add_nlflags([NlmNewFlags.NLM_F_CREATE]) + msg.base_hdr.rtm_family = socket.AF_INET6 + msg.base_hdr.rtm_dst_len = 64 + msg.add_nla(NlAttrIp(RtattrType.RTA_DST, "2001:db8:2::")) + msg.add_nla(NlAttrIp(RtattrType.RTA_GATEWAY, "fe80::1")) + msg.add_nla(NlAttrU32(RtattrType.RTA_OIF, epair_ifindex)) + + rx_msg = self.get_reply(msg) + assert rx_msg.is_type(NlMsgType.NLMSG_ERROR) + assert rx_msg.error_code == 0 + + ToolsHelper.print_net_debug() + ToolsHelper.print_output("netstat -6onW") + @pytest.mark.timeout(20) def test_buffer_override(self): msg_flags = (