76#include "opt_mrouting.h"
82#include <sys/kernel.h>
83#include <sys/stddef.h>
84#include <sys/condvar.h>
85#include <sys/eventhandler.h>
87#include <sys/kthread.h>
89#include <sys/malloc.h>
91#include <sys/module.h>
93#include <sys/protosw.h>
94#include <sys/signalvar.h>
95#include <sys/socket.h>
96#include <sys/socketvar.h>
97#include <sys/sockio.h>
99#include <sys/sysctl.h>
100#include <sys/syslog.h>
101#include <sys/systm.h>
102#include <sys/taskqueue.h>
104#include <sys/counter.h>
105#include <machine/atomic.h>
108#include <net/if_var.h>
109#include <net/if_types.h>
110#include <net/netisr.h>
111#include <net/route.h>
127#include <machine/in_cksum.h>
130#define KTR_IPMF KTR_INET
133#define VIFI_INVALID ((vifi_t) -1)
146#define MRW_RLOCK() rw_rlock(&mrouter_mtx)
147#define MRW_WLOCK() rw_wlock(&mrouter_mtx)
148#define MRW_RUNLOCK() rw_runlock(&mrouter_mtx)
149#define MRW_WUNLOCK() rw_wunlock(&mrouter_mtx)
150#define MRW_UNLOCK() rw_unlock(&mrouter_mtx)
151#define MRW_LOCK_ASSERT() rw_assert(&mrouter_mtx, RA_LOCKED)
152#define MRW_WLOCK_ASSERT() rw_assert(&mrouter_mtx, RA_WLOCKED)
153#define MRW_LOCK_TRY_UPGRADE() rw_try_upgrade(&mrouter_mtx)
154#define MRW_WOWNED() rw_wowned(&mrouter_mtx)
155#define MRW_LOCK_INIT() \
156 rw_init(&mrouter_mtx, "IPv4 multicast forwarding")
157#define MRW_LOCK_DESTROY() rw_destroy(&mrouter_mtx)
166 mrtstat,
"IPv4 Multicast Forwarding Statistics (struct mrtstat, "
167 "netinet/ip_mroute.h)");
170#define V_mfchash VNET(mfchash)
171#define MFCHASH(a, g) \
172 ((((a).s_addr >> 20) ^ ((a).s_addr >> 10) ^ (a).s_addr ^ \
173 ((g).s_addr >> 20) ^ ((g).s_addr >> 10) ^ (g).s_addr) & V_mfchash)
174#define MFCHASHSIZE 256
178#define V_nexpire VNET(nexpire)
180#define V_mfchashtbl VNET(mfchashtbl)
182#define V_task_queue VNET(task_queue)
184#define V_task VNET(task)
187#define V_numvifs VNET(numvifs)
189#define V_viftable VNET(viftable)
194#define V_expire_upcalls_ch VNET(expire_upcalls_ch)
197#define V_buf_ring_mtx VNET(buf_ring_mtx)
199#define EXPIRE_TIMEOUT (hz / 4)
200#define UPCALL_EXPIRE 6
212#define V_bw_upcalls_ch VNET(bw_upcalls_ch)
214#define V_bw_upcalls_ring VNET(bw_upcalls_ring)
216#define V_bw_upcalls_ring_mtx VNET(bw_upcalls_ring_mtx)
218#define BW_UPCALLS_PERIOD (hz)
227 pimstat,
"PIM Statistics (struct pimstat, netinet/pim_var.h)");
232 "Disable IGMP_WHOLEPKT notifications if rendezvous point is unspecified");
241 .
proto = IPPROTO_PIM,
263#define PIM_ENCAP_TTL 64
266#if BYTE_ORDER == LITTLE_ENDIAN
267 sizeof(
struct ip) >> 2,
271 sizeof(struct
ip) >> 2,
292#define V_reg_vif_num VNET(reg_vif_num)
294#define V_multicast_register_if VNET(multicast_register_if)
302 struct ip_moptions *);
329static __inline
struct mfc *
335 struct mbuf *,
struct mfc *);
337 struct mbuf *,
struct mfc *);
339 struct mbuf *,
struct mfc *);
343static int socket_send(
struct socket *,
struct mbuf *,
351#define MRT_API_VERSION 0x0305
359#define V_mrt_api_config VNET(mrt_api_config)
361#define V_pim_assert_enabled VNET(pim_assert_enabled)
368static __inline
struct mfc *
390static __inline
struct mfc *
394 rt = (
struct mfc*) malloc(
sizeof(*rt), M_MRTABLE, M_NOWAIT | M_ZERO);
425 switch (sopt->sopt_name) {
427 error = sooptcopyin(sopt, &optval,
sizeof optval,
sizeof optval);
438 error = sooptcopyin(sopt, &vifc,
sizeof vifc,
sizeof vifc);
445 error = sooptcopyin(sopt, &vifi,
sizeof vifi,
sizeof vifi);
458 error = sooptcopyin(sopt, &
mfc,
sizeof(
struct mfcctl2),
461 error = sooptcopyin(sopt, &
mfc,
sizeof(
struct mfcctl),
463 bzero((caddr_t)&
mfc +
sizeof(
struct mfcctl),
475 error = sooptcopyin(sopt, &optval,
sizeof optval,
sizeof optval);
482 error = sooptcopyin(sopt, &i,
sizeof i,
sizeof i);
486 error = sooptcopyout(sopt, &i,
sizeof i);
516 switch (sopt->sopt_name) {
554 error = priv_check(curthread, PRIV_NETINET_MROUTE);
558 case (SIOCGETVIFCNT):
586 return EADDRNOTAVAIL;
624 u_long i, vifi_cnt = 0;
625 struct ifnet *free_ptr;
642 for (vifi = 0; vifi <
V_numvifs; vifi++) {
646 struct mfc *rt, *nrt;
648 LIST_FOREACH_SAFE(rt, &
V_mfchashtbl[i], mfc_hash, nrt) {
655 if (free_ptr != NULL)
666 for (i = 0; i < vifi_cnt; i++)
673 CURVNET_SET((
struct vnet *) arg);
689 CTR3(
KTR_IPMF,
"%s: so_type %d, pr_protocol %d", __func__,
690 so->so_type, so->so_proto->pr_protocol);
692 if (so->so_type != SOCK_RAW || so->so_proto->pr_protocol != IPPROTO_IGMP)
739 CTR1(
KTR_IPMF,
"%s: done", __func__);
769 epoch_wait_preempt(net_epoch_preempt);
791 for (vifi = 0; vifi <
V_numvifs; vifi++) {
810 struct mfc *rt, *nrt;
812 LIST_FOREACH_SAFE(rt, &
V_mfchashtbl[i], mfc_hash, nrt) {
827 CTR1(
KTR_IPMF,
"%s: done", __func__);
838 if ((i != 1) && (i != 0))
905 log(LOG_ERR,
"rate limiting is no longer supported\n");
910 return EADDRNOTAVAIL;
921 struct epoch_tracker et;
925 ifa = ifa_ifwithaddr((
struct sockaddr *)&sin);
928 return EADDRNOTAVAIL;
936 CTR1(
KTR_IPMF,
"%s: tunnels are no longer supported", __func__);
940 CTR2(
KTR_IPMF,
"%s: add register vif for ifp %p", __func__, ifp);
946 if ((ifp->if_flags & IFF_MULTICAST) == 0)
950 error = if_allmulti(ifp, 1);
980 if (V_numvifs <= vifcp->vifc_vifi)
985 CTR4(
KTR_IPMF,
"%s: add vif %d laddr 0x%08x thresh %x", __func__,
1009 return EADDRNOTAVAIL;
1013 if_allmulti(vifp->
v_ifp, 0);
1020 *ifp_free = vifp->
v_ifp;
1024 mtx_destroy(&vifp->
v_spin);
1026 bzero((caddr_t)vifp,
sizeof (*vifp));
1028 CTR2(
KTR_IPMF,
"%s: delete vif %d", __func__, (
int)vifi);
1031 for (vifi =
V_numvifs; vifi > 0; vifi--)
1043 struct ifnet *free_ptr;
1108 free(rte, M_MRTABLE);
1113 LIST_REMOVE(rt, mfc_hash);
1114 free(rt, M_MRTABLE);
1133 CTR4(
KTR_IPMF,
"%s: update mfc orig 0x%08x group %lx parent %x",
1152 "%s: add mfc orig 0x%08x group %lx parent %x qh %p",
1158 CTR1(
KTR_IPMF,
"%s: multiple matches", __func__);
1167 if (rte->
ifp != NULL)
1170 free(rte, M_MRTABLE);
1179 CTR1(
KTR_IPMF,
"%s: adding mfc w/o upcall", __func__);
1227 CTR3(
KTR_IPMF,
"%s: delete mfc orig 0x%08x group %lx", __func__,
1235 return EADDRNOTAVAIL;
1246 LIST_REMOVE(rt, mfc_hash);
1247 free(rt, M_MRTABLE);
1261 SOCKBUF_LOCK(&s->so_rcv);
1262 if (sbappendaddr_locked(&s->so_rcv, (
struct sockaddr *)src, mm,
1264 sorwakeup_locked(s);
1267 soroverflow_locked(s);
1284#define TUNNEL_LEN 12
1288 struct ip_moptions *imo)
1298 CTR3(
KTR_IPMF,
"ip_mforward: delete mfc orig 0x%08x group %lx ifp %p",
1319 if (imo && ((vifi = imo->imo_multicast_vif) <
V_numvifs)) {
1359 goto mfc_find_retry;
1370 CTR2(
KTR_IPMF,
"ip_mforward: no mfc for (0x%08x,%lx)",
1378 rte = (
struct rtdetq*) malloc((
sizeof *rte), M_MRTABLE,
1385 mb0 = m_copypacket(
m, M_NOWAIT);
1386 if (mb0 && (!M_WRITABLE(mb0) || mb0->m_len < hlen))
1387 mb0 = m_pullup(mb0, hlen);
1389 free(rte, M_MRTABLE);
1407 struct sockaddr_in k_igmpsrc = {
sizeof k_igmpsrc, AF_INET };
1426 mm = m_copym(mb0, 0, hlen, M_NOWAIT);
1435 im = mtod(mm,
struct igmpmsg*);
1444 CTR0(
KTR_IPMF,
"ip_mforward: socket queue full");
1446 fail1: free(rt, M_MRTABLE);
1447 fail: free(rte, M_MRTABLE);
1483 non_fatal: free(rte, M_MRTABLE);
1508 CURVNET_SET((
struct vnet *) arg);
1513 struct mfc *rt, *nrt;
1518 LIST_FOREACH_SAFE(rt, &
V_mfchashtbl[i], mfc_hash, nrt) {
1526 CTR3(
KTR_IPMF,
"%s: expire (%lx, %lx)", __func__,
1546 struct ip *
ip = mtod(m,
struct ip *);
1570 CTR4(
KTR_IPMF,
"%s: rx on wrong ifp %p (vifi %d, v_ifp %p)",
1571 __func__, ifp, (
int)vifi,
V_viftable[vifi].v_ifp);
1598 struct sockaddr_in k_igmpsrc = {
sizeof k_igmpsrc, AF_INET };
1601 struct mbuf *mm = m_copym(m, 0, hlen, M_NOWAIT);
1603 if (mm && (!M_WRITABLE(mm) || mm->m_len < hlen))
1604 mm = m_pullup(mm, hlen);
1608 im = mtod(mm,
struct igmpmsg *);
1617 CTR1(
KTR_IPMF,
"%s: socket queue full", __func__);
1646 for (vifi = 0; vifi <
V_numvifs; vifi++)
1729 struct mbuf *mb_copy;
1739 mb_copy = m_copypacket(m, M_NOWAIT);
1740 if (mb_copy && (!M_WRITABLE(mb_copy) || mb_copy->m_len < hlen))
1741 mb_copy = m_pullup(mb_copy, hlen);
1742 if (mb_copy == NULL)
1751 struct ip_moptions imo;
1756 imo.imo_multicast_ifp = vifp->
v_ifp;
1757 imo.imo_multicast_ttl = mtod(m,
struct ip *)->ip_ttl - 1;
1759 imo.imo_multicast_vif = -1;
1760 STAILQ_INIT(&imo.imo_head);
1769 CTR3(
KTR_IPMF,
"%s: vif %td err %d", __func__,
1781 return (EOPNOTSUPP);
1799 return (IPPROTO_DONE);
1809#define BW_TIMEVALCMP(tvp, uvp, cmp) timevalcmp((tvp), (uvp), cmp)
1810#define BW_TIMEVALDECR(vvp, uvp) timevalsub((vvp), (uvp))
1811#define BW_TIMEVALADD(vvp, uvp) timevaladd((vvp), (uvp))
1840 CURVNET_SET((
struct vnet *)x->
arg);
1911 return EADDRNOTAVAIL;
1920 for (x = *bwm_ptr; x != NULL; x = x->
bm_mfc_next) {
1935 x = (
struct bw_meter*) malloc(
sizeof(*x), M_BWMETER,
1976 while (list != NULL) {
2008 return EADDRNOTAVAIL;
2039 for (prev = NULL, x = *bwm_ptr; x != NULL;
2055 callout_stop(&x->bm_meter_callout);
2075 struct timeval delta;
2092 x->
bm_flags &= ~BW_METER_UPCALL_DELIVERED;
2120 struct timeval delta;
2134 u = malloc(
sizeof(
struct bw_upcall), M_MRTABLE, M_NOWAIT | M_ZERO);
2136 log(LOG_WARNING,
"bw_meter_prepare_upcall: cannot allocate entry\n");
2158 log(LOG_WARNING,
"bw_meter_prepare_upcall: cannot enqueue upcall\n");
2172 struct sockaddr_in k_igmpsrc = {
sizeof k_igmpsrc, AF_INET };
2191 m = m_gethdr(M_NOWAIT, MT_DATA);
2193 log(LOG_WARNING,
"bw_upcalls_send: cannot allocate mbuf\n");
2198 len +=
sizeof(
struct igmpmsg);
2200 m_copyback(m, len,
sizeof(
struct bw_upcall), (caddr_t)bu);
2202 free(bu, M_MRTABLE);
2211 log(LOG_WARNING,
"bw_upcalls_send: ip_mrouter socket queue full\n");
2222 CURVNET_SET((
struct vnet *) arg);
2245 struct mbuf *mb_copy, *mm;
2256 if (mb_copy == NULL)
2263 for (mm = mb_copy; mm; mm = mb_copy) {
2264 mb_copy = mm->m_nextpkt;
2266 mm = m_pullup(mm,
sizeof(
struct ip));
2268 ip = mtod(mm,
struct ip *);
2288 struct mbuf *mb_copy = NULL;
2292 if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
2294 m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
2301 mb_copy = m_copypacket(m, M_NOWAIT);
2302 if (mb_copy == NULL)
2304 mb_copy = m_pullup(mb_copy,
ip->
ip_hl << 2);
2305 if (mb_copy == NULL)
2309 ip = mtod(mb_copy,
struct ip *);
2321 mb_copy->m_pkthdr.csum_flags |= CSUM_IP;
2335 struct mbuf *mb_copy,
struct mfc *rt)
2337 struct mbuf *mb_first;
2340 struct sockaddr_in k_igmpsrc = {
sizeof k_igmpsrc, AF_INET };
2347 mb_first = m_gethdr(M_NOWAIT, MT_DATA);
2348 if (mb_first == NULL) {
2352 mb_first->m_data += max_linkhdr;
2353 mb_first->m_pkthdr.len = len +
sizeof(
struct igmpmsg);
2354 mb_first->m_len =
sizeof(
struct igmpmsg);
2355 mb_first->m_next = mb_copy;
2358 im = mtod(mb_first,
struct igmpmsg *);
2362 im->im_src =
ip->ip_src;
2370 CTR1(
KTR_IPMF,
"%s: socket queue full", __func__);
2389 struct mbuf *mb_first;
2390 struct ip *ip_outer;
2399 return EADDRNOTAVAIL;
2405 mb_first = m_gethdr(M_NOWAIT, MT_DATA);
2406 if (mb_first == NULL) {
2410 mb_first->m_data += max_linkhdr;
2412 mb_first->m_next = mb_copy;
2414 mb_first->m_pkthdr.len = len + mb_first->m_len;
2419 ip_outer = mtod(mb_first,
struct ip *);
2423 ip_outer->ip_src =
V_viftable[vifi].v_lcl_addr;
2460 int proto __unused,
void *arg __unused)
2463 KASSERT(proto == IPPROTO_PIM, (
"not for IPPROTO_PIM"));
2476pim_input(
struct mbuf *m,
int off,
int proto,
void *arg __unused)
2478 struct ip *
ip = mtod(m,
struct ip *);
2482 int datalen = ntohs(
ip->
ip_len) - iphlen;
2494 CTR3(
KTR_IPMF,
"%s: short packet (%d) from 0x%08x",
2495 __func__, datalen, ntohl(
ip->ip_src.s_addr));
2497 return (IPPROTO_DONE);
2513 if (m->m_len < minlen && (m = m_pullup(m, minlen)) == NULL) {
2514 CTR1(
KTR_IPMF,
"%s: m_pullup() failed", __func__);
2515 return (IPPROTO_DONE);
2519 ip = mtod(m,
struct ip *);
2523 m->m_data += iphlen;
2525 pim = mtod(m,
struct pim *);
2536 }
else if (in_cksum(m, datalen)) {
2538 CTR1(
KTR_IPMF,
"%s: invalid checksum", __func__);
2540 return (IPPROTO_DONE);
2546 CTR3(
KTR_IPMF,
"%s: bad version %d expect %d", __func__,
2549 return (IPPROTO_DONE);
2553 m->m_data -= iphlen;
2562 struct sockaddr_in dst = {
sizeof(dst), AF_INET };
2564 struct ip *encap_ip;
2571 CTR2(
KTR_IPMF,
"%s: register vif not set: %d", __func__,
2574 return (IPPROTO_DONE);
2586 CTR1(
KTR_IPMF,
"%s: register packet size too small", __func__);
2588 return (IPPROTO_DONE);
2591 reghdr = (u_int32_t *)(
pim + 1);
2592 encap_ip = (
struct ip *)(reghdr + 1);
2594 CTR3(
KTR_IPMF,
"%s: register: encap ip src 0x%08x len %d",
2595 __func__, ntohl(encap_ip->ip_src.s_addr),
2596 ntohs(encap_ip->
ip_len));
2601 CTR1(
KTR_IPMF,
"%s: bad encap ip version", __func__);
2603 return (IPPROTO_DONE);
2609 CTR2(
KTR_IPMF,
"%s: bad encap ip dest 0x%08x", __func__,
2612 return (IPPROTO_DONE);
2617 goto pim_input_to_daemon;
2632 encap_ip->
ip_sum = in_cksum(m, encap_ip->
ip_hl << 2);
2649 CTR1(
KTR_IPMF,
"%s: m_copym() failed", __func__);
2651 return (IPPROTO_DONE);
2665 "%s: forward decap'd REGISTER: src %lx dst %lx vif %d",
2667 (u_long)ntohl(encap_ip->ip_src.s_addr),
2700 error = sysctl_wire_old_buffer(req, 0);
2707 error = SYSCTL_OUT(req, rt,
sizeof(
struct mfc));
2719 "IPv4 Multicast Forwarding Table "
2720 "(struct *mfc[mfchashsize], netinet/ip_mroute.h)");
2742 CTLTYPE_OPAQUE | CTLFLAG_VNET | CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, 0,
2744 "IPv4 Multicast Interfaces (struct vif[MAXVIFS], netinet/ip_mroute.h)");
2753 M_MRTABLE, M_WAITOK|M_ZERO);
2759 V_task_queue = taskqueue_create_fast(
"ip_mroute_tskq", M_NOWAIT,
2761 taskqueue_start_threads(&
V_task_queue, 1, PI_NET,
"ip_mroute_tskq task");
2793 printf(
"ip_mroute: unable to register "
2794 "ifnet_departure_event handler\n");
2800 if (TUNABLE_ULONG_FETCH(
"net.inet.ip.mfchashsize", &
mfchashsize) &&
2802 printf(
"WARNING: %s not a power of 2; using default\n",
2803 "net.inet.ip.mfchashsize");
2808 TUNABLE_ULONG_FETCH(
"net.inet.pim.squelch_wholepkt",
2813 printf(
"ip_mroute: unable to attach pim encap\n");
static LIST_HEAD(carp_softc)
int ip_encap_detach(const struct encaptab *)
const struct encaptab * ip_encap_attach(const struct encap_config *, void *arg, int mflags)
void ip_fillid(struct ip *ip)
static const struct encaptab * pim_encap_cookie
static moduledata_t ip_mroutemod
static __inline struct mfc * mfc_find(struct in_addr *, struct in_addr *)
static void bw_meter_prepare_upcall(struct bw_meter *, struct timeval *)
VNET_SYSUNINIT(vnet_mroute_uninit, SI_SUB_PROTO_MC, SI_ORDER_MIDDLE, vnet_mroute_uninit, NULL)
static const struct encap_config ipv4_encap_cfg
static int X_ip_mrouter_set(struct socket *, struct sockopt *)
VNET_PCPUSTAT_SYSINIT(mrtstat)
SYSCTL_PROC(_net_inet_ip, OID_AUTO, viftable, CTLTYPE_OPAQUE|CTLFLAG_VNET|CTLFLAG_RD|CTLFLAG_MPSAFE, NULL, 0, sysctl_viflist, "S,vif[MAXVIFS]", "IPv4 Multicast Interfaces (struct vif[MAXVIFS], netinet/ip_mroute.h)")
static struct timeval pim_assert_interval
static void ip_mrouter_upcall_thread(void *arg, int pending __unused)
static void vnet_mroute_init(const void *unused __unused)
#define MRW_LOCK_TRY_UPGRADE()
static uint32_t compute_bw_meter_flags(struct bw_upcall *req)
static void update_mfc_params(struct mfc *rt, struct mfcctl2 *mfccp)
static u_long mfchashsize
static void expire_upcalls(void *)
static int del_vif_locked(vifi_t, struct ifnet **)
static int sysctl_mfctable(SYSCTL_HANDLER_ARGS)
#define BW_TIMEVALDECR(vvp, uvp)
static int del_bw_upcall(struct bw_upcall *)
static int pim_register_send_rp(struct ip *, struct vif *, struct mbuf *, struct mfc *)
static u_long pim_squelch_wholepkt
static void if_detached_event(void *, struct ifnet *)
VNET_DEFINE_STATIC(u_long, mfchash)
#define V_multicast_register_if
static void init_mfc_params(struct mfc *rt, struct mfcctl2 *mfccp)
static int add_mfc(struct mfcctl2 *)
DECLARE_MODULE(ip_mroute, ip_mroutemod, SI_SUB_PROTO_MC, SI_ORDER_MIDDLE)
static eventhandler_tag if_detach_event_tag
#define V_bw_upcalls_ring_mtx
VNET_PCPUSTAT_DEFINE_STATIC(struct mrtstat, mrtstat)
static int add_vif(struct vifctl *)
static int X_mrt_ioctl(u_long, caddr_t, int)
static int get_vif_cnt(struct sioc_vif_req *)
SYSCTL_NODE(_net_inet, IPPROTO_PIM, pim, CTLFLAG_RW|CTLFLAG_MPSAFE, 0, "PIM")
static void expire_bw_upcalls_send(void *)
#define MRW_LOCK_ASSERT()
static const uint32_t mrt_api_support
static void send_packet(struct vif *, struct mbuf *)
#define V_pim_assert_enabled
#define MRW_LOCK_DESTROY()
static int pim_register_send(struct ip *, struct vif *, struct mbuf *, struct mfc *)
static int set_assert(int)
static const int mrt_api_version
SYSCTL_ULONG(_net_inet_pim, OID_AUTO, squelch_wholepkt, CTLFLAG_RW, &pim_squelch_wholepkt, 0, "Disable IGMP_WHOLEPKT notifications if rendezvous point is unspecified")
static int pim_input(struct mbuf *, int, int, void *)
static int ip_mroute_modevent(module_t mod, int type, void *unused)
static void expire_mfc(struct mfc *)
static int X_ip_mforward(struct ip *, struct ifnet *, struct mbuf *, struct ip_moptions *)
static void expire_bw_meter_leq(void *arg)
static struct rwlock mrouter_mtx
#define V_bw_upcalls_ring
static struct pim_encap_pimhdr pim_encap_pimhdr
static int ip_mrouter_init(struct socket *, int)
static MALLOC_DEFINE(M_MRTABLE, "mroutetbl", "multicast forwarding cache")
static int sysctl_viflist(SYSCTL_HANDLER_ARGS)
static void bw_upcalls_send(void)
static int X_legal_vif_num(int)
static int pim_encapcheck(const struct mbuf *, int, int, void *)
VNET_PCPUSTAT_SYSUNINIT(mrtstat)
static struct ip pim_encap_iphdr
static int X_rsvp_input(struct mbuf **mp, int *offp, int proto)
static int ip_mrouter_unloading
static void phyint_send(struct ip *, struct vif *, struct mbuf *)
static void bw_meter_geq_receive_packet(struct bw_meter *, int, struct timeval *)
static struct mbuf * pim_register_prepare(struct ip *, struct mbuf *)
#define BW_TIMEVALCMP(tvp, uvp, cmp)
static int ip_mdq(struct mbuf *, struct ifnet *, struct mfc *, vifi_t)
static int socket_send(struct socket *, struct mbuf *, struct sockaddr_in *)
static int X_ip_mrouter_get(struct socket *, struct sockopt *)
#define BW_UPCALLS_PERIOD
static void X_ip_rsvp_force_done(struct socket *so __unused)
static int get_sg_cnt(struct sioc_sg_req *)
static int pim_register_send_upcall(struct ip *, struct vif *, struct mbuf *, struct mfc *)
static int ip_mrouter_cnt
static u_long X_ip_mcast_src(int)
static int X_ip_rsvp_vif(struct socket *so __unused, struct sockopt *sopt __unused)
static void vnet_mroute_uninit(const void *unused __unused)
static int X_ip_mrouter_done(void)
static int del_vif(vifi_t)
#define V_expire_upcalls_ch
static int add_bw_upcall(struct bw_upcall *)
static int set_api_config(uint32_t *)
static void free_bw_list(struct bw_meter *)
static __inline struct mfc * mfc_alloc(void)
#define MRW_WLOCK_ASSERT()
VNET_SYSINIT(vnet_mroute_init, SI_SUB_PROTO_MC, SI_ORDER_ANY, vnet_mroute_init, NULL)
SYSCTL_VNET_PCPUSTAT(_net_inet_ip, OID_AUTO, mrtstat, struct mrtstat, mrtstat, "IPv4 Multicast Forwarding Statistics (struct mrtstat, " "netinet/ip_mroute.h)")
static int del_mfc(struct mfcctl2 *)
#define MRT_MFC_FLAGS_BORDER_VIF
int(* mrt_ioctl)(u_long, caddr_t, int)
#define MRT_DEL_BW_UPCALL
#define BW_UPCALL_THRESHOLD_INTERVAL_MIN_USEC
#define BW_METER_UNIT_BYTES
int(* ip_mrouter_done)(void)
#define MRT_MFC_FLAGS_ALL
#define MRT_ADD_BW_UPCALL
int(* ip_mrouter_set)(struct socket *, struct sockopt *)
#define MRTSTAT_INC(name)
#define MRT_MFC_BW_UPCALL
#define BW_METER_UNIT_PACKETS
int(* ip_mrouter_get)(struct socket *, struct sockopt *)
#define IGMPMSG_BW_UPCALL
#define BW_UPCALL_UNIT_BYTES
#define BW_METER_USER_FLAGS
#define MRT_MFC_FLAGS_DISABLE_WRONGVIF
#define BW_UPCALL_DELETE_ALL
#define MRT_API_FLAGS_ALL
#define BW_UPCALL_THRESHOLD_INTERVAL_MIN_SEC
#define BW_METER_UPCALL_DELIVERED
#define BW_UPCALL_UNIT_PACKETS
int ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro, int flags, struct ip_moptions *imo, struct inpcb *inp)
int ip_fragment(struct ip *ip, struct mbuf **m_frag, int mtu, u_long if_hwassist_flags)
void in_delayed_cksum(struct mbuf *m)
int(* ip_rsvp_vif)(struct socket *, struct sockopt *)
int(* rsvp_input_p)(struct mbuf **, int *, int)
int(* legal_vif_num)(int)
int(* ip_mforward)(struct ip *, struct ifnet *, struct mbuf *, struct ip_moptions *)
void(* ip_rsvp_force_done)(struct socket *)
u_long(* ip_mcast_src)(int)
int rip_input(struct mbuf **, int *, int)
#define PIM_NULL_REGISTER
#define PIM_BORDER_REGISTER
#define PIMSTAT_ADD(name, val)
#define PIMSTAT_INC(name)
struct callout bm_meter_callout
struct timeval bm_start_time
struct bw_data bm_threshold
struct bw_data bm_measured
struct bw_meter * bm_time_next
struct bw_meter * bm_mfc_next
struct bw_data bu_threshold
struct bw_data bu_measured
struct in_addr im_src im_dst
struct in_addr ip_src ip_dst
uint8_t mfc_flags[MAXVIFS]
struct timeval mfc_last_assert
struct bw_meter * mfc_bw_meter_leq
struct bw_meter * mfc_bw_meter_geq
struct in_addr mfc_mcastgrp
struct in_addr mfc_origin
struct buf_ring * mfc_stall_ring
struct in_addr mfcc_mcastgrp
struct in_addr mfcc_origin
uint8_t mfcc_flags[MAXVIFS]
u_char mfcc_ttls[MAXVIFS]
struct in_addr v_rmt_addr
struct in_addr v_lcl_addr
struct in_addr vifc_rmt_addr
struct in_addr vifc_lcl_addr