#ifndef _NET_IF_H_
#define _NET_IF_H_
#if !defined(_KERNEL) && !defined(_STANDALONE)
#include <stdbool.h>
#endif
#include <sys/featuretest.h>
#define IF_NAMESIZE 16
#define IFDESCRSIZE 64
#if defined(_NETBSD_SOURCE)
#include <sys/socket.h>
#include <sys/queue.h>
#include <sys/mutex.h>
#include <sys/hook.h>
#include <net/dlt.h>
#include <net/pfil.h>
#ifdef _KERNEL
#include <net/pktqueue.h>
#include <sys/pslist.h>
#include <sys/pserialize.h>
#include <sys/psref.h>
#include <sys/module_hook.h>
#endif
#include <altq/if_altq.h>
#include <sys/time.h>
#if defined(_KERNEL_OPT)
#include "opt_compat_netbsd.h"
#include "opt_gateway.h"
#endif
struct mbuf;
struct proc;
struct rtentry;
struct socket;
struct ether_header;
struct ifaddr;
struct ifnet;
struct rt_addrinfo;
#define IFNAMSIZ IF_NAMESIZE
struct if_clone {
LIST_ENTRY(if_clone) ifc_list;
const char *ifc_name;
size_t ifc_namelen;
int (*ifc_create)(struct if_clone *, int);
int (*ifc_destroy)(struct ifnet *);
};
#define IF_CLONE_INITIALIZER(name, create, destroy) \
{ { NULL, NULL }, name, sizeof(name) - 1, create, destroy }
struct if_clonereq {
int ifcr_total;
int ifcr_count;
char *ifcr_buffer;
};
struct if_data {
u_char ifi_type;
u_char ifi_addrlen;
u_char ifi_hdrlen;
int ifi_link_state;
uint64_t ifi_mtu;
uint64_t ifi_metric;
uint64_t ifi_baudrate;
uint64_t ifi_ipackets;
uint64_t ifi_ierrors;
uint64_t ifi_opackets;
uint64_t ifi_oerrors;
uint64_t ifi_collisions;
uint64_t ifi_ibytes;
uint64_t ifi_obytes;
uint64_t ifi_imcasts;
uint64_t ifi_omcasts;
uint64_t ifi_iqdrops;
uint64_t ifi_noproto;
struct timespec ifi_lastchange;
};
#define LINK_STATE_UNKNOWN 0
#define LINK_STATE_DOWN 1
#define LINK_STATE_UP 2
struct if_status_description {
unsigned char ifs_type;
unsigned char ifs_state;
const char *ifs_string;
};
#define LINK_STATE_DESC_MATCH(_ifs, _t, _s) \
(((_ifs)->ifs_type == (_t) || (_ifs)->ifs_type == 0) && \
(_ifs)->ifs_state == (_s))
#define LINK_STATE_DESCRIPTIONS { \
{ IFT_ETHER, LINK_STATE_DOWN, "no carrier" }, \
{ IFT_IEEE80211, LINK_STATE_DOWN, "no network" }, \
{ IFT_PPP, LINK_STATE_DOWN, "no carrier" }, \
{ IFT_CARP, LINK_STATE_DOWN, "backup" }, \
{ IFT_CARP, LINK_STATE_UP, "master" }, \
{ 0, LINK_STATE_UP, "active" }, \
{ 0, LINK_STATE_UNKNOWN, "unknown" }, \
{ 0, LINK_STATE_DOWN, "down" }, \
{ 0, 0, NULL } \
}
struct ifqueue {
struct mbuf *ifq_head;
struct mbuf *ifq_tail;
int ifq_len;
int ifq_maxlen;
uint64_t ifq_drops;
kmutex_t *ifq_lock;
};
#ifdef _KERNEL
#include <sys/percpu.h>
#include <sys/callout.h>
#include <sys/rwlock.h>
#include <sys/workqueue.h>
#endif
TAILQ_HEAD(ifnet_head, ifnet);
struct bridge_softc;
struct bridge_iflist;
struct callout;
struct krwlock;
struct if_percpuq;
struct if_deferred_start;
struct in6_multi;
typedef unsigned short if_index_t;
typedef struct ifnet {
void *if_softc;
TAILQ_ENTRY(ifnet)
if_list;
TAILQ_HEAD(, ifaddr)
if_addrlist;
char if_xname[IFNAMSIZ];
int if_pcount;
struct bpf_if *if_bpf;
if_index_t if_index;
short if_timer;
unsigned short if_flags;
short if_extflags;
u_char if_type;
u_char if_addrlen;
u_char if_hdrlen;
int if_link_state;
uint64_t if_mtu;
uint64_t if_metric;
uint64_t if_baudrate;
struct timespec if_lastchange;
#ifdef _KERNEL
percpu_t *if_stats;
#else
void *if_stats;
#endif
int (*if_output)
(struct ifnet *, struct mbuf *, const struct sockaddr *,
const struct rtentry *);
void (*_if_input)
(struct ifnet *, struct mbuf *);
void (*if_start)
(struct ifnet *);
int (*if_transmit)
(struct ifnet *, struct mbuf *);
int (*if_ioctl)
(struct ifnet *, u_long, void *);
int (*if_init)
(struct ifnet *);
void (*if_stop)
(struct ifnet *, int);
void (*if_slowtimo)
(struct ifnet *);
#define if_watchdog if_slowtimo
void (*if_drain)
(struct ifnet *);
void (*if_bpf_mtap)
(struct bpf_if *, struct mbuf *, u_int);
struct ifaltq if_snd;
struct ifaddr *if_dl;
const struct sockaddr_dl
*if_sadl;
struct ifaddr *if_hwdl;
const uint8_t *if_broadcastaddr;
struct bridge_softc
*if_bridge;
struct bridge_iflist
*if_bridgeif;
int if_dlt;
pfil_head_t * if_pfil;
uint64_t if_capabilities;
uint64_t if_capenable;
union {
void * carp_s;
struct ifnet *carp_d;
} if_carp_ptr;
#define if_carp if_carp_ptr.carp_s
#define if_carpdev if_carp_ptr.carp_d
int if_csum_flags_tx;
int if_csum_flags_rx;
void *if_afdata[AF_MAX];
struct mowner *if_mowner;
void *if_lagg;
void *if_npf_private;
void *if_pf_kif;
void *if_pf_groups;
uint64_t if_index_gen;
struct sysctllog
*if_sysctl_log;
int (*if_initaddr)
(struct ifnet *, struct ifaddr *, bool);
int (*if_setflags)
(struct ifnet *, const u_short);
kmutex_t *if_ioctl_lock;
char *if_description;
#ifdef _KERNEL
struct if_slowtimo_data *if_slowtimo_data;
struct krwlock *if_afdata_lock;
struct if_percpuq
*if_percpuq;
struct work if_link_work;
uint16_t if_link_queue;
#define LINK_QUEUE_LOCKED (1 << 0)
#define LINK_QUEUE_SCHEDULED (1 << 1)
#define LINK_QUEUE_DOWN (1 << 2)
#define LINK_QUEUE_UNKNOWN (1 << 3)
#define LINK_QUEUE_UP (1 << 4)
bool if_link_scheduled;
struct pslist_entry
if_pslist_entry;
struct psref_target
if_psref;
struct pslist_head
if_addr_pslist;
struct if_deferred_start
*if_deferred_start;
LIST_HEAD(, in6_multi)
if_multiaddrs;
khook_list_t *if_linkstate_hooks;
#endif
} ifnet_t;
#include <net/if_stats.h>
#define if_name(ifp) ((ifp)->if_xname)
#define IFF_UP 0x0001
#define IFF_BROADCAST 0x0002
#define IFF_DEBUG 0x0004
#define IFF_LOOPBACK 0x0008
#define IFF_POINTOPOINT 0x0010
#if 0
#else
#define IFF_UNNUMBERED 0x0020
#endif
#define IFF_RUNNING 0x0040
#define IFF_NOARP 0x0080
#define IFF_PROMISC 0x0100
#define IFF_ALLMULTI 0x0200
#define IFF_OACTIVE 0x0400
#define IFF_SIMPLEX 0x0800
#define IFF_LINK0 0x1000
#define IFF_LINK1 0x2000
#define IFF_LINK2 0x4000
#define IFF_MULTICAST 0x8000
#define IFEF_MPSAFE __BIT(0)
#ifdef _KERNEL
static __inline bool
if_is_mpsafe(struct ifnet *ifp)
{
return ((ifp->if_extflags & IFEF_MPSAFE) != 0);
}
static __inline int
if_output_lock(struct ifnet *cifp, struct ifnet *ifp, struct mbuf *m,
const struct sockaddr *dst, const struct rtentry *rt)
{
if (if_is_mpsafe(cifp)) {
return (*cifp->if_output)(ifp, m, dst, rt);
} else {
int ret;
KERNEL_LOCK(1, NULL);
ret = (*cifp->if_output)(ifp, m, dst, rt);
KERNEL_UNLOCK_ONE(NULL);
return ret;
}
}
static __inline void
if_start_lock(struct ifnet *ifp)
{
if (if_is_mpsafe(ifp)) {
(*ifp->if_start)(ifp);
} else {
KERNEL_LOCK(1, NULL);
(*ifp->if_start)(ifp);
KERNEL_UNLOCK_ONE(NULL);
}
}
#define KERNEL_LOCK_IF_IFP_MPSAFE(ifp) \
do { if (if_is_mpsafe(ifp)) { KERNEL_LOCK(1, NULL); } } while (0)
#define KERNEL_UNLOCK_IF_IFP_MPSAFE(ifp) \
do { if (if_is_mpsafe(ifp)) { KERNEL_UNLOCK_ONE(NULL); } } while (0)
#define KERNEL_LOCK_UNLESS_IFP_MPSAFE(ifp) \
do { if (!if_is_mpsafe(ifp)) { KERNEL_LOCK(1, NULL); } } while (0)
#define KERNEL_UNLOCK_UNLESS_IFP_MPSAFE(ifp) \
do { if (!if_is_mpsafe(ifp)) { KERNEL_UNLOCK_ONE(NULL); } } while (0)
#ifdef _KERNEL_OPT
#include "opt_net_mpsafe.h"
#endif
#ifdef NET_MPSAFE
#define KERNEL_LOCK_UNLESS_NET_MPSAFE() do { } while (0)
#define KERNEL_UNLOCK_UNLESS_NET_MPSAFE() do { } while (0)
#define SOFTNET_LOCK_UNLESS_NET_MPSAFE() do { } while (0)
#define SOFTNET_UNLOCK_UNLESS_NET_MPSAFE() do { } while (0)
#define SOFTNET_LOCK_IF_NET_MPSAFE() \
do { mutex_enter(softnet_lock); } while (0)
#define SOFTNET_UNLOCK_IF_NET_MPSAFE() \
do { mutex_exit(softnet_lock); } while (0)
#else
#define KERNEL_LOCK_UNLESS_NET_MPSAFE() \
do { KERNEL_LOCK(1, NULL); } while (0)
#define KERNEL_UNLOCK_UNLESS_NET_MPSAFE() \
do { KERNEL_UNLOCK_ONE(NULL); } while (0)
#define SOFTNET_LOCK_UNLESS_NET_MPSAFE() \
do { mutex_enter(softnet_lock); } while (0)
#define SOFTNET_UNLOCK_UNLESS_NET_MPSAFE() \
do { mutex_exit(softnet_lock); } while (0)
#define SOFTNET_LOCK_IF_NET_MPSAFE() do { } while (0)
#define SOFTNET_UNLOCK_IF_NET_MPSAFE() do { } while (0)
#endif
#define SOFTNET_KERNEL_LOCK_UNLESS_NET_MPSAFE() \
do { \
SOFTNET_LOCK_UNLESS_NET_MPSAFE(); \
KERNEL_LOCK_UNLESS_NET_MPSAFE(); \
} while (0)
#define SOFTNET_KERNEL_UNLOCK_UNLESS_NET_MPSAFE() \
do { \
KERNEL_UNLOCK_UNLESS_NET_MPSAFE(); \
SOFTNET_UNLOCK_UNLESS_NET_MPSAFE(); \
} while (0)
#endif
#define IFFBITS \
"\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6UNNUMBERED" \
"\7RUNNING\10NOARP\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX" \
"\15LINK0\16LINK1\17LINK2\20MULTICAST"
#define IFF_CANTCHANGE \
(IFF_BROADCAST|IFF_POINTOPOINT|IFF_RUNNING|IFF_OACTIVE|\
IFF_SIMPLEX|IFF_MULTICAST|IFF_ALLMULTI|IFF_PROMISC)
#define IF_Kbps(x) ((x) * 1000ULL)
#define IF_Mbps(x) (IF_Kbps((x) * 1000ULL))
#define IF_Gbps(x) (IF_Mbps((x) * 1000ULL))
#define IFCAP_TSOv4 0x00080
#define IFCAP_CSUM_IPv4_Rx 0x00100
#define IFCAP_CSUM_IPv4_Tx 0x00200
#define IFCAP_CSUM_TCPv4_Rx 0x00400
#define IFCAP_CSUM_TCPv4_Tx 0x00800
#define IFCAP_CSUM_UDPv4_Rx 0x01000
#define IFCAP_CSUM_UDPv4_Tx 0x02000
#define IFCAP_CSUM_TCPv6_Rx 0x04000
#define IFCAP_CSUM_TCPv6_Tx 0x08000
#define IFCAP_CSUM_UDPv6_Rx 0x10000
#define IFCAP_CSUM_UDPv6_Tx 0x20000
#define IFCAP_TSOv6 0x40000
#define IFCAP_LRO 0x80000
#define IFCAP_MASK 0xfff80
#define IFCAPBITS \
"\020" \
"\10TSO4" \
"\11IP4CSUM_Rx" \
"\12IP4CSUM_Tx" \
"\13TCP4CSUM_Rx" \
"\14TCP4CSUM_Tx" \
"\15UDP4CSUM_Rx" \
"\16UDP4CSUM_Tx" \
"\17TCP6CSUM_Rx" \
"\20TCP6CSUM_Tx" \
"\21UDP6CSUM_Rx" \
"\22UDP6CSUM_Tx" \
"\23TSO6" \
"\24LRO" \
#define IF_AFDATA_LOCK_INIT(ifp) \
do {(ifp)->if_afdata_lock = rw_obj_alloc();} while (0)
#define IF_AFDATA_LOCK_DESTROY(ifp) rw_obj_free((ifp)->if_afdata_lock)
#define IF_AFDATA_WLOCK(ifp) rw_enter((ifp)->if_afdata_lock, RW_WRITER)
#define IF_AFDATA_RLOCK(ifp) rw_enter((ifp)->if_afdata_lock, RW_READER)
#define IF_AFDATA_WUNLOCK(ifp) rw_exit((ifp)->if_afdata_lock)
#define IF_AFDATA_RUNLOCK(ifp) rw_exit((ifp)->if_afdata_lock)
#define IF_AFDATA_LOCK(ifp) IF_AFDATA_WLOCK(ifp)
#define IF_AFDATA_UNLOCK(ifp) IF_AFDATA_WUNLOCK(ifp)
#define IF_AFDATA_TRYLOCK(ifp) rw_tryenter((ifp)->if_afdata_lock, RW_WRITER)
#define IF_AFDATA_LOCK_ASSERT(ifp) \
KASSERT(rw_lock_held((ifp)->if_afdata_lock))
#define IF_AFDATA_RLOCK_ASSERT(ifp) \
KASSERT(rw_read_held((ifp)->if_afdata_lock))
#define IF_AFDATA_WLOCK_ASSERT(ifp) \
KASSERT(rw_write_held((ifp)->if_afdata_lock))
#define IF_QFULL(ifq) ((ifq)->ifq_len >= (ifq)->ifq_maxlen)
#define IF_DROP(ifq) ((ifq)->ifq_drops++)
#define IF_ENQUEUE(ifq, m) do { \
(m)->m_nextpkt = 0; \
if ((ifq)->ifq_tail == 0) \
(ifq)->ifq_head = m; \
else \
(ifq)->ifq_tail->m_nextpkt = m; \
(ifq)->ifq_tail = m; \
(ifq)->ifq_len++; \
} while (0)
#define IF_PREPEND(ifq, m) do { \
(m)->m_nextpkt = (ifq)->ifq_head; \
if ((ifq)->ifq_tail == 0) \
(ifq)->ifq_tail = (m); \
(ifq)->ifq_head = (m); \
(ifq)->ifq_len++; \
} while (0)
#define IF_DEQUEUE(ifq, m) do { \
(m) = (ifq)->ifq_head; \
if (m) { \
if (((ifq)->ifq_head = (m)->m_nextpkt) == 0) \
(ifq)->ifq_tail = 0; \
(m)->m_nextpkt = 0; \
(ifq)->ifq_len--; \
} \
} while (0)
#define IF_POLL(ifq, m) ((m) = (ifq)->ifq_head)
#define IF_PURGE(ifq) \
do { \
struct mbuf *__m0; \
\
for (;;) { \
IF_DEQUEUE((ifq), __m0); \
if (__m0 == NULL) \
break; \
else \
m_freem(__m0); \
} \
} while ( 0)
#define IF_IS_EMPTY(ifq) ((ifq)->ifq_len == 0)
#ifndef IFQ_MAXLEN
#define IFQ_MAXLEN 256
#endif
#define IFNET_SLOWHZ 1
struct ifaddr_data {
int64_t ifad_inbytes;
int64_t ifad_outbytes;
};
struct ifaddr {
struct sockaddr *ifa_addr;
struct sockaddr *ifa_dstaddr;
#define ifa_broadaddr ifa_dstaddr
struct sockaddr *ifa_netmask;
struct ifnet *ifa_ifp;
TAILQ_ENTRY(ifaddr) ifa_list;
struct ifaddr_data ifa_data;
void (*ifa_rtrequest)
(int, struct rtentry *, const struct rt_addrinfo *);
u_int ifa_flags;
int ifa_refcnt;
int ifa_metric;
struct ifaddr *(*ifa_getifa)(struct ifaddr *,
const struct sockaddr *);
uint32_t *ifa_seqno;
int16_t ifa_preference;
#ifdef _KERNEL
struct pslist_entry ifa_pslist_entry;
struct psref_target ifa_psref;
#endif
};
#define IFA_ROUTE RTF_UP
#define IFA_DESTROYING 0x2
#if !defined(_KERNEL) || !defined(COMPAT_RTSOCK)
#define __align64 __aligned(sizeof(uint64_t))
#else
#define __align64
#endif
struct if_msghdr {
u_short ifm_msglen __align64;
u_char ifm_version;
u_char ifm_type;
int ifm_addrs;
int ifm_flags;
u_short ifm_index;
struct if_data ifm_data __align64;
};
struct ifa_msghdr {
u_short ifam_msglen __align64;
u_char ifam_version;
u_char ifam_type;
u_short ifam_index;
int ifam_flags;
int ifam_addrs;
pid_t ifam_pid;
int ifam_addrflags;
int ifam_metric;
};
struct if_announcemsghdr {
u_short ifan_msglen __align64;
u_char ifan_version;
u_char ifan_type;
u_short ifan_index;
char ifan_name[IFNAMSIZ];
u_short ifan_what;
};
#define IFAN_ARRIVAL 0
#define IFAN_DEPARTURE 1
#undef __align64
struct ifreq {
char ifr_name[IFNAMSIZ];
union {
struct sockaddr ifru_addr;
struct sockaddr ifru_dstaddr;
struct sockaddr ifru_broadaddr;
struct sockaddr_storage ifru_space;
short ifru_flags;
int ifru_addrflags;
int ifru_metric;
int ifru_mtu;
int ifru_dlt;
u_int ifru_value;
void * ifru_data;
struct {
uint32_t b_buflen;
void *b_buf;
} ifru_b;
} ifr_ifru;
#define ifr_addr ifr_ifru.ifru_addr
#define ifr_dstaddr ifr_ifru.ifru_dstaddr
#define ifr_broadaddr ifr_ifru.ifru_broadaddr
#define ifr_space ifr_ifru.ifru_space
#define ifr_flags ifr_ifru.ifru_flags
#define ifr_addrflags ifr_ifru.ifru_addrflags
#define ifr_metric ifr_ifru.ifru_metric
#define ifr_mtu ifr_ifru.ifru_mtu
#define ifr_dlt ifr_ifru.ifru_dlt
#define ifr_value ifr_ifru.ifru_value
#define ifr_media ifr_ifru.ifru_metric
#define ifr_data ifr_ifru.ifru_data
#define ifr_buf ifr_ifru.ifru_b.b_buf
#define ifr_buflen ifr_ifru.ifru_b.b_buflen
#define ifr_index ifr_ifru.ifru_value
#define ifr_ifindex ifr_index
};
#ifdef _KERNEL
#define ifreq_setdstaddr ifreq_setaddr
#define ifreq_setbroadaddr ifreq_setaddr
#define ifreq_getdstaddr ifreq_getaddr
#define ifreq_getbroadaddr ifreq_getaddr
static __inline const struct sockaddr *
ifreq_getaddr(u_long cmd, const struct ifreq *ifr)
{
return &ifr->ifr_addr;
}
#endif
struct ifcapreq {
char ifcr_name[IFNAMSIZ];
uint64_t ifcr_capabilities;
uint64_t ifcr_capenable;
};
struct ifaliasreq {
char ifra_name[IFNAMSIZ];
struct sockaddr ifra_addr;
struct sockaddr ifra_dstaddr;
#define ifra_broadaddr ifra_dstaddr
struct sockaddr ifra_mask;
};
struct ifdatareq {
char ifdr_name[IFNAMSIZ];
struct if_data ifdr_data;
};
struct ifmediareq {
char ifm_name[IFNAMSIZ];
int ifm_current;
int ifm_mask;
int ifm_status;
int ifm_active;
int ifm_count;
int *ifm_ulist;
};
struct ifdrv {
char ifd_name[IFNAMSIZ];
unsigned long ifd_cmd;
size_t ifd_len;
void *ifd_data;
};
#define IFLINKSTR_QUERYLEN 0x01
#define IFLINKSTR_UNSET 0x02
struct ifconf {
int ifc_len;
union {
void * ifcu_buf;
struct ifreq *ifcu_req;
} ifc_ifcu;
#define ifc_buf ifc_ifcu.ifcu_buf
#define ifc_req ifc_ifcu.ifcu_req
};
struct if_laddrreq {
char iflr_name[IFNAMSIZ];
unsigned int flags;
#define IFLR_PREFIX 0x8000
#define IFLR_ACTIVE 0x4000
#define IFLR_FACTORY 0x2000
unsigned int prefixlen;
struct sockaddr_storage addr;
struct sockaddr_storage dstaddr;
};
struct if_addrprefreq {
char ifap_name[IFNAMSIZ];
int16_t ifap_preference;
struct sockaddr_storage ifap_addr;
};
#include <net/if_arp.h>
#endif
#ifdef _KERNEL
#ifdef ALTQ
#define IFQ_ENQUEUE(ifq, m, err) \
do { \
mutex_enter((ifq)->ifq_lock); \
if (ALTQ_IS_ENABLED(ifq)) \
ALTQ_ENQUEUE((ifq), (m), (err)); \
else { \
if (IF_QFULL(ifq)) { \
m_freem(m); \
(err) = ENOBUFS; \
} else { \
IF_ENQUEUE((ifq), (m)); \
(err) = 0; \
} \
} \
if ((err)) \
(ifq)->ifq_drops++; \
mutex_exit((ifq)->ifq_lock); \
} while ( 0)
#define IFQ_DEQUEUE(ifq, m) \
do { \
mutex_enter((ifq)->ifq_lock); \
if (TBR_IS_ENABLED(ifq)) \
(m) = tbr_dequeue((ifq), ALTDQ_REMOVE); \
else if (ALTQ_IS_ENABLED(ifq)) \
ALTQ_DEQUEUE((ifq), (m)); \
else \
IF_DEQUEUE((ifq), (m)); \
mutex_exit((ifq)->ifq_lock); \
} while ( 0)
#define IFQ_POLL(ifq, m) \
do { \
mutex_enter((ifq)->ifq_lock); \
if (TBR_IS_ENABLED(ifq)) \
(m) = tbr_dequeue((ifq), ALTDQ_POLL); \
else if (ALTQ_IS_ENABLED(ifq)) \
ALTQ_POLL((ifq), (m)); \
else \
IF_POLL((ifq), (m)); \
mutex_exit((ifq)->ifq_lock); \
} while ( 0)
#define IFQ_PURGE(ifq) \
do { \
mutex_enter((ifq)->ifq_lock); \
if (ALTQ_IS_ENABLED(ifq)) \
ALTQ_PURGE(ifq); \
else \
IF_PURGE(ifq); \
mutex_exit((ifq)->ifq_lock); \
} while ( 0)
#define IFQ_SET_READY(ifq) \
do { \
(ifq)->altq_flags |= ALTQF_READY; \
} while ( 0)
#define IFQ_CLASSIFY(ifq, m, af) \
do { \
KASSERT(((m)->m_flags & M_PKTHDR) != 0); \
mutex_enter((ifq)->ifq_lock); \
if (ALTQ_IS_ENABLED(ifq)) { \
if (ALTQ_NEEDS_CLASSIFY(ifq)) \
(m)->m_pkthdr.pattr_class = (*(ifq)->altq_classify) \
((ifq)->altq_clfier, (m), (af)); \
(m)->m_pkthdr.pattr_af = (af); \
(m)->m_pkthdr.pattr_hdr = mtod((m), void *); \
} \
mutex_exit((ifq)->ifq_lock); \
} while ( 0)
#else
#define IFQ_ENQUEUE(ifq, m, err) \
do { \
mutex_enter((ifq)->ifq_lock); \
if (IF_QFULL(ifq)) { \
m_freem(m); \
(err) = ENOBUFS; \
} else { \
IF_ENQUEUE((ifq), (m)); \
(err) = 0; \
} \
if (err) \
(ifq)->ifq_drops++; \
mutex_exit((ifq)->ifq_lock); \
} while ( 0)
#define IFQ_DEQUEUE(ifq, m) \
do { \
mutex_enter((ifq)->ifq_lock); \
IF_DEQUEUE((ifq), (m)); \
mutex_exit((ifq)->ifq_lock); \
} while ( 0)
#define IFQ_POLL(ifq, m) \
do { \
mutex_enter((ifq)->ifq_lock); \
IF_POLL((ifq), (m)); \
mutex_exit((ifq)->ifq_lock); \
} while ( 0)
#define IFQ_PURGE(ifq) \
do { \
mutex_enter((ifq)->ifq_lock); \
IF_PURGE(ifq); \
mutex_exit((ifq)->ifq_lock); \
} while ( 0)
#define IFQ_SET_READY(ifq)
#define IFQ_CLASSIFY(ifq, m, af)
#endif
#define IFQ_LOCK_INIT(ifq) (ifq)->ifq_lock = \
mutex_obj_alloc(MUTEX_DEFAULT, IPL_NET)
#define IFQ_LOCK_DESTROY(ifq) mutex_obj_free((ifq)->ifq_lock)
#define IFQ_LOCK(ifq) mutex_enter((ifq)->ifq_lock)
#define IFQ_UNLOCK(ifq) mutex_exit((ifq)->ifq_lock)
#define IFQ_IS_EMPTY(ifq) IF_IS_EMPTY(ifq)
#define IFQ_INC_LEN(ifq) ((ifq)->ifq_len++)
#define IFQ_DEC_LEN(ifq) (--(ifq)->ifq_len)
#define IFQ_INC_DROPS(ifq) ((ifq)->ifq_drops++)
#define IFQ_SET_MAXLEN(ifq, len) ((ifq)->ifq_maxlen = (len))
#include <sys/mallocvar.h>
MALLOC_DECLARE(M_IFADDR);
MALLOC_DECLARE(M_IFMADDR);
int ifreq_setaddr(u_long, struct ifreq *, const struct sockaddr *);
struct ifnet *if_alloc(u_char);
void if_free(struct ifnet *);
void if_initname(struct ifnet *, const char *, int);
struct ifaddr *if_dl_create(const struct ifnet *, const struct sockaddr_dl **);
void if_activate_sadl(struct ifnet *, struct ifaddr *,
const struct sockaddr_dl *);
void if_set_sadl(struct ifnet *, const void *, u_char, bool);
void if_alloc_sadl(struct ifnet *);
void if_free_sadl(struct ifnet *, int);
void if_initialize(struct ifnet *);
void if_register(struct ifnet *);
void if_attach(struct ifnet *);
void if_attachdomain(void);
void if_deactivate(struct ifnet *);
bool if_is_deactivated(const struct ifnet *);
void if_export_if_data(struct ifnet *, struct if_data *, bool);
void if_purgeaddrs(struct ifnet *, int, void (*)(struct ifaddr *));
void if_detach(struct ifnet *);
void if_down(struct ifnet *);
void if_down_locked(struct ifnet *);
void if_link_state_change(struct ifnet *, int);
void if_domain_link_state_change(struct ifnet *, int);
void if_up(struct ifnet *);
void ifinit(void);
void ifinit1(void);
void ifinit_post(void);
int ifaddrpref_ioctl(struct socket *, u_long, void *, struct ifnet *);
extern int (*ifioctl)(struct socket *, u_long, void *, struct lwp *);
int ifioctl_common(struct ifnet *, u_long, void *);
int ifpromisc(struct ifnet *, int);
int ifpromisc_locked(struct ifnet *, int);
int if_addr_init(ifnet_t *, struct ifaddr *, bool);
int if_do_dad(struct ifnet *);
int if_mcast_op(ifnet_t *, const unsigned long, const struct sockaddr *);
int if_flags_set(struct ifnet *, const u_short);
int if_clone_list(int, char *, int *);
int if_ioctl(struct ifnet *, u_long, void *);
int if_init(struct ifnet *);
void if_stop(struct ifnet *, int);
struct ifnet *ifunit(const char *);
struct ifnet *if_get(const char *, struct psref *);
ifnet_t *if_byindex(u_int);
ifnet_t *_if_byindex(u_int);
ifnet_t *if_get_byindex(u_int, struct psref *);
ifnet_t *if_get_bylla(const void *, unsigned char, struct psref *);
void if_put(const struct ifnet *, struct psref *);
void if_acquire(struct ifnet *, struct psref *);
#define if_release if_put
int if_tunnel_check_nesting(struct ifnet *, struct mbuf *, int);
percpu_t *if_tunnel_alloc_ro_percpu(void);
void if_tunnel_free_ro_percpu(percpu_t *);
void if_tunnel_ro_percpu_rtcache_free(percpu_t *);
struct tunnel_ro {
struct route *tr_ro;
kmutex_t *tr_lock;
};
static inline void
if_tunnel_get_ro(percpu_t *ro_percpu, struct route **ro, kmutex_t **lock)
{
struct tunnel_ro *tro;
tro = percpu_getref(ro_percpu);
*ro = tro->tr_ro;
*lock = tro->tr_lock;
mutex_enter(*lock);
}
static inline void
if_tunnel_put_ro(percpu_t *ro_percpu, kmutex_t *lock)
{
mutex_exit(lock);
percpu_putref(ro_percpu);
}
static __inline if_index_t
if_get_index(const struct ifnet *ifp)
{
return ifp != NULL ? ifp->if_index : 0;
}
bool if_held(struct ifnet *);
void if_input(struct ifnet *, struct mbuf *);
struct if_percpuq *
if_percpuq_create(struct ifnet *);
void if_percpuq_destroy(struct if_percpuq *);
void
if_percpuq_enqueue(struct if_percpuq *, struct mbuf *);
void if_deferred_start_init(struct ifnet *, void (*)(struct ifnet *));
void if_schedule_deferred_start(struct ifnet *);
void ifa_insert(struct ifnet *, struct ifaddr *);
void ifa_remove(struct ifnet *, struct ifaddr *);
void ifa_psref_init(struct ifaddr *);
void ifa_acquire(struct ifaddr *, struct psref *);
void ifa_release(struct ifaddr *, struct psref *);
bool ifa_held(struct ifaddr *);
bool ifa_is_destroying(struct ifaddr *);
void ifaref(struct ifaddr *);
void ifafree(struct ifaddr *);
struct ifaddr *ifa_ifwithaddr(const struct sockaddr *);
struct ifaddr *ifa_ifwithaddr_psref(const struct sockaddr *, struct psref *);
struct ifaddr *ifa_ifwithdstaddr(const struct sockaddr *);
struct ifaddr *ifa_ifwithdstaddr_psref(const struct sockaddr *,
struct psref *);
struct ifaddr *ifa_ifwithnet(const struct sockaddr *);
struct ifaddr *ifa_ifwithnet_psref(const struct sockaddr *, struct psref *);
struct ifaddr *ifa_ifwithladdr(const struct sockaddr *);
struct ifaddr *ifa_ifwithladdr_psref(const struct sockaddr *, struct psref *);
struct ifaddr *ifaof_ifpforaddr(const struct sockaddr *, struct ifnet *);
struct ifaddr *ifaof_ifpforaddr_psref(const struct sockaddr *, struct ifnet *,
struct psref *);
void link_rtrequest(int, struct rtentry *, const struct rt_addrinfo *);
void p2p_rtrequest(int, struct rtentry *, const struct rt_addrinfo *);
struct ifaddr *if_first_addr(const struct ifnet *, const int);
struct ifaddr *if_first_addr_psref(const struct ifnet *, const int, struct psref *);
void if_clone_attach(struct if_clone *);
void if_clone_detach(struct if_clone *);
int if_transmit_lock(struct ifnet *, struct mbuf *);
int ifq_enqueue(struct ifnet *, struct mbuf *);
int ifq_enqueue2(struct ifnet *, struct ifqueue *, struct mbuf *);
int loioctl(struct ifnet *, u_long, void *);
void loopattach(int);
void loopinit(void);
int looutput(struct ifnet *,
struct mbuf *, const struct sockaddr *, const struct rtentry *);
void * if_linkstate_change_establish(struct ifnet *,
void (*)(void *), void *);
void if_linkstate_change_disestablish(struct ifnet *,
void *, kmutex_t *);
int if_nulloutput(struct ifnet *, struct mbuf *,
const struct sockaddr *, const struct rtentry *);
void if_nullinput(struct ifnet *, struct mbuf *);
void if_nullstart(struct ifnet *);
int if_nulltransmit(struct ifnet *, struct mbuf *);
int if_nullioctl(struct ifnet *, u_long, void *);
int if_nullinit(struct ifnet *);
void if_nullstop(struct ifnet *, int);
void if_nullslowtimo(struct ifnet *);
#define if_nullwatchdog if_nullslowtimo
void if_nulldrain(struct ifnet *);
#else
struct if_nameindex {
unsigned int if_index;
char *if_name;
};
#include <sys/cdefs.h>
__BEGIN_DECLS
unsigned int if_nametoindex(const char *);
char * if_indextoname(unsigned int, char *);
struct if_nameindex * if_nameindex(void);
void if_freenameindex(struct if_nameindex *);
__END_DECLS
#endif
#ifdef _KERNEL
#define IFADDR_FIRST(__ifp) TAILQ_FIRST(&(__ifp)->if_addrlist)
#define IFADDR_NEXT(__ifa) TAILQ_NEXT((__ifa), ifa_list)
#define IFADDR_FOREACH(__ifa, __ifp) TAILQ_FOREACH(__ifa, \
&(__ifp)->if_addrlist, ifa_list)
#define IFADDR_FOREACH_SAFE(__ifa, __ifp, __nifa) \
TAILQ_FOREACH_SAFE(__ifa, \
&(__ifp)->if_addrlist, ifa_list, __nifa)
#define IFADDR_EMPTY(__ifp) TAILQ_EMPTY(&(__ifp)->if_addrlist)
#define IFADDR_ENTRY_INIT(__ifa) \
PSLIST_ENTRY_INIT((__ifa), ifa_pslist_entry)
#define IFADDR_ENTRY_DESTROY(__ifa) \
PSLIST_ENTRY_DESTROY((__ifa), ifa_pslist_entry)
#define IFADDR_READER_EMPTY(__ifp) \
(PSLIST_READER_FIRST(&(__ifp)->if_addr_pslist, struct ifaddr, \
ifa_pslist_entry) == NULL)
#define IFADDR_READER_FIRST(__ifp) \
PSLIST_READER_FIRST(&(__ifp)->if_addr_pslist, struct ifaddr, \
ifa_pslist_entry)
#define IFADDR_READER_NEXT(__ifa) \
PSLIST_READER_NEXT((__ifa), struct ifaddr, ifa_pslist_entry)
#define IFADDR_READER_FOREACH(__ifa, __ifp) \
PSLIST_READER_FOREACH((__ifa), &(__ifp)->if_addr_pslist, struct ifaddr,\
ifa_pslist_entry)
#define IFADDR_WRITER_INSERT_HEAD(__ifp, __ifa) \
PSLIST_WRITER_INSERT_HEAD(&(__ifp)->if_addr_pslist, (__ifa), \
ifa_pslist_entry)
#define IFADDR_WRITER_REMOVE(__ifa) \
PSLIST_WRITER_REMOVE((__ifa), ifa_pslist_entry)
#define IFADDR_WRITER_FOREACH(__ifa, __ifp) \
PSLIST_WRITER_FOREACH((__ifa), &(__ifp)->if_addr_pslist, struct ifaddr,\
ifa_pslist_entry)
#define IFADDR_WRITER_NEXT(__ifp) \
PSLIST_WRITER_NEXT((__ifp), struct ifaddr, ifa_pslist_entry)
#define IFADDR_WRITER_INSERT_AFTER(__ifp, __new) \
PSLIST_WRITER_INSERT_AFTER((__ifp), (__new), ifa_pslist_entry)
#define IFADDR_WRITER_EMPTY(__ifp) \
(PSLIST_WRITER_FIRST(&(__ifp)->if_addr_pslist, struct ifaddr, \
ifa_pslist_entry) == NULL)
#define IFADDR_WRITER_INSERT_TAIL(__ifp, __new) \
do { \
if (IFADDR_WRITER_EMPTY(__ifp)) { \
IFADDR_WRITER_INSERT_HEAD((__ifp), (__new)); \
} else { \
struct ifaddr *__ifa; \
IFADDR_WRITER_FOREACH(__ifa, (__ifp)) { \
if (IFADDR_WRITER_NEXT(__ifa) == NULL) {\
IFADDR_WRITER_INSERT_AFTER(__ifa,\
(__new)); \
break; \
} \
} \
} \
} while (0)
#define IFNET_GLOBAL_LOCK() mutex_enter(&ifnet_mtx)
#define IFNET_GLOBAL_UNLOCK() mutex_exit(&ifnet_mtx)
#define IFNET_GLOBAL_LOCKED() mutex_owned(&ifnet_mtx)
#define IFNET_READER_EMPTY() \
(PSLIST_READER_FIRST(&ifnet_pslist, struct ifnet, if_pslist_entry) == NULL)
#define IFNET_READER_FIRST() \
PSLIST_READER_FIRST(&ifnet_pslist, struct ifnet, if_pslist_entry)
#define IFNET_READER_NEXT(__ifp) \
PSLIST_READER_NEXT((__ifp), struct ifnet, if_pslist_entry)
#define IFNET_READER_FOREACH(__ifp) \
PSLIST_READER_FOREACH((__ifp), &ifnet_pslist, struct ifnet, \
if_pslist_entry)
#define IFNET_WRITER_INSERT_HEAD(__ifp) \
PSLIST_WRITER_INSERT_HEAD(&ifnet_pslist, (__ifp), if_pslist_entry)
#define IFNET_WRITER_REMOVE(__ifp) \
PSLIST_WRITER_REMOVE((__ifp), if_pslist_entry)
#define IFNET_WRITER_FOREACH(__ifp) \
PSLIST_WRITER_FOREACH((__ifp), &ifnet_pslist, struct ifnet, \
if_pslist_entry)
#define IFNET_WRITER_NEXT(__ifp) \
PSLIST_WRITER_NEXT((__ifp), struct ifnet, if_pslist_entry)
#define IFNET_WRITER_INSERT_AFTER(__ifp, __new) \
PSLIST_WRITER_INSERT_AFTER((__ifp), (__new), if_pslist_entry)
#define IFNET_WRITER_EMPTY() \
(PSLIST_WRITER_FIRST(&ifnet_pslist, struct ifnet, if_pslist_entry) == NULL)
#define IFNET_WRITER_INSERT_TAIL(__new) \
do { \
if (IFNET_WRITER_EMPTY()) { \
IFNET_WRITER_INSERT_HEAD(__new); \
} else { \
struct ifnet *__ifp; \
IFNET_WRITER_FOREACH(__ifp) { \
if (IFNET_WRITER_NEXT(__ifp) == NULL) { \
IFNET_WRITER_INSERT_AFTER(__ifp,\
(__new)); \
break; \
} \
} \
} \
} while (0)
#define IFNET_LOCK(ifp) mutex_enter((ifp)->if_ioctl_lock)
#define IFNET_UNLOCK(ifp) mutex_exit((ifp)->if_ioctl_lock)
#define IFNET_LOCKED(ifp) mutex_owned((ifp)->if_ioctl_lock)
#define IFNET_ASSERT_UNLOCKED(ifp) \
KDASSERT(mutex_ownable((ifp)->if_ioctl_lock))
extern struct pslist_head ifnet_pslist;
extern kmutex_t ifnet_mtx;
extern struct ifnet *lo0ifp;
int sysctl_ifq(int *name, u_int namelen, void *oldp,
size_t *oldlenp, void *newp, size_t newlen,
struct ifqueue *ifq);
#define IFQCTL_LEN 1
#define IFQCTL_MAXLEN 2
#define IFQCTL_PEAK 3
#define IFQCTL_DROPS 4
MODULE_HOOK(if_vlan_vlan_input_hook,
struct mbuf *, (struct ifnet *, struct mbuf *));
#endif
#endif