diff options
| author | Pouria Mousavizadeh Tehrani <pouria@FreeBSD.org> | 2026-02-18 18:12:35 +0000 |
|---|---|---|
| committer | Pouria Mousavizadeh Tehrani <pouria@FreeBSD.org> | 2026-02-18 19:42:29 +0000 |
| commit | e1e18cc12e68762b641646b203d9ac42d10e3b1f (patch) | |
| tree | 3dc79949762d2586ee8c5c763bc1bea51a0e526e /tests | |
| parent | 07d29f9c177e731e4497bedf5fde09176c90b444 (diff) | |
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/sys/netlink/Makefile | 1 | ||||
| -rw-r--r-- | tests/sys/netlink/test_rtnl_gre.c | 173 |
2 files changed, 174 insertions, 0 deletions
diff --git a/tests/sys/netlink/Makefile b/tests/sys/netlink/Makefile index c07ef8663867..43b9db80ee63 100644 --- a/tests/sys/netlink/Makefile +++ b/tests/sys/netlink/Makefile @@ -5,6 +5,7 @@ TESTSDIR= ${TESTSBASE}/sys/netlink ATF_TESTS_C+= netlink_socket ATF_TESTS_C+= test_snl test_snl_generic +ATF_TESTS_C+= test_rtnl_gre ATF_TESTS_PYTEST += test_nl_core.py ATF_TESTS_PYTEST += test_rtnl_iface.py ATF_TESTS_PYTEST += test_rtnl_ifaddr.py diff --git a/tests/sys/netlink/test_rtnl_gre.c b/tests/sys/netlink/test_rtnl_gre.c new file mode 100644 index 000000000000..12ecc8d14230 --- /dev/null +++ b/tests/sys/netlink/test_rtnl_gre.c @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2026 Pouria Mousavizadeh Tehrani <pouria@FreeBSD.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <sys/param.h> +#include <sys/module.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <net/if_gre.h> + +#include <netlink/netlink.h> +#include <netlink/netlink_route.h> +#include "netlink/netlink_snl.h" +#include <netlink/netlink_snl_route.h> +#include <netlink/netlink_snl_route_compat.h> +#include <netlink/netlink_snl_route_parsers.h> + +#include <atf-c.h> + +struct nl_parsed_gre { + struct sockaddr *ifla_local; + struct sockaddr *ifla_remote; + uint32_t ifla_flags; + uint32_t ifla_okey; + uint32_t ifla_encap_type; + uint16_t ifla_encap_sport; +}; + +struct nla_gre_info { + const char *kind; + struct nl_parsed_gre data; +}; + +struct nla_gre_link { + uint32_t ifi_index; + struct nla_gre_info linkinfo; +}; + +#define _OUT(_field) offsetof(struct nl_parsed_gre, _field) +static const struct snl_attr_parser nla_p_gre[] = { + { .type = IFLA_GRE_LOCAL, .off = _OUT(ifla_local), .cb = snl_attr_get_ip }, + { .type = IFLA_GRE_REMOTE, .off = _OUT(ifla_remote), .cb = snl_attr_get_ip }, + { .type = IFLA_GRE_FLAGS, .off = _OUT(ifla_flags), .cb = snl_attr_get_uint32 }, + { .type = IFLA_GRE_OKEY, .off = _OUT(ifla_okey), .cb = snl_attr_get_uint32 }, + { .type = IFLA_GRE_ENCAP_TYPE, .off = _OUT(ifla_encap_type), .cb = snl_attr_get_uint32 }, + { .type = IFLA_GRE_ENCAP_SPORT, .off = _OUT(ifla_encap_sport), .cb = snl_attr_get_uint16 }, +}; +#undef _OUT +SNL_DECLARE_ATTR_PARSER(gre_linkinfo_data_parser, nla_p_gre); + +#define _OUT(_field) offsetof(struct nla_gre_info, _field) +static const struct snl_attr_parser ap_gre_linkinfo[] = { + { .type = IFLA_INFO_KIND, .off = _OUT(kind), .cb = snl_attr_get_string }, + { .type = IFLA_INFO_DATA, .off = _OUT(data), + .arg = &gre_linkinfo_data_parser, .cb = snl_attr_get_nested }, +}; +#undef _OUT +SNL_DECLARE_ATTR_PARSER(gre_linkinfo_parser, ap_gre_linkinfo); + +#define _IN(_field) offsetof(struct ifinfomsg, _field) +#define _OUT(_field) offsetof(struct nla_gre_link, _field) +static const struct snl_attr_parser ap_gre_link[] = { + { .type = IFLA_LINKINFO, .off = _OUT(linkinfo), + .arg = &gre_linkinfo_parser, .cb = snl_attr_get_nested }, +}; + +static const struct snl_field_parser fp_gre_link[] = { + { .off_in = _IN(ifi_index), .off_out = _OUT(ifi_index), .cb = snl_field_get_uint32 }, +}; +#undef _IN +#undef _OUT +SNL_DECLARE_PARSER(gre_parser, struct ifinfomsg, fp_gre_link, ap_gre_link); + +ATF_TC(test_rtnl_gre); +ATF_TC_HEAD(test_rtnl_gre, tc) +{ + atf_tc_set_md_var(tc, "descr", "test gre interface using netlink"); + atf_tc_set_md_var(tc, "require.user", "root"); +} + +ATF_TC_BODY(test_rtnl_gre, tc) +{ + struct snl_state ss; + struct snl_writer nw; + struct nlmsghdr *hdr, *rx_hdr; + struct sockaddr_in src, dst; + struct nla_gre_link lattrs = {}; + struct nl_parsed_gre attrs = {}; + struct snl_errmsg_data e = {}; + struct ifinfomsg *ifmsg; + int off, off2; + + ATF_REQUIRE_MSG(snl_init(&ss, NETLINK_ROUTE), "snl_init() failed"); + + /* Create gre interface */ + snl_init_writer(&ss, &nw); + ATF_REQUIRE((hdr = snl_create_msg_request(&nw, RTM_NEWLINK)) != NULL); + hdr->nlmsg_flags |= (NLM_F_CREATE | NLM_F_EXCL | NLM_F_REQUEST | NLM_F_ACK); + snl_reserve_msg_object(&nw, struct ifinfomsg); + + /* Create parameters */ + snl_add_msg_attr_string(&nw, IFLA_IFNAME, "gre10"); + off = snl_add_msg_attr_nested(&nw, IFLA_LINKINFO); + snl_add_msg_attr_string(&nw, IFLA_INFO_KIND, "gre"); + off2 = snl_add_msg_attr_nested(&nw, IFLA_INFO_DATA); + + src.sin_family = AF_INET; + dst.sin_family = AF_INET; + inet_pton(src.sin_family, "127.0.0.1", &src.sin_addr); + inet_pton(dst.sin_family, "127.0.0.2", &dst.sin_addr); + snl_add_msg_attr_ip(&nw, IFLA_GRE_LOCAL, (struct sockaddr *)&src); + snl_add_msg_attr_ip(&nw, IFLA_GRE_REMOTE, (struct sockaddr *)&dst); + snl_add_msg_attr_u32(&nw, IFLA_GRE_FLAGS, (GRE_ENABLE_SEQ | GRE_ENABLE_CSUM)); + snl_add_msg_attr_u32(&nw, IFLA_GRE_OKEY, 123456); + snl_add_msg_attr_u32(&nw, IFLA_GRE_ENCAP_TYPE, IFLA_TUNNEL_GRE_UDP); + snl_add_msg_attr_u16(&nw, IFLA_GRE_ENCAP_SPORT, 50000); + + snl_end_attr_nested(&nw, off2); + snl_end_attr_nested(&nw, off); + + ATF_REQUIRE((hdr = snl_finalize_msg(&nw)) != NULL); + ATF_REQUIRE(snl_send_message(&ss, hdr)); + ATF_REQUIRE((rx_hdr = snl_read_reply(&ss, hdr->nlmsg_seq)) != NULL); + ATF_REQUIRE(snl_parse_errmsg(&ss, rx_hdr, &e)); + ATF_REQUIRE_INTEQ(e.error, 0); + + /* Dump gre interface */ + snl_init_writer(&ss, &nw); + ATF_REQUIRE((hdr = snl_create_msg_request(&nw, RTM_GETLINK)) != NULL); + hdr->nlmsg_flags |= NLM_F_DUMP; + snl_reserve_msg_object(&nw, struct ifinfomsg); + snl_add_msg_attr_string(&nw, IFLA_IFNAME, "gre10"); + off = snl_add_msg_attr_nested(&nw, IFLA_LINKINFO); + snl_add_msg_attr_string(&nw, IFLA_INFO_KIND, "gre"); + snl_end_attr_nested(&nw, off); + + ATF_REQUIRE((hdr = snl_finalize_msg(&nw)) != NULL); + ATF_REQUIRE(snl_send_message(&ss, hdr)); + + /* Check parameters */ + ATF_REQUIRE((rx_hdr = snl_read_reply(&ss, hdr->nlmsg_seq)) != NULL); + ATF_CHECK(snl_parse_nlmsg(&ss, rx_hdr, &gre_parser, &lattrs)); + attrs = lattrs.linkinfo.data; + ATF_CHECK_STREQ(lattrs.linkinfo.kind, "gre"); + ATF_CHECK_INTEQ(attrs.ifla_flags, (GRE_ENABLE_SEQ | GRE_ENABLE_CSUM | GRE_UDPENCAP)); + ATF_CHECK_INTEQ(attrs.ifla_okey, 123456); + ATF_CHECK_INTEQ(attrs.ifla_encap_type, IFLA_TUNNEL_GRE_UDP); + ATF_CHECK_INTEQ(attrs.ifla_encap_sport, 50000); + + /* Delete gre interface */ + snl_init_writer(&ss, &nw); + ATF_REQUIRE((hdr = snl_create_msg_request(&nw, RTM_DELLINK)) != NULL); + hdr->nlmsg_flags |= (NLM_F_ACK | NLM_F_REQUEST); + ATF_REQUIRE((ifmsg = snl_reserve_msg_object(&nw, struct ifinfomsg)) != NULL); + ifmsg->ifi_index = lattrs.ifi_index; + ATF_REQUIRE((hdr = snl_finalize_msg(&nw)) != NULL); + ATF_REQUIRE(snl_send_message(&ss, hdr)); + ATF_REQUIRE((rx_hdr = snl_read_reply(&ss, hdr->nlmsg_seq)) != NULL); + ATF_REQUIRE(snl_parse_errmsg(&ss, rx_hdr, &e)); + ATF_REQUIRE_INTEQ(e.error, 0); +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, test_rtnl_gre); + + return (atf_no_error()); +} + |
