Date: Mon, 30 Mar 2026 16:15:36 +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: a223d6c489c7 - main - ip6_mroute: Start putting global variables into a structure Message-ID: <69caa1a8.3bf3e.c1eaaab@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=a223d6c489c7ea9a384f3d2bbda1b05b00d4502d commit a223d6c489c7ea9a384f3d2bbda1b05b00d4502d Author: Mark Johnston <markj@FreeBSD.org> AuthorDate: 2026-03-30 13:29:01 +0000 Commit: Mark Johnston <markj@FreeBSD.org> CommitDate: 2026-03-30 16:08:20 +0000 ip6_mroute: Start putting global variables into a structure As in the IPv4 version of this change, I added a struct mf6ctable structure which holds all global routing table state, soon to become per-FIB state. Note that much of the v6 multicast routing code was not VNETified; this change fixes that too. MFC after: 2 weeks Sponsored by: Stormshield Sponsored by: Klara, Inc. Differential Revision: https://reviews.freebsd.org/D55238 --- sys/netinet6/ip6_mroute.c | 391 +++++++++++++++++++++++++++------------------- 1 file changed, 229 insertions(+), 162 deletions(-) diff --git a/sys/netinet6/ip6_mroute.c b/sys/netinet6/ip6_mroute.c index a8313e1753a6..912bbfda2486 100644 --- a/sys/netinet6/ip6_mroute.c +++ b/sys/netinet6/ip6_mroute.c @@ -106,6 +106,7 @@ #include <net/if_var.h> #include <net/if_private.h> #include <net/if_types.h> +#include <net/route.h> #include <net/vnet.h> #include <netinet/in.h> @@ -124,9 +125,13 @@ static MALLOC_DEFINE(M_MRTABLE6, "mf6c", "multicast forwarding cache entry"); -static int ip6_mdq(struct mbuf *, struct ifnet *, struct mf6c *); +struct mf6ctable; + +static int ip6_mdq(struct mf6ctable *, struct mbuf *, struct ifnet *, + struct mf6c *); static void phyint_send(struct ip6_hdr *, struct mif6 *, struct mbuf *); -static int register_send(struct ip6_hdr *, struct mif6 *, struct mbuf *); +static int register_send(struct mf6ctable *, struct ip6_hdr *, mifi_t, + struct mbuf *); static int set_pim6(int *); static int socket_send(struct socket *, struct mbuf *, struct sockaddr_in6 *); @@ -146,9 +151,6 @@ static const struct encap_config ipv6_encap_cfg = { .input = pim6_input }; -VNET_DEFINE_STATIC(int, ip6_mrouter_ver) = 0; -#define V_ip6_mrouter_ver VNET(ip6_mrouter_ver) - SYSCTL_DECL(_net_inet6); SYSCTL_DECL(_net_inet6_ip6); static SYSCTL_NODE(_net_inet6, IPPROTO_PIM, pim, @@ -172,15 +174,6 @@ static struct sx mrouter6_mtx; #define MROUTER6_LOCK_INIT() sx_init(MROUTER6_LOCKPTR(), "mrouter6") #define MROUTER6_LOCK_DESTROY() sx_destroy(MROUTER6_LOCKPTR()) -VNET_DEFINE_STATIC(struct socket *, ip6_mrouter); -#define V_ip6_mrouter VNET(ip6_mrouter) - -static struct mf6c *mf6ctable[MF6CTBLSIZ]; -SYSCTL_OPAQUE(_net_inet6_ip6, OID_AUTO, mf6ctable, CTLFLAG_RD, - &mf6ctable, sizeof(mf6ctable), "S,*mf6ctable[MF6CTBLSIZ]", - "IPv6 Multicast Forwarding Table (struct *mf6ctable[MF6CTBLSIZ], " - "netinet6/ip6_mroute.h)"); - static struct mtx mfc6_mtx; #define MFC6_LOCKPTR() (&mfc6_mtx) #define MFC6_LOCK() mtx_lock(MFC6_LOCKPTR()) @@ -191,9 +184,42 @@ static struct mtx mfc6_mtx; NULL, MTX_DEF) #define MFC6_LOCK_DESTROY() mtx_destroy(MFC6_LOCKPTR()) -static u_char n6expire[MF6CTBLSIZ]; +struct mf6ctable { + struct socket *router; + int router_ver; + struct mf6c *mfchashtbl[MF6CTBLSIZ]; + u_char nexpire[MF6CTBLSIZ]; + int nummifs; + struct mif6 miftable[MAXMIFS]; + + /* + * 'Interfaces' associated with decapsulator (so we can tell packets + * that went through it from ones that get reflected by a broken + * gateway). Different from IPv4 register_if, these interfaces are + * linked into the system ifnet list, because per-interface IPv6 + * statistics are maintained in ifp->if_afdata. But it does not have + * any routes point to them. I.e., packets can't be sent this way. + * They only exist as a placeholder for multicast source verification. + */ + struct ifnet *register_if; + mifi_t register_mif; +}; + +VNET_DEFINE_STATIC(struct mf6ctable *, mfctables); +#define V_mfctables VNET(mfctables) + +static int +sysctl_mfctable(SYSCTL_HANDLER_ARGS) +{ + return (SYSCTL_OUT(req, &V_mfctables[0].mfchashtbl, + sizeof(V_mfctables[0].mfchashtbl))); +} +SYSCTL_PROC(_net_inet6_ip6, OID_AUTO, mf6ctable, + CTLTYPE_OPAQUE | CTLFLAG_RD, + NULL, 0, sysctl_mfctable, "S,*mf6c[MF6CTBLSIZ]", + "IPv6 Multicast Forwarding Table (struct mf6c *[MF6CTBLSIZ], " + "netinet6/ip6_mroute.h)"); -static struct mif6 mif6table[MAXMIFS]; static int sysctl_mif6table(SYSCTL_HANDLER_ARGS) { @@ -203,17 +229,20 @@ sysctl_mif6table(SYSCTL_HANDLER_ARGS) out = malloc(sizeof(struct mif6_sctl) * MAXMIFS, M_TEMP, M_WAITOK | M_ZERO); for (int i = 0; i < MAXMIFS; i++) { - out[i].m6_flags = mif6table[i].m6_flags; - out[i].m6_rate_limit = mif6table[i].m6_rate_limit; - out[i].m6_lcl_addr = mif6table[i].m6_lcl_addr; - if (mif6table[i].m6_ifp != NULL) - out[i].m6_ifp = mif6table[i].m6_ifp->if_index; + struct mif6_sctl *outp = &out[i]; + struct mif6 *mifp = &V_mfctables[0].miftable[i]; + + outp->m6_flags = mifp->m6_flags; + outp->m6_rate_limit = mifp->m6_rate_limit; + outp->m6_lcl_addr = mifp->m6_lcl_addr; + if (mifp->m6_ifp != NULL) + outp->m6_ifp = mifp->m6_ifp->if_index; else - out[i].m6_ifp = 0; - out[i].m6_pkt_in = mif6table[i].m6_pkt_in; - out[i].m6_pkt_out = mif6table[i].m6_pkt_out; - out[i].m6_bytes_in = mif6table[i].m6_bytes_in; - out[i].m6_bytes_out = mif6table[i].m6_bytes_out; + outp->m6_ifp = 0; + outp->m6_pkt_in = mifp->m6_pkt_in; + outp->m6_pkt_out = mifp->m6_pkt_out; + outp->m6_bytes_in = mifp->m6_bytes_in; + outp->m6_bytes_out = mifp->m6_bytes_out; } error = SYSCTL_OUT(req, out, sizeof(struct mif6_sctl) * MAXMIFS); free(out, M_TEMP); @@ -257,25 +286,6 @@ static void expire_upcalls(void *); #define EXPIRE_TIMEOUT (hz / 4) /* 4x / second */ #define UPCALL_EXPIRE 6 /* number of timeouts */ -/* - * 'Interfaces' associated with decapsulator (so we can tell - * packets that went through it from ones that get reflected - * by a broken gateway). Different from IPv4 register_if, - * these interfaces are linked into the system ifnet list, - * because per-interface IPv6 statistics are maintained in - * ifp->if_afdata. But it does not have any routes point - * to them. I.e., packets can't be sent this way. They - * only exist as a placeholder for multicast source - * verification. - */ -static struct ifnet *multicast_register_if6; - -/* - * Private variables. - */ -static mifi_t nummifs = 0; -static mifi_t reg_mif_num = (mifi_t)-1; - static struct pim6stat pim6stat; SYSCTL_STRUCT(_net_inet6_pim, PIM6CTL_STATS, stats, CTLFLAG_RW, &pim6stat, pim6stat, @@ -335,7 +345,8 @@ 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 struct callout expire_upcalls_ch; +VNET_DEFINE_STATIC(struct callout, expire_upcalls_ch); +#define V_expire_upcalls_ch VNET(expire_upcalls_ch) static int X_ip6_mforward(struct ip6_hdr *, struct ifnet *, struct mbuf *); static void X_ip6_mrouter_done(struct socket *); @@ -344,12 +355,13 @@ static int X_ip6_mrouter_get(struct socket *, struct sockopt *); static int X_mrt6_ioctl(u_long, caddr_t); static struct mf6c * -mf6c_find(const struct in6_addr *origin, const struct in6_addr *group) +mf6c_find(const struct mf6ctable *mfct, const struct in6_addr *origin, + const struct in6_addr *group) { MFC6_LOCK_ASSERT(); - for (struct mf6c *rt = mf6ctable[MF6CHASH(*origin, *group)]; rt != NULL; - rt = rt->mf6c_next) { + for (struct mf6c *rt = mfct->mfchashtbl[MF6CHASH(*origin, *group)]; + rt != NULL; rt = rt->mf6c_next) { if (IN6_ARE_ADDR_EQUAL(&rt->mf6c_origin.sin6_addr, origin) && IN6_ARE_ADDR_EQUAL(&rt->mf6c_mcastgrp.sin6_addr, group) && rt->mf6c_stall == NULL) @@ -365,13 +377,15 @@ mf6c_find(const struct in6_addr *origin, const struct in6_addr *group) static int X_ip6_mrouter_set(struct socket *so, struct sockopt *sopt) { + struct mf6ctable *mfct; int error = 0; int optval; struct mif6ctl mifc; struct mf6cctl mfcc; mifi_t mifi; - if (so != V_ip6_mrouter && sopt->sopt_name != MRT6_INIT) + mfct = &V_mfctables[0]; + if (so != mfct->router && sopt->sopt_name != MRT6_INIT) return (EPERM); switch (sopt->sopt_name) { @@ -433,9 +447,11 @@ X_ip6_mrouter_set(struct socket *so, struct sockopt *sopt) static int X_ip6_mrouter_get(struct socket *so, struct sockopt *sopt) { + struct mf6ctable *mfct; int error = 0; - if (so != V_ip6_mrouter) + mfct = &V_mfctables[0]; + if (so != mfct->router) return (EACCES); switch (sopt->sopt_name) { @@ -486,8 +502,8 @@ get_sg_cnt(struct sioc_sg_req6 *req) ret = 0; MFC6_LOCK(); - - rt = mf6c_find(&req->src.sin6_addr, &req->grp.sin6_addr); + rt = mf6c_find(&V_mfctables[0], &req->src.sin6_addr, + &req->grp.sin6_addr); if (rt == NULL) { ret = ESRCH; } else { @@ -495,7 +511,6 @@ get_sg_cnt(struct sioc_sg_req6 *req) req->bytecnt = rt->mf6c_byte_cnt; req->wrong_if = rt->mf6c_wrong_if; } - MFC6_UNLOCK(); return (ret); @@ -507,21 +522,25 @@ get_sg_cnt(struct sioc_sg_req6 *req) static int get_mif6_cnt(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 >= nummifs) { + if (mifi >= mfct->nummifs) { ret = EINVAL; } else { - req->icount = mif6table[mifi].m6_pkt_in; - req->ocount = mif6table[mifi].m6_pkt_out; - req->ibytes = mif6table[mifi].m6_bytes_in; - req->obytes = mif6table[mifi].m6_bytes_out; + struct mif6 *mif = &mfct->miftable[mifi]; + + req->icount = mif->m6_pkt_in; + req->ocount = mif->m6_pkt_out; + req->ibytes = mif->m6_bytes_in; + req->obytes = mif->m6_bytes_out; } MIF6_UNLOCK(); @@ -546,32 +565,33 @@ set_pim6(int *i) static int ip6_mrouter_init(struct socket *so, int v, int cmd) { + struct mf6ctable *mfct; MRT6_DLOG(DEBUG_ANY, "%s: socket %p", __func__, so); if (v != 1) return (ENOPROTOOPT); + mfct = &V_mfctables[0]; MROUTER6_LOCK(); - if (V_ip6_mrouter != NULL) { + if (mfct->router != NULL) { MROUTER6_UNLOCK(); return (EADDRINUSE); } MFC6_LOCK(); V_ip6_mrouting_enabled = true; - V_ip6_mrouter = so; - V_ip6_mrouter_ver = cmd; + mfct->router = so; + mfct->router_ver = cmd; - bzero((caddr_t)mf6ctable, sizeof(mf6ctable)); - bzero((caddr_t)n6expire, sizeof(n6expire)); + bzero(&mfct->mfchashtbl, sizeof(mfct->mfchashtbl)); + bzero(&mfct->nexpire, sizeof(mfct->nexpire)); V_pim6 = 0;/* used for stubbing out/in pim stuff */ - callout_init_mtx(&expire_upcalls_ch, MFC6_LOCKPTR(), 0); - callout_reset(&expire_upcalls_ch, EXPIRE_TIMEOUT, - expire_upcalls, NULL); + callout_reset(&V_expire_upcalls_ch, EXPIRE_TIMEOUT, expire_upcalls, + curvnet); MFC6_UNLOCK(); MROUTER6_UNLOCK(); @@ -587,14 +607,16 @@ ip6_mrouter_init(struct socket *so, int v, int cmd) static void X_ip6_mrouter_done(struct socket *so) { + struct mf6ctable *mfct; mifi_t mifi; u_long i; struct mf6c *rt; struct rtdetq *rte; + mfct = &V_mfctables[0]; MROUTER6_LOCK(); - if (V_ip6_mrouter != so) { + if (mfct->router != so) { MROUTER6_UNLOCK(); return; } @@ -603,15 +625,16 @@ X_ip6_mrouter_done(struct socket *so) * For each phyint in use, disable promiscuous reception of all IPv6 * multicasts. */ - for (mifi = 0; mifi < nummifs; mifi++) { - if (mif6table[mifi].m6_ifp && - !(mif6table[mifi].m6_flags & MIFF_REGISTER)) { - if_allmulti(mif6table[mifi].m6_ifp, 0); + for (mifi = 0; mifi < mfct->nummifs; mifi++) { + struct mif6 *mif = &mfct->miftable[mifi]; + + if (mif->m6_ifp && !(mif->m6_flags & MIFF_REGISTER)) { + if_allmulti(mif->m6_ifp, 0); } } MFC6_LOCK(); - bzero((caddr_t)mif6table, sizeof(mif6table)); - nummifs = 0; + bzero(mfct->miftable, sizeof(mfct->miftable)); + mfct->nummifs = 0; V_pim6 = 0; /* used to stub out/in pim specific code */ @@ -619,7 +642,7 @@ X_ip6_mrouter_done(struct socket *so) * Free all multicast forwarding cache entries. */ for (i = 0; i < MF6CTBLSIZ; i++) { - rt = mf6ctable[i]; + rt = mfct->mfchashtbl[i]; while (rt) { struct mf6c *frt; @@ -635,23 +658,21 @@ X_ip6_mrouter_done(struct socket *so) free(frt, M_MRTABLE6); } } - bzero((caddr_t)mf6ctable, sizeof(mf6ctable)); - - V_ip6_mrouter = NULL; + mfct->router = NULL; + mfct->router_ver = 0; V_ip6_mrouting_enabled = false; - V_ip6_mrouter_ver = 0; - MFC6_UNLOCK(); - callout_drain(&expire_upcalls_ch); + bzero(mfct->mfchashtbl, sizeof(mfct->mfchashtbl)); + MFC6_UNLOCK(); /* * Reset register interface */ - if (reg_mif_num != (mifi_t)-1 && multicast_register_if6 != NULL) { - if_detach(multicast_register_if6); - if_free(multicast_register_if6); - reg_mif_num = (mifi_t)-1; - multicast_register_if6 = NULL; + if (mfct->register_mif != (mifi_t)-1 && mfct->register_if != NULL) { + if_detach(mfct->register_if); + if_free(mfct->register_if); + mfct->register_mif = (mifi_t)-1; + mfct->register_if = NULL; } MROUTER6_UNLOCK(); @@ -666,6 +687,7 @@ static struct sockaddr_in6 sin6 = { sizeof(sin6), AF_INET6 }; static int add_m6if(struct mif6ctl *mifcp) { + struct mf6ctable *mfct; struct epoch_tracker et; struct mif6 *mifp; struct ifnet *ifp; @@ -677,7 +699,8 @@ add_m6if(struct mif6ctl *mifcp) MIF6_UNLOCK(); return (EINVAL); } - mifp = mif6table + mifcp->mif6c_mifi; + mfct = &V_mfctables[0]; + mifp = &mfct->miftable[mifcp->mif6c_mifi]; if (mifp->m6_ifp != NULL) { MIF6_UNLOCK(); return (EADDRINUSE); /* XXX: is it appropriate? */ @@ -692,14 +715,14 @@ add_m6if(struct mif6ctl *mifcp) NET_EPOCH_EXIT(et); /* XXXGL: unsafe ifp */ if (mifcp->mif6c_flags & MIFF_REGISTER) { - if (reg_mif_num == (mifi_t)-1) { + if (mfct->register_mif == (mifi_t)-1) { ifp = if_alloc(IFT_OTHER); if_initname(ifp, "register_mif", 0); ifp->if_flags |= IFF_LOOPBACK; if_attach(ifp); - multicast_register_if6 = ifp; - reg_mif_num = mifcp->mif6c_mifi; + mfct->register_if = ifp; + mfct->register_mif = mifcp->mif6c_mifi; /* * it is impossible to guess the ifindex of the * register interface. So mif6c_pifi is automatically @@ -707,7 +730,7 @@ add_m6if(struct mif6ctl *mifcp) */ mifcp->mif6c_pifi = ifp->if_index; } else { - ifp = multicast_register_if6; + ifp = mfct->register_if; } } else { /* Make sure the interface supports multicast */ @@ -733,8 +756,8 @@ add_m6if(struct mif6ctl *mifcp) mifp->m6_bytes_out = 0; /* Adjust nummifs up if the mifi is higher than nummifs */ - if (nummifs <= mifcp->mif6c_mifi) - nummifs = mifcp->mif6c_mifi + 1; + if (mfct->nummifs <= mifcp->mif6c_mifi) + mfct->nummifs = mifcp->mif6c_mifi + 1; MIF6_UNLOCK(); MRT6_DLOG(DEBUG_ANY, "mif #%d, phyint %s", mifcp->mif6c_mifi, @@ -749,14 +772,17 @@ add_m6if(struct mif6ctl *mifcp) static int del_m6if_locked(mifi_t *mifip) { - struct mif6 *mifp = mif6table + *mifip; + struct mf6ctable *mfct; + struct mif6 *mifp; mifi_t mifi; struct ifnet *ifp; MIF6_LOCK_ASSERT(); - if (*mifip >= nummifs) + mfct = &V_mfctables[0]; + if (*mifip >= mfct->nummifs) return (EINVAL); + mifp = &mfct->miftable[*mifip]; if (mifp->m6_ifp == NULL) return (EINVAL); @@ -765,23 +791,23 @@ del_m6if_locked(mifi_t *mifip) ifp = mifp->m6_ifp; if_allmulti(ifp, 0); } else { - if (reg_mif_num != (mifi_t)-1 && - multicast_register_if6 != NULL) { - if_detach(multicast_register_if6); - if_free(multicast_register_if6); - reg_mif_num = (mifi_t)-1; - multicast_register_if6 = NULL; + if (mfct->register_mif != (mifi_t)-1 && + mfct->register_if != NULL) { + if_detach(mfct->register_if); + if_free(mfct->register_if); + mfct->register_mif = (mifi_t)-1; + mfct->register_if = NULL; } } - bzero((caddr_t)mifp, sizeof(*mifp)); + bzero(mifp, sizeof(*mifp)); /* Adjust nummifs down */ - for (mifi = nummifs; mifi > 0; mifi--) - if (mif6table[mifi - 1].m6_ifp) + for (mifi = mfct->nummifs; mifi > 0; mifi--) + if (mfct->miftable[mifi - 1].m6_ifp != NULL) break; - nummifs = mifi; - MRT6_DLOG(DEBUG_ANY, "mif %d, nummifs %d", *mifip, nummifs); + mfct->nummifs = mifi; + MRT6_DLOG(DEBUG_ANY, "mif %d, nummifs %d", *mifip, mfct->nummifs); return (0); } @@ -804,15 +830,17 @@ del_m6if(mifi_t *mifip) static int add_m6fc(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]; - MFC6_LOCK(); + mfct = &V_mfctables[0]; - rt = mf6c_find(&mfccp->mf6cc_origin.sin6_addr, + MFC6_LOCK(); + rt = mf6c_find(mfct, &mfccp->mf6cc_origin.sin6_addr, &mfccp->mf6cc_mcastgrp.sin6_addr); /* If an entry already exists, just update the fields */ if (rt) { @@ -833,7 +861,7 @@ add_m6fc(struct mf6cctl *mfccp) */ hash = MF6CHASH(mfccp->mf6cc_origin.sin6_addr, mfccp->mf6cc_mcastgrp.sin6_addr); - for (rt = mf6ctable[hash], nstl = 0; rt; rt = rt->mf6c_next) { + for (rt = mfct->mfchashtbl[hash], nstl = 0; rt; rt = rt->mf6c_next) { if (IN6_ARE_ADDR_EQUAL(&rt->mf6c_origin.sin6_addr, &mfccp->mf6cc_origin.sin6_addr) && IN6_ARE_ADDR_EQUAL(&rt->mf6c_mcastgrp.sin6_addr, @@ -866,12 +894,12 @@ add_m6fc(struct mf6cctl *mfccp) rt->mf6c_wrong_if = 0; rt->mf6c_expire = 0; /* Don't clean this guy up */ - n6expire[hash]--; + mfct->nexpire[hash]--; /* free packets Qed at the end of this entry */ for (rte = rt->mf6c_stall; rte != NULL; ) { struct rtdetq *n = rte->next; - ip6_mdq(rte->m, rte->ifp, rt); + ip6_mdq(mfct, rte->m, rte->ifp, rt); m_freem(rte->m); #ifdef UPCALL_TIMING collate(&(rte->t)); @@ -892,7 +920,7 @@ add_m6fc(struct mf6cctl *mfccp) ip6_sprintf(ip6bufg, &mfccp->mf6cc_mcastgrp.sin6_addr), mfccp->mf6cc_parent); - for (rt = mf6ctable[hash]; rt; rt = rt->mf6c_next) { + for (rt = mfct->mfchashtbl[hash]; rt; rt = rt->mf6c_next) { if (IN6_ARE_ADDR_EQUAL(&rt->mf6c_origin.sin6_addr, &mfccp->mf6cc_origin.sin6_addr)&& IN6_ARE_ADDR_EQUAL(&rt->mf6c_mcastgrp.sin6_addr, @@ -907,7 +935,7 @@ add_m6fc(struct mf6cctl *mfccp) rt->mf6c_wrong_if = 0; if (rt->mf6c_expire) - n6expire[hash]--; + mfct->nexpire[hash]--; rt->mf6c_expire = 0; } } @@ -932,8 +960,8 @@ add_m6fc(struct mf6cctl *mfccp) rt->mf6c_stall = NULL; /* link into table */ - rt->mf6c_next = mf6ctable[hash]; - mf6ctable[hash] = rt; + rt->mf6c_next = mfct->mfchashtbl[hash]; + mfct->mfchashtbl[hash] = rt; } } @@ -976,12 +1004,14 @@ del_m6fc(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); @@ -992,7 +1022,7 @@ del_m6fc(struct mf6cctl *mfccp) MFC6_LOCK(); - nptr = &mf6ctable[hash]; + nptr = &mfct->mfchashtbl[hash]; while ((rt = *nptr) != NULL) { if (IN6_ARE_ADDR_EQUAL(&origin.sin6_addr, &rt->mf6c_origin.sin6_addr) && @@ -1054,6 +1084,7 @@ socket_send(struct socket *s, struct mbuf *mm, struct sockaddr_in6 *src) static int X_ip6_mforward(struct ip6_hdr *ip6, struct ifnet *ifp, struct mbuf *m) { + struct mf6ctable *mfct; struct rtdetq *rte; struct mbuf *mb0; struct mf6c *rt; @@ -1103,18 +1134,19 @@ X_ip6_mforward(struct ip6_hdr *ip6, struct ifnet *ifp, struct mbuf *m) return (0); } + mfct = &V_mfctables[0]; MFC6_LOCK(); /* * Determine forwarding mifs from the forwarding cache table */ - rt = mf6c_find(&ip6->ip6_src, &ip6->ip6_dst); + rt = mf6c_find(mfct, &ip6->ip6_src, &ip6->ip6_dst); MRT6STAT_INC(mrt6s_mfc_lookups); /* Entry exists, so forward if necessary */ if (rt) { MFC6_UNLOCK(); - return (ip6_mdq(m, ifp, rt)); + return (ip6_mdq(mfct, m, ifp, rt)); } /* @@ -1150,7 +1182,7 @@ X_ip6_mforward(struct ip6_hdr *ip6, struct ifnet *ifp, struct mbuf *m) /* is there an upcall waiting for this packet? */ hash = MF6CHASH(ip6->ip6_src, ip6->ip6_dst); - for (rt = mf6ctable[hash]; rt; rt = rt->mf6c_next) { + for (rt = mfct->mfchashtbl[hash]; rt; rt = rt->mf6c_next) { if (IN6_ARE_ADDR_EQUAL(&ip6->ip6_src, &rt->mf6c_origin.sin6_addr) && IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst, @@ -1192,7 +1224,7 @@ X_ip6_mforward(struct ip6_hdr *ip6, struct ifnet *ifp, struct mbuf *m) #ifdef MRT6_OINIT oim = NULL; #endif - switch (V_ip6_mrouter_ver) { + switch (mfct->router_ver) { #ifdef MRT6_OINIT case MRT6_OINIT: oim = mtod(mm, struct omrt6msg *); @@ -1214,11 +1246,11 @@ X_ip6_mforward(struct ip6_hdr *ip6, struct ifnet *ifp, struct mbuf *m) } MRT6_DLOG(DEBUG_FORWARD, "getting the iif info in the kernel"); - for (mifp = mif6table, mifi = 0; - mifi < nummifs && mifp->m6_ifp != ifp; mifp++, mifi++) - ; + for (mifp = mfct->miftable, mifi = 0; + mifi < mfct->nummifs && mifp->m6_ifp != ifp; mifp++, mifi++) + ; - switch (V_ip6_mrouter_ver) { + switch (mfct->router_ver) { #ifdef MRT6_OINIT case MRT6_OINIT: oim->im6_mif = mifi; @@ -1229,7 +1261,7 @@ X_ip6_mforward(struct ip6_hdr *ip6, struct ifnet *ifp, struct mbuf *m) break; } - if (socket_send(V_ip6_mrouter, mm, &sin6) < 0) { + if (socket_send(mfct->router, mm, &sin6) < 0) { log(LOG_WARNING, "ip6_mforward: ip6_mrouter " "socket queue full\n"); MRT6STAT_INC(mrt6s_upq_sockfull); @@ -1251,12 +1283,12 @@ X_ip6_mforward(struct ip6_hdr *ip6, struct ifnet *ifp, struct mbuf *m) rt->mf6c_mcastgrp.sin6_len = sizeof(struct sockaddr_in6); rt->mf6c_mcastgrp.sin6_addr = ip6->ip6_dst; rt->mf6c_expire = UPCALL_EXPIRE; - n6expire[hash]++; + mfct->nexpire[hash]++; rt->mf6c_parent = MF6C_INCOMPLETE_PARENT; /* link into table */ - rt->mf6c_next = mf6ctable[hash]; - mf6ctable[hash] = rt; + rt->mf6c_next = mfct->mfchashtbl[hash]; + mfct->mfchashtbl[hash] = rt; /* Add this entry to the end of the queue */ rt->mf6c_stall = rte; } else { @@ -1294,21 +1326,24 @@ 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 *unused) +expire_upcalls(void *arg) { #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 (n6expire[i] == 0) + if (mfct->nexpire[i] == 0) continue; - nptr = &mf6ctable[i]; + nptr = &mfct->mfchashtbl[i]; while ((mfc = *nptr) != NULL) { rte = mfc->mf6c_stall; /* @@ -1333,7 +1368,7 @@ expire_upcalls(void *unused) rte = n; } while (rte != NULL); MRT6STAT_INC(mrt6s_cache_cleanups); - n6expire[i]--; + mfct->nexpire[i]--; *nptr = mfc->mf6c_next; free(mfc, M_MRTABLE6); @@ -1342,15 +1377,18 @@ expire_upcalls(void *unused) } } } - callout_reset(&expire_upcalls_ch, EXPIRE_TIMEOUT, - expire_upcalls, NULL); + callout_reset(&V_expire_upcalls_ch, EXPIRE_TIMEOUT, + expire_upcalls, curvnet); + + CURVNET_RESTORE(); } /* * Packet forwarding routine once entry in the cache is made */ static int -ip6_mdq(struct mbuf *m, struct ifnet *ifp, struct mf6c *rt) +ip6_mdq(struct mf6ctable *mfct, struct mbuf *m, struct ifnet *ifp, + struct mf6c *rt) { struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); mifi_t mifi, iif; @@ -1367,13 +1405,13 @@ ip6_mdq(struct mbuf *m, struct ifnet *ifp, struct mf6c *rt) * for its origin. */ mifi = rt->mf6c_parent; - if (mifi >= nummifs || mif6table[mifi].m6_ifp != ifp) { + if (mifi >= mfct->nummifs || mfct->miftable[mifi].m6_ifp != ifp) { MRT6STAT_INC(mrt6s_wrong_if); rt->mf6c_wrong_if++; - if (mifi >= nummifs) + if (mifi >= mfct->nummifs) return (0); - mifp = &mif6table[mifi]; + mifp = &mfct->miftable[mifi]; MRT6_DLOG(DEBUG_FORWARD, "wrong if: ifid %d mifi %d mififid %x", ifp->if_index, mifi, mifp->m6_ifp->if_index); @@ -1412,7 +1450,7 @@ ip6_mdq(struct mbuf *m, struct ifnet *ifp, struct mf6c *rt) oim = NULL; #endif im = NULL; - switch (V_ip6_mrouter_ver) { + switch (mfct->router_ver) { #ifdef MRT6_OINIT case MRT6_OINIT: oim = mtod(mm, struct omrt6msg *); @@ -1430,12 +1468,12 @@ ip6_mdq(struct mbuf *m, struct ifnet *ifp, struct mf6c *rt) return (EINVAL); } - for (mifp = mif6table, iif = 0; - iif < nummifs && mifp->m6_ifp != ifp; + for (mifp = mfct->miftable, iif = 0; + iif < mfct->nummifs && mifp->m6_ifp != ifp; mifp++, iif++) ; - switch (V_ip6_mrouter_ver) { + switch (mfct->router_ver) { #ifdef MRT6_OINIT case MRT6_OINIT: oim->im6_mif = iif; @@ -1450,7 +1488,7 @@ ip6_mdq(struct mbuf *m, struct ifnet *ifp, struct mf6c *rt) MRT6STAT_INC(mrt6s_upcalls); - if (socket_send(V_ip6_mrouter, mm, &sin6) < 0) { + if (socket_send(mfct->router, mm, &sin6) < 0) { MRT6_DLOG(DEBUG_ANY, "ip6_mrouter socket queue full"); MRT6STAT_INC(mrt6s_upq_sockfull); @@ -1460,14 +1498,16 @@ ip6_mdq(struct mbuf *m, struct ifnet *ifp, struct mf6c *rt) return (0); } + mifp = &mfct->miftable[mifi]; + /* If I sourced this packet, it counts as output, else it was input. */ if (m->m_pkthdr.rcvif == NULL) { /* XXX: is rcvif really NULL when output?? */ - mif6table[mifi].m6_pkt_out++; - mif6table[mifi].m6_bytes_out += plen; + mifp->m6_pkt_out++; + mifp->m6_bytes_out += plen; } else { - mif6table[mifi].m6_pkt_in++; - mif6table[mifi].m6_bytes_in += plen; + mifp->m6_pkt_in++; + mifp->m6_bytes_in += plen; } rt->mf6c_pkt_cnt++; rt->mf6c_byte_cnt += plen; @@ -1483,7 +1523,8 @@ ip6_mdq(struct mbuf *m, struct ifnet *ifp, struct mf6c *rt) IP6STAT_INC(ip6s_badscope); return (error); } - for (mifp = mif6table, mifi = 0; mifi < nummifs; mifp++, mifi++) { + for (mifp = mfct->miftable, mifi = 0; mifi < mfct->nummifs; + mifp++, mifi++) { if (IF_ISSET(mifi, &rt->mf6c_ifset)) { /* * check if the outgoing packet is going to break @@ -1491,12 +1532,12 @@ ip6_mdq(struct mbuf *m, struct ifnet *ifp, struct mf6c *rt) * XXX For packets through PIM register tunnel * interface, we believe a routing daemon. */ - if (!(mif6table[rt->mf6c_parent].m6_flags & + if (!(mfct->miftable[rt->mf6c_parent].m6_flags & MIFF_REGISTER) && - !(mif6table[mifi].m6_flags & MIFF_REGISTER)) { - if (in6_setscope(&src0, mif6table[mifi].m6_ifp, + !(mifp->m6_flags & MIFF_REGISTER)) { + if (in6_setscope(&src0, mifp->m6_ifp, &oszone) || - in6_setscope(&dst0, mif6table[mifi].m6_ifp, + in6_setscope(&dst0, mifp->m6_ifp, &odzone) || iszone != oszone || idzone != odzone) { @@ -1508,7 +1549,7 @@ ip6_mdq(struct mbuf *m, struct ifnet *ifp, struct mf6c *rt) mifp->m6_pkt_out++; mifp->m6_bytes_out += plen; if (mifp->m6_flags & MIFF_REGISTER) - register_send(ip6, mifp, m); + register_send(mfct, ip6, mifi, m); else phyint_send(ip6, mifp, m); } @@ -1619,7 +1660,8 @@ phyint_send(struct ip6_hdr *ip6, struct mif6 *mifp, struct mbuf *m) } static int -register_send(struct ip6_hdr *ip6, struct mif6 *mif, struct mbuf *m) +register_send(struct mf6ctable *mfct, struct ip6_hdr *ip6, mifi_t mifi, + struct mbuf *m) { #ifdef MRT6DEBUG char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN]; @@ -1663,12 +1705,12 @@ register_send(struct ip6_hdr *ip6, struct mif6 *mif, struct mbuf *m) im6->im6_msgtype = MRT6MSG_WHOLEPKT; im6->im6_mbz = 0; - im6->im6_mif = mif - mif6table; + im6->im6_mif = mifi; /* iif info is not given for reg. encap.n */ MRT6STAT_INC(mrt6s_upcalls); - if (socket_send(V_ip6_mrouter, mm, &sin6) < 0) { + if (socket_send(mfct->router, mm, &sin6) < 0) { MRT6_DLOG(DEBUG_ANY, "ip6_mrouter socket queue full"); MRT6STAT_INC(mrt6s_upq_sockfull); return (ENOBUFS); @@ -1700,11 +1742,14 @@ pim6_encapcheck(const struct mbuf *m __unused, int off __unused, static int pim6_input(struct mbuf *m, int off, int proto, void *arg __unused) { - struct pim *pim; /* pointer to a pim struct */ + struct mf6ctable *mfct; + struct pim *pim; struct ip6_hdr *ip6; int pimlen; int minlen; + mfct = &V_mfctables[0]; + PIM6STAT_INC(pim6s_rcv_total); /* @@ -1792,9 +1837,10 @@ pim6_input(struct mbuf *m, int off, int proto, void *arg __unused) PIM6STAT_INC(pim6s_rcv_registers); - if ((reg_mif_num >= nummifs) || (reg_mif_num == (mifi_t) -1)) { + if (mfct->register_mif >= mfct->nummifs || + mfct->register_mif == (mifi_t)-1) { MRT6_DLOG(DEBUG_PIM, "register mif not set: %d", - reg_mif_num); + mfct->register_mif); m_freem(m); return (IPPROTO_DONE); } @@ -1861,10 +1907,10 @@ pim6_input(struct mbuf *m, int off, int proto, void *arg __unused) MRT6_DLOG(DEBUG_PIM, "forwarding decapsulated register: " "src %s, dst %s, mif %d", ip6_sprintf(ip6bufs, &eip6->ip6_src), - ip6_sprintf(ip6bufd, &eip6->ip6_dst), reg_mif_num); + ip6_sprintf(ip6bufd, &eip6->ip6_dst), mfct->register_mif); - if_simloop(mif6table[reg_mif_num].m6_ifp, m, - dst.sin6_family, 0); + if_simloop(mfct->miftable[mfct->register_mif].m6_ifp, m, + dst.sin6_family, 0); /* prepare the register head to send to the mrouting daemon */ m = mcp; @@ -1880,6 +1926,27 @@ pim6_input(struct mbuf *m, int off, int proto, void *arg __unused) return (rip6_input(&m, &off, proto)); } +static void +vnet_mroute_init(const void *unused __unused) +{ + V_mfctables = mallocarray(V_rt_numfibs, sizeof(*V_mfctables), + M_MRTABLE6, M_WAITOK | M_ZERO); + + callout_init_mtx(&V_expire_upcalls_ch, MFC6_LOCKPTR(), 0); +} +VNET_SYSINIT(vnet_mroute6_init, SI_SUB_PROTO_MC, SI_ORDER_ANY, vnet_mroute_init, + NULL); + +static void +vnet_mroute_uninit(const void *unused __unused) +{ + callout_drain(&V_expire_upcalls_ch); + free(V_mfctables, M_MRTABLE6); + V_mfctables = NULL; +} +VNET_SYSUNINIT(vnet_mroute6_uninit, SI_SUB_PROTO_MC, SI_ORDER_ANY, + vnet_mroute_uninit, NULL); + static int ip6_mroute_modevent(module_t mod, int type, void *unused) {home | help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?69caa1a8.3bf3e.c1eaaab>
