git: c35a43b261f8 - main - netlink: allow exact-match route lookups via RTM_GETROUTE.
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sun, 02 Apr 2023 13:50:45 UTC
The branch main has been updated by melifaro: URL: https://cgit.FreeBSD.org/src/commit/?id=c35a43b261f807fd85b8cc30306112eee9dd62ce commit c35a43b261f807fd85b8cc30306112eee9dd62ce Author: Alexander V. Chernikov <melifaro@FreeBSD.org> AuthorDate: 2023-04-02 13:47:10 +0000 Commit: Alexander V. Chernikov <melifaro@FreeBSD.org> CommitDate: 2023-04-02 13:47:10 +0000 netlink: allow exact-match route lookups via RTM_GETROUTE. Use already-existing RTM_F_PREFIX rtm_flag to indicate that the request assumes exact-prefix lookup instead of the longest-prefix-match. MFC after: 2 weeks --- sys/net/route/route_ctl.c | 14 ++++++++++++++ sys/net/route/route_ctl.h | 6 ++---- sys/netlink/route/rt.c | 13 ++++++++++--- 3 files changed, 26 insertions(+), 7 deletions(-) diff --git a/sys/net/route/route_ctl.c b/sys/net/route/route_ctl.c index 755765869e84..db3728c3cd88 100644 --- a/sys/net/route/route_ctl.c +++ b/sys/net/route/route_ctl.c @@ -96,6 +96,8 @@ static int delete_route(struct rib_head *rnh, struct rtentry *rt, static int rt_delete_conditional(struct rib_head *rnh, struct rtentry *rt, int prio, rib_filter_f_t *cb, void *cbdata, struct rib_cmd_info *rc); +static bool fill_pxmask_family(int family, int plen, struct sockaddr *_dst, + struct sockaddr **pmask); static int get_prio_from_info(const struct rt_addrinfo *info); static int nhop_get_prio(const struct nhop_object *nh); @@ -391,6 +393,18 @@ lookup_prefix(struct rib_head *rnh, const struct rt_addrinfo *info, return (rt); } +const struct rtentry * +rib_lookup_prefix_plen(struct rib_head *rnh, struct sockaddr *dst, int plen, + struct route_nhop_data *rnd) +{ + union sockaddr_union mask_storage; + struct sockaddr *netmask = &mask_storage.sa; + + if (fill_pxmask_family(dst->sa_family, plen, dst, &netmask)) + return (lookup_prefix_bysa(rnh, dst, netmask, rnd)); + return (NULL); +} + static bool fill_pxmask_family(int family, int plen, struct sockaddr *_dst, struct sockaddr **pmask) diff --git a/sys/net/route/route_ctl.h b/sys/net/route/route_ctl.h index b65b64fcdaa0..7a4ed804feb7 100644 --- a/sys/net/route/route_ctl.h +++ b/sys/net/route/route_ctl.h @@ -123,11 +123,9 @@ struct nhop_object; struct nhgrp_object; struct ucred; -const struct rtentry *rib_lookup_prefix(uint32_t fibnum, int family, - const struct sockaddr *dst, const struct sockaddr *netmask, +const struct rtentry * +rib_lookup_prefix_plen(struct rib_head *rnh, struct sockaddr *dst, int plen, struct route_nhop_data *rnd); -const struct rtentry *rib_lookup_lpm(uint32_t fibnum, int family, - const struct sockaddr *dst, struct route_nhop_data *rnd); /* rtentry accessors */ bool rt_is_host(const struct rtentry *rt); diff --git a/sys/netlink/route/rt.c b/sys/netlink/route/rt.c index 6d76390016dd..288ff111a038 100644 --- a/sys/netlink/route/rt.c +++ b/sys/netlink/route/rt.c @@ -461,6 +461,7 @@ struct nl_parsed_route { uint8_t rtm_dst_len; uint8_t rtm_protocol; uint8_t rtm_type; + uint32_t rtm_flags; }; #define _IN(_field) offsetof(struct rtmsg, _field) @@ -488,6 +489,7 @@ static const struct nlfield_parser nlf_p_rtmsg[] = { { .off_in = _IN(rtm_dst_len), .off_out = _OUT(rtm_dst_len), .cb = nlf_get_u8 }, { .off_in = _IN(rtm_protocol), .off_out = _OUT(rtm_protocol), .cb = nlf_get_u8 }, { .off_in = _IN(rtm_type), .off_out = _OUT(rtm_type), .cb = nlf_get_u8 }, + { .off_in = _IN(rtm_flags), .off_out = _OUT(rtm_flags), .cb = nlf_get_u32 }, }; #undef _IN #undef _OUT @@ -581,7 +583,8 @@ handle_rtm_getroute(struct nlpcb *nlp, struct nl_parsed_route *attrs, { RIB_RLOCK_TRACKER; struct rib_head *rnh; - struct rtentry *rt; + const struct rtentry *rt; + struct route_nhop_data rnd; uint32_t fibnum = attrs->rta_table; sa_family_t family = attrs->rtm_family; @@ -596,13 +599,17 @@ handle_rtm_getroute(struct nlpcb *nlp, struct nl_parsed_route *attrs, RIB_RLOCK(rnh); - rt = (struct rtentry *)rnh->rnh_matchaddr(attrs->rta_dst, &rnh->head); + struct sockaddr *dst = attrs->rta_dst; + + if (attrs->rtm_flags & RTM_F_PREFIX) + rt = rib_lookup_prefix_plen(rnh, dst, attrs->rtm_dst_len, &rnd); + else + rt = (const struct rtentry *)rnh->rnh_matchaddr(dst, &rnh->head); if (rt == NULL) { RIB_RUNLOCK(rnh); return (ESRCH); } - struct route_nhop_data rnd; rt_get_rnd(rt, &rnd); rnd.rnd_nhop = nhop_select_func(rnd.rnd_nhop, 0);