Page MenuHomeFreeBSD

D55237.id174555.diff
No OneTemporary

D55237.id174555.diff

diff --git a/sys/netinet/ip_mroute.c b/sys/netinet/ip_mroute.c
--- a/sys/netinet/ip_mroute.c
+++ b/sys/netinet/ip_mroute.c
@@ -169,8 +169,26 @@
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 @@
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 @@
*/
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 @@
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 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 @@
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 @@
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 @@
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 @@
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 @@
* 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 @@
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 @@
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 @@
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 @@
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 @@
* 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 @@
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 @@
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 @@
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 @@
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 @@
/*
* 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 @@
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 @@
* 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 @@
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 @@
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 @@
int
set_api_config(uint32_t *apival)
{
+ struct mfctable *mfct;
u_long i;
/*
@@ -890,11 +896,12 @@
* - 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
*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 @@
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 @@
* 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 @@
* 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 @@
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 @@
__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 @@
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 @@
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 @@
*/
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 @@
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 @@
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 @@
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 @@
struct ip_moptions *imo)
{
struct mfc *rt;
+ struct mfctable *mfct;
int error;
vifi_t vifi;
struct mbuf *mb0;
@@ -1347,14 +1368,16 @@
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 @@
* 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 @@
/* 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 @@
* 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 @@
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 @@
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 @@
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 @@
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 @@
* 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 @@
*
* (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 @@
* 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 @@
* 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 @@
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 @@
* - 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];
vif->v_pkt_out++;
vif->v_bytes_out += plen;
if (vif->v_flags & VIFF_REGISTER)
- pim_register_send(ip, vif, m, rt);
+ pim_register_send(mfct, ip, vif, m, rt);
else
phyint_send(ip, vif, m);
}
@@ -1734,7 +1763,7 @@
return (ret);
MRW_RLOCK();
- if (vif < V_numvifs)
+ if (vif < V_mfctables[0].numvifs)
ret = 1;
MRW_RUNLOCK();
@@ -1754,8 +1783,8 @@
return (addr);
MRW_RLOCK();
- if (vifi < V_numvifs)
- addr = V_viftable[vifi].v_lcl_addr.s_addr;
+ if (vifi < V_mfctables[0].numvifs)
+ addr = V_mfctables[0].viftable[vifi].v_lcl_addr.s_addr;
MRW_RUNLOCK();
return (addr);
@@ -1807,7 +1836,7 @@
*/
error = ip_output(m, NULL, NULL, IP_FORWARDING, &imo, NULL);
CTR3(KTR_IPMF, "%s: vif %td err %d", __func__,
- (ptrdiff_t)(vifp - V_viftable), error);
+ (ptrdiff_t)(vifp - V_mfctables[0].viftable), error);
}
/*
@@ -1872,13 +1901,11 @@
{
struct bw_meter *x = arg;
struct timeval now;
- /*
- * INFO:
- * callout is always executed with MRW_WLOCK taken
- */
CURVNET_SET((struct vnet *)x->arg);
+ MRW_LOCK_ASSERT();
+
microtime(&now);
/*
@@ -1917,6 +1944,7 @@
static int
add_bw_upcall(struct bw_upcall *req)
{
+ struct mfctable *mfct;
struct mfc *mfc;
struct timeval delta = { BW_UPCALL_THRESHOLD_INTERVAL_MIN_SEC,
BW_UPCALL_THRESHOLD_INTERVAL_MIN_USEC };
@@ -1924,7 +1952,9 @@
struct bw_meter *x, **bwm_ptr;
uint32_t flags;
- if (!(V_mrt_api_config & MRT_MFC_BW_UPCALL))
+ mfct = &V_mfctables[0];
+
+ if (!(mfct->api_config & MRT_MFC_BW_UPCALL))
return EOPNOTSUPP;
/* Test if the flags are valid */
@@ -1945,7 +1975,7 @@
* Find if we have already same bw_meter entry
*/
MRW_WLOCK();
- mfc = mfc_find(&req->bu_src, &req->bu_dst);
+ mfc = mfc_find(&V_mfctables[0], &req->bu_src, &req->bu_dst);
if (mfc == NULL) {
MRW_WUNLOCK();
return EADDRNOTAVAIL;
@@ -2032,16 +2062,19 @@
static int
del_bw_upcall(struct bw_upcall *req)
{
+ struct mfctable *mfct;
struct mfc *mfc;
struct bw_meter *x, **bwm_ptr;
- if (!(V_mrt_api_config & MRT_MFC_BW_UPCALL))
+ mfct = &V_mfctables[0];
+
+ if (!(mfct->api_config & MRT_MFC_BW_UPCALL))
return EOPNOTSUPP;
MRW_WLOCK();
/* Find the corresponding MFC entry */
- mfc = mfc_find(&req->bu_src, &req->bu_dst);
+ mfc = mfc_find(mfct, &req->bu_src, &req->bu_dst);
if (mfc == NULL) {
MRW_WUNLOCK();
return EADDRNOTAVAIL;
@@ -2155,11 +2188,14 @@
static void
bw_meter_prepare_upcall(struct bw_meter *x, struct timeval *nowp)
{
+ struct mfctable *mfct;
struct timeval delta;
struct bw_upcall *u;
MRW_LOCK_ASSERT();
+ mfct = &V_mfctables[0];
+
/*
* Compute the measured time interval
*/
@@ -2192,9 +2228,9 @@
if (x->bm_flags & BW_METER_LEQ)
u->bu_flags |= BW_UPCALL_LEQ;
- if (buf_ring_enqueue(V_bw_upcalls_ring, u))
+ if (buf_ring_enqueue(mfct->bw_upcalls, u))
log(LOG_WARNING, "bw_meter_prepare_upcall: cannot enqueue upcall\n");
- if (buf_ring_count(V_bw_upcalls_ring) > (BW_UPCALLS_MAX / 2)) {
+ if (buf_ring_count(mfct->bw_upcalls) > (BW_UPCALLS_MAX / 2)) {
taskqueue_enqueue(V_task_queue, &V_task);
}
}
@@ -2204,6 +2240,7 @@
static void
bw_upcalls_send(void)
{
+ struct mfctable *mfct;
struct mbuf *m;
int len = 0;
struct bw_upcall *bu;
@@ -2219,9 +2256,11 @@
{ 0 } /* im_dst */
};
+ mfct = &V_mfctables[0];
+
MRW_LOCK_ASSERT();
- if (buf_ring_empty(V_bw_upcalls_ring))
+ if (buf_ring_empty(mfct->bw_upcalls))
return;
/*
@@ -2236,7 +2275,7 @@
m_copyback(m, 0, sizeof(struct igmpmsg), (caddr_t)&igmpmsg);
len += sizeof(struct igmpmsg);
- while ((bu = buf_ring_dequeue_mc(V_bw_upcalls_ring)) != NULL) {
+ while ((bu = buf_ring_dequeue_mc(mfct->bw_upcalls)) != NULL) {
m_copyback(m, len, sizeof(struct bw_upcall), (caddr_t)bu);
len += sizeof(struct bw_upcall);
free(bu, M_MRTABLE);
@@ -2247,7 +2286,7 @@
* XXX do we need to set the address in k_igmpsrc ?
*/
MRTSTAT_INC(mrts_upcalls);
- if (socket_send(V_ip_mrouter, m, &k_igmpsrc) < 0) {
+ if (socket_send(mfct->router, m, &k_igmpsrc) < 0) {
log(LOG_WARNING, "bw_upcalls_send: ip_mrouter socket queue full\n");
MRTSTAT_INC(mrts_upq_sockfull);
}
@@ -2279,8 +2318,8 @@
*
*/
static int
-pim_register_send(struct ip *ip, struct vif *vifp, struct mbuf *m,
- struct mfc *rt)
+pim_register_send(struct mfctable *mfct, struct ip *ip, struct vif *vifp,
+ struct mbuf *m, struct mfc *rt)
{
struct mbuf *mb_copy, *mm;
@@ -2288,7 +2327,7 @@
* Do not send IGMP_WHOLEPKT notifications to userland, if the
* rendezvous point was unspecified, and we were told not to.
*/
- if (pim_squelch_wholepkt != 0 && (V_mrt_api_config & MRT_MFC_RP) &&
+ if (pim_squelch_wholepkt != 0 && (mfct->api_config & MRT_MFC_RP) &&
in_nullhost(rt->mfc_rp))
return 0;
@@ -2306,7 +2345,8 @@
mm = m_pullup(mm, sizeof(struct ip));
if (mm != NULL) {
ip = mtod(mm, struct ip *);
- if ((V_mrt_api_config & MRT_MFC_RP) && !in_nullhost(rt->mfc_rp)) {
+ if ((mfct->api_config & MRT_MFC_RP) &&
+ !in_nullhost(rt->mfc_rp)) {
pim_register_send_rp(ip, vifp, mm, rt);
} else {
pim_register_send_upcall(ip, vifp, mm, rt);
@@ -2374,6 +2414,7 @@
pim_register_send_upcall(struct ip *ip, struct vif *vifp,
struct mbuf *mb_copy, struct mfc *rt)
{
+ struct mfctable *mfct;
struct mbuf *mb_first;
int len = ntohs(ip->ip_len);
struct igmpmsg *im;
@@ -2381,6 +2422,8 @@
MRW_LOCK_ASSERT();
+ mfct = &V_mfctables[0];
+
/*
* Add a new mbuf with an upcall header
*/
@@ -2398,7 +2441,7 @@
im = mtod(mb_first, struct igmpmsg *);
im->im_msgtype = IGMPMSG_WHOLEPKT;
im->im_mbz = 0;
- im->im_vif = vifp - V_viftable;
+ im->im_vif = vifp - mfct->viftable;
im->im_src = ip->ip_src;
im->im_dst = ip->ip_dst;
@@ -2406,7 +2449,7 @@
MRTSTAT_INC(mrts_upcalls);
- if (socket_send(V_ip_mrouter, mb_first, &k_igmpsrc) < 0) {
+ if (socket_send(mfct->router, mb_first, &k_igmpsrc) < 0) {
CTR1(KTR_IPMF, "%s: socket queue full", __func__);
MRTSTAT_INC(mrts_upq_sockfull);
return ENOBUFS;
@@ -2426,6 +2469,7 @@
pim_register_send_rp(struct ip *ip, struct vif *vifp, struct mbuf *mb_copy,
struct mfc *rt)
{
+ struct mfctable *mfct;
struct mbuf *mb_first;
struct ip *ip_outer;
struct pim_encap_pimhdr *pimhdr;
@@ -2434,7 +2478,9 @@
MRW_LOCK_ASSERT();
- if ((vifi >= V_numvifs) || in_nullhost(V_viftable[vifi].v_lcl_addr)) {
+ mfct = &V_mfctables[0];
+ if (vifi >= mfct->numvifs ||
+ in_nullhost(mfct->viftable[vifi].v_lcl_addr)) {
m_freem(mb_copy);
return EADDRNOTAVAIL; /* The iif vif is invalid */
}
@@ -2460,7 +2506,7 @@
*ip_outer = pim_encap_iphdr;
ip_outer->ip_len = htons(len + sizeof(pim_encap_iphdr) +
sizeof(pim_encap_pimhdr));
- ip_outer->ip_src = V_viftable[vifi].v_lcl_addr;
+ ip_outer->ip_src = mfct->viftable[vifi].v_lcl_addr;
ip_outer->ip_dst = rt->mfc_rp;
/*
* Copy the inner header TOS to the outer header, and take care of the
@@ -2474,7 +2520,7 @@
+ sizeof(pim_encap_iphdr));
*pimhdr = pim_encap_pimhdr;
/* If the iif crosses a border, set the Border-bit */
- if (rt->mfc_flags[vifi] & MRT_MFC_FLAGS_BORDER_VIF & V_mrt_api_config)
+ if (rt->mfc_flags[vifi] & MRT_MFC_FLAGS_BORDER_VIF & mfct->api_config)
pimhdr->flags |= htonl(PIM_BORDER_REGISTER);
mb_first->m_data += sizeof(pim_encap_iphdr);
@@ -2515,6 +2561,7 @@
static int
pim_input(struct mbuf *m, int off, int proto, void *arg __unused)
{
+ struct mfctable *mfct;
struct ip *ip = mtod(m, struct ip *);
struct pim *pim;
int iphlen = off;
@@ -2522,6 +2569,8 @@
int datalen = ntohs(ip->ip_len) - iphlen;
int ip_tos;
+ mfct = &V_mfctables[0];
+
/* Keep statistics */
PIMSTAT_INC(pims_rcv_total_msgs);
PIMSTAT_ADD(pims_rcv_total_bytes, datalen);
@@ -2606,15 +2655,16 @@
struct ifnet *vifp;
MRW_RLOCK();
- if ((V_reg_vif_num >= V_numvifs) || (V_reg_vif_num == VIFI_INVALID)) {
+ if (mfct->register_vif >= mfct->numvifs ||
+ mfct->register_vif == VIFI_INVALID) {
MRW_RUNLOCK();
CTR2(KTR_IPMF, "%s: register vif not set: %d", __func__,
- (int)V_reg_vif_num);
+ (int)mfct->register_vif);
m_freem(m);
return (IPPROTO_DONE);
}
/* XXX need refcnt? */
- vifp = V_viftable[V_reg_vif_num].v_ifp;
+ vifp = mfct->viftable[mfct->register_vif].v_ifp;
MRW_RUNLOCK();
/*
@@ -2706,7 +2756,7 @@
__func__,
(u_long)ntohl(encap_ip->ip_src.s_addr),
(u_long)ntohl(encap_ip->ip_dst.s_addr),
- (int)V_reg_vif_num);
+ (int)mfct->register_vif);
/* NB: vifp was collected above; can it change on us? */
if_simloop(vifp, m, dst.sin_family, 0);
@@ -2730,23 +2780,25 @@
static int
sysctl_mfctable(SYSCTL_HANDLER_ARGS)
{
- struct mfc *rt;
- int error, i;
+ struct mfctable *mfct;
+ struct mfc *rt;
+ int error, i;
if (req->newptr)
return (EPERM);
- if (V_mfchashtbl == NULL) /* XXX unlocked */
+ mfct = &V_mfctables[0];
+ if (mfct->mfchashtbl == NULL) /* XXX unlocked */
return (0);
error = sysctl_wire_old_buffer(req, 0);
if (error)
return (error);
MRW_RLOCK();
- if (V_mfchashtbl == NULL)
+ if (mfct->mfchashtbl == NULL)
goto out_locked;
for (i = 0; i < mfchashsize; i++) {
- LIST_FOREACH(rt, &V_mfchashtbl[i], mfc_hash) {
+ LIST_FOREACH(rt, &mfct->mfchashtbl[i], mfc_hash) {
error = SYSCTL_OUT(req, rt, sizeof(struct mfc));
if (error)
goto out_locked;
@@ -2765,20 +2817,21 @@
static int
sysctl_viflist(SYSCTL_HANDLER_ARGS)
{
+ struct mfctable *mfct;
int error, i;
if (req->newptr)
return (EPERM);
- if (V_viftable == NULL) /* XXX unlocked */
- return (0);
error = sysctl_wire_old_buffer(req, MROUTE_VIF_SYSCTL_LEN * MAXVIFS);
if (error)
return (error);
+ mfct = &V_mfctables[0];
MRW_RLOCK();
/* Copy out user-visible portion of vif entry. */
for (i = 0; i < MAXVIFS; i++) {
- error = SYSCTL_OUT(req, &V_viftable[i], MROUTE_VIF_SYSCTL_LEN);
+ error = SYSCTL_OUT(req, &mfct->viftable[i],
+ MROUTE_VIF_SYSCTL_LEN);
if (error)
break;
}
@@ -2794,11 +2847,16 @@
static void
vnet_mroute_init(const void *unused __unused)
{
+ V_mfctables = mallocarray(V_rt_numfibs, sizeof(*V_mfctables), M_MRTABLE,
+ M_WAITOK | M_ZERO);
+ for (int i = 0; i < V_rt_numfibs; i++) {
+ struct mfctable *mfct;
- V_nexpire = malloc(mfchashsize, M_MRTABLE, M_WAITOK|M_ZERO);
-
- V_viftable = mallocarray(MAXVIFS, sizeof(*V_viftable),
- M_MRTABLE, M_WAITOK|M_ZERO);
+ mfct = &V_mfctables[i];
+ mfct->nexpire = malloc(mfchashsize, M_MRTABLE,
+ M_WAITOK | M_ZERO);
+ mfct->register_vif = VIFI_INVALID;
+ }
callout_init_rw(&V_expire_upcalls_ch, &mrouter_lock, 0);
callout_init_rw(&V_bw_upcalls_ch, &mrouter_lock, 0);
@@ -2808,22 +2866,23 @@
taskqueue_thread_enqueue, &V_task_queue);
taskqueue_start_threads(&V_task_queue, 1, PI_NET, "ip_mroute_tskq task");
}
-
VNET_SYSINIT(vnet_mroute_init, SI_SUB_PROTO_MC, SI_ORDER_ANY, vnet_mroute_init,
- NULL);
+ NULL);
static void
vnet_mroute_uninit(const void *unused __unused)
{
-
/* Taskqueue should be cancelled and drained before freeing */
taskqueue_free(V_task_queue);
- free(V_viftable, M_MRTABLE);
- free(V_nexpire, M_MRTABLE);
- V_nexpire = NULL;
-}
+ for (int i = 0; i < V_rt_numfibs; i++) {
+ struct mfctable *mfct;
+ mfct = &V_mfctables[i];
+ free(mfct->nexpire, M_MRTABLE);
+ }
+ free(V_mfctables, M_MRTABLE);
+}
VNET_SYSUNINIT(vnet_mroute_uninit, SI_SUB_PROTO_MC, SI_ORDER_MIDDLE,
vnet_mroute_uninit, NULL);

File Metadata

Mime Type
text/plain
Expires
Thu, May 14, 2:03 PM (5 h, 48 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28661278
Default Alt Text
D55237.id174555.diff (38 KB)

Event Timeline