Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 09 Feb 2007 03:37:00 +0000
From:      Bruce M Simpson <bms@incunabulum.net>
To:        freebsd-net@freebsd.org
Subject:   [PATCH] make netinet MROUTING dynamically loadable with PIM
Message-ID:  <45CBEC5C.4060900@incunabulum.net>

next in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format.
--------------070503090209060701040608
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit

I plan to commit this soon as part of the mrouting cleanup.

--------------070503090209060701040608
Content-Type: text/x-patch;
 name="ipv4-pim-module.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="ipv4-pim-module.diff"

Bring the IPv4 multicast forwarding code more into line with the IPv6
version, by unconditionally building with PIM support enabled, and
allowing it to be built as a loadable module.

Use encap_attach_func() to hookup the IPPROTO_PIM input path.
Keep the reserved identifier _PIM_VT around as some folks use this.

TODO: Make the IPv6 multicast forwarding code dynamically loadable.

Index: sys/conf/NOTES
===================================================================
RCS file: /home/ncvs/src/sys/conf/NOTES,v
retrieving revision 1.1409
diff -u -p -r1.1409 NOTES
--- sys/conf/NOTES	7 Feb 2007 18:55:29 -0000	1.1409
+++ sys/conf/NOTES	9 Feb 2007 01:59:43 -0000
@@ -807,10 +807,7 @@ device		stf			#6to4 IPv6 over IPv4 encap
 # Internet family options:
 #
 # MROUTING enables the kernel multicast packet forwarder, which works
-# with mrouted(8).
-#
-# PIM enables Protocol Independent Multicast in the kernel.
-# Requires MROUTING enabled.
+# with mrouted and XORP.
 #
 # IPFIREWALL enables support for IP firewall construction, in
 # conjunction with the `ipfw' program.  IPFIREWALL_VERBOSE sends
@@ -854,7 +851,6 @@ device		stf			#6to4 IPv6 over IPv4 encap
 # using the trpt(8) utility.
 #
 options 	MROUTING		# Multicast routing
-options 	PIM			# Protocol Independent Multicast
 options 	IPFIREWALL		#firewall
 options 	IPFIREWALL_VERBOSE	#enable logging to syslogd(8)
 options 	IPFIREWALL_VERBOSE_LIMIT=100	#limit verbosity
Index: sys/conf/options
===================================================================
RCS file: /home/ncvs/src/sys/conf/options,v
retrieving revision 1.575
diff -u -p -r1.575 options
--- sys/conf/options	7 Feb 2007 18:55:29 -0000	1.575
+++ sys/conf/options	9 Feb 2007 01:59:43 -0000
@@ -352,7 +352,6 @@ ETHER_8023		opt_ef.h
 ETHER_8022		opt_ef.h
 ETHER_SNAP		opt_ef.h
 MROUTING		opt_mrouting.h
-PIM			opt_mrouting.h
 INET			opt_inet.h
 INET6			opt_inet6.h
 IPSEC			opt_ipsec.h
Index: sys/netinet/in_proto.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet/in_proto.c,v
retrieving revision 1.82
diff -u -p -r1.82 in_proto.c
--- sys/netinet/in_proto.c	3 Nov 2006 15:23:14 -0000	1.82
+++ sys/netinet/in_proto.c	9 Feb 2007 01:59:43 -0000
@@ -56,9 +56,6 @@
 #include <netinet/ip_var.h>
 #include <netinet/ip_icmp.h>
 #include <netinet/igmp_var.h>
-#ifdef PIM
-#include <netinet/pim_var.h>
-#endif
 #include <netinet/tcp.h>
 #include <netinet/tcp_timer.h>
 #include <netinet/tcp_var.h>
@@ -345,17 +342,6 @@ struct protosw inetsw[] = {
 	.pr_usrreqs =		&rip_usrreqs
 },
 #endif
