From nobody Sat Apr 08 19:44:52 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 4Pv5Kx28Dzz44nb5; Sat, 8 Apr 2023 19:44:53 +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 4Pv5Kw6jP5z4400; Sat, 8 Apr 2023 19:44:52 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1680983092; 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=1+Wr+MfHJiD3atrUPWPcEB+N6pDtXKuheiM5SfyrJok=; b=fE7/wYu2nCAIWF7cAs4cDsrUtznLQkrH4mNe/BAPapcUMUZG83/hus4mwZLIgipZjWmRtu feXqmL4NLy6nGm4cPKbSFKMjkwIEn4J7h7seivhusYxF2BhcpoXOKr3p8eddbo18NzCWjD cQ/dGWRmO7gxGM37ffHLDotJaVbQzN7AdA0eZTCamY1GIEKiQJAS/q2cAk6esQrhfFfHK9 soCbGSR+FCMDpbRhE5AcPbCnEUWzROLB43GISMG7YxNYroct626ST1R/2C6dRKYgDSxq8A AQPHC3lItYRTh2ySLCf1MG6e59M4RdkrLLYNVZ8bP1c+DRPcZ1qTvctUyB8P/w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1680983093; 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=1+Wr+MfHJiD3atrUPWPcEB+N6pDtXKuheiM5SfyrJok=; b=j/m1H/WI13M5cyoFlMHRR1QD3FHRSwwKIycRgn3pVn1dR7tX42mQr4NAWC/lo7WFU2U0WN 1tL/saeGiA6d97OVNbNZg2OYE3elaRxK7mmGcEGIM9kpoDxUveatzDDKi68F4JkQr9vj0v aUct1ViqioQAu92v8LQo5dDwSdOdL8h7mKPDF2bT/aj0tfFDkmggREQ7mJwbeWMeiCdWHp llDjC4wIkX+ZqhkH8uUlZJFJB6y4yvjKSjkF0j7AXZR+uwD79t3cNGWio1UDk4qvivpym8 uZw6TryEJRO6liJ0ZbD7ncIF1GjDM5k19nnB2OCrrw8ejyBwvEJPVH63rnN8Ww== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1680983093; a=rsa-sha256; cv=none; b=RNtPtwwZXLsOgj1qx6S0UsMrOB29eu23CODum0Wi5OpZ1WHY4AgpzwLkmptR/cDteA4PnX HvcnWDtkFGRfSIwFIBeo+eANueLfL8jFARzWTMtuH1exrAS7CLqsRn7gJ5LMr22L2udewi UnXVownwKfz+BSMUog0Q4umZB5Dp6163yGa+1ri+jF3f5I/p2p1LZnI0qFAOM80hD1RqBL fImXfLhI1XP503mKs839F/vbmSyxX4NVk86u2DxFzaCeC2/G8B0rIv2W28OIuyKGIPEOPr lRjtw1Gd8PLuuEhp6L4VxcRzZvZf5G+xxldVxoS+xdHbPiSkWJ6M2RrQGoearg== 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 4Pv5Kw2CkMzg3L; Sat, 8 Apr 2023 19:44:52 +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 338Jiqp2018733; Sat, 8 Apr 2023 19:44:52 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 338Jiq7r018732; Sat, 8 Apr 2023 19:44:52 GMT (envelope-from git) Date: Sat, 8 Apr 2023 19:44:52 GMT Message-Id: <202304081944.338Jiq7r018732@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: 22b7b3250b2e - stable/13 - netlink: add snl(3) default parsers for routes and links. 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: 22b7b3250b2ef5ba98500601221dbc1461b3652b Auto-Submitted: auto-generated X-ThisMailContainsUnwantedMimeParts: N The branch stable/13 has been updated by melifaro: URL: https://cgit.FreeBSD.org/src/commit/?id=22b7b3250b2ef5ba98500601221dbc1461b3652b commit 22b7b3250b2ef5ba98500601221dbc1461b3652b Author: Alexander V. Chernikov AuthorDate: 2023-03-09 14:43:56 +0000 Commit: Alexander V. Chernikov CommitDate: 2023-04-08 19:06:01 +0000 netlink: add snl(3) default parsers for routes and links. This change adds the "default" parsers of _all_ route/link attributes exported by the kernel. It removes the need to declare similar parsers in the userland applications, simplifying their logic. Differential Revision: https://reviews.freebsd.org/D38979 MFC after: 2 weeks (cherry picked from commit 595d23f777dc24cb285b072c596ca96bbc2db3cd) --- sys/netlink/netlink_snl.h | 14 ++ sys/netlink/netlink_snl_route_parsers.h | 222 ++++++++++++++++++++++++++++++++ tests/sys/netlink/test_snl.c | 13 ++ 3 files changed, 249 insertions(+) diff --git a/sys/netlink/netlink_snl.h b/sys/netlink/netlink_snl.h index 19b3e2f985f3..4e6524783310 100644 --- a/sys/netlink/netlink_snl.h +++ b/sys/netlink/netlink_snl.h @@ -518,6 +518,20 @@ snl_attr_get_nla(struct snl_state *ss __unused, struct nlattr *nla, return (true); } +static inline bool +snl_attr_copy_struct(struct snl_state *ss, struct nlattr *nla, + const void *arg __unused, void *target) +{ + void *ptr = snl_allocz(ss, NLA_DATA_LEN(nla)); + + if (ptr != NULL) { + memcpy(ptr, NLA_DATA(nla), NLA_DATA_LEN(nla)); + *((void **)target) = ptr; + return (true); + } + return (false); +} + static inline void snl_field_get_uint8(struct snl_state *ss __unused, void *src, void *target) { diff --git a/sys/netlink/netlink_snl_route_parsers.h b/sys/netlink/netlink_snl_route_parsers.h new file mode 100644 index 000000000000..a76fb7da8ec2 --- /dev/null +++ b/sys/netlink/netlink_snl_route_parsers.h @@ -0,0 +1,222 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2023 Alexander V. Chernikov + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef _NETLINK_NETLINK_SNL_ROUTE_PARSERS_H_ +#define _NETLINK_NETLINK_SNL_ROUTE_PARSERS_H_ + +#include +#include + +/* TODO: this file should be generated automatically */ + +/* RTM_ROUTE message parser */ + +struct rta_mpath_nh { + struct sockaddr *gw; + uint32_t ifindex; + uint8_t rtnh_flags; + uint8_t rtnh_weight; + uint32_t rtax_mtu; + uint32_t rta_rtflags; +}; + +#define _IN(_field) offsetof(struct rtnexthop, _field) +#define _OUT(_field) offsetof(struct rta_mpath_nh, _field) +static const struct snl_attr_parser _nla_p_mp_nh_metrics[] = { + { .type = NL_RTAX_MTU, .off = _OUT(rtax_mtu), .cb = snl_attr_get_uint32 }, +}; +SNL_DECLARE_ATTR_PARSER(_metrics_mp_nh_parser, _nla_p_mp_nh_metrics); + +static const struct snl_attr_parser _nla_p_mp_nh[] = { + { .type = NL_RTA_GATEWAY, .off = _OUT(gw), .cb = snl_attr_get_ip }, + { .type = NL_RTA_METRICS, .arg = &_metrics_mp_nh_parser, .cb = snl_attr_get_nested }, + { .type = NL_RTA_RTFLAGS, .off = _OUT(rta_rtflags), .cb = snl_attr_get_uint32 }, + { .type = NL_RTA_VIA, .off = _OUT(gw), .cb = snl_attr_get_ipvia }, +}; + +static const struct snl_field_parser _fp_p_mp_nh[] = { + { .off_in = _IN(rtnh_flags), .off_out = _OUT(rtnh_flags), .cb = snl_field_get_uint8 }, + { .off_in = _IN(rtnh_hops), .off_out = _OUT(rtnh_weight), .cb = snl_field_get_uint8 }, + { .off_in = _IN(rtnh_ifindex), .off_out = _OUT(ifindex), .cb = snl_field_get_uint32 }, +}; +#undef _IN +#undef _OUT +SNL_DECLARE_PARSER(_mpath_nh_parser, struct rtnexthop, _fp_p_mp_nh, _nla_p_mp_nh); + +struct rta_mpath { + int num_nhops; + struct rta_mpath_nh nhops[0]; +}; + +static bool +nlattr_get_multipath(struct snl_state *ss, struct nlattr *nla, const void *arg, void *target) +{ + int data_len = nla->nla_len - sizeof(struct nlattr); + struct rtnexthop *rtnh; + + int max_nhops = data_len / sizeof(struct rtnexthop); + size_t sz = (max_nhops + 2) * sizeof(struct rta_mpath_nh); + + struct rta_mpath *mp = snl_allocz(ss, sz); + mp->num_nhops = 0; + + for (rtnh = (struct rtnexthop *)(nla + 1); data_len > 0; ) { + struct rta_mpath_nh *mpnh = &mp->nhops[mp->num_nhops++]; + + if (!snl_parse_header(ss, rtnh, rtnh->rtnh_len, &_mpath_nh_parser, mpnh)) + return (false); + + int len = NL_ITEM_ALIGN(rtnh->rtnh_len); + data_len -= len; + rtnh = (struct rtnexthop *)((char *)rtnh + len); + } + if (data_len != 0 || mp->num_nhops == 0) { + return (false); + } + + *((struct rta_mpath **)target) = mp; + return (true); +} + +struct snl_parsed_route { + struct sockaddr *rta_dst; + struct sockaddr *rta_gw; + struct nlattr *rta_metrics; + struct rta_mpath *rta_multipath; + uint32_t rta_expires; + uint32_t rta_oif; + uint32_t rta_expire; + uint32_t rta_table; + uint32_t rta_knh_id; + uint32_t rta_nh_id; + uint32_t rta_rtflags; + uint32_t rtax_mtu; + uint32_t rtax_weight; + uint8_t rtm_family; + uint8_t rtm_type; + uint8_t rtm_protocol; + uint8_t rtm_dst_len; +}; + +#define _IN(_field) offsetof(struct rtmsg, _field) +#define _OUT(_field) offsetof(struct snl_parsed_route, _field) +static const struct snl_attr_parser _nla_p_rtmetrics[] = { + { .type = NL_RTAX_MTU, .off = _OUT(rtax_mtu), .cb = snl_attr_get_uint32 }, +}; +SNL_DECLARE_ATTR_PARSER(_metrics_parser, _nla_p_rtmetrics); + +static const struct snl_attr_parser _nla_p_route[] = { + { .type = NL_RTA_DST, .off = _OUT(rta_dst), .cb = snl_attr_get_ip }, + { .type = NL_RTA_OIF, .off = _OUT(rta_oif), .cb = snl_attr_get_uint32 }, + { .type = NL_RTA_GATEWAY, .off = _OUT(rta_gw), .cb = snl_attr_get_ip }, + { .type = NL_RTA_METRICS, .arg = &_metrics_parser, .cb = snl_attr_get_nested }, + { .type = NL_RTA_MULTIPATH, .off = _OUT(rta_multipath), .cb = nlattr_get_multipath }, + { .type = NL_RTA_KNH_ID, .off = _OUT(rta_knh_id), .cb = snl_attr_get_uint32 }, + { .type = NL_RTA_WEIGHT, .off = _OUT(rtax_weight), .cb = snl_attr_get_uint32 }, + { .type = NL_RTA_RTFLAGS, .off = _OUT(rta_rtflags), .cb = snl_attr_get_uint32 }, + { .type = NL_RTA_TABLE, .off = _OUT(rta_table), .cb = snl_attr_get_uint32 }, + { .type = NL_RTA_VIA, .off = _OUT(rta_gw), .cb = snl_attr_get_ipvia }, + { .type = NL_RTA_EXPIRES, .off = _OUT(rta_expire), .cb = snl_attr_get_uint32 }, + { .type = NL_RTA_NH_ID, .off = _OUT(rta_nh_id), .cb = snl_attr_get_uint32 }, +}; + +static const struct snl_field_parser _fp_p_route[] = { + {.off_in = _IN(rtm_family), .off_out = _OUT(rtm_family), .cb = snl_field_get_uint8 }, + {.off_in = _IN(rtm_type), .off_out = _OUT(rtm_type), .cb = snl_field_get_uint8 }, + {.off_in = _IN(rtm_protocol), .off_out = _OUT(rtm_protocol), .cb = snl_field_get_uint8 }, + {.off_in = _IN(rtm_dst_len), .off_out = _OUT(rtm_dst_len), .cb = snl_field_get_uint8 }, +}; +#undef _IN +#undef _OUT +SNL_DECLARE_PARSER(snl_rtm_route_parser, struct rtmsg, _fp_p_route, _nla_p_route); + +/* RTM_LINK message parser */ +struct snl_parsed_link { + uint32_t ifi_index; + uint32_t ifi_flags; + uint32_t ifi_change; + uint16_t ifi_type; + uint8_t ifla_operstate; + uint8_t ifla_carrier; + uint32_t ifla_mtu; + char *ifla_ifname; + struct nlattr *ifla_address; + struct nlattr *ifla_broadcast; + char *ifla_ifalias; + uint32_t ifla_promiscuity; + struct rtnl_link_stats64 *ifla_stats64; +}; + +#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[] = { + { .type = IFLA_ADDRESS, .off = _OUT(ifla_address), .cb = snl_attr_get_nla }, + { .type = IFLA_BROADCAST, .off = _OUT(ifla_broadcast), .cb = snl_attr_get_nla }, + { .type = IFLA_IFNAME, .off = _OUT(ifla_ifname), .cb = snl_attr_get_string }, + { .type = IFLA_MTU, .off = _OUT(ifla_mtu), .cb = snl_attr_get_uint32 }, + { .type = IFLA_OPERSTATE, .off = _OUT(ifla_operstate), .cb = snl_attr_get_uint8 }, + { .type = IFLA_IFALIAS, .off = _OUT(ifla_ifalias), .cb = snl_attr_get_string }, + { .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 }, +}; +static const struct snl_field_parser _fp_p_link[] = { + {.off_in = _IN(ifi_index), .off_out = _OUT(ifi_index), .cb = snl_field_get_uint32 }, + {.off_in = _IN(ifi_flags), .off_out = _OUT(ifi_flags), .cb = snl_field_get_uint32 }, + {.off_in = _IN(ifi_change), .off_out = _OUT(ifi_change), .cb = snl_field_get_uint32 }, + {.off_in = _IN(ifi_type), .off_out = _OUT(ifi_type), .cb = snl_field_get_uint16 }, +}; +#undef _IN +#undef _OUT +SNL_DECLARE_PARSER(snl_rtm_link_parser, struct ifinfomsg, _fp_p_link, _nla_p_link); + +struct snl_parsed_link_simple { + uint32_t ifi_index; + uint32_t ifla_mtu; + uint16_t ifi_type; + char *ifla_ifname; +}; + +#define _IN(_field) offsetof(struct ifinfomsg, _field) +#define _OUT(_field) offsetof(struct snl_parsed_link_simple, _field) +static struct snl_attr_parser _nla_p_link_s[] = { + { .type = IFLA_IFNAME, .off = _OUT(ifla_ifname), .cb = snl_attr_get_string }, + { .type = IFLA_MTU, .off = _OUT(ifla_mtu), .cb = snl_attr_get_uint32 }, +}; +static struct snl_field_parser _fp_p_link_s[] = { + {.off_in = _IN(ifi_index), .off_out = _OUT(ifi_index), .cb = snl_field_get_uint32 }, + {.off_in = _IN(ifi_type), .off_out = _OUT(ifi_type), .cb = snl_field_get_uint16 }, +}; +#undef _IN +#undef _OUT +SNL_DECLARE_PARSER(snl_rtm_link_parser_simple, struct ifinfomsg, _fp_p_link_s, _nla_p_link_s); + +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, +}; + +#endif diff --git a/tests/sys/netlink/test_snl.c b/tests/sys/netlink/test_snl.c index d917d81d967d..daacc1aaacec 100644 --- a/tests/sys/netlink/test_snl.c +++ b/tests/sys/netlink/test_snl.c @@ -9,6 +9,7 @@ #include #include "netlink/netlink_snl.h" #include "netlink/netlink_snl_route.h" +#include "netlink/netlink_snl_route_parsers.h" #include @@ -19,6 +20,17 @@ require_netlink(void) atf_tc_skip("netlink module not loaded"); } +ATF_TC(snl_verify_parsers); +ATF_TC_HEAD(snl_verify_parsers, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests snl(3) parsers are correct"); +} + +ATF_TC_BODY(snl_verify_parsers, tc) +{ + SNL_VERIFY_PARSERS(snl_all_route_parsers); + +} ATF_TC(snl_list_ifaces); ATF_TC_HEAD(snl_list_ifaces, tc) @@ -87,6 +99,7 @@ ATF_TC_BODY(snl_list_ifaces, tc) ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, snl_list_ifaces); + ATF_TP_ADD_TC(tp, snl_verify_parsers); return (atf_no_error()); }