netmap_kern.h revision 229939
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 229939 2012-01-10 19:57:23Z 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); 172229939Sluigivoid netmap_load_map(bus_dma_tag_t tag, bus_dmamap_t map, void *buf); 173229939Sluigivoid netmap_reload_map(bus_dma_tag_t tag, bus_dmamap_t map, void *buf); 174227614Sluigiint netmap_ring_reinit(struct netmap_kring *); 175227614Sluigi 176227614Sluigi/* 177227614Sluigi * XXX eventually, get rid of netmap_total_buffers and netmap_buffer_base 178227614Sluigi * in favour of the structure 179227614Sluigi */ 180227614Sluigi// struct netmap_buf_pool; 181227614Sluigi// extern struct netmap_buf_pool nm_buf_pool; 182227614Sluigiextern u_int netmap_total_buffers; 183227614Sluigiextern char *netmap_buffer_base; 184227614Sluigiextern int netmap_verbose; // XXX debugging 185227614Sluigienum { /* verbose flags */ 186227614Sluigi NM_VERB_ON = 1, /* generic verbose */ 187227614Sluigi NM_VERB_HOST = 0x2, /* verbose host stack */ 188227614Sluigi NM_VERB_RXSYNC = 0x10, /* verbose on rxsync/txsync */ 189227614Sluigi NM_VERB_TXSYNC = 0x20, 190227614Sluigi NM_VERB_RXINTR = 0x100, /* verbose on rx/tx intr (driver) */ 191227614Sluigi NM_VERB_TXINTR = 0x200, 192227614Sluigi NM_VERB_NIC_RXSYNC = 0x1000, /* verbose on rx/tx intr (driver) */ 193227614Sluigi NM_VERB_NIC_TXSYNC = 0x2000, 194227614Sluigi}; 195227614Sluigi 196227614Sluigi/* 197228845Sluigi * NA returns a pointer to the struct netmap adapter from the ifp, 198228845Sluigi * WNA is used to write it. 199227614Sluigi */ 200228845Sluigi#ifndef WNA 201228845Sluigi#define WNA(_ifp) (_ifp)->if_pspare[0] 202228845Sluigi#endif 203228845Sluigi#define NA(_ifp) ((struct netmap_adapter *)WNA(_ifp)) 204227614Sluigi 205227614Sluigi 206227614Sluigi/* 207229939Sluigi * NMB return the virtual address of a buffer (buffer 0 on bad index) 208229939Sluigi * PNMB also fills the physical address 209227614Sluigi * XXX this is a special version with hardwired 2k bufs 210227614Sluigi */ 211229939Sluigistatic inline void * 212227614SluigiNMB(struct netmap_slot *slot) 213227614Sluigi{ 214227614Sluigi uint32_t i = slot->buf_idx; 215227614Sluigi return (i >= netmap_total_buffers) ? netmap_buffer_base : 216227614Sluigi#if NETMAP_BUF_SIZE == 2048 217227614Sluigi netmap_buffer_base + (i << 11); 218227614Sluigi#else 219227614Sluigi netmap_buffer_base + (i *NETMAP_BUF_SIZE); 220227614Sluigi#endif 221227614Sluigi} 222227614Sluigi 223229939Sluigistatic inline void * 224229939SluigiPNMB(struct netmap_slot *slot, uint64_t *pp) 225229939Sluigi{ 226229939Sluigi uint32_t i = slot->buf_idx; 227229939Sluigi void *ret = (i >= netmap_total_buffers) ? netmap_buffer_base : 228229939Sluigi#if NETMAP_BUF_SIZE == 2048 229229939Sluigi netmap_buffer_base + (i << 11); 230229939Sluigi#else 231229939Sluigi netmap_buffer_base + (i *NETMAP_BUF_SIZE); 232229939Sluigi#endif 233229939Sluigi *pp = vtophys(ret); 234229939Sluigi return ret; 235229939Sluigi} 236229939Sluigi 237227614Sluigi#endif /* _NET_NETMAP_KERN_H_ */ 238