netmap_kern.h revision 230572
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 230572 2012-01-26 09:55:16Z 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, ...) 42230058Sluigi#define D(format, ...) \ 43230058Sluigi do { \ 44230058Sluigi struct timeval __xxts; \ 45227614Sluigi microtime(&__xxts); \ 46230058Sluigi printf("%03d.%06d %s [%d] " format "\n", \ 47230058Sluigi (int)__xxts.tv_sec % 1000, (int)__xxts.tv_usec, \ 48230058Sluigi __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; 68230572Sluigi u_int nr_kflags; /* private driver flags */ 69230572Sluigi#define NKR_PENDINTR 0x1 // Pending interrupt. 70227614Sluigi u_int nkr_num_slots; 71227614Sluigi 72228276Sluigi int nkr_hwofs; /* offset between NIC and netmap ring */ 73227614Sluigi struct netmap_adapter *na; // debugging 74227614Sluigi struct selinfo si; /* poll/select wait queue */ 75230572Sluigi} __attribute__((__aligned__(64))); 76227614Sluigi 77227614Sluigi/* 78227614Sluigi * This struct is part of and extends the 'struct adapter' (or 79227614Sluigi * equivalent) device descriptor. It contains all fields needed to 80227614Sluigi * support netmap operation. 81227614Sluigi */ 82227614Sluigistruct netmap_adapter { 83227614Sluigi int refcount; /* number of user-space descriptors using this 84227614Sluigi interface, which is equal to the number of 85227614Sluigi struct netmap_if objs in the mapped region. */ 86227614Sluigi 87227614Sluigi int separate_locks; /* set if the interface suports different 88227614Sluigi locks for rx, tx and core. */ 89227614Sluigi 90227614Sluigi u_int num_queues; /* number of tx/rx queue pairs: this is 91227614Sluigi a duplicate field needed to simplify the 92227614Sluigi signature of ``netmap_detach``. */ 93227614Sluigi 94227614Sluigi u_int num_tx_desc; /* number of descriptor in each queue */ 95227614Sluigi u_int num_rx_desc; 96227614Sluigi u_int buff_size; 97227614Sluigi 98228276Sluigi u_int flags; 99227614Sluigi /* tx_rings and rx_rings are private but allocated 100227614Sluigi * as a contiguous chunk of memory. Each array has 101227614Sluigi * N+1 entries, for the adapter queues and for the host queue. 102227614Sluigi */ 103227614Sluigi struct netmap_kring *tx_rings; /* array of TX rings. */ 104227614Sluigi struct netmap_kring *rx_rings; /* array of RX rings. */ 105227614Sluigi 106227614Sluigi /* copy of if_qflush and if_transmit pointers, to intercept 107227614Sluigi * packets from the network stack when netmap is active. 108227614Sluigi * XXX probably if_qflush is not necessary. 109227614Sluigi */ 110227614Sluigi void (*if_qflush)(struct ifnet *); 111227614Sluigi int (*if_transmit)(struct ifnet *, struct mbuf *); 112227614Sluigi 113227614Sluigi /* references to the ifnet and device routines, used by 114227614Sluigi * the generic netmap functions. 115227614Sluigi */ 116227614Sluigi struct ifnet *ifp; /* adapter is ifp->if_softc */ 117227614Sluigi 118227614Sluigi int (*nm_register)(struct ifnet *, int onoff); 119227614Sluigi void (*nm_lock)(void *, int what, u_int ringid); 120227614Sluigi int (*nm_txsync)(void *, u_int ring, int lock); 121227614Sluigi int (*nm_rxsync)(void *, u_int ring, int lock); 122227614Sluigi}; 123227614Sluigi 124227614Sluigi/* 125227614Sluigi * The combination of "enable" (ifp->if_capabilities &IFCAP_NETMAP) 126227614Sluigi * and refcount gives the status of the interface, namely: 127227614Sluigi * 128227614Sluigi * enable refcount Status 129227614Sluigi * 130227614Sluigi * FALSE 0 normal operation 131227614Sluigi * FALSE != 0 -- (impossible) 132227614Sluigi * TRUE 1 netmap mode 133227614Sluigi * TRUE 0 being deleted. 134227614Sluigi */ 135227614Sluigi 136227614Sluigi#define NETMAP_DELETING(_na) ( ((_na)->refcount == 0) && \ 137227614Sluigi ( (_na)->ifp->if_capenable & IFCAP_NETMAP) ) 138227614Sluigi 139227614Sluigi/* 140227614Sluigi * parameters for (*nm_lock)(adapter, what, index) 141227614Sluigi */ 142227614Sluigienum { 143227614Sluigi NETMAP_NO_LOCK = 0, 144227614Sluigi NETMAP_CORE_LOCK, NETMAP_CORE_UNLOCK, 145227614Sluigi NETMAP_TX_LOCK, NETMAP_TX_UNLOCK, 146227614Sluigi NETMAP_RX_LOCK, NETMAP_RX_UNLOCK, 147227614Sluigi}; 148227614Sluigi 149227614Sluigi/* 150227614Sluigi * The following are support routines used by individual drivers to 151227614Sluigi * support netmap operation. 152227614Sluigi * 153227614Sluigi * netmap_attach() initializes a struct netmap_adapter, allocating the 154227614Sluigi * struct netmap_ring's and the struct selinfo. 155227614Sluigi * 156227614Sluigi * netmap_detach() frees the memory allocated by netmap_attach(). 157227614Sluigi * 158227614Sluigi * netmap_start() replaces the if_transmit routine of the interface, 159227614Sluigi * and is used to intercept packets coming from the stack. 160227614Sluigi * 161227614Sluigi * netmap_load_map/netmap_reload_map are helper routines to set/reset 162227614Sluigi * the dmamap for a packet buffer 163227614Sluigi * 164227614Sluigi * netmap_reset() is a helper routine to be called in the driver 165227614Sluigi * when reinitializing a ring. 166227614Sluigi */ 167227614Sluigiint netmap_attach(struct netmap_adapter *, int); 168227614Sluigivoid netmap_detach(struct ifnet *); 169227614Sluigiint netmap_start(struct ifnet *, struct mbuf *); 170227614Sluigienum txrx { NR_RX = 0, NR_TX = 1 }; 171227614Sluigistruct netmap_slot *netmap_reset(struct netmap_adapter *na, 172227614Sluigi enum txrx tx, int n, u_int new_cur); 173227614Sluigiint netmap_ring_reinit(struct netmap_kring *); 174227614Sluigi 175230572Sluigiextern int netmap_mitigate; 176230572Sluigiextern int netmap_skip_txsync, netmap_skip_rxsync; 177227614Sluigiextern u_int netmap_total_buffers; 178227614Sluigiextern char *netmap_buffer_base; 179227614Sluigiextern int netmap_verbose; // XXX debugging 180227614Sluigienum { /* verbose flags */ 181227614Sluigi NM_VERB_ON = 1, /* generic verbose */ 182227614Sluigi NM_VERB_HOST = 0x2, /* verbose host stack */ 183227614Sluigi NM_VERB_RXSYNC = 0x10, /* verbose on rxsync/txsync */ 184227614Sluigi NM_VERB_TXSYNC = 0x20, 185227614Sluigi NM_VERB_RXINTR = 0x100, /* verbose on rx/tx intr (driver) */ 186227614Sluigi NM_VERB_TXINTR = 0x200, 187227614Sluigi NM_VERB_NIC_RXSYNC = 0x1000, /* verbose on rx/tx intr (driver) */ 188227614Sluigi NM_VERB_NIC_TXSYNC = 0x2000, 189227614Sluigi}; 190227614Sluigi 191227614Sluigi/* 192228845Sluigi * NA returns a pointer to the struct netmap adapter from the ifp, 193228845Sluigi * WNA is used to write it. 194227614Sluigi */ 195228845Sluigi#ifndef WNA 196228845Sluigi#define WNA(_ifp) (_ifp)->if_pspare[0] 197228845Sluigi#endif 198228845Sluigi#define NA(_ifp) ((struct netmap_adapter *)WNA(_ifp)) 199227614Sluigi 200227614Sluigi 201230052Sluigi/* Callback invoked by the dma machinery after a successfull dmamap_load */ 202230052Sluigistatic void netmap_dmamap_cb(__unused void *arg, 203230058Sluigi __unused bus_dma_segment_t * segs, __unused int nseg, __unused int error) 204230052Sluigi{ 205230052Sluigi} 206230052Sluigi 207230052Sluigi/* bus_dmamap_load wrapper: call aforementioned function if map != NULL. 208230052Sluigi * XXX can we do it without a callback ? 209230052Sluigi */ 210230052Sluigistatic inline void 211230052Sluiginetmap_load_map(bus_dma_tag_t tag, bus_dmamap_t map, void *buf) 212230052Sluigi{ 213230052Sluigi if (map) 214230052Sluigi bus_dmamap_load(tag, map, buf, NETMAP_BUF_SIZE, 215230058Sluigi netmap_dmamap_cb, NULL, BUS_DMA_NOWAIT); 216230052Sluigi} 217230052Sluigi 218230052Sluigi/* update the map when a buffer changes. */ 219230052Sluigistatic inline void 220230052Sluiginetmap_reload_map(bus_dma_tag_t tag, bus_dmamap_t map, void *buf) 221230052Sluigi{ 222230052Sluigi if (map) { 223230052Sluigi bus_dmamap_unload(tag, map); 224230052Sluigi bus_dmamap_load(tag, map, buf, NETMAP_BUF_SIZE, 225230058Sluigi netmap_dmamap_cb, NULL, BUS_DMA_NOWAIT); 226230052Sluigi } 227230052Sluigi} 228230052Sluigi 229230052Sluigi 230227614Sluigi/* 231229939Sluigi * NMB return the virtual address of a buffer (buffer 0 on bad index) 232229939Sluigi * PNMB also fills the physical address 233227614Sluigi */ 234229939Sluigistatic inline void * 235227614SluigiNMB(struct netmap_slot *slot) 236227614Sluigi{ 237227614Sluigi uint32_t i = slot->buf_idx; 238227614Sluigi return (i >= netmap_total_buffers) ? netmap_buffer_base : 239227614Sluigi#if NETMAP_BUF_SIZE == 2048 240227614Sluigi netmap_buffer_base + (i << 11); 241227614Sluigi#else 242227614Sluigi netmap_buffer_base + (i *NETMAP_BUF_SIZE); 243227614Sluigi#endif 244227614Sluigi} 245227614Sluigi 246229939Sluigistatic inline void * 247229939SluigiPNMB(struct netmap_slot *slot, uint64_t *pp) 248229939Sluigi{ 249229939Sluigi uint32_t i = slot->buf_idx; 250229939Sluigi void *ret = (i >= netmap_total_buffers) ? netmap_buffer_base : 251229939Sluigi#if NETMAP_BUF_SIZE == 2048 252229939Sluigi netmap_buffer_base + (i << 11); 253229939Sluigi#else 254229939Sluigi netmap_buffer_base + (i *NETMAP_BUF_SIZE); 255229939Sluigi#endif 256229939Sluigi *pp = vtophys(ret); 257229939Sluigi return ret; 258229939Sluigi} 259229939Sluigi 260227614Sluigi#endif /* _NET_NETMAP_KERN_H_ */ 261