xref: /freebsd-14.2/sys/dev/netmap/netmap_mem2.h (revision ab1e2860)
1*ab1e2860SLuigi Rizzo /*
2*ab1e2860SLuigi Rizzo  * Copyright (C) 2012-2013 Matteo Landi, Luigi Rizzo, Giuseppe Lettieri. All rights reserved.
3*ab1e2860SLuigi Rizzo  *
4*ab1e2860SLuigi Rizzo  * Redistribution and use in source and binary forms, with or without
5*ab1e2860SLuigi Rizzo  * modification, are permitted provided that the following conditions
6*ab1e2860SLuigi Rizzo  * are met:
7*ab1e2860SLuigi Rizzo  *   1. Redistributions of source code must retain the above copyright
8*ab1e2860SLuigi Rizzo  *      notice, this list of conditions and the following disclaimer.
9*ab1e2860SLuigi Rizzo  *   2. Redistributions in binary form must reproduce the above copyright
10*ab1e2860SLuigi Rizzo  *      notice, this list of conditions and the following disclaimer in the
11*ab1e2860SLuigi Rizzo  *    documentation and/or other materials provided with the distribution.
12*ab1e2860SLuigi Rizzo  *
13*ab1e2860SLuigi Rizzo  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14*ab1e2860SLuigi Rizzo  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15*ab1e2860SLuigi Rizzo  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16*ab1e2860SLuigi Rizzo  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17*ab1e2860SLuigi Rizzo  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18*ab1e2860SLuigi Rizzo  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19*ab1e2860SLuigi Rizzo  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20*ab1e2860SLuigi Rizzo  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21*ab1e2860SLuigi Rizzo  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22*ab1e2860SLuigi Rizzo  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23*ab1e2860SLuigi Rizzo  * SUCH DAMAGE.
24*ab1e2860SLuigi Rizzo  */
25*ab1e2860SLuigi Rizzo 
26*ab1e2860SLuigi Rizzo /*
27*ab1e2860SLuigi Rizzo  * $FreeBSD$
28*ab1e2860SLuigi Rizzo  *
29*ab1e2860SLuigi Rizzo  * (New) memory allocator for netmap
30*ab1e2860SLuigi Rizzo  */
31*ab1e2860SLuigi Rizzo 
32*ab1e2860SLuigi Rizzo /*
33*ab1e2860SLuigi Rizzo  * This allocator creates three memory pools:
34*ab1e2860SLuigi Rizzo  *	nm_if_pool	for the struct netmap_if
35*ab1e2860SLuigi Rizzo  *	nm_ring_pool	for the struct netmap_ring
36*ab1e2860SLuigi Rizzo  *	nm_buf_pool	for the packet buffers.
37*ab1e2860SLuigi Rizzo  *
38*ab1e2860SLuigi Rizzo  * that contain netmap objects. Each pool is made of a number of clusters,
39*ab1e2860SLuigi Rizzo  * multiple of a page size, each containing an integer number of objects.
40*ab1e2860SLuigi Rizzo  * The clusters are contiguous in user space but not in the kernel.
41*ab1e2860SLuigi Rizzo  * Only nm_buf_pool needs to be dma-able,
42*ab1e2860SLuigi Rizzo  * but for convenience use the same type of allocator for all.
43*ab1e2860SLuigi Rizzo  *
44*ab1e2860SLuigi Rizzo  * Once mapped, the three pools are exported to userspace
45*ab1e2860SLuigi Rizzo  * as a contiguous block, starting from nm_if_pool. Each
46*ab1e2860SLuigi Rizzo  * cluster (and pool) is an integral number of pages.
47*ab1e2860SLuigi Rizzo  *   [ . . . ][ . . . . . .][ . . . . . . . . . .]
48*ab1e2860SLuigi Rizzo  *    nm_if     nm_ring            nm_buf
49*ab1e2860SLuigi Rizzo  *
50*ab1e2860SLuigi Rizzo  * The userspace areas contain offsets of the objects in userspace.
51*ab1e2860SLuigi Rizzo  * When (at init time) we write these offsets, we find out the index
52*ab1e2860SLuigi Rizzo  * of the object, and from there locate the offset from the beginning
53*ab1e2860SLuigi Rizzo  * of the region.
54*ab1e2860SLuigi Rizzo  *
55*ab1e2860SLuigi Rizzo  * The invididual allocators manage a pool of memory for objects of
56*ab1e2860SLuigi Rizzo  * the same size.
57*ab1e2860SLuigi Rizzo  * The pool is split into smaller clusters, whose size is a
58*ab1e2860SLuigi Rizzo  * multiple of the page size. The cluster size is chosen
59*ab1e2860SLuigi Rizzo  * to minimize the waste for a given max cluster size
60*ab1e2860SLuigi Rizzo  * (we do it by brute force, as we have relatively few objects
61*ab1e2860SLuigi Rizzo  * per cluster).
62*ab1e2860SLuigi Rizzo  *
63*ab1e2860SLuigi Rizzo  * Objects are aligned to the cache line (64 bytes) rounding up object
64*ab1e2860SLuigi Rizzo  * sizes when needed. A bitmap contains the state of each object.
65*ab1e2860SLuigi Rizzo  * Allocation scans the bitmap; this is done only on attach, so we are not
66*ab1e2860SLuigi Rizzo  * too worried about performance
67*ab1e2860SLuigi Rizzo  *
68*ab1e2860SLuigi Rizzo  * For each allocator we can define (thorugh sysctl) the size and
69*ab1e2860SLuigi Rizzo  * number of each object. Memory is allocated at the first use of a
70*ab1e2860SLuigi Rizzo  * netmap file descriptor, and can be freed when all such descriptors
71*ab1e2860SLuigi Rizzo  * have been released (including unmapping the memory).
72*ab1e2860SLuigi Rizzo  * If memory is scarce, the system tries to get as much as possible
73*ab1e2860SLuigi Rizzo  * and the sysctl values reflect the actual allocation.
74*ab1e2860SLuigi Rizzo  * Together with desired values, the sysctl export also absolute
75*ab1e2860SLuigi Rizzo  * min and maximum values that cannot be overridden.
76*ab1e2860SLuigi Rizzo  *
77*ab1e2860SLuigi Rizzo  * struct netmap_if:
78*ab1e2860SLuigi Rizzo  *	variable size, max 16 bytes per ring pair plus some fixed amount.
79*ab1e2860SLuigi Rizzo  *	1024 bytes should be large enough in practice.
80*ab1e2860SLuigi Rizzo  *
81*ab1e2860SLuigi Rizzo  *	In the worst case we have one netmap_if per ring in the system.
82*ab1e2860SLuigi Rizzo  *
83*ab1e2860SLuigi Rizzo  * struct netmap_ring
84*ab1e2860SLuigi Rizzo  *	variable size, 8 byte per slot plus some fixed amount.
85*ab1e2860SLuigi Rizzo  *	Rings can be large (e.g. 4k slots, or >32Kbytes).
86*ab1e2860SLuigi Rizzo  *	We default to 36 KB (9 pages), and a few hundred rings.
87*ab1e2860SLuigi Rizzo  *
88*ab1e2860SLuigi Rizzo  * struct netmap_buffer
89*ab1e2860SLuigi Rizzo  *	The more the better, both because fast interfaces tend to have
90*ab1e2860SLuigi Rizzo  *	many slots, and because we may want to use buffers to store
91*ab1e2860SLuigi Rizzo  *	packets in userspace avoiding copies.
92*ab1e2860SLuigi Rizzo  *	Must contain a full frame (eg 1518, or more for vlans, jumbo
93*ab1e2860SLuigi Rizzo  *	frames etc.) plus be nicely aligned, plus some NICs restrict
94*ab1e2860SLuigi Rizzo  *	the size to multiple of 1K or so. Default to 2K
95*ab1e2860SLuigi Rizzo  */
96*ab1e2860SLuigi Rizzo #ifndef _NET_NETMAP_MEM2_H_
97*ab1e2860SLuigi Rizzo #define _NET_NETMAP_MEM2_H_
98*ab1e2860SLuigi Rizzo 
99*ab1e2860SLuigi Rizzo 
100*ab1e2860SLuigi Rizzo #define NETMAP_BUF_MAX_NUM	20*4096*2	/* large machine */
101*ab1e2860SLuigi Rizzo 
102*ab1e2860SLuigi Rizzo #define NETMAP_POOL_MAX_NAMSZ	32
103*ab1e2860SLuigi Rizzo 
104*ab1e2860SLuigi Rizzo 
105*ab1e2860SLuigi Rizzo enum {
106*ab1e2860SLuigi Rizzo 	NETMAP_IF_POOL   = 0,
107*ab1e2860SLuigi Rizzo 	NETMAP_RING_POOL,
108*ab1e2860SLuigi Rizzo 	NETMAP_BUF_POOL,
109*ab1e2860SLuigi Rizzo 	NETMAP_POOLS_NR
110*ab1e2860SLuigi Rizzo };
111*ab1e2860SLuigi Rizzo 
112*ab1e2860SLuigi Rizzo 
113*ab1e2860SLuigi Rizzo struct netmap_obj_params {
114*ab1e2860SLuigi Rizzo 	u_int size;
115*ab1e2860SLuigi Rizzo 	u_int num;
116*ab1e2860SLuigi Rizzo };
117*ab1e2860SLuigi Rizzo struct netmap_obj_pool {
118*ab1e2860SLuigi Rizzo 	char name[NETMAP_POOL_MAX_NAMSZ];	/* name of the allocator */
119*ab1e2860SLuigi Rizzo 
120*ab1e2860SLuigi Rizzo 	/* ---------------------------------------------------*/
121*ab1e2860SLuigi Rizzo 	/* these are only meaningful if the pool is finalized */
122*ab1e2860SLuigi Rizzo 	/* (see 'finalized' field in netmap_mem_d)            */
123*ab1e2860SLuigi Rizzo 	u_int objtotal;         /* actual total number of objects. */
124*ab1e2860SLuigi Rizzo 	u_int memtotal;		/* actual total memory space */
125*ab1e2860SLuigi Rizzo 	u_int numclusters;	/* actual number of clusters */
126*ab1e2860SLuigi Rizzo 
127*ab1e2860SLuigi Rizzo 	u_int objfree;          /* number of free objects. */
128*ab1e2860SLuigi Rizzo 
129*ab1e2860SLuigi Rizzo 	struct lut_entry *lut;  /* virt,phys addresses, objtotal entries */
130*ab1e2860SLuigi Rizzo 	uint32_t *bitmap;       /* one bit per buffer, 1 means free */
131*ab1e2860SLuigi Rizzo 	uint32_t bitmap_slots;	/* number of uint32 entries in bitmap */
132*ab1e2860SLuigi Rizzo 	/* ---------------------------------------------------*/
133*ab1e2860SLuigi Rizzo 
134*ab1e2860SLuigi Rizzo 	/* limits */
135*ab1e2860SLuigi Rizzo 	u_int objminsize;	/* minimum object size */
136*ab1e2860SLuigi Rizzo 	u_int objmaxsize;	/* maximum object size */
137*ab1e2860SLuigi Rizzo 	u_int nummin;		/* minimum number of objects */
138*ab1e2860SLuigi Rizzo 	u_int nummax;		/* maximum number of objects */
139*ab1e2860SLuigi Rizzo 
140*ab1e2860SLuigi Rizzo 	/* these are changed only by config */
141*ab1e2860SLuigi Rizzo 	u_int _objtotal;	/* total number of objects */
142*ab1e2860SLuigi Rizzo 	u_int _objsize;		/* object size */
143*ab1e2860SLuigi Rizzo 	u_int _clustsize;       /* cluster size */
144*ab1e2860SLuigi Rizzo 	u_int _clustentries;    /* objects per cluster */
145*ab1e2860SLuigi Rizzo 	u_int _numclusters;	/* number of clusters */
146*ab1e2860SLuigi Rizzo 
147*ab1e2860SLuigi Rizzo 	/* requested values */
148*ab1e2860SLuigi Rizzo 	u_int r_objtotal;
149*ab1e2860SLuigi Rizzo 	u_int r_objsize;
150*ab1e2860SLuigi Rizzo };
151*ab1e2860SLuigi Rizzo 
152*ab1e2860SLuigi Rizzo #ifdef linux
153*ab1e2860SLuigi Rizzo // XXX a mtx would suffice here 20130415 lr
154*ab1e2860SLuigi Rizzo #define NMA_LOCK_T		struct semaphore
155*ab1e2860SLuigi Rizzo #else /* !linux */
156*ab1e2860SLuigi Rizzo #define NMA_LOCK_T		struct mtx
157*ab1e2860SLuigi Rizzo #endif /* linux */
158*ab1e2860SLuigi Rizzo 
159*ab1e2860SLuigi Rizzo typedef int (*netmap_mem_config_t)(struct netmap_mem_d*);
160*ab1e2860SLuigi Rizzo typedef int (*netmap_mem_finalize_t)(struct netmap_mem_d*);
161*ab1e2860SLuigi Rizzo typedef void (*netmap_mem_deref_t)(struct netmap_mem_d*);
162*ab1e2860SLuigi Rizzo 
163*ab1e2860SLuigi Rizzo 
164*ab1e2860SLuigi Rizzo /* We implement two kinds of netmap_mem_d structures:
165*ab1e2860SLuigi Rizzo  *
166*ab1e2860SLuigi Rizzo  * - global: used by hardware NICS;
167*ab1e2860SLuigi Rizzo  *
168*ab1e2860SLuigi Rizzo  * - private: used by VALE ports.
169*ab1e2860SLuigi Rizzo  *
170*ab1e2860SLuigi Rizzo  * In both cases, the netmap_mem_d structure has the same lifetime as the
171*ab1e2860SLuigi Rizzo  * netmap_adapter of the corresponding NIC or port. It is the responsibility of
172*ab1e2860SLuigi Rizzo  * the client code to delete the private allocator when the associated
173*ab1e2860SLuigi Rizzo  * netmap_adapter is freed (this is implemented by the NAF_MEM_OWNER flag in
174*ab1e2860SLuigi Rizzo  * netmap.c).  The 'refcount' field counts the number of active users of the
175*ab1e2860SLuigi Rizzo  * structure. The global allocator uses this information to prevent/allow
176*ab1e2860SLuigi Rizzo  * reconfiguration. The private allocators release all their memory when there
177*ab1e2860SLuigi Rizzo  * are no active users.  By 'active user' we mean an existing netmap_priv
178*ab1e2860SLuigi Rizzo  * structure holding a reference to the allocator.
179*ab1e2860SLuigi Rizzo  */
180*ab1e2860SLuigi Rizzo struct netmap_mem_d {
181*ab1e2860SLuigi Rizzo 	NMA_LOCK_T nm_mtx;  /* protect the allocator */
182*ab1e2860SLuigi Rizzo 	u_int nm_totalsize; /* shorthand */
183*ab1e2860SLuigi Rizzo 
184*ab1e2860SLuigi Rizzo 	u_int flags;
185*ab1e2860SLuigi Rizzo #define NETMAP_MEM_FINALIZED	0x1	/* preallocation done */
186*ab1e2860SLuigi Rizzo #define NETMAP_MEM_PRIVATE	0x2	/* uses private address space */
187*ab1e2860SLuigi Rizzo 	int lasterr;		/* last error for curr config */
188*ab1e2860SLuigi Rizzo 	int refcount;		/* existing priv structures */
189*ab1e2860SLuigi Rizzo 	/* the three allocators */
190*ab1e2860SLuigi Rizzo 	struct netmap_obj_pool pools[NETMAP_POOLS_NR];
191*ab1e2860SLuigi Rizzo 
192*ab1e2860SLuigi Rizzo 	netmap_mem_config_t   config;
193*ab1e2860SLuigi Rizzo 	netmap_mem_finalize_t finalize;
194*ab1e2860SLuigi Rizzo 	netmap_mem_deref_t    deref;
195*ab1e2860SLuigi Rizzo };
196*ab1e2860SLuigi Rizzo 
197*ab1e2860SLuigi Rizzo extern struct netmap_mem_d nm_mem;
198*ab1e2860SLuigi Rizzo 
199*ab1e2860SLuigi Rizzo vm_paddr_t netmap_mem_ofstophys(struct netmap_mem_d *, vm_ooffset_t);
200*ab1e2860SLuigi Rizzo int	   netmap_mem_finalize(struct netmap_mem_d *);
201*ab1e2860SLuigi Rizzo int 	   netmap_mem_init(void);
202*ab1e2860SLuigi Rizzo void 	   netmap_mem_fini(void);
203*ab1e2860SLuigi Rizzo struct netmap_if *   netmap_mem_if_new(const char *, struct netmap_adapter *);
204*ab1e2860SLuigi Rizzo void 	   netmap_mem_if_delete(struct netmap_adapter *na, struct netmap_if *nifp);
205*ab1e2860SLuigi Rizzo void 	   netmap_mem_deref(struct netmap_mem_d *);
206*ab1e2860SLuigi Rizzo int	   netmap_mem_get_info(struct netmap_mem_d *nm_mem, u_int *size, u_int *memflags);
207*ab1e2860SLuigi Rizzo ssize_t    netmap_mem_if_offset(struct netmap_mem_d *nm_mem, const void *vaddr);
208*ab1e2860SLuigi Rizzo struct netmap_mem_d*
209*ab1e2860SLuigi Rizzo 	   netmap_mem_private_new(const char *name, u_int txr, u_int txd, u_int rxr, u_int rxd);
210*ab1e2860SLuigi Rizzo void	   netmap_mem_private_delete(struct netmap_mem_d *nm_mem);
211*ab1e2860SLuigi Rizzo 
212*ab1e2860SLuigi Rizzo #define NETMAP_BDG_BUF_SIZE(n)	((n)->pools[NETMAP_BUF_POOL]._objsize)
213*ab1e2860SLuigi Rizzo 
214*ab1e2860SLuigi Rizzo 
215*ab1e2860SLuigi Rizzo 
216*ab1e2860SLuigi Rizzo #endif
217