netmap_kern.h revision 231594
1227614Sluigi/* 2231594Sluigi * Copyright (C) 2011-2012 Matteo Landi, Luigi Rizzo. All rights reserved. 3228276Sluigi * 4227614Sluigi * Redistribution and use in source and binary forms, with or without 5227614Sluigi * modification, are permitted provided that the following conditions 6227614Sluigi * are met: 7228276Sluigi * 1. Redistributions of source code must retain the above copyright 8228276Sluigi * notice, this list of conditions and the following disclaimer. 9228276Sluigi * 2. Redistributions in binary form must reproduce the above copyright 10228276Sluigi * notice, this list of conditions and the following disclaimer in the 11227614Sluigi * documentation and/or other materials provided with the distribution. 12228276Sluigi * 13227614Sluigi * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14227614Sluigi * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15227614Sluigi * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16227614Sluigi * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17227614Sluigi * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18227614Sluigi * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19227614Sluigi * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20227614Sluigi * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21227614Sluigi * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22227614Sluigi * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23227614Sluigi * SUCH DAMAGE. 24227614Sluigi */ 25227614Sluigi 26227614Sluigi/* 27227614Sluigi * $FreeBSD: head/sys/dev/netmap/netmap_kern.h 231594 2012-02-13 18:56:34Z luigi $ 28228276Sluigi * $Id: netmap_kern.h 9795 2011-12-02 11:39:08Z luigi $ 29227614Sluigi * 30227614Sluigi * The header contains the definitions of constants and function 31227614Sluigi * prototypes used only in kernelspace. 32227614Sluigi */ 33227614Sluigi 34227614Sluigi#ifndef _NET_NETMAP_KERN_H_ 35227614Sluigi#define _NET_NETMAP_KERN_H_ 36227614Sluigi 37231594Sluigi#if defined(__FreeBSD__) 38231594Sluigi#define NM_LOCK_T struct mtx 39231594Sluigi#define NM_SELINFO_T struct selinfo 40231594Sluigi#define MBUF_LEN(m) ((m)->m_pkthdr.len) 41231594Sluigi#define NM_SEND_UP(ifp, m) ((ifp)->if_input)(ifp, m) 42231594Sluigi#elif defined (__linux__) 43231594Sluigi#define NM_LOCK_T spinlock_t 44231594Sluigi#define NM_SELINFO_T wait_queue_head_t 45231594Sluigi#define MBUF_LEN(m) ((m)->len) 46231594Sluigi#define NM_SEND_UP(ifp, m) netif_rx(m) 47231594Sluigi#else 48231594Sluigi#error unsupported platform 49231594Sluigi#endif 50231594Sluigi 51227614Sluigi#ifdef MALLOC_DECLARE 52227614SluigiMALLOC_DECLARE(M_NETMAP); 53227614Sluigi#endif 54227614Sluigi 55227614Sluigi#define ND(format, ...) 56230058Sluigi#define D(format, ...) \ 57230058Sluigi do { \ 58230058Sluigi struct timeval __xxts; \ 59227614Sluigi microtime(&__xxts); \ 60230058Sluigi printf("%03d.%06d %s [%d] " format "\n", \ 61230058Sluigi (int)__xxts.tv_sec % 1000, (int)__xxts.tv_usec, \ 62230058Sluigi __FUNCTION__, __LINE__, ##__VA_ARGS__); \ 63227614Sluigi } while (0) 64227614Sluigi 65227614Sluigistruct netmap_adapter; 66227614Sluigi 67227614Sluigi/* 68227614Sluigi * private, kernel view of a ring. 69227614Sluigi * 70231594Sluigi * The indexes in the NIC and netmap rings are offset by nkr_hwofs slots. 71227614Sluigi * This is so that, on a reset, buffers owned by userspace are not 72227614Sluigi * modified by the kernel. In particular: 73231594Sluigi * RX rings: the next empty buffer (hwcur + hwavail + hwofs) coincides with 74227614Sluigi * the next empty buffer as known by the hardware (next_to_check or so). 75227614Sluigi * TX rings: hwcur + hwofs coincides with next_to_send 76227614Sluigi */ 77227614Sluigistruct netmap_kring { 78227614Sluigi struct netmap_ring *ring; 79227614Sluigi u_int nr_hwcur; 80227614Sluigi int nr_hwavail; 81230572Sluigi u_int nr_kflags; /* private driver flags */ 82230572Sluigi#define NKR_PENDINTR 0x1 // Pending interrupt. 83227614Sluigi u_int nkr_num_slots; 84227614Sluigi 85228276Sluigi int nkr_hwofs; /* offset between NIC and netmap ring */ 86231594Sluigi struct netmap_adapter *na; 87231594Sluigi NM_SELINFO_T si; /* poll/select wait queue */ 88231594Sluigi NM_LOCK_T q_lock; /* used if no device lock available */ 89230572Sluigi} __attribute__((__aligned__(64))); 90227614Sluigi 91227614Sluigi/* 92231594Sluigi * This struct extends the 'struct adapter' (or 93227614Sluigi * equivalent) device descriptor. It contains all fields needed to 94227614Sluigi * support netmap operation. 95227614Sluigi */ 96227614Sluigistruct netmap_adapter { 97227614Sluigi int refcount; /* number of user-space descriptors using this 98227614Sluigi interface, which is equal to the number of 99227614Sluigi struct netmap_if objs in the mapped region. */ 100227614Sluigi 101227614Sluigi int separate_locks; /* set if the interface suports different 102227614Sluigi locks for rx, tx and core. */ 103227614Sluigi 104227614Sluigi u_int num_queues; /* number of tx/rx queue pairs: this is 105227614Sluigi a duplicate field needed to simplify the 106227614Sluigi signature of ``netmap_detach``. */ 107227614Sluigi 108227614Sluigi u_int num_tx_desc; /* number of descriptor in each queue */ 109227614Sluigi u_int num_rx_desc; 110231594Sluigi u_int buff_size; 111227614Sluigi 112231594Sluigi //u_int flags; // XXX unused 113227614Sluigi /* tx_rings and rx_rings are private but allocated 114227614Sluigi * as a contiguous chunk of memory. Each array has 115227614Sluigi * N+1 entries, for the adapter queues and for the host queue. 116227614Sluigi */ 117227614Sluigi struct netmap_kring *tx_rings; /* array of TX rings. */ 118227614Sluigi struct netmap_kring *rx_rings; /* array of RX rings. */ 119227614Sluigi 120227614Sluigi /* copy of if_qflush and if_transmit pointers, to intercept 121227614Sluigi * packets from the network stack when netmap is active. 122227614Sluigi * XXX probably if_qflush is not necessary. 123227614Sluigi */ 124231594Sluigi //void (*if_qflush)(struct ifnet *); // XXX unused 125227614Sluigi int (*if_transmit)(struct ifnet *, struct mbuf *); 126227614Sluigi 127227614Sluigi /* references to the ifnet and device routines, used by 128227614Sluigi * the generic netmap functions. 129227614Sluigi */ 130227614Sluigi struct ifnet *ifp; /* adapter is ifp->if_softc */ 131227614Sluigi 132231594Sluigi NM_LOCK_T core_lock; /* used if no device lock available */ 133231594Sluigi 134227614Sluigi int (*nm_register)(struct ifnet *, int onoff); 135231594Sluigi void (*nm_lock)(struct ifnet *, int what, u_int ringid); 136231594Sluigi int (*nm_txsync)(struct ifnet *, u_int ring, int lock); 137231594Sluigi int (*nm_rxsync)(struct ifnet *, u_int ring, int lock); 138227614Sluigi}; 139227614Sluigi 140227614Sluigi/* 141227614Sluigi * The combination of "enable" (ifp->if_capabilities &IFCAP_NETMAP) 142227614Sluigi * and refcount gives the status of the interface, namely: 143227614Sluigi * 144227614Sluigi * enable refcount Status 145227614Sluigi * 146227614Sluigi * FALSE 0 normal operation 147227614Sluigi * FALSE != 0 -- (impossible) 148227614Sluigi * TRUE 1 netmap mode 149227614Sluigi * TRUE 0 being deleted. 150227614Sluigi */ 151227614Sluigi 152227614Sluigi#define NETMAP_DELETING(_na) ( ((_na)->refcount == 0) && \ 153227614Sluigi ( (_na)->ifp->if_capenable & IFCAP_NETMAP) ) 154227614Sluigi 155227614Sluigi/* 156227614Sluigi * parameters for (*nm_lock)(adapter, what, index) 157227614Sluigi */ 158227614Sluigienum { 159227614Sluigi NETMAP_NO_LOCK = 0, 160227614Sluigi NETMAP_CORE_LOCK, NETMAP_CORE_UNLOCK, 161227614Sluigi NETMAP_TX_LOCK, NETMAP_TX_UNLOCK, 162227614Sluigi NETMAP_RX_LOCK, NETMAP_RX_UNLOCK, 163231594Sluigi#ifdef __FreeBSD__ 164231594Sluigi#define NETMAP_REG_LOCK NETMAP_CORE_LOCK 165231594Sluigi#define NETMAP_REG_UNLOCK NETMAP_CORE_UNLOCK 166231594Sluigi#else 167231594Sluigi NETMAP_REG_LOCK, NETMAP_REG_UNLOCK 168231594Sluigi#endif 169227614Sluigi}; 170227614Sluigi 171227614Sluigi/* 172227614Sluigi * The following are support routines used by individual drivers to 173227614Sluigi * support netmap operation. 174227614Sluigi * 175227614Sluigi * netmap_attach() initializes a struct netmap_adapter, allocating the 176227614Sluigi * struct netmap_ring's and the struct selinfo. 177227614Sluigi * 178227614Sluigi * netmap_detach() frees the memory allocated by netmap_attach(). 179227614Sluigi * 180227614Sluigi * netmap_start() replaces the if_transmit routine of the interface, 181227614Sluigi * and is used to intercept packets coming from the stack. 182227614Sluigi * 183227614Sluigi * netmap_load_map/netmap_reload_map are helper routines to set/reset 184227614Sluigi * the dmamap for a packet buffer 185227614Sluigi * 186227614Sluigi * netmap_reset() is a helper routine to be called in the driver 187227614Sluigi * when reinitializing a ring. 188227614Sluigi */ 189227614Sluigiint netmap_attach(struct netmap_adapter *, int); 190227614Sluigivoid netmap_detach(struct ifnet *); 191227614Sluigiint netmap_start(struct ifnet *, struct mbuf *); 192227614Sluigienum txrx { NR_RX = 0, NR_TX = 1 }; 193227614Sluigistruct netmap_slot *netmap_reset(struct netmap_adapter *na, 194227614Sluigi enum txrx tx, int n, u_int new_cur); 195227614Sluigiint netmap_ring_reinit(struct netmap_kring *); 196227614Sluigi 197231198Sluigiextern int netmap_buf_size; 198231198Sluigi#define NETMAP_BUF_SIZE netmap_buf_size 199230572Sluigiextern int netmap_mitigate; 200231198Sluigiextern int netmap_no_pendintr; 201227614Sluigiextern u_int netmap_total_buffers; 202227614Sluigiextern char *netmap_buffer_base; 203227614Sluigiextern int netmap_verbose; // XXX debugging 204227614Sluigienum { /* verbose flags */ 205227614Sluigi NM_VERB_ON = 1, /* generic verbose */ 206227614Sluigi NM_VERB_HOST = 0x2, /* verbose host stack */ 207227614Sluigi NM_VERB_RXSYNC = 0x10, /* verbose on rxsync/txsync */ 208227614Sluigi NM_VERB_TXSYNC = 0x20, 209227614Sluigi NM_VERB_RXINTR = 0x100, /* verbose on rx/tx intr (driver) */ 210227614Sluigi NM_VERB_TXINTR = 0x200, 211227614Sluigi NM_VERB_NIC_RXSYNC = 0x1000, /* verbose on rx/tx intr (driver) */ 212227614Sluigi NM_VERB_NIC_TXSYNC = 0x2000, 213227614Sluigi}; 214227614Sluigi 215227614Sluigi/* 216228845Sluigi * NA returns a pointer to the struct netmap adapter from the ifp, 217228845Sluigi * WNA is used to write it. 218227614Sluigi */ 219228845Sluigi#ifndef WNA 220228845Sluigi#define WNA(_ifp) (_ifp)->if_pspare[0] 221228845Sluigi#endif 222228845Sluigi#define NA(_ifp) ((struct netmap_adapter *)WNA(_ifp)) 223227614Sluigi 224227614Sluigi 225230052Sluigi/* Callback invoked by the dma machinery after a successfull dmamap_load */ 226230052Sluigistatic void netmap_dmamap_cb(__unused void *arg, 227230058Sluigi __unused bus_dma_segment_t * segs, __unused int nseg, __unused int error) 228230052Sluigi{ 229230052Sluigi} 230230052Sluigi 231230052Sluigi/* bus_dmamap_load wrapper: call aforementioned function if map != NULL. 232230052Sluigi * XXX can we do it without a callback ? 233230052Sluigi */ 234230052Sluigistatic inline void 235230052Sluiginetmap_load_map(bus_dma_tag_t tag, bus_dmamap_t map, void *buf) 236230052Sluigi{ 237230052Sluigi if (map) 238230052Sluigi bus_dmamap_load(tag, map, buf, NETMAP_BUF_SIZE, 239230058Sluigi netmap_dmamap_cb, NULL, BUS_DMA_NOWAIT); 240230052Sluigi} 241230052Sluigi 242230052Sluigi/* update the map when a buffer changes. */ 243230052Sluigistatic inline void 244230052Sluiginetmap_reload_map(bus_dma_tag_t tag, bus_dmamap_t map, void *buf) 245230052Sluigi{ 246230052Sluigi if (map) { 247230052Sluigi bus_dmamap_unload(tag, map); 248230052Sluigi bus_dmamap_load(tag, map, buf, NETMAP_BUF_SIZE, 249230058Sluigi netmap_dmamap_cb, NULL, BUS_DMA_NOWAIT); 250230052Sluigi } 251230052Sluigi} 252230052Sluigi 253230052Sluigi 254227614Sluigi/* 255229939Sluigi * NMB return the virtual address of a buffer (buffer 0 on bad index) 256229939Sluigi * PNMB also fills the physical address 257227614Sluigi */ 258229939Sluigistatic inline void * 259227614SluigiNMB(struct netmap_slot *slot) 260227614Sluigi{ 261227614Sluigi uint32_t i = slot->buf_idx; 262227614Sluigi return (i >= netmap_total_buffers) ? netmap_buffer_base : 263227614Sluigi netmap_buffer_base + (i *NETMAP_BUF_SIZE); 264227614Sluigi} 265227614Sluigi 266229939Sluigistatic inline void * 267229939SluigiPNMB(struct netmap_slot *slot, uint64_t *pp) 268229939Sluigi{ 269229939Sluigi uint32_t i = slot->buf_idx; 270229939Sluigi void *ret = (i >= netmap_total_buffers) ? netmap_buffer_base : 271229939Sluigi netmap_buffer_base + (i *NETMAP_BUF_SIZE); 272229939Sluigi *pp = vtophys(ret); 273229939Sluigi return ret; 274229939Sluigi} 275229939Sluigi 276231594Sluigi/* default functions to handle rx/tx interrupts */ 277231594Sluigiint netmap_rx_irq(struct ifnet *, int, int *); 278231594Sluigi#define netmap_tx_irq(_n, _q) netmap_rx_irq(_n, _q, NULL) 279231594Sluigi#ifdef __linux__ 280231594Sluigi#define bus_dmamap_sync(_a, _b, _c) // wmb() or rmb() ? 281231594Sluiginetdev_tx_t netmap_start_linux(struct sk_buff *skb, struct net_device *dev); 282231594Sluigi#endif 283227614Sluigi#endif /* _NET_NETMAP_KERN_H_ */ 284