ip_mroute: Make the routing socket private
I have some patches which make ip_mroute and ip6_mroute multi-FIB-aware. This enables running per-FIB routing daemons, each of which has a separate routing socket. Several places in the network stack check whether multicast routing is configured by checking whether the multicast routing socket is non-NULL. This doesn't directly translate in my proposed scheme, as each FIB would have its own socket. I'd like to modify the ip(6)_mroute code to store all state, including the socket, in a per-FIB structure. So, take a step towards that and 1) hide the socket, 2) add a boolean flag which indicates whether a multicast router is registered. Reviewed by: pouria, zlei, glebius, adrian MFC after: 2 weeks Sponsored by: Stormshield Sponsored by: Klara, Inc. Differential Revision: https://reviews.freebsd.org/D55236
This commit is contained in:
+1
-1
@@ -3489,7 +3489,7 @@ igmp_intr(struct mbuf *m)
|
||||
|
||||
imo.imo_multicast_ttl = 1;
|
||||
imo.imo_multicast_vif = -1;
|
||||
imo.imo_multicast_loop = (V_ip_mrouter != NULL);
|
||||
imo.imo_multicast_loop = V_ip_mrouting_enabled;
|
||||
|
||||
/*
|
||||
* If the user requested that IGMP traffic be explicitly
|
||||
|
||||
@@ -772,7 +772,8 @@ ip_input(struct mbuf *m)
|
||||
* RFC 3927 2.7: Do not forward multicast packets from
|
||||
* IN_LINKLOCAL.
|
||||
*/
|
||||
if (V_ip_mrouter && !IN_LINKLOCAL(ntohl(ip->ip_src.s_addr))) {
|
||||
if (V_ip_mrouting_enabled &&
|
||||
!IN_LINKLOCAL(ntohl(ip->ip_src.s_addr))) {
|
||||
/*
|
||||
* If we are acting as a multicast router, all
|
||||
* incoming multicast packets are passed to the
|
||||
|
||||
+15
-14
@@ -169,6 +169,9 @@ 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)
|
||||
|
||||
VNET_DEFINE_STATIC(u_long, mfchash);
|
||||
#define V_mfchash VNET(mfchash)
|
||||
#define MFCHASH(a, g) \
|
||||
@@ -305,7 +308,7 @@ VNET_DEFINE_STATIC(struct ifnet *, multicast_register_if);
|
||||
static u_long X_ip_mcast_src(int);
|
||||
static int X_ip_mforward(struct ip *, struct ifnet *, struct mbuf *,
|
||||
struct ip_moptions *);
|
||||
static int X_ip_mrouter_done(void);
|
||||
static void X_ip_mrouter_done(struct socket *);
|
||||
static int X_ip_mrouter_get(struct socket *, struct sockopt *);
|
||||
static int X_ip_mrouter_set(struct socket *, struct sockopt *);
|
||||
static int X_legal_vif_num(int);
|
||||
@@ -435,7 +438,7 @@ X_ip_mrouter_set(struct socket *so, struct sockopt *sopt)
|
||||
error = ip_mrouter_init(so, optval);
|
||||
break;
|
||||
case MRT_DONE:
|
||||
error = ip_mrouter_done();
|
||||
ip_mrouter_done(so);
|
||||
break;
|
||||
case MRT_ADD_VIF:
|
||||
error = sooptcopyin(sopt, &vifc, sizeof vifc, sizeof vifc);
|
||||
@@ -624,8 +627,7 @@ if_detached_event(void *arg __unused, struct ifnet *ifp)
|
||||
struct ifnet *free_ptr, *multi_leave;
|
||||
|
||||
MRW_WLOCK();
|
||||
|
||||
if (V_ip_mrouter == NULL) {
|
||||
if (!V_ip_mrouting_enabled) {
|
||||
MRW_WUNLOCK();
|
||||
return;
|
||||
}
|
||||
@@ -740,6 +742,7 @@ ip_mrouter_init(struct socket *so, int version)
|
||||
curvnet);
|
||||
|
||||
V_ip_mrouter = so;
|
||||
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 */
|
||||
@@ -756,8 +759,8 @@ ip_mrouter_init(struct socket *so, int version)
|
||||
/*
|
||||
* Disable multicast forwarding.
|
||||
*/
|
||||
static int
|
||||
X_ip_mrouter_done(void)
|
||||
static void
|
||||
X_ip_mrouter_done(struct socket *so)
|
||||
{
|
||||
struct ifnet **ifps;
|
||||
int nifp;
|
||||
@@ -766,22 +769,22 @@ X_ip_mrouter_done(void)
|
||||
struct bw_upcall *bu;
|
||||
|
||||
MRW_TEARDOWN_WLOCK();
|
||||
|
||||
if (V_ip_mrouter == NULL) {
|
||||
if (so != V_ip_mrouter) {
|
||||
MRW_TEARDOWN_WUNLOCK();
|
||||
return (EINVAL);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Detach/disable hooks to the reset of the system.
|
||||
*/
|
||||
V_ip_mrouter = NULL;
|
||||
V_ip_mrouting_enabled = false;
|
||||
atomic_subtract_int(&ip_mrouter_cnt, 1);
|
||||
V_mrt_api_config = 0;
|
||||
|
||||
/*
|
||||
* Wait for all epoch sections to complete to ensure
|
||||
* V_ip_mrouter = NULL is visible to others.
|
||||
* Wait for all epoch sections to complete to ensure the new value of
|
||||
* V_ip_mrouting_enabled is visible to others.
|
||||
*/
|
||||
NET_EPOCH_WAIT();
|
||||
|
||||
@@ -856,8 +859,6 @@ X_ip_mrouter_done(void)
|
||||
free(ifps, M_TEMP);
|
||||
|
||||
CTR1(KTR_IPMF, "%s: done", __func__);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2872,7 +2873,7 @@ ip_mroute_modevent(module_t mod, int type, void *unused)
|
||||
MRW_WLOCK();
|
||||
if (ip_mrouter_cnt != 0) {
|
||||
MRW_WUNLOCK();
|
||||
return (EINVAL);
|
||||
return (EBUSY);
|
||||
}
|
||||
ip_mrouter_unloading = 1;
|
||||
MRW_WUNLOCK();
|
||||
|
||||
@@ -356,8 +356,8 @@ struct bw_meter {
|
||||
};
|
||||
|
||||
#ifdef _KERNEL
|
||||
VNET_DECLARE(struct socket *, ip_mrouter); /* multicast routing daemon */
|
||||
#define V_ip_mrouter VNET(ip_mrouter)
|
||||
VNET_DECLARE(bool, ip_mrouting_enabled);
|
||||
#define V_ip_mrouting_enabled VNET(ip_mrouting_enabled)
|
||||
|
||||
struct ifnet;
|
||||
struct ip;
|
||||
@@ -369,7 +369,7 @@ struct sockopt;
|
||||
extern u_long (*ip_mcast_src)(int);
|
||||
extern int (*ip_mforward)(struct ip *, struct ifnet *, struct mbuf *,
|
||||
struct ip_moptions *);
|
||||
extern int (*ip_mrouter_done)(void);
|
||||
extern void (*ip_mrouter_done)(struct socket *);
|
||||
extern int (*ip_mrouter_get)(struct socket *, struct sockopt *);
|
||||
extern int (*ip_mrouter_set)(struct socket *, struct sockopt *);
|
||||
|
||||
|
||||
@@ -610,7 +610,8 @@ ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro, int flags,
|
||||
* above, will be forwarded by the ip_input() routine,
|
||||
* if necessary.
|
||||
*/
|
||||
if (V_ip_mrouter && (flags & IP_FORWARDING) == 0) {
|
||||
if (V_ip_mrouting_enabled &&
|
||||
(flags & IP_FORWARDING) == 0) {
|
||||
/*
|
||||
* If rsvp daemon is not running, do not
|
||||
* set ip_moptions. This ensures that the packet
|
||||
|
||||
@@ -106,16 +106,16 @@ int (*ng_ipfw_input_p)(struct mbuf **, struct ip_fw_args *, bool);
|
||||
*/
|
||||
|
||||
/*
|
||||
* The socket used to communicate with the multicast routing daemon.
|
||||
* A per-VNET flag indicating whether multicast routing is enabled.
|
||||
*/
|
||||
VNET_DEFINE(struct socket *, ip_mrouter);
|
||||
VNET_DEFINE(bool, ip_mrouting_enabled);
|
||||
|
||||
/*
|
||||
* The various mrouter and rsvp functions.
|
||||
*/
|
||||
int (*ip_mrouter_set)(struct socket *, struct sockopt *);
|
||||
int (*ip_mrouter_get)(struct socket *, struct sockopt *);
|
||||
int (*ip_mrouter_done)(void);
|
||||
void (*ip_mrouter_done)(struct socket *);
|
||||
int (*ip_mforward)(struct ip *, struct ifnet *, struct mbuf *,
|
||||
struct ip_moptions *);
|
||||
int (*mrt_ioctl)(u_long, caddr_t, int);
|
||||
@@ -860,8 +860,8 @@ rip_detach(struct socket *so)
|
||||
("rip_detach: not closed"));
|
||||
|
||||
/* Disable mrouter first */
|
||||
if (so == V_ip_mrouter && ip_mrouter_done)
|
||||
ip_mrouter_done();
|
||||
if (ip_mrouter_done != NULL)
|
||||
ip_mrouter_done(so);
|
||||
|
||||
INP_WLOCK(inp);
|
||||
INP_HASH_WLOCK(&V_ripcbinfo);
|
||||
|
||||
@@ -891,7 +891,7 @@ ip6_input(struct mbuf *m)
|
||||
/*
|
||||
* Forward if desirable.
|
||||
*/
|
||||
if (V_ip6_mrouter &&
|
||||
if (V_ip6_mrouting_enabled &&
|
||||
IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
|
||||
/*
|
||||
* If we are acting as a multicast router, all
|
||||
|
||||
+20
-15
@@ -172,6 +172,9 @@ 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]",
|
||||
@@ -335,7 +338,7 @@ static int get_sg_cnt(struct sioc_sg_req6 *);
|
||||
static struct callout expire_upcalls_ch;
|
||||
|
||||
static int X_ip6_mforward(struct ip6_hdr *, struct ifnet *, struct mbuf *);
|
||||
static int X_ip6_mrouter_done(void);
|
||||
static void X_ip6_mrouter_done(struct socket *);
|
||||
static int X_ip6_mrouter_set(struct socket *, struct sockopt *);
|
||||
static int X_ip6_mrouter_get(struct socket *, struct sockopt *);
|
||||
static int X_mrt6_ioctl(u_long, caddr_t);
|
||||
@@ -383,7 +386,7 @@ X_ip6_mrouter_set(struct socket *so, struct sockopt *sopt)
|
||||
error = ip6_mrouter_init(so, optval, sopt->sopt_name);
|
||||
break;
|
||||
case MRT6_DONE:
|
||||
error = X_ip6_mrouter_done();
|
||||
X_ip6_mrouter_done(so);
|
||||
break;
|
||||
case MRT6_ADD_MIF:
|
||||
error = sooptcopyin(sopt, &mifc, sizeof(mifc), sizeof(mifc));
|
||||
@@ -556,6 +559,8 @@ ip6_mrouter_init(struct socket *so, int v, int cmd)
|
||||
return (EADDRINUSE);
|
||||
}
|
||||
|
||||
MFC6_LOCK();
|
||||
V_ip6_mrouting_enabled = true;
|
||||
V_ip6_mrouter = so;
|
||||
V_ip6_mrouter_ver = cmd;
|
||||
|
||||
@@ -568,6 +573,7 @@ ip6_mrouter_init(struct socket *so, int v, int cmd)
|
||||
callout_reset(&expire_upcalls_ch, EXPIRE_TIMEOUT,
|
||||
expire_upcalls, NULL);
|
||||
|
||||
MFC6_UNLOCK();
|
||||
MROUTER6_UNLOCK();
|
||||
|
||||
MRT6_DLOG(DEBUG_ANY, "finished");
|
||||
@@ -578,8 +584,8 @@ ip6_mrouter_init(struct socket *so, int v, int cmd)
|
||||
/*
|
||||
* Disable IPv6 multicast forwarding.
|
||||
*/
|
||||
static int
|
||||
X_ip6_mrouter_done(void)
|
||||
static void
|
||||
X_ip6_mrouter_done(struct socket *so)
|
||||
{
|
||||
mifi_t mifi;
|
||||
u_long i;
|
||||
@@ -588,9 +594,9 @@ X_ip6_mrouter_done(void)
|
||||
|
||||
MROUTER6_LOCK();
|
||||
|
||||
if (V_ip6_mrouter == NULL) {
|
||||
if (V_ip6_mrouter != so) {
|
||||
MROUTER6_UNLOCK();
|
||||
return (EINVAL);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -603,6 +609,7 @@ X_ip6_mrouter_done(void)
|
||||
if_allmulti(mif6table[mifi].m6_ifp, 0);
|
||||
}
|
||||
}
|
||||
MFC6_LOCK();
|
||||
bzero((caddr_t)mif6table, sizeof(mif6table));
|
||||
nummifs = 0;
|
||||
|
||||
@@ -611,7 +618,6 @@ X_ip6_mrouter_done(void)
|
||||
/*
|
||||
* Free all multicast forwarding cache entries.
|
||||
*/
|
||||
MFC6_LOCK();
|
||||
for (i = 0; i < MF6CTBLSIZ; i++) {
|
||||
rt = mf6ctable[i];
|
||||
while (rt) {
|
||||
@@ -630,6 +636,10 @@ X_ip6_mrouter_done(void)
|
||||
}
|
||||
}
|
||||
bzero((caddr_t)mf6ctable, sizeof(mf6ctable));
|
||||
|
||||
V_ip6_mrouter = NULL;
|
||||
V_ip6_mrouting_enabled = false;
|
||||
V_ip6_mrouter_ver = 0;
|
||||
MFC6_UNLOCK();
|
||||
|
||||
callout_drain(&expire_upcalls_ch);
|
||||
@@ -644,13 +654,8 @@ X_ip6_mrouter_done(void)
|
||||
multicast_register_if6 = NULL;
|
||||
}
|
||||
|
||||
V_ip6_mrouter = NULL;
|
||||
V_ip6_mrouter_ver = 0;
|
||||
|
||||
MROUTER6_UNLOCK();
|
||||
MRT6_DLOG(DEBUG_ANY, "finished");
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static struct sockaddr_in6 sin6 = { sizeof(sin6), AF_INET6 };
|
||||
@@ -1903,14 +1908,14 @@ ip6_mroute_modevent(module_t mod, int type, void *unused)
|
||||
break;
|
||||
|
||||
case MOD_UNLOAD:
|
||||
if (V_ip6_mrouter != NULL)
|
||||
return EINVAL;
|
||||
if (V_ip6_mrouting_enabled)
|
||||
return (EBUSY);
|
||||
|
||||
if (pim6_encap_cookie) {
|
||||
ip6_encap_detach(pim6_encap_cookie);
|
||||
pim6_encap_cookie = NULL;
|
||||
}
|
||||
X_ip6_mrouter_done();
|
||||
|
||||
ip6_mforward = NULL;
|
||||
ip6_mrouter_done = NULL;
|
||||
ip6_mrouter_get = NULL;
|
||||
|
||||
@@ -273,8 +273,8 @@ struct rtdetq { /* XXX: rtdetq is also defined in ip_mroute.h */
|
||||
#endif /* _KERNEL || KERNEL */
|
||||
|
||||
#ifdef _KERNEL
|
||||
VNET_DECLARE(struct socket *, ip6_mrouter); /* multicast routing daemon */
|
||||
#define V_ip6_mrouter VNET(ip6_mrouter)
|
||||
VNET_DECLARE(bool, ip6_mrouting_enabled);
|
||||
#define V_ip6_mrouting_enabled VNET(ip6_mrouting_enabled)
|
||||
|
||||
struct ifnet;
|
||||
struct ip6_hdr;
|
||||
@@ -286,7 +286,7 @@ extern int (*ip6_mforward)(struct ip6_hdr *, struct ifnet *,
|
||||
struct mbuf *);
|
||||
extern int (*ip6_mrouter_set)(struct socket *so, struct sockopt *sopt);
|
||||
extern int (*ip6_mrouter_get)(struct socket *so, struct sockopt *sopt);
|
||||
extern int (*ip6_mrouter_done)(void);
|
||||
extern void (*ip6_mrouter_done)(struct socket *so);
|
||||
|
||||
extern int (*mrt6_ioctl)(u_long, caddr_t);
|
||||
#endif /* _KERNEL */
|
||||
|
||||
@@ -890,7 +890,8 @@ ip6_output(struct mbuf *m0, struct ip6_pktopts *opt,
|
||||
* above, will be forwarded by the ip6_input() routine,
|
||||
* if necessary.
|
||||
*/
|
||||
if (V_ip6_mrouter && (flags & IPV6_FORWARDING) == 0) {
|
||||
if (V_ip6_mrouting_enabled &&
|
||||
(flags & IPV6_FORWARDING) == 0) {
|
||||
/*
|
||||
* XXX: ip6_mforward expects that rcvif is NULL
|
||||
* when it is called from the originating path.
|
||||
|
||||
+1
-1
@@ -3063,7 +3063,7 @@ mld_dispatch_packet(struct mbuf *m)
|
||||
}
|
||||
|
||||
im6o.im6o_multicast_hlim = 1;
|
||||
im6o.im6o_multicast_loop = (V_ip6_mrouter != NULL);
|
||||
im6o.im6o_multicast_loop = V_ip6_mrouting_enabled;
|
||||
im6o.im6o_multicast_ifp = ifp;
|
||||
|
||||
if (m->m_flags & M_MLDV1) {
|
||||
|
||||
@@ -137,14 +137,14 @@ VNET_PCPUSTAT_SYSUNINIT(rip6stat);
|
||||
/*
|
||||
* The socket used to communicate with the multicast routing daemon.
|
||||
*/
|
||||
VNET_DEFINE(struct socket *, ip6_mrouter);
|
||||
VNET_DEFINE(bool, ip6_mrouting_enabled);
|
||||
|
||||
/*
|
||||
* The various mrouter functions.
|
||||
*/
|
||||
int (*ip6_mrouter_set)(struct socket *, struct sockopt *);
|
||||
int (*ip6_mrouter_get)(struct socket *, struct sockopt *);
|
||||
int (*ip6_mrouter_done)(void);
|
||||
void (*ip6_mrouter_done)(struct socket *);
|
||||
int (*ip6_mforward)(struct ip6_hdr *, struct ifnet *, struct mbuf *);
|
||||
int (*mrt6_ioctl)(u_long, caddr_t);
|
||||
|
||||
@@ -694,8 +694,8 @@ rip6_detach(struct socket *so)
|
||||
inp = sotoinpcb(so);
|
||||
KASSERT(inp != NULL, ("rip6_detach: inp == NULL"));
|
||||
|
||||
if (so == V_ip6_mrouter && ip6_mrouter_done)
|
||||
ip6_mrouter_done();
|
||||
if (ip6_mrouter_done != NULL)
|
||||
ip6_mrouter_done(so);
|
||||
/* xxx: RSVP */
|
||||
INP_WLOCK(inp);
|
||||
free(inp->in6p_icmp6filt, M_PCB);
|
||||
|
||||
Reference in New Issue
Block a user