From 078cb1083454d16008411522ff06fc72136cc36f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Tue, 14 Nov 2017 21:22:30 +0100 Subject: [PATCH] freebsd11_network: adapt code based on needs of the e1000 R11.1 driver. --- src/libs/compat/Jamfile | 1 + src/libs/compat/freebsd11_network/Jamfile | 5 +- src/libs/compat/freebsd11_network/bus.cpp | 10 + src/libs/compat/freebsd11_network/clock.c | 4 +- .../freebsd11_network/compat/machine/atomic.h | 5 + .../compat/freebsd11_network/compat/net/if.h | 48 +- .../freebsd11_network/compat/net/if_var.h | 155 ++++- .../freebsd11_network/compat/net/vnet.h | 496 ++++++++++++++ .../compat/freebsd11_network/compat/sys/bus.h | 1 + .../freebsd11_network/compat/sys/counter.h | 12 + .../freebsd11_network/compat/sys/kernel.h | 2 +- .../compat/freebsd11_network/compat/sys/smp.h | 32 + src/libs/compat/freebsd11_network/if.c | 643 +++++++++++++++++- src/libs/compat/freebsd11_network/smp.c | 12 + 14 files changed, 1371 insertions(+), 55 deletions(-) create mode 100644 src/libs/compat/freebsd11_network/compat/net/vnet.h create mode 100644 src/libs/compat/freebsd11_network/compat/sys/counter.h create mode 100644 src/libs/compat/freebsd11_network/compat/sys/smp.h create mode 100644 src/libs/compat/freebsd11_network/smp.c diff --git a/src/libs/compat/Jamfile b/src/libs/compat/Jamfile index 8709c90448..1b4bd3b639 100644 --- a/src/libs/compat/Jamfile +++ b/src/libs/compat/Jamfile @@ -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 ; diff --git a/src/libs/compat/freebsd11_network/Jamfile b/src/libs/compat/freebsd11_network/Jamfile index 3d7b496a88..ed2249cdd7 100644 --- a/src/libs/compat/freebsd11_network/Jamfile +++ b/src/libs/compat/freebsd11_network/Jamfile @@ -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 diff --git a/src/libs/compat/freebsd11_network/bus.cpp b/src/libs/compat/freebsd11_network/bus.cpp index 4a77a0af1c..290378fd84 100644 --- a/src/libs/compat/freebsd11_network/bus.cpp +++ b/src/libs/compat/freebsd11_network/bus.cpp @@ -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 diff --git a/src/libs/compat/freebsd11_network/clock.c b/src/libs/compat/freebsd11_network/clock.c index fce43ccef2..43c7743144 100644 --- a/src/libs/compat/freebsd11_network/clock.c +++ b/src/libs/compat/freebsd11_network/clock.c @@ -9,7 +9,7 @@ #include -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; } diff --git a/src/libs/compat/freebsd11_network/compat/machine/atomic.h b/src/libs/compat/freebsd11_network/compat/machine/atomic.h index d02f8ff148..14855bbce3 100644 --- a/src/libs/compat/freebsd11_network/compat/machine/atomic.h +++ b/src/libs/compat/freebsd11_network/compat/machine/atomic.h @@ -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_ */ diff --git a/src/libs/compat/freebsd11_network/compat/net/if.h b/src/libs/compat/freebsd11_network/compat/net/if.h index e56059cd50..a876195fc5 100644 --- a/src/libs/compat/freebsd11_network/compat/net/if.h +++ b/src/libs/compat/freebsd11_network/compat/net/if.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 */ diff --git a/src/libs/compat/freebsd11_network/compat/net/if_var.h b/src/libs/compat/freebsd11_network/compat/net/if_var.h index 6a766f5bd0..a10704c3c3 100644 --- a/src/libs/compat/freebsd11_network/compat/net/if_var.h +++ b/src/libs/compat/freebsd11_network/compat/net/if_var.h @@ -80,6 +80,7 @@ struct route; #include #include #endif /* _KERNEL */ +#include #include /* XXX */ #include /* XXX */ #include /* 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 }; diff --git a/src/libs/compat/freebsd11_network/compat/net/vnet.h b/src/libs/compat/freebsd11_network/compat/net/vnet.h new file mode 100644 index 0000000000..ab2aa97a70 --- /dev/null +++ b/src/libs/compat/freebsd11_network/compat/net/vnet.h @@ -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 + * 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 + +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 +#include /* for struct thread */ +#include +#include + +/* + * 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 + * 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 + +/* + * 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 + +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_ */ diff --git a/src/libs/compat/freebsd11_network/compat/sys/bus.h b/src/libs/compat/freebsd11_network/compat/sys/bus.h index 889cd9992a..4056a83510 100644 --- a/src/libs/compat/freebsd11_network/compat/sys/bus.h +++ b/src/libs/compat/freebsd11_network/compat/sys/bus.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); diff --git a/src/libs/compat/freebsd11_network/compat/sys/counter.h b/src/libs/compat/freebsd11_network/compat/sys/counter.h new file mode 100644 index 0000000000..d4133a46e3 --- /dev/null +++ b/src/libs/compat/freebsd11_network/compat/sys/counter.h @@ -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 diff --git a/src/libs/compat/freebsd11_network/compat/sys/kernel.h b/src/libs/compat/freebsd11_network/compat/sys/kernel.h index 0124a6892b..1baa354c00 100644 --- a/src/libs/compat/freebsd11_network/compat/sys/kernel.h +++ b/src/libs/compat/freebsd11_network/compat/sys/kernel.h @@ -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 diff --git a/src/libs/compat/freebsd11_network/compat/sys/smp.h b/src/libs/compat/freebsd11_network/compat/sys/smp.h new file mode 100644 index 0000000000..62a79e5d7f --- /dev/null +++ b/src/libs/compat/freebsd11_network/compat/sys/smp.h @@ -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 diff --git a/src/libs/compat/freebsd11_network/if.c b/src/libs/compat/freebsd11_network/if.c index dc67514295..e609912cdd 100644 --- a/src/libs/compat/freebsd11_network/if.c +++ b/src/libs/compat/freebsd11_network/if.c @@ -18,17 +18,22 @@ #include #include +#include #include #include #include #include +#include #include -#include 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; +} + diff --git a/src/libs/compat/freebsd11_network/smp.c b/src/libs/compat/freebsd11_network/smp.c new file mode 100644 index 0000000000..adf98acea7 --- /dev/null +++ b/src/libs/compat/freebsd11_network/smp.c @@ -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 + +u_int mp_maxid = 0; +int mp_ncpus = 1;