freebsd11_network: adapt code based on needs of the e1000 R11.1 driver.

This commit is contained in:
Jérôme Duval
2017-11-15 21:21:44 +01:00
parent f9a21cf8ba
commit 078cb10834
14 changed files with 1371 additions and 55 deletions
+1
View File
@@ -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 ;
+3 -2
View File
@@ -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
+10
View File
@@ -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
+2 -2
View File
@@ -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
+622 -21
View File
@@ -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;
}
+12
View File
@@ -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;