freebsd11_network: adapt code based on needs of the e1000 R11.1 driver.
This commit is contained in:
@@ -2,3 +2,4 @@ SubDir HAIKU_TOP src libs compat ;
|
||||
|
||||
SubInclude HAIKU_TOP src libs compat freebsd_network ;
|
||||
SubInclude HAIKU_TOP src libs compat freebsd_wlan ;
|
||||
SubInclude HAIKU_TOP src libs compat freebsd11_network ;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
SubDir HAIKU_TOP src libs compat freebsd_network ;
|
||||
SubDir HAIKU_TOP src libs compat freebsd11_network ;
|
||||
|
||||
UseHeaders [ FDirName $(SUBDIR) ] : true ;
|
||||
UseHeaders [ FDirName $(SUBDIR) compat ] : true ;
|
||||
@@ -12,7 +12,7 @@ Includes [ FGristFiles kernel_c++_structs.h ]
|
||||
|
||||
SubDirCcFlags [ FDefines _KERNEL=1 _XOPEN_SOURCE ] ;
|
||||
|
||||
KernelStaticLibrary libfreebsd_network.a :
|
||||
KernelStaticLibrary libfreebsd11_network.a :
|
||||
bus.cpp
|
||||
callout.cpp
|
||||
clock.c
|
||||
@@ -39,6 +39,7 @@ KernelStaticLibrary libfreebsd_network.a :
|
||||
mii.c
|
||||
mutex.c
|
||||
priv.cpp
|
||||
smp.c
|
||||
synch.c
|
||||
systm.c
|
||||
taskqueue.c
|
||||
|
||||
@@ -437,6 +437,16 @@ bus_teardown_intr(device_t dev, struct resource *res, void *arg)
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
bus_bind_intr(device_t dev, struct resource *res, int cpu)
|
||||
{
|
||||
if (dev->parent == NULL)
|
||||
return EINVAL;
|
||||
|
||||
// TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
// #pragma mark - bus functions
|
||||
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include <compat/sys/kernel.h>
|
||||
|
||||
|
||||
int ticks;
|
||||
int32 ticks;
|
||||
static timer sHardClockTimer;
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ static timer sHardClockTimer;
|
||||
static status_t
|
||||
hardClock(timer* hardClockTimer)
|
||||
{
|
||||
atomic_add((vint32*)&ticks, 1);
|
||||
atomic_add(&ticks, 1);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,4 +24,9 @@
|
||||
#define atomic_readandclear_int(ptr) \
|
||||
atomic_set((int32 *)(ptr), 0)
|
||||
|
||||
|
||||
#define mb() memory_full_barrier()
|
||||
#define wmb() memory_write_barrier_inline()
|
||||
#define rmb() memory_read_barrier()
|
||||
|
||||
#endif /* _FBSD_COMPAT_MACHINE_ATOMIC_H_ */
|
||||
|
||||
@@ -62,31 +62,31 @@
|
||||
*/
|
||||
struct if_data {
|
||||
/* generic interface information */
|
||||
u_char ifi_type; /* ethernet, tokenring, etc */
|
||||
u_char ifi_physical; /* e.g., AUI, Thinnet, 10base-T, etc */
|
||||
u_char ifi_addrlen; /* media address length */
|
||||
u_char ifi_hdrlen; /* media header length */
|
||||
u_char ifi_link_state; /* current link state */
|
||||
u_char ifi_recvquota; /* polling quota for receive intrs */
|
||||
u_char ifi_xmitquota; /* polling quota for xmit intrs */
|
||||
u_char ifi_datalen; /* length of this data struct */
|
||||
u_long ifi_mtu; /* maximum transmission unit */
|
||||
u_long ifi_metric; /* routing metric (external only) */
|
||||
u_long ifi_baudrate; /* linespeed */
|
||||
uint8_t ifi_type; /* ethernet, tokenring, etc */
|
||||
uint8_t ifi_physical; /* e.g., AUI, Thinnet, 10base-T, etc */
|
||||
uint8_t ifi_addrlen; /* media address length */
|
||||
uint8_t ifi_hdrlen; /* media header length */
|
||||
uint8_t ifi_link_state; /* current link state */
|
||||
uint8_t ifi_recvquota; /* polling quota for receive intrs */
|
||||
uint8_t ifi_xmitquota; /* polling quota for xmit intrs */
|
||||
uint16_t ifi_datalen; /* length of this data struct */
|
||||
uint32_t ifi_mtu; /* maximum transmission unit */
|
||||
uint32_t ifi_metric; /* routing metric (external only) */
|
||||
uint32_t ifi_baudrate; /* linespeed */
|
||||
/* volatile statistics */
|
||||
u_long ifi_ipackets; /* packets received on interface */
|
||||
u_long ifi_ierrors; /* input errors on interface */
|
||||
u_long ifi_opackets; /* packets sent on interface */
|
||||
u_long ifi_oerrors; /* output errors on interface */
|
||||
u_long ifi_collisions; /* collisions on csma interfaces */
|
||||
u_long ifi_ibytes; /* total number of octets received */
|
||||
u_long ifi_obytes; /* total number of octets sent */
|
||||
u_long ifi_imcasts; /* packets received via multicast */
|
||||
u_long ifi_omcasts; /* packets sent via multicast */
|
||||
u_long ifi_iqdrops; /* dropped on input, this interface */
|
||||
u_long ifi_oqdrops; /* dropped on output, this interface */
|
||||
u_long ifi_noproto; /* destined for unsupported protocol */
|
||||
u_long ifi_hwassist; /* HW offload capabilities */
|
||||
uint64_t ifi_ipackets; /* packets received on interface */
|
||||
uint64_t ifi_ierrors; /* input errors on interface */
|
||||
uint64_t ifi_opackets; /* packets sent on interface */
|
||||
uint64_t ifi_oerrors; /* output errors on interface */
|
||||
uint64_t ifi_collisions; /* collisions on csma interfaces */
|
||||
uint64_t ifi_ibytes; /* total number of octets received */
|
||||
uint64_t ifi_obytes; /* total number of octets sent */
|
||||
uint64_t ifi_imcasts; /* packets received via multicast */
|
||||
uint64_t ifi_omcasts; /* packets sent via multicast */
|
||||
uint64_t ifi_iqdrops; /* dropped on input, this interface */
|
||||
uint64_t ifi_oqdrops; /* dropped on output, this interface */
|
||||
uint64_t ifi_noproto; /* destined for unsupported protocol */
|
||||
uint64_t ifi_hwassist; /* HW offload capabilities */
|
||||
time_t ifi_epoch; /* uptime at attach or stat reset */
|
||||
#ifdef __alpha__
|
||||
u_int ifi_timepad; /* time_t is int, not long on alpha */
|
||||
|
||||
@@ -80,6 +80,7 @@ struct route;
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/eventhandler.h>
|
||||
#endif /* _KERNEL */
|
||||
#include <sys/counter.h>
|
||||
#include <sys/lock.h> /* XXX */
|
||||
#include <sys/mutex.h> /* XXX */
|
||||
#include <sys/event.h> /* XXX */
|
||||
@@ -110,6 +111,61 @@ TAILQ_HEAD(ifaddrhead, ifaddr); /* instantiation is preserved in the list */
|
||||
TAILQ_HEAD(ifprefixhead, ifprefix);
|
||||
TAILQ_HEAD(ifmultihead, ifmultiaddr);
|
||||
|
||||
typedef struct ifnet * if_t;
|
||||
|
||||
typedef void (*if_start_fn_t)(if_t);
|
||||
typedef int (*if_ioctl_fn_t)(if_t, u_long, caddr_t);
|
||||
typedef void (*if_init_fn_t)(void *);
|
||||
typedef void (*if_qflush_fn_t)(if_t);
|
||||
typedef int (*if_transmit_fn_t)(if_t, struct mbuf *);
|
||||
typedef uint64_t (*if_get_counter_t)(if_t, ift_counter);
|
||||
|
||||
struct ifnet_hw_tsomax {
|
||||
u_int tsomaxbytes; /* TSO total burst length limit in bytes */
|
||||
u_int tsomaxsegcount; /* TSO maximum segment count */
|
||||
u_int tsomaxsegsize; /* TSO maximum segment size in bytes */
|
||||
};
|
||||
|
||||
/* Interface encap request types */
|
||||
typedef enum {
|
||||
IFENCAP_LL = 1 /* pre-calculate link-layer header */
|
||||
} ife_type;
|
||||
|
||||
/*
|
||||
* The structure below allows to request various pre-calculated L2/L3 headers
|
||||
* for different media. Requests varies by type (rtype field).
|
||||
*
|
||||
* IFENCAP_LL type: pre-calculates link header based on address family
|
||||
* and destination lladdr.
|
||||
*
|
||||
* Input data fields:
|
||||
* buf: pointer to destination buffer
|
||||
* bufsize: buffer size
|
||||
* flags: IFENCAP_FLAG_BROADCAST if destination is broadcast
|
||||
* family: address family defined by AF_ constant.
|
||||
* lladdr: pointer to link-layer address
|
||||
* lladdr_len: length of link-layer address
|
||||
* hdata: pointer to L3 header (optional, used for ARP requests).
|
||||
* Output data fields:
|
||||
* buf: encap data is stored here
|
||||
* bufsize: resulting encap length is stored here
|
||||
* lladdr_off: offset of link-layer address from encap hdr start
|
||||
* hdata: L3 header may be altered if necessary
|
||||
*/
|
||||
|
||||
struct if_encap_req {
|
||||
u_char *buf; /* Destination buffer (w) */
|
||||
size_t bufsize; /* size of provided buffer (r) */
|
||||
ife_type rtype; /* request type (r) */
|
||||
uint32_t flags; /* Request flags (r) */
|
||||
int family; /* Address family AF_* (r) */
|
||||
int lladdr_off; /* offset from header start (w) */
|
||||
int lladdr_len; /* lladdr length (r) */
|
||||
char *lladdr; /* link-level address pointer (r) */
|
||||
char *hdata; /* Upper layer header data (rw) */
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Structure defining a queue for a network interface.
|
||||
*/
|
||||
@@ -163,6 +219,7 @@ struct ifnet {
|
||||
struct if_data if_data;
|
||||
struct ifmultihead if_multiaddrs; /* multicast addresses configured */
|
||||
int if_amcount; /* number of all-multicast requests */
|
||||
struct ifaddr *if_addr; /* pointer to link-level address */
|
||||
/* procedure handles */
|
||||
int (*if_output) /* output routine (enqueue) */
|
||||
(struct ifnet *, struct mbuf *, struct sockaddr *,
|
||||
@@ -204,6 +261,32 @@ struct ifnet {
|
||||
struct task if_linktask; /* task for link change events */
|
||||
struct mtx if_addr_mtx; /* mutex to protect address lists */
|
||||
|
||||
if_qflush_fn_t if_qflush; /* flush any queue */
|
||||
if_get_counter_t if_get_counter; /* get counter values */
|
||||
int (*if_requestencap) /* make link header from request */
|
||||
(struct ifnet *, struct if_encap_req *);
|
||||
|
||||
/*
|
||||
* Network adapter TSO limits:
|
||||
* ===========================
|
||||
*
|
||||
* If the "if_hw_tsomax" field is zero the maximum segment
|
||||
* length limit does not apply. If the "if_hw_tsomaxsegcount"
|
||||
* or the "if_hw_tsomaxsegsize" field is zero the TSO segment
|
||||
* count limit does not apply. If all three fields are zero,
|
||||
* there is no TSO limit.
|
||||
*
|
||||
* NOTE: The TSO limits should reflect the values used in the
|
||||
* BUSDMA tag a network adapter is using to load a mbuf chain
|
||||
* for transmission. The TCP/IP network stack will subtract
|
||||
* space for all linklevel and protocol level headers and
|
||||
* ensure that the full mbuf chain passed to the network
|
||||
* adapter fits within the given limits.
|
||||
*/
|
||||
u_int if_hw_tsomax; /* TSO maximum size in bytes */
|
||||
u_int if_hw_tsomaxsegcount; /* TSO maximum segment count */
|
||||
u_int if_hw_tsomaxsegsize; /* TSO maximum segment size in bytes */
|
||||
|
||||
/* Haiku additions */
|
||||
struct sockaddr_dl if_lladdr;
|
||||
char device_name[128];
|
||||
@@ -581,6 +664,12 @@ struct ifaddr {
|
||||
/* for compatibility with other BSDs */
|
||||
#define ifa_list ifa_link
|
||||
|
||||
|
||||
struct ifaddr * ifa_alloc(size_t size, int flags);
|
||||
void ifa_free(struct ifaddr *ifa);
|
||||
void ifa_ref(struct ifaddr *ifa);
|
||||
|
||||
|
||||
#define IFA_LOCK_INIT(ifa) \
|
||||
mtx_init(&(ifa)->ifa_mtx, "ifaddr", NULL, MTX_DEF)
|
||||
#define IFA_LOCK(ifa) mtx_lock(&(ifa)->ifa_mtx)
|
||||
@@ -623,10 +712,6 @@ struct ifmultiaddr {
|
||||
#define IFA_LOCK(ifa) mtx_lock(&(ifa)->ifa_mtx)
|
||||
#define IFA_UNLOCK(ifa) mtx_unlock(&(ifa)->ifa_mtx)
|
||||
|
||||
__unused static void ifa_free(struct ifaddr *ifa) {}
|
||||
__unused static void ifa_init(struct ifaddr *ifa) {}
|
||||
__unused static void ifa_ref(struct ifaddr *ifa) {}
|
||||
|
||||
extern struct rw_lock ifnet_rwlock;
|
||||
#define IFNET_LOCK_INIT() rw_lock_init(&ifnet_rwlock, "ifnet rwlock")
|
||||
#define IFNET_WLOCK() rw_lock_write_lock(&ifnet_rwlock)
|
||||
@@ -679,9 +764,69 @@ typedef void *if_com_alloc_t(u_char type, struct ifnet *ifp);
|
||||
typedef void if_com_free_t(void *com, u_char type);
|
||||
void if_register_com_alloc(u_char type, if_com_alloc_t *a, if_com_free_t *f);
|
||||
void if_deregister_com_alloc(u_char type);
|
||||
void if_data_copy(struct ifnet *, struct if_data *);
|
||||
uint64_t if_get_counter_default(struct ifnet *, ift_counter);
|
||||
void if_inc_counter(struct ifnet *, ift_counter, int64_t);
|
||||
|
||||
#define IF_LLADDR(ifp) LLADDR(&ifp->if_lladdr)
|
||||
#define IF_LLADDR(ifp) \
|
||||
LLADDR((struct sockaddr_dl *)((ifp)->if_addr->ifa_addr))
|
||||
|
||||
uint64_t if_setbaudrate(if_t ifp, uint64_t baudrate);
|
||||
uint64_t if_getbaudrate(if_t ifp);
|
||||
int if_setcapabilities(if_t ifp, int capabilities);
|
||||
int if_setcapabilitiesbit(if_t ifp, int setbit, int clearbit);
|
||||
int if_getcapabilities(if_t ifp);
|
||||
int if_togglecapenable(if_t ifp, int togglecap);
|
||||
int if_setcapenable(if_t ifp, int capenable);
|
||||
int if_setcapenablebit(if_t ifp, int setcap, int clearcap);
|
||||
int if_getcapenable(if_t ifp);
|
||||
const char *if_getdname(if_t ifp);
|
||||
int if_setdev(if_t ifp, void *dev);
|
||||
int if_setdrvflagbits(if_t ifp, int if_setflags, int clear_flags);
|
||||
int if_getdrvflags(if_t ifp);
|
||||
int if_setdrvflags(if_t ifp, int flags);
|
||||
int if_clearhwassist(if_t ifp);
|
||||
int if_sethwassistbits(if_t ifp, int toset, int toclear);
|
||||
int if_sethwassist(if_t ifp, int hwassist_bit);
|
||||
int if_gethwassist(if_t ifp);
|
||||
int if_setsoftc(if_t ifp, void *softc);
|
||||
void *if_getsoftc(if_t ifp);
|
||||
int if_setflags(if_t ifp, int flags);
|
||||
int if_gethwaddr(if_t ifp, struct ifreq *);
|
||||
int if_setmtu(if_t ifp, int mtu);
|
||||
int if_getmtu(if_t ifp);
|
||||
int if_getmtu_family(if_t ifp, int family);
|
||||
int if_setflagbits(if_t ifp, int set, int clear);
|
||||
int if_getflags(if_t ifp);
|
||||
int if_sendq_empty(if_t ifp);
|
||||
int if_setsendqready(if_t ifp);
|
||||
int if_setsendqlen(if_t ifp, int tx_desc_count);
|
||||
int if_input(if_t ifp, struct mbuf* sendmp);
|
||||
int if_sendq_prepend(if_t ifp, struct mbuf *m);
|
||||
struct mbuf *if_dequeue(if_t ifp);
|
||||
int if_setifheaderlen(if_t ifp, int len);
|
||||
void if_setrcvif(struct mbuf *m, if_t ifp);
|
||||
|
||||
void if_setvtag(struct mbuf *m, u_int16_t tag);
|
||||
u_int16_t if_getvtag(struct mbuf *m);
|
||||
int if_vlantrunkinuse(if_t ifp);
|
||||
caddr_t if_getlladdr(if_t ifp);
|
||||
void *if_gethandle(u_char);
|
||||
void if_bpfmtap(if_t ifp, struct mbuf *m);
|
||||
void if_etherbpfmtap(if_t ifp, struct mbuf *m);
|
||||
void if_vlancap(if_t ifp);
|
||||
|
||||
int if_setupmultiaddr(if_t ifp, void *mta, int *cnt, int max);
|
||||
int if_multiaddr_array(if_t ifp, void *mta, int *cnt, int max);
|
||||
int if_multiaddr_count(if_t ifp, int max);
|
||||
|
||||
/* Functions */
|
||||
void if_setinitfn(if_t ifp, void (*)(void *));
|
||||
void if_setioctlfn(if_t ifp, int (*)(if_t, u_long, caddr_t));
|
||||
void if_setstartfn(if_t ifp, void (*)(if_t));
|
||||
void if_settransmitfn(if_t ifp, if_transmit_fn_t);
|
||||
void if_setqflushfn(if_t ifp, if_qflush_fn_t);
|
||||
void if_setgetcounterfn(if_t ifp, if_get_counter_t);
|
||||
|
||||
#ifdef DEVICE_POLLING
|
||||
enum poll_cmd { POLL_ONLY, POLL_AND_CHECK_STATUS };
|
||||
|
||||
@@ -0,0 +1,496 @@
|
||||
/*-
|
||||
* Copyright (c) 2006-2009 University of Zagreb
|
||||
* Copyright (c) 2006-2009 FreeBSD Foundation
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by the University of Zagreb and the
|
||||
* FreeBSD Foundation under sponsorship by the Stichting NLnet and the
|
||||
* FreeBSD Foundation.
|
||||
*
|
||||
* Copyright (c) 2009 Jeffrey Roberson <jeff@freebsd.org>
|
||||
* Copyright (c) 2009 Robert N. M. Watson
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/*-
|
||||
* This header file defines several sets of interfaces supporting virtualized
|
||||
* network stacks:
|
||||
*
|
||||
* - Definition of 'struct vnet' and functions and macros to allocate/free/
|
||||
* manipulate it.
|
||||
*
|
||||
* - A virtual network stack memory allocator, which provides support for
|
||||
* virtualized global variables via a special linker set, set_vnet.
|
||||
*
|
||||
* - Virtualized sysinits/sysuninits, which allow constructors and
|
||||
* destructors to be run for each network stack subsystem as virtual
|
||||
* instances are created and destroyed.
|
||||
*
|
||||
* If VIMAGE isn't compiled into the kernel, virtualized global variables
|
||||
* compile to normal global variables, and virtualized sysinits to regular
|
||||
* sysinits.
|
||||
*/
|
||||
|
||||
#ifndef _FBSD_COMPAT_NET_VNET_H_
|
||||
#define _FBSD_COMPAT_NET_VNET_H_
|
||||
|
||||
/*
|
||||
* struct vnet describes a virtualized network stack, and is primarily a
|
||||
* pointer to storage for virtualized global variables. Expose to userspace
|
||||
* as required for libkvm.
|
||||
*/
|
||||
#if defined(_KERNEL) || defined(_WANT_VNET)
|
||||
#include <sys/queue.h>
|
||||
|
||||
struct vnet {
|
||||
LIST_ENTRY(vnet) vnet_le; /* all vnets list */
|
||||
u_int vnet_magic_n;
|
||||
u_int vnet_ifcnt;
|
||||
u_int vnet_sockcnt;
|
||||
void *vnet_data_mem;
|
||||
uintptr_t vnet_data_base;
|
||||
};
|
||||
#define VNET_MAGIC_N 0x3e0d8f29
|
||||
|
||||
/*
|
||||
* These two virtual network stack allocator definitions are also required
|
||||
* for libkvm so that it can evaluate virtualized global variables.
|
||||
*/
|
||||
#define VNET_SETNAME "set_vnet"
|
||||
#define VNET_SYMPREFIX "vnet_entry_"
|
||||
#endif
|
||||
|
||||
#ifdef _KERNEL
|
||||
|
||||
#define VNET_PCPUSTAT_DECLARE(type, name) \
|
||||
VNET_DECLARE(counter_u64_t, name[sizeof(type) / sizeof(uint64_t)])
|
||||
|
||||
#define VNET_PCPUSTAT_DEFINE(type, name) \
|
||||
VNET_DEFINE(counter_u64_t, name[sizeof(type) / sizeof(uint64_t)])
|
||||
|
||||
#define VNET_PCPUSTAT_ALLOC(name, wait) \
|
||||
COUNTER_ARRAY_ALLOC(VNET(name), \
|
||||
sizeof(VNET(name)) / sizeof(counter_u64_t), (wait))
|
||||
|
||||
#define VNET_PCPUSTAT_FREE(name) \
|
||||
COUNTER_ARRAY_FREE(VNET(name), sizeof(VNET(name)) / sizeof(counter_u64_t))
|
||||
|
||||
#define VNET_PCPUSTAT_ADD(type, name, f, v) \
|
||||
counter_u64_add(VNET(name)[offsetof(type, f) / sizeof(uint64_t)], (v))
|
||||
|
||||
#define VNET_PCPUSTAT_SYSINIT(name) \
|
||||
static void \
|
||||
vnet_##name##_init(const void *unused) \
|
||||
{ \
|
||||
VNET_PCPUSTAT_ALLOC(name, M_WAITOK); \
|
||||
} \
|
||||
VNET_SYSINIT(vnet_ ## name ## _init, SI_SUB_PROTO_IFATTACHDOMAIN, \
|
||||
SI_ORDER_ANY, vnet_ ## name ## _init, NULL)
|
||||
|
||||
#define VNET_PCPUSTAT_SYSUNINIT(name) \
|
||||
static void \
|
||||
vnet_##name##_uninit(const void *unused) \
|
||||
{ \
|
||||
VNET_PCPUSTAT_FREE(name); \
|
||||
} \
|
||||
VNET_SYSUNINIT(vnet_ ## name ## _uninit, SI_SUB_PROTO_IFATTACHDOMAIN, \
|
||||
SI_ORDER_ANY, vnet_ ## name ## _uninit, NULL)
|
||||
|
||||
#define SYSCTL_VNET_PCPUSTAT(parent, nbr, name, type, array, desc) \
|
||||
static int \
|
||||
array##_sysctl(SYSCTL_HANDLER_ARGS) \
|
||||
{ \
|
||||
type s; \
|
||||
CTASSERT((sizeof(type) / sizeof(uint64_t)) == \
|
||||
(sizeof(VNET(array)) / sizeof(counter_u64_t))); \
|
||||
COUNTER_ARRAY_COPY(VNET(array), &s, sizeof(type) / sizeof(uint64_t));\
|
||||
if (req->newptr) \
|
||||
COUNTER_ARRAY_ZERO(VNET(array), \
|
||||
sizeof(type) / sizeof(uint64_t)); \
|
||||
return (SYSCTL_OUT(req, &s, sizeof(type))); \
|
||||
} \
|
||||
SYSCTL_VNET_PROC(parent, nbr, name, CTLTYPE_OPAQUE | CTLFLAG_RW, NULL, \
|
||||
0, array ## _sysctl, "I", desc)
|
||||
|
||||
#ifdef VIMAGE
|
||||
#include <sys/lock.h>
|
||||
#include <sys/proc.h> /* for struct thread */
|
||||
#include <sys/rwlock.h>
|
||||
#include <sys/sx.h>
|
||||
|
||||
/*
|
||||
* Location of the kernel's 'set_vnet' linker set.
|
||||
*/
|
||||
extern uintptr_t *__start_set_vnet;
|
||||
__GLOBL(__start_set_vnet);
|
||||
extern uintptr_t *__stop_set_vnet;
|
||||
__GLOBL(__stop_set_vnet);
|
||||
|
||||
#define VNET_START (uintptr_t)&__start_set_vnet
|
||||
#define VNET_STOP (uintptr_t)&__stop_set_vnet
|
||||
|
||||
/*
|
||||
* Functions to allocate and destroy virtual network stacks.
|
||||
*/
|
||||
struct vnet *vnet_alloc(void);
|
||||
void vnet_destroy(struct vnet *vnet);
|
||||
|
||||
/*
|
||||
* The current virtual network stack -- we may wish to move this to struct
|
||||
* pcpu in the future.
|
||||
*/
|
||||
#define curvnet curthread->td_vnet
|
||||
|
||||
/*
|
||||
* Various macros -- get and set the current network stack, but also
|
||||
* assertions.
|
||||
*/
|
||||
#if defined(INVARIANTS) || defined(VNET_DEBUG)
|
||||
#define VNET_ASSERT(exp, msg) do { \
|
||||
if (!(exp)) \
|
||||
panic msg; \
|
||||
} while (0)
|
||||
#else
|
||||
#define VNET_ASSERT(exp, msg) do { \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#ifdef VNET_DEBUG
|
||||
void vnet_log_recursion(struct vnet *, const char *, int);
|
||||
|
||||
#define CURVNET_SET_QUIET(arg) \
|
||||
VNET_ASSERT((arg) != NULL && (arg)->vnet_magic_n == VNET_MAGIC_N, \
|
||||
("CURVNET_SET at %s:%d %s() curvnet=%p vnet=%p", \
|
||||
__FILE__, __LINE__, __func__, curvnet, (arg))); \
|
||||
struct vnet *saved_vnet = curvnet; \
|
||||
const char *saved_vnet_lpush = curthread->td_vnet_lpush; \
|
||||
curvnet = arg; \
|
||||
curthread->td_vnet_lpush = __func__;
|
||||
|
||||
#define CURVNET_SET_VERBOSE(arg) \
|
||||
CURVNET_SET_QUIET(arg) \
|
||||
if (saved_vnet) \
|
||||
vnet_log_recursion(saved_vnet, saved_vnet_lpush, __LINE__);
|
||||
|
||||
#define CURVNET_SET(arg) CURVNET_SET_VERBOSE(arg)
|
||||
|
||||
#define CURVNET_RESTORE() \
|
||||
VNET_ASSERT(curvnet != NULL && (saved_vnet == NULL || \
|
||||
saved_vnet->vnet_magic_n == VNET_MAGIC_N), \
|
||||
("CURVNET_RESTORE at %s:%d %s() curvnet=%p saved_vnet=%p", \
|
||||
__FILE__, __LINE__, __func__, curvnet, saved_vnet)); \
|
||||
curvnet = saved_vnet; \
|
||||
curthread->td_vnet_lpush = saved_vnet_lpush;
|
||||
#else /* !VNET_DEBUG */
|
||||
|
||||
#define CURVNET_SET_QUIET(arg) \
|
||||
VNET_ASSERT((arg) != NULL && (arg)->vnet_magic_n == VNET_MAGIC_N, \
|
||||
("CURVNET_SET at %s:%d %s() curvnet=%p vnet=%p", \
|
||||
__FILE__, __LINE__, __func__, curvnet, (arg))); \
|
||||
struct vnet *saved_vnet = curvnet; \
|
||||
curvnet = arg;
|
||||
|
||||
#define CURVNET_SET_VERBOSE(arg) \
|
||||
CURVNET_SET_QUIET(arg)
|
||||
|
||||
#define CURVNET_SET(arg) CURVNET_SET_VERBOSE(arg)
|
||||
|
||||
#define CURVNET_RESTORE() \
|
||||
VNET_ASSERT(curvnet != NULL && (saved_vnet == NULL || \
|
||||
saved_vnet->vnet_magic_n == VNET_MAGIC_N), \
|
||||
("CURVNET_RESTORE at %s:%d %s() curvnet=%p saved_vnet=%p", \
|
||||
__FILE__, __LINE__, __func__, curvnet, saved_vnet)); \
|
||||
curvnet = saved_vnet;
|
||||
#endif /* VNET_DEBUG */
|
||||
|
||||
extern struct vnet *vnet0;
|
||||
#define IS_DEFAULT_VNET(arg) ((arg) == vnet0)
|
||||
|
||||
#define CRED_TO_VNET(cr) (cr)->cr_prison->pr_vnet
|
||||
#define TD_TO_VNET(td) CRED_TO_VNET((td)->td_ucred)
|
||||
#define P_TO_VNET(p) CRED_TO_VNET((p)->p_ucred)
|
||||
|
||||
/*
|
||||
* Global linked list of all virtual network stacks, along with read locks to
|
||||
* access it. If a caller may sleep while accessing the list, it must use
|
||||
* the sleepable lock macros.
|
||||
*/
|
||||
LIST_HEAD(vnet_list_head, vnet);
|
||||
extern struct vnet_list_head vnet_head;
|
||||
extern struct rwlock vnet_rwlock;
|
||||
extern struct sx vnet_sxlock;
|
||||
|
||||
#define VNET_LIST_RLOCK() sx_slock(&vnet_sxlock)
|
||||
#define VNET_LIST_RLOCK_NOSLEEP() rw_rlock(&vnet_rwlock)
|
||||
#define VNET_LIST_RUNLOCK() sx_sunlock(&vnet_sxlock)
|
||||
#define VNET_LIST_RUNLOCK_NOSLEEP() rw_runlock(&vnet_rwlock)
|
||||
|
||||
/*
|
||||
* Iteration macros to walk the global list of virtual network stacks.
|
||||
*/
|
||||
#define VNET_ITERATOR_DECL(arg) struct vnet *arg
|
||||
#define VNET_FOREACH(arg) LIST_FOREACH((arg), &vnet_head, vnet_le)
|
||||
|
||||
/*
|
||||
* Virtual network stack memory allocator, which allows global variables to
|
||||
* be automatically instantiated for each network stack instance.
|
||||
*/
|
||||
#define VNET_NAME(n) vnet_entry_##n
|
||||
#define VNET_DECLARE(t, n) extern t VNET_NAME(n)
|
||||
#define VNET_DEFINE(t, n) t VNET_NAME(n) __section(VNET_SETNAME) __used
|
||||
#define _VNET_PTR(b, n) (__typeof(VNET_NAME(n))*) \
|
||||
((b) + (uintptr_t)&VNET_NAME(n))
|
||||
|
||||
#define _VNET(b, n) (*_VNET_PTR(b, n))
|
||||
|
||||
/*
|
||||
* Virtualized global variable accessor macros.
|
||||
*/
|
||||
#define VNET_VNET_PTR(vnet, n) _VNET_PTR((vnet)->vnet_data_base, n)
|
||||
#define VNET_VNET(vnet, n) (*VNET_VNET_PTR((vnet), n))
|
||||
|
||||
#define VNET_PTR(n) VNET_VNET_PTR(curvnet, n)
|
||||
#define VNET(n) VNET_VNET(curvnet, n)
|
||||
|
||||
/*
|
||||
* Virtual network stack allocator interfaces from the kernel linker.
|
||||
*/
|
||||
void *vnet_data_alloc(int size);
|
||||
void vnet_data_copy(void *start, int size);
|
||||
void vnet_data_free(void *start_arg, int size);
|
||||
|
||||
/*
|
||||
* Sysctl variants for vnet-virtualized global variables. Include
|
||||
* <sys/sysctl.h> to expose these definitions.
|
||||
*
|
||||
* Note: SYSCTL_PROC() handler functions will need to resolve pointer
|
||||
* arguments themselves, if required.
|
||||
*/
|
||||
#ifdef SYSCTL_OID
|
||||
int vnet_sysctl_handle_int(SYSCTL_HANDLER_ARGS);
|
||||
int vnet_sysctl_handle_opaque(SYSCTL_HANDLER_ARGS);
|
||||
int vnet_sysctl_handle_string(SYSCTL_HANDLER_ARGS);
|
||||
int vnet_sysctl_handle_uint(SYSCTL_HANDLER_ARGS);
|
||||
|
||||
#define SYSCTL_VNET_INT(parent, nbr, name, access, ptr, val, descr) \
|
||||
SYSCTL_OID(parent, nbr, name, \
|
||||
CTLTYPE_INT|CTLFLAG_MPSAFE|CTLFLAG_VNET|(access), \
|
||||
ptr, val, vnet_sysctl_handle_int, "I", descr)
|
||||
#define SYSCTL_VNET_PROC(parent, nbr, name, access, ptr, arg, handler, \
|
||||
fmt, descr) \
|
||||
CTASSERT(((access) & CTLTYPE) != 0); \
|
||||
SYSCTL_OID(parent, nbr, name, CTLFLAG_VNET|(access), ptr, arg, \
|
||||
handler, fmt, descr)
|
||||
#define SYSCTL_VNET_OPAQUE(parent, nbr, name, access, ptr, len, fmt, \
|
||||
descr) \
|
||||
SYSCTL_OID(parent, nbr, name, \
|
||||
CTLTYPE_OPAQUE|CTLFLAG_VNET|(access), ptr, len, \
|
||||
vnet_sysctl_handle_opaque, fmt, descr)
|
||||
#define SYSCTL_VNET_STRING(parent, nbr, name, access, arg, len, descr) \
|
||||
SYSCTL_OID(parent, nbr, name, \
|
||||
CTLTYPE_STRING|CTLFLAG_VNET|(access), \
|
||||
arg, len, vnet_sysctl_handle_string, "A", descr)
|
||||
#define SYSCTL_VNET_STRUCT(parent, nbr, name, access, ptr, type, descr) \
|
||||
SYSCTL_OID(parent, nbr, name, \
|
||||
CTLTYPE_OPAQUE|CTLFLAG_VNET|(access), ptr, \
|
||||
sizeof(struct type), vnet_sysctl_handle_opaque, "S," #type, \
|
||||
descr)
|
||||
#define SYSCTL_VNET_UINT(parent, nbr, name, access, ptr, val, descr) \
|
||||
SYSCTL_OID(parent, nbr, name, \
|
||||
CTLTYPE_UINT|CTLFLAG_MPSAFE|CTLFLAG_VNET|(access), \
|
||||
ptr, val, vnet_sysctl_handle_uint, "IU", descr)
|
||||
#define VNET_SYSCTL_ARG(req, arg1) do { \
|
||||
if (arg1 != NULL) \
|
||||
arg1 = (void *)(TD_TO_VNET((req)->td)->vnet_data_base + \
|
||||
(uintptr_t)(arg1)); \
|
||||
} while (0)
|
||||
#endif /* SYSCTL_OID */
|
||||
|
||||
/*
|
||||
* Virtual sysinit mechanism, allowing network stack components to declare
|
||||
* startup and shutdown methods to be run when virtual network stack
|
||||
* instances are created and destroyed.
|
||||
*/
|
||||
#include <sys/kernel.h>
|
||||
|
||||
/*
|
||||
* SYSINIT/SYSUNINIT variants that provide per-vnet constructors and
|
||||
* destructors.
|
||||
*/
|
||||
struct vnet_sysinit {
|
||||
enum sysinit_sub_id subsystem;
|
||||
enum sysinit_elem_order order;
|
||||
sysinit_cfunc_t func;
|
||||
const void *arg;
|
||||
TAILQ_ENTRY(vnet_sysinit) link;
|
||||
};
|
||||
|
||||
#define VNET_SYSINIT(ident, subsystem, order, func, arg) \
|
||||
static struct vnet_sysinit ident ## _vnet_init = { \
|
||||
subsystem, \
|
||||
order, \
|
||||
(sysinit_cfunc_t)(sysinit_nfunc_t)func, \
|
||||
(arg) \
|
||||
}; \
|
||||
SYSINIT(vnet_init_ ## ident, subsystem, order, \
|
||||
vnet_register_sysinit, &ident ## _vnet_init); \
|
||||
SYSUNINIT(vnet_init_ ## ident, subsystem, order, \
|
||||
vnet_deregister_sysinit, &ident ## _vnet_init)
|
||||
|
||||
#define VNET_SYSUNINIT(ident, subsystem, order, func, arg) \
|
||||
static struct vnet_sysinit ident ## _vnet_uninit = { \
|
||||
subsystem, \
|
||||
order, \
|
||||
(sysinit_cfunc_t)(sysinit_nfunc_t)func, \
|
||||
(arg) \
|
||||
}; \
|
||||
SYSINIT(vnet_uninit_ ## ident, subsystem, order, \
|
||||
vnet_register_sysuninit, &ident ## _vnet_uninit); \
|
||||
SYSUNINIT(vnet_uninit_ ## ident, subsystem, order, \
|
||||
vnet_deregister_sysuninit, &ident ## _vnet_uninit)
|
||||
|
||||
/*
|
||||
* Run per-vnet sysinits or sysuninits during vnet creation/destruction.
|
||||
*/
|
||||
void vnet_sysinit(void);
|
||||
void vnet_sysuninit(void);
|
||||
|
||||
/*
|
||||
* Interfaces for managing per-vnet constructors and destructors.
|
||||
*/
|
||||
void vnet_register_sysinit(void *arg);
|
||||
void vnet_register_sysuninit(void *arg);
|
||||
void vnet_deregister_sysinit(void *arg);
|
||||
void vnet_deregister_sysuninit(void *arg);
|
||||
|
||||
/*
|
||||
* EVENTHANDLER(9) extensions.
|
||||
*/
|
||||
#include <sys/eventhandler.h>
|
||||
|
||||
void vnet_global_eventhandler_iterator_func(void *, ...);
|
||||
#define VNET_GLOBAL_EVENTHANDLER_REGISTER_TAG(tag, name, func, arg, priority) \
|
||||
do { \
|
||||
if (IS_DEFAULT_VNET(curvnet)) { \
|
||||
(tag) = vimage_eventhandler_register(NULL, #name, func, \
|
||||
arg, priority, \
|
||||
vnet_global_eventhandler_iterator_func); \
|
||||
} \
|
||||
} while(0)
|
||||
#define VNET_GLOBAL_EVENTHANDLER_REGISTER(name, func, arg, priority) \
|
||||
do { \
|
||||
if (IS_DEFAULT_VNET(curvnet)) { \
|
||||
vimage_eventhandler_register(NULL, #name, func, \
|
||||
arg, priority, \
|
||||
vnet_global_eventhandler_iterator_func); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#else /* !VIMAGE */
|
||||
|
||||
/*
|
||||
* Various virtual network stack macros compile to no-ops without VIMAGE.
|
||||
*/
|
||||
#define curvnet NULL
|
||||
|
||||
#define VNET_ASSERT(exp, msg)
|
||||
#define CURVNET_SET(arg)
|
||||
#define CURVNET_SET_QUIET(arg)
|
||||
#define CURVNET_RESTORE()
|
||||
|
||||
#define VNET_LIST_RLOCK()
|
||||
#define VNET_LIST_RLOCK_NOSLEEP()
|
||||
#define VNET_LIST_RUNLOCK()
|
||||
#define VNET_LIST_RUNLOCK_NOSLEEP()
|
||||
#define VNET_ITERATOR_DECL(arg)
|
||||
#define VNET_FOREACH(arg)
|
||||
|
||||
#define IS_DEFAULT_VNET(arg) 1
|
||||
#define CRED_TO_VNET(cr) NULL
|
||||
#define TD_TO_VNET(td) NULL
|
||||
#define P_TO_VNET(p) NULL
|
||||
|
||||
/*
|
||||
* Versions of the VNET macros that compile to normal global variables and
|
||||
* standard sysctl definitions.
|
||||
*/
|
||||
#define VNET_NAME(n) n
|
||||
#define VNET_DECLARE(t, n) extern t n
|
||||
#define VNET_DEFINE(t, n) t n
|
||||
#define _VNET_PTR(b, n) &VNET_NAME(n)
|
||||
|
||||
/*
|
||||
* Virtualized global variable accessor macros.
|
||||
*/
|
||||
#define VNET_VNET_PTR(vnet, n) (&(n))
|
||||
#define VNET_VNET(vnet, n) (n)
|
||||
|
||||
#define VNET_PTR(n) (&(n))
|
||||
#define VNET(n) (n)
|
||||
|
||||
/*
|
||||
* When VIMAGE isn't compiled into the kernel, virtaulized SYSCTLs simply
|
||||
* become normal SYSCTLs.
|
||||
*/
|
||||
#ifdef SYSCTL_OID
|
||||
#define SYSCTL_VNET_INT(parent, nbr, name, access, ptr, val, descr) \
|
||||
SYSCTL_INT(parent, nbr, name, access, ptr, val, descr)
|
||||
#define SYSCTL_VNET_PROC(parent, nbr, name, access, ptr, arg, handler, \
|
||||
fmt, descr) \
|
||||
SYSCTL_PROC(parent, nbr, name, access, ptr, arg, handler, fmt, \
|
||||
descr)
|
||||
#define SYSCTL_VNET_OPAQUE(parent, nbr, name, access, ptr, len, fmt, \
|
||||
descr) \
|
||||
SYSCTL_OPAQUE(parent, nbr, name, access, ptr, len, fmt, descr)
|
||||
#define SYSCTL_VNET_STRING(parent, nbr, name, access, arg, len, descr) \
|
||||
SYSCTL_STRING(parent, nbr, name, access, arg, len, descr)
|
||||
#define SYSCTL_VNET_STRUCT(parent, nbr, name, access, ptr, type, descr) \
|
||||
SYSCTL_STRUCT(parent, nbr, name, access, ptr, type, descr)
|
||||
#define SYSCTL_VNET_UINT(parent, nbr, name, access, ptr, val, descr) \
|
||||
SYSCTL_UINT(parent, nbr, name, access, ptr, val, descr)
|
||||
#define VNET_SYSCTL_ARG(req, arg1)
|
||||
#endif /* SYSCTL_OID */
|
||||
|
||||
/*
|
||||
* When VIMAGE isn't compiled into the kernel, VNET_SYSINIT/VNET_SYSUNINIT
|
||||
* map into normal sysinits, which have the same ordering properties.
|
||||
*/
|
||||
#define VNET_SYSINIT(ident, subsystem, order, func, arg) \
|
||||
SYSINIT(ident, subsystem, order, func, arg)
|
||||
#define VNET_SYSUNINIT(ident, subsystem, order, func, arg) \
|
||||
SYSUNINIT(ident, subsystem, order, func, arg)
|
||||
|
||||
/*
|
||||
* Without VIMAGE revert to the default implementation.
|
||||
*/
|
||||
#define VNET_GLOBAL_EVENTHANDLER_REGISTER_TAG(tag, name, func, arg, priority) \
|
||||
(tag) = eventhandler_register(NULL, #name, func, arg, priority)
|
||||
#define VNET_GLOBAL_EVENTHANDLER_REGISTER(name, func, arg, priority) \
|
||||
eventhandler_register(NULL, #name, func, arg, priority)
|
||||
#endif /* VIMAGE */
|
||||
#endif /* _KERNEL */
|
||||
|
||||
#endif /* !_FBSD_COMPAT_NET_VNET_H_ */
|
||||
@@ -107,6 +107,7 @@ bus_dma_tag_t bus_get_dma_tag(device_t dev);
|
||||
int bus_setup_intr(device_t dev, struct resource *r, int flags,
|
||||
driver_filter_t filter, driver_intr_t handler, void *arg, void **_cookie);
|
||||
int bus_teardown_intr(device_t dev, struct resource *r, void *cookie);
|
||||
int bus_bind_intr(device_t dev, struct resource *r, int cpu);
|
||||
|
||||
const char *device_get_name(device_t dev);
|
||||
const char *device_get_nameunit(device_t dev);
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* Copyright 2017 Haiku Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef _FBSD_COMPAT_SYS_COUNTER_H_
|
||||
#define _FBSD_COMPAT_SYS_COUNTER_H_
|
||||
|
||||
|
||||
typedef uint64_t *counter_u64_t;
|
||||
|
||||
|
||||
#endif
|
||||
@@ -46,6 +46,6 @@ struct __system_init {
|
||||
#define TUNABLE_INT(path, var)
|
||||
#define TUNABLE_INT_FETCH(path, var)
|
||||
|
||||
extern int ticks;
|
||||
extern int32 ticks;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2014 Haiku Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef _FBSD_COMPAT_SYS_SMP_H_
|
||||
#define _FBSD_COMPAT_SYS_SMP_H_
|
||||
|
||||
|
||||
extern u_int mp_maxid;
|
||||
extern int mp_ncpus;
|
||||
|
||||
|
||||
static inline int
|
||||
cpu_first(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
cpu_next(int i)
|
||||
{
|
||||
i++;
|
||||
if (i > mp_maxid)
|
||||
i = 0;
|
||||
return i;
|
||||
}
|
||||
|
||||
#define CPU_FIRST() cpu_first()
|
||||
#define CPU_NEXT(i) cpu_next((i))
|
||||
|
||||
|
||||
#endif
|
||||
@@ -18,17 +18,22 @@
|
||||
#include <compat/sys/kernel.h>
|
||||
#include <compat/sys/taskqueue.h>
|
||||
|
||||
#include <compat/net/ethernet.h>
|
||||
#include <compat/net/if.h>
|
||||
#include <compat/net/if_arp.h>
|
||||
#include <compat/net/if_media.h>
|
||||
#include <compat/net/if_var.h>
|
||||
#include <compat/net/if_vlan_var.h>
|
||||
#include <compat/sys/malloc.h>
|
||||
|
||||
#include <compat/net/ethernet.h>
|
||||
|
||||
|
||||
int ifqmaxlen = IFQ_MAXLEN;
|
||||
|
||||
static void if_input_default(struct ifnet *, struct mbuf *);
|
||||
static int if_requestencap_default(struct ifnet *, struct if_encap_req *);
|
||||
|
||||
|
||||
|
||||
#define IFNET_HOLD (void *)(uintptr_t)(-1)
|
||||
|
||||
@@ -307,9 +312,49 @@ if_transmit(struct ifnet *ifp, struct mbuf *m)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
if_input_default(struct ifnet *ifp __unused, struct mbuf *m)
|
||||
{
|
||||
|
||||
m_freem(m);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Flush an interface queue.
|
||||
*/
|
||||
void
|
||||
if_qflush(struct ifnet *ifp)
|
||||
{
|
||||
struct mbuf *m, *n;
|
||||
struct ifaltq *ifq;
|
||||
|
||||
ifq = &ifp->if_snd;
|
||||
IFQ_LOCK(ifq);
|
||||
#ifdef ALTQ
|
||||
if (ALTQ_IS_ENABLED(ifq))
|
||||
ALTQ_PURGE(ifq);
|
||||
#endif
|
||||
n = ifq->ifq_head;
|
||||
while ((m = n) != NULL) {
|
||||
n = m->m_nextpkt;
|
||||
m_freem(m);
|
||||
}
|
||||
ifq->ifq_head = 0;
|
||||
ifq->ifq_tail = 0;
|
||||
ifq->ifq_len = 0;
|
||||
IFQ_UNLOCK(ifq);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
if_attach(struct ifnet *ifp)
|
||||
{
|
||||
unsigned socksize, ifasize;
|
||||
int namelen, masklen;
|
||||
struct sockaddr_dl *sdl;
|
||||
struct ifaddr *ifa;
|
||||
|
||||
TAILQ_INIT(&ifp->if_addrhead);
|
||||
TAILQ_INIT(&ifp->if_prefixhead);
|
||||
TAILQ_INIT(&ifp->if_multiaddrs);
|
||||
@@ -322,7 +367,46 @@ if_attach(struct ifnet *ifp)
|
||||
|
||||
if (ifp->if_transmit == NULL) {
|
||||
ifp->if_transmit = if_transmit;
|
||||
ifp->if_qflush = if_qflush;
|
||||
}
|
||||
if (ifp->if_input == NULL)
|
||||
ifp->if_input = if_input_default;
|
||||
|
||||
if (ifp->if_requestencap == NULL)
|
||||
ifp->if_requestencap = if_requestencap_default;
|
||||
|
||||
/*
|
||||
* Create a Link Level name for this device.
|
||||
*/
|
||||
namelen = strlen(ifp->if_xname);
|
||||
/*
|
||||
* Always save enough space for any possiable name so we
|
||||
* can do a rename in place later.
|
||||
*/
|
||||
masklen = offsetof(struct sockaddr_dl, sdl_data[0]) + IFNAMSIZ;
|
||||
socksize = masklen + ifp->if_addrlen;
|
||||
if (socksize < sizeof(*sdl))
|
||||
socksize = sizeof(*sdl);
|
||||
socksize = roundup2(socksize, sizeof(long));
|
||||
ifasize = sizeof(*ifa) + 2 * socksize;
|
||||
ifa = ifa_alloc(ifasize, M_WAITOK);
|
||||
sdl = (struct sockaddr_dl *)(ifa + 1);
|
||||
sdl->sdl_len = socksize;
|
||||
sdl->sdl_family = AF_LINK;
|
||||
bcopy(ifp->if_xname, sdl->sdl_data, namelen);
|
||||
sdl->sdl_nlen = namelen;
|
||||
sdl->sdl_index = ifp->if_index;
|
||||
sdl->sdl_type = ifp->if_type;
|
||||
ifp->if_addr = ifa;
|
||||
ifa->ifa_ifp = ifp;
|
||||
//ifa->ifa_rtrequest = link_rtrequest;
|
||||
ifa->ifa_addr = (struct sockaddr *)sdl;
|
||||
sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl);
|
||||
ifa->ifa_netmask = (struct sockaddr *)sdl;
|
||||
sdl->sdl_len = masklen;
|
||||
while (namelen != 0)
|
||||
sdl->sdl_data[--namelen] = 0xff;
|
||||
dprintf("if_attach %p\n", ifa->ifa_addr);
|
||||
}
|
||||
|
||||
|
||||
@@ -362,6 +446,44 @@ if_printf(struct ifnet *ifp, const char *format, ...)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Compat function for handling basic encapsulation requests.
|
||||
* Not converted stacks (FDDI, IB, ..) supports traditional
|
||||
* output model: ARP (and other similar L2 protocols) are handled
|
||||
* inside output routine, arpresolve/nd6_resolve() returns MAC
|
||||
* address instead of full prepend.
|
||||
*
|
||||
* This function creates calculated header==MAC for IPv4/IPv6 and
|
||||
* returns EAFNOSUPPORT (which is then handled in ARP code) for other
|
||||
* address families.
|
||||
*/
|
||||
static int
|
||||
if_requestencap_default(struct ifnet *ifp, struct if_encap_req *req)
|
||||
{
|
||||
|
||||
if (req->rtype != IFENCAP_LL)
|
||||
return (EOPNOTSUPP);
|
||||
|
||||
if (req->bufsize < req->lladdr_len)
|
||||
return (ENOMEM);
|
||||
|
||||
switch (req->family) {
|
||||
case AF_INET:
|
||||
case AF_INET6:
|
||||
break;
|
||||
default:
|
||||
return (EAFNOSUPPORT);
|
||||
}
|
||||
|
||||
/* Copy lladdr to storage as is */
|
||||
memmove(req->buf, req->lladdr, req->lladdr_len);
|
||||
req->bufsize = req->lladdr_len;
|
||||
req->lladdr_off = 0;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
if_link_state_change(struct ifnet *ifp, int linkState)
|
||||
{
|
||||
@@ -372,7 +494,6 @@ if_link_state_change(struct ifnet *ifp, int linkState)
|
||||
release_sem_etc(ifp->link_state_sem, 1, B_DO_NOT_RESCHEDULE);
|
||||
}
|
||||
|
||||
|
||||
static struct ifmultiaddr *
|
||||
if_findmulti(struct ifnet *ifp, struct sockaddr *_address)
|
||||
{
|
||||
@@ -620,6 +741,45 @@ if_purgemaddrs(struct ifnet *ifp)
|
||||
IF_ADDR_UNLOCK(ifp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return counter values from counter(9)s stored in ifnet.
|
||||
*/
|
||||
uint64_t
|
||||
if_get_counter_default(struct ifnet *ifp, ift_counter cnt)
|
||||
{
|
||||
|
||||
KASSERT(cnt < IFCOUNTERS, ("%s: invalid cnt %d", __func__, cnt));
|
||||
|
||||
switch (cnt) {
|
||||
case IFCOUNTER_IPACKETS:
|
||||
return atomic_get64((int64 *)&ifp->if_ipackets);
|
||||
case IFCOUNTER_IERRORS:
|
||||
return atomic_get64((int64 *)&ifp->if_ierrors);
|
||||
case IFCOUNTER_OPACKETS:
|
||||
return atomic_get64((int64 *)&ifp->if_opackets);
|
||||
case IFCOUNTER_OERRORS:
|
||||
return atomic_get64((int64 *)&ifp->if_oerrors);
|
||||
case IFCOUNTER_COLLISIONS:
|
||||
return atomic_get64((int64 *)&ifp->if_collisions);
|
||||
case IFCOUNTER_IBYTES:
|
||||
return atomic_get64((int64 *)&ifp->if_ibytes);
|
||||
case IFCOUNTER_OBYTES:
|
||||
return atomic_get64((int64 *)&ifp->if_obytes);
|
||||
case IFCOUNTER_IMCASTS:
|
||||
return atomic_get64((int64 *)&ifp->if_imcasts);
|
||||
case IFCOUNTER_OMCASTS:
|
||||
return atomic_get64((int64 *)&ifp->if_omcasts);
|
||||
case IFCOUNTER_IQDROPS:
|
||||
return atomic_get64((int64 *)&ifp->if_iqdrops);
|
||||
case IFCOUNTER_OQDROPS:
|
||||
return atomic_get64((int64 *)&ifp->if_oqdrops);
|
||||
case IFCOUNTER_NOPROTO:
|
||||
return atomic_get64((int64 *)&ifp->if_noproto);
|
||||
case IFCOUNTERS:
|
||||
KASSERT(cnt < IFCOUNTERS, ("%s: invalid cnt %d", __func__, cnt));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
if_addr_rlock(struct ifnet *ifp)
|
||||
@@ -667,8 +827,11 @@ static void ether_input(struct ifnet *ifp, struct mbuf *m)
|
||||
|
||||
|
||||
void
|
||||
ether_ifattach(struct ifnet *ifp, const uint8_t *macAddress)
|
||||
ether_ifattach(struct ifnet *ifp, const uint8_t *lla)
|
||||
{
|
||||
struct ifaddr *ifa;
|
||||
struct sockaddr_dl *sdl;
|
||||
|
||||
ifp->if_addrlen = ETHER_ADDR_LEN;
|
||||
ifp->if_hdrlen = ETHER_HDR_LEN;
|
||||
if_attach(ifp);
|
||||
@@ -678,12 +841,11 @@ ether_ifattach(struct ifnet *ifp, const uint8_t *macAddress)
|
||||
ifp->if_resolvemulti = NULL; // done in the stack
|
||||
ifp->if_broadcastaddr = etherbroadcastaddr;
|
||||
|
||||
memcpy(IF_LLADDR(ifp), macAddress, ETHER_ADDR_LEN);
|
||||
|
||||
// TODO: according to FreeBSD's if_ethersubr.c, this should be removed
|
||||
// once all drivers are cleaned up.
|
||||
if (macAddress != IFP2ENADDR(ifp))
|
||||
memcpy(IFP2ENADDR(ifp), macAddress, ETHER_ADDR_LEN);
|
||||
ifa = ifp->if_addr;
|
||||
sdl = (struct sockaddr_dl *)ifa->ifa_addr;
|
||||
sdl->sdl_type = IFT_ETHER;
|
||||
sdl->sdl_alen = ifp->if_addrlen;
|
||||
bcopy(lla, LLADDR(sdl), ifp->if_addrlen);
|
||||
}
|
||||
|
||||
|
||||
@@ -717,47 +879,486 @@ ether_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Initialization, destruction and refcounting functions for ifaddrs.
|
||||
*/
|
||||
struct ifaddr *
|
||||
ifa_alloc(size_t size, int flags)
|
||||
{
|
||||
struct ifaddr *ifa;
|
||||
|
||||
KASSERT(size >= sizeof(struct ifaddr),
|
||||
("%s: invalid size %zu", __func__, size));
|
||||
|
||||
ifa = _kernel_malloc(size, M_ZERO | flags);
|
||||
if (ifa == NULL)
|
||||
return (NULL);
|
||||
|
||||
//refcount_init(&ifa->ifa_refcnt, 1);
|
||||
|
||||
return (ifa);
|
||||
|
||||
fail:
|
||||
/* free(NULL) is okay */
|
||||
free(ifa);
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
void
|
||||
ifa_ref(struct ifaddr *ifa)
|
||||
{
|
||||
//refcount_acquire(&ifa->ifa_refcnt);
|
||||
}
|
||||
|
||||
void
|
||||
ifa_free(struct ifaddr *ifa)
|
||||
{
|
||||
|
||||
//if (refcount_release(&ifa->ifa_refcnt)) {
|
||||
// free(ifa);
|
||||
//}
|
||||
}
|
||||
|
||||
void
|
||||
if_inc_counter(struct ifnet *ifp, ift_counter cnt, int64_t inc)
|
||||
{
|
||||
switch (cnt) {
|
||||
case IFCOUNTER_IPACKETS:
|
||||
atomic_add(&ifp->if_ipackets, inc);
|
||||
atomic_add64((int64 *)&ifp->if_ipackets, inc);
|
||||
break;
|
||||
case IFCOUNTER_IERRORS:
|
||||
atomic_add(&ifp->if_ierrors, inc);
|
||||
atomic_add64((int64 *)&ifp->if_ierrors, inc);
|
||||
break;
|
||||
case IFCOUNTER_OPACKETS:
|
||||
atomic_add(&ifp->if_opackets, inc);
|
||||
atomic_add64((int64 *)&ifp->if_opackets, inc);
|
||||
break;
|
||||
case IFCOUNTER_OERRORS:
|
||||
atomic_add(&ifp->if_oerrors, inc);
|
||||
atomic_add64((int64 *)&ifp->if_oerrors, inc);
|
||||
break;
|
||||
case IFCOUNTER_COLLISIONS:
|
||||
atomic_add(&ifp->if_collisions, inc);
|
||||
atomic_add64((int64 *)&ifp->if_collisions, inc);
|
||||
break;
|
||||
case IFCOUNTER_IBYTES:
|
||||
atomic_add(&ifp->if_ibytes, inc);
|
||||
atomic_add64((int64 *)&ifp->if_ibytes, inc);
|
||||
break;
|
||||
case IFCOUNTER_OBYTES:
|
||||
atomic_add(&ifp->if_obytes, inc);
|
||||
atomic_add64((int64 *)&ifp->if_obytes, inc);
|
||||
break;
|
||||
case IFCOUNTER_IMCASTS:
|
||||
atomic_add(&ifp->if_imcasts, inc);
|
||||
atomic_add64((int64 *)&ifp->if_imcasts, inc);
|
||||
break;
|
||||
case IFCOUNTER_OMCASTS:
|
||||
atomic_add(&ifp->if_omcasts, inc);
|
||||
atomic_add64((int64 *)&ifp->if_omcasts, inc);
|
||||
break;
|
||||
case IFCOUNTER_IQDROPS:
|
||||
atomic_add(&ifp->if_iqdrops, inc);
|
||||
atomic_add64((int64 *)&ifp->if_iqdrops, inc);
|
||||
break;
|
||||
case IFCOUNTER_OQDROPS:
|
||||
atomic_add(&ifp->if_oqdrops, inc);
|
||||
atomic_add64((int64 *)&ifp->if_oqdrops, inc);
|
||||
break;
|
||||
case IFCOUNTER_NOPROTO:
|
||||
atomic_add(&ifp->if_noproto, inc);
|
||||
atomic_add64((int64 *)&ifp->if_noproto, inc);
|
||||
break;
|
||||
case IFCOUNTERS:
|
||||
KASSERT(cnt < IFCOUNTERS, ("%s: invalid cnt %d", __func__, cnt));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* API for driver access to network stack owned ifnet.*/
|
||||
uint64_t
|
||||
if_setbaudrate(struct ifnet *ifp, uint64_t baudrate)
|
||||
{
|
||||
uint64_t oldbrate;
|
||||
|
||||
oldbrate = ifp->if_baudrate;
|
||||
ifp->if_baudrate = baudrate;
|
||||
return (oldbrate);
|
||||
}
|
||||
|
||||
uint64_t
|
||||
if_getbaudrate(if_t ifp)
|
||||
{
|
||||
|
||||
return (((struct ifnet *)ifp)->if_baudrate);
|
||||
}
|
||||
|
||||
int
|
||||
if_setcapabilities(if_t ifp, int capabilities)
|
||||
{
|
||||
((struct ifnet *)ifp)->if_capabilities = capabilities;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
if_setcapabilitiesbit(if_t ifp, int setbit, int clearbit)
|
||||
{
|
||||
((struct ifnet *)ifp)->if_capabilities |= setbit;
|
||||
((struct ifnet *)ifp)->if_capabilities &= ~clearbit;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
if_getcapabilities(if_t ifp)
|
||||
{
|
||||
return ((struct ifnet *)ifp)->if_capabilities;
|
||||
}
|
||||
|
||||
int
|
||||
if_setcapenable(if_t ifp, int capabilities)
|
||||
{
|
||||
((struct ifnet *)ifp)->if_capenable = capabilities;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
if_setcapenablebit(if_t ifp, int setcap, int clearcap)
|
||||
{
|
||||
if(setcap)
|
||||
((struct ifnet *)ifp)->if_capenable |= setcap;
|
||||
if(clearcap)
|
||||
((struct ifnet *)ifp)->if_capenable &= ~clearcap;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
const char *
|
||||
if_getdname(if_t ifp)
|
||||
{
|
||||
return ((struct ifnet *)ifp)->if_dname;
|
||||
}
|
||||
|
||||
int
|
||||
if_togglecapenable(if_t ifp, int togglecap)
|
||||
{
|
||||
((struct ifnet *)ifp)->if_capenable ^= togglecap;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
if_getcapenable(if_t ifp)
|
||||
{
|
||||
return ((struct ifnet *)ifp)->if_capenable;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is largely undesirable because it ties ifnet to a device, but does
|
||||
* provide flexiblity for an embedded product vendor. Should be used with
|
||||
* the understanding that it violates the interface boundaries, and should be
|
||||
* a last resort only.
|
||||
*/
|
||||
int
|
||||
if_setdev(if_t ifp, void *dev)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
if_setdrvflagbits(if_t ifp, int set_flags, int clear_flags)
|
||||
{
|
||||
((struct ifnet *)ifp)->if_drv_flags |= set_flags;
|
||||
((struct ifnet *)ifp)->if_drv_flags &= ~clear_flags;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
if_getdrvflags(if_t ifp)
|
||||
{
|
||||
return ((struct ifnet *)ifp)->if_drv_flags;
|
||||
}
|
||||
|
||||
int
|
||||
if_setdrvflags(if_t ifp, int flags)
|
||||
{
|
||||
((struct ifnet *)ifp)->if_drv_flags = flags;
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
if_setflags(if_t ifp, int flags)
|
||||
{
|
||||
((struct ifnet *)ifp)->if_flags = flags;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
if_setflagbits(if_t ifp, int set, int clear)
|
||||
{
|
||||
((struct ifnet *)ifp)->if_flags |= set;
|
||||
((struct ifnet *)ifp)->if_flags &= ~clear;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
if_getflags(if_t ifp)
|
||||
{
|
||||
return ((struct ifnet *)ifp)->if_flags;
|
||||
}
|
||||
|
||||
int
|
||||
if_clearhwassist(if_t ifp)
|
||||
{
|
||||
((struct ifnet *)ifp)->if_hwassist = 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
if_sethwassistbits(if_t ifp, int toset, int toclear)
|
||||
{
|
||||
((struct ifnet *)ifp)->if_hwassist |= toset;
|
||||
((struct ifnet *)ifp)->if_hwassist &= ~toclear;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
if_sethwassist(if_t ifp, int hwassist_bit)
|
||||
{
|
||||
((struct ifnet *)ifp)->if_hwassist = hwassist_bit;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
if_gethwassist(if_t ifp)
|
||||
{
|
||||
return ((struct ifnet *)ifp)->if_hwassist;
|
||||
}
|
||||
|
||||
int
|
||||
if_setmtu(if_t ifp, int mtu)
|
||||
{
|
||||
((struct ifnet *)ifp)->if_mtu = mtu;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
if_getmtu(if_t ifp)
|
||||
{
|
||||
return ((struct ifnet *)ifp)->if_mtu;
|
||||
}
|
||||
|
||||
int
|
||||
if_setsoftc(if_t ifp, void *softc)
|
||||
{
|
||||
((struct ifnet *)ifp)->if_softc = softc;
|
||||
return (0);
|
||||
}
|
||||
|
||||
void *
|
||||
if_getsoftc(if_t ifp)
|
||||
{
|
||||
return ((struct ifnet *)ifp)->if_softc;
|
||||
}
|
||||
|
||||
void
|
||||
if_setrcvif(struct mbuf *m, if_t ifp)
|
||||
{
|
||||
m->m_pkthdr.rcvif = (struct ifnet *)ifp;
|
||||
}
|
||||
|
||||
void
|
||||
if_setvtag(struct mbuf *m, uint16_t tag)
|
||||
{
|
||||
m->m_pkthdr.ether_vtag = tag;
|
||||
}
|
||||
|
||||
uint16_t
|
||||
if_getvtag(struct mbuf *m)
|
||||
{
|
||||
|
||||
return (m->m_pkthdr.ether_vtag);
|
||||
}
|
||||
|
||||
int
|
||||
if_sendq_empty(if_t ifp)
|
||||
{
|
||||
return IFQ_DRV_IS_EMPTY(&((struct ifnet *)ifp)->if_snd);
|
||||
}
|
||||
|
||||
int
|
||||
if_getamcount(if_t ifp)
|
||||
{
|
||||
return ((struct ifnet *)ifp)->if_amcount;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
if_setsendqready(if_t ifp)
|
||||
{
|
||||
IFQ_SET_READY(&((struct ifnet *)ifp)->if_snd);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
if_setsendqlen(if_t ifp, int tx_desc_count)
|
||||
{
|
||||
IFQ_SET_MAXLEN(&((struct ifnet *)ifp)->if_snd, tx_desc_count);
|
||||
((struct ifnet *)ifp)->if_snd.ifq_drv_maxlen = tx_desc_count;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
if_vlantrunkinuse(if_t ifp)
|
||||
{
|
||||
return ((struct ifnet *)ifp)->if_vlantrunk != NULL?1:0;
|
||||
}
|
||||
|
||||
int
|
||||
if_input(if_t ifp, struct mbuf* sendmp)
|
||||
{
|
||||
(*((struct ifnet *)ifp)->if_input)((struct ifnet *)ifp, sendmp);
|
||||
return (0);
|
||||
|
||||
}
|
||||
|
||||
/* XXX */
|
||||
#ifndef ETH_ADDR_LEN
|
||||
#define ETH_ADDR_LEN 6
|
||||
#endif
|
||||
|
||||
int
|
||||
if_setupmultiaddr(if_t ifp, void *mta, int *cnt, int max)
|
||||
{
|
||||
struct ifmultiaddr *ifma;
|
||||
uint8_t *lmta = (uint8_t *)mta;
|
||||
int mcnt = 0;
|
||||
|
||||
TAILQ_FOREACH(ifma, &((struct ifnet *)ifp)->if_multiaddrs, ifma_link) {
|
||||
if (ifma->ifma_addr->sa_family != AF_LINK)
|
||||
continue;
|
||||
|
||||
if (mcnt == max)
|
||||
break;
|
||||
|
||||
bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr),
|
||||
&lmta[mcnt * ETH_ADDR_LEN], ETH_ADDR_LEN);
|
||||
mcnt++;
|
||||
}
|
||||
*cnt = mcnt;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
if_multiaddr_array(if_t ifp, void *mta, int *cnt, int max)
|
||||
{
|
||||
int error;
|
||||
|
||||
if_maddr_rlock(ifp);
|
||||
error = if_setupmultiaddr(ifp, mta, cnt, max);
|
||||
if_maddr_runlock(ifp);
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
if_multiaddr_count(if_t ifp, int max)
|
||||
{
|
||||
struct ifmultiaddr *ifma;
|
||||
int count;
|
||||
|
||||
count = 0;
|
||||
if_maddr_rlock(ifp);
|
||||
TAILQ_FOREACH(ifma, &((struct ifnet *)ifp)->if_multiaddrs, ifma_link) {
|
||||
if (ifma->ifma_addr->sa_family != AF_LINK)
|
||||
continue;
|
||||
count++;
|
||||
if (count == max)
|
||||
break;
|
||||
}
|
||||
if_maddr_runlock(ifp);
|
||||
return (count);
|
||||
}
|
||||
|
||||
struct mbuf *
|
||||
if_dequeue(if_t ifp)
|
||||
{
|
||||
struct mbuf *m;
|
||||
IFQ_DRV_DEQUEUE(&((struct ifnet *)ifp)->if_snd, m);
|
||||
|
||||
return (m);
|
||||
}
|
||||
|
||||
int
|
||||
if_sendq_prepend(if_t ifp, struct mbuf *m)
|
||||
{
|
||||
IFQ_DRV_PREPEND(&((struct ifnet *)ifp)->if_snd, m);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
if_setifheaderlen(if_t ifp, int len)
|
||||
{
|
||||
((struct ifnet *)ifp)->if_hdrlen = len;
|
||||
return (0);
|
||||
}
|
||||
|
||||
caddr_t
|
||||
if_getlladdr(if_t ifp)
|
||||
{
|
||||
return (IF_LLADDR((struct ifnet *)ifp));
|
||||
}
|
||||
|
||||
void *
|
||||
if_gethandle(u_char type)
|
||||
{
|
||||
return (if_alloc(type));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
if_etherbpfmtap(if_t ifh, struct mbuf *m)
|
||||
{
|
||||
struct ifnet *ifp = (struct ifnet *)ifh;
|
||||
|
||||
ETHER_BPF_MTAP(ifp, m);
|
||||
}
|
||||
|
||||
void
|
||||
if_vlancap(if_t ifh)
|
||||
{
|
||||
struct ifnet *ifp = (struct ifnet *)ifh;
|
||||
VLAN_CAPABILITIES(ifp);
|
||||
}
|
||||
|
||||
void
|
||||
if_setinitfn(if_t ifp, void (*init_fn)(void *))
|
||||
{
|
||||
((struct ifnet *)ifp)->if_init = init_fn;
|
||||
}
|
||||
|
||||
void
|
||||
if_setioctlfn(if_t ifp, int (*ioctl_fn)(if_t, u_long, caddr_t))
|
||||
{
|
||||
((struct ifnet *)ifp)->if_ioctl = (void *)ioctl_fn;
|
||||
}
|
||||
|
||||
void
|
||||
if_setstartfn(if_t ifp, void (*start_fn)(if_t))
|
||||
{
|
||||
((struct ifnet *)ifp)->if_start = (void *)start_fn;
|
||||
}
|
||||
|
||||
void
|
||||
if_settransmitfn(if_t ifp, if_transmit_fn_t start_fn)
|
||||
{
|
||||
((struct ifnet *)ifp)->if_transmit = start_fn;
|
||||
}
|
||||
|
||||
void if_setqflushfn(if_t ifp, if_qflush_fn_t flush_fn)
|
||||
{
|
||||
((struct ifnet *)ifp)->if_qflush = flush_fn;
|
||||
}
|
||||
|
||||
void
|
||||
if_setgetcounterfn(if_t ifp, if_get_counter_t fn)
|
||||
{
|
||||
|
||||
ifp->if_get_counter = fn;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* Copyright 2009, Colin Günther, coling@gmx.de
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "device.h"
|
||||
|
||||
#include <compat/sys/kernel.h>
|
||||
|
||||
u_int mp_maxid = 0;
|
||||
int mp_ncpus = 1;
|
||||
Reference in New Issue
Block a user