Date: Mon, 30 Mar 2026 16:15:35 +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: d50d0c002b98 - main - ip_mroute: Start moving globals into a structure Message-ID: <69caa1a7.3b9c2.3d515715@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=d50d0c002b982f193e36ede9fa2669d5dcf8467b commit d50d0c002b982f193e36ede9fa2669d5dcf8467b Author: Mark Johnston <markj@FreeBSD.org> AuthorDate: 2026-03-30 13:27:52 +0000 Commit: Mark Johnston <markj@FreeBSD.org> CommitDate: 2026-03-30 16:08:20 +0000 ip_mroute: Start moving globals into a structure I would like to support per-FIB multicast routing tables, such that one can run a routing daemon per-FIB, with each daemon oblivious to the existence of others. Currently the multicast routing code is completely unaware of FIBs. To that end, start collecting various global variables in ip_mroute.c into a per-VNET struct mfctable. In a future patch this will be expanded into an array of mfctable structures, one per FIB. For now, all of the state is collected into V_mfctables[0]. Each mfctable contains, among other things: - a pointer to the routing socket, if routing is enabled, - a hash table of routing cache entries, - an table of network interfaces participating in the routing configuration This change has no functional effect, it is just factoring out these global variables to make the subsequent patches simpler. MFC after: 2 weeks Sponsored by: Stormshield Sponsored by: Klara, Inc. Differential Revision: https://reviews.freebsd.org/D55237 --- sys/netinet/ip_mroute.c | 473 +++++++++++++++++++++++++++--------------------- 1 file changed, 266 insertions(+), 207 deletions(-) diff --git a/sys/netinet/ip_mroute.c b/sys/netinet/ip_mroute.c index 7a197e20a62f..6e5b739f1da8 100644 --- a/sys/netinet/ip_mroute.c +++ b/sys/netinet/ip_mroute.c @@ -169,8 +169,26 @@ SYSCTL_VNET_PCPUSTAT(_net_inet_ip, OID_AUTO, mrtstat, struct mrtstat, mrtstat, "IPv4 Multicast Forwarding Statistics (struct mrtstat, " "netinet/ip_mroute.h)"); -VNET_DEFINE_STATIC(struct socket *, ip_mrouter); -#define V_ip_mrouter VNET(ip_mrouter) +struct mfctable { + struct socket *router; + LIST_HEAD(mfchashhdr, mfc) *mfchashtbl; + u_char *nexpire; + vifi_t numvifs; + struct vif viftable[MAXVIFS]; + + struct buf_ring *bw_upcalls; + struct mtx bw_upcalls_mtx; + + struct ifnet *register_if; + vifi_t register_vif; + + uint32_t api_config; + int pim_assert_enabled; + struct timeval pim_assert_interval; +}; + +VNET_DEFINE_STATIC(struct mfctable *, mfctables); +#define V_mfctables VNET(mfctables) VNET_DEFINE_STATIC(u_long, mfchash); #define V_mfchash VNET(mfchash) @@ -182,28 +200,17 @@ VNET_DEFINE_STATIC(u_long, mfchash); static u_long mfchashsize = MFCHASHSIZE; /* Hash size */ SYSCTL_ULONG(_net_inet_ip, OID_AUTO, mfchashsize, CTLFLAG_RDTUN, &mfchashsize, 0, "IPv4 Multicast Forwarding Table hash size"); -VNET_DEFINE_STATIC(u_char *, nexpire); /* 0..mfchashsize-1 */ -#define V_nexpire VNET(nexpire) -VNET_DEFINE_STATIC(LIST_HEAD(mfchashhdr, mfc)*, mfchashtbl); -#define V_mfchashtbl VNET(mfchashtbl) + VNET_DEFINE_STATIC(struct taskqueue *, task_queue); #define V_task_queue VNET(task_queue) VNET_DEFINE_STATIC(struct task, task); #define V_task VNET(task) -VNET_DEFINE_STATIC(vifi_t, numvifs); -#define V_numvifs VNET(numvifs) -VNET_DEFINE_STATIC(struct vif *, viftable); -#define V_viftable VNET(viftable) - static eventhandler_tag if_detach_event_tag = NULL; VNET_DEFINE_STATIC(struct callout, expire_upcalls_ch); #define V_expire_upcalls_ch VNET(expire_upcalls_ch) -VNET_DEFINE_STATIC(struct mtx, buf_ring_mtx); -#define V_buf_ring_mtx VNET(buf_ring_mtx) - #define EXPIRE_TIMEOUT (hz / 4) /* 4x / second */ #define UPCALL_EXPIRE 6 /* number of timeouts */ @@ -218,10 +225,6 @@ static MALLOC_DEFINE(M_BWMETER, "bwmeter", "multicast upcall bw meters"); */ VNET_DEFINE_STATIC(struct callout, bw_upcalls_ch); #define V_bw_upcalls_ch VNET(bw_upcalls_ch) -VNET_DEFINE_STATIC(struct buf_ring *, bw_upcalls_ring); -#define V_bw_upcalls_ring VNET(bw_upcalls_ring) -VNET_DEFINE_STATIC(struct mtx, bw_upcalls_ring_mtx); -#define V_bw_upcalls_ring_mtx VNET(bw_upcalls_ring_mtx) #define BW_UPCALLS_PERIOD (hz) /* periodical flush of bw upcalls */ @@ -296,11 +299,6 @@ static struct pim_encap_pimhdr pim_encap_pimhdr = { 0 /* flags */ }; -VNET_DEFINE_STATIC(vifi_t, reg_vif_num) = VIFI_INVALID; -#define V_reg_vif_num VNET(reg_vif_num) -VNET_DEFINE_STATIC(struct ifnet *, multicast_register_if); -#define V_multicast_register_if VNET(multicast_register_if) - /* * Private variables. */ @@ -332,14 +330,16 @@ static void free_bw_list(struct bw_meter *); static int get_sg_cnt(struct sioc_sg_req *); static int get_vif_cnt(struct sioc_vif_req *); static void if_detached_event(void *, struct ifnet *); -static int ip_mdq(struct mbuf *, struct ifnet *, struct mfc *, vifi_t); +static int ip_mdq(struct mfctable *, struct mbuf *, struct ifnet *, + struct mfc *, vifi_t); static int ip_mrouter_init(struct socket *, int); static __inline struct mfc * - mfc_find(struct in_addr *, struct in_addr *); + mfc_find(const struct mfctable *mfct, const struct in_addr *, + const struct in_addr *); static void phyint_send(struct ip *, struct vif *, struct mbuf *); static struct mbuf * pim_register_prepare(struct ip *, struct mbuf *); -static int pim_register_send(struct ip *, struct vif *, +static int pim_register_send(struct mfctable *, struct ip *, struct vif *, struct mbuf *, struct mfc *); static int pim_register_send_rp(struct ip *, struct vif *, struct mbuf *, struct mfc *); @@ -363,29 +363,20 @@ static const uint32_t mrt_api_support = (MRT_MFC_FLAGS_DISABLE_WRONGVIF | MRT_MFC_FLAGS_BORDER_VIF | MRT_MFC_RP | MRT_MFC_BW_UPCALL); -VNET_DEFINE_STATIC(uint32_t, mrt_api_config); -#define V_mrt_api_config VNET(mrt_api_config) -VNET_DEFINE_STATIC(int, pim_assert_enabled); -#define V_pim_assert_enabled VNET(pim_assert_enabled) -static struct timeval pim_assert_interval = { 3, 0 }; /* Rate limit */ /* * Find a route for a given origin IP address and multicast group address. * Statistics must be updated by the caller. */ -static __inline struct mfc * -mfc_find(struct in_addr *o, struct in_addr *g) +static struct mfc * +mfc_find(const struct mfctable *mfct, const struct in_addr *o, + const struct in_addr *g) { struct mfc *rt; - /* - * Might be called both RLOCK and WLOCK. - * Check if any, it's caller responsibility - * to choose correct option. - */ MRW_LOCK_ASSERT(); - LIST_FOREACH(rt, &V_mfchashtbl[MFCHASH(*o, *g)], mfc_hash) { + LIST_FOREACH(rt, &mfct->mfchashtbl[MFCHASH(*o, *g)], mfc_hash) { if (in_hosteq(rt->mfc_origin, *o) && in_hosteq(rt->mfc_mcastgrp, *g) && buf_ring_empty(rt->mfc_stall_ring)) @@ -403,8 +394,7 @@ mfc_alloc(void) if (rt == NULL) return rt; - rt->mfc_stall_ring = buf_ring_alloc(MAX_UPQ, M_MRTABLE, - M_NOWAIT, &V_buf_ring_mtx); + rt->mfc_stall_ring = buf_ring_alloc(MAX_UPQ, M_MRTABLE, M_NOWAIT, NULL); if (rt->mfc_stall_ring == NULL) { free(rt, M_MRTABLE); return NULL; @@ -419,6 +409,7 @@ mfc_alloc(void) static int X_ip_mrouter_set(struct socket *so, struct sockopt *sopt) { + struct mfctable *mfct; int error, optval; vifi_t vifi; struct vifctl vifc; @@ -426,7 +417,8 @@ X_ip_mrouter_set(struct socket *so, struct sockopt *sopt) struct bw_upcall bw_upcall; uint32_t i; - if (so != V_ip_mrouter && sopt->sopt_name != MRT_INIT) + mfct = &V_mfctables[0]; + if (so != mfct->router && sopt->sopt_name != MRT_INIT) return EPERM; error = 0; @@ -458,7 +450,7 @@ X_ip_mrouter_set(struct socket *so, struct sockopt *sopt) * select data size depending on API version. */ if (sopt->sopt_name == MRT_ADD_MFC && - V_mrt_api_config & MRT_API_FLAGS_ALL) { + (mfct->api_config & MRT_API_FLAGS_ALL) != 0) { error = sooptcopyin(sopt, &mfc, sizeof(struct mfcctl2), sizeof(struct mfcctl2)); } else { @@ -515,24 +507,27 @@ X_ip_mrouter_set(struct socket *so, struct sockopt *sopt) static int X_ip_mrouter_get(struct socket *so, struct sockopt *sopt) { + struct mfctable *mfct; int error; + mfct = &V_mfctables[0]; + switch (sopt->sopt_name) { case MRT_VERSION: error = sooptcopyout(sopt, &mrt_api_version, sizeof mrt_api_version); break; case MRT_ASSERT: - error = sooptcopyout(sopt, &V_pim_assert_enabled, - sizeof V_pim_assert_enabled); + error = sooptcopyout(sopt, &mfct->pim_assert_enabled, + sizeof(mfct->pim_assert_enabled)); break; case MRT_API_SUPPORT: error = sooptcopyout(sopt, &mrt_api_support, sizeof mrt_api_support); break; case MRT_API_CONFIG: - error = sooptcopyout(sopt, &V_mrt_api_config, - sizeof V_mrt_api_config); + error = sooptcopyout(sopt, &mfct->api_config, + sizeof(mfct->api_config)); break; default: error = EOPNOTSUPP; @@ -577,7 +572,7 @@ get_sg_cnt(struct sioc_sg_req *req) struct mfc *rt; MRW_RLOCK(); - rt = mfc_find(&req->src, &req->grp); + rt = mfc_find(&V_mfctables[0], &req->src, &req->grp); if (rt == NULL) { MRW_RUNLOCK(); req->pktcnt = req->bytecnt = req->wrong_if = 0xffffffff; @@ -596,18 +591,20 @@ get_sg_cnt(struct sioc_sg_req *req) static int get_vif_cnt(struct sioc_vif_req *req) { + struct mfctable *mfct; struct vif *vif; vifi_t vifi; + mfct = &V_mfctables[0]; vifi = req->vifi; MRW_RLOCK(); - if (vifi >= V_numvifs) { + if (vifi >= mfct->numvifs) { MRW_RUNLOCK(); return EINVAL; } - vif = &V_viftable[vifi]; + vif = &mfct->viftable[vifi]; mtx_lock(&vif->v_mtx); req->icount = vif->v_pkt_in; req->ocount = vif->v_pkt_out; @@ -622,10 +619,13 @@ get_vif_cnt(struct sioc_vif_req *req) static void if_detached_event(void *arg __unused, struct ifnet *ifp) { + struct mfctable *mfct; vifi_t vifi; u_long i, vifi_cnt = 0; struct ifnet *free_ptr, *multi_leave; + mfct = &V_mfctables[0]; + MRW_WLOCK(); if (!V_ip_mrouting_enabled) { MRW_WUNLOCK(); @@ -641,13 +641,14 @@ if_detached_event(void *arg __unused, struct ifnet *ifp) * 4. Free vif state. This should disable ALLMULTI on the interface. */ restart: - for (vifi = 0; vifi < V_numvifs; vifi++) { - if (V_viftable[vifi].v_ifp != ifp) + for (vifi = 0; vifi < mfct->numvifs; vifi++) { + if (mfct->viftable[vifi].v_ifp != ifp) continue; for (i = 0; i < mfchashsize; i++) { struct mfc *rt, *nrt; - LIST_FOREACH_SAFE(rt, &V_mfchashtbl[i], mfc_hash, nrt) { + LIST_FOREACH_SAFE(rt, &mfct->mfchashtbl[i], mfc_hash, + nrt) { if (rt->mfc_parent == vifi) { expire_mfc(rt); } @@ -693,12 +694,14 @@ ip_mrouter_upcall_thread(void *arg, int pending __unused) static int ip_mrouter_init(struct socket *so, int version) { + struct mfctable *mfct; CTR2(KTR_IPMF, "%s: so %p", __func__, so); if (version != 1) return ENOPROTOOPT; + mfct = &V_mfctables[0]; MRW_TEARDOWN_WLOCK(); MRW_WLOCK(); @@ -708,25 +711,26 @@ ip_mrouter_init(struct socket *so, int version) return ENOPROTOOPT; } - if (V_ip_mrouter != NULL) { + if (mfct->router != NULL) { MRW_WUNLOCK(); MRW_TEARDOWN_WUNLOCK(); return EADDRINUSE; } - V_mfchashtbl = hashinit_flags(mfchashsize, M_MRTABLE, &V_mfchash, + mfct->mfchashtbl = hashinit_flags(mfchashsize, M_MRTABLE, &V_mfchash, HASH_NOWAIT); - if (V_mfchashtbl == NULL) { + if (mfct->mfchashtbl == NULL) { MRW_WUNLOCK(); MRW_TEARDOWN_WUNLOCK(); return (ENOMEM); } /* Create upcall ring */ - mtx_init(&V_bw_upcalls_ring_mtx, "mroute upcall buf_ring mtx", NULL, MTX_DEF); - V_bw_upcalls_ring = buf_ring_alloc(BW_UPCALLS_MAX, M_MRTABLE, - M_NOWAIT, &V_bw_upcalls_ring_mtx); - if (!V_bw_upcalls_ring) { + mtx_init(&mfct->bw_upcalls_mtx, "mroute upcall buf_ring mtx", NULL, + MTX_DEF); + mfct->bw_upcalls = buf_ring_alloc(BW_UPCALLS_MAX, M_MRTABLE, M_NOWAIT, + &mfct->bw_upcalls_mtx); + if (mfct->bw_upcalls == NULL) { MRW_WUNLOCK(); MRW_TEARDOWN_WUNLOCK(); return (ENOMEM); @@ -741,13 +745,11 @@ ip_mrouter_init(struct socket *so, int version) callout_reset(&V_bw_upcalls_ch, BW_UPCALLS_PERIOD, expire_bw_upcalls_send, curvnet); - V_ip_mrouter = so; + mfct->router = so; + mfct->pim_assert_interval.tv_sec = 3; V_ip_mrouting_enabled = true; atomic_add_int(&ip_mrouter_cnt, 1); - /* This is a mutex required by buf_ring init, but not used internally */ - mtx_init(&V_buf_ring_mtx, "mroute buf_ring mtx", NULL, MTX_DEF); - MRW_WUNLOCK(); MRW_TEARDOWN_WUNLOCK(); @@ -762,14 +764,17 @@ ip_mrouter_init(struct socket *so, int version) static void X_ip_mrouter_done(struct socket *so) { + struct mfctable *mfct; struct ifnet **ifps; int nifp; u_long i; vifi_t vifi; struct bw_upcall *bu; + mfct = &V_mfctables[0]; + MRW_TEARDOWN_WLOCK(); - if (so != V_ip_mrouter) { + if (so != mfct->router) { MRW_TEARDOWN_WUNLOCK(); return; } @@ -777,10 +782,10 @@ X_ip_mrouter_done(struct socket *so) /* * Detach/disable hooks to the reset of the system. */ - V_ip_mrouter = NULL; + mfct->router = NULL; V_ip_mrouting_enabled = false; atomic_subtract_int(&ip_mrouter_cnt, 1); - V_mrt_api_config = 0; + mfct->api_config = 0; /* * Wait for all epoch sections to complete to ensure the new value of @@ -800,11 +805,11 @@ X_ip_mrouter_done(struct socket *so) taskqueue_cancel(V_task_queue, &V_task, NULL); /* Destroy upcall ring */ - while ((bu = buf_ring_dequeue_mc(V_bw_upcalls_ring)) != NULL) { + while ((bu = buf_ring_dequeue_mc(mfct->bw_upcalls)) != NULL) { free(bu, M_MRTABLE); } - buf_ring_free(V_bw_upcalls_ring, M_MRTABLE); - mtx_destroy(&V_bw_upcalls_ring_mtx); + buf_ring_free(mfct->bw_upcalls, M_MRTABLE); + mtx_destroy(&mfct->bw_upcalls_mtx); /* * For each phyint in use, prepare to disable promiscuous reception @@ -813,16 +818,19 @@ X_ip_mrouter_done(struct socket *so) * sx locks in their ioctl routines, which is not allowed while holding * a non-sleepable lock. */ - KASSERT(V_numvifs <= MAXVIFS, ("More vifs than possible")); - for (vifi = 0, nifp = 0; vifi < V_numvifs; vifi++) { - if (!in_nullhost(V_viftable[vifi].v_lcl_addr) && - !(V_viftable[vifi].v_flags & (VIFF_TUNNEL | VIFF_REGISTER))) { - ifps[nifp++] = V_viftable[vifi].v_ifp; + KASSERT(mfct->numvifs <= MAXVIFS, ("More vifs than possible")); + for (vifi = 0, nifp = 0; vifi < mfct->numvifs; vifi++) { + struct vif *vif; + + vif = &mfct->viftable[vifi]; + if (!in_nullhost(vif->v_lcl_addr) && + (vif->v_flags & (VIFF_TUNNEL | VIFF_REGISTER)) == 0) { + ifps[nifp++] = vif->v_ifp; } } - bzero((caddr_t)V_viftable, sizeof(*V_viftable) * MAXVIFS); - V_numvifs = 0; - V_pim_assert_enabled = 0; + bzero(mfct->viftable, sizeof(*mfct->viftable) * MAXVIFS); + mfct->numvifs = 0; + mfct->pim_assert_enabled = 0; callout_stop(&V_expire_upcalls_ch); callout_stop(&V_bw_upcalls_ch); @@ -834,18 +842,15 @@ X_ip_mrouter_done(struct socket *so) for (i = 0; i < mfchashsize; i++) { struct mfc *rt, *nrt; - LIST_FOREACH_SAFE(rt, &V_mfchashtbl[i], mfc_hash, nrt) { + LIST_FOREACH_SAFE(rt, &mfct->mfchashtbl[i], mfc_hash, nrt) { expire_mfc(rt); } } - free(V_mfchashtbl, M_MRTABLE); - V_mfchashtbl = NULL; - - bzero(V_nexpire, sizeof(V_nexpire[0]) * mfchashsize); + free(mfct->mfchashtbl, M_MRTABLE); + mfct->mfchashtbl = NULL; - V_reg_vif_num = VIFI_INVALID; - - mtx_destroy(&V_buf_ring_mtx); + bzero(mfct->nexpire, sizeof(mfct->nexpire[0]) * mfchashsize); + mfct->register_vif = VIFI_INVALID; MRW_WUNLOCK(); MRW_TEARDOWN_WUNLOCK(); @@ -870,7 +875,7 @@ set_assert(int i) if ((i != 1) && (i != 0)) return EINVAL; - V_pim_assert_enabled = i; + V_mfctables[0].pim_assert_enabled = i; return 0; } @@ -881,6 +886,7 @@ set_assert(int i) int set_api_config(uint32_t *apival) { + struct mfctable *mfct; u_long i; /* @@ -890,11 +896,12 @@ set_api_config(uint32_t *apival) * - pim_assert is not enabled * - the MFC table is empty */ - if (V_numvifs > 0) { + mfct = &V_mfctables[0]; + if (mfct->numvifs > 0) { *apival = 0; return EPERM; } - if (V_pim_assert_enabled) { + if (mfct->pim_assert_enabled) { *apival = 0; return EPERM; } @@ -902,7 +909,7 @@ set_api_config(uint32_t *apival) MRW_RLOCK(); for (i = 0; i < mfchashsize; i++) { - if (LIST_FIRST(&V_mfchashtbl[i]) != NULL) { + if (LIST_FIRST(&mfct->mfchashtbl[i]) != NULL) { MRW_RUNLOCK(); *apival = 0; return EPERM; @@ -911,8 +918,8 @@ set_api_config(uint32_t *apival) MRW_RUNLOCK(); - V_mrt_api_config = *apival & mrt_api_support; - *apival = V_mrt_api_config; + mfct->api_config = *apival & mrt_api_support; + *apival = mfct->api_config; return 0; } @@ -923,7 +930,8 @@ set_api_config(uint32_t *apival) static int add_vif(struct vifctl *vifcp) { - struct vif *vifp = V_viftable + vifcp->vifc_vifi; + struct mfctable *mfct; + struct vif *vifp; struct sockaddr_in sin = {sizeof sin, AF_INET}; struct ifaddr *ifa; struct ifnet *ifp; @@ -931,6 +939,10 @@ add_vif(struct vifctl *vifcp) if (vifcp->vifc_vifi >= MAXVIFS) return EINVAL; + + mfct = &V_mfctables[0]; + vifp = &mfct->viftable[vifcp->vifc_vifi]; + /* rate limiting is no longer supported by this code */ if (vifcp->vifc_rate_limit != 0) { log(LOG_ERR, "rate limiting is no longer supported\n"); @@ -967,11 +979,11 @@ add_vif(struct vifctl *vifcp) CTR1(KTR_IPMF, "%s: tunnels are no longer supported", __func__); return EOPNOTSUPP; } else if (vifcp->vifc_flags & VIFF_REGISTER) { - ifp = V_multicast_register_if = if_alloc(IFT_LOOP); + ifp = mfct->register_if = if_alloc(IFT_LOOP); CTR2(KTR_IPMF, "%s: add register vif for ifp %p", __func__, ifp); - if (V_reg_vif_num == VIFI_INVALID) { - if_initname(V_multicast_register_if, "register_vif", 0); - V_reg_vif_num = vifcp->vifc_vifi; + if (mfct->register_vif == VIFI_INVALID) { + if_initname(mfct->register_if, "register_vif", 0); + mfct->register_vif = vifcp->vifc_vifi; } } else { /* Make sure the interface supports multicast */ if ((ifp->if_flags & IFF_MULTICAST) == 0) @@ -987,7 +999,7 @@ add_vif(struct vifctl *vifcp) if (!in_nullhost(vifp->v_lcl_addr)) { if (ifp) - V_multicast_register_if = NULL; + mfct->register_if = NULL; MRW_WUNLOCK(); if (ifp) if_free(ifp); @@ -1008,8 +1020,8 @@ add_vif(struct vifctl *vifcp) mtx_init(&vifp->v_mtx, vifp->v_mtx_name, NULL, MTX_DEF); /* Adjust numvifs up if the vifi is higher than numvifs */ - if (V_numvifs <= vifcp->vifc_vifi) - V_numvifs = vifcp->vifc_vifi + 1; + if (mfct->numvifs <= vifcp->vifc_vifi) + mfct->numvifs = vifcp->vifc_vifi + 1; MRW_WUNLOCK(); @@ -1026,17 +1038,19 @@ add_vif(struct vifctl *vifcp) static int del_vif_locked(vifi_t vifi, struct ifnet **ifp_multi_leave, struct ifnet **ifp_free) { + struct mfctable *mfct; struct vif *vifp; + mfct = &V_mfctables[0]; *ifp_free = NULL; *ifp_multi_leave = NULL; MRW_WLOCK_ASSERT(); - if (vifi >= V_numvifs) { + if (vifi >= mfct->numvifs) { return EINVAL; } - vifp = &V_viftable[vifi]; + vifp = &mfct->viftable[vifi]; if (in_nullhost(vifp->v_lcl_addr)) { return EADDRNOTAVAIL; } @@ -1045,10 +1059,10 @@ del_vif_locked(vifi_t vifi, struct ifnet **ifp_multi_leave, struct ifnet **ifp_f *ifp_multi_leave = vifp->v_ifp; if (vifp->v_flags & VIFF_REGISTER) { - V_reg_vif_num = VIFI_INVALID; + mfct->register_vif = VIFI_INVALID; if (vifp->v_ifp) { - if (vifp->v_ifp == V_multicast_register_if) - V_multicast_register_if = NULL; + if (vifp->v_ifp == mfct->register_if) + mfct->register_if = NULL; *ifp_free = vifp->v_ifp; } } @@ -1060,10 +1074,10 @@ del_vif_locked(vifi_t vifi, struct ifnet **ifp_multi_leave, struct ifnet **ifp_f CTR2(KTR_IPMF, "%s: delete vif %d", __func__, (int)vifi); /* Adjust numvifs down */ - for (vifi = V_numvifs; vifi > 0; vifi--) - if (!in_nullhost(V_viftable[vifi-1].v_lcl_addr)) + for (vifi = mfct->numvifs; vifi > 0; vifi--) + if (!in_nullhost(mfct->viftable[vifi - 1].v_lcl_addr)) break; - V_numvifs = vifi; + mfct->numvifs = vifi; return 0; } @@ -1091,18 +1105,18 @@ del_vif(vifi_t vifi) * update an mfc entry without resetting counters and S,G addresses. */ static void -update_mfc_params(struct mfc *rt, struct mfcctl2 *mfccp) +update_mfc_params(struct mfctable *mfct, struct mfc *rt, struct mfcctl2 *mfccp) { int i; rt->mfc_parent = mfccp->mfcc_parent; - for (i = 0; i < V_numvifs; i++) { + for (i = 0; i < mfct->numvifs; i++) { rt->mfc_ttls[i] = mfccp->mfcc_ttls[i]; - rt->mfc_flags[i] = mfccp->mfcc_flags[i] & V_mrt_api_config & + rt->mfc_flags[i] = mfccp->mfcc_flags[i] & mfct->api_config & MRT_MFC_FLAGS_ALL; } /* set the RP address */ - if (V_mrt_api_config & MRT_MFC_RP) + if (mfct->api_config & MRT_MFC_RP) rt->mfc_rp = mfccp->mfcc_rp; else rt->mfc_rp.s_addr = INADDR_ANY; @@ -1112,12 +1126,12 @@ update_mfc_params(struct mfc *rt, struct mfcctl2 *mfccp) * fully initialize an mfc entry from the parameter. */ static void -init_mfc_params(struct mfc *rt, struct mfcctl2 *mfccp) +init_mfc_params(struct mfctable *mfct, struct mfc *rt, struct mfcctl2 *mfccp) { rt->mfc_origin = mfccp->mfcc_origin; rt->mfc_mcastgrp = mfccp->mfcc_mcastgrp; - update_mfc_params(rt, mfccp); + update_mfc_params(mfct, rt, mfccp); /* initialize pkt counters per src-grp */ rt->mfc_pkt_cnt = 0; @@ -1156,13 +1170,16 @@ static int add_mfc(struct mfcctl2 *mfccp) { struct mfc *rt; + struct mfctable *mfct; struct rtdetq *rte; u_long hash = 0; u_short nstl; struct epoch_tracker et; + mfct = &V_mfctables[0]; + MRW_WLOCK(); - rt = mfc_find(&mfccp->mfcc_origin, &mfccp->mfcc_mcastgrp); + rt = mfc_find(mfct, &mfccp->mfcc_origin, &mfccp->mfcc_mcastgrp); /* If an entry already exists, just update the fields */ if (rt) { @@ -1170,7 +1187,7 @@ add_mfc(struct mfcctl2 *mfccp) __func__, ntohl(mfccp->mfcc_origin.s_addr), (u_long)ntohl(mfccp->mfcc_mcastgrp.s_addr), mfccp->mfcc_parent); - update_mfc_params(rt, mfccp); + update_mfc_params(mfct, rt, mfccp); MRW_WUNLOCK(); return (0); } @@ -1181,7 +1198,7 @@ add_mfc(struct mfcctl2 *mfccp) nstl = 0; hash = MFCHASH(mfccp->mfcc_origin, mfccp->mfcc_mcastgrp); NET_EPOCH_ENTER(et); - LIST_FOREACH(rt, &V_mfchashtbl[hash], mfc_hash) { + LIST_FOREACH(rt, &mfct->mfchashtbl[hash], mfc_hash) { if (in_hosteq(rt->mfc_origin, mfccp->mfcc_origin) && in_hosteq(rt->mfc_mcastgrp, mfccp->mfcc_mcastgrp) && !buf_ring_empty(rt->mfc_stall_ring)) { @@ -1194,15 +1211,15 @@ add_mfc(struct mfcctl2 *mfccp) if (nstl++) CTR1(KTR_IPMF, "%s: multiple matches", __func__); - init_mfc_params(rt, mfccp); + init_mfc_params(mfct, rt, mfccp); rt->mfc_expire = 0; /* Don't clean this guy up */ - V_nexpire[hash]--; + mfct->nexpire[hash]--; /* Free queued packets, but attempt to forward them first. */ while (!buf_ring_empty(rt->mfc_stall_ring)) { rte = buf_ring_dequeue_mc(rt->mfc_stall_ring); if (rte->ifp != NULL) - ip_mdq(rte->m, rte->ifp, rt, -1); + ip_mdq(mfct, rte->m, rte->ifp, rt, -1); m_freem(rte->m); free(rte, M_MRTABLE); } @@ -1215,12 +1232,12 @@ add_mfc(struct mfcctl2 *mfccp) */ if (nstl == 0) { CTR1(KTR_IPMF, "%s: adding mfc w/o upcall", __func__); - LIST_FOREACH(rt, &V_mfchashtbl[hash], mfc_hash) { + LIST_FOREACH(rt, &mfct->mfchashtbl[hash], mfc_hash) { if (in_hosteq(rt->mfc_origin, mfccp->mfcc_origin) && in_hosteq(rt->mfc_mcastgrp, mfccp->mfcc_mcastgrp)) { - init_mfc_params(rt, mfccp); + init_mfc_params(mfct, rt, mfccp); if (rt->mfc_expire) - V_nexpire[hash]--; + mfct->nexpire[hash]--; rt->mfc_expire = 0; break; /* XXX */ } @@ -1233,14 +1250,14 @@ add_mfc(struct mfcctl2 *mfccp) return (ENOBUFS); } - init_mfc_params(rt, mfccp); + init_mfc_params(mfct, rt, mfccp); rt->mfc_expire = 0; rt->mfc_bw_meter_leq = NULL; rt->mfc_bw_meter_geq = NULL; /* insert new entry at head of hash chain */ - LIST_INSERT_HEAD(&V_mfchashtbl[hash], rt, mfc_hash); + LIST_INSERT_HEAD(&mfct->mfchashtbl[hash], rt, mfc_hash); } } @@ -1255,6 +1272,7 @@ add_mfc(struct mfcctl2 *mfccp) static int del_mfc(struct mfcctl2 *mfccp) { + struct mfctable *mfct; struct in_addr origin; struct in_addr mcastgrp; struct mfc *rt; @@ -1265,9 +1283,11 @@ del_mfc(struct mfcctl2 *mfccp) CTR3(KTR_IPMF, "%s: delete mfc orig 0x%08x group %lx", __func__, ntohl(origin.s_addr), (u_long)ntohl(mcastgrp.s_addr)); + mfct = &V_mfctables[0]; MRW_WLOCK(); - LIST_FOREACH(rt, &V_mfchashtbl[MFCHASH(origin, mcastgrp)], mfc_hash) { + LIST_FOREACH(rt, &mfct->mfchashtbl[MFCHASH(origin, mcastgrp)], + mfc_hash) { if (in_hosteq(rt->mfc_origin, origin) && in_hosteq(rt->mfc_mcastgrp, mcastgrp)) break; @@ -1321,6 +1341,7 @@ X_ip_mforward(struct ip *ip, struct ifnet *ifp, struct mbuf *m, struct ip_moptions *imo) { struct mfc *rt; + struct mfctable *mfct; int error; vifi_t vifi; struct mbuf *mb0; @@ -1347,14 +1368,16 @@ X_ip_mforward(struct ip *ip, struct ifnet *ifp, struct mbuf *m, return (1); } + mfct = &V_mfctables[0]; + /* * BEGIN: MCAST ROUTING HOT PATH */ MRW_RLOCK(); - if (imo && ((vifi = imo->imo_multicast_vif) < V_numvifs)) { + if (imo && ((vifi = imo->imo_multicast_vif) < mfct->numvifs)) { if (ip->ip_ttl < MAXTTL) ip->ip_ttl++; /* compensate for -1 in *_send routines */ - error = ip_mdq(m, ifp, NULL, vifi); + error = ip_mdq(mfct, m, ifp, NULL, vifi); MRW_RUNLOCK(); return error; } @@ -1373,11 +1396,11 @@ mfc_find_retry: * Determine forwarding vifs from the forwarding cache table */ MRTSTAT_INC(mrts_mfc_lookups); - rt = mfc_find(&ip->ip_src, &ip->ip_dst); + rt = mfc_find(mfct, &ip->ip_src, &ip->ip_dst); /* Entry exists, so forward if necessary */ if (rt != NULL) { - error = ip_mdq(m, ifp, rt, -1); + error = ip_mdq(mfct, m, ifp, rt, -1); /* Generic unlock here as we might release R or W lock */ MRW_UNLOCK(); return error; @@ -1427,8 +1450,7 @@ mfc_find_retry: /* is there an upcall waiting for this flow ? */ hash = MFCHASH(ip->ip_src, ip->ip_dst); - LIST_FOREACH(rt, &V_mfchashtbl[hash], mfc_hash) - { + LIST_FOREACH(rt, &mfct->mfchashtbl[hash], mfc_hash) { if (in_hosteq(ip->ip_src, rt->mfc_origin) && in_hosteq(ip->ip_dst, rt->mfc_mcastgrp) && !buf_ring_empty(rt->mfc_stall_ring)) @@ -1445,10 +1467,10 @@ mfc_find_retry: * Locate the vifi for the incoming interface for this packet. * If none found, drop packet. */ - for (vifi = 0; vifi < V_numvifs && - V_viftable[vifi].v_ifp != ifp; vifi++) + for (vifi = 0; vifi < mfct->numvifs && + mfct->viftable[vifi].v_ifp != ifp; vifi++) ; - if (vifi >= V_numvifs) /* vif not found, drop packet */ + if (vifi >= mfct->numvifs) /* vif not found, drop packet */ goto non_fatal; /* no upcall, so make a new entry */ @@ -1474,7 +1496,7 @@ mfc_find_retry: MRTSTAT_INC(mrts_upcalls); k_igmpsrc.sin_addr = ip->ip_src; - if (socket_send(V_ip_mrouter, mm, &k_igmpsrc) < 0) { + if (socket_send(mfct->router, mm, &k_igmpsrc) < 0) { CTR0(KTR_IPMF, "ip_mforward: socket queue full"); MRTSTAT_INC(mrts_upq_sockfull); fail1: free(rt, M_MRTABLE); @@ -1488,8 +1510,8 @@ mfc_find_retry: rt->mfc_origin.s_addr = ip->ip_src.s_addr; rt->mfc_mcastgrp.s_addr = ip->ip_dst.s_addr; rt->mfc_expire = UPCALL_EXPIRE; - V_nexpire[hash]++; - for (i = 0; i < V_numvifs; i++) { + mfct->nexpire[hash]++; + for (i = 0; i < mfct->numvifs; i++) { rt->mfc_ttls[i] = 0; rt->mfc_flags[i] = 0; } @@ -1509,7 +1531,7 @@ mfc_find_retry: buf_ring_enqueue(rt->mfc_stall_ring, rte); /* Add RT to hashtable as it didn't exist before */ - LIST_INSERT_HEAD(&V_mfchashtbl[hash], rt, mfc_hash); + LIST_INSERT_HEAD(&mfct->mfchashtbl[hash], rt, mfc_hash); } else { /* determine if queue has overflowed */ if (buf_ring_full(rt->mfc_stall_ring)) { @@ -1537,19 +1559,21 @@ mfc_find_retry: static void expire_upcalls(void *arg) { + struct mfctable *mfct; u_long i; CURVNET_SET((struct vnet *) arg); - /*This callout is always run with MRW_WLOCK taken. */ + MRW_LOCK_ASSERT(); + mfct = &V_mfctables[0]; for (i = 0; i < mfchashsize; i++) { struct mfc *rt, *nrt; - if (V_nexpire[i] == 0) + if (mfct->nexpire[i] == 0) continue; - LIST_FOREACH_SAFE(rt, &V_mfchashtbl[i], mfc_hash, nrt) { + LIST_FOREACH_SAFE(rt, &mfct->mfchashtbl[i], mfc_hash, nrt) { if (buf_ring_empty(rt->mfc_stall_ring)) continue; @@ -1575,7 +1599,8 @@ expire_upcalls(void *arg) * Packet forwarding routine once entry in the cache is made */ static int -ip_mdq(struct mbuf *m, struct ifnet *ifp, struct mfc *rt, vifi_t xmt_vif) +ip_mdq(struct mfctable *mfct, struct mbuf *m, struct ifnet *ifp, struct mfc *rt, + vifi_t xmt_vif) { struct ip *ip = mtod(m, struct ip *); struct vif *vif; @@ -1591,11 +1616,12 @@ ip_mdq(struct mbuf *m, struct ifnet *ifp, struct mfc *rt, vifi_t xmt_vif) * * (since vifi_t is u_short, -1 becomes MAXUSHORT, which > numvifs.) */ - if (xmt_vif < V_numvifs) { - if (V_viftable[xmt_vif].v_flags & VIFF_REGISTER) - pim_register_send(ip, V_viftable + xmt_vif, m, rt); + if (xmt_vif < mfct->numvifs) { + if (mfct->viftable[xmt_vif].v_flags & VIFF_REGISTER) + pim_register_send(mfct, ip, &mfct->viftable[xmt_vif], m, + rt); else - phyint_send(ip, V_viftable + xmt_vif, m); + phyint_send(ip, &mfct->viftable[xmt_vif], m); return 1; } @@ -1603,8 +1629,8 @@ ip_mdq(struct mbuf *m, struct ifnet *ifp, struct mfc *rt, vifi_t xmt_vif) * Don't forward if it didn't arrive from the parent vif for its origin. */ vifi = rt->mfc_parent; - vif = &V_viftable[vifi]; - if (vifi >= V_numvifs || vif->v_ifp != ifp) { + vif = &mfct->viftable[vifi]; + if (vifi >= mfct->numvifs || vif->v_ifp != ifp) { CTR4(KTR_IPMF, "%s: rx on wrong ifp %p (vifi %d, v_ifp %p)", __func__, ifp, (int)vifi, vif->v_ifp); MRTSTAT_INC(mrts_wrong_if); @@ -1617,21 +1643,23 @@ ip_mdq(struct mbuf *m, struct ifnet *ifp, struct mfc *rt, vifi_t xmt_vif) * can complete the SPT switch, regardless of the type * of the iif (broadcast media, GRE tunnel, etc). */ - if (V_pim_assert_enabled && (vifi < V_numvifs) && + if (mfct->pim_assert_enabled && (vifi < mfct->numvifs) && vif->v_ifp != NULL) { - if (ifp == V_multicast_register_if) + if (ifp == mfct->register_if) PIMSTAT_INC(pims_rcv_registers_wrongiif); /* Get vifi for the incoming packet */ - for (vifi = 0; vifi < V_numvifs && V_viftable[vifi].v_ifp != ifp; vifi++) + for (vifi = 0; vifi < mfct->numvifs && + mfct->viftable[vifi].v_ifp != ifp; vifi++) ; - if (vifi >= V_numvifs) + if (vifi >= mfct->numvifs) return 0; /* The iif is not found: ignore the packet. */ if (rt->mfc_flags[vifi] & MRT_MFC_FLAGS_DISABLE_WRONGVIF) return 0; /* WRONGVIF disabled: ignore the packet */ - if (ratecheck(&rt->mfc_last_assert, &pim_assert_interval)) { + if (ratecheck(&rt->mfc_last_assert, + &mfct->pim_assert_interval)) { struct sockaddr_in k_igmpsrc = { sizeof k_igmpsrc, AF_INET }; struct igmpmsg *im; int hlen = ip->ip_hl << 2; @@ -1650,7 +1678,8 @@ ip_mdq(struct mbuf *m, struct ifnet *ifp, struct mfc *rt, vifi_t xmt_vif) MRTSTAT_INC(mrts_upcalls); k_igmpsrc.sin_addr = im->im_src; - if (socket_send(V_ip_mrouter, mm, &k_igmpsrc) < 0) { + if (socket_send(mfct->router, mm, + &k_igmpsrc) < 0) { CTR1(KTR_IPMF, "%s: socket queue full", __func__); MRTSTAT_INC(mrts_upq_sockfull); return ENOBUFS; @@ -1680,13 +1709,13 @@ ip_mdq(struct mbuf *m, struct ifnet *ifp, struct mfc *rt, vifi_t xmt_vif) * - the ttl exceeds the vif's threshold * - there are group members downstream on interface */ - for (vifi = 0; vifi < V_numvifs; vifi++) + for (vifi = 0; vifi < mfct->numvifs; vifi++) if ((rt->mfc_ttls[vifi] > 0) && (ip->ip_ttl > rt->mfc_ttls[vifi])) { - vif = &V_viftable[vifi]; + vif = &mfct->viftable[vifi]; *** 425 LINES SKIPPED ***home | help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?69caa1a7.3b9c2.3d515715>
