ifq.h revision 256521
133965Sjdp/*-
278828Sobrien * Copyright (c) 1982, 1986, 1989, 1993
3218822Sdim *	The Regents of the University of California.  All rights reserved.
433965Sjdp *
533965Sjdp * Redistribution and use in source and binary forms, with or without
633965Sjdp * modification, are permitted provided that the following conditions
733965Sjdp * are met:
833965Sjdp * 1. Redistributions of source code must retain the above copyright
933965Sjdp *    notice, this list of conditions and the following disclaimer.
1033965Sjdp * 2. Redistributions in binary form must reproduce the above copyright
1133965Sjdp *    notice, this list of conditions and the following disclaimer in the
1233965Sjdp *    documentation and/or other materials provided with the distribution.
1333965Sjdp * 4. Neither the name of the University nor the names of its contributors
1433965Sjdp *    may be used to endorse or promote products derived from this software
1533965Sjdp *    without specific prior written permission.
1633965Sjdp *
1733965Sjdp * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
1833965Sjdp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1933965Sjdp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20218822Sdim * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21218822Sdim * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2233965Sjdp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2333965Sjdp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2433965Sjdp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2533965Sjdp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2633965Sjdp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2733965Sjdp * SUCH DAMAGE.
2833965Sjdp *
29218822Sdim *	From: @(#)if.h	8.1 (Berkeley) 6/10/93
30218822Sdim * $FreeBSD: head/sys/net/if_var.h 256521 2013-10-15 10:41:22Z glebius $
31218822Sdim */
32218822Sdim
33218822Sdim#ifndef	_NET_IF_VAR_H_
34218822Sdim#define	_NET_IF_VAR_H_
35218822Sdim
3633965Sjdp/*
3733965Sjdp * Structures defining a network interface, providing a packet
3833965Sjdp * transport mechanism (ala level 0 of the PUP protocols).
3933965Sjdp *
4033965Sjdp * Each interface accepts output datagrams of a specified maximum
41218822Sdim * length, and provides higher level routines with input datagrams
42218822Sdim * received from its medium.
43218822Sdim *
4477298Sobrien * Output occurs when the routine if_output is called, with three parameters:
4577298Sobrien *	(*ifp->if_output)(ifp, m, dst, rt)
4677298Sobrien * Here m is the mbuf chain to be sent and dst is the destination address.
4777298Sobrien * The output routine encapsulates the supplied datagram if necessary,
4889857Sobrien * and then transmits it on its medium.
4989857Sobrien *
5089857Sobrien * On input, each interface unwraps the data received by it, and either
51218822Sdim * places it on the input queue of an internetwork datagram routine
52218822Sdim * and posts the associated software interrupt, or passes the datagram to a raw
53218822Sdim * packet input routine.
54218822Sdim *
5589857Sobrien * Routines exist for locating interfaces by their addresses
5689857Sobrien * or for locating an interface on a certain network, as well as more general
5789857Sobrien * routing and gateway routines maintaining information used to locate
5889857Sobrien * interfaces.  These routines live in the files if.c and route.c
5989857Sobrien */
6089857Sobrien
6189857Sobrien#ifdef __STDC__
6289857Sobrien/*
6389857Sobrien * Forward structure declarations for function prototypes [sic].
6489857Sobrien */
6589857Sobrienstruct	mbuf;
6633965Sjdpstruct	thread;
67218822Sdimstruct	rtentry;
6833965Sjdpstruct	rt_addrinfo;
6933965Sjdpstruct	socket;
70218822Sdimstruct	ether_header;
71218822Sdimstruct	carp_if;
7233965Sjdpstruct	carp_softc;
7333965Sjdpstruct  ifvlantrunk;
7433965Sjdpstruct	route;
75218822Sdimstruct	vnet;
7633965Sjdp#endif
77218822Sdim
7833965Sjdp#include <sys/queue.h>		/* get TAILQ macros */
7933965Sjdp
8033965Sjdp#ifdef _KERNEL
8133965Sjdp#include <sys/mbuf.h>
82218822Sdim#include <sys/eventhandler.h>
8333965Sjdp#include <sys/buf_ring.h>
8433965Sjdp#include <net/vnet.h>
8533965Sjdp#endif /* _KERNEL */
8633965Sjdp#include <sys/lock.h>		/* XXX */
8733965Sjdp#include <sys/mutex.h>		/* XXX */
8833965Sjdp#include <sys/rwlock.h>		/* XXX */
8933965Sjdp#include <sys/sx.h>		/* XXX */
9033965Sjdp#include <sys/event.h>		/* XXX */
9133965Sjdp#include <sys/_task.h>
92218822Sdim
9333965Sjdp#define	IF_DUNIT_NONE	-1
9433965Sjdp
9533965Sjdp#include <altq/if_altq.h>
9633965Sjdp
97218822SdimTAILQ_HEAD(ifnethead, ifnet);	/* we use TAILQs so that the order of */
98218822SdimTAILQ_HEAD(ifaddrhead, ifaddr);	/* instantiation is preserved in the list */
9933965SjdpTAILQ_HEAD(ifmultihead, ifmultiaddr);
10033965SjdpTAILQ_HEAD(ifgrouphead, ifg_group);
10133965Sjdp
10233965Sjdp#ifdef _KERNEL
10333965SjdpVNET_DECLARE(struct pfil_head, link_pfil_hook);	/* packet filter hooks */
10433965Sjdp#define	V_link_pfil_hook	VNET(link_pfil_hook)
10533965Sjdp#endif /* _KERNEL */
106218822Sdim
10733965Sjdp/*
10833965Sjdp * Structure defining a queue for a network interface.
10933965Sjdp */
11033965Sjdpstruct	ifqueue {
111218822Sdim	struct	mbuf *ifq_head;
11233965Sjdp	struct	mbuf *ifq_tail;
11333965Sjdp	int	ifq_len;
11433965Sjdp	int	ifq_maxlen;
11533965Sjdp	int	ifq_drops;
11633965Sjdp	struct	mtx ifq_mtx;
117218822Sdim};
11833965Sjdp
11933965Sjdp/*
12033965Sjdp * Structure defining a network interface.
12133965Sjdp *
122218822Sdim * (Would like to call this struct ``if'', but C isn't PL/1.)
12333965Sjdp */
12433965Sjdp
12533965Sjdpstruct ifnet {
12633965Sjdp	void	*if_softc;		/* pointer to driver state */
12733965Sjdp	void	*if_l2com;		/* pointer to protocol bits */
128218822Sdim	struct vnet *if_vnet;		/* pointer to network stack instance */
12933965Sjdp	TAILQ_ENTRY(ifnet) if_link; 	/* all struct ifnets are chained */
13033965Sjdp	char	if_xname[IFNAMSIZ];	/* external name (name + unit) */
13133965Sjdp	const char *if_dname;		/* driver name */
13233965Sjdp	int	if_dunit;		/* unit or IF_DUNIT_NONE */
133218822Sdim	u_int	if_refcount;		/* reference count */
134218822Sdim	struct	ifaddrhead if_addrhead;	/* linked list of addresses per if */
13533965Sjdp		/*
13633965Sjdp		 * if_addrhead is the list of all addresses associated to
13733965Sjdp		 * an interface.
138218822Sdim		 * Some code in the kernel assumes that first element
13933965Sjdp		 * of the list has type AF_LINK, and contains sockaddr_dl
14033965Sjdp		 * addresses which store the link-level address and the name
14133965Sjdp		 * of the interface.
14233965Sjdp		 * However, access to the AF_LINK address through this
14333965Sjdp		 * field is deprecated. Use if_addr or ifaddr_byindex() instead.
144218822Sdim		 */
14533965Sjdp	int	if_pcount;		/* number of promiscuous listeners */
14633965Sjdp	struct	carp_if *if_carp;	/* carp interface structure */
14733965Sjdp	struct	bpf_if *if_bpf;		/* packet filter structure */
14833965Sjdp	u_short	if_index;		/* numeric abbreviation for this if  */
14933965Sjdp	short	if_index_reserved;	/* spare space to grow if_index */
15033965Sjdp	struct  ifvlantrunk *if_vlantrunk; /* pointer to 802.1q data */
15133965Sjdp	int	if_flags;		/* up/down, broadcast, etc. */
15233965Sjdp	int	if_capabilities;	/* interface features & capabilities */
15333965Sjdp	int	if_capenable;		/* enabled features & capabilities */
15433965Sjdp	void	*if_linkmib;		/* link-type-specific MIB data */
155218822Sdim	size_t	if_linkmiblen;		/* length of above data */
15633965Sjdp	struct	if_data if_data;
15733965Sjdp	struct	ifmultihead if_multiaddrs; /* multicast addresses configured */
15833965Sjdp	int	if_amcount;		/* number of all-multicast requests */
15933965Sjdp/* procedure handles */
16038889Sjdp	int	(*if_output)		/* output routine (enqueue) */
16138889Sjdp		(struct ifnet *, struct mbuf *, const struct sockaddr *,
16233965Sjdp		     struct route *);
16338889Sjdp	void	(*if_input)		/* input routine (from h/w driver) */
164218822Sdim		(struct ifnet *, struct mbuf *);
16538889Sjdp	void	(*if_start)		/* initiate output routine */
16638889Sjdp		(struct ifnet *);
16738889Sjdp	int	(*if_ioctl)		/* ioctl routine */
16838889Sjdp		(struct ifnet *, u_long, caddr_t);
16938889Sjdp	void	(*if_init)		/* Init routine */
17038889Sjdp		(void *);
17133965Sjdp	int	(*if_resolvemulti)	/* validate/resolve multicast */
17233965Sjdp		(struct ifnet *, struct sockaddr **, struct sockaddr *);
173218822Sdim	void	(*if_qflush)		/* flush any queues */
17433965Sjdp		(struct ifnet *);
17533965Sjdp	int	(*if_transmit)		/* initiate output routine */
17633965Sjdp		(struct ifnet *, struct mbuf *);
177218822Sdim	void	(*if_reassign)		/* reassign to vnet routine */
17833965Sjdp		(struct ifnet *, struct vnet *, char *);
17933965Sjdp	struct	vnet *if_home_vnet;	/* where this ifnet originates from */
180218822Sdim	struct	ifaddr	*if_addr;	/* pointer to link-level address */
18133965Sjdp	void	*if_llsoftc;		/* link layer softc */
18233965Sjdp	int	if_drv_flags;		/* driver-managed status flags */
183104834Sobrien	struct  ifaltq if_snd;		/* output queue (includes altq) */
184218822Sdim	const u_int8_t *if_broadcastaddr; /* linklevel broadcast bytestring */
185218822Sdim
18633965Sjdp	void	*if_bridge;		/* bridge glue */
18733965Sjdp
18833965Sjdp	struct	label *if_label;	/* interface MAC label */
18933965Sjdp
19033965Sjdp	/* these are only used by IPv6 */
19133965Sjdp	void	*if_unused[2];
19233965Sjdp	void	*if_afdata[AF_MAX];
193218822Sdim	int	if_afdata_initialized;
19433965Sjdp	struct	rwlock if_afdata_lock;
19533965Sjdp	struct	task if_linktask;	/* task for link change events */
19633965Sjdp	struct	rwlock if_addr_lock;	/* lock to protect address lists */
19760484Sobrien
19860484Sobrien	LIST_ENTRY(ifnet) if_clones;	/* interfaces of a cloner */
19933965Sjdp	TAILQ_HEAD(, ifg_list) if_groups; /* linked list of groups per if */
20033965Sjdp					/* protected by if_addr_lock */
20133965Sjdp	void	*if_pf_kif;
20233965Sjdp	void	*if_lagg;		/* lagg glue */
20333965Sjdp	char	*if_description;	/* interface description */
204218822Sdim	u_int	if_fib;			/* interface FIB */
20533965Sjdp	u_char	if_alloctype;		/* if_type at time of allocation */
20633965Sjdp
20733965Sjdp	u_int	if_hw_tsomax;		/* tso burst length limit, the minimum
20860484Sobrien					 * is (IP_MAXPACKET / 8).
20960484Sobrien					 * XXXAO: Have to find a better place
21033965Sjdp					 * for it eventually. */
21133965Sjdp
21233965Sjdp	/*
21333965Sjdp	 * Spare fields are added so that we can modify sensitive data
21433965Sjdp	 * structures without changing the kernel binary interface, and must
215218822Sdim	 * be used with care where binary compatibility is required.
21633965Sjdp	 */
21760484Sobrien	char	if_cspare[3];
21833965Sjdp	int	if_ispare[4];
21933965Sjdp	void	*if_pspare[8];		/* 1 netmap, 7 TDB */
22033965Sjdp};
221218822Sdim
22233965Sjdptypedef void if_init_f_t(void *);
22360484Sobrien
22433965Sjdp/*
22533965Sjdp * XXX These aliases are terribly dangerous because they could apply
22633965Sjdp * to anything.
22733965Sjdp */
228218822Sdim#define	if_mtu		if_data.ifi_mtu
22933965Sjdp#define	if_type		if_data.ifi_type
23060484Sobrien#define if_physical	if_data.ifi_physical
23133965Sjdp#define	if_addrlen	if_data.ifi_addrlen
23233965Sjdp#define	if_hdrlen	if_data.ifi_hdrlen
23333965Sjdp#define	if_metric	if_data.ifi_metric
234218822Sdim#define	if_link_state	if_data.ifi_link_state
23533965Sjdp#define	if_baudrate	if_data.ifi_baudrate
23660484Sobrien#define	if_baudrate_pf	if_data.ifi_baudrate_pf
23733965Sjdp#define	if_hwassist	if_data.ifi_hwassist
23833965Sjdp#define	if_ipackets	if_data.ifi_ipackets
23933965Sjdp#define	if_ierrors	if_data.ifi_ierrors
24077298Sobrien#define	if_opackets	if_data.ifi_opackets
24133965Sjdp#define	if_oerrors	if_data.ifi_oerrors
242218822Sdim#define	if_collisions	if_data.ifi_collisions
243218822Sdim#define	if_ibytes	if_data.ifi_ibytes
24433965Sjdp#define	if_obytes	if_data.ifi_obytes
24533965Sjdp#define	if_imcasts	if_data.ifi_imcasts
24633965Sjdp#define	if_omcasts	if_data.ifi_omcasts
24733965Sjdp#define	if_iqdrops	if_data.ifi_iqdrops
24833965Sjdp#define	if_noproto	if_data.ifi_noproto
249218822Sdim#define	if_lastchange	if_data.ifi_lastchange
250218822Sdim
25133965Sjdp/* for compatibility with other BSDs */
25233965Sjdp#define	if_addrlist	if_addrhead
253218822Sdim#define	if_list		if_link
254218822Sdim#define	if_name(ifp)	((ifp)->if_xname)
255218822Sdim
256218822Sdim/*
25733965Sjdp * Locks for address lists on the network interface.
25877298Sobrien */
25933965Sjdp#define	IF_ADDR_LOCK_INIT(if)	rw_init(&(if)->if_addr_lock, "if_addr_lock")
26033965Sjdp#define	IF_ADDR_LOCK_DESTROY(if)	rw_destroy(&(if)->if_addr_lock)
26133965Sjdp#define	IF_ADDR_WLOCK(if)	rw_wlock(&(if)->if_addr_lock)
26233965Sjdp#define	IF_ADDR_WUNLOCK(if)	rw_wunlock(&(if)->if_addr_lock)
263218822Sdim#define	IF_ADDR_RLOCK(if)	rw_rlock(&(if)->if_addr_lock)
26433965Sjdp#define	IF_ADDR_RUNLOCK(if)	rw_runlock(&(if)->if_addr_lock)
26533965Sjdp#define	IF_ADDR_LOCK_ASSERT(if)	rw_assert(&(if)->if_addr_lock, RA_LOCKED)
26633965Sjdp#define	IF_ADDR_WLOCK_ASSERT(if) rw_assert(&(if)->if_addr_lock, RA_WLOCKED)
26760484Sobrien
26860484Sobrien/*
26933965Sjdp * Function variations on locking macros intended to be used by loadable
27033965Sjdp * kernel modules in order to divorce them from the internals of address list
27133965Sjdp * locking.
27233965Sjdp */
27333965Sjdpvoid	if_addr_rlock(struct ifnet *ifp);	/* if_addrhead */
27460484Sobrienvoid	if_addr_runlock(struct ifnet *ifp);	/* if_addrhead */
27533965Sjdpvoid	if_maddr_rlock(struct ifnet *ifp);	/* if_multiaddrs */
27633965Sjdpvoid	if_maddr_runlock(struct ifnet *ifp);	/* if_multiaddrs */
27733965Sjdp
27833965Sjdp/*
279218822Sdim * Output queues (ifp->if_snd) and slow device input queues (*ifp->if_slowq)
28033965Sjdp * are queues of messages stored on ifqueue structures
281218822Sdim * (defined above).  Entries are added to and deleted from these structures
28233965Sjdp * by these macros.
28333965Sjdp */
28433965Sjdp#define IF_LOCK(ifq)		mtx_lock(&(ifq)->ifq_mtx)
285218822Sdim#define IF_UNLOCK(ifq)		mtx_unlock(&(ifq)->ifq_mtx)
28633965Sjdp#define	IF_LOCK_ASSERT(ifq)	mtx_assert(&(ifq)->ifq_mtx, MA_OWNED)
28733965Sjdp#define	_IF_QFULL(ifq)		((ifq)->ifq_len >= (ifq)->ifq_maxlen)
28833965Sjdp#define	_IF_DROP(ifq)		((ifq)->ifq_drops++)
28933965Sjdp#define	_IF_QLEN(ifq)		((ifq)->ifq_len)
290218822Sdim
29133965Sjdp#define	_IF_ENQUEUE(ifq, m) do { 				\
29233965Sjdp	(m)->m_nextpkt = NULL;					\
293218822Sdim	if ((ifq)->ifq_tail == NULL) 				\
29433965Sjdp		(ifq)->ifq_head = m; 				\
295218822Sdim	else 							\
296218822Sdim		(ifq)->ifq_tail->m_nextpkt = m; 		\
29733965Sjdp	(ifq)->ifq_tail = m; 					\
29833965Sjdp	(ifq)->ifq_len++; 					\
29933965Sjdp} while (0)
30033965Sjdp
30133965Sjdp#define IF_ENQUEUE(ifq, m) do {					\
30233965Sjdp	IF_LOCK(ifq); 						\
30333965Sjdp	_IF_ENQUEUE(ifq, m); 					\
30433965Sjdp	IF_UNLOCK(ifq); 					\
30533965Sjdp} while (0)
30633965Sjdp
30733965Sjdp#define	_IF_PREPEND(ifq, m) do {				\
30833965Sjdp	(m)->m_nextpkt = (ifq)->ifq_head; 			\
30933965Sjdp	if ((ifq)->ifq_tail == NULL) 				\
31033965Sjdp		(ifq)->ifq_tail = (m); 				\
31133965Sjdp	(ifq)->ifq_head = (m); 					\
31233965Sjdp	(ifq)->ifq_len++; 					\
313218822Sdim} while (0)
31433965Sjdp
31560484Sobrien#define IF_PREPEND(ifq, m) do {		 			\
316218822Sdim	IF_LOCK(ifq); 						\
31777298Sobrien	_IF_PREPEND(ifq, m); 					\
31860484Sobrien	IF_UNLOCK(ifq); 					\
31960484Sobrien} while (0)
32033965Sjdp
32133965Sjdp#define	_IF_DEQUEUE(ifq, m) do { 				\
32233965Sjdp	(m) = (ifq)->ifq_head; 					\
32333965Sjdp	if (m) { 						\
32433965Sjdp		if (((ifq)->ifq_head = (m)->m_nextpkt) == NULL)	\
32533965Sjdp			(ifq)->ifq_tail = NULL; 		\
32633965Sjdp		(m)->m_nextpkt = NULL; 				\
32777298Sobrien		(ifq)->ifq_len--; 				\
32860484Sobrien	} 							\
32933965Sjdp} while (0)
33033965Sjdp
33133965Sjdp#define IF_DEQUEUE(ifq, m) do { 				\
332218822Sdim	IF_LOCK(ifq); 						\
333218822Sdim	_IF_DEQUEUE(ifq, m); 					\
334218822Sdim	IF_UNLOCK(ifq); 					\
335218822Sdim} while (0)
336218822Sdim
337218822Sdim#define	_IF_DEQUEUE_ALL(ifq, m) do {				\
338218822Sdim	(m) = (ifq)->ifq_head;					\
339218822Sdim	(ifq)->ifq_head = (ifq)->ifq_tail = NULL;		\
340218822Sdim	(ifq)->ifq_len = 0;					\
341218822Sdim} while (0)
342218822Sdim
343218822Sdim#define	IF_DEQUEUE_ALL(ifq, m) do {				\
34433965Sjdp	IF_LOCK(ifq); 						\
345218822Sdim	_IF_DEQUEUE_ALL(ifq, m);				\
34633965Sjdp	IF_UNLOCK(ifq); 					\
34733965Sjdp} while (0)
34833965Sjdp
349218822Sdim#define	_IF_POLL(ifq, m)	((m) = (ifq)->ifq_head)
35033965Sjdp#define	IF_POLL(ifq, m)		_IF_POLL(ifq, m)
35133965Sjdp
35233965Sjdp#define _IF_DRAIN(ifq) do { 					\
353218822Sdim	struct mbuf *m; 					\
35433965Sjdp	for (;;) { 						\
355218822Sdim		_IF_DEQUEUE(ifq, m); 				\
356218822Sdim		if (m == NULL) 					\
35733965Sjdp			break; 					\
358218822Sdim		m_freem(m); 					\
35978828Sobrien	} 							\
36078828Sobrien} while (0)
361218822Sdim
36278828Sobrien#define IF_DRAIN(ifq) do {					\
36377298Sobrien	IF_LOCK(ifq);						\
36460484Sobrien	_IF_DRAIN(ifq);						\
36560484Sobrien	IF_UNLOCK(ifq);						\
36660484Sobrien} while(0)
36760484Sobrien
36860484Sobrien#ifdef _KERNEL
36978828Sobrien/* interface link layer address change event */
37033965Sjdptypedef void (*iflladdr_event_handler_t)(void *, struct ifnet *);
37133965SjdpEVENTHANDLER_DECLARE(iflladdr_event, iflladdr_event_handler_t);
37233965Sjdp/* interface address change event */
37333965Sjdptypedef void (*ifaddr_event_handler_t)(void *, struct ifnet *);
37433965SjdpEVENTHANDLER_DECLARE(ifaddr_event, ifaddr_event_handler_t);
37533965Sjdp/* new interface arrival event */
37633965Sjdptypedef void (*ifnet_arrival_event_handler_t)(void *, struct ifnet *);
37733965SjdpEVENTHANDLER_DECLARE(ifnet_arrival_event, ifnet_arrival_event_handler_t);
37833965Sjdp/* interface departure event */
379218822Sdimtypedef void (*ifnet_departure_event_handler_t)(void *, struct ifnet *);
38033965SjdpEVENTHANDLER_DECLARE(ifnet_departure_event, ifnet_departure_event_handler_t);
38133965Sjdp/* Interface link state change event */
38233965Sjdptypedef void (*ifnet_link_event_handler_t)(void *, struct ifnet *, int);
38360484SobrienEVENTHANDLER_DECLARE(ifnet_link_event, ifnet_link_event_handler_t);
38460484Sobrien
38533965Sjdp/*
38633965Sjdp * interface groups
38733965Sjdp */
38833965Sjdpstruct ifg_group {
38933965Sjdp	char				 ifg_group[IFNAMSIZ];
39033965Sjdp	u_int				 ifg_refcnt;
39133965Sjdp	void				*ifg_pf_kif;
392218822Sdim	TAILQ_HEAD(, ifg_member)	 ifg_members;
39333965Sjdp	TAILQ_ENTRY(ifg_group)		 ifg_next;
39433965Sjdp};
39533965Sjdp
39633965Sjdpstruct ifg_member {
39733965Sjdp	TAILQ_ENTRY(ifg_member)	 ifgm_next;
39860484Sobrien	struct ifnet		*ifgm_ifp;
39933965Sjdp};
40033965Sjdp
40133965Sjdpstruct ifg_list {
40233965Sjdp	struct ifg_group	*ifgl_group;
40333965Sjdp	TAILQ_ENTRY(ifg_list)	 ifgl_next;
40433965Sjdp};
40589857Sobrien
40689857Sobrien/* group attach event */
40789857Sobrientypedef void (*group_attach_event_handler_t)(void *, struct ifg_group *);
40833965SjdpEVENTHANDLER_DECLARE(group_attach_event, group_attach_event_handler_t);
40989857Sobrien/* group detach event */
41089857Sobrientypedef void (*group_detach_event_handler_t)(void *, struct ifg_group *);
41133965SjdpEVENTHANDLER_DECLARE(group_detach_event, group_detach_event_handler_t);
41233965Sjdp/* group change event */
41333965Sjdptypedef void (*group_change_event_handler_t)(void *, const char *);
41433965SjdpEVENTHANDLER_DECLARE(group_change_event, group_change_event_handler_t);
41533965Sjdp
41633965Sjdp#define	IF_AFDATA_LOCK_INIT(ifp)	\
41733965Sjdp	rw_init(&(ifp)->if_afdata_lock, "if_afdata")
41833965Sjdp
41933965Sjdp#define	IF_AFDATA_WLOCK(ifp)	rw_wlock(&(ifp)->if_afdata_lock)
42033965Sjdp#define	IF_AFDATA_RLOCK(ifp)	rw_rlock(&(ifp)->if_afdata_lock)
42133965Sjdp#define	IF_AFDATA_WUNLOCK(ifp)	rw_wunlock(&(ifp)->if_afdata_lock)
42233965Sjdp#define	IF_AFDATA_RUNLOCK(ifp)	rw_runlock(&(ifp)->if_afdata_lock)
42333965Sjdp#define	IF_AFDATA_LOCK(ifp)	IF_AFDATA_WLOCK(ifp)
42433965Sjdp#define	IF_AFDATA_UNLOCK(ifp)	IF_AFDATA_WUNLOCK(ifp)
42533965Sjdp#define	IF_AFDATA_TRYLOCK(ifp)	rw_try_wlock(&(ifp)->if_afdata_lock)
42633965Sjdp#define	IF_AFDATA_DESTROY(ifp)	rw_destroy(&(ifp)->if_afdata_lock)
42733965Sjdp
42860484Sobrien#define	IF_AFDATA_LOCK_ASSERT(ifp)	rw_assert(&(ifp)->if_afdata_lock, RA_LOCKED)
42960484Sobrien#define	IF_AFDATA_RLOCK_ASSERT(ifp)	rw_assert(&(ifp)->if_afdata_lock, RA_RLOCKED)
43060484Sobrien#define	IF_AFDATA_WLOCK_ASSERT(ifp)	rw_assert(&(ifp)->if_afdata_lock, RA_WLOCKED)
43160484Sobrien#define	IF_AFDATA_UNLOCK_ASSERT(ifp)	rw_assert(&(ifp)->if_afdata_lock, RA_UNLOCKED)
432218822Sdim
43360484Sobrienint	if_handoff(struct ifqueue *ifq, struct mbuf *m, struct ifnet *ifp,
43460484Sobrien	    int adjust);
43560484Sobrien#define	IF_HANDOFF(ifq, m, ifp)			\
43660484Sobrien	if_handoff((struct ifqueue *)ifq, m, ifp, 0)
43760484Sobrien#define	IF_HANDOFF_ADJ(ifq, m, ifp, adj)	\
43860484Sobrien	if_handoff((struct ifqueue *)ifq, m, ifp, adj)
43960484Sobrien
44060484Sobrienvoid	if_start(struct ifnet *);
44160484Sobrien
44260484Sobrien#define	IFQ_ENQUEUE(ifq, m, err)					\
44360484Sobriendo {									\
44460484Sobrien	IF_LOCK(ifq);							\
44560484Sobrien	if (ALTQ_IS_ENABLED(ifq))					\
44660484Sobrien		ALTQ_ENQUEUE(ifq, m, NULL, err);			\
44760484Sobrien	else {								\
44860484Sobrien		if (_IF_QFULL(ifq)) {					\
44960484Sobrien			m_freem(m);					\
45060484Sobrien			(err) = ENOBUFS;				\
45160484Sobrien		} else {						\
45260484Sobrien			_IF_ENQUEUE(ifq, m);				\
45360484Sobrien			(err) = 0;					\
45460484Sobrien		}							\
45560484Sobrien	}								\
45660484Sobrien	if (err)							\
45760484Sobrien		(ifq)->ifq_drops++;					\
45860484Sobrien	IF_UNLOCK(ifq);							\
45960484Sobrien} while (0)
46060484Sobrien
46160484Sobrien#define	IFQ_DEQUEUE_NOLOCK(ifq, m)					\
46260484Sobriendo {									\
46360484Sobrien	if (TBR_IS_ENABLED(ifq))					\
46460484Sobrien		(m) = tbr_dequeue_ptr(ifq, ALTDQ_REMOVE);		\
465104834Sobrien	else if (ALTQ_IS_ENABLED(ifq))					\
46660484Sobrien		ALTQ_DEQUEUE(ifq, m);					\
46760484Sobrien	else								\
46860484Sobrien		_IF_DEQUEUE(ifq, m);					\
46960484Sobrien} while (0)
47060484Sobrien
47160484Sobrien#define	IFQ_DEQUEUE(ifq, m)						\
47260484Sobriendo {									\
47360484Sobrien	IF_LOCK(ifq);							\
47460484Sobrien	IFQ_DEQUEUE_NOLOCK(ifq, m);					\
47560484Sobrien	IF_UNLOCK(ifq);							\
47660484Sobrien} while (0)
47760484Sobrien
47860484Sobrien#define	IFQ_POLL_NOLOCK(ifq, m)						\
479218822Sdimdo {									\
48060484Sobrien	if (TBR_IS_ENABLED(ifq))					\
48160484Sobrien		(m) = tbr_dequeue_ptr(ifq, ALTDQ_POLL);			\
48260484Sobrien	else if (ALTQ_IS_ENABLED(ifq))					\
48360484Sobrien		ALTQ_POLL(ifq, m);					\
48460484Sobrien	else								\
48560484Sobrien		_IF_POLL(ifq, m);					\
48660484Sobrien} while (0)
48760484Sobrien
48860484Sobrien#define	IFQ_POLL(ifq, m)						\
48960484Sobriendo {									\
49060484Sobrien	IF_LOCK(ifq);							\
49160484Sobrien	IFQ_POLL_NOLOCK(ifq, m);					\
49260484Sobrien	IF_UNLOCK(ifq);							\
49360484Sobrien} while (0)
49460484Sobrien
49560484Sobrien#define	IFQ_PURGE_NOLOCK(ifq)						\
49660484Sobriendo {									\
49760484Sobrien	if (ALTQ_IS_ENABLED(ifq)) {					\
49860484Sobrien		ALTQ_PURGE(ifq);					\
49960484Sobrien	} else								\
50060484Sobrien		_IF_DRAIN(ifq);						\
50160484Sobrien} while (0)
50260484Sobrien
50360484Sobrien#define	IFQ_PURGE(ifq)							\
504218822Sdimdo {									\
50533965Sjdp	IF_LOCK(ifq);							\
506218822Sdim	IFQ_PURGE_NOLOCK(ifq);						\
507218822Sdim	IF_UNLOCK(ifq);							\
508218822Sdim} while (0)
509218822Sdim
510218822Sdim#define	IFQ_SET_READY(ifq)						\
511218822Sdim	do { ((ifq)->altq_flags |= ALTQF_READY); } while (0)
512218822Sdim
51333965Sjdp#define	IFQ_LOCK(ifq)			IF_LOCK(ifq)
51433965Sjdp#define	IFQ_UNLOCK(ifq)			IF_UNLOCK(ifq)
515218822Sdim#define	IFQ_LOCK_ASSERT(ifq)		IF_LOCK_ASSERT(ifq)
516218822Sdim#define	IFQ_IS_EMPTY(ifq)		((ifq)->ifq_len == 0)
51733965Sjdp#define	IFQ_INC_LEN(ifq)		((ifq)->ifq_len++)
51833965Sjdp#define	IFQ_DEC_LEN(ifq)		(--(ifq)->ifq_len)
519218822Sdim#define	IFQ_INC_DROPS(ifq)		((ifq)->ifq_drops++)
52033965Sjdp#define	IFQ_SET_MAXLEN(ifq, len)	((ifq)->ifq_maxlen = (len))
521218822Sdim
522218822Sdim/*
523218822Sdim * The IFF_DRV_OACTIVE test should really occur in the device driver, not in
52433965Sjdp * the handoff logic, as that flag is locked by the device driver.
52533965Sjdp */
52633965Sjdp#define	IFQ_HANDOFF_ADJ(ifp, m, adj, err)				\
52733965Sjdpdo {									\
52860484Sobrien	int len;							\
52933965Sjdp	short mflags;							\
53033965Sjdp									\
531218822Sdim	len = (m)->m_pkthdr.len;					\
53233965Sjdp	mflags = (m)->m_flags;						\
53333965Sjdp	IFQ_ENQUEUE(&(ifp)->if_snd, m, err);				\
53433965Sjdp	if ((err) == 0) {						\
53533965Sjdp		(ifp)->if_obytes += len + (adj);			\
53633965Sjdp		if (mflags & M_MCAST)					\
53733965Sjdp			(ifp)->if_omcasts++;				\
53833965Sjdp		if (((ifp)->if_drv_flags & IFF_DRV_OACTIVE) == 0)	\
53933965Sjdp			if_start(ifp);					\
54033965Sjdp	}								\
54133965Sjdp} while (0)
54233965Sjdp
54333965Sjdp#define	IFQ_HANDOFF(ifp, m, err)					\
544218822Sdim	IFQ_HANDOFF_ADJ(ifp, m, 0, err)
54533965Sjdp
54660484Sobrien#define	IFQ_DRV_DEQUEUE(ifq, m)						\
54733965Sjdpdo {									\
54833965Sjdp	(m) = (ifq)->ifq_drv_head;					\
54933965Sjdp	if (m) {							\
55033965Sjdp		if (((ifq)->ifq_drv_head = (m)->m_nextpkt) == NULL)	\
55133965Sjdp			(ifq)->ifq_drv_tail = NULL;			\
55233965Sjdp		(m)->m_nextpkt = NULL;					\
55333965Sjdp		(ifq)->ifq_drv_len--;					\
55433965Sjdp	} else {							\
55533965Sjdp		IFQ_LOCK(ifq);						\
55633965Sjdp		IFQ_DEQUEUE_NOLOCK(ifq, m);				\
55733965Sjdp		while ((ifq)->ifq_drv_len < (ifq)->ifq_drv_maxlen) {	\
55833965Sjdp			struct mbuf *m0;				\
55933965Sjdp			IFQ_DEQUEUE_NOLOCK(ifq, m0);			\
560218822Sdim			if (m0 == NULL)					\
56133965Sjdp				break;					\
56277298Sobrien			m0->m_nextpkt = NULL;				\
56360484Sobrien			if ((ifq)->ifq_drv_tail == NULL)		\
56433965Sjdp				(ifq)->ifq_drv_head = m0;		\
56533965Sjdp			else						\
56633965Sjdp				(ifq)->ifq_drv_tail->m_nextpkt = m0;	\
56760484Sobrien			(ifq)->ifq_drv_tail = m0;			\
56833965Sjdp			(ifq)->ifq_drv_len++;				\
56933965Sjdp		}							\
570218822Sdim		IFQ_UNLOCK(ifq);					\
57133965Sjdp	}								\
57277298Sobrien} while (0)
57333965Sjdp
57433965Sjdp#define	IFQ_DRV_PREPEND(ifq, m)						\
57533965Sjdpdo {									\
57633965Sjdp	(m)->m_nextpkt = (ifq)->ifq_drv_head;				\
57733965Sjdp	if ((ifq)->ifq_drv_tail == NULL)				\
57833965Sjdp		(ifq)->ifq_drv_tail = (m);				\
579218822Sdim	(ifq)->ifq_drv_head = (m);					\
58033965Sjdp	(ifq)->ifq_drv_len++;						\
58133965Sjdp} while (0)
58233965Sjdp
58333965Sjdp#define	IFQ_DRV_IS_EMPTY(ifq)						\
58433965Sjdp	(((ifq)->ifq_drv_len == 0) && ((ifq)->ifq_len == 0))
58533965Sjdp
58633965Sjdp#define	IFQ_DRV_PURGE(ifq)						\
58777298Sobriendo {									\
588218822Sdim	struct mbuf *m, *n = (ifq)->ifq_drv_head;			\
58933965Sjdp	while((m = n) != NULL) {					\
590218822Sdim		n = m->m_nextpkt;					\
591218822Sdim		m_freem(m);						\
59233965Sjdp	}								\
59333965Sjdp	(ifq)->ifq_drv_head = (ifq)->ifq_drv_tail = NULL;		\
594104834Sobrien	(ifq)->ifq_drv_len = 0;						\
595218822Sdim	IFQ_PURGE(ifq);							\
59633965Sjdp} while (0)
59733965Sjdp
59860484Sobrien#ifdef _KERNEL
59960484Sobrienstatic __inline void
600104834Sobrienif_initbaudrate(struct ifnet *ifp, uintmax_t baud)
60160484Sobrien{
60260484Sobrien
60377298Sobrien	ifp->if_baudrate_pf = 0;
60460484Sobrien	while (baud > (u_long)(~0UL)) {
60560484Sobrien		baud /= 10;
60660484Sobrien		ifp->if_baudrate_pf++;
60760484Sobrien	}
60860484Sobrien	ifp->if_baudrate = baud;
60960484Sobrien}
61060484Sobrien
61160484Sobrienstatic __inline int
61277298Sobriendrbr_enqueue(struct ifnet *ifp, struct buf_ring *br, struct mbuf *m)
61360484Sobrien{
61460484Sobrien	int error = 0;
61560484Sobrien
61660484Sobrien#ifdef ALTQ
61777298Sobrien	if (ALTQ_IS_ENABLED(&ifp->if_snd)) {
61860484Sobrien		IFQ_ENQUEUE(&ifp->if_snd, m, error);
61960484Sobrien		return (error);
62060484Sobrien	}
62160484Sobrien#endif
62260484Sobrien	error = buf_ring_enqueue(br, m);
62333965Sjdp	if (error)
62433965Sjdp		m_freem(m);
62533965Sjdp
62633965Sjdp	return (error);
62733965Sjdp}
62833965Sjdp
62933965Sjdpstatic __inline void
63033965Sjdpdrbr_putback(struct ifnet *ifp, struct buf_ring *br, struct mbuf *new)
63133965Sjdp{
63233965Sjdp	/*
63333965Sjdp	 * The top of the list needs to be swapped
63433965Sjdp	 * for this one.
63577298Sobrien	 */
63677298Sobrien#ifdef ALTQ
63777298Sobrien	if (ifp != NULL && ALTQ_IS_ENABLED(&ifp->if_snd)) {
63877298Sobrien		/*
63977298Sobrien		 * Peek in altq case dequeued it
64077298Sobrien		 * so put it back.
64177298Sobrien		 */
64277298Sobrien		IFQ_DRV_PREPEND(&ifp->if_snd, new);
64377298Sobrien		return;
64477298Sobrien	}
64577298Sobrien#endif
64677298Sobrien	buf_ring_putback_sc(br, new);
64777298Sobrien}
64877298Sobrien
64977298Sobrienstatic __inline struct mbuf *
65077298Sobriendrbr_peek(struct ifnet *ifp, struct buf_ring *br)
65177298Sobrien{
65277298Sobrien#ifdef ALTQ
65377298Sobrien	struct mbuf *m;
65477298Sobrien	if (ifp != NULL && ALTQ_IS_ENABLED(&ifp->if_snd)) {
65577298Sobrien		/*
65677298Sobrien		 * Pull it off like a dequeue
65777298Sobrien		 * since drbr_advance() does nothing
65877298Sobrien		 * for altq and drbr_putback() will
65977298Sobrien		 * use the old prepend function.
66077298Sobrien		 */
66177298Sobrien		IFQ_DEQUEUE(&ifp->if_snd, m);
66277298Sobrien		return (m);
66377298Sobrien	}
66477298Sobrien#endif
66577298Sobrien	return(buf_ring_peek(br));
66633965Sjdp}
66733965Sjdp
66833965Sjdpstatic __inline void
66933965Sjdpdrbr_flush(struct ifnet *ifp, struct buf_ring *br)
67077298Sobrien{
67133965Sjdp	struct mbuf *m;
67233965Sjdp
67333965Sjdp#ifdef ALTQ
67433965Sjdp	if (ifp != NULL && ALTQ_IS_ENABLED(&ifp->if_snd))
67533965Sjdp		IFQ_PURGE(&ifp->if_snd);
67633965Sjdp#endif
67777298Sobrien	while ((m = buf_ring_dequeue_sc(br)) != NULL)
67833965Sjdp		m_freem(m);
67933965Sjdp}
68060484Sobrien
68160484Sobrienstatic __inline void
68260484Sobriendrbr_free(struct buf_ring *br, struct malloc_type *type)
68360484Sobrien{
68433965Sjdp
68533965Sjdp	drbr_flush(NULL, br);
686218822Sdim	buf_ring_free(br, type);
68733965Sjdp}
68833965Sjdp
68960484Sobrienstatic __inline struct mbuf *
69033965Sjdpdrbr_dequeue(struct ifnet *ifp, struct buf_ring *br)
69133965Sjdp{
69233965Sjdp#ifdef ALTQ
69360484Sobrien	struct mbuf *m;
69433965Sjdp
69533965Sjdp	if (ifp != NULL && ALTQ_IS_ENABLED(&ifp->if_snd)) {
696218822Sdim		IFQ_DEQUEUE(&ifp->if_snd, m);
69733965Sjdp		return (m);
69833965Sjdp	}
69933965Sjdp#endif
70060484Sobrien	return (buf_ring_dequeue_sc(br));
70160484Sobrien}
70260484Sobrien
70360484Sobrienstatic __inline void
70433965Sjdpdrbr_advance(struct ifnet *ifp, struct buf_ring *br)
70533965Sjdp{
70633965Sjdp#ifdef ALTQ
70733965Sjdp	/* Nothing to do here since peek dequeues in altq case */
70833965Sjdp	if (ifp != NULL && ALTQ_IS_ENABLED(&ifp->if_snd))
70933965Sjdp		return;
71033965Sjdp#endif
71177298Sobrien	return (buf_ring_advance_sc(br));
71233965Sjdp}
71333965Sjdp
71433965Sjdp
71577298Sobrienstatic __inline struct mbuf *
71633965Sjdpdrbr_dequeue_cond(struct ifnet *ifp, struct buf_ring *br,
71733965Sjdp    int (*func) (struct mbuf *, void *), void *arg)
71860484Sobrien{
719218822Sdim	struct mbuf *m;
720218822Sdim#ifdef ALTQ
721218822Sdim	if (ALTQ_IS_ENABLED(&ifp->if_snd)) {
72233965Sjdp		IFQ_LOCK(&ifp->if_snd);
72333965Sjdp		IFQ_POLL_NOLOCK(&ifp->if_snd, m);
72460484Sobrien		if (m != NULL && func(m, arg) == 0) {
725218822Sdim			IFQ_UNLOCK(&ifp->if_snd);
72660484Sobrien			return (NULL);
72733965Sjdp		}
72860484Sobrien		IFQ_DEQUEUE_NOLOCK(&ifp->if_snd, m);
72933965Sjdp		IFQ_UNLOCK(&ifp->if_snd);
730104834Sobrien		return (m);
73160484Sobrien	}
73260484Sobrien#endif
73360484Sobrien	m = buf_ring_peek(br);
734104834Sobrien	if (m == NULL || func(m, arg) == 0)
73533965Sjdp		return (NULL);
73633965Sjdp
73733965Sjdp	return (buf_ring_dequeue_sc(br));
73833965Sjdp}
73933965Sjdp
74033965Sjdpstatic __inline int
74133965Sjdpdrbr_empty(struct ifnet *ifp, struct buf_ring *br)
742218822Sdim{
74333965Sjdp#ifdef ALTQ
74433965Sjdp	if (ALTQ_IS_ENABLED(&ifp->if_snd))
74577298Sobrien		return (IFQ_IS_EMPTY(&ifp->if_snd));
74633965Sjdp#endif
74733965Sjdp	return (buf_ring_empty(br));
74833965Sjdp}
74933965Sjdp
75033965Sjdpstatic __inline int
75133965Sjdpdrbr_needs_enqueue(struct ifnet *ifp, struct buf_ring *br)
75233965Sjdp{
75333965Sjdp#ifdef ALTQ
75433965Sjdp	if (ALTQ_IS_ENABLED(&ifp->if_snd))
75533965Sjdp		return (1);
75633965Sjdp#endif
75733965Sjdp	return (!buf_ring_empty(br));
75877298Sobrien}
759218822Sdim
76033965Sjdpstatic __inline int
76133965Sjdpdrbr_inuse(struct ifnet *ifp, struct buf_ring *br)
76233965Sjdp{
76333965Sjdp#ifdef ALTQ
76433965Sjdp	if (ALTQ_IS_ENABLED(&ifp->if_snd))
76533965Sjdp		return (ifp->if_snd.ifq_len);
76633965Sjdp#endif
76733965Sjdp	return (buf_ring_count(br));
76833965Sjdp}
76933965Sjdp#endif
77033965Sjdp/*
77133965Sjdp * 72 was chosen below because it is the size of a TCP/IP
772218822Sdim * header (40) + the minimum mss (32).
77333965Sjdp */
77433965Sjdp#define	IF_MINMTU	72
77533965Sjdp#define	IF_MAXMTU	65535
77633965Sjdp
77733965Sjdp#define	TOEDEV(ifp)	((ifp)->if_llsoftc)
77833965Sjdp
77933965Sjdp#endif /* _KERNEL */
78033965Sjdp
78133965Sjdp/*
78233965Sjdp * The ifaddr structure contains information about one address
78333965Sjdp * of an interface.  They are maintained by the different address families,
78433965Sjdp * are allocated and attached when an address is set, and are linked
785218822Sdim * together so all addresses for an interface can be located.
786218822Sdim *
787218822Sdim * NOTE: a 'struct ifaddr' is always at the beginning of a larger
78833965Sjdp * chunk of malloc'ed memory, where we store the three addresses
789218822Sdim * (ifa_addr, ifa_dstaddr and ifa_netmask) referenced here.
790218822Sdim */
79133965Sjdp#if defined(_KERNEL) || defined(_WANT_IFADDR)
79233965Sjdpstruct ifaddr {
79333965Sjdp	struct	sockaddr *ifa_addr;	/* address of interface */
79433965Sjdp	struct	sockaddr *ifa_dstaddr;	/* other end of p-to-p link */
79533965Sjdp#define	ifa_broadaddr	ifa_dstaddr	/* broadcast address interface */
796218822Sdim	struct	sockaddr *ifa_netmask;	/* used to determine subnet */
79733965Sjdp	struct	if_data if_data;	/* not all members are meaningful */
79833965Sjdp	struct	ifnet *ifa_ifp;		/* back-pointer to interface */
79933965Sjdp	struct	carp_softc *ifa_carp;	/* pointer to CARP data */
80033965Sjdp	TAILQ_ENTRY(ifaddr) ifa_link;	/* queue macro glue */
80133965Sjdp	void	(*ifa_rtrequest)	/* check or clean routes (+ or -)'d */
80260484Sobrien		(int, struct rtentry *, struct rt_addrinfo *);
80333965Sjdp	u_short	ifa_flags;		/* mostly rt_flags for cloning */
80433965Sjdp	u_int	ifa_refcnt;		/* references to this structure */
805218822Sdim	int	ifa_metric;		/* cost of going out this interface */
80633965Sjdp	int (*ifa_claim_addr)		/* check if an addr goes to this if */
80733965Sjdp		(struct ifaddr *, struct sockaddr *);
80833965Sjdp};
80933965Sjdp#endif
81033965Sjdp
81133965Sjdp#define	IFA_ROUTE	RTF_UP		/* route installed */
81233965Sjdp#define IFA_RTSELF	RTF_HOST	/* loopback route to self installed */
81333965Sjdp
81433965Sjdp/* for compatibility with other BSDs */
81533965Sjdp#define	ifa_list	ifa_link
81633965Sjdp
81733965Sjdp#ifdef _KERNEL
81833965Sjdpstruct ifaddr *	ifa_alloc(size_t size, int flags);
81933965Sjdpvoid	ifa_free(struct ifaddr *ifa);
82033965Sjdpvoid	ifa_ref(struct ifaddr *ifa);
82133965Sjdp#endif
82260484Sobrien
823218822Sdim/*
82433965Sjdp * Multicast address structure.  This is analogous to the ifaddr
82533965Sjdp * structure except that it keeps track of multicast addresses.
82633965Sjdp */
82733965Sjdpstruct ifmultiaddr {
82833965Sjdp	TAILQ_ENTRY(ifmultiaddr) ifma_link; /* queue macro glue */
82933965Sjdp	struct	sockaddr *ifma_addr; 	/* address this membership is for */
83033965Sjdp	struct	sockaddr *ifma_lladdr;	/* link-layer translation, if any */
83133965Sjdp	struct	ifnet *ifma_ifp;	/* back-pointer to interface */
83233965Sjdp	u_int	ifma_refcount;		/* reference count */
83333965Sjdp	void	*ifma_protospec;	/* protocol-specific state, if any */
83433965Sjdp	struct	ifmultiaddr *ifma_llifma; /* pointer to ifma for ifma_lladdr */
835218822Sdim};
83633965Sjdp
83733965Sjdp#ifdef _KERNEL
83833965Sjdp
83933965Sjdpextern	struct rwlock ifnet_rwlock;
84033965Sjdpextern	struct sx ifnet_sxlock;
84133965Sjdp
84233965Sjdp#define	IFNET_LOCK_INIT() do {						\
84333965Sjdp	rw_init_flags(&ifnet_rwlock, "ifnet_rw",  RW_RECURSE);		\
84433965Sjdp	sx_init_flags(&ifnet_sxlock, "ifnet_sx",  SX_RECURSE);		\
84533965Sjdp} while(0)
84633965Sjdp
847218822Sdim#define	IFNET_WLOCK() do {						\
84833965Sjdp	sx_xlock(&ifnet_sxlock);					\
84933965Sjdp	rw_wlock(&ifnet_rwlock);					\
85033965Sjdp} while (0)
85160484Sobrien
85233965Sjdp#define	IFNET_WUNLOCK() do {						\
85333965Sjdp	rw_wunlock(&ifnet_rwlock);					\
85433965Sjdp	sx_xunlock(&ifnet_sxlock);					\
85533965Sjdp} while (0)
856218822Sdim
85733965Sjdp/*
85833965Sjdp * To assert the ifnet lock, you must know not only whether it's for read or
85933965Sjdp * write, but also whether it was acquired with sleep support or not.
86033965Sjdp */
86160484Sobrien#define	IFNET_RLOCK_ASSERT()		sx_assert(&ifnet_sxlock, SA_SLOCKED)
86233965Sjdp#define	IFNET_RLOCK_NOSLEEP_ASSERT()	rw_assert(&ifnet_rwlock, RA_RLOCKED)
86333965Sjdp#define	IFNET_WLOCK_ASSERT() do {					\
86433965Sjdp	sx_assert(&ifnet_sxlock, SA_XLOCKED);				\
86533965Sjdp	rw_assert(&ifnet_rwlock, RA_WLOCKED);				\
86633965Sjdp} while (0)
867218822Sdim
86833965Sjdp#define	IFNET_RLOCK()		sx_slock(&ifnet_sxlock)
86933965Sjdp#define	IFNET_RLOCK_NOSLEEP()	rw_rlock(&ifnet_rwlock)
87033965Sjdp#define	IFNET_RUNLOCK()		sx_sunlock(&ifnet_sxlock)
87160484Sobrien#define	IFNET_RUNLOCK_NOSLEEP()	rw_runlock(&ifnet_rwlock)
87233965Sjdp
87333965Sjdp/*
874218822Sdim * Look up an ifnet given its index; the _ref variant also acquires a
87533965Sjdp * reference that must be freed using if_rele().  It is almost always a bug
87633965Sjdp * to call ifnet_byindex() instead if ifnet_byindex_ref().
87733965Sjdp */
87833965Sjdpstruct ifnet	*ifnet_byindex(u_short idx);
87933965Sjdpstruct ifnet	*ifnet_byindex_locked(u_short idx);
88033965Sjdpstruct ifnet	*ifnet_byindex_ref(u_short idx);
88133965Sjdp
882218822Sdim/*
88333965Sjdp * Given the index, ifaddr_byindex() returns the one and only
88433965Sjdp * link-level ifaddr for the interface. You are not supposed to use
88533965Sjdp * it to traverse the list of addresses associated to the interface.
88660484Sobrien */
88733965Sjdpstruct ifaddr	*ifaddr_byindex(u_short idx);
88833965Sjdp
889218822SdimVNET_DECLARE(struct ifnethead, ifnet);
89033965SjdpVNET_DECLARE(struct ifgrouphead, ifg_head);
89133965SjdpVNET_DECLARE(int, if_index);
89233965SjdpVNET_DECLARE(struct ifnet *, loif);	/* first loopback interface */
89333965SjdpVNET_DECLARE(int, useloopback);
89433965Sjdp
89533965Sjdp#define	V_ifnet		VNET(ifnet)
896218822Sdim#define	V_ifg_head	VNET(ifg_head)
89733965Sjdp#define	V_if_index	VNET(if_index)
89833965Sjdp#define	V_loif		VNET(loif)
89933965Sjdp#define	V_useloopback	VNET(useloopback)
90033965Sjdp
90133965Sjdpextern	int ifqmaxlen;
90233965Sjdp
90360484Sobrienint	if_addgroup(struct ifnet *, const char *);
90433965Sjdpint	if_delgroup(struct ifnet *, const char *);
90533965Sjdpint	if_addmulti(struct ifnet *, struct sockaddr *, struct ifmultiaddr **);
90633965Sjdpint	if_allmulti(struct ifnet *, int);
90733965Sjdpstruct	ifnet* if_alloc(u_char);
90833965Sjdpvoid	if_attach(struct ifnet *);
90933965Sjdpvoid	if_dead(struct ifnet *);
91033965Sjdpint	if_delmulti(struct ifnet *, struct sockaddr *);
91133965Sjdpvoid	if_delmulti_ifma(struct ifmultiaddr *);
91233965Sjdpvoid	if_detach(struct ifnet *);
91333965Sjdpvoid	if_vmove(struct ifnet *, struct vnet *);
91433965Sjdpvoid	if_purgeaddrs(struct ifnet *);
91533965Sjdpvoid	if_delallmulti(struct ifnet *);
91633965Sjdpvoid	if_down(struct ifnet *);
91777298Sobrienstruct ifmultiaddr *
91833965Sjdp	if_findmulti(struct ifnet *, struct sockaddr *);
91933965Sjdpvoid	if_free(struct ifnet *);
92033965Sjdpvoid	if_initname(struct ifnet *, const char *, int);
921218822Sdimvoid	if_link_state_change(struct ifnet *, int);
92233965Sjdpint	if_printf(struct ifnet *, const char *, ...) __printflike(2, 3);
92333965Sjdpvoid	if_qflush(struct ifnet *);
92433965Sjdpvoid	if_ref(struct ifnet *);
92533965Sjdpvoid	if_rele(struct ifnet *);
92633965Sjdpint	if_setlladdr(struct ifnet *, const u_char *, int);
92733965Sjdpvoid	if_up(struct ifnet *);
92833965Sjdpint	ifioctl(struct socket *, u_long, caddr_t, struct thread *);
92933965Sjdpint	ifpromisc(struct ifnet *, int);
930218822Sdimstruct	ifnet *ifunit(const char *);
93133965Sjdpstruct	ifnet *ifunit_ref(const char *);
93233965Sjdp
93333965Sjdpvoid	ifq_init(struct ifaltq *, struct ifnet *ifp);
93460484Sobrienvoid	ifq_delete(struct ifaltq *);
93533965Sjdp
93633965Sjdpint	ifa_add_loopback_route(struct ifaddr *, struct sockaddr *);
937218822Sdimint	ifa_del_loopback_route(struct ifaddr *, struct sockaddr *);
93833965Sjdp
93933965Sjdpstruct	ifaddr *ifa_ifwithaddr(struct sockaddr *);
94033965Sjdpint		ifa_ifwithaddr_check(struct sockaddr *);
94133965Sjdpstruct	ifaddr *ifa_ifwithbroadaddr(struct sockaddr *);
94233965Sjdpstruct	ifaddr *ifa_ifwithdstaddr(struct sockaddr *);
943218822Sdimstruct	ifaddr *ifa_ifwithnet(struct sockaddr *, int);
94433965Sjdpstruct	ifaddr *ifa_ifwithroute(int, struct sockaddr *, struct sockaddr *);
94533965Sjdpstruct	ifaddr *ifa_ifwithroute_fib(int, struct sockaddr *, struct sockaddr *, u_int);
94633965Sjdpstruct	ifaddr *ifaof_ifpforaddr(struct sockaddr *, struct ifnet *);
94733965Sjdpint	ifa_preferred(struct ifaddr *, struct ifaddr *);
94833965Sjdp
949218822Sdimint	if_simloop(struct ifnet *ifp, struct mbuf *m, int af, int hlen);
95033965Sjdp
95133965Sjdptypedef	void *if_com_alloc_t(u_char type, struct ifnet *ifp);
95233965Sjdptypedef	void if_com_free_t(void *com, u_char type);
95360484Sobrienvoid	if_register_com_alloc(u_char type, if_com_alloc_t *a, if_com_free_t *f);
95433965Sjdpvoid	if_deregister_com_alloc(u_char type);
95533965Sjdp
956218822Sdim#define IF_LLADDR(ifp)							\
95733965Sjdp    LLADDR((struct sockaddr_dl *)((ifp)->if_addr->ifa_addr))
95833965Sjdp
95933965Sjdp#ifdef DEVICE_POLLING
96033965Sjdpenum poll_cmd {	POLL_ONLY, POLL_AND_CHECK_STATUS };
96133965Sjdp
96233965Sjdptypedef	int poll_handler_t(struct ifnet *ifp, enum poll_cmd cmd, int count);
96333965Sjdpint    ether_poll_register(poll_handler_t *h, struct ifnet *ifp);
96433965Sjdpint    ether_poll_deregister(struct ifnet *ifp);
96533965Sjdp#endif /* DEVICE_POLLING */
966218822Sdim
96733965Sjdp#endif /* _KERNEL */
968218822Sdim
96960484Sobrien#endif /* !_NET_IF_VAR_H_ */
97033965Sjdp