diff options
Diffstat (limited to 'freebsd/sys/netinet/ip_mroute.c')
-rw-r--r-- | freebsd/sys/netinet/ip_mroute.c | 136 |
1 files changed, 71 insertions, 65 deletions
diff --git a/freebsd/sys/netinet/ip_mroute.c b/freebsd/sys/netinet/ip_mroute.c index f4aeed24..f8b14735 100644 --- a/freebsd/sys/netinet/ip_mroute.c +++ b/freebsd/sys/netinet/ip_mroute.c @@ -79,6 +79,7 @@ __FBSDID("$FreeBSD$"); #include <rtems/bsd/sys/param.h> #include <sys/kernel.h> #include <sys/stddef.h> +#include <sys/eventhandler.h> #include <rtems/bsd/sys/lock.h> #include <sys/ktr.h> #include <sys/malloc.h> @@ -95,8 +96,10 @@ __FBSDID("$FreeBSD$"); #include <sys/syslog.h> #include <sys/systm.h> #include <sys/time.h> +#include <sys/counter.h> #include <net/if.h> +#include <net/if_var.h> #include <net/netisr.h> #include <net/route.h> #include <net/vnet.h> @@ -121,7 +124,6 @@ __FBSDID("$FreeBSD$"); #endif #define VIFI_INVALID ((vifi_t) -1) -#define M_HASCL(m) ((m)->m_flags & M_EXT) static VNET_DEFINE(uint32_t, last_tv_sec); /* last time we processed this */ #define V_last_tv_sec VNET(last_tv_sec) @@ -147,11 +149,11 @@ static struct mtx mrouter_mtx; static int ip_mrouter_cnt; /* # of vnets with active mrouters */ static int ip_mrouter_unloading; /* Allow no more V_ip_mrouter sockets */ -static VNET_DEFINE(struct mrtstat, mrtstat); -#define V_mrtstat VNET(mrtstat) -SYSCTL_VNET_STRUCT(_net_inet_ip, OID_AUTO, mrtstat, CTLFLAG_RW, - &VNET_NAME(mrtstat), mrtstat, - "IPv4 Multicast Forwarding Statistics (struct mrtstat, " +static VNET_PCPUSTAT_DEFINE(struct mrtstat, mrtstat); +VNET_PCPUSTAT_SYSINIT(mrtstat); +VNET_PCPUSTAT_SYSUNINIT(mrtstat); +SYSCTL_VNET_PCPUSTAT(_net_inet_ip, OID_AUTO, mrtstat, struct mrtstat, + mrtstat, "IPv4 Multicast Forwarding Statistics (struct mrtstat, " "netinet/ip_mroute.h)"); static VNET_DEFINE(u_long, mfchash); @@ -179,7 +181,7 @@ static VNET_DEFINE(vifi_t, numvifs); #define V_numvifs VNET(numvifs) static VNET_DEFINE(struct vif, viftable[MAXVIFS]); #define V_viftable VNET(viftable) -SYSCTL_VNET_OPAQUE(_net_inet_ip, OID_AUTO, viftable, CTLFLAG_RD, +SYSCTL_OPAQUE(_net_inet_ip, OID_AUTO, viftable, CTLFLAG_VNET | CTLFLAG_RD, &VNET_NAME(viftable), sizeof(V_viftable), "S,vif[MAXVIFS]", "IPv4 Multicast Interfaces (struct vif[MAXVIFS], netinet/ip_mroute.h)"); @@ -227,13 +229,13 @@ static VNET_DEFINE(struct callout, bw_upcalls_ch); #define BW_UPCALLS_PERIOD (hz) /* periodical flush of bw upcalls */ -static VNET_DEFINE(struct pimstat, pimstat); -#define V_pimstat VNET(pimstat) +static VNET_PCPUSTAT_DEFINE(struct pimstat, pimstat); +VNET_PCPUSTAT_SYSINIT(pimstat); +VNET_PCPUSTAT_SYSUNINIT(pimstat); SYSCTL_NODE(_net_inet, IPPROTO_PIM, pim, CTLFLAG_RW, 0, "PIM"); -SYSCTL_VNET_STRUCT(_net_inet_pim, PIMCTL_STATS, stats, CTLFLAG_RD, - &VNET_NAME(pimstat), pimstat, - "PIM Statistics (struct pimstat, netinet/pim_var.h)"); +SYSCTL_VNET_PCPUSTAT(_net_inet_pim, PIMCTL_STATS, stats, struct pimstat, + pimstat, "PIM Statistics (struct pimstat, netinet/pim_var.h)"); static u_long pim_squelch_wholepkt = 0; SYSCTL_ULONG(_net_inet_pim, OID_AUTO, squelch_wholepkt, CTLFLAG_RW, @@ -247,7 +249,7 @@ static const struct protosw in_pim_protosw = { .pr_protocol = IPPROTO_PIM, .pr_flags = PR_ATOMIC|PR_ADDR|PR_LASTHDR, .pr_input = pim_input, - .pr_output = (pr_output_t*)rip_output, + .pr_output = rip_output, .pr_ctloutput = rip_ctloutput, .pr_usrreqs = &rip_usrreqs }; @@ -538,7 +540,7 @@ X_mrt_ioctl(u_long cmd, caddr_t data, int fibnum __unused) int error = 0; /* - * Currently the only function calling this ioctl routine is rtioctl(). + * Currently the only function calling this ioctl routine is rtioctl_fib(). * Typically, only root can create the raw socket in order to execute * this ioctl method, however the request might be coming from a prison */ @@ -635,8 +637,8 @@ if_detached_event(void *arg __unused, struct ifnet *ifp) continue; for (i = 0; i < mfchashsize; i++) { struct mfc *rt, *nrt; - for (rt = LIST_FIRST(&V_mfchashtbl[i]); rt; rt = nrt) { - nrt = LIST_NEXT(rt, mfc_hash); + + LIST_FOREACH_SAFE(rt, &V_mfchashtbl[i], mfc_hash, nrt) { if (rt->mfc_parent == vifi) { expire_mfc(rt); } @@ -754,8 +756,8 @@ X_ip_mrouter_done(void) */ for (i = 0; i < mfchashsize; i++) { struct mfc *rt, *nrt; - for (rt = LIST_FIRST(&V_mfchashtbl[i]); rt; rt = nrt) { - nrt = LIST_NEXT(rt, mfc_hash); + + LIST_FOREACH_SAFE(rt, &V_mfchashtbl[i], mfc_hash, nrt) { expire_mfc(rt); } } @@ -1303,8 +1305,8 @@ X_ip_mforward(struct ip *ip, struct ifnet *ifp, struct mbuf *m, return ENOBUFS; } - mb0 = m_copypacket(m, M_DONTWAIT); - if (mb0 && (M_HASCL(mb0) || mb0->m_len < hlen)) + mb0 = m_copypacket(m, M_NOWAIT); + if (mb0 && (!M_WRITABLE(mb0) || mb0->m_len < hlen)) mb0 = m_pullup(mb0, hlen); if (mb0 == NULL) { free(rte, M_MRTABLE); @@ -1446,9 +1448,7 @@ expire_upcalls(void *arg) if (V_nexpire[i] == 0) continue; - for (rt = LIST_FIRST(&V_mfchashtbl[i]); rt; rt = nrt) { - nrt = LIST_NEXT(rt, mfc_hash); - + LIST_FOREACH_SAFE(rt, &V_mfchashtbl[i], mfc_hash, nrt) { if (TAILQ_EMPTY(&rt->mfc_stall)) continue; @@ -1490,7 +1490,7 @@ ip_mdq(struct mbuf *m, struct ifnet *ifp, struct mfc *rt, vifi_t xmt_vif) { struct ip *ip = mtod(m, struct ip *); vifi_t vifi; - int plen = ip->ip_len; + int plen = ntohs(ip->ip_len); VIF_LOCK_ASSERT(); @@ -1546,7 +1546,7 @@ ip_mdq(struct mbuf *m, struct ifnet *ifp, struct mfc *rt, vifi_t xmt_vif) int hlen = ip->ip_hl << 2; struct mbuf *mm = m_copy(m, 0, hlen); - if (mm && (M_HASCL(mm) || mm->m_len < hlen)) + if (mm && (!M_WRITABLE(mm) || mm->m_len < hlen)) mm = m_pullup(mm, hlen); if (mm == NULL) return ENOBUFS; @@ -1666,8 +1666,8 @@ phyint_send(struct ip *ip, struct vif *vifp, struct mbuf *m) * the IP header is actually copied, not just referenced, * so that ip_output() only scribbles on the copy. */ - mb_copy = m_copypacket(m, M_DONTWAIT); - if (mb_copy && (M_HASCL(mb_copy) || mb_copy->m_len < hlen)) + mb_copy = m_copypacket(m, M_NOWAIT); + if (mb_copy && (!M_WRITABLE(mb_copy) || mb_copy->m_len < hlen)) mb_copy = m_pullup(mb_copy, hlen); if (mb_copy == NULL) return; @@ -1720,12 +1720,16 @@ X_ip_rsvp_force_done(struct socket *so __unused) } -static void -X_rsvp_input(struct mbuf *m, int off __unused) +static int +X_rsvp_input(struct mbuf **mp, int *offp, int proto) { + struct mbuf *m; + m = *mp; + *mp = NULL; if (!V_rsvp_on) m_freem(m); + return (IPPROTO_DONE); } /* @@ -2080,13 +2084,12 @@ bw_upcalls_send(void) * Allocate a new mbuf, initialize it with the header and * the payload for the pending calls. */ - MGETHDR(m, M_DONTWAIT, MT_DATA); + m = m_gethdr(M_NOWAIT, MT_DATA); if (m == NULL) { log(LOG_WARNING, "bw_upcalls_send: cannot allocate mbuf\n"); return; } - m->m_len = m->m_pkthdr.len = 0; m_copyback(m, 0, sizeof(struct igmpmsg), (caddr_t)&igmpmsg); m_copyback(m, sizeof(struct igmpmsg), len, (caddr_t)&V_bw_upcalls[0]); @@ -2381,7 +2384,7 @@ pim_register_prepare(struct ip *ip, struct mbuf *m) * Copy the old packet & pullup its IP header into the * new mbuf so we can modify it. */ - mb_copy = m_copypacket(m, M_DONTWAIT); + mb_copy = m_copypacket(m, M_NOWAIT); if (mb_copy == NULL) return NULL; mb_copy = m_pullup(mb_copy, ip->ip_hl << 2); @@ -2395,15 +2398,14 @@ pim_register_prepare(struct ip *ip, struct mbuf *m) /* Compute the MTU after the PIM Register encapsulation */ mtu = 0xffff - sizeof(pim_encap_iphdr) - sizeof(pim_encap_pimhdr); - if (ip->ip_len <= mtu) { + if (ntohs(ip->ip_len) <= mtu) { /* Turn the IP header into a valid one */ - ip->ip_len = htons(ip->ip_len); - ip->ip_off = htons(ip->ip_off); ip->ip_sum = 0; ip->ip_sum = in_cksum(mb_copy, ip->ip_hl << 2); } else { /* Fragment the packet */ - if (ip_fragment(ip, &mb_copy, mtu, 0, CSUM_DELAY_IP) != 0) { + mb_copy->m_pkthdr.csum_flags |= CSUM_IP; + if (ip_fragment(ip, &mb_copy, mtu, 0) != 0) { m_freem(mb_copy); return NULL; } @@ -2428,7 +2430,7 @@ pim_register_send_upcall(struct ip *ip, struct vif *vifp, /* * Add a new mbuf with an upcall header */ - MGETHDR(mb_first, M_DONTWAIT, MT_DATA); + mb_first = m_gethdr(M_NOWAIT, MT_DATA); if (mb_first == NULL) { m_freem(mb_copy); return ENOBUFS; @@ -2486,7 +2488,7 @@ pim_register_send_rp(struct ip *ip, struct vif *vifp, struct mbuf *mb_copy, /* * Add a new mbuf with the encapsulating header */ - MGETHDR(mb_first, M_DONTWAIT, MT_DATA); + mb_first = m_gethdr(M_NOWAIT, MT_DATA); if (mb_first == NULL) { m_freem(mb_copy); return ENOBUFS; @@ -2502,8 +2504,8 @@ pim_register_send_rp(struct ip *ip, struct vif *vifp, struct mbuf *mb_copy, */ ip_outer = mtod(mb_first, struct ip *); *ip_outer = pim_encap_iphdr; - ip_outer->ip_id = ip_newid(); - ip_outer->ip_len = len + sizeof(pim_encap_iphdr) + sizeof(pim_encap_pimhdr); + 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_dst = rt->mfc_rp; /* @@ -2511,8 +2513,9 @@ pim_register_send_rp(struct ip *ip, struct vif *vifp, struct mbuf *mb_copy, * IP_DF bit. */ ip_outer->ip_tos = ip->ip_tos; - if (ntohs(ip->ip_off) & IP_DF) - ip_outer->ip_off |= IP_DF; + if (ip->ip_off & htons(IP_DF)) + ip_outer->ip_off |= htons(IP_DF); + ip_fillid(ip_outer); pimhdr = (struct pim_encap_pimhdr *)((caddr_t)ip_outer + sizeof(pim_encap_iphdr)); *pimhdr = pim_encap_pimhdr; @@ -2559,15 +2562,18 @@ pim_encapcheck(const struct mbuf *m, int off, int proto, void *arg) * (used by PIM-SM): the PIM header is stripped off, and the inner packet * is passed to if_simloop(). */ -void -pim_input(struct mbuf *m, int off) +int +pim_input(struct mbuf **mp, int *offp, int proto) { + struct mbuf *m = *mp; struct ip *ip = mtod(m, struct ip *); struct pim *pim; + int iphlen = *offp; int minlen; - int datalen = ip->ip_len; + int datalen = ntohs(ip->ip_len) - iphlen; int ip_tos; - int iphlen = off; + + *mp = NULL; /* Keep statistics */ PIMSTAT_INC(pims_rcv_total_msgs); @@ -2581,7 +2587,7 @@ pim_input(struct mbuf *m, int off) CTR3(KTR_IPMF, "%s: short packet (%d) from %s", __func__, datalen, inet_ntoa(ip->ip_src)); m_freem(m); - return; + return (IPPROTO_DONE); } /* @@ -2597,10 +2603,9 @@ pim_input(struct mbuf *m, int off) * Get the IP and PIM headers in contiguous memory, and * possibly the PIM REGISTER header. */ - if ((m->m_flags & M_EXT || m->m_len < minlen) && - (m = m_pullup(m, minlen)) == 0) { + if (m->m_len < minlen && (m = m_pullup(m, minlen)) == NULL) { CTR1(KTR_IPMF, "%s: m_pullup() failed", __func__); - return; + return (IPPROTO_DONE); } /* m_pullup() may have given us a new mbuf so reset ip. */ @@ -2625,7 +2630,7 @@ pim_input(struct mbuf *m, int off) PIMSTAT_INC(pims_rcv_badsum); CTR1(KTR_IPMF, "%s: invalid checksum", __func__); m_freem(m); - return; + return (IPPROTO_DONE); } /* PIM version check */ @@ -2634,7 +2639,7 @@ pim_input(struct mbuf *m, int off) CTR3(KTR_IPMF, "%s: bad version %d expect %d", __func__, (int)PIM_VT_V(pim->pim_vt), PIM_VERSION); m_freem(m); - return; + return (IPPROTO_DONE); } /* restore mbuf back to the outer IP */ @@ -2659,7 +2664,7 @@ pim_input(struct mbuf *m, int off) CTR2(KTR_IPMF, "%s: register vif not set: %d", __func__, (int)V_reg_vif_num); m_freem(m); - return; + return (IPPROTO_DONE); } /* XXX need refcnt? */ vifp = V_viftable[V_reg_vif_num].v_ifp; @@ -2673,7 +2678,7 @@ pim_input(struct mbuf *m, int off) PIMSTAT_INC(pims_rcv_badregisters); CTR1(KTR_IPMF, "%s: register packet size too small", __func__); m_freem(m); - return; + return (IPPROTO_DONE); } reghdr = (u_int32_t *)(pim + 1); @@ -2687,7 +2692,7 @@ pim_input(struct mbuf *m, int off) PIMSTAT_INC(pims_rcv_badregisters); CTR1(KTR_IPMF, "%s: bad encap ip version", __func__); m_freem(m); - return; + return (IPPROTO_DONE); } /* verify the inner packet is destined to a mcast group */ @@ -2696,7 +2701,7 @@ pim_input(struct mbuf *m, int off) CTR2(KTR_IPMF, "%s: bad encap ip dest %s", __func__, inet_ntoa(encap_ip->ip_dst)); m_freem(m); - return; + return (IPPROTO_DONE); } /* If a NULL_REGISTER, pass it to the daemon */ @@ -2735,7 +2740,7 @@ pim_input(struct mbuf *m, int off) if (mcp == NULL) { CTR1(KTR_IPMF, "%s: m_copy() failed", __func__); m_freem(m); - return; + return (IPPROTO_DONE); } /* Keep statistics */ @@ -2771,9 +2776,10 @@ pim_input_to_daemon: * XXX: the outer IP header pkt size of a Register is not adjust to * reflect the fact that the inner multicast data is truncated. */ - rip_input(m, iphlen); + *mp = m; + rip_input(mp, offp, proto); - return; + return (IPPROTO_DONE); } static int @@ -2813,12 +2819,12 @@ vnet_mroute_init(const void *unused __unused) MALLOC(V_nexpire, u_char *, mfchashsize, M_MRTABLE, M_WAITOK|M_ZERO); bzero(V_bw_meter_timers, sizeof(V_bw_meter_timers)); - callout_init(&V_expire_upcalls_ch, CALLOUT_MPSAFE); - callout_init(&V_bw_upcalls_ch, CALLOUT_MPSAFE); - callout_init(&V_bw_meter_ch, CALLOUT_MPSAFE); + callout_init(&V_expire_upcalls_ch, 1); + callout_init(&V_bw_upcalls_ch, 1); + callout_init(&V_bw_meter_ch, 1); } -VNET_SYSINIT(vnet_mroute_init, SI_SUB_PSEUDO, SI_ORDER_ANY, vnet_mroute_init, +VNET_SYSINIT(vnet_mroute_init, SI_SUB_PROTO_MC, SI_ORDER_ANY, vnet_mroute_init, NULL); static void @@ -2829,7 +2835,7 @@ vnet_mroute_uninit(const void *unused __unused) V_nexpire = NULL; } -VNET_SYSUNINIT(vnet_mroute_uninit, SI_SUB_PSEUDO, SI_ORDER_MIDDLE, +VNET_SYSUNINIT(vnet_mroute_uninit, SI_SUB_PROTO_MC, SI_ORDER_MIDDLE, vnet_mroute_uninit, NULL); static int @@ -2944,4 +2950,4 @@ static moduledata_t ip_mroutemod = { 0 }; -DECLARE_MODULE(ip_mroute, ip_mroutemod, SI_SUB_PSEUDO, SI_ORDER_MIDDLE); +DECLARE_MODULE(ip_mroute, ip_mroutemod, SI_SUB_PROTO_MC, SI_ORDER_MIDDLE); |