-#ifdef PIM
-{
-	.pr_type =		SOCK_RAW,
-	.pr_domain =		&inetdomain,
-	.pr_protocol =		IPPROTO_PIM,
-	.pr_flags =		PR_ATOMIC|PR_ADDR|PR_LASTHDR,
-	.pr_input =		pim_input,
-	.pr_ctloutput =		rip_ctloutput,
-	.pr_usrreqs =		&rip_usrreqs
-},
-#endif	/* PIM */
 #ifdef DEV_PFSYNC
 {
 	.pr_type =		SOCK_RAW,
@@ -438,9 +424,6 @@ SYSCTL_NODE(_net_inet, IPPROTO_AH,	ipsec
 #endif /* IPSEC */
 #endif /* !FAST_IPSEC */
 SYSCTL_NODE(_net_inet, IPPROTO_RAW,	raw,	CTLFLAG_RW, 0,	"RAW");
-#ifdef PIM
-SYSCTL_NODE(_net_inet, IPPROTO_PIM,	pim,	CTLFLAG_RW, 0,	"PIM");
-#endif
 #ifdef DEV_PFSYNC
 SYSCTL_NODE(_net_inet, IPPROTO_PFSYNC,	pfsync,	CTLFLAG_RW, 0,	"PFSYNC");
 #endif
Index: sys/netinet/ip_mroute.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet/ip_mroute.c,v
retrieving revision 1.126
diff -u -p -r1.126 ip_mroute.c
--- sys/netinet/ip_mroute.c	8 Feb 2007 23:05:08 -0000	1.126
+++ sys/netinet/ip_mroute.c	9 Feb 2007 01:59:45 -0000
@@ -58,9 +58,7 @@
 #include "opt_mac.h"
 #include "opt_mrouting.h"
 
-#ifdef PIM
 #define _PIM_VT 1
-#endif
 
 #include <sys/param.h>
 #include <sys/kernel.h>
@@ -91,10 +89,8 @@
 #include <netinet/ip_mroute.h>
 #include <netinet/ip_var.h>
 #include <netinet/ip_options.h>
-#ifdef PIM
 #include <netinet/pim.h>
 #include <netinet/pim_var.h>
-#endif
 #include <netinet/udp.h>
 #include <machine/in_cksum.h>
 
@@ -197,12 +193,27 @@ static u_int	bw_upcalls_n; /* # of pendi
 static struct callout bw_upcalls_ch;
 #define BW_UPCALLS_PERIOD (hz)		/* periodical flush of bw upcalls */
 
-#ifdef PIM
 static struct pimstat pimstat;
+
+SYSCTL_NODE(_net_inet, IPPROTO_PIM, pim, CTLFLAG_RW, 0, "PIM");
 SYSCTL_STRUCT(_net_inet_pim, PIMCTL_STATS, stats, CTLFLAG_RD,
     &pimstat, pimstat,
     "PIM Statistics (struct pimstat, netinet/pim_var.h)");
 
+extern  struct domain inetdomain;
+struct protosw in_pim_protosw = {
+	.pr_type =		SOCK_RAW,
+	.pr_domain =		&inetdomain,
+	.pr_protocol =		IPPROTO_PIM,
+	.pr_flags =		PR_ATOMIC|PR_ADDR|PR_LASTHDR,
+	.pr_input =		pim_input,
+	.pr_output =		(pr_output_t*)rip_output,
+	.pr_ctloutput =		rip_ctloutput,
+	.pr_usrreqs =		&rip_usrreqs
+};
+static const struct encaptab *pim_encap_cookie;
+static int pim_encapcheck(const struct mbuf *, int, int, void *);
+
 /*
  * Note: the PIM Register encapsulation adds the following in front of a
  * data packet:
@@ -247,7 +258,6 @@ static struct pim_encap_pimhdr pim_encap
 
 static struct ifnet multicast_register_if;
 static vifi_t reg_vif_num = VIFI_INVALID;
-#endif /* PIM */
 
 /*
  * Private variables.
@@ -296,7 +306,6 @@ static void bw_meter_process(void);
 static void expire_bw_upcalls_send(void *);
 static void expire_bw_meter_process(void *);
 
-#ifdef PIM
 static int pim_register_send(struct ip *, struct vif *,
 		struct mbuf *, struct mfc *);
 static int pim_register_send_rp(struct ip *, struct vif *,
@@ -304,7 +313,6 @@ static int pim_register_send_rp(struct i
 static int pim_register_send_upcall(struct ip *, struct vif *,
 		struct mbuf *, struct mfc *);
 static struct mbuf *pim_register_prepare(struct ip *, struct mbuf *);
-#endif
 
 /*
  * whether or not special PIM assert processing is enabled.
@@ -603,7 +611,7 @@ ip_mrouter_reset(void)
     callout_init(&bw_meter_ch, NET_CALLOUT_MPSAFE);
 }
 
-static struct mtx mrouter_mtx;		/* used to synch init/done work */
+static struct mtx mrouter_mtx;
 
 static void
 if_detached_event(void *arg __unused, struct ifnet *ifp)
@@ -788,9 +796,7 @@ X_ip_mrouter_done(void)
     bzero(bw_meter_timers, sizeof(bw_meter_timers));
     MFC_UNLOCK();
 
-#ifdef PIM
     reg_vif_num = VIFI_INVALID;
-#endif
 
     mtx_unlock(&mrouter_mtx);
 
@@ -883,7 +889,6 @@ add_vif(struct vifctl *vifcp)
     }
 
     /* Find the interface with an address in AF_INET family */
-#ifdef PIM
     if (vifcp->vifc_flags & VIFF_REGISTER) {
 	/*
 	 * XXX: Because VIFF_REGISTER does not really need a valid
@@ -891,9 +896,7 @@ add_vif(struct vifctl *vifcp)
 	 * check its address.
 	 */
 	ifp = NULL;
-    } else
-#endif
-    {
+    } else {
 	sin.sin_addr = vifcp->vifc_lcl_addr;
 	ifa = ifa_ifwithaddr((struct sockaddr *)&sin);
 	if (ifa == NULL) {
@@ -907,7 +910,6 @@ add_vif(struct vifctl *vifcp)
 	log(LOG_ERR, "tunnels are no longer supported\n");
 	VIF_UNLOCK();
 	return EOPNOTSUPP;
-#ifdef PIM
     } else if (vifcp->vifc_flags & VIFF_REGISTER) {
 	ifp = &multicast_register_if;
 	if (mrtdebug)
@@ -918,7 +920,6 @@ add_vif(struct vifctl *vifcp)
 	    multicast_register_if.if_flags = IFF_LOOPBACK;
 	    reg_vif_num = vifcp->vifc_vifi;
 	}
-#endif
     } else {		/* Make sure the interface supports multicast */
 	if ((ifp->if_flags & IFF_MULTICAST) == 0) {
 	    VIF_UNLOCK();
@@ -984,10 +985,8 @@ del_vif_locked(vifi_t vifi)
     if (!(vifp->v_flags & (VIFF_TUNNEL | VIFF_REGISTER)))
 	if_allmulti(vifp->v_ifp, 0);
 
-#ifdef PIM
     if (vifp->v_flags & VIFF_REGISTER)
 	reg_vif_num = VIFI_INVALID;
-#endif
 
     bzero((caddr_t)vifp, sizeof (*vifp));
 
@@ -1571,12 +1570,10 @@ ip_mdq(struct mbuf *m, struct ifnet *ifp
      * (since vifi_t is u_short, -1 becomes MAXUSHORT, which > numvifs.)
      */
     if (xmt_vif < numvifs) {
-#ifdef PIM
 	if (viftable[xmt_vif].v_flags & VIFF_REGISTER)
-	    pim_register_send(ip, viftable + xmt_vif, m, rt);
+		pim_register_send(ip, viftable + xmt_vif, m, rt);
 	else
-#endif
-	phyint_send(ip, viftable + xmt_vif, m);
+		phyint_send(ip, viftable + xmt_vif, m);
 	return 1;
     }
 
@@ -1603,10 +1600,8 @@ ip_mdq(struct mbuf *m, struct ifnet *ifp
 	    struct timeval now;
 	    u_long delta;
 
-#ifdef PIM
 	    if (ifp == &multicast_register_if)
 		pimstat.pims_rcv_registers_wrongiif++;
-#endif
 
 	    /* Get vifi for the incoming packet */
 	    for (vifi=0; vifi < numvifs && viftable[vifi].v_ifp != ifp; vifi++)
@@ -1674,12 +1669,10 @@ ip_mdq(struct mbuf *m, struct ifnet *ifp
 	if ((rt->mfc_ttls[vifi] > 0) && (ip->ip_ttl > rt->mfc_ttls[vifi])) {
 	    viftable[vifi].v_pkt_out++;
 	    viftable[vifi].v_bytes_out += plen;
-#ifdef PIM
 	    if (viftable[vifi].v_flags & VIFF_REGISTER)
 		pim_register_send(ip, viftable + vifi, m, rt);
 	    else
-#endif
-	    phyint_send(ip, viftable + vifi, m);
+		phyint_send(ip, viftable + vifi, m);
 	}
 
     /*
@@ -2516,7 +2509,6 @@ expire_bw_meter_process(void *unused)
  * End of bandwidth monitoring code
  */
 
-#ifdef PIM
 /*
  * Send the packet up to the user daemon, or eventually do kernel encapsulation
  *
@@ -2739,6 +2731,21 @@ pim_register_send_rp(struct ip *ip, stru
  * (used by PIM-SM): the PIM header is stripped off, and the inner packet
  * is passed to if_simloop().
  */
+static int
+pim_encapcheck(const struct mbuf *m, int off, int proto, void *arg)
+{
+    struct ip *ip = mtod(m, struct ip *);
+    int hlen = ip->ip_hl << 2;
+
+#ifdef DIAGNOSTIC
+    KASSERT(proto == IPPROTO_PIM, ("not for IPPROTO_PIM"));
+#endif
+    if (!IN_MULTICAST(ntohl(((struct ip *)((char *)ip+hlen))->ip_dst.s_addr)))
+	return 0;
+
+    return 64;
+}
+
 void
 pim_input(struct mbuf *m, int off)
 {
@@ -2971,7 +2978,6 @@ pim_input_to_daemon:
 
     return;
 }
-#endif /* PIM */
 
 static int
 ip_mroute_modevent(module_t mod, int type, void *unused)
@@ -2982,6 +2988,15 @@ ip_mroute_modevent(module_t mod, int typ
 	MFC_LOCK_INIT();
 	VIF_LOCK_INIT();
 	ip_mrouter_reset();
+	pim_encap_cookie = encap_attach_func(AF_INET, IPPROTO_PIM,
+	    pim_encapcheck, &in_pim_protosw, NULL);
+	if (pim_encap_cookie == NULL) {
+		printf("ip_mroute: unable to attach pim encap\n");
+		VIF_LOCK_DESTROY();
+		MFC_LOCK_DESTROY();
+		mtx_destroy(&mrouter_mtx);
+		return (EINVAL);
+	}
 	ip_mcast_src = X_ip_mcast_src;
 	ip_mforward = X_ip_mforward;
 	ip_mrouter_done = X_ip_mrouter_done;
@@ -3006,6 +3021,11 @@ ip_mroute_modevent(module_t mod, int typ
 	if (ip_mrouter)
 	    return EINVAL;
 
+	if (pim_encap_cookie) {
+	    encap_detach(pim_encap_cookie);
+	    pim_encap_cookie = NULL;
+	}
+
 	X_ip_mrouter_done();
 	ip_mcast_src = NULL;
 	ip_mforward = NULL;

--------------070503090209060701040608--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?45CBEC5C.4060900>