FreeBSD kernel IPv4 code
ip_mroute.c
Go to the documentation of this file.
1/*-
2 * SPDX-License-Identifier: BSD-3-Clause
3 *
4 * Copyright (c) 1989 Stephen Deering
5 * Copyright (c) 1992, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * This code is derived from software contributed to Berkeley by
9 * Stephen Deering of Stanford University.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 * @(#)ip_mroute.c 8.2 (Berkeley) 11/15/93
36 */
37
38/*
39 * IP multicast forwarding procedures
40 *
41 * Written by David Waitzman, BBN Labs, August 1988.
42 * Modified by Steve Deering, Stanford, February 1989.
43 * Modified by Mark J. Steiglitz, Stanford, May, 1991
44 * Modified by Van Jacobson, LBL, January 1993
45 * Modified by Ajit Thyagarajan, PARC, August 1993
46 * Modified by Bill Fenner, PARC, April 1995
47 * Modified by Ahmed Helmy, SGI, June 1996
48 * Modified by George Edmond Eddy (Rusty), ISI, February 1998
49 * Modified by Pavlin Radoslavov, USC/ISI, May 1998, August 1999, October 2000
50 * Modified by Hitoshi Asaeda, WIDE, August 2000
51 * Modified by Pavlin Radoslavov, ICSI, October 2002
52 * Modified by Wojciech Macek, Semihalf, May 2021
53 *
54 * MROUTING Revision: 3.5
55 * and PIM-SMv2 and PIM-DM support, advanced API support,
56 * bandwidth metering and signaling
57 */
58
59/*
60 * TODO: Prefix functions with ipmf_.
61 * TODO: Maintain a refcount on if_allmulti() in ifnet or in the protocol
62 * domain attachment (if_afdata) so we can track consumers of that service.
63 * TODO: Deprecate routing socket path for SIOCGETSGCNT and SIOCGETVIFCNT,
64 * move it to socket options.
65 * TODO: Cleanup LSRR removal further.
66 * TODO: Push RSVP stubs into raw_ip.c.
67 * TODO: Use bitstring.h for vif set.
68 * TODO: Fix mrt6_ioctl dangling ref when dynamically loaded.
69 * TODO: Sync ip6_mroute.c with this file.
70 */
71
72#include <sys/cdefs.h>
73__FBSDID("$FreeBSD$");
74
75#include "opt_inet.h"
76#include "opt_mrouting.h"
77
78#define _PIM_VT 1
79
80#include <sys/types.h>
81#include <sys/param.h>
82#include <sys/kernel.h>
83#include <sys/stddef.h>
84#include <sys/condvar.h>
85#include <sys/eventhandler.h>
86#include <sys/lock.h>
87#include <sys/kthread.h>
88#include <sys/ktr.h>
89#include <sys/malloc.h>
90#include <sys/mbuf.h>
91#include <sys/module.h>
92#include <sys/priv.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>
98#include <sys/sx.h>
99#include <sys/sysctl.h>
100#include <sys/syslog.h>
101#include <sys/systm.h>
102#include <sys/taskqueue.h>
103#include <sys/time.h>
104#include <sys/counter.h>
105#include <machine/atomic.h>
106
107#include <net/if.h>
108#include <net/if_var.h>
109#include <net/if_types.h>
110#include <net/netisr.h>
111#include <net/route.h>
112#include <net/vnet.h>
113
114#include <netinet/in.h>
115#include <netinet/igmp.h>
116#include <netinet/in_systm.h>
117#include <netinet/in_var.h>
118#include <netinet/ip.h>
119#include <netinet/ip_encap.h>
120#include <netinet/ip_mroute.h>
121#include <netinet/ip_var.h>
122#include <netinet/ip_options.h>
123#include <netinet/pim.h>
124#include <netinet/pim_var.h>
125#include <netinet/udp.h>
126
127#include <machine/in_cksum.h>
128
129#ifndef KTR_IPMF
130#define KTR_IPMF KTR_INET
131#endif
132
133#define VIFI_INVALID ((vifi_t) -1)
134
135static MALLOC_DEFINE(M_MRTABLE, "mroutetbl", "multicast forwarding cache");
136
137/*
138 * Locking. We use two locks: one for the virtual interface table and
139 * one for the forwarding table. These locks may be nested in which case
140 * the VIF lock must always be taken first. Note that each lock is used
141 * to cover not only the specific data structure but also related data
142 * structures.
143 */
144
145static struct rwlock mrouter_mtx;
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)
158
159static int ip_mrouter_cnt; /* # of vnets with active mrouters */
160static int ip_mrouter_unloading; /* Allow no more V_ip_mrouter sockets */
161
165SYSCTL_VNET_PCPUSTAT(_net_inet_ip, OID_AUTO, mrtstat, struct mrtstat,
166 mrtstat, "IPv4 Multicast Forwarding Statistics (struct mrtstat, "
167 "netinet/ip_mroute.h)");
168
169VNET_DEFINE_STATIC(u_long, mfchash);
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
175
176static u_long mfchashsize; /* Hash size */
177VNET_DEFINE_STATIC(u_char *, nexpire); /* 0..mfchashsize-1 */
178#define V_nexpire VNET(nexpire)
179VNET_DEFINE_STATIC(LIST_HEAD(mfchashhdr, mfc)*, mfchashtbl);
180#define V_mfchashtbl VNET(mfchashtbl)
181VNET_DEFINE_STATIC(struct taskqueue *, task_queue);
182#define V_task_queue VNET(task_queue)
183VNET_DEFINE_STATIC(struct task, task);
184#define V_task VNET(task)
185
187#define V_numvifs VNET(numvifs)
188VNET_DEFINE_STATIC(struct vif *, viftable);
189#define V_viftable VNET(viftable)
190
191static eventhandler_tag if_detach_event_tag = NULL;
192
193VNET_DEFINE_STATIC(struct callout, expire_upcalls_ch);
194#define V_expire_upcalls_ch VNET(expire_upcalls_ch)
195
196VNET_DEFINE_STATIC(struct mtx, buf_ring_mtx);
197#define V_buf_ring_mtx VNET(buf_ring_mtx)
198
199#define EXPIRE_TIMEOUT (hz / 4) /* 4x / second */
200#define UPCALL_EXPIRE 6 /* number of timeouts */
201
202/*
203 * Bandwidth meter variables and constants
204 */
205static MALLOC_DEFINE(M_BWMETER, "bwmeter", "multicast upcall bw meters");
206
207/*
208 * Pending upcalls are stored in a ring which is flushed when
209 * full, or periodically
210 */
211VNET_DEFINE_STATIC(struct callout, bw_upcalls_ch);
212#define V_bw_upcalls_ch VNET(bw_upcalls_ch)
213VNET_DEFINE_STATIC(struct buf_ring *, bw_upcalls_ring);
214#define V_bw_upcalls_ring VNET(bw_upcalls_ring)
215VNET_DEFINE_STATIC(struct mtx, bw_upcalls_ring_mtx);
216#define V_bw_upcalls_ring_mtx VNET(bw_upcalls_ring_mtx)
217
218#define BW_UPCALLS_PERIOD (hz) /* periodical flush of bw upcalls */
219
223
224SYSCTL_NODE(_net_inet, IPPROTO_PIM, pim, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
225 "PIM");
226SYSCTL_VNET_PCPUSTAT(_net_inet_pim, PIMCTL_STATS, stats, struct pimstat,
227 pimstat, "PIM Statistics (struct pimstat, netinet/pim_var.h)");
228
229static u_long pim_squelch_wholepkt = 0;
230SYSCTL_ULONG(_net_inet_pim, OID_AUTO, squelch_wholepkt, CTLFLAG_RW,
232 "Disable IGMP_WHOLEPKT notifications if rendezvous point is unspecified");
233
234static const struct encaptab *pim_encap_cookie;
235static int pim_encapcheck(const struct mbuf *, int, int, void *);
236static int pim_input(struct mbuf *, int, int, void *);
237
238extern int in_mcast_loop;
239
240static const struct encap_config ipv4_encap_cfg = {
241 .proto = IPPROTO_PIM,
242 .min_length = sizeof(struct ip) + PIM_MINLEN,
243 .exact_match = 8,
244 .check = pim_encapcheck,
245 .input = pim_input
246};
247
248/*
249 * Note: the PIM Register encapsulation adds the following in front of a
250 * data packet:
251 *
252 * struct pim_encap_hdr {
253 * struct ip ip;
254 * struct pim_encap_pimhdr pim;
255 * }
256 *
257 */
258
260 struct pim pim;
262};
263#define PIM_ENCAP_TTL 64
264
265static struct ip pim_encap_iphdr = {
266#if BYTE_ORDER == LITTLE_ENDIAN
267 sizeof(struct ip) >> 2,
268 IPVERSION,
269#else
270 IPVERSION,
271 sizeof(struct ip) >> 2,
272#endif
273 0, /* tos */
274 sizeof(struct ip), /* total length */
275 0, /* id */
276 0, /* frag offset */
278 IPPROTO_PIM,
279 0, /* checksum */
280};
281
283 {
284 PIM_MAKE_VT(PIM_VERSION, PIM_REGISTER), /* PIM vers and message type */
285 0, /* reserved */
286 0, /* checksum */
287 },
288 0 /* flags */
289};
290
292#define V_reg_vif_num VNET(reg_vif_num)
293VNET_DEFINE_STATIC(struct ifnet *, multicast_register_if);
294#define V_multicast_register_if VNET(multicast_register_if)
295
296/*
297 * Private variables.
298 */
299
300static u_long X_ip_mcast_src(int);
301static int X_ip_mforward(struct ip *, struct ifnet *, struct mbuf *,
302 struct ip_moptions *);
303static int X_ip_mrouter_done(void);
304static int X_ip_mrouter_get(struct socket *, struct sockopt *);
305static int X_ip_mrouter_set(struct socket *, struct sockopt *);
306static int X_legal_vif_num(int);
307static int X_mrt_ioctl(u_long, caddr_t, int);
308
309static int add_bw_upcall(struct bw_upcall *);
310static int add_mfc(struct mfcctl2 *);
311static int add_vif(struct vifctl *);
312static void bw_meter_prepare_upcall(struct bw_meter *, struct timeval *);
313static void bw_meter_geq_receive_packet(struct bw_meter *, int,
314 struct timeval *);
315static void bw_upcalls_send(void);
316static int del_bw_upcall(struct bw_upcall *);
317static int del_mfc(struct mfcctl2 *);
318static int del_vif(vifi_t);
319static int del_vif_locked(vifi_t, struct ifnet **);
320static void expire_bw_upcalls_send(void *);
321static void expire_mfc(struct mfc *);
322static void expire_upcalls(void *);
323static void free_bw_list(struct bw_meter *);
324static int get_sg_cnt(struct sioc_sg_req *);
325static int get_vif_cnt(struct sioc_vif_req *);
326static void if_detached_event(void *, struct ifnet *);
327static int ip_mdq(struct mbuf *, struct ifnet *, struct mfc *, vifi_t);
328static int ip_mrouter_init(struct socket *, int);
329static __inline struct mfc *
330 mfc_find(struct in_addr *, struct in_addr *);
331static void phyint_send(struct ip *, struct vif *, struct mbuf *);
332static struct mbuf *
333 pim_register_prepare(struct ip *, struct mbuf *);
334static int pim_register_send(struct ip *, struct vif *,
335 struct mbuf *, struct mfc *);
336static int pim_register_send_rp(struct ip *, struct vif *,
337 struct mbuf *, struct mfc *);
338static int pim_register_send_upcall(struct ip *, struct vif *,
339 struct mbuf *, struct mfc *);
340static void send_packet(struct vif *, struct mbuf *);
341static int set_api_config(uint32_t *);
342static int set_assert(int);
343static int socket_send(struct socket *, struct mbuf *,
344 struct sockaddr_in *);
345
346/*
347 * Kernel multicast forwarding API capabilities and setup.
348 * If more API capabilities are added to the kernel, they should be
349 * recorded in `mrt_api_support'.
350 */
351#define MRT_API_VERSION 0x0305
352
356 MRT_MFC_RP |
359#define V_mrt_api_config VNET(mrt_api_config)
360VNET_DEFINE_STATIC(int, pim_assert_enabled);
361#define V_pim_assert_enabled VNET(pim_assert_enabled)
362static struct timeval pim_assert_interval = { 3, 0 }; /* Rate limit */
363
364/*
365 * Find a route for a given origin IP address and multicast group address.
366 * Statistics must be updated by the caller.
367 */
368static __inline struct mfc *
369mfc_find(struct in_addr *o, struct in_addr *g)
370{
371 struct mfc *rt;
372
373 /*
374 * Might be called both RLOCK and WLOCK.
375 * Check if any, it's caller responsibility
376 * to choose correct option.
377 */
379
380 LIST_FOREACH(rt, &V_mfchashtbl[MFCHASH(*o, *g)], mfc_hash) {
381 if (in_hosteq(rt->mfc_origin, *o) &&
382 in_hosteq(rt->mfc_mcastgrp, *g) &&
383 buf_ring_empty(rt->mfc_stall_ring))
384 break;
385 }
386
387 return (rt);
388}
389
390static __inline struct mfc *
392{
393 struct mfc *rt;
394 rt = (struct mfc*) malloc(sizeof(*rt), M_MRTABLE, M_NOWAIT | M_ZERO);
395 if (rt == NULL)
396 return rt;
397
398 rt->mfc_stall_ring = buf_ring_alloc(MAX_UPQ, M_MRTABLE,
399 M_NOWAIT, &V_buf_ring_mtx);
400 if (rt->mfc_stall_ring == NULL) {
401 free(rt, M_MRTABLE);
402 return NULL;
403 }
404
405 return rt;
406}
407
408/*
409 * Handle MRT setsockopt commands to modify the multicast forwarding tables.
410 */
411static int
412X_ip_mrouter_set(struct socket *so, struct sockopt *sopt)
413{
414 int error, optval;
415 vifi_t vifi;
416 struct vifctl vifc;
417 struct mfcctl2 mfc;
418 struct bw_upcall bw_upcall;
419 uint32_t i;
420
421 if (so != V_ip_mrouter && sopt->sopt_name != MRT_INIT)
422 return EPERM;
423
424 error = 0;
425 switch (sopt->sopt_name) {
426 case MRT_INIT:
427 error = sooptcopyin(sopt, &optval, sizeof optval, sizeof optval);
428 if (error)
429 break;
430 error = ip_mrouter_init(so, optval);
431 break;
432
433 case MRT_DONE:
434 error = ip_mrouter_done();
435 break;
436
437 case MRT_ADD_VIF:
438 error = sooptcopyin(sopt, &vifc, sizeof vifc, sizeof vifc);
439 if (error)
440 break;
441 error = add_vif(&vifc);
442 break;
443
444 case MRT_DEL_VIF:
445 error = sooptcopyin(sopt, &vifi, sizeof vifi, sizeof vifi);
446 if (error)
447 break;
448 error = del_vif(vifi);
449 break;
450
451 case MRT_ADD_MFC:
452 case MRT_DEL_MFC:
453 /*
454 * select data size depending on API version.
455 */
456 if (sopt->sopt_name == MRT_ADD_MFC &&
458 error = sooptcopyin(sopt, &mfc, sizeof(struct mfcctl2),
459 sizeof(struct mfcctl2));
460 } else {
461 error = sooptcopyin(sopt, &mfc, sizeof(struct mfcctl),
462 sizeof(struct mfcctl));
463 bzero((caddr_t)&mfc + sizeof(struct mfcctl),
464 sizeof(mfc) - sizeof(struct mfcctl));
465 }
466 if (error)
467 break;
468 if (sopt->sopt_name == MRT_ADD_MFC)
469 error = add_mfc(&mfc);
470 else
471 error = del_mfc(&mfc);
472 break;
473
474 case MRT_ASSERT:
475 error = sooptcopyin(sopt, &optval, sizeof optval, sizeof optval);
476 if (error)
477 break;
478 set_assert(optval);
479 break;
480
481 case MRT_API_CONFIG:
482 error = sooptcopyin(sopt, &i, sizeof i, sizeof i);
483 if (!error)
484 error = set_api_config(&i);
485 if (!error)
486 error = sooptcopyout(sopt, &i, sizeof i);
487 break;
488
491 error = sooptcopyin(sopt, &bw_upcall, sizeof bw_upcall,
492 sizeof bw_upcall);
493 if (error)
494 break;
495 if (sopt->sopt_name == MRT_ADD_BW_UPCALL)
496 error = add_bw_upcall(&bw_upcall);
497 else
498 error = del_bw_upcall(&bw_upcall);
499 break;
500
501 default:
502 error = EOPNOTSUPP;
503 break;
504 }
505 return error;
506}
507
508/*
509 * Handle MRT getsockopt commands
510 */
511static int
512X_ip_mrouter_get(struct socket *so, struct sockopt *sopt)
513{
514 int error;
515
516 switch (sopt->sopt_name) {
517 case MRT_VERSION:
518 error = sooptcopyout(sopt, &mrt_api_version, sizeof mrt_api_version);
519 break;
520
521 case MRT_ASSERT:
522 error = sooptcopyout(sopt, &V_pim_assert_enabled,
523 sizeof V_pim_assert_enabled);
524 break;
525
526 case MRT_API_SUPPORT:
527 error = sooptcopyout(sopt, &mrt_api_support, sizeof mrt_api_support);
528 break;
529
530 case MRT_API_CONFIG:
531 error = sooptcopyout(sopt, &V_mrt_api_config, sizeof V_mrt_api_config);
532 break;
533
534 default:
535 error = EOPNOTSUPP;
536 break;
537 }
538 return error;
539}
540
541/*
542 * Handle ioctl commands to obtain information from the cache
543 */
544static int
545X_mrt_ioctl(u_long cmd, caddr_t data, int fibnum __unused)
546{
547 int error = 0;
548
549 /*
550 * Currently the only function calling this ioctl routine is rtioctl_fib().
551 * Typically, only root can create the raw socket in order to execute
552 * this ioctl method, however the request might be coming from a prison
553 */
554 error = priv_check(curthread, PRIV_NETINET_MROUTE);
555 if (error)
556 return (error);
557 switch (cmd) {
558 case (SIOCGETVIFCNT):
559 error = get_vif_cnt((struct sioc_vif_req *)data);
560 break;
561
562 case (SIOCGETSGCNT):
563 error = get_sg_cnt((struct sioc_sg_req *)data);
564 break;
565
566 default:
567 error = EINVAL;
568 break;
569 }
570 return error;
571}
572
573/*
574 * returns the packet, byte, rpf-failure count for the source group provided
575 */
576static int
578{
579 struct mfc *rt;
580
581 MRW_RLOCK();
582 rt = mfc_find(&req->src, &req->grp);
583 if (rt == NULL) {
584 MRW_RUNLOCK();
585 req->pktcnt = req->bytecnt = req->wrong_if = 0xffffffff;
586 return EADDRNOTAVAIL;
587 }
588 req->pktcnt = rt->mfc_pkt_cnt;
589 req->bytecnt = rt->mfc_byte_cnt;
590 req->wrong_if = rt->mfc_wrong_if;
591 MRW_RUNLOCK();
592 return 0;
593}
594
595/*
596 * returns the input and output packet and byte counts on the vif provided
597 */
598static int
600{
601 vifi_t vifi = req->vifi;
602
603 MRW_RLOCK();
604 if (vifi >= V_numvifs) {
605 MRW_RUNLOCK();
606 return EINVAL;
607 }
608
609 mtx_lock_spin(&V_viftable[vifi].v_spin);
610 req->icount = V_viftable[vifi].v_pkt_in;
611 req->ocount = V_viftable[vifi].v_pkt_out;
612 req->ibytes = V_viftable[vifi].v_bytes_in;
613 req->obytes = V_viftable[vifi].v_bytes_out;
614 mtx_unlock_spin(&V_viftable[vifi].v_spin);
615 MRW_RUNLOCK();
616
617 return 0;
618}
619
620static void
621if_detached_event(void *arg __unused, struct ifnet *ifp)
622{
623 vifi_t vifi;
624 u_long i, vifi_cnt = 0;
625 struct ifnet *free_ptr;
626
627 MRW_WLOCK();
628
629 if (V_ip_mrouter == NULL) {
630 MRW_WUNLOCK();
631 return;
632 }
633
634 /*
635 * Tear down multicast forwarder state associated with this ifnet.
636 * 1. Walk the vif list, matching vifs against this ifnet.
637 * 2. Walk the multicast forwarding cache (mfc) looking for
638 * inner matches with this vif's index.
639 * 3. Expire any matching multicast forwarding cache entries.
640 * 4. Free vif state. This should disable ALLMULTI on the interface.
641 */
642 for (vifi = 0; vifi < V_numvifs; vifi++) {
643 if (V_viftable[vifi].v_ifp != ifp)
644 continue;
645 for (i = 0; i < mfchashsize; i++) {
646 struct mfc *rt, *nrt;
647
648 LIST_FOREACH_SAFE(rt, &V_mfchashtbl[i], mfc_hash, nrt) {
649 if (rt->mfc_parent == vifi) {
650 expire_mfc(rt);
651 }
652 }
653 }
654 del_vif_locked(vifi, &free_ptr);
655 if (free_ptr != NULL)
656 vifi_cnt++;
657 }
658
659 MRW_WUNLOCK();
660
661 /*
662 * Free IFP. We don't have to use free_ptr here as it is the same
663 * that ifp. Perform free as many times as required in case
664 * refcount is greater than 1.
665 */
666 for (i = 0; i < vifi_cnt; i++)
667 if_free(ifp);
668}
669
670static void
671ip_mrouter_upcall_thread(void *arg, int pending __unused)
672{
673 CURVNET_SET((struct vnet *) arg);
674
675 MRW_WLOCK();
677 MRW_WUNLOCK();
678
679 CURVNET_RESTORE();
680}
681
682/*
683 * Enable multicast forwarding.
684 */
685static int
686ip_mrouter_init(struct socket *so, int version)
687{
688
689 CTR3(KTR_IPMF, "%s: so_type %d, pr_protocol %d", __func__,
690 so->so_type, so->so_proto->pr_protocol);
691
692 if (so->so_type != SOCK_RAW || so->so_proto->pr_protocol != IPPROTO_IGMP)
693 return EOPNOTSUPP;
694
695 if (version != 1)
696 return ENOPROTOOPT;
697
698 MRW_WLOCK();
699
701 MRW_WUNLOCK();
702 return ENOPROTOOPT;
703 }
704
705 if (V_ip_mrouter != NULL) {
706 MRW_WUNLOCK();
707 return EADDRINUSE;
708 }
709
710 V_mfchashtbl = hashinit_flags(mfchashsize, M_MRTABLE, &V_mfchash,
711 HASH_NOWAIT);
712
713 /* Create upcall ring */
714 mtx_init(&V_bw_upcalls_ring_mtx, "mroute upcall buf_ring mtx", NULL, MTX_DEF);
715 V_bw_upcalls_ring = buf_ring_alloc(BW_UPCALLS_MAX, M_MRTABLE,
716 M_NOWAIT, &V_bw_upcalls_ring_mtx);
717 if (!V_bw_upcalls_ring) {
718 MRW_WUNLOCK();
719 return (ENOMEM);
720 }
721
722 TASK_INIT(&V_task, 0, ip_mrouter_upcall_thread, curvnet);
723 taskqueue_cancel(V_task_queue, &V_task, NULL);
724 taskqueue_unblock(V_task_queue);
725
727 curvnet);
729 curvnet);
730
731 V_ip_mrouter = so;
732 atomic_add_int(&ip_mrouter_cnt, 1);
733
734 /* This is a mutex required by buf_ring init, but not used internally */
735 mtx_init(&V_buf_ring_mtx, "mroute buf_ring mtx", NULL, MTX_DEF);
736
737 MRW_WUNLOCK();
738
739 CTR1(KTR_IPMF, "%s: done", __func__);
740
741 return 0;
742}
743
744/*
745 * Disable multicast forwarding.
746 */
747static int
749{
750 struct ifnet *ifp;
751 u_long i;
752 vifi_t vifi;
753 struct bw_upcall *bu;
754
755 if (V_ip_mrouter == NULL)
756 return (EINVAL);
757
758 /*
759 * Detach/disable hooks to the reset of the system.
760 */
761 V_ip_mrouter = NULL;
762 atomic_subtract_int(&ip_mrouter_cnt, 1);
764
765 /*
766 * Wait for all epoch sections to complete to ensure
767 * V_ip_mrouter = NULL is visible to others.
768 */
769 epoch_wait_preempt(net_epoch_preempt);
770
771 /* Stop and drain task queue */
772 taskqueue_block(V_task_queue);
773 while (taskqueue_cancel(V_task_queue, &V_task, NULL)) {
774 taskqueue_drain(V_task_queue, &V_task);
775 }
776
777 MRW_WLOCK();
778 taskqueue_cancel(V_task_queue, &V_task, NULL);
779
780 /* Destroy upcall ring */
781 while ((bu = buf_ring_dequeue_mc(V_bw_upcalls_ring)) != NULL) {
782 free(bu, M_MRTABLE);
783 }
784 buf_ring_free(V_bw_upcalls_ring, M_MRTABLE);
785 mtx_destroy(&V_bw_upcalls_ring_mtx);
786
787 /*
788 * For each phyint in use, disable promiscuous reception of all IP
789 * multicasts.
790 */
791 for (vifi = 0; vifi < V_numvifs; vifi++) {
792 if (!in_nullhost(V_viftable[vifi].v_lcl_addr) &&
793 !(V_viftable[vifi].v_flags & (VIFF_TUNNEL | VIFF_REGISTER))) {
794 ifp = V_viftable[vifi].v_ifp;
795 if_allmulti(ifp, 0);
796 }
797 }
798 bzero((caddr_t)V_viftable, sizeof(*V_viftable) * MAXVIFS);
799 V_numvifs = 0;
801
802 callout_stop(&V_expire_upcalls_ch);
803 callout_stop(&V_bw_upcalls_ch);
804
805 /*
806 * Free all multicast forwarding cache entries.
807 * Do not use hashdestroy(), as we must perform other cleanup.
808 */
809 for (i = 0; i < mfchashsize; i++) {
810 struct mfc *rt, *nrt;
811
812 LIST_FOREACH_SAFE(rt, &V_mfchashtbl[i], mfc_hash, nrt) {
813 expire_mfc(rt);
814 }
815 }
816 free(V_mfchashtbl, M_MRTABLE);
817 V_mfchashtbl = NULL;
818
819 bzero(V_nexpire, sizeof(V_nexpire[0]) * mfchashsize);
820
822
823 mtx_destroy(&V_buf_ring_mtx);
824
825 MRW_WUNLOCK();
826
827 CTR1(KTR_IPMF, "%s: done", __func__);
828
829 return 0;
830}
831
832/*
833 * Set PIM assert processing global
834 */
835static int
837{
838 if ((i != 1) && (i != 0))
839 return EINVAL;
840
842
843 return 0;
844}
845
846/*
847 * Configure API capabilities
848 */
849int
851{
852 u_long i;
853
854 /*
855 * We can set the API capabilities only if it is the first operation
856 * after MRT_INIT. I.e.:
857 * - there are no vifs installed
858 * - pim_assert is not enabled
859 * - the MFC table is empty
860 */
861 if (V_numvifs > 0) {
862 *apival = 0;
863 return EPERM;
864 }
866 *apival = 0;
867 return EPERM;
868 }
869
870 MRW_RLOCK();
871
872 for (i = 0; i < mfchashsize; i++) {
873 if (LIST_FIRST(&V_mfchashtbl[i]) != NULL) {
874 MRW_RUNLOCK();
875 *apival = 0;
876 return EPERM;
877 }
878 }
879
880 MRW_RUNLOCK();
881
883 *apival = V_mrt_api_config;
884
885 return 0;
886}
887
888/*
889 * Add a vif to the vif table
890 */
891static int
892add_vif(struct vifctl *vifcp)
893{
894 struct vif *vifp = V_viftable + vifcp->vifc_vifi;
895 struct sockaddr_in sin = {sizeof sin, AF_INET};
896 struct ifaddr *ifa;
897 struct ifnet *ifp;
898 int error;
899
900
901 if (vifcp->vifc_vifi >= MAXVIFS)
902 return EINVAL;
903 /* rate limiting is no longer supported by this code */
904 if (vifcp->vifc_rate_limit != 0) {
905 log(LOG_ERR, "rate limiting is no longer supported\n");
906 return EINVAL;
907 }
908
909 if (in_nullhost(vifcp->vifc_lcl_addr))
910 return EADDRNOTAVAIL;
911
912 /* Find the interface with an address in AF_INET family */
913 if (vifcp->vifc_flags & VIFF_REGISTER) {
914 /*
915 * XXX: Because VIFF_REGISTER does not really need a valid
916 * local interface (e.g. it could be 127.0.0.2), we don't
917 * check its address.
918 */
919 ifp = NULL;
920 } else {
921 struct epoch_tracker et;
922
923 sin.sin_addr = vifcp->vifc_lcl_addr;
924 NET_EPOCH_ENTER(et);
925 ifa = ifa_ifwithaddr((struct sockaddr *)&sin);
926 if (ifa == NULL) {
927 NET_EPOCH_EXIT(et);
928 return EADDRNOTAVAIL;
929 }
930 ifp = ifa->ifa_ifp;
931 /* XXX FIXME we need to take a ref on ifp and cleanup properly! */
932 NET_EPOCH_EXIT(et);
933 }
934
935 if ((vifcp->vifc_flags & VIFF_TUNNEL) != 0) {
936 CTR1(KTR_IPMF, "%s: tunnels are no longer supported", __func__);
937 return EOPNOTSUPP;
938 } else if (vifcp->vifc_flags & VIFF_REGISTER) {
939 ifp = V_multicast_register_if = if_alloc(IFT_LOOP);
940 CTR2(KTR_IPMF, "%s: add register vif for ifp %p", __func__, ifp);
942 if_initname(V_multicast_register_if, "register_vif", 0);
943 V_reg_vif_num = vifcp->vifc_vifi;
944 }
945 } else { /* Make sure the interface supports multicast */
946 if ((ifp->if_flags & IFF_MULTICAST) == 0)
947 return EOPNOTSUPP;
948
949 /* Enable promiscuous reception of all IP multicasts from the if */
950 error = if_allmulti(ifp, 1);
951 if (error)
952 return error;
953 }
954
955 MRW_WLOCK();
956
957 if (!in_nullhost(vifp->v_lcl_addr)) {
958 if (ifp)
960 MRW_WUNLOCK();
961 if (ifp)
962 if_free(ifp);
963 return EADDRINUSE;
964 }
965
966 vifp->v_flags = vifcp->vifc_flags;
967 vifp->v_threshold = vifcp->vifc_threshold;
968 vifp->v_lcl_addr = vifcp->vifc_lcl_addr;
969 vifp->v_rmt_addr = vifcp->vifc_rmt_addr;
970 vifp->v_ifp = ifp;
971 /* initialize per vif pkt counters */
972 vifp->v_pkt_in = 0;
973 vifp->v_pkt_out = 0;
974 vifp->v_bytes_in = 0;
975 vifp->v_bytes_out = 0;
976 sprintf(vifp->v_spin_name, "BM[%d] spin", vifcp->vifc_vifi);
977 mtx_init(&vifp->v_spin, vifp->v_spin_name, NULL, MTX_SPIN);
978
979 /* Adjust numvifs up if the vifi is higher than numvifs */
980 if (V_numvifs <= vifcp->vifc_vifi)
981 V_numvifs = vifcp->vifc_vifi + 1;
982
983 MRW_WUNLOCK();
984
985 CTR4(KTR_IPMF, "%s: add vif %d laddr 0x%08x thresh %x", __func__,
986 (int)vifcp->vifc_vifi, ntohl(vifcp->vifc_lcl_addr.s_addr),
987 (int)vifcp->vifc_threshold);
988
989 return 0;
990}
991
992/*
993 * Delete a vif from the vif table
994 */
995static int
996del_vif_locked(vifi_t vifi, struct ifnet **ifp_free)
997{
998 struct vif *vifp;
999
1000 *ifp_free = NULL;
1001
1003
1004 if (vifi >= V_numvifs) {
1005 return EINVAL;
1006 }
1007 vifp = &V_viftable[vifi];
1008 if (in_nullhost(vifp->v_lcl_addr)) {
1009 return EADDRNOTAVAIL;
1010 }
1011
1012 if (!(vifp->v_flags & (VIFF_TUNNEL | VIFF_REGISTER)))
1013 if_allmulti(vifp->v_ifp, 0);
1014
1015 if (vifp->v_flags & VIFF_REGISTER) {
1017 if (vifp->v_ifp) {
1018 if (vifp->v_ifp == V_multicast_register_if)
1020 *ifp_free = vifp->v_ifp;
1021 }
1022 }
1023
1024 mtx_destroy(&vifp->v_spin);
1025
1026 bzero((caddr_t)vifp, sizeof (*vifp));
1027
1028 CTR2(KTR_IPMF, "%s: delete vif %d", __func__, (int)vifi);
1029
1030 /* Adjust numvifs down */
1031 for (vifi = V_numvifs; vifi > 0; vifi--)
1032 if (!in_nullhost(V_viftable[vifi-1].v_lcl_addr))
1033 break;
1034 V_numvifs = vifi;
1035
1036 return 0;
1037}
1038
1039static int
1041{
1042 int cc;
1043 struct ifnet *free_ptr;
1044
1045 MRW_WLOCK();
1046 cc = del_vif_locked(vifi, &free_ptr);
1047 MRW_WUNLOCK();
1048
1049 if (free_ptr)
1050 if_free(free_ptr);
1051
1052 return cc;
1053}
1054
1055/*
1056 * update an mfc entry without resetting counters and S,G addresses.
1057 */
1058static void
1059update_mfc_params(struct mfc *rt, struct mfcctl2 *mfccp)
1060{
1061 int i;
1062
1063 rt->mfc_parent = mfccp->mfcc_parent;
1064 for (i = 0; i < V_numvifs; i++) {
1065 rt->mfc_ttls[i] = mfccp->mfcc_ttls[i];
1066 rt->mfc_flags[i] = mfccp->mfcc_flags[i] & V_mrt_api_config &
1068 }
1069 /* set the RP address */
1071 rt->mfc_rp = mfccp->mfcc_rp;
1072 else
1073 rt->mfc_rp.s_addr = INADDR_ANY;
1074}
1075
1076/*
1077 * fully initialize an mfc entry from the parameter.
1078 */
1079static void
1080init_mfc_params(struct mfc *rt, struct mfcctl2 *mfccp)
1081{
1082 rt->mfc_origin = mfccp->mfcc_origin;
1083 rt->mfc_mcastgrp = mfccp->mfcc_mcastgrp;
1084
1085 update_mfc_params(rt, mfccp);
1086
1087 /* initialize pkt counters per src-grp */
1088 rt->mfc_pkt_cnt = 0;
1089 rt->mfc_byte_cnt = 0;
1090 rt->mfc_wrong_if = 0;
1091 timevalclear(&rt->mfc_last_assert);
1092}
1093
1094static void
1095expire_mfc(struct mfc *rt)
1096{
1097 struct rtdetq *rte;
1098
1100
1103
1104 while (!buf_ring_empty(rt->mfc_stall_ring)) {
1105 rte = buf_ring_dequeue_mc(rt->mfc_stall_ring);
1106 if (rte) {
1107 m_freem(rte->m);
1108 free(rte, M_MRTABLE);
1109 }
1110 }
1111 buf_ring_free(rt->mfc_stall_ring, M_MRTABLE);
1112
1113 LIST_REMOVE(rt, mfc_hash);
1114 free(rt, M_MRTABLE);
1115}
1116
1117/*
1118 * Add an mfc entry
1119 */
1120static int
1121add_mfc(struct mfcctl2 *mfccp)
1122{
1123 struct mfc *rt;
1124 struct rtdetq *rte;
1125 u_long hash = 0;
1126 u_short nstl;
1127
1128 MRW_WLOCK();
1129 rt = mfc_find(&mfccp->mfcc_origin, &mfccp->mfcc_mcastgrp);
1130
1131 /* If an entry already exists, just update the fields */
1132 if (rt) {
1133 CTR4(KTR_IPMF, "%s: update mfc orig 0x%08x group %lx parent %x",
1134 __func__, ntohl(mfccp->mfcc_origin.s_addr),
1135 (u_long)ntohl(mfccp->mfcc_mcastgrp.s_addr),
1136 mfccp->mfcc_parent);
1137 update_mfc_params(rt, mfccp);
1138 MRW_WUNLOCK();
1139 return (0);
1140 }
1141
1142 /*
1143 * Find the entry for which the upcall was made and update
1144 */
1145 nstl = 0;
1146 hash = MFCHASH(mfccp->mfcc_origin, mfccp->mfcc_mcastgrp);
1147 LIST_FOREACH(rt, &V_mfchashtbl[hash], mfc_hash) {
1148 if (in_hosteq(rt->mfc_origin, mfccp->mfcc_origin) &&
1149 in_hosteq(rt->mfc_mcastgrp, mfccp->mfcc_mcastgrp) &&
1150 !buf_ring_empty(rt->mfc_stall_ring)) {
1151 CTR5(KTR_IPMF,
1152 "%s: add mfc orig 0x%08x group %lx parent %x qh %p",
1153 __func__, ntohl(mfccp->mfcc_origin.s_addr),
1154 (u_long)ntohl(mfccp->mfcc_mcastgrp.s_addr),
1155 mfccp->mfcc_parent,
1156 rt->mfc_stall_ring);
1157 if (nstl++)
1158 CTR1(KTR_IPMF, "%s: multiple matches", __func__);
1159
1160 init_mfc_params(rt, mfccp);
1161 rt->mfc_expire = 0; /* Don't clean this guy up */
1162 V_nexpire[hash]--;
1163
1164 /* Free queued packets, but attempt to forward them first. */
1165 while (!buf_ring_empty(rt->mfc_stall_ring)) {
1166 rte = buf_ring_dequeue_mc(rt->mfc_stall_ring);
1167 if (rte->ifp != NULL)
1168 ip_mdq(rte->m, rte->ifp, rt, -1);
1169 m_freem(rte->m);
1170 free(rte, M_MRTABLE);
1171 }
1172 }
1173 }
1174
1175 /*
1176 * It is possible that an entry is being inserted without an upcall
1177 */
1178 if (nstl == 0) {
1179 CTR1(KTR_IPMF, "%s: adding mfc w/o upcall", __func__);
1180 LIST_FOREACH(rt, &V_mfchashtbl[hash], mfc_hash) {
1181 if (in_hosteq(rt->mfc_origin, mfccp->mfcc_origin) &&
1182 in_hosteq(rt->mfc_mcastgrp, mfccp->mfcc_mcastgrp)) {
1183 init_mfc_params(rt, mfccp);
1184 if (rt->mfc_expire)
1185 V_nexpire[hash]--;
1186 rt->mfc_expire = 0;
1187 break; /* XXX */
1188 }
1189 }
1190
1191 if (rt == NULL) { /* no upcall, so make a new entry */
1192 rt = mfc_alloc();
1193 if (rt == NULL) {
1194 MRW_WUNLOCK();
1195 return (ENOBUFS);
1196 }
1197
1198 init_mfc_params(rt, mfccp);
1199
1200 rt->mfc_expire = 0;
1201 rt->mfc_bw_meter_leq = NULL;
1202 rt->mfc_bw_meter_geq = NULL;
1203
1204 /* insert new entry at head of hash chain */
1205 LIST_INSERT_HEAD(&V_mfchashtbl[hash], rt, mfc_hash);
1206 }
1207 }
1208
1209 MRW_WUNLOCK();
1210
1211 return (0);
1212}
1213
1214/*
1215 * Delete an mfc entry
1216 */
1217static int
1218del_mfc(struct mfcctl2 *mfccp)
1219{
1220 struct in_addr origin;
1221 struct in_addr mcastgrp;
1222 struct mfc *rt;
1223
1224 origin = mfccp->mfcc_origin;
1225 mcastgrp = mfccp->mfcc_mcastgrp;
1226
1227 CTR3(KTR_IPMF, "%s: delete mfc orig 0x%08x group %lx", __func__,
1228 ntohl(origin.s_addr), (u_long)ntohl(mcastgrp.s_addr));
1229
1230 MRW_WLOCK();
1231
1232 rt = mfc_find(&origin, &mcastgrp);
1233 if (rt == NULL) {
1234 MRW_WUNLOCK();
1235 return EADDRNOTAVAIL;
1236 }
1237
1238 /*
1239 * free the bw_meter entries
1240 */
1242 rt->mfc_bw_meter_leq = NULL;
1244 rt->mfc_bw_meter_geq = NULL;
1245
1246 LIST_REMOVE(rt, mfc_hash);
1247 free(rt, M_MRTABLE);
1248
1249 MRW_WUNLOCK();
1250
1251 return (0);
1252}
1253
1254/*
1255 * Send a message to the routing daemon on the multicast routing socket.
1256 */
1257static int
1258socket_send(struct socket *s, struct mbuf *mm, struct sockaddr_in *src)
1259{
1260 if (s) {
1261 SOCKBUF_LOCK(&s->so_rcv);
1262 if (sbappendaddr_locked(&s->so_rcv, (struct sockaddr *)src, mm,
1263 NULL) != 0) {
1264 sorwakeup_locked(s);
1265 return 0;
1266 }
1267 soroverflow_locked(s);
1268 }
1269 m_freem(mm);
1270 return -1;
1271}
1272
1273/*
1274 * IP multicast forwarding function. This function assumes that the packet
1275 * pointed to by "ip" has arrived on (or is about to be sent to) the interface
1276 * pointed to by "ifp", and the packet is to be relayed to other networks
1277 * that have members of the packet's destination IP multicast group.
1278 *
1279 * The packet is returned unscathed to the caller, unless it is
1280 * erroneous, in which case a non-zero return value tells the caller to
1281 * discard it.
1282 */
1283
1284#define TUNNEL_LEN 12 /* # bytes of IP option for tunnel encapsulation */
1285
1286static int
1287X_ip_mforward(struct ip *ip, struct ifnet *ifp, struct mbuf *m,
1288 struct ip_moptions *imo)
1289{
1290 struct mfc *rt;
1291 int error;
1292 vifi_t vifi;
1293 struct mbuf *mb0;
1294 struct rtdetq *rte;
1295 u_long hash;
1296 int hlen;
1297
1298 CTR3(KTR_IPMF, "ip_mforward: delete mfc orig 0x%08x group %lx ifp %p",
1299 ntohl(ip->ip_src.s_addr), (u_long)ntohl(ip->ip_dst.s_addr), ifp);
1300
1301 if (ip->ip_hl < (sizeof(struct ip) + TUNNEL_LEN) >> 2 ||
1302 ((u_char *)(ip + 1))[1] != IPOPT_LSRR) {
1303 /*
1304 * Packet arrived via a physical interface or
1305 * an encapsulated tunnel or a register_vif.
1306 */
1307 } else {
1308 /*
1309 * Packet arrived through a source-route tunnel.
1310 * Source-route tunnels are no longer supported.
1311 */
1312 return (1);
1313 }
1314
1315 /*
1316 * BEGIN: MCAST ROUTING HOT PATH
1317 */
1318 MRW_RLOCK();
1319 if (imo && ((vifi = imo->imo_multicast_vif) < V_numvifs)) {
1320 if (ip->ip_ttl < MAXTTL)
1321 ip->ip_ttl++; /* compensate for -1 in *_send routines */
1322 error = ip_mdq(m, ifp, NULL, vifi);
1323 MRW_RUNLOCK();
1324 return error;
1325 }
1326
1327 /*
1328 * Don't forward a packet with time-to-live of zero or one,
1329 * or a packet destined to a local-only group.
1330 */
1331 if (ip->ip_ttl <= 1 || IN_LOCAL_GROUP(ntohl(ip->ip_dst.s_addr))) {
1332 MRW_RUNLOCK();
1333 return 0;
1334 }
1335
1336 mfc_find_retry:
1337 /*
1338 * Determine forwarding vifs from the forwarding cache table
1339 */
1340 MRTSTAT_INC(mrts_mfc_lookups);
1341 rt = mfc_find(&ip->ip_src, &ip->ip_dst);
1342
1343 /* Entry exists, so forward if necessary */
1344 if (rt != NULL) {
1345 error = ip_mdq(m, ifp, rt, -1);
1346 /* Generic unlock here as we might release R or W lock */
1347 MRW_UNLOCK();
1348 return error;
1349 }
1350
1351 /*
1352 * END: MCAST ROUTING HOT PATH
1353 */
1354
1355 /* Further processing must be done with WLOCK taken */
1356 if ((MRW_WOWNED() == 0) && (MRW_LOCK_TRY_UPGRADE() == 0)) {
1357 MRW_RUNLOCK();
1358 MRW_WLOCK();
1359 goto mfc_find_retry;
1360 }
1361
1362 /*
1363 * If we don't have a route for packet's origin,
1364 * Make a copy of the packet & send message to routing daemon
1365 */
1366 hlen = ip->ip_hl << 2;
1367
1368 MRTSTAT_INC(mrts_mfc_misses);
1369 MRTSTAT_INC(mrts_no_route);
1370 CTR2(KTR_IPMF, "ip_mforward: no mfc for (0x%08x,%lx)",
1371 ntohl(ip->ip_src.s_addr), (u_long)ntohl(ip->ip_dst.s_addr));
1372
1373 /*
1374 * Allocate mbufs early so that we don't do extra work if we are
1375 * just going to fail anyway. Make sure to pullup the header so
1376 * that other people can't step on it.
1377 */
1378 rte = (struct rtdetq*) malloc((sizeof *rte), M_MRTABLE,
1379 M_NOWAIT|M_ZERO);
1380 if (rte == NULL) {
1381 MRW_WUNLOCK();
1382 return ENOBUFS;
1383 }
1384
1385 mb0 = m_copypacket(m, M_NOWAIT);
1386 if (mb0 && (!M_WRITABLE(mb0) || mb0->m_len < hlen))
1387 mb0 = m_pullup(mb0, hlen);
1388 if (mb0 == NULL) {
1389 free(rte, M_MRTABLE);
1390 MRW_WUNLOCK();
1391 return ENOBUFS;
1392 }
1393
1394 /* is there an upcall waiting for this flow ? */
1395 hash = MFCHASH(ip->ip_src, ip->ip_dst);
1396 LIST_FOREACH(rt, &V_mfchashtbl[hash], mfc_hash)
1397 {
1398 if (in_hosteq(ip->ip_src, rt->mfc_origin) &&
1400 !buf_ring_empty(rt->mfc_stall_ring))
1401 break;
1402 }
1403
1404 if (rt == NULL) {
1405 int i;
1406 struct igmpmsg *im;
1407 struct sockaddr_in k_igmpsrc = { sizeof k_igmpsrc, AF_INET };
1408 struct mbuf *mm;
1409
1410 /*
1411 * Locate the vifi for the incoming interface for this packet.
1412 * If none found, drop packet.
1413 */
1414 for (vifi = 0; vifi < V_numvifs &&
1415 V_viftable[vifi].v_ifp != ifp; vifi++)
1416 ;
1417 if (vifi >= V_numvifs) /* vif not found, drop packet */
1418 goto non_fatal;
1419
1420 /* no upcall, so make a new entry */
1421 rt = mfc_alloc();
1422 if (rt == NULL)
1423 goto fail;
1424
1425 /* Make a copy of the header to send to the user level process */
1426 mm = m_copym(mb0, 0, hlen, M_NOWAIT);
1427 if (mm == NULL)
1428 goto fail1;
1429
1430 /*
1431 * Send message to routing daemon to install
1432 * a route into the kernel table
1433 */
1434
1435 im = mtod(mm, struct igmpmsg*);
1437 im->im_mbz = 0;
1438 im->im_vif = vifi;
1439
1440 MRTSTAT_INC(mrts_upcalls);
1441
1442 k_igmpsrc.sin_addr = ip->ip_src;
1443 if (socket_send(V_ip_mrouter, mm, &k_igmpsrc) < 0) {
1444 CTR0(KTR_IPMF, "ip_mforward: socket queue full");
1445 MRTSTAT_INC(mrts_upq_sockfull);
1446 fail1: free(rt, M_MRTABLE);
1447 fail: free(rte, M_MRTABLE);
1448 m_freem(mb0);
1449 MRW_WUNLOCK();
1450 return ENOBUFS;
1451 }
1452
1453 /* insert new entry at head of hash chain */
1454 rt->mfc_origin.s_addr = ip->ip_src.s_addr;
1457 V_nexpire[hash]++;
1458 for (i = 0; i < V_numvifs; i++) {
1459 rt->mfc_ttls[i] = 0;
1460 rt->mfc_flags[i] = 0;
1461 }
1462 rt->mfc_parent = -1;
1463
1464 /* clear the RP address */
1465 rt->mfc_rp.s_addr = INADDR_ANY;
1466 rt->mfc_bw_meter_leq = NULL;
1467 rt->mfc_bw_meter_geq = NULL;
1468
1469 /* initialize pkt counters per src-grp */
1470 rt->mfc_pkt_cnt = 0;
1471 rt->mfc_byte_cnt = 0;
1472 rt->mfc_wrong_if = 0;
1473 timevalclear(&rt->mfc_last_assert);
1474
1475 buf_ring_enqueue(rt->mfc_stall_ring, rte);
1476
1477 /* Add RT to hashtable as it didn't exist before */
1478 LIST_INSERT_HEAD(&V_mfchashtbl[hash], rt, mfc_hash);
1479 } else {
1480 /* determine if queue has overflowed */
1481 if (buf_ring_full(rt->mfc_stall_ring)) {
1482 MRTSTAT_INC(mrts_upq_ovflw);
1483 non_fatal: free(rte, M_MRTABLE);
1484 m_freem(mb0);
1485 MRW_WUNLOCK();
1486 return (0);
1487 }
1488
1489 buf_ring_enqueue(rt->mfc_stall_ring, rte);
1490 }
1491
1492 rte->m = mb0;
1493 rte->ifp = ifp;
1494
1495 MRW_WUNLOCK();
1496
1497 return 0;
1498}
1499
1500/*
1501 * Clean up the cache entry if upcall is not serviced
1502 */
1503static void
1505{
1506 u_long i;
1507
1508 CURVNET_SET((struct vnet *) arg);
1509
1510 /*This callout is always run with MRW_WLOCK taken. */
1511
1512 for (i = 0; i < mfchashsize; i++) {
1513 struct mfc *rt, *nrt;
1514
1515 if (V_nexpire[i] == 0)
1516 continue;
1517
1518 LIST_FOREACH_SAFE(rt, &V_mfchashtbl[i], mfc_hash, nrt) {
1519 if (buf_ring_empty(rt->mfc_stall_ring))
1520 continue;
1521
1522 if (rt->mfc_expire == 0 || --rt->mfc_expire > 0)
1523 continue;
1524
1525 MRTSTAT_INC(mrts_cache_cleanups);
1526 CTR3(KTR_IPMF, "%s: expire (%lx, %lx)", __func__,
1527 (u_long)ntohl(rt->mfc_origin.s_addr),
1528 (u_long)ntohl(rt->mfc_mcastgrp.s_addr));
1529
1530 expire_mfc(rt);
1531 }
1532 }
1533
1535 curvnet);
1536
1537 CURVNET_RESTORE();
1538}
1539
1540/*
1541 * Packet forwarding routine once entry in the cache is made
1542 */
1543static int
1544ip_mdq(struct mbuf *m, struct ifnet *ifp, struct mfc *rt, vifi_t xmt_vif)
1545{
1546 struct ip *ip = mtod(m, struct ip *);
1547 vifi_t vifi;
1548 int plen = ntohs(ip->ip_len);
1549
1551
1552 /*
1553 * If xmt_vif is not -1, send on only the requested vif.
1554 *
1555 * (since vifi_t is u_short, -1 becomes MAXUSHORT, which > numvifs.)
1556 */
1557 if (xmt_vif < V_numvifs) {
1558 if (V_viftable[xmt_vif].v_flags & VIFF_REGISTER)
1559 pim_register_send(ip, V_viftable + xmt_vif, m, rt);
1560 else
1561 phyint_send(ip, V_viftable + xmt_vif, m);
1562 return 1;
1563 }
1564
1565 /*
1566 * Don't forward if it didn't arrive from the parent vif for its origin.
1567 */
1568 vifi = rt->mfc_parent;
1569 if ((vifi >= V_numvifs) || (V_viftable[vifi].v_ifp != ifp)) {
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);
1572 MRTSTAT_INC(mrts_wrong_if);
1573 ++rt->mfc_wrong_if;
1574 /*
1575 * If we are doing PIM assert processing, send a message
1576 * to the routing daemon.
1577 *
1578 * XXX: A PIM-SM router needs the WRONGVIF detection so it
1579 * can complete the SPT switch, regardless of the type
1580 * of the iif (broadcast media, GRE tunnel, etc).
1581 */
1582 if (V_pim_assert_enabled && (vifi < V_numvifs) &&
1583 V_viftable[vifi].v_ifp) {
1584 if (ifp == V_multicast_register_if)
1585 PIMSTAT_INC(pims_rcv_registers_wrongiif);
1586
1587 /* Get vifi for the incoming packet */
1588 for (vifi = 0; vifi < V_numvifs && V_viftable[vifi].v_ifp != ifp;
1589 vifi++)
1590 ;
1591 if (vifi >= V_numvifs)
1592 return 0; /* The iif is not found: ignore the packet. */
1593
1595 return 0; /* WRONGVIF disabled: ignore the packet */
1596
1597 if (ratecheck(&rt->mfc_last_assert, &pim_assert_interval)) {
1598 struct sockaddr_in k_igmpsrc = { sizeof k_igmpsrc, AF_INET };
1599 struct igmpmsg *im;
1600 int hlen = ip->ip_hl << 2;
1601 struct mbuf *mm = m_copym(m, 0, hlen, M_NOWAIT);
1602
1603 if (mm && (!M_WRITABLE(mm) || mm->m_len < hlen))
1604 mm = m_pullup(mm, hlen);
1605 if (mm == NULL)
1606 return ENOBUFS;
1607
1608 im = mtod(mm, struct igmpmsg *);
1610 im->im_mbz = 0;
1611 im->im_vif = vifi;
1612
1613 MRTSTAT_INC(mrts_upcalls);
1614
1615 k_igmpsrc.sin_addr = im->im_src;
1616 if (socket_send(V_ip_mrouter, mm, &k_igmpsrc) < 0) {
1617 CTR1(KTR_IPMF, "%s: socket queue full", __func__);
1618 MRTSTAT_INC(mrts_upq_sockfull);
1619 return ENOBUFS;
1620 }
1621 }
1622 }
1623 return 0;
1624 }
1625
1626 /* If I sourced this packet, it counts as output, else it was input. */
1627 mtx_lock_spin(&V_viftable[vifi].v_spin);
1628 if (in_hosteq(ip->ip_src, V_viftable[vifi].v_lcl_addr)) {
1629 V_viftable[vifi].v_pkt_out++;
1630 V_viftable[vifi].v_bytes_out += plen;
1631 } else {
1632 V_viftable[vifi].v_pkt_in++;
1633 V_viftable[vifi].v_bytes_in += plen;
1634 }
1635 mtx_unlock_spin(&V_viftable[vifi].v_spin);
1636
1637 rt->mfc_pkt_cnt++;
1638 rt->mfc_byte_cnt += plen;
1639
1640 /*
1641 * For each vif, decide if a copy of the packet should be forwarded.
1642 * Forward if:
1643 * - the ttl exceeds the vif's threshold
1644 * - there are group members downstream on interface
1645 */
1646 for (vifi = 0; vifi < V_numvifs; vifi++)
1647 if ((rt->mfc_ttls[vifi] > 0) && (ip->ip_ttl > rt->mfc_ttls[vifi])) {
1648 V_viftable[vifi].v_pkt_out++;
1649 V_viftable[vifi].v_bytes_out += plen;
1650 if (V_viftable[vifi].v_flags & VIFF_REGISTER)
1651 pim_register_send(ip, V_viftable + vifi, m, rt);
1652 else
1653 phyint_send(ip, V_viftable + vifi, m);
1654 }
1655
1656 /*
1657 * Perform upcall-related bw measuring.
1658 */
1659 if ((rt->mfc_bw_meter_geq != NULL) || (rt->mfc_bw_meter_leq != NULL)) {
1660 struct bw_meter *x;
1661 struct timeval now;
1662
1663 microtime(&now);
1664 /* Process meters for Greater-or-EQual case */
1665 for (x = rt->mfc_bw_meter_geq; x != NULL; x = x->bm_mfc_next)
1666 bw_meter_geq_receive_packet(x, plen, &now);
1667
1668 /* Process meters for Lower-or-EQual case */
1669 for (x = rt->mfc_bw_meter_leq; x != NULL; x = x->bm_mfc_next) {
1670 /*
1671 * Record that a packet is received.
1672 * Spin lock has to be taken as callout context
1673 * (expire_bw_meter_leq) might modify these fields
1674 * as well
1675 */
1676 mtx_lock_spin(&x->bm_spin);
1678 x->bm_measured.b_bytes += plen;
1679 mtx_unlock_spin(&x->bm_spin);
1680 }
1681 }
1682
1683 return 0;
1684}
1685
1686/*
1687 * Check if a vif number is legal/ok. This is used by in_mcast.c.
1688 */
1689static int
1691{
1692 int ret;
1693
1694 ret = 0;
1695 if (vif < 0)
1696 return (ret);
1697
1698 MRW_RLOCK();
1699 if (vif < V_numvifs)
1700 ret = 1;
1701 MRW_RUNLOCK();
1702
1703 return (ret);
1704}
1705
1706/*
1707 * Return the local address used by this vif
1708 */
1709static u_long
1711{
1712 in_addr_t addr;
1713
1714 addr = INADDR_ANY;
1715 if (vifi < 0)
1716 return (addr);
1717
1718 MRW_RLOCK();
1719 if (vifi < V_numvifs)
1720 addr = V_viftable[vifi].v_lcl_addr.s_addr;
1721 MRW_RUNLOCK();
1722
1723 return (addr);
1724}
1725
1726static void
1727phyint_send(struct ip *ip, struct vif *vifp, struct mbuf *m)
1728{
1729 struct mbuf *mb_copy;
1730 int hlen = ip->ip_hl << 2;
1731
1733
1734 /*
1735 * Make a new reference to the packet; make sure that
1736 * the IP header is actually copied, not just referenced,
1737 * so that ip_output() only scribbles on the copy.
1738 */
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)
1743 return;
1744
1745 send_packet(vifp, mb_copy);
1746}
1747
1748static void
1749send_packet(struct vif *vifp, struct mbuf *m)
1750{
1751 struct ip_moptions imo;
1752 int error __unused;
1753
1755
1756 imo.imo_multicast_ifp = vifp->v_ifp;
1757 imo.imo_multicast_ttl = mtod(m, struct ip *)->ip_ttl - 1;
1758 imo.imo_multicast_loop = !!in_mcast_loop;
1759 imo.imo_multicast_vif = -1;
1760 STAILQ_INIT(&imo.imo_head);
1761
1762 /*
1763 * Re-entrancy should not be a problem here, because
1764 * the packets that we send out and are looped back at us
1765 * should get rejected because they appear to come from
1766 * the loopback interface, thus preventing looping.
1767 */
1768 error = ip_output(m, NULL, NULL, IP_FORWARDING, &imo, NULL);
1769 CTR3(KTR_IPMF, "%s: vif %td err %d", __func__,
1770 (ptrdiff_t)(vifp - V_viftable), error);
1771}
1772
1773/*
1774 * Stubs for old RSVP socket shim implementation.
1775 */
1776
1777static int
1778X_ip_rsvp_vif(struct socket *so __unused, struct sockopt *sopt __unused)
1779{
1780
1781 return (EOPNOTSUPP);
1782}
1783
1784static void
1785X_ip_rsvp_force_done(struct socket *so __unused)
1786{
1787
1788}
1789
1790static int
1791X_rsvp_input(struct mbuf **mp, int *offp, int proto)
1792{
1793 struct mbuf *m;
1794
1795 m = *mp;
1796 *mp = NULL;
1797 if (!V_rsvp_on)
1798 m_freem(m);
1799 return (IPPROTO_DONE);
1800}
1801
1802/*
1803 * Code for bandwidth monitors
1804 */
1805
1806/*
1807 * Define common interface for timeval-related methods
1808 */
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))
1812
1813static uint32_t
1815{
1816 uint32_t flags = 0;
1817
1819 flags |= BW_METER_UNIT_PACKETS;
1820 if (req->bu_flags & BW_UPCALL_UNIT_BYTES)
1821 flags |= BW_METER_UNIT_BYTES;
1822 if (req->bu_flags & BW_UPCALL_GEQ)
1823 flags |= BW_METER_GEQ;
1824 if (req->bu_flags & BW_UPCALL_LEQ)
1825 flags |= BW_METER_LEQ;
1826
1827 return flags;
1828}
1829
1830static void
1832{
1833 struct bw_meter *x = arg;
1834 struct timeval now;
1835 /*
1836 * INFO:
1837 * callout is always executed with MRW_WLOCK taken
1838 */
1839
1840 CURVNET_SET((struct vnet *)x->arg);
1841
1842 microtime(&now);
1843
1844 /*
1845 * Test if we should deliver an upcall
1846 */
1847 if (((x->bm_flags & BW_METER_UNIT_PACKETS) &&
1849 ((x->bm_flags & BW_METER_UNIT_BYTES) &&
1851 /* Prepare an upcall for delivery */
1852 bw_meter_prepare_upcall(x, &now);
1853 }
1854
1855 /* Send all upcalls that are pending delivery */
1856 taskqueue_enqueue(V_task_queue, &V_task);
1857
1858 /* Reset counters */
1859 x->bm_start_time = now;
1860 /* Spin lock has to be taken as ip_forward context
1861 * might modify these fields as well
1862 */
1863 mtx_lock_spin(&x->bm_spin);
1864 x->bm_measured.b_bytes = 0;
1865 x->bm_measured.b_packets = 0;
1866 mtx_unlock_spin(&x->bm_spin);
1867
1868 callout_schedule(&x->bm_meter_callout, tvtohz(&x->bm_threshold.b_time));
1869
1870 CURVNET_RESTORE();
1871}
1872
1873/*
1874 * Add a bw_meter entry
1875 */
1876static int
1878{
1879 struct mfc *mfc;
1880 struct timeval delta = { BW_UPCALL_THRESHOLD_INTERVAL_MIN_SEC,
1882 struct timeval now;
1883 struct bw_meter *x, **bwm_ptr;
1884 uint32_t flags;
1885
1887 return EOPNOTSUPP;
1888
1889 /* Test if the flags are valid */
1891 return EINVAL;
1892 if (!(req->bu_flags & (BW_UPCALL_GEQ | BW_UPCALL_LEQ)))
1893 return EINVAL;
1894 if ((req->bu_flags & (BW_UPCALL_GEQ | BW_UPCALL_LEQ))
1896 return EINVAL;
1897
1898 /* Test if the threshold time interval is valid */
1899 if (BW_TIMEVALCMP(&req->bu_threshold.b_time, &delta, <))
1900 return EINVAL;
1901
1902 flags = compute_bw_meter_flags(req);
1903
1904 /*
1905 * Find if we have already same bw_meter entry
1906 */
1907 MRW_WLOCK();
1908 mfc = mfc_find(&req->bu_src, &req->bu_dst);
1909 if (mfc == NULL) {
1910 MRW_WUNLOCK();
1911 return EADDRNOTAVAIL;
1912 }
1913
1914 /* Choose an appropriate bw_meter list */
1915 if (req->bu_flags & BW_UPCALL_GEQ)
1916 bwm_ptr = &mfc->mfc_bw_meter_geq;
1917 else
1918 bwm_ptr = &mfc->mfc_bw_meter_leq;
1919
1920 for (x = *bwm_ptr; x != NULL; x = x->bm_mfc_next) {
1922 &req->bu_threshold.b_time, ==))
1923 && (x->bm_threshold.b_packets
1924 == req->bu_threshold.b_packets)
1925 && (x->bm_threshold.b_bytes
1926 == req->bu_threshold.b_bytes)
1928 == flags) {
1929 MRW_WUNLOCK();
1930 return 0; /* XXX Already installed */
1931 }
1932 }
1933
1934 /* Allocate the new bw_meter entry */
1935 x = (struct bw_meter*) malloc(sizeof(*x), M_BWMETER,
1936 M_ZERO | M_NOWAIT);
1937 if (x == NULL) {
1938 MRW_WUNLOCK();
1939 return ENOBUFS;
1940 }
1941
1942 /* Set the new bw_meter entry */
1944 microtime(&now);
1945 x->bm_start_time = now;
1948 x->bm_measured.b_packets = 0;
1949 x->bm_measured.b_bytes = 0;
1950 x->bm_flags = flags;
1951 x->bm_time_next = NULL;
1952 x->bm_mfc = mfc;
1953 x->arg = curvnet;
1954 sprintf(x->bm_spin_name, "BM spin %p", x);
1955 mtx_init(&x->bm_spin, x->bm_spin_name, NULL, MTX_SPIN);
1956
1957 /* For LEQ case create periodic callout */
1958 if (req->bu_flags & BW_UPCALL_LEQ) {
1959 callout_init_rw(&x->bm_meter_callout, &mrouter_mtx, CALLOUT_SHAREDLOCK);
1960 callout_reset(&x->bm_meter_callout, tvtohz(&x->bm_threshold.b_time),
1962 }
1963
1964 /* Add the new bw_meter entry to the front of entries for this MFC */
1965 x->bm_mfc_next = *bwm_ptr;
1966 *bwm_ptr = x;
1967
1968 MRW_WUNLOCK();
1969
1970 return 0;
1971}
1972
1973static void
1975{
1976 while (list != NULL) {
1977 struct bw_meter *x = list;
1978
1979 /* MRW_WLOCK must be held here */
1980 if (x->bm_flags & BW_METER_LEQ) {
1981 callout_drain(&x->bm_meter_callout);
1982 mtx_destroy(&x->bm_spin);
1983 }
1984
1985 list = list->bm_mfc_next;
1986 free(x, M_BWMETER);
1987 }
1988}
1989
1990/*
1991 * Delete one or multiple bw_meter entries
1992 */
1993static int
1995{
1996 struct mfc *mfc;
1997 struct bw_meter *x, **bwm_ptr;
1998
2000 return EOPNOTSUPP;
2001
2002 MRW_WLOCK();
2003
2004 /* Find the corresponding MFC entry */
2005 mfc = mfc_find(&req->bu_src, &req->bu_dst);
2006 if (mfc == NULL) {
2007 MRW_WUNLOCK();
2008 return EADDRNOTAVAIL;
2009 } else if (req->bu_flags & BW_UPCALL_DELETE_ALL) {
2010 /*
2011 * Delete all bw_meter entries for this mfc
2012 */
2013 struct bw_meter *list;
2014
2015 /* Free LEQ list */
2016 list = mfc->mfc_bw_meter_leq;
2017 mfc->mfc_bw_meter_leq = NULL;
2018 free_bw_list(list);
2019
2020 /* Free GEQ list */
2021 list = mfc->mfc_bw_meter_geq;
2022 mfc->mfc_bw_meter_geq = NULL;
2023 free_bw_list(list);
2024 MRW_WUNLOCK();
2025 return 0;
2026 } else { /* Delete a single bw_meter entry */
2027 struct bw_meter *prev;
2028 uint32_t flags = 0;
2029
2030 flags = compute_bw_meter_flags(req);
2031
2032 /* Choose an appropriate bw_meter list */
2033 if (req->bu_flags & BW_UPCALL_GEQ)
2034 bwm_ptr = &mfc->mfc_bw_meter_geq;
2035 else
2036 bwm_ptr = &mfc->mfc_bw_meter_leq;
2037
2038 /* Find the bw_meter entry to delete */
2039 for (prev = NULL, x = *bwm_ptr; x != NULL;
2040 prev = x, x = x->bm_mfc_next) {
2041 if ((BW_TIMEVALCMP(&x->bm_threshold.b_time,
2042 &req->bu_threshold.b_time, ==)) &&
2043 (x->bm_threshold.b_packets == req->bu_threshold.b_packets) &&
2044 (x->bm_threshold.b_bytes == req->bu_threshold.b_bytes) &&
2045 (x->bm_flags & BW_METER_USER_FLAGS) == flags)
2046 break;
2047 }
2048 if (x != NULL) { /* Delete entry from the list for this MFC */
2049 if (prev != NULL)
2050 prev->bm_mfc_next = x->bm_mfc_next; /* remove from middle*/
2051 else
2052 *bwm_ptr = x->bm_mfc_next;/* new head of list */
2053
2054 if (req->bu_flags & BW_UPCALL_LEQ)
2055 callout_stop(&x->bm_meter_callout);
2056
2057 MRW_WUNLOCK();
2058 /* Free the bw_meter entry */
2059 free(x, M_BWMETER);
2060 return 0;
2061 } else {
2062 MRW_WUNLOCK();
2063 return EINVAL;
2064 }
2065 }
2066 /* NOTREACHED */
2067}
2068
2069/*
2070 * Perform bandwidth measurement processing that may result in an upcall
2071 */
2072static void
2073bw_meter_geq_receive_packet(struct bw_meter *x, int plen, struct timeval *nowp)
2074{
2075 struct timeval delta;
2076
2078
2079 delta = *nowp;
2080 BW_TIMEVALDECR(&delta, &x->bm_start_time);
2081
2082 /*
2083 * Processing for ">=" type of bw_meter entry.
2084 * bm_spin does not have to be hold here as in GEQ
2085 * case this is the only context accessing bm_measured.
2086 */
2087 if (BW_TIMEVALCMP(&delta, &x->bm_threshold.b_time, >)) {
2088 /* Reset the bw_meter entry */
2089 x->bm_start_time = *nowp;
2090 x->bm_measured.b_packets = 0;
2091 x->bm_measured.b_bytes = 0;
2092 x->bm_flags &= ~BW_METER_UPCALL_DELIVERED;
2093 }
2094
2095 /* Record that a packet is received */
2097 x->bm_measured.b_bytes += plen;
2098
2099 /*
2100 * Test if we should deliver an upcall
2101 */
2102 if (!(x->bm_flags & BW_METER_UPCALL_DELIVERED)) {
2103 if (((x->bm_flags & BW_METER_UNIT_PACKETS) &&
2105 ((x->bm_flags & BW_METER_UNIT_BYTES) &&
2107 /* Prepare an upcall for delivery */
2108 bw_meter_prepare_upcall(x, nowp);
2110 }
2111 }
2112}
2113
2114/*
2115 * Prepare a bandwidth-related upcall
2116 */
2117static void
2118bw_meter_prepare_upcall(struct bw_meter *x, struct timeval *nowp)
2119{
2120 struct timeval delta;
2121 struct bw_upcall *u;
2122
2124
2125 /*
2126 * Compute the measured time interval
2127 */
2128 delta = *nowp;
2129 BW_TIMEVALDECR(&delta, &x->bm_start_time);
2130
2131 /*
2132 * Set the bw_upcall entry
2133 */
2134 u = malloc(sizeof(struct bw_upcall), M_MRTABLE, M_NOWAIT | M_ZERO);
2135 if (!u) {
2136 log(LOG_WARNING, "bw_meter_prepare_upcall: cannot allocate entry\n");
2137 return;
2138 }
2139 u->bu_src = x->bm_mfc->mfc_origin;
2140 u->bu_dst = x->bm_mfc->mfc_mcastgrp;
2144 u->bu_measured.b_time = delta;
2147 u->bu_flags = 0;
2152 if (x->bm_flags & BW_METER_GEQ)
2153 u->bu_flags |= BW_UPCALL_GEQ;
2154 if (x->bm_flags & BW_METER_LEQ)
2155 u->bu_flags |= BW_UPCALL_LEQ;
2156
2157 if (buf_ring_enqueue(V_bw_upcalls_ring, u))
2158 log(LOG_WARNING, "bw_meter_prepare_upcall: cannot enqueue upcall\n");
2159 if (buf_ring_count(V_bw_upcalls_ring) > (BW_UPCALLS_MAX / 2)) {
2160 taskqueue_enqueue(V_task_queue, &V_task);
2161 }
2162}
2163/*
2164 * Send the pending bandwidth-related upcalls
2165 */
2166static void
2168{
2169 struct mbuf *m;
2170 int len = 0;
2171 struct bw_upcall *bu;
2172 struct sockaddr_in k_igmpsrc = { sizeof k_igmpsrc, AF_INET };
2173 static struct igmpmsg igmpmsg = { 0, /* unused1 */
2174 0, /* unused2 */
2175 IGMPMSG_BW_UPCALL,/* im_msgtype */
2176 0, /* im_mbz */
2177 0, /* im_vif */
2178 0, /* unused3 */
2179 { 0 }, /* im_src */
2180 { 0 } }; /* im_dst */
2181
2183
2184 if (buf_ring_empty(V_bw_upcalls_ring))
2185 return;
2186
2187 /*
2188 * Allocate a new mbuf, initialize it with the header and
2189 * the payload for the pending calls.
2190 */
2191 m = m_gethdr(M_NOWAIT, MT_DATA);
2192 if (m == NULL) {
2193 log(LOG_WARNING, "bw_upcalls_send: cannot allocate mbuf\n");
2194 return;
2195 }
2196
2197 m_copyback(m, 0, sizeof(struct igmpmsg), (caddr_t)&igmpmsg);
2198 len += sizeof(struct igmpmsg);
2199 while ((bu = buf_ring_dequeue_mc(V_bw_upcalls_ring)) != NULL) {
2200 m_copyback(m, len, sizeof(struct bw_upcall), (caddr_t)bu);
2201 len += sizeof(struct bw_upcall);
2202 free(bu, M_MRTABLE);
2203 }
2204
2205 /*
2206 * Send the upcalls
2207 * XXX do we need to set the address in k_igmpsrc ?
2208 */
2209 MRTSTAT_INC(mrts_upcalls);
2210 if (socket_send(V_ip_mrouter, m, &k_igmpsrc) < 0) {
2211 log(LOG_WARNING, "bw_upcalls_send: ip_mrouter socket queue full\n");
2212 MRTSTAT_INC(mrts_upq_sockfull);
2213 }
2214}
2215
2216/*
2217 * A periodic function for sending all upcalls that are pending delivery
2218 */
2219static void
2221{
2222 CURVNET_SET((struct vnet *) arg);
2223
2224 /* This callout is run with MRW_RLOCK taken */
2225
2227
2229 curvnet);
2230 CURVNET_RESTORE();
2231}
2232
2233/*
2234 * End of bandwidth monitoring code
2235 */
2236
2237/*
2238 * Send the packet up to the user daemon, or eventually do kernel encapsulation
2239 *
2240 */
2241static int
2242pim_register_send(struct ip *ip, struct vif *vifp, struct mbuf *m,
2243 struct mfc *rt)
2244{
2245 struct mbuf *mb_copy, *mm;
2246
2247 /*
2248 * Do not send IGMP_WHOLEPKT notifications to userland, if the
2249 * rendezvous point was unspecified, and we were told not to.
2250 */
2252 in_nullhost(rt->mfc_rp))
2253 return 0;
2254
2255 mb_copy = pim_register_prepare(ip, m);
2256 if (mb_copy == NULL)
2257 return ENOBUFS;
2258
2259 /*
2260 * Send all the fragments. Note that the mbuf for each fragment
2261 * is freed by the sending machinery.
2262 */
2263 for (mm = mb_copy; mm; mm = mb_copy) {
2264 mb_copy = mm->m_nextpkt;
2265 mm->m_nextpkt = 0;
2266 mm = m_pullup(mm, sizeof(struct ip));
2267 if (mm != NULL) {
2268 ip = mtod(mm, struct ip *);
2269 if ((V_mrt_api_config & MRT_MFC_RP) && !in_nullhost(rt->mfc_rp)) {
2270 pim_register_send_rp(ip, vifp, mm, rt);
2271 } else {
2272 pim_register_send_upcall(ip, vifp, mm, rt);
2273 }
2274 }
2275 }
2276
2277 return 0;
2278}
2279
2280/*
2281 * Return a copy of the data packet that is ready for PIM Register
2282 * encapsulation.
2283 * XXX: Note that in the returned copy the IP header is a valid one.
2284 */
2285static struct mbuf *
2286pim_register_prepare(struct ip *ip, struct mbuf *m)
2287{
2288 struct mbuf *mb_copy = NULL;
2289 int mtu;
2290
2291 /* Take care of delayed checksums */
2292 if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
2294 m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
2295 }
2296
2297 /*
2298 * Copy the old packet & pullup its IP header into the
2299 * new mbuf so we can modify it.
2300 */
2301 mb_copy = m_copypacket(m, M_NOWAIT);
2302 if (mb_copy == NULL)
2303 return NULL;
2304 mb_copy = m_pullup(mb_copy, ip->ip_hl << 2);
2305 if (mb_copy == NULL)
2306 return NULL;
2307
2308 /* take care of the TTL */
2309 ip = mtod(mb_copy, struct ip *);
2310 --ip->ip_ttl;
2311
2312 /* Compute the MTU after the PIM Register encapsulation */
2313 mtu = 0xffff - sizeof(pim_encap_iphdr) - sizeof(pim_encap_pimhdr);
2314
2315 if (ntohs(ip->ip_len) <= mtu) {
2316 /* Turn the IP header into a valid one */
2317 ip->ip_sum = 0;
2318 ip->ip_sum = in_cksum(mb_copy, ip->ip_hl << 2);
2319 } else {
2320 /* Fragment the packet */
2321 mb_copy->m_pkthdr.csum_flags |= CSUM_IP;
2322 if (ip_fragment(ip, &mb_copy, mtu, 0) != 0) {
2323 m_freem(mb_copy);
2324 return NULL;
2325 }
2326 }
2327 return mb_copy;
2328}
2329
2330/*
2331 * Send an upcall with the data packet to the user-level process.
2332 */
2333static int
2334pim_register_send_upcall(struct ip *ip, struct vif *vifp,
2335 struct mbuf *mb_copy, struct mfc *rt)
2336{
2337 struct mbuf *mb_first;
2338 int len = ntohs(ip->ip_len);
2339 struct igmpmsg *im;
2340 struct sockaddr_in k_igmpsrc = { sizeof k_igmpsrc, AF_INET };
2341
2343
2344 /*
2345 * Add a new mbuf with an upcall header
2346 */
2347 mb_first = m_gethdr(M_NOWAIT, MT_DATA);
2348 if (mb_first == NULL) {
2349 m_freem(mb_copy);
2350 return ENOBUFS;
2351 }
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;
2356
2357 /* Send message to routing daemon */
2358 im = mtod(mb_first, struct igmpmsg *);
2360 im->im_mbz = 0;
2361 im->im_vif = vifp - V_viftable;
2362 im->im_src = ip->ip_src;
2363 im->im_dst = ip->ip_dst;
2364
2365 k_igmpsrc.sin_addr = ip->ip_src;
2366
2367 MRTSTAT_INC(mrts_upcalls);
2368
2369 if (socket_send(V_ip_mrouter, mb_first, &k_igmpsrc) < 0) {
2370 CTR1(KTR_IPMF, "%s: socket queue full", __func__);
2371 MRTSTAT_INC(mrts_upq_sockfull);
2372 return ENOBUFS;
2373 }
2374
2375 /* Keep statistics */
2376 PIMSTAT_INC(pims_snd_registers_msgs);
2377 PIMSTAT_ADD(pims_snd_registers_bytes, len);
2378
2379 return 0;
2380}
2381
2382/*
2383 * Encapsulate the data packet in PIM Register message and send it to the RP.
2384 */
2385static int
2386pim_register_send_rp(struct ip *ip, struct vif *vifp, struct mbuf *mb_copy,
2387 struct mfc *rt)
2388{
2389 struct mbuf *mb_first;
2390 struct ip *ip_outer;
2391 struct pim_encap_pimhdr *pimhdr;
2392 int len = ntohs(ip->ip_len);
2393 vifi_t vifi = rt->mfc_parent;
2394
2396
2397 if ((vifi >= V_numvifs) || in_nullhost(V_viftable[vifi].v_lcl_addr)) {
2398 m_freem(mb_copy);
2399 return EADDRNOTAVAIL; /* The iif vif is invalid */
2400 }
2401
2402 /*
2403 * Add a new mbuf with the encapsulating header
2404 */
2405 mb_first = m_gethdr(M_NOWAIT, MT_DATA);
2406 if (mb_first == NULL) {
2407 m_freem(mb_copy);
2408 return ENOBUFS;
2409 }
2410 mb_first->m_data += max_linkhdr;
2411 mb_first->m_len = sizeof(pim_encap_iphdr) + sizeof(pim_encap_pimhdr);
2412 mb_first->m_next = mb_copy;
2413
2414 mb_first->m_pkthdr.len = len + mb_first->m_len;
2415
2416 /*
2417 * Fill in the encapsulating IP and PIM header
2418 */
2419 ip_outer = mtod(mb_first, struct ip *);
2420 *ip_outer = pim_encap_iphdr;
2421 ip_outer->ip_len = htons(len + sizeof(pim_encap_iphdr) +
2422 sizeof(pim_encap_pimhdr));
2423 ip_outer->ip_src = V_viftable[vifi].v_lcl_addr;
2424 ip_outer->ip_dst = rt->mfc_rp;
2425 /*
2426 * Copy the inner header TOS to the outer header, and take care of the
2427 * IP_DF bit.
2428 */
2429 ip_outer->ip_tos = ip->ip_tos;
2430 if (ip->ip_off & htons(IP_DF))
2431 ip_outer->ip_off |= htons(IP_DF);
2432 ip_fillid(ip_outer);
2433 pimhdr = (struct pim_encap_pimhdr *)((caddr_t)ip_outer
2434 + sizeof(pim_encap_iphdr));
2435 *pimhdr = pim_encap_pimhdr;
2436 /* If the iif crosses a border, set the Border-bit */
2438 pimhdr->flags |= htonl(PIM_BORDER_REGISTER);
2439
2440 mb_first->m_data += sizeof(pim_encap_iphdr);
2441 pimhdr->pim.pim_cksum = in_cksum(mb_first, sizeof(pim_encap_pimhdr));
2442 mb_first->m_data -= sizeof(pim_encap_iphdr);
2443
2444 send_packet(vifp, mb_first);
2445
2446 /* Keep statistics */
2447 PIMSTAT_INC(pims_snd_registers_msgs);
2448 PIMSTAT_ADD(pims_snd_registers_bytes, len);
2449
2450 return 0;
2451}
2452
2453/*
2454 * pim_encapcheck() is called by the encap4_input() path at runtime to
2455 * determine if a packet is for PIM; allowing PIM to be dynamically loaded
2456 * into the kernel.
2457 */
2458static int
2459pim_encapcheck(const struct mbuf *m __unused, int off __unused,
2460 int proto __unused, void *arg __unused)
2461{
2462
2463 KASSERT(proto == IPPROTO_PIM, ("not for IPPROTO_PIM"));
2464 return (8); /* claim the datagram. */
2465}
2466
2467/*
2468 * PIM-SMv2 and PIM-DM messages processing.
2469 * Receives and verifies the PIM control messages, and passes them
2470 * up to the listening socket, using rip_input().
2471 * The only message with special processing is the PIM_REGISTER message
2472 * (used by PIM-SM): the PIM header is stripped off, and the inner packet
2473 * is passed to if_simloop().
2474 */
2475static int
2476pim_input(struct mbuf *m, int off, int proto, void *arg __unused)
2477{
2478 struct ip *ip = mtod(m, struct ip *);
2479 struct pim *pim;
2480 int iphlen = off;
2481 int minlen;
2482 int datalen = ntohs(ip->ip_len) - iphlen;
2483 int ip_tos;
2484
2485 /* Keep statistics */
2486 PIMSTAT_INC(pims_rcv_total_msgs);
2487 PIMSTAT_ADD(pims_rcv_total_bytes, datalen);
2488
2489 /*
2490 * Validate lengths
2491 */
2492 if (datalen < PIM_MINLEN) {
2493 PIMSTAT_INC(pims_rcv_tooshort);
2494 CTR3(KTR_IPMF, "%s: short packet (%d) from 0x%08x",
2495 __func__, datalen, ntohl(ip->ip_src.s_addr));
2496 m_freem(m);
2497 return (IPPROTO_DONE);
2498 }
2499
2500 /*
2501 * If the packet is at least as big as a REGISTER, go agead
2502 * and grab the PIM REGISTER header size, to avoid another
2503 * possible m_pullup() later.
2504 *
2505 * PIM_MINLEN == pimhdr + u_int32_t == 4 + 4 = 8
2506 * PIM_REG_MINLEN == pimhdr + reghdr + encap_iphdr == 4 + 4 + 20 = 28
2507 */
2508 minlen = iphlen + (datalen >= PIM_REG_MINLEN ? PIM_REG_MINLEN : PIM_MINLEN);
2509 /*
2510 * Get the IP and PIM headers in contiguous memory, and
2511 * possibly the PIM REGISTER header.
2512 */
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);
2516 }
2517
2518 /* m_pullup() may have given us a new mbuf so reset ip. */
2519 ip = mtod(m, struct ip *);
2520 ip_tos = ip->ip_tos;
2521
2522 /* adjust mbuf to point to the PIM header */
2523 m->m_data += iphlen;
2524 m->m_len -= iphlen;
2525 pim = mtod(m, struct pim *);
2526
2527 /*
2528 * Validate checksum. If PIM REGISTER, exclude the data packet.
2529 *
2530 * XXX: some older PIMv2 implementations don't make this distinction,
2531 * so for compatibility reason perform the checksum over part of the
2532 * message, and if error, then over the whole message.
2533 */
2534 if (PIM_VT_T(pim->pim_vt) == PIM_REGISTER && in_cksum(m, PIM_MINLEN) == 0) {
2535 /* do nothing, checksum okay */
2536 } else if (in_cksum(m, datalen)) {
2537 PIMSTAT_INC(pims_rcv_badsum);
2538 CTR1(KTR_IPMF, "%s: invalid checksum", __func__);
2539 m_freem(m);
2540 return (IPPROTO_DONE);
2541 }
2542
2543 /* PIM version check */
2544 if (PIM_VT_V(pim->pim_vt) < PIM_VERSION) {
2545 PIMSTAT_INC(pims_rcv_badversion);
2546 CTR3(KTR_IPMF, "%s: bad version %d expect %d", __func__,
2547 (int)PIM_VT_V(pim->pim_vt), PIM_VERSION);
2548 m_freem(m);
2549 return (IPPROTO_DONE);
2550 }
2551
2552 /* restore mbuf back to the outer IP */
2553 m->m_data -= iphlen;
2554 m->m_len += iphlen;
2555
2556 if (PIM_VT_T(pim->pim_vt) == PIM_REGISTER) {
2557 /*
2558 * Since this is a REGISTER, we'll make a copy of the register
2559 * headers ip + pim + u_int32 + encap_ip, to be passed up to the
2560 * routing daemon.
2561 */
2562 struct sockaddr_in dst = { sizeof(dst), AF_INET };
2563 struct mbuf *mcp;
2564 struct ip *encap_ip;
2565 u_int32_t *reghdr;
2566 struct ifnet *vifp;
2567
2568 MRW_RLOCK();
2570 MRW_RUNLOCK();
2571 CTR2(KTR_IPMF, "%s: register vif not set: %d", __func__,
2572 (int)V_reg_vif_num);
2573 m_freem(m);
2574 return (IPPROTO_DONE);
2575 }
2576 /* XXX need refcnt? */
2577 vifp = V_viftable[V_reg_vif_num].v_ifp;
2578 MRW_RUNLOCK();
2579
2580 /*
2581 * Validate length
2582 */
2583 if (datalen < PIM_REG_MINLEN) {
2584 PIMSTAT_INC(pims_rcv_tooshort);
2585 PIMSTAT_INC(pims_rcv_badregisters);
2586 CTR1(KTR_IPMF, "%s: register packet size too small", __func__);
2587 m_freem(m);
2588 return (IPPROTO_DONE);
2589 }
2590
2591 reghdr = (u_int32_t *)(pim + 1);
2592 encap_ip = (struct ip *)(reghdr + 1);
2593
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));
2597
2598 /* verify the version number of the inner packet */
2599 if (encap_ip->ip_v != IPVERSION) {
2600 PIMSTAT_INC(pims_rcv_badregisters);
2601 CTR1(KTR_IPMF, "%s: bad encap ip version", __func__);
2602 m_freem(m);
2603 return (IPPROTO_DONE);
2604 }
2605
2606 /* verify the inner packet is destined to a mcast group */
2607 if (!IN_MULTICAST(ntohl(encap_ip->ip_dst.s_addr))) {
2608 PIMSTAT_INC(pims_rcv_badregisters);
2609 CTR2(KTR_IPMF, "%s: bad encap ip dest 0x%08x", __func__,
2610 ntohl(encap_ip->ip_dst.s_addr));
2611 m_freem(m);
2612 return (IPPROTO_DONE);
2613 }
2614
2615 /* If a NULL_REGISTER, pass it to the daemon */
2616 if ((ntohl(*reghdr) & PIM_NULL_REGISTER))
2617 goto pim_input_to_daemon;
2618
2619 /*
2620 * Copy the TOS from the outer IP header to the inner IP header.
2621 */
2622 if (encap_ip->ip_tos != ip_tos) {
2623 /* Outer TOS -> inner TOS */
2624 encap_ip->ip_tos = ip_tos;
2625 /* Recompute the inner header checksum. Sigh... */
2626
2627 /* adjust mbuf to point to the inner IP header */
2628 m->m_data += (iphlen + PIM_MINLEN);
2629 m->m_len -= (iphlen + PIM_MINLEN);
2630
2631 encap_ip->ip_sum = 0;
2632 encap_ip->ip_sum = in_cksum(m, encap_ip->ip_hl << 2);
2633
2634 /* restore mbuf to point back to the outer IP header */
2635 m->m_data -= (iphlen + PIM_MINLEN);
2636 m->m_len += (iphlen + PIM_MINLEN);
2637 }
2638
2639 /*
2640 * Decapsulate the inner IP packet and loopback to forward it
2641 * as a normal multicast packet. Also, make a copy of the
2642 * outer_iphdr + pimhdr + reghdr + encap_iphdr
2643 * to pass to the daemon later, so it can take the appropriate
2644 * actions (e.g., send back PIM_REGISTER_STOP).
2645 * XXX: here m->m_data points to the outer IP header.
2646 */
2647 mcp = m_copym(m, 0, iphlen + PIM_REG_MINLEN, M_NOWAIT);
2648 if (mcp == NULL) {
2649 CTR1(KTR_IPMF, "%s: m_copym() failed", __func__);
2650 m_freem(m);
2651 return (IPPROTO_DONE);
2652 }
2653
2654 /* Keep statistics */
2655 /* XXX: registers_bytes include only the encap. mcast pkt */
2656 PIMSTAT_INC(pims_rcv_registers_msgs);
2657 PIMSTAT_ADD(pims_rcv_registers_bytes, ntohs(encap_ip->ip_len));
2658
2659 /*
2660 * forward the inner ip packet; point m_data at the inner ip.
2661 */
2662 m_adj(m, iphlen + PIM_MINLEN);
2663
2664 CTR4(KTR_IPMF,
2665 "%s: forward decap'd REGISTER: src %lx dst %lx vif %d",
2666 __func__,
2667 (u_long)ntohl(encap_ip->ip_src.s_addr),
2668 (u_long)ntohl(encap_ip->ip_dst.s_addr),
2669 (int)V_reg_vif_num);
2670
2671 /* NB: vifp was collected above; can it change on us? */
2672 if_simloop(vifp, m, dst.sin_family, 0);
2673
2674 /* prepare the register head to send to the mrouting daemon */
2675 m = mcp;
2676 }
2677
2678pim_input_to_daemon:
2679 /*
2680 * Pass the PIM message up to the daemon; if it is a Register message,
2681 * pass the 'head' only up to the daemon. This includes the
2682 * outer IP header, PIM header, PIM-Register header and the
2683 * inner IP header.
2684 * XXX: the outer IP header pkt size of a Register is not adjust to
2685 * reflect the fact that the inner multicast data is truncated.
2686 */
2687 return (rip_input(&m, &off, proto));
2688}
2689
2690static int
2691sysctl_mfctable(SYSCTL_HANDLER_ARGS)
2692{
2693 struct mfc *rt;
2694 int error, i;
2695
2696 if (req->newptr)
2697 return (EPERM);
2698 if (V_mfchashtbl == NULL) /* XXX unlocked */
2699 return (0);
2700 error = sysctl_wire_old_buffer(req, 0);
2701 if (error)
2702 return (error);
2703
2704 MRW_RLOCK();
2705 for (i = 0; i < mfchashsize; i++) {
2706 LIST_FOREACH(rt, &V_mfchashtbl[i], mfc_hash) {
2707 error = SYSCTL_OUT(req, rt, sizeof(struct mfc));
2708 if (error)
2709 goto out_locked;
2710 }
2711 }
2712out_locked:
2713 MRW_RUNLOCK();
2714 return (error);
2715}
2716
2717static SYSCTL_NODE(_net_inet_ip, OID_AUTO, mfctable,
2718 CTLFLAG_RD | CTLFLAG_MPSAFE, sysctl_mfctable,
2719 "IPv4 Multicast Forwarding Table "
2720 "(struct *mfc[mfchashsize], netinet/ip_mroute.h)");
2721
2722static int
2723sysctl_viflist(SYSCTL_HANDLER_ARGS)
2724{
2725 int error;
2726
2727 if (req->newptr)
2728 return (EPERM);
2729 if (V_viftable == NULL) /* XXX unlocked */
2730 return (0);
2731 error = sysctl_wire_old_buffer(req, sizeof(*V_viftable) * MAXVIFS);
2732 if (error)
2733 return (error);
2734
2735 MRW_RLOCK();
2736 error = SYSCTL_OUT(req, V_viftable, sizeof(*V_viftable) * MAXVIFS);
2737 MRW_RUNLOCK();
2738 return (error);
2739}
2740
2741SYSCTL_PROC(_net_inet_ip, OID_AUTO, viftable,
2742 CTLTYPE_OPAQUE | CTLFLAG_VNET | CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, 0,
2743 sysctl_viflist, "S,vif[MAXVIFS]",
2744 "IPv4 Multicast Interfaces (struct vif[MAXVIFS], netinet/ip_mroute.h)");
2745
2746static void
2747vnet_mroute_init(const void *unused __unused)
2748{
2749
2750 V_nexpire = malloc(mfchashsize, M_MRTABLE, M_WAITOK|M_ZERO);
2751
2752 V_viftable = mallocarray(MAXVIFS, sizeof(*V_viftable),
2753 M_MRTABLE, M_WAITOK|M_ZERO);
2754
2755 callout_init_rw(&V_expire_upcalls_ch, &mrouter_mtx, 0);
2756 callout_init_rw(&V_bw_upcalls_ch, &mrouter_mtx, 0);
2757
2758 /* Prepare taskqueue */
2759 V_task_queue = taskqueue_create_fast("ip_mroute_tskq", M_NOWAIT,
2760 taskqueue_thread_enqueue, &V_task_queue);
2761 taskqueue_start_threads(&V_task_queue, 1, PI_NET, "ip_mroute_tskq task");
2762}
2763
2764VNET_SYSINIT(vnet_mroute_init, SI_SUB_PROTO_MC, SI_ORDER_ANY, vnet_mroute_init,
2765 NULL);
2766
2767static void
2768vnet_mroute_uninit(const void *unused __unused)
2769{
2770
2771 /* Taskqueue should be cancelled and drained before freeing */
2772 taskqueue_free(V_task_queue);
2773
2774 free(V_viftable, M_MRTABLE);
2775 free(V_nexpire, M_MRTABLE);
2776 V_nexpire = NULL;
2777}
2778
2779VNET_SYSUNINIT(vnet_mroute_uninit, SI_SUB_PROTO_MC, SI_ORDER_MIDDLE,
2780 vnet_mroute_uninit, NULL);
2781
2782static int
2783ip_mroute_modevent(module_t mod, int type, void *unused)
2784{
2785
2786 switch (type) {
2787 case MOD_LOAD:
2788 MRW_LOCK_INIT();
2789
2790 if_detach_event_tag = EVENTHANDLER_REGISTER(ifnet_departure_event,
2791 if_detached_event, NULL, EVENTHANDLER_PRI_ANY);
2792 if (if_detach_event_tag == NULL) {
2793 printf("ip_mroute: unable to register "
2794 "ifnet_departure_event handler\n");
2796 return (EINVAL);
2797 }
2798
2800 if (TUNABLE_ULONG_FETCH("net.inet.ip.mfchashsize", &mfchashsize) &&
2801 !powerof2(mfchashsize)) {
2802 printf("WARNING: %s not a power of 2; using default\n",
2803 "net.inet.ip.mfchashsize");
2805 }
2806
2808 TUNABLE_ULONG_FETCH("net.inet.pim.squelch_wholepkt",
2810
2812 if (pim_encap_cookie == NULL) {
2813 printf("ip_mroute: unable to attach pim encap\n");
2815 return (EINVAL);
2816 }
2817
2823
2826
2830 break;
2831
2832 case MOD_UNLOAD:
2833 /*
2834 * Typically module unload happens after the user-level
2835 * process has shutdown the kernel services (the check
2836 * below insures someone can't just yank the module out
2837 * from under a running process). But if the module is
2838 * just loaded and then unloaded w/o starting up a user
2839 * process we still need to cleanup.
2840 */
2841 MRW_WLOCK();
2842 if (ip_mrouter_cnt != 0) {
2843 MRW_WUNLOCK();
2844 return (EINVAL);
2845 }
2847 MRW_WUNLOCK();
2848
2849 EVENTHANDLER_DEREGISTER(ifnet_departure_event, if_detach_event_tag);
2850
2851 if (pim_encap_cookie) {
2853 pim_encap_cookie = NULL;
2854 }
2855
2856 ip_mcast_src = NULL;
2857 ip_mforward = NULL;
2858 ip_mrouter_done = NULL;
2859 ip_mrouter_get = NULL;
2860 ip_mrouter_set = NULL;
2861
2862 ip_rsvp_force_done = NULL;
2863 ip_rsvp_vif = NULL;
2864
2865 legal_vif_num = NULL;
2866 mrt_ioctl = NULL;
2867 rsvp_input_p = NULL;
2868
2870 break;
2871
2872 default:
2873 return EOPNOTSUPP;
2874 }
2875 return 0;
2876}
2877
2878static moduledata_t ip_mroutemod = {
2879 "ip_mroute",
2881 0
2882};
2883
2884DECLARE_MODULE(ip_mroute, ip_mroutemod, SI_SUB_PROTO_MC, SI_ORDER_MIDDLE);
__uint32_t uint32_t
Definition: in.h:62
#define in_nullhost(x)
Definition: in.h:675
#define INADDR_ANY
Definition: in.h:48
uint32_t in_addr_t
Definition: in.h:67
#define in_hosteq(s, t)
Definition: in.h:674
u_char ip_tos
Definition: ip.h:8
#define MAXTTL
Definition: ip.h:211
#define IPVERSION
Definition: ip.h:46
#define IPOPT_LSRR
Definition: ip.h:155
#define IP_DF
Definition: ip.h:13
static LIST_HEAD(carp_softc)
Definition: ip_carp.c:333
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)
Definition: ip_id.c:243
static const struct encaptab * pim_encap_cookie
Definition: ip_mroute.c:234
static moduledata_t ip_mroutemod
Definition: ip_mroute.c:2878
static __inline struct mfc * mfc_find(struct in_addr *, struct in_addr *)
Definition: ip_mroute.c:369
static void bw_meter_prepare_upcall(struct bw_meter *, struct timeval *)
Definition: ip_mroute.c:2118
VNET_SYSUNINIT(vnet_mroute_uninit, SI_SUB_PROTO_MC, SI_ORDER_MIDDLE, vnet_mroute_uninit, NULL)
static const struct encap_config ipv4_encap_cfg
Definition: ip_mroute.c:240
static int X_ip_mrouter_set(struct socket *, struct sockopt *)
Definition: ip_mroute.c:412
VNET_PCPUSTAT_SYSINIT(mrtstat)
#define EXPIRE_TIMEOUT
Definition: ip_mroute.c:199
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
Definition: ip_mroute.c:362
static void ip_mrouter_upcall_thread(void *arg, int pending __unused)
Definition: ip_mroute.c:671
static void vnet_mroute_init(const void *unused __unused)
Definition: ip_mroute.c:2747
#define MRW_LOCK_TRY_UPGRADE()
Definition: ip_mroute.c:153
static uint32_t compute_bw_meter_flags(struct bw_upcall *req)
Definition: ip_mroute.c:1814
static void update_mfc_params(struct mfc *rt, struct mfcctl2 *mfccp)
Definition: ip_mroute.c:1059
static u_long mfchashsize
Definition: ip_mroute.c:176
#define V_bw_upcalls_ch
Definition: ip_mroute.c:212
static void expire_upcalls(void *)
Definition: ip_mroute.c:1504
static int del_vif_locked(vifi_t, struct ifnet **)
Definition: ip_mroute.c:996
static int sysctl_mfctable(SYSCTL_HANDLER_ARGS)
Definition: ip_mroute.c:2691
#define BW_TIMEVALDECR(vvp, uvp)
Definition: ip_mroute.c:1810
static int del_bw_upcall(struct bw_upcall *)
Definition: ip_mroute.c:1994
static int pim_register_send_rp(struct ip *, struct vif *, struct mbuf *, struct mfc *)
Definition: ip_mroute.c:2386
static u_long pim_squelch_wholepkt
Definition: ip_mroute.c:229
#define V_nexpire
Definition: ip_mroute.c:178
static void if_detached_event(void *, struct ifnet *)
#define KTR_IPMF
Definition: ip_mroute.c:130
#define V_mrt_api_config
Definition: ip_mroute.c:359
VNET_DEFINE_STATIC(u_long, mfchash)
#define V_multicast_register_if
Definition: ip_mroute.c:294
static void init_mfc_params(struct mfc *rt, struct mfcctl2 *mfccp)
Definition: ip_mroute.c:1080
static int add_mfc(struct mfcctl2 *)
Definition: ip_mroute.c:1121
DECLARE_MODULE(ip_mroute, ip_mroutemod, SI_SUB_PROTO_MC, SI_ORDER_MIDDLE)
static eventhandler_tag if_detach_event_tag
Definition: ip_mroute.c:191
#define MFCHASH(a, g)
Definition: ip_mroute.c:171
#define V_bw_upcalls_ring_mtx
Definition: ip_mroute.c:216
VNET_PCPUSTAT_DEFINE_STATIC(struct mrtstat, mrtstat)
static int add_vif(struct vifctl *)
Definition: ip_mroute.c:892
static int X_mrt_ioctl(u_long, caddr_t, int)
static int get_vif_cnt(struct sioc_vif_req *)
Definition: ip_mroute.c:599
#define MRT_API_VERSION
Definition: ip_mroute.c:351
SYSCTL_NODE(_net_inet, IPPROTO_PIM, pim, CTLFLAG_RW|CTLFLAG_MPSAFE, 0, "PIM")
static void expire_bw_upcalls_send(void *)
Definition: ip_mroute.c:2220
#define MRW_LOCK_ASSERT()
Definition: ip_mroute.c:151
int in_mcast_loop
Definition: in_mcast.c:188
#define UPCALL_EXPIRE
Definition: ip_mroute.c:200
#define V_task
Definition: ip_mroute.c:184
static const uint32_t mrt_api_support
Definition: ip_mroute.c:354
static void send_packet(struct vif *, struct mbuf *)
Definition: ip_mroute.c:1749
#define MRW_LOCK_INIT()
Definition: ip_mroute.c:155
#define V_pim_assert_enabled
Definition: ip_mroute.c:361
#define MRW_LOCK_DESTROY()
Definition: ip_mroute.c:157
static int pim_register_send(struct ip *, struct vif *, struct mbuf *, struct mfc *)
Definition: ip_mroute.c:2242
static int set_assert(int)
Definition: ip_mroute.c:836
static const int mrt_api_version
Definition: ip_mroute.c:353
SYSCTL_ULONG(_net_inet_pim, OID_AUTO, squelch_wholepkt, CTLFLAG_RW, &pim_squelch_wholepkt, 0, "Disable IGMP_WHOLEPKT notifications if rendezvous point is unspecified")
#define PIM_ENCAP_TTL
Definition: ip_mroute.c:263
#define MFCHASHSIZE
Definition: ip_mroute.c:174
__FBSDID("$FreeBSD$")
static int pim_input(struct mbuf *, int, int, void *)
#define V_mfchash
Definition: ip_mroute.c:170
static int ip_mroute_modevent(module_t mod, int type, void *unused)
Definition: ip_mroute.c:2783
static void expire_mfc(struct mfc *)
Definition: ip_mroute.c:1095
static int X_ip_mforward(struct ip *, struct ifnet *, struct mbuf *, struct ip_moptions *)
Definition: ip_mroute.c:1287
static void expire_bw_meter_leq(void *arg)
Definition: ip_mroute.c:1831
static struct rwlock mrouter_mtx
Definition: ip_mroute.c:145
#define V_bw_upcalls_ring
Definition: ip_mroute.c:214
#define VIFI_INVALID
Definition: ip_mroute.c:133
#define MRW_RUNLOCK()
Definition: ip_mroute.c:148
static struct pim_encap_pimhdr pim_encap_pimhdr
Definition: ip_mroute.c:282
#define MRW_UNLOCK()
Definition: ip_mroute.c:150
static int ip_mrouter_init(struct socket *, int)
Definition: ip_mroute.c:686
#define V_mfchashtbl
Definition: ip_mroute.c:180
static MALLOC_DEFINE(M_MRTABLE, "mroutetbl", "multicast forwarding cache")
static int sysctl_viflist(SYSCTL_HANDLER_ARGS)
Definition: ip_mroute.c:2723
static void bw_upcalls_send(void)
Definition: ip_mroute.c:2167
static int X_legal_vif_num(int)
Definition: ip_mroute.c:1690
static int pim_encapcheck(const struct mbuf *, int, int, void *)
VNET_PCPUSTAT_SYSUNINIT(mrtstat)
#define V_numvifs
Definition: ip_mroute.c:187
static struct ip pim_encap_iphdr
Definition: ip_mroute.c:265
#define V_reg_vif_num
Definition: ip_mroute.c:292
static int X_rsvp_input(struct mbuf **mp, int *offp, int proto)
Definition: ip_mroute.c:1791
static int ip_mrouter_unloading
Definition: ip_mroute.c:160
static void phyint_send(struct ip *, struct vif *, struct mbuf *)
Definition: ip_mroute.c:1727
static void bw_meter_geq_receive_packet(struct bw_meter *, int, struct timeval *)
Definition: ip_mroute.c:2073
static struct mbuf * pim_register_prepare(struct ip *, struct mbuf *)
Definition: ip_mroute.c:2286
#define BW_TIMEVALCMP(tvp, uvp, cmp)
Definition: ip_mroute.c:1809
static int ip_mdq(struct mbuf *, struct ifnet *, struct mfc *, vifi_t)
Definition: ip_mroute.c:1544
#define TUNNEL_LEN
Definition: ip_mroute.c:1284
static int socket_send(struct socket *, struct mbuf *, struct sockaddr_in *)
Definition: ip_mroute.c:1258
static int X_ip_mrouter_get(struct socket *, struct sockopt *)
Definition: ip_mroute.c:512
#define BW_UPCALLS_PERIOD
Definition: ip_mroute.c:218
static void X_ip_rsvp_force_done(struct socket *so __unused)
Definition: ip_mroute.c:1785
#define MRW_WUNLOCK()
Definition: ip_mroute.c:149
static int get_sg_cnt(struct sioc_sg_req *)
Definition: ip_mroute.c:577
static int pim_register_send_upcall(struct ip *, struct vif *, struct mbuf *, struct mfc *)
Definition: ip_mroute.c:2334
#define V_task_queue
Definition: ip_mroute.c:182
static int ip_mrouter_cnt
Definition: ip_mroute.c:159
static u_long X_ip_mcast_src(int)
Definition: ip_mroute.c:1710
#define MRW_RLOCK()
Definition: ip_mroute.c:146
static int X_ip_rsvp_vif(struct socket *so __unused, struct sockopt *sopt __unused)
Definition: ip_mroute.c:1778
static void vnet_mroute_uninit(const void *unused __unused)
Definition: ip_mroute.c:2768
static int X_ip_mrouter_done(void)
Definition: ip_mroute.c:748
static int del_vif(vifi_t)
Definition: ip_mroute.c:1040
#define V_expire_upcalls_ch
Definition: ip_mroute.c:194
static int add_bw_upcall(struct bw_upcall *)
Definition: ip_mroute.c:1877
static int set_api_config(uint32_t *)
Definition: ip_mroute.c:850
static void free_bw_list(struct bw_meter *)
Definition: ip_mroute.c:1974
static __inline struct mfc * mfc_alloc(void)
Definition: ip_mroute.c:391
#define MRW_WLOCK_ASSERT()
Definition: ip_mroute.c:152
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 *)
Definition: ip_mroute.c:1218
#define V_viftable
Definition: ip_mroute.c:189
#define MRW_WOWNED()
Definition: ip_mroute.c:154
#define MRW_WLOCK()
Definition: ip_mroute.c:147
#define V_buf_ring_mtx
Definition: ip_mroute.c:197
#define MRT_MFC_FLAGS_BORDER_VIF
Definition: ip_mroute.h:141
int(* mrt_ioctl)(u_long, caddr_t, int)
#define MRT_DEL_VIF
Definition: ip_mroute.h:63
#define MRT_DEL_BW_UPCALL
Definition: ip_mroute.h:72
#define MRT_ASSERT
Definition: ip_mroute.h:67
#define MRT_DONE
Definition: ip_mroute.h:61
#define BW_UPCALL_THRESHOLD_INTERVAL_MIN_USEC
Definition: ip_mroute.h:205
#define BW_METER_UNIT_BYTES
Definition: ip_mroute.h:339
int(* ip_mrouter_done)(void)
#define BW_METER_GEQ
Definition: ip_mroute.h:340
#define MAX_UPQ
Definition: ip_mroute.h:326
#define BW_UPCALLS_MAX
Definition: ip_mroute.h:202
#define MRT_ADD_VIF
Definition: ip_mroute.h:62
#define MRT_DEL_MFC
Definition: ip_mroute.h:65
#define MRT_MFC_FLAGS_ALL
Definition: ip_mroute.h:144
#define MRT_ADD_BW_UPCALL
Definition: ip_mroute.h:71
#define MRT_API_SUPPORT
Definition: ip_mroute.h:69
int(* ip_mrouter_set)(struct socket *, struct sockopt *)
#define MRT_API_CONFIG
Definition: ip_mroute.h:70
#define MRT_INIT
Definition: ip_mroute.h:60
#define VIFF_TUNNEL
Definition: ip_mroute.h:104
#define VIFF_REGISTER
Definition: ip_mroute.h:106
#define MRTSTAT_INC(name)
Definition: ip_mroute.h:229
#define BW_UPCALL_LEQ
Definition: ip_mroute.h:195
#define MRT_ADD_MFC
Definition: ip_mroute.h:64
#define IGMPMSG_WRONGVIF
Definition: ip_mroute.h:307
#define MRT_MFC_BW_UPCALL
Definition: ip_mroute.h:143
#define BW_METER_UNIT_PACKETS
Definition: ip_mroute.h:338
int(* ip_mrouter_get)(struct socket *, struct sockopt *)
#define IGMPMSG_BW_UPCALL
Definition: ip_mroute.h:309
#define BW_UPCALL_UNIT_BYTES
Definition: ip_mroute.h:193
#define BW_METER_USER_FLAGS
Definition: ip_mroute.h:342
#define IGMPMSG_NOCACHE
Definition: ip_mroute.h:306
#define MRT_MFC_FLAGS_DISABLE_WRONGVIF
Definition: ip_mroute.h:140
#define IGMPMSG_WHOLEPKT
Definition: ip_mroute.h:308
#define BW_UPCALL_DELETE_ALL
Definition: ip_mroute.h:196
#define MRT_VERSION
Definition: ip_mroute.h:66
#define MRT_API_FLAGS_ALL
Definition: ip_mroute.h:146
#define MRT_MFC_RP
Definition: ip_mroute.h:142
u_short vifi_t
Definition: ip_mroute.h:79
#define MAXVIFS
Definition: ip_mroute.h:77
#define BW_UPCALL_THRESHOLD_INTERVAL_MIN_SEC
Definition: ip_mroute.h:204
#define BW_METER_UPCALL_DELIVERED
Definition: ip_mroute.h:347
#define BW_UPCALL_GEQ
Definition: ip_mroute.h:194
#define BW_METER_LEQ
Definition: ip_mroute.h:341
#define BW_UPCALL_UNIT_PACKETS
Definition: ip_mroute.h:192
int ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro, int flags, struct ip_moptions *imo, struct inpcb *inp)
Definition: ip_output.c:320
int ip_fragment(struct ip *ip, struct mbuf **m_frag, int mtu, u_long if_hwassist_flags)
Definition: ip_output.c:859
void in_delayed_cksum(struct mbuf *m)
Definition: ip_output.c:1032
int(* ip_rsvp_vif)(struct socket *, struct sockopt *)
int(* rsvp_input_p)(struct mbuf **, int *, int)
#define IP_FORWARDING
Definition: ip_var.h:165
#define V_rsvp_on
Definition: ip_var.h:210
#define V_ip_mrouter
Definition: ip_var.h:209
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_MINLEN
Definition: pim.h:88
#define PIM_NULL_REGISTER
Definition: pim.h:110
#define PIM_VERSION
Definition: pim.h:87
#define PIM_REG_MINLEN
Definition: pim.h:89
#define PIM_BORDER_REGISTER
Definition: pim.h:109
#define PIM_REGISTER
Definition: pim.h:96
#define PIMSTAT_ADD(name, val)
Definition: pim_var.h:65
#define PIMSTAT_INC(name)
Definition: pim_var.h:67
#define PIMCTL_STATS
Definition: pim_var.h:73
uint64_t b_bytes
Definition: ip_mroute.h:185
struct timeval b_time
Definition: ip_mroute.h:183
uint64_t b_packets
Definition: ip_mroute.h:184
struct callout bm_meter_callout
Definition: ip_mroute.h:353
uint32_t bm_flags
Definition: ip_mroute.h:337
struct mfc * bm_mfc
Definition: ip_mroute.h:336
struct timeval bm_start_time
Definition: ip_mroute.h:351
struct bw_data bm_threshold
Definition: ip_mroute.h:349
char bm_spin_name[32]
Definition: ip_mroute.h:356
struct bw_data bm_measured
Definition: ip_mroute.h:350
struct bw_meter * bm_time_next
Definition: ip_mroute.h:335
struct bw_meter * bm_mfc_next
Definition: ip_mroute.h:334
void * arg
Definition: ip_mroute.h:354
struct mtx bm_spin
Definition: ip_mroute.h:355
struct in_addr bu_dst
Definition: ip_mroute.h:190
struct bw_data bu_threshold
Definition: ip_mroute.h:197
struct in_addr bu_src
Definition: ip_mroute.h:189
struct bw_data bu_measured
Definition: ip_mroute.h:198
uint32_t bu_flags
Definition: ip_mroute.h:191
u_char im_vif
Definition: ip_mroute.h:311
u_char im_mbz
Definition: ip_mroute.h:310
u_char im_msgtype
Definition: ip_mroute.h:305
struct in_addr im_src im_dst
Definition: ip_mroute.h:313
Definition: in.h:83
in_addr_t s_addr
Definition: in.h:84
Definition: ip.h:51
struct in_addr ip_src ip_dst
Definition: ip.h:71
u_char ip_tos
Definition: ip.h:60
u_char ip_hl
Definition: ip.h:53
u_short ip_sum
Definition: ip.h:70
u_short ip_len
Definition: ip.h:61
u_char ip_v
Definition: ip.h:54
u_char ip_ttl
Definition: ip.h:68
u_short ip_off
Definition: ip.h:63
Definition: ip_mroute.h:277
uint8_t mfc_flags[MAXVIFS]
Definition: ip_mroute.h:288
struct timeval mfc_last_assert
Definition: ip_mroute.h:287
u_long mfc_wrong_if
Definition: ip_mroute.h:285
int mfc_expire
Definition: ip_mroute.h:286
struct bw_meter * mfc_bw_meter_leq
Definition: ip_mroute.h:290
struct bw_meter * mfc_bw_meter_geq
Definition: ip_mroute.h:292
struct in_addr mfc_mcastgrp
Definition: ip_mroute.h:280
u_long mfc_byte_cnt
Definition: ip_mroute.h:284
struct in_addr mfc_origin
Definition: ip_mroute.h:279
struct in_addr mfc_rp
Definition: ip_mroute.h:289
u_long mfc_pkt_cnt
Definition: ip_mroute.h:283
vifi_t mfc_parent
Definition: ip_mroute.h:281
struct buf_ring * mfc_stall_ring
Definition: ip_mroute.h:294
u_char mfc_ttls[MAXVIFS]
Definition: ip_mroute.h:282
struct in_addr mfcc_mcastgrp
Definition: ip_mroute.h:126
struct in_addr mfcc_origin
Definition: ip_mroute.h:125
vifi_t mfcc_parent
Definition: ip_mroute.h:127
struct in_addr mfcc_rp
Definition: ip_mroute.h:132
uint8_t mfcc_flags[MAXVIFS]
Definition: ip_mroute.h:131
u_char mfcc_ttls[MAXVIFS]
Definition: ip_mroute.h:128
uint32_t flags
Definition: ip_mroute.c:261
struct pim pim
Definition: ip_mroute.c:260
Definition: pim.h:61
uint16_t pim_cksum
Definition: pim.h:75
struct ifnet * ifp
Definition: ip_mroute.h:323
struct mbuf * m
Definition: ip_mroute.h:322
struct in_addr src
Definition: ip_mroute.h:236
u_long wrong_if
Definition: ip_mroute.h:240
struct in_addr grp
Definition: ip_mroute.h:237
u_long pktcnt
Definition: ip_mroute.h:238
u_long bytecnt
Definition: ip_mroute.h:239
u_long ocount
Definition: ip_mroute.h:249
u_long obytes
Definition: ip_mroute.h:251
u_long ibytes
Definition: ip_mroute.h:250
u_long icount
Definition: ip_mroute.h:248
vifi_t vifi
Definition: ip_mroute.h:247
Definition: in.h:97
struct in_addr sin_addr
Definition: in.h:101
sa_family_t sin_family
Definition: in.h:99
Definition: ip_mroute.h:257
u_char v_threshold
Definition: ip_mroute.h:259
char v_spin_name[32]
Definition: ip_mroute.h:269
struct ifnet * v_ifp
Definition: ip_mroute.h:262
u_long v_bytes_out
Definition: ip_mroute.h:266
u_char v_flags
Definition: ip_mroute.h:258
struct mtx v_spin
Definition: ip_mroute.h:268
struct in_addr v_rmt_addr
Definition: ip_mroute.h:261
u_long v_pkt_in
Definition: ip_mroute.h:263
u_long v_bytes_in
Definition: ip_mroute.h:265
u_long v_pkt_out
Definition: ip_mroute.h:264
struct in_addr v_lcl_addr
Definition: ip_mroute.h:260
u_char vifc_flags
Definition: ip_mroute.h:97
vifi_t vifc_vifi
Definition: ip_mroute.h:96
struct in_addr vifc_rmt_addr
Definition: ip_mroute.h:101
u_char vifc_threshold
Definition: ip_mroute.h:98
struct in_addr vifc_lcl_addr
Definition: ip_mroute.h:100
u_int vifc_rate_limit
Definition: ip_mroute.h:99