netmap_kern.h revision 230052
1227614Sluigi/* 2227614Sluigi * Copyright (C) 2011 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 230052 2012-01-13 10:21:15Z 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 37227614Sluigi#ifdef MALLOC_DECLARE 38227614SluigiMALLOC_DECLARE(M_NETMAP); 39227614Sluigi#endif 40227614Sluigi 41227614Sluigi#define ND(format, ...) 42227614Sluigi#define D(format, ...) \ 43227614Sluigi do { \ 44227614Sluigi struct timeval __xxts; \ 45227614Sluigi microtime(&__xxts); \ 46227614Sluigi printf("%03d.%06d %s [%d] " format "\n",\ 47227614Sluigi (int)__xxts.tv_sec % 1000, (int)__xxts.tv_usec, \ 48227614Sluigi __FUNCTION__, __LINE__, ##__VA_ARGS__); \ 49227614Sluigi } while (0) 50227614Sluigi 51227614Sluigistruct netmap_adapter; 52227614Sluigi 53227614Sluigi/* 54227614Sluigi * private, kernel view of a ring. 55227614Sluigi * 56227614Sluigi * XXX 20110627-todo 57227614Sluigi * The index in the NIC and netmap ring is offset by nkr_hwofs slots. 58227614Sluigi * This is so that, on a reset, buffers owned by userspace are not 59227614Sluigi * modified by the kernel. In particular: 60227614Sluigi * RX rings: the next empty buffer (hwcur + hwavail + hwofs) coincides 61227614Sluigi * the next empty buffer as known by the hardware (next_to_check or so). 62227614Sluigi * TX rings: hwcur + hwofs coincides with next_to_send 63227614Sluigi */ 64227614Sluigistruct netmap_kring { 65227614Sluigi struct netmap_ring *ring; 66227614Sluigi u_int nr_hwcur; 67227614Sluigi int nr_hwavail; 68227614Sluigi u_int nr_kflags; 69227614Sluigi u_int nkr_num_slots; 70227614Sluigi 71228276Sluigi int nkr_hwofs; /* offset between NIC and netmap ring */ 72227614Sluigi struct netmap_adapter *na; // debugging 73227614Sluigi struct selinfo si; /* poll/select wait queue */ 74227614Sluigi}; 75227614Sluigi 76227614Sluigi/* 77227614Sluigi * This struct is part of and extends the 'struct adapter' (or 78227614Sluigi * equivalent) device descriptor. It contains all fields needed to 79227614Sluigi * support netmap operation. 80227614Sluigi */ 81227614Sluigistruct netmap_adapter { 82227614Sluigi int refcount; /* number of user-space descriptors using this 83227614Sluigi interface, which is equal to the number of 84227614Sluigi struct netmap_if objs in the mapped region. */ 85227614Sluigi 86227614Sluigi int separate_locks; /* set if the interface suports different 87227614Sluigi locks for rx, tx and core. */ 88227614Sluigi 89227614Sluigi u_int num_queues; /* number of tx/rx queue pairs: this is 90227614Sluigi a duplicate field needed to simplify the 91227614Sluigi signature of ``netmap_detach``. */ 92227614Sluigi 93227614Sluigi u_int num_tx_desc; /* number of descriptor in each queue */ 94227614Sluigi u_int num_rx_desc; 95227614Sluigi u_int buff_size; 96227614Sluigi 97228276Sluigi u_int flags; 98227614Sluigi /* tx_rings and rx_rings are private but allocated 99227614Sluigi * as a contiguous chunk of memory. Each array has 100227614Sluigi * N+1 entries, for the adapter queues and for the host queue. 101227614Sluigi */ 102227614Sluigi struct netmap_kring *tx_rings; /* array of TX rings. */ 103227614Sluigi struct netmap_kring *rx_rings; /* array of RX rings. */ 104227614Sluigi 105227614Sluigi /* copy of if_qflush and if_transmit pointers, to intercept 106227614Sluigi * packets from the network stack when netmap is active. 107227614Sluigi * XXX probably if_qflush is not necessary. 108227614Sluigi */ 109227614Sluigi void (*if_qflush)(struct ifnet *); 110227614Sluigi int (*if_transmit)(struct ifnet *, struct mbuf *); 111227614Sluigi 112227614Sluigi /* references to the ifnet and device routines, used by 113227614Sluigi * the generic netmap functions. 114227614Sluigi */ 115227614Sluigi struct ifnet *ifp; /* adapter is ifp->if_softc */ 116227614Sluigi 117227614Sluigi int (*nm_register)(struct ifnet *, int onoff); 118227614Sluigi void (*nm_lock)(void *, int what, u_int ringid); 119227614Sluigi int (*nm_txsync)(void *, u_int ring, int lock); 120227614Sluigi int (*nm_rxsync)(void *, u_int ring, int lock); 121227614Sluigi}; 122227614Sluigi 123227614Sluigi/* 124227614Sluigi * The combination of "enable" (ifp->if_capabilities &IFCAP_NETMAP) 125227614Sluigi * and refcount gives the status of the interface, namely: 126227614Sluigi * 127227614Sluigi * enable refcount Status 128227614Sluigi * 129227614Sluigi * FALSE 0 normal operation 130227614Sluigi * FALSE != 0 -- (impossible) 131227614Sluigi * TRUE 1 netmap mode 132227614Sluigi * TRUE 0 being deleted. 133227614Sluigi */ 134227614Sluigi 135227614Sluigi#define NETMAP_DELETING(_na) ( ((_na)->refcount == 0) && \ 136227614Sluigi ( (_na)->ifp->if_capenable & IFCAP_NETMAP) ) 137227614Sluigi 138227614Sluigi/* 139227614Sluigi * parameters for (*nm_lock)(adapter, what, index) 140227614Sluigi */ 141227614Sluigienum { 142227614Sluigi NETMAP_NO_LOCK = 0, 143227614Sluigi NETMAP_CORE_LOCK, NETMAP_CORE_UNLOCK, 144227614Sluigi NETMAP_TX_LOCK, NETMAP_TX_UNLOCK, 145227614Sluigi NETMAP_RX_LOCK, NETMAP_RX_UNLOCK, 146227614Sluigi}; 147227614Sluigi 148227614Sluigi/* 149227614Sluigi * The following are support routines used by individual drivers to 150227614Sluigi * support netmap operation. 151227614Sluigi * 152227614Sluigi * netmap_attach() initializes a struct netmap_adapter, allocating the 153227614Sluigi * struct netmap_ring's and the struct selinfo. 154227614Sluigi * 155227614Sluigi * netmap_detach() frees the memory allocated by netmap_attach(). 156227614Sluigi * 157227614Sluigi * netmap_start() replaces the if_transmit routine of the interface, 158227614Sluigi * and is used to intercept packets coming from the stack. 159227614Sluigi * 160227614Sluigi * netmap_load_map/netmap_reload_map are helper routines to set/reset 161227614Sluigi * the dmamap for a packet buffer 162227614Sluigi * 163227614Sluigi * netmap_reset() is a helper routine to be called in the driver 164227614Sluigi * when reinitializing a ring. 165227614Sluigi */ 166227614Sluigiint netmap_attach(struct netmap_adapter *, int); 167227614Sluigivoid netmap_detach(struct ifnet *); 168227614Sluigiint netmap_start(struct ifnet *, struct mbuf *); 169227614Sluigienum txrx { NR_RX = 0, NR_TX = 1 }; 170227614Sluigistruct netmap_slot *netmap_reset(struct netmap_adapter *na, 171227614Sluigi enum txrx tx, int n, u_int new_cur); 172227614Sluigiint netmap_ring_reinit(struct netmap_kring *); 173227614Sluigi 174227614Sluigiextern u_int netmap_total_buffers; 175227614Sluigiextern char *netmap_buffer_base; 176227614Sluigiextern int netmap_verbose; // XXX debugging 177227614Sluigienum { /* verbose flags */ 178227614Sluigi NM_VERB_ON = 1, /* generic verbose */ 179227614Sluigi NM_VERB_HOST = 0x2, /* verbose host stack */ 180227614Sluigi NM_VERB_RXSYNC = 0x10, /* verbose on rxsync/txsync */ 181227614Sluigi NM_VERB_TXSYNC = 0x20, 182227614Sluigi NM_VERB_RXINTR = 0x100, /* verbose on rx/tx intr (driver) */ 183227614Sluigi NM_VERB_TXINTR = 0x200, 184227614Sluigi NM_VERB_NIC_RXSYNC = 0x1000, /* verbose on rx/tx intr (driver) */ 185227614Sluigi NM_VERB_NIC_TXSYNC = 0x2000, 186227614Sluigi}; 187227614Sluigi 188227614Sluigi/* 189228845Sluigi * NA returns a pointer to the struct netmap adapter from the ifp, 190228845Sluigi * WNA is used to write it. 191227614Sluigi */ 192228845Sluigi#ifndef WNA 193228845Sluigi#define WNA(_ifp) (_ifp)->if_pspare[0] 194228845Sluigi#endif 195228845Sluigi#define NA(_ifp) ((struct netmap_adapter *)WNA(_ifp)) 196227614Sluigi 197227614Sluigi 198230052Sluigi/* Callback invoked by the dma machinery after a successfull dmamap_load */ 199230052Sluigistatic void netmap_dmamap_cb(__unused void *arg, 200230052Sluigi __unused bus_dma_segment_t * segs, __unused int nseg, __unused int error) 201230052Sluigi{ 202230052Sluigi} 203230052Sluigi 204230052Sluigi/* bus_dmamap_load wrapper: call aforementioned function if map != NULL. 205230052Sluigi * XXX can we do it without a callback ? 206230052Sluigi */ 207230052Sluigistatic inline void 208230052Sluiginetmap_load_map(bus_dma_tag_t tag, bus_dmamap_t map, void *buf) 209230052Sluigi{ 210230052Sluigi if (map) 211230052Sluigi bus_dmamap_load(tag, map, buf, NETMAP_BUF_SIZE, 212230052Sluigi netmap_dmamap_cb, NULL, BUS_DMA_NOWAIT); 213230052Sluigi} 214230052Sluigi 215230052Sluigi/* update the map when a buffer changes. */ 216230052Sluigistatic inline void 217230052Sluiginetmap_reload_map(bus_dma_tag_t tag, bus_dmamap_t map, void *buf) 218230052Sluigi{ 219230052Sluigi if (map) { 220230052Sluigi bus_dmamap_unload(tag, map); 221230052Sluigi bus_dmamap_load(tag, map, buf, NETMAP_BUF_SIZE, 222230052Sluigi netmap_dmamap_cb, NULL, BUS_DMA_NOWAIT); 223230052Sluigi } 224230052Sluigi} 225230052Sluigi 226230052Sluigi 227227614Sluigi/* 228229939Sluigi * NMB return the virtual address of a buffer (buffer 0 on bad index) 229229939Sluigi * PNMB also fills the physical address 230227614Sluigi * XXX this is a special version with hardwired 2k bufs 231227614Sluigi */ 232229939Sluigistatic inline void * 233227614SluigiNMB(struct netmap_slot *slot) 234227614Sluigi{ 235227614Sluigi uint32_t i = slot->buf_idx; 236227614Sluigi return (i >= netmap_total_buffers) ? netmap_buffer_base : 237227614Sluigi#if NETMAP_BUF_SIZE == 2048 238227614Sluigi netmap_buffer_base + (i << 11); 239227614Sluigi#else 240227614Sluigi netmap_buffer_base + (i *NETMAP_BUF_SIZE); 241227614Sluigi#endif 242227614Sluigi} 243227614Sluigi 244229939Sluigistatic inline void * 245229939SluigiPNMB(struct netmap_slot *slot, uint64_t *pp) 246229939Sluigi{ 247229939Sluigi uint32_t i = slot->buf_idx; 248229939Sluigi void *ret = (i >= netmap_total_buffers) ? netmap_buffer_base : 249229939Sluigi#if NETMAP_BUF_SIZE == 2048 250229939Sluigi netmap_buffer_base + (i << 11); 251229939Sluigi#else 252229939Sluigi netmap_buffer_base + (i *NETMAP_BUF_SIZE); 253229939Sluigi#endif 254229939Sluigi *pp = vtophys(ret); 255229939Sluigi return ret; 256229939Sluigi} 257229939Sluigi 258227614Sluigi#endif /* _NET_NETMAP_KERN_H_ */ 259