168b8534bSLuigi Rizzo /* 2*17885a7bSLuigi Rizzo * Copyright (C) 2011-2014 Matteo Landi, Luigi Rizzo. All rights reserved. 3*17885a7bSLuigi Rizzo * Copyright (C) 2013-2014 Universita` di Pisa. All rights reserved. 468b8534bSLuigi Rizzo * 568b8534bSLuigi Rizzo * Redistribution and use in source and binary forms, with or without 668b8534bSLuigi Rizzo * modification, are permitted provided that the following conditions 768b8534bSLuigi Rizzo * are met: 868b8534bSLuigi Rizzo * 1. Redistributions of source code must retain the above copyright 968b8534bSLuigi Rizzo * notice, this list of conditions and the following disclaimer. 1068b8534bSLuigi Rizzo * 2. Redistributions in binary form must reproduce the above copyright 1168b8534bSLuigi Rizzo * notice, this list of conditions and the following disclaimer in the 1268b8534bSLuigi Rizzo * documentation and/or other materials provided with the distribution. 1368b8534bSLuigi Rizzo * 1468b8534bSLuigi Rizzo * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1568b8534bSLuigi Rizzo * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1668b8534bSLuigi Rizzo * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1768b8534bSLuigi Rizzo * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1868b8534bSLuigi Rizzo * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1968b8534bSLuigi Rizzo * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2068b8534bSLuigi Rizzo * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2168b8534bSLuigi Rizzo * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2268b8534bSLuigi Rizzo * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2368b8534bSLuigi Rizzo * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2468b8534bSLuigi Rizzo * SUCH DAMAGE. 2568b8534bSLuigi Rizzo */ 2668b8534bSLuigi Rizzo 2768b8534bSLuigi Rizzo /* 2868b8534bSLuigi Rizzo * $FreeBSD$ 2968b8534bSLuigi Rizzo * 3068b8534bSLuigi Rizzo * The header contains the definitions of constants and function 3168b8534bSLuigi Rizzo * prototypes used only in kernelspace. 3268b8534bSLuigi Rizzo */ 3368b8534bSLuigi Rizzo 3468b8534bSLuigi Rizzo #ifndef _NET_NETMAP_KERN_H_ 3568b8534bSLuigi Rizzo #define _NET_NETMAP_KERN_H_ 3668b8534bSLuigi Rizzo 37f9790aebSLuigi Rizzo #define WITH_VALE // comment out to disable VALE support 38f9790aebSLuigi Rizzo 391a26580eSLuigi Rizzo #if defined(__FreeBSD__) 40d4b42e08SLuigi Rizzo 41ce3ee1e7SLuigi Rizzo #define likely(x) __builtin_expect((long)!!(x), 1L) 42ce3ee1e7SLuigi Rizzo #define unlikely(x) __builtin_expect((long)!!(x), 0L) 43f196ce38SLuigi Rizzo 441a26580eSLuigi Rizzo #define NM_LOCK_T struct mtx 45f9790aebSLuigi Rizzo #define NMG_LOCK_T struct mtx 46f9790aebSLuigi Rizzo #define NMG_LOCK_INIT() mtx_init(&netmap_global_lock, \ 47f9790aebSLuigi Rizzo "netmap global lock", NULL, MTX_DEF) 48f9790aebSLuigi Rizzo #define NMG_LOCK_DESTROY() mtx_destroy(&netmap_global_lock) 49f9790aebSLuigi Rizzo #define NMG_LOCK() mtx_lock(&netmap_global_lock) 50f9790aebSLuigi Rizzo #define NMG_UNLOCK() mtx_unlock(&netmap_global_lock) 51f9790aebSLuigi Rizzo #define NMG_LOCK_ASSERT() mtx_assert(&netmap_global_lock, MA_OWNED) 52f9790aebSLuigi Rizzo 531a26580eSLuigi Rizzo #define NM_SELINFO_T struct selinfo 541a26580eSLuigi Rizzo #define MBUF_LEN(m) ((m)->m_pkthdr.len) 55f9790aebSLuigi Rizzo #define MBUF_IFP(m) ((m)->m_pkthdr.rcvif) 56*17885a7bSLuigi Rizzo #define NM_SEND_UP(ifp, m) ((NA(ifp))->if_input)(ifp, m) 57d4b42e08SLuigi Rizzo 58f9790aebSLuigi Rizzo #define NM_ATOMIC_T volatile int // XXX ? 59f9790aebSLuigi Rizzo /* atomic operations */ 60f9790aebSLuigi Rizzo #include <machine/atomic.h> 61f9790aebSLuigi Rizzo #define NM_ATOMIC_TEST_AND_SET(p) (!atomic_cmpset_acq_int((p), 0, 1)) 62f9790aebSLuigi Rizzo #define NM_ATOMIC_CLEAR(p) atomic_store_rel_int((p), 0) 63f9790aebSLuigi Rizzo 64f9790aebSLuigi Rizzo 65f9790aebSLuigi Rizzo MALLOC_DECLARE(M_NETMAP); 66f9790aebSLuigi Rizzo 67f9790aebSLuigi Rizzo // XXX linux struct, not used in FreeBSD 68f9790aebSLuigi Rizzo struct net_device_ops { 69f9790aebSLuigi Rizzo }; 70f9790aebSLuigi Rizzo struct hrtimer { 71f9790aebSLuigi Rizzo }; 72ce3ee1e7SLuigi Rizzo 7364ae02c3SLuigi Rizzo #elif defined (linux) 74d4b42e08SLuigi Rizzo 752579e2d7SLuigi Rizzo #define NM_LOCK_T safe_spinlock_t // see bsd_glue.h 761a26580eSLuigi Rizzo #define NM_SELINFO_T wait_queue_head_t 771a26580eSLuigi Rizzo #define MBUF_LEN(m) ((m)->len) 78f9790aebSLuigi Rizzo #define MBUF_IFP(m) ((m)->dev) 79*17885a7bSLuigi Rizzo #define NM_SEND_UP(ifp, m) \ 80*17885a7bSLuigi Rizzo do { \ 81*17885a7bSLuigi Rizzo m->priority = NM_MAGIC_PRIORITY; \ 82*17885a7bSLuigi Rizzo netif_rx(m); \ 83*17885a7bSLuigi Rizzo } while (0) 84f196ce38SLuigi Rizzo 85ce3ee1e7SLuigi Rizzo #define NM_ATOMIC_T volatile long unsigned int 86ce3ee1e7SLuigi Rizzo 87f9790aebSLuigi Rizzo // XXX a mtx would suffice here too 20130404 gl 88f9790aebSLuigi Rizzo #define NMG_LOCK_T struct semaphore 89f9790aebSLuigi Rizzo #define NMG_LOCK_INIT() sema_init(&netmap_global_lock, 1) 90f9790aebSLuigi Rizzo #define NMG_LOCK_DESTROY() 91f9790aebSLuigi Rizzo #define NMG_LOCK() down(&netmap_global_lock) 92f9790aebSLuigi Rizzo #define NMG_UNLOCK() up(&netmap_global_lock) 93f9790aebSLuigi Rizzo #define NMG_LOCK_ASSERT() // XXX to be completed 94f9790aebSLuigi Rizzo 95f196ce38SLuigi Rizzo #ifndef DEV_NETMAP 96f196ce38SLuigi Rizzo #define DEV_NETMAP 97ce3ee1e7SLuigi Rizzo #endif /* DEV_NETMAP */ 98f196ce38SLuigi Rizzo 99f196ce38SLuigi Rizzo /* 1008241616dSLuigi Rizzo * IFCAP_NETMAP goes into net_device's priv_flags (if_capenable). 1018241616dSLuigi Rizzo * This was 16 bits up to linux 2.6.36, so we need a 16 bit value on older 102f196ce38SLuigi Rizzo * platforms and tolerate the clash with IFF_DYNAMIC and IFF_BRIDGE_PORT. 1038241616dSLuigi Rizzo * For the 32-bit value, 0x100000 has no clashes until at least 3.5.1 104f196ce38SLuigi Rizzo */ 105f196ce38SLuigi Rizzo #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) 106f196ce38SLuigi Rizzo #define IFCAP_NETMAP 0x8000 107f196ce38SLuigi Rizzo #else 108f18be576SLuigi Rizzo #define IFCAP_NETMAP 0x200000 109f196ce38SLuigi Rizzo #endif 110f196ce38SLuigi Rizzo 111f196ce38SLuigi Rizzo #elif defined (__APPLE__) 112d4b42e08SLuigi Rizzo 1138241616dSLuigi Rizzo #warning apple support is incomplete. 114f196ce38SLuigi Rizzo #define likely(x) __builtin_expect(!!(x), 1) 115f196ce38SLuigi Rizzo #define unlikely(x) __builtin_expect(!!(x), 0) 116f196ce38SLuigi Rizzo #define NM_LOCK_T IOLock * 117f196ce38SLuigi Rizzo #define NM_SELINFO_T struct selinfo 118f196ce38SLuigi Rizzo #define MBUF_LEN(m) ((m)->m_pkthdr.len) 119f196ce38SLuigi Rizzo #define NM_SEND_UP(ifp, m) ((ifp)->if_input)(ifp, m) 120f196ce38SLuigi Rizzo 1211a26580eSLuigi Rizzo #else 122d4b42e08SLuigi Rizzo 1231a26580eSLuigi Rizzo #error unsupported platform 124d4b42e08SLuigi Rizzo 125d4b42e08SLuigi Rizzo #endif /* end - platform-specific code */ 1261a26580eSLuigi Rizzo 12768b8534bSLuigi Rizzo #define ND(format, ...) 12868b8534bSLuigi Rizzo #define D(format, ...) \ 12968b8534bSLuigi Rizzo do { \ 13068b8534bSLuigi Rizzo struct timeval __xxts; \ 13168b8534bSLuigi Rizzo microtime(&__xxts); \ 132*17885a7bSLuigi Rizzo printf("%03d.%06d [%4d] %-25s " format "\n", \ 13368b8534bSLuigi Rizzo (int)__xxts.tv_sec % 1000, (int)__xxts.tv_usec, \ 134*17885a7bSLuigi Rizzo __LINE__, __FUNCTION__, ##__VA_ARGS__); \ 13568b8534bSLuigi Rizzo } while (0) 13668b8534bSLuigi Rizzo 1378241616dSLuigi Rizzo /* rate limited, lps indicates how many per second */ 1388241616dSLuigi Rizzo #define RD(lps, format, ...) \ 1398241616dSLuigi Rizzo do { \ 1408241616dSLuigi Rizzo static int t0, __cnt; \ 1418241616dSLuigi Rizzo if (t0 != time_second) { \ 1428241616dSLuigi Rizzo t0 = time_second; \ 1438241616dSLuigi Rizzo __cnt = 0; \ 1448241616dSLuigi Rizzo } \ 1458241616dSLuigi Rizzo if (__cnt++ < lps) \ 1468241616dSLuigi Rizzo D(format, ##__VA_ARGS__); \ 1478241616dSLuigi Rizzo } while (0) 1488241616dSLuigi Rizzo 14968b8534bSLuigi Rizzo struct netmap_adapter; 150f18be576SLuigi Rizzo struct nm_bdg_fwd; 151f18be576SLuigi Rizzo struct nm_bridge; 152f18be576SLuigi Rizzo struct netmap_priv_d; 15368b8534bSLuigi Rizzo 154ce3ee1e7SLuigi Rizzo const char *nm_dump_buf(char *p, int len, int lim, char *dst); 155ce3ee1e7SLuigi Rizzo 156f9790aebSLuigi Rizzo #include "netmap_mbq.h" 157f9790aebSLuigi Rizzo 158f9790aebSLuigi Rizzo extern NMG_LOCK_T netmap_global_lock; 159f9790aebSLuigi Rizzo 16068b8534bSLuigi Rizzo /* 16164ae02c3SLuigi Rizzo * private, kernel view of a ring. Keeps track of the status of 16264ae02c3SLuigi Rizzo * a ring across system calls. 16364ae02c3SLuigi Rizzo * 16464ae02c3SLuigi Rizzo * nr_hwcur index of the next buffer to refill. 165*17885a7bSLuigi Rizzo * It corresponds to ring->head 166*17885a7bSLuigi Rizzo * at the time the system call returns. 16764ae02c3SLuigi Rizzo * 168*17885a7bSLuigi Rizzo * nr_hwtail index of the first buffer owned by the kernel. 169*17885a7bSLuigi Rizzo * On RX, hwcur->hwtail are receive buffers 170*17885a7bSLuigi Rizzo * not yet released. hwcur is advanced following 171*17885a7bSLuigi Rizzo * ring->head, hwtail is advanced on incoming packets, 172*17885a7bSLuigi Rizzo * and a wakeup is generated when hwtail passes ring->cur 173*17885a7bSLuigi Rizzo * On TX, hwcur->rcur have been filled by the sender 174*17885a7bSLuigi Rizzo * but not sent yet to the NIC; rcur->hwtail are available 175*17885a7bSLuigi Rizzo * for new transmissions, and hwtail->hwcur-1 are pending 176*17885a7bSLuigi Rizzo * transmissions not yet acknowledged. 17768b8534bSLuigi Rizzo * 1781a26580eSLuigi Rizzo * The indexes in the NIC and netmap rings are offset by nkr_hwofs slots. 17968b8534bSLuigi Rizzo * This is so that, on a reset, buffers owned by userspace are not 18068b8534bSLuigi Rizzo * modified by the kernel. In particular: 181*17885a7bSLuigi Rizzo * RX rings: the next empty buffer (hwtail + hwofs) coincides with 18268b8534bSLuigi Rizzo * the next empty buffer as known by the hardware (next_to_check or so). 18368b8534bSLuigi Rizzo * TX rings: hwcur + hwofs coincides with next_to_send 1841dce924dSLuigi Rizzo * 185ce3ee1e7SLuigi Rizzo * Clients cannot issue concurrent syscall on a ring. The system 186ce3ee1e7SLuigi Rizzo * detects this and reports an error using two flags, 187ce3ee1e7SLuigi Rizzo * NKR_WBUSY and NKR_RBUSY 1881dce924dSLuigi Rizzo * For received packets, slot->flags is set to nkr_slot_flags 1891dce924dSLuigi Rizzo * so we can provide a proper initial value (e.g. set NS_FORWARD 1901dce924dSLuigi Rizzo * when operating in 'transparent' mode). 191ce3ee1e7SLuigi Rizzo * 192ce3ee1e7SLuigi Rizzo * The following fields are used to implement lock-free copy of packets 193ce3ee1e7SLuigi Rizzo * from input to output ports in VALE switch: 194ce3ee1e7SLuigi Rizzo * nkr_hwlease buffer after the last one being copied. 195ce3ee1e7SLuigi Rizzo * A writer in nm_bdg_flush reserves N buffers 196ce3ee1e7SLuigi Rizzo * from nr_hwlease, advances it, then does the 197ce3ee1e7SLuigi Rizzo * copy outside the lock. 198ce3ee1e7SLuigi Rizzo * In RX rings (used for VALE ports), 199*17885a7bSLuigi Rizzo * nkr_hwtail <= nkr_hwlease < nkr_hwcur+N-1 200ce3ee1e7SLuigi Rizzo * In TX rings (used for NIC or host stack ports) 201*17885a7bSLuigi Rizzo * nkr_hwcur <= nkr_hwlease < nkr_hwtail 202ce3ee1e7SLuigi Rizzo * nkr_leases array of nkr_num_slots where writers can report 203ce3ee1e7SLuigi Rizzo * completion of their block. NR_NOSLOT (~0) indicates 204ce3ee1e7SLuigi Rizzo * that the writer has not finished yet 205ce3ee1e7SLuigi Rizzo * nkr_lease_idx index of next free slot in nr_leases, to be assigned 206ce3ee1e7SLuigi Rizzo * 207ce3ee1e7SLuigi Rizzo * The kring is manipulated by txsync/rxsync and generic netmap function. 208*17885a7bSLuigi Rizzo * 209*17885a7bSLuigi Rizzo * Concurrent rxsync or txsync on the same ring are prevented through 210*17885a7bSLuigi Rizzo * by nm_kr_lock() which in turn uses nr_busy. This is all we need 211*17885a7bSLuigi Rizzo * for NIC rings, and for TX rings attached to the host stack. 212*17885a7bSLuigi Rizzo * 213*17885a7bSLuigi Rizzo * RX rings attached to the host stack use an mbq (rx_queue) on both 214*17885a7bSLuigi Rizzo * rxsync_from_host() and netmap_transmit(). The mbq is protected 215*17885a7bSLuigi Rizzo * by its internal lock. 216*17885a7bSLuigi Rizzo * 217*17885a7bSLuigi Rizzo * RX rings attached to the VALE switch are accessed by both sender 218*17885a7bSLuigi Rizzo * and receiver. They are protected through the q_lock on the RX ring. 21968b8534bSLuigi Rizzo */ 22068b8534bSLuigi Rizzo struct netmap_kring { 22168b8534bSLuigi Rizzo struct netmap_ring *ring; 222*17885a7bSLuigi Rizzo 223ce3ee1e7SLuigi Rizzo uint32_t nr_hwcur; 224*17885a7bSLuigi Rizzo uint32_t nr_hwtail; 225*17885a7bSLuigi Rizzo 226*17885a7bSLuigi Rizzo /* 227*17885a7bSLuigi Rizzo * Copies of values in user rings, so we do not need to look 228*17885a7bSLuigi Rizzo * at the ring (which could be modified). These are set in the 229*17885a7bSLuigi Rizzo * *sync_prologue()/finalize() routines. 230*17885a7bSLuigi Rizzo */ 231*17885a7bSLuigi Rizzo uint32_t rhead; 232*17885a7bSLuigi Rizzo uint32_t rcur; 233*17885a7bSLuigi Rizzo uint32_t rtail; 234*17885a7bSLuigi Rizzo 235ce3ee1e7SLuigi Rizzo uint32_t nr_kflags; /* private driver flags */ 2362157a17cSLuigi Rizzo #define NKR_PENDINTR 0x1 // Pending interrupt. 237ce3ee1e7SLuigi Rizzo uint32_t nkr_num_slots; 238*17885a7bSLuigi Rizzo 239*17885a7bSLuigi Rizzo /* 240*17885a7bSLuigi Rizzo * On a NIC reset, the NIC ring indexes may be reset but the 241*17885a7bSLuigi Rizzo * indexes in the netmap rings remain the same. nkr_hwofs 242*17885a7bSLuigi Rizzo * keeps track of the offset between the two. 243*17885a7bSLuigi Rizzo */ 244*17885a7bSLuigi Rizzo int32_t nkr_hwofs; 24568b8534bSLuigi Rizzo 2461dce924dSLuigi Rizzo uint16_t nkr_slot_flags; /* initial value for flags */ 247*17885a7bSLuigi Rizzo 248*17885a7bSLuigi Rizzo /* last_reclaim is opaque marker to help reduce the frequency 249*17885a7bSLuigi Rizzo * of operations such as reclaiming tx buffers. A possible use 250*17885a7bSLuigi Rizzo * is set it to ticks and do the reclaim only once per tick. 251*17885a7bSLuigi Rizzo */ 252*17885a7bSLuigi Rizzo uint64_t last_reclaim; 253*17885a7bSLuigi Rizzo 254ce3ee1e7SLuigi Rizzo 2551a26580eSLuigi Rizzo NM_SELINFO_T si; /* poll/select wait queue */ 256ce3ee1e7SLuigi Rizzo NM_LOCK_T q_lock; /* protects kring and ring. */ 257ce3ee1e7SLuigi Rizzo NM_ATOMIC_T nr_busy; /* prevent concurrent syscalls */ 258ce3ee1e7SLuigi Rizzo 259*17885a7bSLuigi Rizzo struct netmap_adapter *na; 260*17885a7bSLuigi Rizzo 261*17885a7bSLuigi Rizzo /* The folloiwing fields are for VALE switch support */ 262*17885a7bSLuigi Rizzo struct nm_bdg_fwd *nkr_ft; 263*17885a7bSLuigi Rizzo uint32_t *nkr_leases; 264*17885a7bSLuigi Rizzo #define NR_NOSLOT ((uint32_t)~0) /* used in nkr_*lease* */ 265*17885a7bSLuigi Rizzo uint32_t nkr_hwlease; 266*17885a7bSLuigi Rizzo uint32_t nkr_lease_idx; 267*17885a7bSLuigi Rizzo 268*17885a7bSLuigi Rizzo volatile int nkr_stopped; // XXX what for ? 269f9790aebSLuigi Rizzo 270f9790aebSLuigi Rizzo /* support for adapters without native netmap support. 271f9790aebSLuigi Rizzo * On tx rings we preallocate an array of tx buffers 272f9790aebSLuigi Rizzo * (same size as the netmap ring), on rx rings we 273f9790aebSLuigi Rizzo * store incoming packets in a queue. 274f9790aebSLuigi Rizzo * XXX who writes to the rx queue ? 275f9790aebSLuigi Rizzo */ 276f9790aebSLuigi Rizzo struct mbuf **tx_pool; 277*17885a7bSLuigi Rizzo // u_int nr_ntc; /* Emulation of a next-to-clean RX ring pointer. */ 278*17885a7bSLuigi Rizzo struct mbq rx_queue; /* intercepted rx mbufs. */ 279*17885a7bSLuigi Rizzo 280*17885a7bSLuigi Rizzo uint32_t ring_id; /* debugging */ 281*17885a7bSLuigi Rizzo char name[64]; /* diagnostic */ 282f9790aebSLuigi Rizzo 2832157a17cSLuigi Rizzo } __attribute__((__aligned__(64))); 28468b8534bSLuigi Rizzo 285ce3ee1e7SLuigi Rizzo 286ce3ee1e7SLuigi Rizzo /* return the next index, with wraparound */ 287ce3ee1e7SLuigi Rizzo static inline uint32_t 288ce3ee1e7SLuigi Rizzo nm_next(uint32_t i, uint32_t lim) 289ce3ee1e7SLuigi Rizzo { 290ce3ee1e7SLuigi Rizzo return unlikely (i == lim) ? 0 : i + 1; 291ce3ee1e7SLuigi Rizzo } 292ce3ee1e7SLuigi Rizzo 293*17885a7bSLuigi Rizzo 294*17885a7bSLuigi Rizzo /* return the previous index, with wraparound */ 295*17885a7bSLuigi Rizzo static inline uint32_t 296*17885a7bSLuigi Rizzo nm_prev(uint32_t i, uint32_t lim) 297*17885a7bSLuigi Rizzo { 298*17885a7bSLuigi Rizzo return unlikely (i == 0) ? lim : i - 1; 299*17885a7bSLuigi Rizzo } 300*17885a7bSLuigi Rizzo 301*17885a7bSLuigi Rizzo 302ce3ee1e7SLuigi Rizzo /* 303ce3ee1e7SLuigi Rizzo * 304ce3ee1e7SLuigi Rizzo * Here is the layout for the Rx and Tx rings. 305ce3ee1e7SLuigi Rizzo 306ce3ee1e7SLuigi Rizzo RxRING TxRING 307ce3ee1e7SLuigi Rizzo 308ce3ee1e7SLuigi Rizzo +-----------------+ +-----------------+ 309ce3ee1e7SLuigi Rizzo | | | | 310ce3ee1e7SLuigi Rizzo |XXX free slot XXX| |XXX free slot XXX| 311ce3ee1e7SLuigi Rizzo +-----------------+ +-----------------+ 312*17885a7bSLuigi Rizzo head->| owned by user |<-hwcur | not sent to nic |<-hwcur 313*17885a7bSLuigi Rizzo | | | yet | 314*17885a7bSLuigi Rizzo +-----------------+ | | 315*17885a7bSLuigi Rizzo cur->| available to | | | 316*17885a7bSLuigi Rizzo | user, not read | +-----------------+ 317*17885a7bSLuigi Rizzo | yet | cur->| (being | 318*17885a7bSLuigi Rizzo | | | prepared) | 319ce3ee1e7SLuigi Rizzo | | | | 320*17885a7bSLuigi Rizzo +-----------------+ + ------ + 321*17885a7bSLuigi Rizzo tail->| |<-hwtail | |<-hwlease 322*17885a7bSLuigi Rizzo | (being | ... | | ... 323*17885a7bSLuigi Rizzo | prepared) | ... | | ... 324*17885a7bSLuigi Rizzo +-----------------+ ... | | ... 325*17885a7bSLuigi Rizzo | |<-hwlease +-----------------+ 326*17885a7bSLuigi Rizzo | | tail->| |<-hwtail 327ce3ee1e7SLuigi Rizzo | | | | 328ce3ee1e7SLuigi Rizzo | | | | 329ce3ee1e7SLuigi Rizzo | | | | 330ce3ee1e7SLuigi Rizzo +-----------------+ +-----------------+ 331ce3ee1e7SLuigi Rizzo 332*17885a7bSLuigi Rizzo * The cur/tail (user view) and hwcur/hwtail (kernel view) 333ce3ee1e7SLuigi Rizzo * are used in the normal operation of the card. 334ce3ee1e7SLuigi Rizzo * 335ce3ee1e7SLuigi Rizzo * When a ring is the output of a switch port (Rx ring for 336ce3ee1e7SLuigi Rizzo * a VALE port, Tx ring for the host stack or NIC), slots 337ce3ee1e7SLuigi Rizzo * are reserved in blocks through 'hwlease' which points 338ce3ee1e7SLuigi Rizzo * to the next unused slot. 339*17885a7bSLuigi Rizzo * On an Rx ring, hwlease is always after hwtail, 340*17885a7bSLuigi Rizzo * and completions cause hwtail to advance. 341*17885a7bSLuigi Rizzo * On a Tx ring, hwlease is always between cur and hwtail, 342ce3ee1e7SLuigi Rizzo * and completions cause cur to advance. 343ce3ee1e7SLuigi Rizzo * 344ce3ee1e7SLuigi Rizzo * nm_kr_space() returns the maximum number of slots that 345ce3ee1e7SLuigi Rizzo * can be assigned. 346ce3ee1e7SLuigi Rizzo * nm_kr_lease() reserves the required number of buffers, 347ce3ee1e7SLuigi Rizzo * advances nkr_hwlease and also returns an entry in 348ce3ee1e7SLuigi Rizzo * a circular array where completions should be reported. 349ce3ee1e7SLuigi Rizzo */ 350ce3ee1e7SLuigi Rizzo 351ce3ee1e7SLuigi Rizzo 352ce3ee1e7SLuigi Rizzo 353f9790aebSLuigi Rizzo enum txrx { NR_RX = 0, NR_TX = 1 }; 354ce3ee1e7SLuigi Rizzo 35568b8534bSLuigi Rizzo /* 356f9790aebSLuigi Rizzo * The "struct netmap_adapter" extends the "struct adapter" 357f9790aebSLuigi Rizzo * (or equivalent) device descriptor. 358f9790aebSLuigi Rizzo * It contains all base fields needed to support netmap operation. 359f9790aebSLuigi Rizzo * There are in fact different types of netmap adapters 360f9790aebSLuigi Rizzo * (native, generic, VALE switch...) so a netmap_adapter is 361f9790aebSLuigi Rizzo * just the first field in the derived type. 36268b8534bSLuigi Rizzo */ 36368b8534bSLuigi Rizzo struct netmap_adapter { 3648241616dSLuigi Rizzo /* 3658241616dSLuigi Rizzo * On linux we do not have a good way to tell if an interface 366f9790aebSLuigi Rizzo * is netmap-capable. So we always use the following trick: 3678241616dSLuigi Rizzo * NA(ifp) points here, and the first entry (which hopefully 3688241616dSLuigi Rizzo * always exists and is at least 32 bits) contains a magic 3698241616dSLuigi Rizzo * value which we can use to detect that the interface is good. 3708241616dSLuigi Rizzo */ 3718241616dSLuigi Rizzo uint32_t magic; 372f9790aebSLuigi Rizzo uint32_t na_flags; /* enabled, and other flags */ 3738241616dSLuigi Rizzo #define NAF_SKIP_INTR 1 /* use the regular interrupt handler. 3748241616dSLuigi Rizzo * useful during initialization 3758241616dSLuigi Rizzo */ 376f18be576SLuigi Rizzo #define NAF_SW_ONLY 2 /* forward packets only to sw adapter */ 377ce3ee1e7SLuigi Rizzo #define NAF_BDG_MAYSLEEP 4 /* the bridge is allowed to sleep when 378ce3ee1e7SLuigi Rizzo * forwarding packets coming from this 379ce3ee1e7SLuigi Rizzo * interface 380ce3ee1e7SLuigi Rizzo */ 381ce3ee1e7SLuigi Rizzo #define NAF_MEM_OWNER 8 /* the adapter is responsible for the 382ce3ee1e7SLuigi Rizzo * deallocation of the memory allocator 383ce3ee1e7SLuigi Rizzo */ 384f9790aebSLuigi Rizzo #define NAF_NATIVE_ON 16 /* the adapter is native and the attached 385f9790aebSLuigi Rizzo * interface is in netmap mode 386f9790aebSLuigi Rizzo */ 387f9790aebSLuigi Rizzo #define NAF_NETMAP_ON 32 /* netmap is active (either native or 388f9790aebSLuigi Rizzo * emulated. Where possible (e.g. FreeBSD) 389f9790aebSLuigi Rizzo * IFCAP_NETMAP also mirrors this flag. 390f9790aebSLuigi Rizzo */ 391f9790aebSLuigi Rizzo int active_fds; /* number of user-space descriptors using this 39268b8534bSLuigi Rizzo interface, which is equal to the number of 39368b8534bSLuigi Rizzo struct netmap_if objs in the mapped region. */ 39468b8534bSLuigi Rizzo 39524e57ec9SEd Maste u_int num_rx_rings; /* number of adapter receive rings */ 39624e57ec9SEd Maste u_int num_tx_rings; /* number of adapter transmit rings */ 39768b8534bSLuigi Rizzo 39868b8534bSLuigi Rizzo u_int num_tx_desc; /* number of descriptor in each queue */ 39968b8534bSLuigi Rizzo u_int num_rx_desc; 40068b8534bSLuigi Rizzo 40168b8534bSLuigi Rizzo /* tx_rings and rx_rings are private but allocated 40268b8534bSLuigi Rizzo * as a contiguous chunk of memory. Each array has 40368b8534bSLuigi Rizzo * N+1 entries, for the adapter queues and for the host queue. 40468b8534bSLuigi Rizzo */ 40568b8534bSLuigi Rizzo struct netmap_kring *tx_rings; /* array of TX rings. */ 40668b8534bSLuigi Rizzo struct netmap_kring *rx_rings; /* array of RX rings. */ 407*17885a7bSLuigi Rizzo 408f9790aebSLuigi Rizzo void *tailroom; /* space below the rings array */ 409f9790aebSLuigi Rizzo /* (used for leases) */ 410f9790aebSLuigi Rizzo 41168b8534bSLuigi Rizzo 41264ae02c3SLuigi Rizzo NM_SELINFO_T tx_si, rx_si; /* global wait queues */ 41364ae02c3SLuigi Rizzo 41468b8534bSLuigi Rizzo /* copy of if_qflush and if_transmit pointers, to intercept 41568b8534bSLuigi Rizzo * packets from the network stack when netmap is active. 41668b8534bSLuigi Rizzo */ 41768b8534bSLuigi Rizzo int (*if_transmit)(struct ifnet *, struct mbuf *); 41868b8534bSLuigi Rizzo 419*17885a7bSLuigi Rizzo /* copy of if_input for netmap_send_up() */ 420*17885a7bSLuigi Rizzo void (*if_input)(struct ifnet *, struct mbuf *); 421*17885a7bSLuigi Rizzo 42268b8534bSLuigi Rizzo /* references to the ifnet and device routines, used by 42368b8534bSLuigi Rizzo * the generic netmap functions. 42468b8534bSLuigi Rizzo */ 42568b8534bSLuigi Rizzo struct ifnet *ifp; /* adapter is ifp->if_softc */ 42668b8534bSLuigi Rizzo 427*17885a7bSLuigi Rizzo /*---- callbacks for this netmap adapter -----*/ 428*17885a7bSLuigi Rizzo /* 429*17885a7bSLuigi Rizzo * nm_dtor() is the cleanup routine called when destroying 430*17885a7bSLuigi Rizzo * the adapter. 431*17885a7bSLuigi Rizzo * 432*17885a7bSLuigi Rizzo * nm_register() is called on NIOCREGIF and close() to enter 433*17885a7bSLuigi Rizzo * or exit netmap mode on the NIC 434*17885a7bSLuigi Rizzo * 435*17885a7bSLuigi Rizzo * nm_txsync() pushes packets to the underlying hw/switch 436*17885a7bSLuigi Rizzo * 437*17885a7bSLuigi Rizzo * nm_rxsync() collects packets from the underlying hw/switch 438*17885a7bSLuigi Rizzo * 439*17885a7bSLuigi Rizzo * nm_config() returns configuration information from the OS 440*17885a7bSLuigi Rizzo * 441*17885a7bSLuigi Rizzo * nm_krings_create() XXX 442*17885a7bSLuigi Rizzo * 443*17885a7bSLuigi Rizzo * nm_krings_delete() XXX 444*17885a7bSLuigi Rizzo * 445*17885a7bSLuigi Rizzo * nm_notify() is used to act after data have become available. 446*17885a7bSLuigi Rizzo * For hw devices this is typically a selwakeup(), 447*17885a7bSLuigi Rizzo * but for NIC/host ports attached to a switch (or vice-versa) 448*17885a7bSLuigi Rizzo * we also need to invoke the 'txsync' code downstream. 449*17885a7bSLuigi Rizzo */ 450*17885a7bSLuigi Rizzo 451f9790aebSLuigi Rizzo /* private cleanup */ 452f9790aebSLuigi Rizzo void (*nm_dtor)(struct netmap_adapter *); 4531a26580eSLuigi Rizzo 454f9790aebSLuigi Rizzo int (*nm_register)(struct netmap_adapter *, int onoff); 455ce3ee1e7SLuigi Rizzo 456f9790aebSLuigi Rizzo int (*nm_txsync)(struct netmap_adapter *, u_int ring, int flags); 457f9790aebSLuigi Rizzo int (*nm_rxsync)(struct netmap_adapter *, u_int ring, int flags); 458ce3ee1e7SLuigi Rizzo #define NAF_FORCE_READ 1 459ce3ee1e7SLuigi Rizzo #define NAF_FORCE_RECLAIM 2 460ae10d1afSLuigi Rizzo /* return configuration information */ 461f9790aebSLuigi Rizzo int (*nm_config)(struct netmap_adapter *, 462f9790aebSLuigi Rizzo u_int *txr, u_int *txd, u_int *rxr, u_int *rxd); 463f9790aebSLuigi Rizzo int (*nm_krings_create)(struct netmap_adapter *); 464f9790aebSLuigi Rizzo void (*nm_krings_delete)(struct netmap_adapter *); 465f9790aebSLuigi Rizzo int (*nm_notify)(struct netmap_adapter *, 466f9790aebSLuigi Rizzo u_int ring, enum txrx, int flags); 467f9790aebSLuigi Rizzo #define NAF_GLOBAL_NOTIFY 4 468f9790aebSLuigi Rizzo #define NAF_DISABLE_NOTIFY 8 469f9790aebSLuigi Rizzo 470f9790aebSLuigi Rizzo /* standard refcount to control the lifetime of the adapter 471f9790aebSLuigi Rizzo * (it should be equal to the lifetime of the corresponding ifp) 472f9790aebSLuigi Rizzo */ 473f9790aebSLuigi Rizzo int na_refcount; 474f9790aebSLuigi Rizzo 475f9790aebSLuigi Rizzo /* memory allocator (opaque) 476f9790aebSLuigi Rizzo * We also cache a pointer to the lut_entry for translating 477f9790aebSLuigi Rizzo * buffer addresses, and the total number of buffers. 478f9790aebSLuigi Rizzo */ 479f9790aebSLuigi Rizzo struct netmap_mem_d *nm_mem; 480f9790aebSLuigi Rizzo struct lut_entry *na_lut; 481f9790aebSLuigi Rizzo uint32_t na_lut_objtotal; /* max buffer index */ 482f9790aebSLuigi Rizzo 483f9790aebSLuigi Rizzo /* used internally. If non-null, the interface cannot be bound 484f9790aebSLuigi Rizzo * from userspace 485f9790aebSLuigi Rizzo */ 486f9790aebSLuigi Rizzo void *na_private; 487f9790aebSLuigi Rizzo }; 488f9790aebSLuigi Rizzo 489*17885a7bSLuigi Rizzo 490f9790aebSLuigi Rizzo /* 491f9790aebSLuigi Rizzo * If the NIC is owned by the kernel 492f9790aebSLuigi Rizzo * (i.e., bridge), neither another bridge nor user can use it; 493f9790aebSLuigi Rizzo * if the NIC is owned by a user, only users can share it. 494f9790aebSLuigi Rizzo * Evaluation must be done under NMG_LOCK(). 495f9790aebSLuigi Rizzo */ 496f9790aebSLuigi Rizzo #define NETMAP_OWNED_BY_KERN(na) (na->na_private) 497f9790aebSLuigi Rizzo #define NETMAP_OWNED_BY_ANY(na) \ 498f9790aebSLuigi Rizzo (NETMAP_OWNED_BY_KERN(na) || (na->active_fds > 0)) 499f9790aebSLuigi Rizzo 500f9790aebSLuigi Rizzo 501f9790aebSLuigi Rizzo /* 502f9790aebSLuigi Rizzo * derived netmap adapters for various types of ports 503f9790aebSLuigi Rizzo */ 504f9790aebSLuigi Rizzo struct netmap_vp_adapter { /* VALE software port */ 505f9790aebSLuigi Rizzo struct netmap_adapter up; 506f196ce38SLuigi Rizzo 507849bec0eSLuigi Rizzo /* 508849bec0eSLuigi Rizzo * Bridge support: 509849bec0eSLuigi Rizzo * 510849bec0eSLuigi Rizzo * bdg_port is the port number used in the bridge; 511f18be576SLuigi Rizzo * na_bdg points to the bridge this NA is attached to. 512849bec0eSLuigi Rizzo */ 513f196ce38SLuigi Rizzo int bdg_port; 514f18be576SLuigi Rizzo struct nm_bridge *na_bdg; 515f9790aebSLuigi Rizzo int retry; 516f9790aebSLuigi Rizzo 517f9790aebSLuigi Rizzo u_int offset; /* Offset of ethernet header for each packet. */ 518f9790aebSLuigi Rizzo }; 519f9790aebSLuigi Rizzo 520*17885a7bSLuigi Rizzo 521f9790aebSLuigi Rizzo struct netmap_hw_adapter { /* physical device */ 522f9790aebSLuigi Rizzo struct netmap_adapter up; 523f9790aebSLuigi Rizzo 524f9790aebSLuigi Rizzo struct net_device_ops nm_ndo; // XXX linux only 525f9790aebSLuigi Rizzo }; 526f9790aebSLuigi Rizzo 527*17885a7bSLuigi Rizzo 528*17885a7bSLuigi Rizzo struct netmap_generic_adapter { /* emulated device */ 529f9790aebSLuigi Rizzo struct netmap_hw_adapter up; 530f9790aebSLuigi Rizzo 531f9790aebSLuigi Rizzo /* Pointer to a previously used netmap adapter. */ 532f9790aebSLuigi Rizzo struct netmap_adapter *prev; 533f9790aebSLuigi Rizzo 534f9790aebSLuigi Rizzo /* generic netmap adapters support: 535f9790aebSLuigi Rizzo * a net_device_ops struct overrides ndo_select_queue(), 536f9790aebSLuigi Rizzo * save_if_input saves the if_input hook (FreeBSD), 537f9790aebSLuigi Rizzo * mit_timer and mit_pending implement rx interrupt mitigation, 538f9790aebSLuigi Rizzo */ 539f9790aebSLuigi Rizzo struct net_device_ops generic_ndo; 540f9790aebSLuigi Rizzo void (*save_if_input)(struct ifnet *, struct mbuf *); 541f9790aebSLuigi Rizzo 542f9790aebSLuigi Rizzo struct hrtimer mit_timer; 543f9790aebSLuigi Rizzo int mit_pending; 544*17885a7bSLuigi Rizzo #ifdef linux 545*17885a7bSLuigi Rizzo netdev_tx_t (*save_start_xmit)(struct mbuf *, struct ifnet *); 546*17885a7bSLuigi Rizzo #endif 547f9790aebSLuigi Rizzo }; 548f9790aebSLuigi Rizzo 549f9790aebSLuigi Rizzo #ifdef WITH_VALE 550f9790aebSLuigi Rizzo 551*17885a7bSLuigi Rizzo /* 552*17885a7bSLuigi Rizzo * Bridge wrapper for non VALE ports attached to a VALE switch. 553f9790aebSLuigi Rizzo * 554*17885a7bSLuigi Rizzo * The real device must already have its own netmap adapter (hwna). 555*17885a7bSLuigi Rizzo * The bridge wrapper and the hwna adapter share the same set of 556*17885a7bSLuigi Rizzo * netmap rings and buffers, but they have two separate sets of 557*17885a7bSLuigi Rizzo * krings descriptors, with tx/rx meanings swapped: 558f9790aebSLuigi Rizzo * 559f9790aebSLuigi Rizzo * netmap 560f9790aebSLuigi Rizzo * bwrap krings rings krings hwna 561f9790aebSLuigi Rizzo * +------+ +------+ +-----+ +------+ +------+ 562f9790aebSLuigi Rizzo * |tx_rings->| |\ /| |----| |<-tx_rings| 563f9790aebSLuigi Rizzo * | | +------+ \ / +-----+ +------+ | | 564f9790aebSLuigi Rizzo * | | X | | 565f9790aebSLuigi Rizzo * | | / \ | | 566f9790aebSLuigi Rizzo * | | +------+/ \+-----+ +------+ | | 567f9790aebSLuigi Rizzo * |rx_rings->| | | |----| |<-rx_rings| 568f9790aebSLuigi Rizzo * | | +------+ +-----+ +------+ | | 569f9790aebSLuigi Rizzo * +------+ +------+ 570f9790aebSLuigi Rizzo * 571*17885a7bSLuigi Rizzo * - packets coming from the bridge go to the brwap rx rings, 572*17885a7bSLuigi Rizzo * which are also the hwna tx rings. The bwrap notify callback 573*17885a7bSLuigi Rizzo * will then complete the hwna tx (see netmap_bwrap_notify). 574f9790aebSLuigi Rizzo * 575*17885a7bSLuigi Rizzo * - packets coming from the outside go to the hwna rx rings, 576*17885a7bSLuigi Rizzo * which are also the bwrap tx rings. The (overwritten) hwna 577*17885a7bSLuigi Rizzo * notify method will then complete the bridge tx 578*17885a7bSLuigi Rizzo * (see netmap_bwrap_intr_notify). 579f9790aebSLuigi Rizzo * 580*17885a7bSLuigi Rizzo * The bridge wrapper may optionally connect the hwna 'host' rings 581*17885a7bSLuigi Rizzo * to the bridge. This is done by using a second port in the 582*17885a7bSLuigi Rizzo * bridge and connecting it to the 'host' netmap_vp_adapter 583*17885a7bSLuigi Rizzo * contained in the netmap_bwrap_adapter. The brwap host adapter 584*17885a7bSLuigi Rizzo * cross-links the hwna host rings in the same way as shown above. 585*17885a7bSLuigi Rizzo * 586*17885a7bSLuigi Rizzo * - packets coming from the bridge and directed to the host stack 587*17885a7bSLuigi Rizzo * are handled by the bwrap host notify callback 588*17885a7bSLuigi Rizzo * (see netmap_bwrap_host_notify) 589*17885a7bSLuigi Rizzo * 590*17885a7bSLuigi Rizzo * - packets coming from the host stack are still handled by the 591*17885a7bSLuigi Rizzo * overwritten hwna notify callback (netmap_bwrap_intr_notify), 592*17885a7bSLuigi Rizzo * but are diverted to the host adapter depending on the ring number. 593f9790aebSLuigi Rizzo * 594f9790aebSLuigi Rizzo */ 595f9790aebSLuigi Rizzo struct netmap_bwrap_adapter { 596f9790aebSLuigi Rizzo struct netmap_vp_adapter up; 597f9790aebSLuigi Rizzo struct netmap_vp_adapter host; /* for host rings */ 598f9790aebSLuigi Rizzo struct netmap_adapter *hwna; /* the underlying device */ 599f9790aebSLuigi Rizzo 600f9790aebSLuigi Rizzo /* backup of the hwna notify callback */ 601f9790aebSLuigi Rizzo int (*save_notify)(struct netmap_adapter *, 602f9790aebSLuigi Rizzo u_int ring, enum txrx, int flags); 603*17885a7bSLuigi Rizzo 604*17885a7bSLuigi Rizzo /* 605*17885a7bSLuigi Rizzo * When we attach a physical interface to the bridge, we 606f18be576SLuigi Rizzo * allow the controlling process to terminate, so we need 607f18be576SLuigi Rizzo * a place to store the netmap_priv_d data structure. 608*17885a7bSLuigi Rizzo * This is only done when physical interfaces 609*17885a7bSLuigi Rizzo * are attached to a bridge. 610f18be576SLuigi Rizzo */ 611f18be576SLuigi Rizzo struct netmap_priv_d *na_kpriv; 61268b8534bSLuigi Rizzo }; 61368b8534bSLuigi Rizzo 614f9790aebSLuigi Rizzo 615*17885a7bSLuigi Rizzo #endif /* WITH_VALE */ 616ce3ee1e7SLuigi Rizzo 617*17885a7bSLuigi Rizzo 618*17885a7bSLuigi Rizzo /* return slots reserved to rx clients; used in drivers */ 619*17885a7bSLuigi Rizzo static inline uint32_t 620*17885a7bSLuigi Rizzo nm_kr_rxspace(struct netmap_kring *k) 621*17885a7bSLuigi Rizzo { 622*17885a7bSLuigi Rizzo int space = k->nr_hwtail - k->nr_hwcur; 623ce3ee1e7SLuigi Rizzo if (space < 0) 624ce3ee1e7SLuigi Rizzo space += k->nkr_num_slots; 625*17885a7bSLuigi Rizzo ND("preserving %d rx slots %d -> %d", space, k->nr_hwcur, k->nr_hwtail); 626*17885a7bSLuigi Rizzo 627ce3ee1e7SLuigi Rizzo return space; 628ce3ee1e7SLuigi Rizzo } 629ce3ee1e7SLuigi Rizzo 630ce3ee1e7SLuigi Rizzo 631*17885a7bSLuigi Rizzo /* True if no space in the tx ring. only valid after txsync_prologue */ 632*17885a7bSLuigi Rizzo static inline int 633*17885a7bSLuigi Rizzo nm_kr_txempty(struct netmap_kring *kring) 634ce3ee1e7SLuigi Rizzo { 635*17885a7bSLuigi Rizzo return kring->rcur == kring->nr_hwtail; 636f9790aebSLuigi Rizzo } 637f9790aebSLuigi Rizzo 638ce3ee1e7SLuigi Rizzo 639ce3ee1e7SLuigi Rizzo /* 640f9790aebSLuigi Rizzo * protect against multiple threads using the same ring. 641f9790aebSLuigi Rizzo * also check that the ring has not been stopped. 642f9790aebSLuigi Rizzo * We only care for 0 or !=0 as a return code. 64368b8534bSLuigi Rizzo */ 644f9790aebSLuigi Rizzo #define NM_KR_BUSY 1 645f9790aebSLuigi Rizzo #define NM_KR_STOPPED 2 64668b8534bSLuigi Rizzo 647*17885a7bSLuigi Rizzo 648f9790aebSLuigi Rizzo static __inline void nm_kr_put(struct netmap_kring *kr) 649f9790aebSLuigi Rizzo { 650f9790aebSLuigi Rizzo NM_ATOMIC_CLEAR(&kr->nr_busy); 651f9790aebSLuigi Rizzo } 652f9790aebSLuigi Rizzo 653*17885a7bSLuigi Rizzo 654f9790aebSLuigi Rizzo static __inline int nm_kr_tryget(struct netmap_kring *kr) 655f9790aebSLuigi Rizzo { 656f9790aebSLuigi Rizzo /* check a first time without taking the lock 657f9790aebSLuigi Rizzo * to avoid starvation for nm_kr_get() 658f9790aebSLuigi Rizzo */ 659f9790aebSLuigi Rizzo if (unlikely(kr->nkr_stopped)) { 660f9790aebSLuigi Rizzo ND("ring %p stopped (%d)", kr, kr->nkr_stopped); 661f9790aebSLuigi Rizzo return NM_KR_STOPPED; 662f9790aebSLuigi Rizzo } 663f9790aebSLuigi Rizzo if (unlikely(NM_ATOMIC_TEST_AND_SET(&kr->nr_busy))) 664f9790aebSLuigi Rizzo return NM_KR_BUSY; 665f9790aebSLuigi Rizzo /* check a second time with lock held */ 666f9790aebSLuigi Rizzo if (unlikely(kr->nkr_stopped)) { 667f9790aebSLuigi Rizzo ND("ring %p stopped (%d)", kr, kr->nkr_stopped); 668f9790aebSLuigi Rizzo nm_kr_put(kr); 669f9790aebSLuigi Rizzo return NM_KR_STOPPED; 670f9790aebSLuigi Rizzo } 671f9790aebSLuigi Rizzo return 0; 672f9790aebSLuigi Rizzo } 67368b8534bSLuigi Rizzo 674849bec0eSLuigi Rizzo 67568b8534bSLuigi Rizzo /* 676*17885a7bSLuigi Rizzo * The following functions are used by individual drivers to 67768b8534bSLuigi Rizzo * support netmap operation. 67868b8534bSLuigi Rizzo * 67968b8534bSLuigi Rizzo * netmap_attach() initializes a struct netmap_adapter, allocating the 68068b8534bSLuigi Rizzo * struct netmap_ring's and the struct selinfo. 68168b8534bSLuigi Rizzo * 68268b8534bSLuigi Rizzo * netmap_detach() frees the memory allocated by netmap_attach(). 68368b8534bSLuigi Rizzo * 684ce3ee1e7SLuigi Rizzo * netmap_transmit() replaces the if_transmit routine of the interface, 68568b8534bSLuigi Rizzo * and is used to intercept packets coming from the stack. 68668b8534bSLuigi Rizzo * 68768b8534bSLuigi Rizzo * netmap_load_map/netmap_reload_map are helper routines to set/reset 68868b8534bSLuigi Rizzo * the dmamap for a packet buffer 68968b8534bSLuigi Rizzo * 69068b8534bSLuigi Rizzo * netmap_reset() is a helper routine to be called in the driver 69168b8534bSLuigi Rizzo * when reinitializing a ring. 69268b8534bSLuigi Rizzo */ 693f9790aebSLuigi Rizzo int netmap_attach(struct netmap_adapter *); 694f9790aebSLuigi Rizzo int netmap_attach_common(struct netmap_adapter *); 695f9790aebSLuigi Rizzo void netmap_detach_common(struct netmap_adapter *na); 69668b8534bSLuigi Rizzo void netmap_detach(struct ifnet *); 697ce3ee1e7SLuigi Rizzo int netmap_transmit(struct ifnet *, struct mbuf *); 69868b8534bSLuigi Rizzo struct netmap_slot *netmap_reset(struct netmap_adapter *na, 699ce3ee1e7SLuigi Rizzo enum txrx tx, u_int n, u_int new_cur); 70068b8534bSLuigi Rizzo int netmap_ring_reinit(struct netmap_kring *); 70168b8534bSLuigi Rizzo 702*17885a7bSLuigi Rizzo /* default functions to handle rx/tx interrupts */ 703*17885a7bSLuigi Rizzo int netmap_rx_irq(struct ifnet *, u_int, u_int *); 704*17885a7bSLuigi Rizzo #define netmap_tx_irq(_n, _q) netmap_rx_irq(_n, _q, NULL) 705*17885a7bSLuigi Rizzo void netmap_common_irq(struct ifnet *, u_int, u_int *work_done); 706*17885a7bSLuigi Rizzo 707*17885a7bSLuigi Rizzo void netmap_disable_all_rings(struct ifnet *); 708*17885a7bSLuigi Rizzo void netmap_enable_all_rings(struct ifnet *); 709*17885a7bSLuigi Rizzo void netmap_disable_ring(struct netmap_kring *kr); 710*17885a7bSLuigi Rizzo 711*17885a7bSLuigi Rizzo 712*17885a7bSLuigi Rizzo /* set/clear native flags and if_transmit/netdev_ops */ 713f9790aebSLuigi Rizzo static inline void 714f9790aebSLuigi Rizzo nm_set_native_flags(struct netmap_adapter *na) 715f9790aebSLuigi Rizzo { 716f9790aebSLuigi Rizzo struct ifnet *ifp = na->ifp; 717ce3ee1e7SLuigi Rizzo 718f9790aebSLuigi Rizzo na->na_flags |= (NAF_NATIVE_ON | NAF_NETMAP_ON); 719f9790aebSLuigi Rizzo #ifdef IFCAP_NETMAP /* or FreeBSD ? */ 720f9790aebSLuigi Rizzo ifp->if_capenable |= IFCAP_NETMAP; 721f9790aebSLuigi Rizzo #endif 722f9790aebSLuigi Rizzo #ifdef __FreeBSD__ 723f9790aebSLuigi Rizzo na->if_transmit = ifp->if_transmit; 724f9790aebSLuigi Rizzo ifp->if_transmit = netmap_transmit; 725f9790aebSLuigi Rizzo #else 726f9790aebSLuigi Rizzo na->if_transmit = (void *)ifp->netdev_ops; 727f9790aebSLuigi Rizzo ifp->netdev_ops = &((struct netmap_hw_adapter *)na)->nm_ndo; 728f9790aebSLuigi Rizzo #endif 729f9790aebSLuigi Rizzo } 730f9790aebSLuigi Rizzo 731*17885a7bSLuigi Rizzo 732f9790aebSLuigi Rizzo static inline void 733f9790aebSLuigi Rizzo nm_clear_native_flags(struct netmap_adapter *na) 734f9790aebSLuigi Rizzo { 735f9790aebSLuigi Rizzo struct ifnet *ifp = na->ifp; 736f9790aebSLuigi Rizzo 737f9790aebSLuigi Rizzo #ifdef __FreeBSD__ 738f9790aebSLuigi Rizzo ifp->if_transmit = na->if_transmit; 739f9790aebSLuigi Rizzo #else 740f9790aebSLuigi Rizzo ifp->netdev_ops = (void *)na->if_transmit; 741f9790aebSLuigi Rizzo #endif 742f9790aebSLuigi Rizzo na->na_flags &= ~(NAF_NATIVE_ON | NAF_NETMAP_ON); 743f9790aebSLuigi Rizzo #ifdef IFCAP_NETMAP /* or FreeBSD ? */ 744f9790aebSLuigi Rizzo ifp->if_capenable &= ~IFCAP_NETMAP; 745f9790aebSLuigi Rizzo #endif 746f9790aebSLuigi Rizzo } 747f9790aebSLuigi Rizzo 748f9790aebSLuigi Rizzo 749f9790aebSLuigi Rizzo /* 750*17885a7bSLuigi Rizzo * validates parameters in the ring/kring, returns a value for head 751*17885a7bSLuigi Rizzo * If any error, returns ring_size to force a reinit. 752*17885a7bSLuigi Rizzo */ 753*17885a7bSLuigi Rizzo uint32_t nm_txsync_prologue(struct netmap_kring *); 754*17885a7bSLuigi Rizzo 755*17885a7bSLuigi Rizzo 756*17885a7bSLuigi Rizzo /* 757*17885a7bSLuigi Rizzo * validates parameters in the ring/kring, returns a value for head, 758f9790aebSLuigi Rizzo * and the 'reserved' value in the argument. 759*17885a7bSLuigi Rizzo * If any error, returns ring_size lim to force a reinit. 760f9790aebSLuigi Rizzo */ 761*17885a7bSLuigi Rizzo uint32_t nm_rxsync_prologue(struct netmap_kring *); 762*17885a7bSLuigi Rizzo 763f9790aebSLuigi Rizzo 764f9790aebSLuigi Rizzo /* 765*17885a7bSLuigi Rizzo * update kring and ring at the end of txsync. 766f9790aebSLuigi Rizzo */ 767f9790aebSLuigi Rizzo static inline void 768*17885a7bSLuigi Rizzo nm_txsync_finalize(struct netmap_kring *kring) 769f9790aebSLuigi Rizzo { 770*17885a7bSLuigi Rizzo /* update ring head/tail to what the kernel knows */ 771*17885a7bSLuigi Rizzo kring->ring->tail = kring->rtail = kring->nr_hwtail; 772*17885a7bSLuigi Rizzo kring->ring->head = kring->rhead = kring->nr_hwcur; 773f9790aebSLuigi Rizzo 774*17885a7bSLuigi Rizzo /* note, head/rhead/hwcur might be behind cur/rcur 775*17885a7bSLuigi Rizzo * if no carrier 776*17885a7bSLuigi Rizzo */ 777*17885a7bSLuigi Rizzo ND(5, "%s now hwcur %d hwtail %d head %d cur %d tail %d", 778*17885a7bSLuigi Rizzo kring->name, kring->nr_hwcur, kring->nr_hwtail, 779*17885a7bSLuigi Rizzo kring->rhead, kring->rcur, kring->rtail); 780f9790aebSLuigi Rizzo } 781f9790aebSLuigi Rizzo 782*17885a7bSLuigi Rizzo 783*17885a7bSLuigi Rizzo /* 784*17885a7bSLuigi Rizzo * update kring and ring at the end of rxsync 785*17885a7bSLuigi Rizzo */ 786*17885a7bSLuigi Rizzo static inline void 787*17885a7bSLuigi Rizzo nm_rxsync_finalize(struct netmap_kring *kring) 788*17885a7bSLuigi Rizzo { 789*17885a7bSLuigi Rizzo /* tell userspace that there might be new packets */ 790*17885a7bSLuigi Rizzo //struct netmap_ring *ring = kring->ring; 791*17885a7bSLuigi Rizzo ND("head %d cur %d tail %d -> %d", ring->head, ring->cur, ring->tail, 792*17885a7bSLuigi Rizzo kring->nr_hwtail); 793*17885a7bSLuigi Rizzo kring->ring->tail = kring->rtail = kring->nr_hwtail; 794*17885a7bSLuigi Rizzo /* make a copy of the state for next round */ 795*17885a7bSLuigi Rizzo kring->rhead = kring->ring->head; 796*17885a7bSLuigi Rizzo kring->rcur = kring->ring->cur; 797*17885a7bSLuigi Rizzo } 798*17885a7bSLuigi Rizzo 799*17885a7bSLuigi Rizzo 800f9790aebSLuigi Rizzo /* check/fix address and len in tx rings */ 801f9790aebSLuigi Rizzo #if 1 /* debug version */ 802f9790aebSLuigi Rizzo #define NM_CHECK_ADDR_LEN(_a, _l) do { \ 803f9790aebSLuigi Rizzo if (_a == netmap_buffer_base || _l > NETMAP_BUF_SIZE) { \ 804f9790aebSLuigi Rizzo RD(5, "bad addr/len ring %d slot %d idx %d len %d", \ 805f9790aebSLuigi Rizzo ring_nr, nm_i, slot->buf_idx, len); \ 806f9790aebSLuigi Rizzo if (_l > NETMAP_BUF_SIZE) \ 807f9790aebSLuigi Rizzo _l = NETMAP_BUF_SIZE; \ 808f9790aebSLuigi Rizzo } } while (0) 809f9790aebSLuigi Rizzo #else /* no debug version */ 810f9790aebSLuigi Rizzo #define NM_CHECK_ADDR_LEN(_a, _l) do { \ 811f9790aebSLuigi Rizzo if (_l > NETMAP_BUF_SIZE) \ 812f9790aebSLuigi Rizzo _l = NETMAP_BUF_SIZE; \ 813f9790aebSLuigi Rizzo } while (0) 814f9790aebSLuigi Rizzo #endif 815f9790aebSLuigi Rizzo 816f9790aebSLuigi Rizzo 817f9790aebSLuigi Rizzo /*---------------------------------------------------------------*/ 818f9790aebSLuigi Rizzo /* 819f9790aebSLuigi Rizzo * Support routines to be used with the VALE switch 820f9790aebSLuigi Rizzo */ 821f9790aebSLuigi Rizzo int netmap_update_config(struct netmap_adapter *na); 822f9790aebSLuigi Rizzo int netmap_krings_create(struct netmap_adapter *na, u_int ntx, u_int nrx, u_int tailroom); 823f9790aebSLuigi Rizzo void netmap_krings_delete(struct netmap_adapter *na); 824*17885a7bSLuigi Rizzo int netmap_rxsync_from_host(struct netmap_adapter *na, struct thread *td, void *pwait); 825*17885a7bSLuigi Rizzo 826f9790aebSLuigi Rizzo 827f9790aebSLuigi Rizzo struct netmap_if * 828f9790aebSLuigi Rizzo netmap_do_regif(struct netmap_priv_d *priv, struct netmap_adapter *na, 829f9790aebSLuigi Rizzo uint16_t ringid, int *err); 830f9790aebSLuigi Rizzo 831f9790aebSLuigi Rizzo 832f9790aebSLuigi Rizzo 833f9790aebSLuigi Rizzo u_int nm_bound_var(u_int *v, u_int dflt, u_int lo, u_int hi, const char *msg); 834f9790aebSLuigi Rizzo int netmap_get_na(struct nmreq *nmr, struct netmap_adapter **na, int create); 835f9790aebSLuigi Rizzo int netmap_get_hw_na(struct ifnet *ifp, struct netmap_adapter **na); 836f9790aebSLuigi Rizzo 837*17885a7bSLuigi Rizzo 838f9790aebSLuigi Rizzo #ifdef WITH_VALE 839f18be576SLuigi Rizzo /* 840*17885a7bSLuigi Rizzo * The following bridge-related functions are used by other 841*17885a7bSLuigi Rizzo * kernel modules. 842*17885a7bSLuigi Rizzo * 843*17885a7bSLuigi Rizzo * VALE only supports unicast or broadcast. The lookup 844f18be576SLuigi Rizzo * function can return 0 .. NM_BDG_MAXPORTS-1 for regular ports, 845f18be576SLuigi Rizzo * NM_BDG_MAXPORTS for broadcast, NM_BDG_MAXPORTS+1 for unknown. 846f18be576SLuigi Rizzo * XXX in practice "unknown" might be handled same as broadcast. 847f18be576SLuigi Rizzo */ 848f9790aebSLuigi Rizzo typedef u_int (*bdg_lookup_fn_t)(char *buf, u_int len, 849f9790aebSLuigi Rizzo uint8_t *ring_nr, struct netmap_vp_adapter *); 850f9790aebSLuigi Rizzo u_int netmap_bdg_learning(char *, u_int, uint8_t *, 851f9790aebSLuigi Rizzo struct netmap_vp_adapter *); 852f9790aebSLuigi Rizzo 853f9790aebSLuigi Rizzo #define NM_BDG_MAXPORTS 254 /* up to 254 */ 854f18be576SLuigi Rizzo #define NM_BDG_BROADCAST NM_BDG_MAXPORTS 855f18be576SLuigi Rizzo #define NM_BDG_NOPORT (NM_BDG_MAXPORTS+1) 856f18be576SLuigi Rizzo 857f9790aebSLuigi Rizzo #define NM_NAME "vale" /* prefix for bridge port name */ 858f9790aebSLuigi Rizzo 859f9790aebSLuigi Rizzo 860f9790aebSLuigi Rizzo /* these are redefined in case of no VALE support */ 861f9790aebSLuigi Rizzo int netmap_get_bdg_na(struct nmreq *nmr, struct netmap_adapter **na, int create); 862f9790aebSLuigi Rizzo void netmap_init_bridges(void); 863f9790aebSLuigi Rizzo int netmap_bdg_ctl(struct nmreq *nmr, bdg_lookup_fn_t func); 864f9790aebSLuigi Rizzo 865f9790aebSLuigi Rizzo #else /* !WITH_VALE */ 866f9790aebSLuigi Rizzo #define netmap_get_bdg_na(_1, _2, _3) 0 867f9790aebSLuigi Rizzo #define netmap_init_bridges(_1) 868f9790aebSLuigi Rizzo #define netmap_bdg_ctl(_1, _2) EINVAL 869f9790aebSLuigi Rizzo #endif /* !WITH_VALE */ 870f9790aebSLuigi Rizzo 871f9790aebSLuigi Rizzo /* Various prototypes */ 872f9790aebSLuigi Rizzo int netmap_poll(struct cdev *dev, int events, struct thread *td); 873f9790aebSLuigi Rizzo int netmap_init(void); 874f9790aebSLuigi Rizzo void netmap_fini(void); 875f9790aebSLuigi Rizzo int netmap_get_memory(struct netmap_priv_d* p); 876f9790aebSLuigi Rizzo void netmap_dtor(void *data); 877f9790aebSLuigi Rizzo int netmap_dtor_locked(struct netmap_priv_d *priv); 878f9790aebSLuigi Rizzo 879f9790aebSLuigi Rizzo int netmap_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, struct thread *td); 880f9790aebSLuigi Rizzo 881f9790aebSLuigi Rizzo /* netmap_adapter creation/destruction */ 882f9790aebSLuigi Rizzo #define NM_IFPNAME(ifp) ((ifp) ? (ifp)->if_xname : "zombie") 883*17885a7bSLuigi Rizzo 884*17885a7bSLuigi Rizzo // #define NM_DEBUG_PUTGET 1 885f9790aebSLuigi Rizzo 886f9790aebSLuigi Rizzo #ifdef NM_DEBUG_PUTGET 887f9790aebSLuigi Rizzo 888f9790aebSLuigi Rizzo #define NM_DBG(f) __##f 889f9790aebSLuigi Rizzo 890f9790aebSLuigi Rizzo void __netmap_adapter_get(struct netmap_adapter *na); 891f9790aebSLuigi Rizzo 892f9790aebSLuigi Rizzo #define netmap_adapter_get(na) \ 893f9790aebSLuigi Rizzo do { \ 894f9790aebSLuigi Rizzo struct netmap_adapter *__na = na; \ 895f9790aebSLuigi Rizzo D("getting %p:%s (%d)", __na, NM_IFPNAME(__na->ifp), __na->na_refcount); \ 896f9790aebSLuigi Rizzo __netmap_adapter_get(__na); \ 897f9790aebSLuigi Rizzo } while (0) 898f9790aebSLuigi Rizzo 899f9790aebSLuigi Rizzo int __netmap_adapter_put(struct netmap_adapter *na); 900f9790aebSLuigi Rizzo 901f9790aebSLuigi Rizzo #define netmap_adapter_put(na) \ 902f9790aebSLuigi Rizzo do { \ 903f9790aebSLuigi Rizzo struct netmap_adapter *__na = na; \ 904f9790aebSLuigi Rizzo D("putting %p:%s (%d)", __na, NM_IFPNAME(__na->ifp), __na->na_refcount); \ 905f9790aebSLuigi Rizzo __netmap_adapter_put(__na); \ 906f9790aebSLuigi Rizzo } while (0) 907f9790aebSLuigi Rizzo 908f9790aebSLuigi Rizzo #else /* !NM_DEBUG_PUTGET */ 909f9790aebSLuigi Rizzo 910f9790aebSLuigi Rizzo #define NM_DBG(f) f 911f9790aebSLuigi Rizzo void netmap_adapter_get(struct netmap_adapter *na); 912f9790aebSLuigi Rizzo int netmap_adapter_put(struct netmap_adapter *na); 913f9790aebSLuigi Rizzo 914f9790aebSLuigi Rizzo #endif /* !NM_DEBUG_PUTGET */ 915f9790aebSLuigi Rizzo 916f9790aebSLuigi Rizzo 917*17885a7bSLuigi Rizzo /* 918*17885a7bSLuigi Rizzo * module variables 919*17885a7bSLuigi Rizzo */ 920b3d53016SLuigi Rizzo extern u_int netmap_buf_size; 921849bec0eSLuigi Rizzo #define NETMAP_BUF_SIZE netmap_buf_size // XXX remove 922*17885a7bSLuigi Rizzo extern int netmap_mitigate; // XXX not really used 9235819da83SLuigi Rizzo extern int netmap_no_pendintr; 924*17885a7bSLuigi Rizzo extern u_int netmap_total_buffers; // global allocator 925*17885a7bSLuigi Rizzo extern char *netmap_buffer_base; // global allocator 92668b8534bSLuigi Rizzo extern int netmap_verbose; // XXX debugging 92768b8534bSLuigi Rizzo enum { /* verbose flags */ 92868b8534bSLuigi Rizzo NM_VERB_ON = 1, /* generic verbose */ 92968b8534bSLuigi Rizzo NM_VERB_HOST = 0x2, /* verbose host stack */ 93068b8534bSLuigi Rizzo NM_VERB_RXSYNC = 0x10, /* verbose on rxsync/txsync */ 93168b8534bSLuigi Rizzo NM_VERB_TXSYNC = 0x20, 93268b8534bSLuigi Rizzo NM_VERB_RXINTR = 0x100, /* verbose on rx/tx intr (driver) */ 93368b8534bSLuigi Rizzo NM_VERB_TXINTR = 0x200, 93468b8534bSLuigi Rizzo NM_VERB_NIC_RXSYNC = 0x1000, /* verbose on rx/tx intr (driver) */ 93568b8534bSLuigi Rizzo NM_VERB_NIC_TXSYNC = 0x2000, 93668b8534bSLuigi Rizzo }; 93768b8534bSLuigi Rizzo 938f9790aebSLuigi Rizzo extern int netmap_txsync_retry; 939f9790aebSLuigi Rizzo extern int netmap_generic_mit; 940f9790aebSLuigi Rizzo extern int netmap_generic_ringsize; 941f9790aebSLuigi Rizzo 94268b8534bSLuigi Rizzo /* 943d0c7b075SLuigi Rizzo * NA returns a pointer to the struct netmap adapter from the ifp, 944d0c7b075SLuigi Rizzo * WNA is used to write it. 94568b8534bSLuigi Rizzo */ 946d0c7b075SLuigi Rizzo #ifndef WNA 947d0c7b075SLuigi Rizzo #define WNA(_ifp) (_ifp)->if_pspare[0] 948d0c7b075SLuigi Rizzo #endif 949d0c7b075SLuigi Rizzo #define NA(_ifp) ((struct netmap_adapter *)WNA(_ifp)) 95068b8534bSLuigi Rizzo 9518241616dSLuigi Rizzo /* 9528241616dSLuigi Rizzo * Macros to determine if an interface is netmap capable or netmap enabled. 9538241616dSLuigi Rizzo * See the magic field in struct netmap_adapter. 9548241616dSLuigi Rizzo */ 9558241616dSLuigi Rizzo #ifdef __FreeBSD__ 9568241616dSLuigi Rizzo /* 9578241616dSLuigi Rizzo * on FreeBSD just use if_capabilities and if_capenable. 9588241616dSLuigi Rizzo */ 9598241616dSLuigi Rizzo #define NETMAP_CAPABLE(ifp) (NA(ifp) && \ 9608241616dSLuigi Rizzo (ifp)->if_capabilities & IFCAP_NETMAP ) 9618241616dSLuigi Rizzo 9628241616dSLuigi Rizzo #define NETMAP_SET_CAPABLE(ifp) \ 9638241616dSLuigi Rizzo (ifp)->if_capabilities |= IFCAP_NETMAP 9648241616dSLuigi Rizzo 9658241616dSLuigi Rizzo #else /* linux */ 9668241616dSLuigi Rizzo 9678241616dSLuigi Rizzo /* 9688241616dSLuigi Rizzo * on linux: 9698241616dSLuigi Rizzo * we check if NA(ifp) is set and its first element has a related 9708241616dSLuigi Rizzo * magic value. The capenable is within the struct netmap_adapter. 9718241616dSLuigi Rizzo */ 9728241616dSLuigi Rizzo #define NETMAP_MAGIC 0x52697a7a 9738241616dSLuigi Rizzo 9748241616dSLuigi Rizzo #define NETMAP_CAPABLE(ifp) (NA(ifp) && \ 9758241616dSLuigi Rizzo ((uint32_t)(uintptr_t)NA(ifp) ^ NA(ifp)->magic) == NETMAP_MAGIC ) 9768241616dSLuigi Rizzo 9778241616dSLuigi Rizzo #define NETMAP_SET_CAPABLE(ifp) \ 9788241616dSLuigi Rizzo NA(ifp)->magic = ((uint32_t)(uintptr_t)NA(ifp)) ^ NETMAP_MAGIC 9798241616dSLuigi Rizzo 9808241616dSLuigi Rizzo #endif /* linux */ 98168b8534bSLuigi Rizzo 982f196ce38SLuigi Rizzo #ifdef __FreeBSD__ 983f9790aebSLuigi Rizzo 984*17885a7bSLuigi Rizzo /* Callback invoked by the dma machinery after a successful dmamap_load */ 9856dba29a2SLuigi Rizzo static void netmap_dmamap_cb(__unused void *arg, 9866dba29a2SLuigi Rizzo __unused bus_dma_segment_t * segs, __unused int nseg, __unused int error) 9876dba29a2SLuigi Rizzo { 9886dba29a2SLuigi Rizzo } 9896dba29a2SLuigi Rizzo 9906dba29a2SLuigi Rizzo /* bus_dmamap_load wrapper: call aforementioned function if map != NULL. 9916dba29a2SLuigi Rizzo * XXX can we do it without a callback ? 9926dba29a2SLuigi Rizzo */ 9936dba29a2SLuigi Rizzo static inline void 9946dba29a2SLuigi Rizzo netmap_load_map(bus_dma_tag_t tag, bus_dmamap_t map, void *buf) 9956dba29a2SLuigi Rizzo { 9966dba29a2SLuigi Rizzo if (map) 9976dba29a2SLuigi Rizzo bus_dmamap_load(tag, map, buf, NETMAP_BUF_SIZE, 9986dba29a2SLuigi Rizzo netmap_dmamap_cb, NULL, BUS_DMA_NOWAIT); 9996dba29a2SLuigi Rizzo } 10006dba29a2SLuigi Rizzo 10016dba29a2SLuigi Rizzo /* update the map when a buffer changes. */ 10026dba29a2SLuigi Rizzo static inline void 10036dba29a2SLuigi Rizzo netmap_reload_map(bus_dma_tag_t tag, bus_dmamap_t map, void *buf) 10046dba29a2SLuigi Rizzo { 10056dba29a2SLuigi Rizzo if (map) { 10066dba29a2SLuigi Rizzo bus_dmamap_unload(tag, map); 10076dba29a2SLuigi Rizzo bus_dmamap_load(tag, map, buf, NETMAP_BUF_SIZE, 10086dba29a2SLuigi Rizzo netmap_dmamap_cb, NULL, BUS_DMA_NOWAIT); 10096dba29a2SLuigi Rizzo } 10106dba29a2SLuigi Rizzo } 1011f9790aebSLuigi Rizzo 1012f196ce38SLuigi Rizzo #else /* linux */ 1013f196ce38SLuigi Rizzo 1014f196ce38SLuigi Rizzo /* 1015f196ce38SLuigi Rizzo * XXX How do we redefine these functions: 1016f196ce38SLuigi Rizzo * 1017f196ce38SLuigi Rizzo * on linux we need 1018f196ce38SLuigi Rizzo * dma_map_single(&pdev->dev, virt_addr, len, direction) 1019f196ce38SLuigi Rizzo * dma_unmap_single(&adapter->pdev->dev, phys_addr, len, direction 1020f196ce38SLuigi Rizzo * The len can be implicit (on netmap it is NETMAP_BUF_SIZE) 1021f196ce38SLuigi Rizzo * unfortunately the direction is not, so we need to change 1022f196ce38SLuigi Rizzo * something to have a cross API 1023f196ce38SLuigi Rizzo */ 1024f196ce38SLuigi Rizzo #define netmap_load_map(_t, _m, _b) 1025f196ce38SLuigi Rizzo #define netmap_reload_map(_t, _m, _b) 1026f196ce38SLuigi Rizzo #if 0 1027f196ce38SLuigi Rizzo struct e1000_buffer *buffer_info = &tx_ring->buffer_info[l]; 1028f196ce38SLuigi Rizzo /* set time_stamp *before* dma to help avoid a possible race */ 1029f196ce38SLuigi Rizzo buffer_info->time_stamp = jiffies; 1030f196ce38SLuigi Rizzo buffer_info->mapped_as_page = false; 1031f196ce38SLuigi Rizzo buffer_info->length = len; 1032f196ce38SLuigi Rizzo //buffer_info->next_to_watch = l; 1033f196ce38SLuigi Rizzo /* reload dma map */ 1034f196ce38SLuigi Rizzo dma_unmap_single(&adapter->pdev->dev, buffer_info->dma, 1035f196ce38SLuigi Rizzo NETMAP_BUF_SIZE, DMA_TO_DEVICE); 1036f196ce38SLuigi Rizzo buffer_info->dma = dma_map_single(&adapter->pdev->dev, 1037f196ce38SLuigi Rizzo addr, NETMAP_BUF_SIZE, DMA_TO_DEVICE); 1038f196ce38SLuigi Rizzo 1039f196ce38SLuigi Rizzo if (dma_mapping_error(&adapter->pdev->dev, buffer_info->dma)) { 1040f196ce38SLuigi Rizzo D("dma mapping error"); 1041f196ce38SLuigi Rizzo /* goto dma_error; See e1000_put_txbuf() */ 1042f196ce38SLuigi Rizzo /* XXX reset */ 1043f196ce38SLuigi Rizzo } 1044f196ce38SLuigi Rizzo tx_desc->buffer_addr = htole64(buffer_info->dma); //XXX 1045f196ce38SLuigi Rizzo 1046f196ce38SLuigi Rizzo #endif 1047f196ce38SLuigi Rizzo 1048f196ce38SLuigi Rizzo /* 1049f196ce38SLuigi Rizzo * The bus_dmamap_sync() can be one of wmb() or rmb() depending on direction. 1050f196ce38SLuigi Rizzo */ 1051f196ce38SLuigi Rizzo #define bus_dmamap_sync(_a, _b, _c) 1052f196ce38SLuigi Rizzo 1053f196ce38SLuigi Rizzo #endif /* linux */ 10546dba29a2SLuigi Rizzo 1055ce3ee1e7SLuigi Rizzo 10565644ccecSLuigi Rizzo /* 10575644ccecSLuigi Rizzo * functions to map NIC to KRING indexes (n2k) and vice versa (k2n) 10585644ccecSLuigi Rizzo */ 10595644ccecSLuigi Rizzo static inline int 106064ae02c3SLuigi Rizzo netmap_idx_n2k(struct netmap_kring *kr, int idx) 10615644ccecSLuigi Rizzo { 106264ae02c3SLuigi Rizzo int n = kr->nkr_num_slots; 106364ae02c3SLuigi Rizzo idx += kr->nkr_hwofs; 106464ae02c3SLuigi Rizzo if (idx < 0) 106564ae02c3SLuigi Rizzo return idx + n; 106664ae02c3SLuigi Rizzo else if (idx < n) 106764ae02c3SLuigi Rizzo return idx; 10685644ccecSLuigi Rizzo else 106964ae02c3SLuigi Rizzo return idx - n; 10705644ccecSLuigi Rizzo } 10715644ccecSLuigi Rizzo 10725644ccecSLuigi Rizzo 10735644ccecSLuigi Rizzo static inline int 107464ae02c3SLuigi Rizzo netmap_idx_k2n(struct netmap_kring *kr, int idx) 10755644ccecSLuigi Rizzo { 107664ae02c3SLuigi Rizzo int n = kr->nkr_num_slots; 107764ae02c3SLuigi Rizzo idx -= kr->nkr_hwofs; 107864ae02c3SLuigi Rizzo if (idx < 0) 107964ae02c3SLuigi Rizzo return idx + n; 108064ae02c3SLuigi Rizzo else if (idx < n) 108164ae02c3SLuigi Rizzo return idx; 10825644ccecSLuigi Rizzo else 108364ae02c3SLuigi Rizzo return idx - n; 10845644ccecSLuigi Rizzo } 10855644ccecSLuigi Rizzo 10865644ccecSLuigi Rizzo 1087d76bf4ffSLuigi Rizzo /* Entries of the look-up table. */ 1088d76bf4ffSLuigi Rizzo struct lut_entry { 1089d76bf4ffSLuigi Rizzo void *vaddr; /* virtual address. */ 1090849bec0eSLuigi Rizzo vm_paddr_t paddr; /* physical address. */ 1091d76bf4ffSLuigi Rizzo }; 1092d76bf4ffSLuigi Rizzo 1093d76bf4ffSLuigi Rizzo struct netmap_obj_pool; 1094d76bf4ffSLuigi Rizzo extern struct lut_entry *netmap_buffer_lut; 1095d76bf4ffSLuigi Rizzo #define NMB_VA(i) (netmap_buffer_lut[i].vaddr) 1096d76bf4ffSLuigi Rizzo #define NMB_PA(i) (netmap_buffer_lut[i].paddr) 1097d76bf4ffSLuigi Rizzo 109868b8534bSLuigi Rizzo /* 10996e10c8b8SLuigi Rizzo * NMB return the virtual address of a buffer (buffer 0 on bad index) 11006e10c8b8SLuigi Rizzo * PNMB also fills the physical address 110168b8534bSLuigi Rizzo */ 11026e10c8b8SLuigi Rizzo static inline void * 110368b8534bSLuigi Rizzo NMB(struct netmap_slot *slot) 110468b8534bSLuigi Rizzo { 110568b8534bSLuigi Rizzo uint32_t i = slot->buf_idx; 1106f196ce38SLuigi Rizzo return (unlikely(i >= netmap_total_buffers)) ? NMB_VA(0) : NMB_VA(i); 110768b8534bSLuigi Rizzo } 110868b8534bSLuigi Rizzo 11096e10c8b8SLuigi Rizzo static inline void * 11106e10c8b8SLuigi Rizzo PNMB(struct netmap_slot *slot, uint64_t *pp) 11116e10c8b8SLuigi Rizzo { 11126e10c8b8SLuigi Rizzo uint32_t i = slot->buf_idx; 1113d76bf4ffSLuigi Rizzo void *ret = (i >= netmap_total_buffers) ? NMB_VA(0) : NMB_VA(i); 11142579e2d7SLuigi Rizzo 1115d76bf4ffSLuigi Rizzo *pp = (i >= netmap_total_buffers) ? NMB_PA(0) : NMB_PA(i); 11166e10c8b8SLuigi Rizzo return ret; 11176e10c8b8SLuigi Rizzo } 11186e10c8b8SLuigi Rizzo 1119f9790aebSLuigi Rizzo /* Generic version of NMB, which uses device-specific memory. */ 1120f9790aebSLuigi Rizzo static inline void * 1121f9790aebSLuigi Rizzo BDG_NMB(struct netmap_adapter *na, struct netmap_slot *slot) 1122f9790aebSLuigi Rizzo { 1123f9790aebSLuigi Rizzo struct lut_entry *lut = na->na_lut; 1124f9790aebSLuigi Rizzo uint32_t i = slot->buf_idx; 1125f9790aebSLuigi Rizzo return (unlikely(i >= na->na_lut_objtotal)) ? 1126f9790aebSLuigi Rizzo lut[0].vaddr : lut[i].vaddr; 1127f9790aebSLuigi Rizzo } 1128f9790aebSLuigi Rizzo 1129ce3ee1e7SLuigi Rizzo 1130ce3ee1e7SLuigi Rizzo 1131f9790aebSLuigi Rizzo void netmap_txsync_to_host(struct netmap_adapter *na); 1132f9790aebSLuigi Rizzo 1133f9790aebSLuigi Rizzo 1134*17885a7bSLuigi Rizzo /* 1135*17885a7bSLuigi Rizzo * Structure associated to each thread which registered an interface. 1136f9790aebSLuigi Rizzo * 1137f9790aebSLuigi Rizzo * The first 4 fields of this structure are written by NIOCREGIF and 1138f9790aebSLuigi Rizzo * read by poll() and NIOC?XSYNC. 1139*17885a7bSLuigi Rizzo * 1140*17885a7bSLuigi Rizzo * There is low contention among writers (a correct user program 1141*17885a7bSLuigi Rizzo * should have none) and among writers and readers, so we use a 1142*17885a7bSLuigi Rizzo * single global lock to protect the structure initialization; 1143*17885a7bSLuigi Rizzo * since initialization involves the allocation of memory, 1144*17885a7bSLuigi Rizzo * we reuse the memory allocator lock. 1145*17885a7bSLuigi Rizzo * 1146f9790aebSLuigi Rizzo * Read access to the structure is lock free. Readers must check that 1147f9790aebSLuigi Rizzo * np_nifp is not NULL before using the other fields. 1148*17885a7bSLuigi Rizzo * If np_nifp is NULL initialization has not been performed, 1149*17885a7bSLuigi Rizzo * so they should return an error to userspace. 1150f9790aebSLuigi Rizzo * 1151f9790aebSLuigi Rizzo * The ref_done field is used to regulate access to the refcount in the 1152f9790aebSLuigi Rizzo * memory allocator. The refcount must be incremented at most once for 1153f9790aebSLuigi Rizzo * each open("/dev/netmap"). The increment is performed by the first 1154f9790aebSLuigi Rizzo * function that calls netmap_get_memory() (currently called by 1155f9790aebSLuigi Rizzo * mmap(), NIOCGINFO and NIOCREGIF). 1156f9790aebSLuigi Rizzo * If the refcount is incremented, it is then decremented when the 1157f9790aebSLuigi Rizzo * private structure is destroyed. 1158f9790aebSLuigi Rizzo */ 1159f9790aebSLuigi Rizzo struct netmap_priv_d { 1160f9790aebSLuigi Rizzo struct netmap_if * volatile np_nifp; /* netmap if descriptor. */ 1161f9790aebSLuigi Rizzo 1162f9790aebSLuigi Rizzo struct netmap_adapter *np_na; 1163f9790aebSLuigi Rizzo int np_ringid; /* from the ioctl */ 1164f9790aebSLuigi Rizzo u_int np_qfirst, np_qlast; /* range of rings to scan */ 1165f9790aebSLuigi Rizzo uint16_t np_txpoll; 1166f9790aebSLuigi Rizzo 1167f9790aebSLuigi Rizzo struct netmap_mem_d *np_mref; /* use with NMG_LOCK held */ 1168f9790aebSLuigi Rizzo /* np_refcount is only used on FreeBSD */ 1169f9790aebSLuigi Rizzo int np_refcount; /* use with NMG_LOCK held */ 1170f9790aebSLuigi Rizzo }; 1171f9790aebSLuigi Rizzo 1172f9790aebSLuigi Rizzo 1173f9790aebSLuigi Rizzo /* 1174f9790aebSLuigi Rizzo * generic netmap emulation for devices that do not have 1175f9790aebSLuigi Rizzo * native netmap support. 1176f9790aebSLuigi Rizzo */ 1177f9790aebSLuigi Rizzo int generic_netmap_attach(struct ifnet *ifp); 1178f9790aebSLuigi Rizzo 1179f9790aebSLuigi Rizzo int netmap_catch_rx(struct netmap_adapter *na, int intercept); 1180f9790aebSLuigi Rizzo void generic_rx_handler(struct ifnet *ifp, struct mbuf *m);; 1181*17885a7bSLuigi Rizzo void netmap_catch_tx(struct netmap_generic_adapter *na, int enable); 1182f9790aebSLuigi Rizzo int generic_xmit_frame(struct ifnet *ifp, struct mbuf *m, void *addr, u_int len, u_int ring_nr); 1183f9790aebSLuigi Rizzo int generic_find_num_desc(struct ifnet *ifp, u_int *tx, u_int *rx); 1184f9790aebSLuigi Rizzo void generic_find_num_queues(struct ifnet *ifp, u_int *txq, u_int *rxq); 1185f9790aebSLuigi Rizzo 1186f9790aebSLuigi Rizzo /* 1187f9790aebSLuigi Rizzo * netmap_mitigation API. This is used by the generic adapter 1188f9790aebSLuigi Rizzo * to reduce the number of interrupt requests/selwakeup 1189f9790aebSLuigi Rizzo * to clients on incoming packets. 1190f9790aebSLuigi Rizzo */ 1191f9790aebSLuigi Rizzo void netmap_mitigation_init(struct netmap_generic_adapter *na); 1192f9790aebSLuigi Rizzo void netmap_mitigation_start(struct netmap_generic_adapter *na); 1193f9790aebSLuigi Rizzo void netmap_mitigation_restart(struct netmap_generic_adapter *na); 1194f9790aebSLuigi Rizzo int netmap_mitigation_active(struct netmap_generic_adapter *na); 1195f9790aebSLuigi Rizzo void netmap_mitigation_cleanup(struct netmap_generic_adapter *na); 1196f9790aebSLuigi Rizzo 119768b8534bSLuigi Rizzo #endif /* _NET_NETMAP_KERN_H_ */ 1198