Date: Mon, 30 Mar 2026 16:15:41 +0000 From: Mark Johnston <markj@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org Subject: git: 0bb9c2b665d9 - main - ip6_mroute: FIBify Message-ID: <69caa1ad.3c307.55d18a69@gitrepo.freebsd.org>
index | next in thread | raw e-mail
The branch main has been updated by markj: URL: https://cgit.FreeBSD.org/src/commit/?id=0bb9c2b665d90934ae16eee152b6b4f4f4be0dd5 commit 0bb9c2b665d90934ae16eee152b6b4f4f4be0dd5 Author: Mark Johnston <markj@FreeBSD.org> AuthorDate: 2026-03-30 13:31:55 +0000 Commit: Mark Johnston <markj@FreeBSD.org> CommitDate: 2026-03-30 16:08:21 +0000 ip6_mroute: FIBify Modify the control plane (ioctl and socket option handlers) to use the routing socket FIB to index into the mfctable array. Modify the forwarding plane to use the mbuf's FIB to determine which routing table to use. MFC after: 2 weeks Sponsored by: Stormshield Sponsored by: Klara, Inc. Differential Revision: https://reviews.freebsd.org/D55242 --- sys/netinet6/in6.c | 17 +++--- sys/netinet6/ip6_mroute.c | 131 +++++++++++++++++++++++++++------------------- sys/netinet6/ip6_mroute.h | 2 +- sys/netinet6/raw_ip6.c | 2 +- 4 files changed, 85 insertions(+), 67 deletions(-) diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c index eb6c327de76f..cf2720cac036 100644 --- a/sys/netinet6/in6.c +++ b/sys/netinet6/in6.c @@ -279,17 +279,6 @@ in6_control_ioctl(u_long cmd, void *data, ifra->ifra_vhid = 0; } - switch (cmd) { - case SIOCGETSGCNT_IN6: - case SIOCGETMIFCNT_IN6: - /* - * XXX mrt_ioctl has a 3rd, unused, FIB argument in route.c. - * We cannot see how that would be needed, so do not adjust the - * KPI blindly; more likely should clean up the IPv4 variant. - */ - return (mrt6_ioctl ? mrt6_ioctl(cmd, data) : EOPNOTSUPP); - } - switch (cmd) { case SIOCAADDRCTL_POLICY: case SIOCDADDRCTL_POLICY: @@ -615,6 +604,12 @@ int in6_control(struct socket *so, u_long cmd, void *data, struct ifnet *ifp, struct thread *td) { + switch (cmd) { + case SIOCGETSGCNT_IN6: + case SIOCGETMIFCNT_IN6: + return (mrt6_ioctl ? + mrt6_ioctl(cmd, data, so->so_fibnum) : EOPNOTSUPP); + } return (in6_control_ioctl(cmd, data, ifp, td ? td->td_ucred : NULL)); } diff --git a/sys/netinet6/ip6_mroute.c b/sys/netinet6/ip6_mroute.c index fff68a7ff47d..52fd319ba4f4 100644 --- a/sys/netinet6/ip6_mroute.c +++ b/sys/netinet6/ip6_mroute.c @@ -216,8 +216,11 @@ static eventhandler_tag rtnumfibs_change_tag; static int sysctl_mfctable(SYSCTL_HANDLER_ARGS) { - return (SYSCTL_OUT(req, &V_mfctables[0].mfchashtbl, - sizeof(V_mfctables[0].mfchashtbl))); + int fibnum; + + fibnum = curthread->td_proc->p_fibnum; + return (SYSCTL_OUT(req, &V_mfctables[fibnum].mfchashtbl, + sizeof(struct mfc6c *) * MF6CTBLSIZ)); } SYSCTL_PROC(_net_inet6_ip6, OID_AUTO, mf6ctable, CTLTYPE_OPAQUE | CTLFLAG_RD, @@ -229,13 +232,15 @@ static int sysctl_mif6table(SYSCTL_HANDLER_ARGS) { struct mif6_sctl *out; + struct mf6ctable *mfct; int error; + mfct = &V_mfctables[curthread->td_proc->p_fibnum]; out = malloc(sizeof(struct mif6_sctl) * MAXMIFS, M_TEMP, M_WAITOK | M_ZERO); for (int i = 0; i < MAXMIFS; i++) { struct mif6_sctl *outp = &out[i]; - struct mif6 *mifp = &V_mfctables[0].miftable[i]; + struct mif6 *mifp = &mfct->miftable[i]; outp->m6_flags = mifp->m6_flags; outp->m6_rate_limit = mifp->m6_rate_limit; @@ -287,7 +292,8 @@ VNET_DEFINE_STATIC(u_int, mrt6debug) = 0; /* debug level */ #define MRT6_DLOG(m, fmt, ...) #endif -static void expire_upcalls(void *); +static void expire_upcalls(struct mf6ctable *); +static void expire_upcalls_all(void *); #define EXPIRE_TIMEOUT (hz / 4) /* 4x / second */ #define UPCALL_EXPIRE 6 /* number of timeouts */ @@ -342,13 +348,13 @@ static void collate(struct timeval *); #endif /* UPCALL_TIMING */ static int ip6_mrouter_init(struct socket *, int, int); -static int add_m6fc(struct mf6cctl *); -static int add_m6if(struct mif6ctl *); -static int del_m6fc(struct mf6cctl *); -static int del_m6if(mifi_t *); -static int del_m6if_locked(mifi_t *); -static int get_mif6_cnt(struct sioc_mif_req6 *); -static int get_sg_cnt(struct sioc_sg_req6 *); +static int add_m6fc(struct mf6ctable *, struct mf6cctl *); +static int add_m6if(struct mf6ctable *, int, struct mif6ctl *); +static int del_m6fc(struct mf6ctable *, struct mf6cctl *); +static int del_m6if(struct mf6ctable *, mifi_t *); +static int del_m6if_locked(struct mf6ctable *, mifi_t *); +static int get_mif6_cnt(struct mf6ctable *, struct sioc_mif_req6 *); +static int get_sg_cnt(struct mf6ctable *, struct sioc_sg_req6 *); VNET_DEFINE_STATIC(struct callout, expire_upcalls_ch); #define V_expire_upcalls_ch VNET(expire_upcalls_ch) @@ -357,7 +363,7 @@ static int X_ip6_mforward(struct ip6_hdr *, struct ifnet *, struct mbuf *); static void X_ip6_mrouter_done(struct socket *); static int X_ip6_mrouter_set(struct socket *, struct sockopt *); static int X_ip6_mrouter_get(struct socket *, struct sockopt *); -static int X_mrt6_ioctl(u_long, caddr_t); +static int X_mrt6_ioctl(u_long, caddr_t, int); static struct mf6c * mf6c_find(const struct mf6ctable *mfct, const struct in6_addr *origin, @@ -376,6 +382,17 @@ mf6c_find(const struct mf6ctable *mfct, const struct in6_addr *origin, return (NULL); } +static struct mf6ctable * +somfctable(struct socket *so) +{ + int fib; + + fib = atomic_load_int(&so->so_fibnum); + KASSERT(fib >= 0 && fib < V_nmfctables, + ("%s: so_fibnum %d out of range", __func__, fib)); + return (&V_mfctables[fib]); +} + /* * Handle MRT setsockopt commands to modify the multicast routing tables. */ @@ -389,7 +406,7 @@ X_ip6_mrouter_set(struct socket *so, struct sockopt *sopt) struct mf6cctl mfcc; mifi_t mifi; - mfct = &V_mfctables[0]; + mfct = somfctable(so); if (so != mfct->router && sopt->sopt_name != MRT6_INIT) return (EPERM); @@ -411,25 +428,25 @@ X_ip6_mrouter_set(struct socket *so, struct sockopt *sopt) error = sooptcopyin(sopt, &mifc, sizeof(mifc), sizeof(mifc)); if (error) break; - error = add_m6if(&mifc); + error = add_m6if(mfct, so->so_fibnum, &mifc); break; case MRT6_ADD_MFC: error = sooptcopyin(sopt, &mfcc, sizeof(mfcc), sizeof(mfcc)); if (error) break; - error = add_m6fc(&mfcc); + error = add_m6fc(mfct, &mfcc); break; case MRT6_DEL_MFC: error = sooptcopyin(sopt, &mfcc, sizeof(mfcc), sizeof(mfcc)); if (error) break; - error = del_m6fc(&mfcc); + error = del_m6fc(mfct, &mfcc); break; case MRT6_DEL_MIF: error = sooptcopyin(sopt, &mifi, sizeof(mifi), sizeof(mifi)); if (error) break; - error = del_m6if(&mifi); + error = del_m6if(mfct, &mifi); break; case MRT6_PIM: error = sooptcopyin(sopt, &optval, sizeof(optval), @@ -455,7 +472,7 @@ X_ip6_mrouter_get(struct socket *so, struct sockopt *sopt) struct mf6ctable *mfct; int error = 0; - mfct = &V_mfctables[0]; + mfct = somfctable(so); if (so != mfct->router) return (EACCES); @@ -471,24 +488,27 @@ X_ip6_mrouter_get(struct socket *so, struct sockopt *sopt) * Handle ioctl commands to obtain information from the cache */ static int -X_mrt6_ioctl(u_long cmd, caddr_t data) +X_mrt6_ioctl(u_long cmd, caddr_t data, int fibnum) { + struct mf6ctable *mfct; int error; error = priv_check(curthread, PRIV_NETINET_MROUTE); if (error) return (error); - error = EINVAL; + + mfct = &V_mfctables[fibnum]; switch (cmd) { case SIOCGETSGCNT_IN6: - error = get_sg_cnt((struct sioc_sg_req6 *)data); + error = get_sg_cnt(mfct, (struct sioc_sg_req6 *)data); break; case SIOCGETMIFCNT_IN6: - error = get_mif6_cnt((struct sioc_mif_req6 *)data); + error = get_mif6_cnt(mfct, (struct sioc_mif_req6 *)data); break; default: + error = EINVAL; break; } @@ -499,7 +519,7 @@ X_mrt6_ioctl(u_long cmd, caddr_t data) * returns the packet, byte, rpf-failure count for the source group provided */ static int -get_sg_cnt(struct sioc_sg_req6 *req) +get_sg_cnt(struct mf6ctable *mfct, struct sioc_sg_req6 *req) { struct mf6c *rt; int ret; @@ -507,8 +527,7 @@ get_sg_cnt(struct sioc_sg_req6 *req) ret = 0; MFC6_LOCK(); - rt = mf6c_find(&V_mfctables[0], &req->src.sin6_addr, - &req->grp.sin6_addr); + rt = mf6c_find(mfct, &req->src.sin6_addr, &req->grp.sin6_addr); if (rt == NULL) { ret = ESRCH; } else { @@ -525,16 +544,14 @@ get_sg_cnt(struct sioc_sg_req6 *req) * returns the input and output packet and byte counts on the mif provided */ static int -get_mif6_cnt(struct sioc_mif_req6 *req) +get_mif6_cnt(struct mf6ctable *mfct, struct sioc_mif_req6 *req) { - struct mf6ctable *mfct; mifi_t mifi; int ret; ret = 0; mifi = req->mifi; - mfct = &V_mfctables[0]; MIF6_LOCK(); if (mifi >= mfct->nummifs) { @@ -559,6 +576,7 @@ set_pim6(int *i) if ((*i != 1) && (*i != 0)) return (EINVAL); + /* XXX-MJ */ V_pim6 = *i; return (0); @@ -577,7 +595,7 @@ ip6_mrouter_init(struct socket *so, int v, int cmd) if (v != 1) return (ENOPROTOOPT); - mfct = &V_mfctables[0]; + mfct = somfctable(so); MROUTER6_LOCK(); if (mfct->router != NULL) { @@ -595,7 +613,7 @@ ip6_mrouter_init(struct socket *so, int v, int cmd) V_pim6 = 0;/* used for stubbing out/in pim stuff */ - callout_reset(&V_expire_upcalls_ch, EXPIRE_TIMEOUT, expire_upcalls, + callout_reset(&V_expire_upcalls_ch, EXPIRE_TIMEOUT, expire_upcalls_all, curvnet); MFC6_UNLOCK(); @@ -618,7 +636,7 @@ X_ip6_mrouter_done(struct socket *so) struct mf6c *rt; struct rtdetq *rte; - mfct = &V_mfctables[0]; + mfct = somfctable(so); MROUTER6_LOCK(); if (mfct->router != so) { @@ -690,9 +708,8 @@ static struct sockaddr_in6 sin6 = { sizeof(sin6), AF_INET6 }; * Add a mif to the mif table */ static int -add_m6if(struct mif6ctl *mifcp) +add_m6if(struct mf6ctable *mfct, int fibnum, struct mif6ctl *mifcp) { - struct mf6ctable *mfct; struct epoch_tracker et; struct mif6 *mifp; struct ifnet *ifp; @@ -704,7 +721,6 @@ add_m6if(struct mif6ctl *mifcp) MIF6_UNLOCK(); return (EINVAL); } - mfct = &V_mfctables[0]; mifp = &mfct->miftable[mifcp->mif6c_mifi]; if (mifp->m6_ifp != NULL) { MIF6_UNLOCK(); @@ -743,6 +759,10 @@ add_m6if(struct mif6ctl *mifcp) MIF6_UNLOCK(); return (EOPNOTSUPP); } + if (ifp->if_fib != fibnum) { + MIF6_UNLOCK(); + return (EADDRNOTAVAIL); + } error = if_allmulti(ifp, 1); if (error) { @@ -775,16 +795,14 @@ add_m6if(struct mif6ctl *mifcp) * Delete a mif from the mif table */ static int -del_m6if_locked(mifi_t *mifip) +del_m6if_locked(struct mf6ctable *mfct, mifi_t *mifip) { - struct mf6ctable *mfct; struct mif6 *mifp; mifi_t mifi; struct ifnet *ifp; MIF6_LOCK_ASSERT(); - mfct = &V_mfctables[0]; if (*mifip >= mfct->nummifs) return (EINVAL); mifp = &mfct->miftable[*mifip]; @@ -818,12 +836,12 @@ del_m6if_locked(mifi_t *mifip) } static int -del_m6if(mifi_t *mifip) +del_m6if(struct mf6ctable *mfct, mifi_t *mifip) { int cc; MIF6_LOCK(); - cc = del_m6if_locked(mifip); + cc = del_m6if_locked(mfct, mifip); MIF6_UNLOCK(); return (cc); @@ -833,17 +851,14 @@ del_m6if(mifi_t *mifip) * Add an mfc entry */ static int -add_m6fc(struct mf6cctl *mfccp) +add_m6fc(struct mf6ctable *mfct, struct mf6cctl *mfccp) { - struct mf6ctable *mfct; struct mf6c *rt; u_long hash; struct rtdetq *rte; u_short nstl; char ip6bufo[INET6_ADDRSTRLEN], ip6bufg[INET6_ADDRSTRLEN]; - mfct = &V_mfctables[0]; - MFC6_LOCK(); rt = mf6c_find(mfct, &mfccp->mf6cc_origin.sin6_addr, &mfccp->mf6cc_mcastgrp.sin6_addr); @@ -1004,19 +1019,17 @@ collate(struct timeval *t) * Delete an mfc entry */ static int -del_m6fc(struct mf6cctl *mfccp) +del_m6fc(struct mf6ctable *mfct, struct mf6cctl *mfccp) { #ifdef MRT6DEBUG char ip6bufo[INET6_ADDRSTRLEN], ip6bufg[INET6_ADDRSTRLEN]; #endif - struct mf6ctable *mfct; struct sockaddr_in6 origin; struct sockaddr_in6 mcastgrp; struct mf6c *rt; struct mf6c **nptr; u_long hash; - mfct = &V_mfctables[0]; origin = mfccp->mf6cc_origin; mcastgrp = mfccp->mf6cc_mcastgrp; hash = MF6CHASH(origin.sin6_addr, mcastgrp.sin6_addr); @@ -1139,7 +1152,7 @@ X_ip6_mforward(struct ip6_hdr *ip6, struct ifnet *ifp, struct mbuf *m) return (0); } - mfct = &V_mfctables[0]; + mfct = &V_mfctables[M_GETFIB(m)]; MFC6_LOCK(); /* @@ -1331,20 +1344,17 @@ X_ip6_mforward(struct ip6_hdr *ip6, struct ifnet *ifp, struct mbuf *m) * Call from the Slow Timeout mechanism, every half second. */ static void -expire_upcalls(void *arg) +expire_upcalls(struct mf6ctable *mfct) { #ifdef MRT6DEBUG char ip6bufo[INET6_ADDRSTRLEN], ip6bufg[INET6_ADDRSTRLEN]; #endif - struct mf6ctable *mfct; struct rtdetq *rte; struct mf6c *mfc, **nptr; u_long i; MFC6_LOCK_ASSERT(); - CURVNET_SET((struct vnet *)arg); - mfct = &V_mfctables[0]; for (i = 0; i < MF6CTBLSIZ; i++) { if (mfct->nexpire[i] == 0) continue; @@ -1382,8 +1392,21 @@ expire_upcalls(void *arg) } } } - callout_reset(&V_expire_upcalls_ch, EXPIRE_TIMEOUT, - expire_upcalls, curvnet); +} + +/* + * Clean up the cache entry if upcall is not serviced + */ +static void +expire_upcalls_all(void *arg) +{ + CURVNET_SET((struct vnet *)arg); + + for (int i = 0; i < V_nmfctables; i++) + expire_upcalls(&V_mfctables[i]); + + callout_reset(&V_expire_upcalls_ch, EXPIRE_TIMEOUT, expire_upcalls_all, + curvnet); CURVNET_RESTORE(); } @@ -1753,7 +1776,7 @@ pim6_input(struct mbuf *m, int off, int proto, void *arg __unused) int pimlen; int minlen; - mfct = &V_mfctables[0]; + mfct = &V_mfctables[M_GETFIB(m)]; PIM6STAT_INC(pim6s_rcv_total); diff --git a/sys/netinet6/ip6_mroute.h b/sys/netinet6/ip6_mroute.h index fda8c4308e86..c8388c3836bb 100644 --- a/sys/netinet6/ip6_mroute.h +++ b/sys/netinet6/ip6_mroute.h @@ -288,7 +288,7 @@ extern int (*ip6_mrouter_set)(struct socket *so, struct sockopt *sopt); extern int (*ip6_mrouter_get)(struct socket *so, struct sockopt *sopt); extern void (*ip6_mrouter_done)(struct socket *so); -extern int (*mrt6_ioctl)(u_long, caddr_t); +extern int (*mrt6_ioctl)(u_long, caddr_t, int); #endif /* _KERNEL */ #endif /* !_NETINET6_IP6_MROUTE_H_ */ diff --git a/sys/netinet6/raw_ip6.c b/sys/netinet6/raw_ip6.c index 9e51005d7c2e..a92035831c6c 100644 --- a/sys/netinet6/raw_ip6.c +++ b/sys/netinet6/raw_ip6.c @@ -145,7 +145,7 @@ int (*ip6_mrouter_set)(struct socket *, struct sockopt *); int (*ip6_mrouter_get)(struct socket *, struct sockopt *); void (*ip6_mrouter_done)(struct socket *); int (*ip6_mforward)(struct ip6_hdr *, struct ifnet *, struct mbuf *); -int (*mrt6_ioctl)(u_long, caddr_t); +int (*mrt6_ioctl)(u_long, caddr_t, int); struct rip6_inp_match_ctx { struct ip6_hdr *ip6;home | help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?69caa1ad.3c307.55d18a69>
