xref: /freebsd/sys/dev/netmap/netmap_vale.c (revision 39ee7a7a6bdd1557b1c3532abf60d139798ac88b)
1 /*
2  * Copyright (C) 2013-2014 Universita` di Pisa. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *   1. Redistributions of source code must retain the above copyright
8  *      notice, this list of conditions and the following disclaimer.
9  *   2. Redistributions in binary form must reproduce the above copyright
10  *      notice, this list of conditions and the following disclaimer in the
11  *      documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23  * SUCH DAMAGE.
24  */
25 
26 
27 /*
28  * This module implements the VALE switch for netmap
29 
30 --- VALE SWITCH ---
31 
32 NMG_LOCK() serializes all modifications to switches and ports.
33 A switch cannot be deleted until all ports are gone.
34 
35 For each switch, an SX lock (RWlock on linux) protects
36 deletion of ports. When configuring or deleting a new port, the
37 lock is acquired in exclusive mode (after holding NMG_LOCK).
38 When forwarding, the lock is acquired in shared mode (without NMG_LOCK).
39 The lock is held throughout the entire forwarding cycle,
40 during which the thread may incur in a page fault.
41 Hence it is important that sleepable shared locks are used.
42 
43 On the rx ring, the per-port lock is grabbed initially to reserve
44 a number of slot in the ring, then the lock is released,
45 packets are copied from source to destination, and then
46 the lock is acquired again and the receive ring is updated.
47 (A similar thing is done on the tx ring for NIC and host stack
48 ports attached to the switch)
49 
50  */
51 
52 /*
53  * OS-specific code that is used only within this file.
54  * Other OS-specific code that must be accessed by drivers
55  * is present in netmap_kern.h
56  */
57 
58 #if defined(__FreeBSD__)
59 #include <sys/cdefs.h> /* prerequisite */
60 __FBSDID("$FreeBSD$");
61 
62 #include <sys/types.h>
63 #include <sys/errno.h>
64 #include <sys/param.h>	/* defines used in kernel.h */
65 #include <sys/kernel.h>	/* types used in module initialization */
66 #include <sys/conf.h>	/* cdevsw struct, UID, GID */
67 #include <sys/sockio.h>
68 #include <sys/socketvar.h>	/* struct socket */
69 #include <sys/malloc.h>
70 #include <sys/poll.h>
71 #include <sys/rwlock.h>
72 #include <sys/socket.h> /* sockaddrs */
73 #include <sys/selinfo.h>
74 #include <sys/sysctl.h>
75 #include <net/if.h>
76 #include <net/if_var.h>
77 #include <net/bpf.h>		/* BIOCIMMEDIATE */
78 #include <machine/bus.h>	/* bus_dmamap_* */
79 #include <sys/endian.h>
80 #include <sys/refcount.h>
81 
82 
83 #define BDG_RWLOCK_T		struct rwlock // struct rwlock
84 
85 #define	BDG_RWINIT(b)		\
86 	rw_init_flags(&(b)->bdg_lock, "bdg lock", RW_NOWITNESS)
87 #define BDG_WLOCK(b)		rw_wlock(&(b)->bdg_lock)
88 #define BDG_WUNLOCK(b)		rw_wunlock(&(b)->bdg_lock)
89 #define BDG_RLOCK(b)		rw_rlock(&(b)->bdg_lock)
90 #define BDG_RTRYLOCK(b)		rw_try_rlock(&(b)->bdg_lock)
91 #define BDG_RUNLOCK(b)		rw_runlock(&(b)->bdg_lock)
92 #define BDG_RWDESTROY(b)	rw_destroy(&(b)->bdg_lock)
93 
94 
95 #elif defined(linux)
96 
97 #include "bsd_glue.h"
98 
99 #elif defined(__APPLE__)
100 
101 #warning OSX support is only partial
102 #include "osx_glue.h"
103 
104 #else
105 
106 #error	Unsupported platform
107 
108 #endif /* unsupported */
109 
110 /*
111  * common headers
112  */
113 
114 #include <net/netmap.h>
115 #include <dev/netmap/netmap_kern.h>
116 #include <dev/netmap/netmap_mem2.h>
117 
118 #ifdef WITH_VALE
119 
120 /*
121  * system parameters (most of them in netmap_kern.h)
122  * NM_NAME	prefix for switch port names, default "vale"
123  * NM_BDG_MAXPORTS	number of ports
124  * NM_BRIDGES	max number of switches in the system.
125  *	XXX should become a sysctl or tunable
126  *
127  * Switch ports are named valeX:Y where X is the switch name and Y
128  * is the port. If Y matches a physical interface name, the port is
129  * connected to a physical device.
130  *
131  * Unlike physical interfaces, switch ports use their own memory region
132  * for rings and buffers.
133  * The virtual interfaces use per-queue lock instead of core lock.
134  * In the tx loop, we aggregate traffic in batches to make all operations
135  * faster. The batch size is bridge_batch.
136  */
137 #define NM_BDG_MAXRINGS		16	/* XXX unclear how many. */
138 #define NM_BDG_MAXSLOTS		4096	/* XXX same as above */
139 #define NM_BRIDGE_RINGSIZE	1024	/* in the device */
140 #define NM_BDG_HASH		1024	/* forwarding table entries */
141 #define NM_BDG_BATCH		1024	/* entries in the forwarding buffer */
142 #define NM_MULTISEG		64	/* max size of a chain of bufs */
143 /* actual size of the tables */
144 #define NM_BDG_BATCH_MAX	(NM_BDG_BATCH + NM_MULTISEG)
145 /* NM_FT_NULL terminates a list of slots in the ft */
146 #define NM_FT_NULL		NM_BDG_BATCH_MAX
147 #define	NM_BRIDGES		8	/* number of bridges */
148 
149 
150 /*
151  * bridge_batch is set via sysctl to the max batch size to be
152  * used in the bridge. The actual value may be larger as the
153  * last packet in the block may overflow the size.
154  */
155 int bridge_batch = NM_BDG_BATCH; /* bridge batch size */
156 SYSCTL_DECL(_dev_netmap);
157 SYSCTL_INT(_dev_netmap, OID_AUTO, bridge_batch, CTLFLAG_RW, &bridge_batch, 0 , "");
158 
159 
160 static int netmap_vp_create(struct nmreq *, struct ifnet *, struct netmap_vp_adapter **);
161 static int netmap_vp_reg(struct netmap_adapter *na, int onoff);
162 static int netmap_bwrap_register(struct netmap_adapter *, int onoff);
163 
164 /*
165  * For each output interface, nm_bdg_q is used to construct a list.
166  * bq_len is the number of output buffers (we can have coalescing
167  * during the copy).
168  */
169 struct nm_bdg_q {
170 	uint16_t bq_head;
171 	uint16_t bq_tail;
172 	uint32_t bq_len;	/* number of buffers */
173 };
174 
175 /* XXX revise this */
176 struct nm_hash_ent {
177 	uint64_t	mac;	/* the top 2 bytes are the epoch */
178 	uint64_t	ports;
179 };
180 
181 /*
182  * nm_bridge is a descriptor for a VALE switch.
183  * Interfaces for a bridge are all in bdg_ports[].
184  * The array has fixed size, an empty entry does not terminate
185  * the search, but lookups only occur on attach/detach so we
186  * don't mind if they are slow.
187  *
188  * The bridge is non blocking on the transmit ports: excess
189  * packets are dropped if there is no room on the output port.
190  *
191  * bdg_lock protects accesses to the bdg_ports array.
192  * This is a rw lock (or equivalent).
193  */
194 struct nm_bridge {
195 	/* XXX what is the proper alignment/layout ? */
196 	BDG_RWLOCK_T	bdg_lock;	/* protects bdg_ports */
197 	int		bdg_namelen;
198 	uint32_t	bdg_active_ports; /* 0 means free */
199 	char		bdg_basename[IFNAMSIZ];
200 
201 	/* Indexes of active ports (up to active_ports)
202 	 * and all other remaining ports.
203 	 */
204 	uint8_t		bdg_port_index[NM_BDG_MAXPORTS];
205 
206 	struct netmap_vp_adapter *bdg_ports[NM_BDG_MAXPORTS];
207 
208 
209 	/*
210 	 * The function to decide the destination port.
211 	 * It returns either of an index of the destination port,
212 	 * NM_BDG_BROADCAST to broadcast this packet, or NM_BDG_NOPORT not to
213 	 * forward this packet.  ring_nr is the source ring index, and the
214 	 * function may overwrite this value to forward this packet to a
215 	 * different ring index.
216 	 * This function must be set by netmap_bdgctl().
217 	 */
218 	struct netmap_bdg_ops bdg_ops;
219 
220 	/* the forwarding table, MAC+ports.
221 	 * XXX should be changed to an argument to be passed to
222 	 * the lookup function, and allocated on attach
223 	 */
224 	struct nm_hash_ent ht[NM_BDG_HASH];
225 
226 #ifdef CONFIG_NET_NS
227 	struct net *ns;
228 #endif /* CONFIG_NET_NS */
229 };
230 
231 const char*
232 netmap_bdg_name(struct netmap_vp_adapter *vp)
233 {
234 	struct nm_bridge *b = vp->na_bdg;
235 	if (b == NULL)
236 		return NULL;
237 	return b->bdg_basename;
238 }
239 
240 
241 #ifndef CONFIG_NET_NS
242 /*
243  * XXX in principle nm_bridges could be created dynamically
244  * Right now we have a static array and deletions are protected
245  * by an exclusive lock.
246  */
247 struct nm_bridge *nm_bridges;
248 #endif /* !CONFIG_NET_NS */
249 
250 
251 /*
252  * this is a slightly optimized copy routine which rounds
253  * to multiple of 64 bytes and is often faster than dealing
254  * with other odd sizes. We assume there is enough room
255  * in the source and destination buffers.
256  *
257  * XXX only for multiples of 64 bytes, non overlapped.
258  */
259 static inline void
260 pkt_copy(void *_src, void *_dst, int l)
261 {
262         uint64_t *src = _src;
263         uint64_t *dst = _dst;
264         if (unlikely(l >= 1024)) {
265                 memcpy(dst, src, l);
266                 return;
267         }
268         for (; likely(l > 0); l-=64) {
269                 *dst++ = *src++;
270                 *dst++ = *src++;
271                 *dst++ = *src++;
272                 *dst++ = *src++;
273                 *dst++ = *src++;
274                 *dst++ = *src++;
275                 *dst++ = *src++;
276                 *dst++ = *src++;
277         }
278 }
279 
280 
281 /*
282  * locate a bridge among the existing ones.
283  * MUST BE CALLED WITH NMG_LOCK()
284  *
285  * a ':' in the name terminates the bridge name. Otherwise, just NM_NAME.
286  * We assume that this is called with a name of at least NM_NAME chars.
287  */
288 static struct nm_bridge *
289 nm_find_bridge(const char *name, int create)
290 {
291 	int i, l, namelen;
292 	struct nm_bridge *b = NULL, *bridges;
293 	u_int num_bridges;
294 
295 	NMG_LOCK_ASSERT();
296 
297 	netmap_bns_getbridges(&bridges, &num_bridges);
298 
299 	namelen = strlen(NM_NAME);	/* base length */
300 	l = name ? strlen(name) : 0;		/* actual length */
301 	if (l < namelen) {
302 		D("invalid bridge name %s", name ? name : NULL);
303 		return NULL;
304 	}
305 	for (i = namelen + 1; i < l; i++) {
306 		if (name[i] == ':') {
307 			namelen = i;
308 			break;
309 		}
310 	}
311 	if (namelen >= IFNAMSIZ)
312 		namelen = IFNAMSIZ;
313 	ND("--- prefix is '%.*s' ---", namelen, name);
314 
315 	/* lookup the name, remember empty slot if there is one */
316 	for (i = 0; i < num_bridges; i++) {
317 		struct nm_bridge *x = bridges + i;
318 
319 		if (x->bdg_active_ports == 0) {
320 			if (create && b == NULL)
321 				b = x;	/* record empty slot */
322 		} else if (x->bdg_namelen != namelen) {
323 			continue;
324 		} else if (strncmp(name, x->bdg_basename, namelen) == 0) {
325 			ND("found '%.*s' at %d", namelen, name, i);
326 			b = x;
327 			break;
328 		}
329 	}
330 	if (i == num_bridges && b) { /* name not found, can create entry */
331 		/* initialize the bridge */
332 		strncpy(b->bdg_basename, name, namelen);
333 		ND("create new bridge %s with ports %d", b->bdg_basename,
334 			b->bdg_active_ports);
335 		b->bdg_namelen = namelen;
336 		b->bdg_active_ports = 0;
337 		for (i = 0; i < NM_BDG_MAXPORTS; i++)
338 			b->bdg_port_index[i] = i;
339 		/* set the default function */
340 		b->bdg_ops.lookup = netmap_bdg_learning;
341 		/* reset the MAC address table */
342 		bzero(b->ht, sizeof(struct nm_hash_ent) * NM_BDG_HASH);
343 		NM_BNS_GET(b);
344 	}
345 	return b;
346 }
347 
348 
349 /*
350  * Free the forwarding tables for rings attached to switch ports.
351  */
352 static void
353 nm_free_bdgfwd(struct netmap_adapter *na)
354 {
355 	int nrings, i;
356 	struct netmap_kring *kring;
357 
358 	NMG_LOCK_ASSERT();
359 	nrings = na->num_tx_rings;
360 	kring = na->tx_rings;
361 	for (i = 0; i < nrings; i++) {
362 		if (kring[i].nkr_ft) {
363 			free(kring[i].nkr_ft, M_DEVBUF);
364 			kring[i].nkr_ft = NULL; /* protect from freeing twice */
365 		}
366 	}
367 }
368 
369 
370 /*
371  * Allocate the forwarding tables for the rings attached to the bridge ports.
372  */
373 static int
374 nm_alloc_bdgfwd(struct netmap_adapter *na)
375 {
376 	int nrings, l, i, num_dstq;
377 	struct netmap_kring *kring;
378 
379 	NMG_LOCK_ASSERT();
380 	/* all port:rings + broadcast */
381 	num_dstq = NM_BDG_MAXPORTS * NM_BDG_MAXRINGS + 1;
382 	l = sizeof(struct nm_bdg_fwd) * NM_BDG_BATCH_MAX;
383 	l += sizeof(struct nm_bdg_q) * num_dstq;
384 	l += sizeof(uint16_t) * NM_BDG_BATCH_MAX;
385 
386 	nrings = netmap_real_rings(na, NR_TX);
387 	kring = na->tx_rings;
388 	for (i = 0; i < nrings; i++) {
389 		struct nm_bdg_fwd *ft;
390 		struct nm_bdg_q *dstq;
391 		int j;
392 
393 		ft = malloc(l, M_DEVBUF, M_NOWAIT | M_ZERO);
394 		if (!ft) {
395 			nm_free_bdgfwd(na);
396 			return ENOMEM;
397 		}
398 		dstq = (struct nm_bdg_q *)(ft + NM_BDG_BATCH_MAX);
399 		for (j = 0; j < num_dstq; j++) {
400 			dstq[j].bq_head = dstq[j].bq_tail = NM_FT_NULL;
401 			dstq[j].bq_len = 0;
402 		}
403 		kring[i].nkr_ft = ft;
404 	}
405 	return 0;
406 }
407 
408 
409 /* remove from bridge b the ports in slots hw and sw
410  * (sw can be -1 if not needed)
411  */
412 static void
413 netmap_bdg_detach_common(struct nm_bridge *b, int hw, int sw)
414 {
415 	int s_hw = hw, s_sw = sw;
416 	int i, lim =b->bdg_active_ports;
417 	uint8_t tmp[NM_BDG_MAXPORTS];
418 
419 	/*
420 	New algorithm:
421 	make a copy of bdg_port_index;
422 	lookup NA(ifp)->bdg_port and SWNA(ifp)->bdg_port
423 	in the array of bdg_port_index, replacing them with
424 	entries from the bottom of the array;
425 	decrement bdg_active_ports;
426 	acquire BDG_WLOCK() and copy back the array.
427 	 */
428 
429 	if (netmap_verbose)
430 		D("detach %d and %d (lim %d)", hw, sw, lim);
431 	/* make a copy of the list of active ports, update it,
432 	 * and then copy back within BDG_WLOCK().
433 	 */
434 	memcpy(tmp, b->bdg_port_index, sizeof(tmp));
435 	for (i = 0; (hw >= 0 || sw >= 0) && i < lim; ) {
436 		if (hw >= 0 && tmp[i] == hw) {
437 			ND("detach hw %d at %d", hw, i);
438 			lim--; /* point to last active port */
439 			tmp[i] = tmp[lim]; /* swap with i */
440 			tmp[lim] = hw;	/* now this is inactive */
441 			hw = -1;
442 		} else if (sw >= 0 && tmp[i] == sw) {
443 			ND("detach sw %d at %d", sw, i);
444 			lim--;
445 			tmp[i] = tmp[lim];
446 			tmp[lim] = sw;
447 			sw = -1;
448 		} else {
449 			i++;
450 		}
451 	}
452 	if (hw >= 0 || sw >= 0) {
453 		D("XXX delete failed hw %d sw %d, should panic...", hw, sw);
454 	}
455 
456 	BDG_WLOCK(b);
457 	if (b->bdg_ops.dtor)
458 		b->bdg_ops.dtor(b->bdg_ports[s_hw]);
459 	b->bdg_ports[s_hw] = NULL;
460 	if (s_sw >= 0) {
461 		b->bdg_ports[s_sw] = NULL;
462 	}
463 	memcpy(b->bdg_port_index, tmp, sizeof(tmp));
464 	b->bdg_active_ports = lim;
465 	BDG_WUNLOCK(b);
466 
467 	ND("now %d active ports", lim);
468 	if (lim == 0) {
469 		ND("marking bridge %s as free", b->bdg_basename);
470 		bzero(&b->bdg_ops, sizeof(b->bdg_ops));
471 		NM_BNS_PUT(b);
472 	}
473 }
474 
475 /* nm_bdg_ctl callback for VALE ports */
476 static int
477 netmap_vp_bdg_ctl(struct netmap_adapter *na, struct nmreq *nmr, int attach)
478 {
479 	struct netmap_vp_adapter *vpna = (struct netmap_vp_adapter *)na;
480 	struct nm_bridge *b = vpna->na_bdg;
481 
482 	if (attach)
483 		return 0; /* nothing to do */
484 	if (b) {
485 		netmap_set_all_rings(na, 0 /* disable */);
486 		netmap_bdg_detach_common(b, vpna->bdg_port, -1);
487 		vpna->na_bdg = NULL;
488 		netmap_set_all_rings(na, 1 /* enable */);
489 	}
490 	/* I have took reference just for attach */
491 	netmap_adapter_put(na);
492 	return 0;
493 }
494 
495 /* nm_dtor callback for ephemeral VALE ports */
496 static void
497 netmap_vp_dtor(struct netmap_adapter *na)
498 {
499 	struct netmap_vp_adapter *vpna = (struct netmap_vp_adapter*)na;
500 	struct nm_bridge *b = vpna->na_bdg;
501 
502 	ND("%s has %d references", na->name, na->na_refcount);
503 
504 	if (b) {
505 		netmap_bdg_detach_common(b, vpna->bdg_port, -1);
506 	}
507 }
508 
509 /* remove a persistent VALE port from the system */
510 static int
511 nm_vi_destroy(const char *name)
512 {
513 	struct ifnet *ifp;
514 	int error;
515 
516 	ifp = ifunit_ref(name);
517 	if (!ifp)
518 		return ENXIO;
519 	NMG_LOCK();
520 	/* make sure this is actually a VALE port */
521 	if (!NETMAP_CAPABLE(ifp) || NA(ifp)->nm_register != netmap_vp_reg) {
522 		error = EINVAL;
523 		goto err;
524 	}
525 
526 	if (NA(ifp)->na_refcount > 1) {
527 		error = EBUSY;
528 		goto err;
529 	}
530 	NMG_UNLOCK();
531 
532 	D("destroying a persistent vale interface %s", ifp->if_xname);
533 	/* Linux requires all the references are released
534 	 * before unregister
535 	 */
536 	if_rele(ifp);
537 	netmap_detach(ifp);
538 	nm_vi_detach(ifp);
539 	return 0;
540 
541 err:
542 	NMG_UNLOCK();
543 	if_rele(ifp);
544 	return error;
545 }
546 
547 /*
548  * Create a virtual interface registered to the system.
549  * The interface will be attached to a bridge later.
550  */
551 static int
552 nm_vi_create(struct nmreq *nmr)
553 {
554 	struct ifnet *ifp;
555 	struct netmap_vp_adapter *vpna;
556 	int error;
557 
558 	/* don't include VALE prefix */
559 	if (!strncmp(nmr->nr_name, NM_NAME, strlen(NM_NAME)))
560 		return EINVAL;
561 	ifp = ifunit_ref(nmr->nr_name);
562 	if (ifp) { /* already exist, cannot create new one */
563 		if_rele(ifp);
564 		return EEXIST;
565 	}
566 	error = nm_vi_persist(nmr->nr_name, &ifp);
567 	if (error)
568 		return error;
569 
570 	NMG_LOCK();
571 	/* netmap_vp_create creates a struct netmap_vp_adapter */
572 	error = netmap_vp_create(nmr, ifp, &vpna);
573 	if (error) {
574 		D("error %d", error);
575 		nm_vi_detach(ifp);
576 		return error;
577 	}
578 	/* persist-specific routines */
579 	vpna->up.nm_bdg_ctl = netmap_vp_bdg_ctl;
580 	netmap_adapter_get(&vpna->up);
581 	NMG_UNLOCK();
582 	D("created %s", ifp->if_xname);
583 	return 0;
584 }
585 
586 /* Try to get a reference to a netmap adapter attached to a VALE switch.
587  * If the adapter is found (or is created), this function returns 0, a
588  * non NULL pointer is returned into *na, and the caller holds a
589  * reference to the adapter.
590  * If an adapter is not found, then no reference is grabbed and the
591  * function returns an error code, or 0 if there is just a VALE prefix
592  * mismatch. Therefore the caller holds a reference when
593  * (*na != NULL && return == 0).
594  */
595 int
596 netmap_get_bdg_na(struct nmreq *nmr, struct netmap_adapter **na, int create)
597 {
598 	char *nr_name = nmr->nr_name;
599 	const char *ifname;
600 	struct ifnet *ifp;
601 	int error = 0;
602 	struct netmap_vp_adapter *vpna, *hostna = NULL;
603 	struct nm_bridge *b;
604 	int i, j, cand = -1, cand2 = -1;
605 	int needed;
606 
607 	*na = NULL;     /* default return value */
608 
609 	/* first try to see if this is a bridge port. */
610 	NMG_LOCK_ASSERT();
611 	if (strncmp(nr_name, NM_NAME, sizeof(NM_NAME) - 1)) {
612 		return 0;  /* no error, but no VALE prefix */
613 	}
614 
615 	b = nm_find_bridge(nr_name, create);
616 	if (b == NULL) {
617 		D("no bridges available for '%s'", nr_name);
618 		return (create ? ENOMEM : ENXIO);
619 	}
620 	if (strlen(nr_name) < b->bdg_namelen) /* impossible */
621 		panic("x");
622 
623 	/* Now we are sure that name starts with the bridge's name,
624 	 * lookup the port in the bridge. We need to scan the entire
625 	 * list. It is not important to hold a WLOCK on the bridge
626 	 * during the search because NMG_LOCK already guarantees
627 	 * that there are no other possible writers.
628 	 */
629 
630 	/* lookup in the local list of ports */
631 	for (j = 0; j < b->bdg_active_ports; j++) {
632 		i = b->bdg_port_index[j];
633 		vpna = b->bdg_ports[i];
634 		// KASSERT(na != NULL);
635 		ND("checking %s", vpna->up.name);
636 		if (!strcmp(vpna->up.name, nr_name)) {
637 			netmap_adapter_get(&vpna->up);
638 			ND("found existing if %s refs %d", nr_name)
639 			*na = &vpna->up;
640 			return 0;
641 		}
642 	}
643 	/* not found, should we create it? */
644 	if (!create)
645 		return ENXIO;
646 	/* yes we should, see if we have space to attach entries */
647 	needed = 2; /* in some cases we only need 1 */
648 	if (b->bdg_active_ports + needed >= NM_BDG_MAXPORTS) {
649 		D("bridge full %d, cannot create new port", b->bdg_active_ports);
650 		return ENOMEM;
651 	}
652 	/* record the next two ports available, but do not allocate yet */
653 	cand = b->bdg_port_index[b->bdg_active_ports];
654 	cand2 = b->bdg_port_index[b->bdg_active_ports + 1];
655 	ND("+++ bridge %s port %s used %d avail %d %d",
656 		b->bdg_basename, ifname, b->bdg_active_ports, cand, cand2);
657 
658 	/*
659 	 * try see if there is a matching NIC with this name
660 	 * (after the bridge's name)
661 	 */
662 	ifname = nr_name + b->bdg_namelen + 1;
663 	ifp = ifunit_ref(ifname);
664 	if (!ifp) {
665 		/* Create an ephemeral virtual port
666 		 * This block contains all the ephemeral-specific logics
667 		 */
668 		if (nmr->nr_cmd) {
669 			/* nr_cmd must be 0 for a virtual port */
670 			return EINVAL;
671 		}
672 
673 		/* bdg_netmap_attach creates a struct netmap_adapter */
674 		error = netmap_vp_create(nmr, NULL, &vpna);
675 		if (error) {
676 			D("error %d", error);
677 			free(ifp, M_DEVBUF);
678 			return error;
679 		}
680 		/* shortcut - we can skip get_hw_na(),
681 		 * ownership check and nm_bdg_attach()
682 		 */
683 	} else {
684 		struct netmap_adapter *hw;
685 
686 		error = netmap_get_hw_na(ifp, &hw);
687 		if (error || hw == NULL)
688 			goto out;
689 
690 		/* host adapter might not be created */
691 		error = hw->nm_bdg_attach(nr_name, hw);
692 		if (error)
693 			goto out;
694 		vpna = hw->na_vp;
695 		hostna = hw->na_hostvp;
696 		if_rele(ifp);
697 		if (nmr->nr_arg1 != NETMAP_BDG_HOST)
698 			hostna = NULL;
699 	}
700 
701 	BDG_WLOCK(b);
702 	vpna->bdg_port = cand;
703 	ND("NIC  %p to bridge port %d", vpna, cand);
704 	/* bind the port to the bridge (virtual ports are not active) */
705 	b->bdg_ports[cand] = vpna;
706 	vpna->na_bdg = b;
707 	b->bdg_active_ports++;
708 	if (hostna != NULL) {
709 		/* also bind the host stack to the bridge */
710 		b->bdg_ports[cand2] = hostna;
711 		hostna->bdg_port = cand2;
712 		hostna->na_bdg = b;
713 		b->bdg_active_ports++;
714 		ND("host %p to bridge port %d", hostna, cand2);
715 	}
716 	ND("if %s refs %d", ifname, vpna->up.na_refcount);
717 	BDG_WUNLOCK(b);
718 	*na = &vpna->up;
719 	netmap_adapter_get(*na);
720 	return 0;
721 
722 out:
723 	if_rele(ifp);
724 
725 	return error;
726 }
727 
728 
729 /* Process NETMAP_BDG_ATTACH */
730 static int
731 nm_bdg_ctl_attach(struct nmreq *nmr)
732 {
733 	struct netmap_adapter *na;
734 	int error;
735 
736 	NMG_LOCK();
737 
738 	error = netmap_get_bdg_na(nmr, &na, 1 /* create if not exists */);
739 	if (error) /* no device */
740 		goto unlock_exit;
741 
742 	if (na == NULL) { /* VALE prefix missing */
743 		error = EINVAL;
744 		goto unlock_exit;
745 	}
746 
747 	if (NETMAP_OWNED_BY_ANY(na)) {
748 		error = EBUSY;
749 		goto unref_exit;
750 	}
751 
752 	if (na->nm_bdg_ctl) {
753 		/* nop for VALE ports. The bwrap needs to put the hwna
754 		 * in netmap mode (see netmap_bwrap_bdg_ctl)
755 		 */
756 		error = na->nm_bdg_ctl(na, nmr, 1);
757 		if (error)
758 			goto unref_exit;
759 		ND("registered %s to netmap-mode", na->name);
760 	}
761 	NMG_UNLOCK();
762 	return 0;
763 
764 unref_exit:
765 	netmap_adapter_put(na);
766 unlock_exit:
767 	NMG_UNLOCK();
768 	return error;
769 }
770 
771 
772 /* process NETMAP_BDG_DETACH */
773 static int
774 nm_bdg_ctl_detach(struct nmreq *nmr)
775 {
776 	struct netmap_adapter *na;
777 	int error;
778 
779 	NMG_LOCK();
780 	error = netmap_get_bdg_na(nmr, &na, 0 /* don't create */);
781 	if (error) { /* no device, or another bridge or user owns the device */
782 		goto unlock_exit;
783 	}
784 
785 	if (na == NULL) { /* VALE prefix missing */
786 		error = EINVAL;
787 		goto unlock_exit;
788 	}
789 
790 	if (na->nm_bdg_ctl) {
791 		/* remove the port from bridge. The bwrap
792 		 * also needs to put the hwna in normal mode
793 		 */
794 		error = na->nm_bdg_ctl(na, nmr, 0);
795 	}
796 
797 	netmap_adapter_put(na);
798 unlock_exit:
799 	NMG_UNLOCK();
800 	return error;
801 
802 }
803 
804 
805 /* Called by either user's context (netmap_ioctl())
806  * or external kernel modules (e.g., Openvswitch).
807  * Operation is indicated in nmr->nr_cmd.
808  * NETMAP_BDG_OPS that sets configure/lookup/dtor functions to the bridge
809  * requires bdg_ops argument; the other commands ignore this argument.
810  *
811  * Called without NMG_LOCK.
812  */
813 int
814 netmap_bdg_ctl(struct nmreq *nmr, struct netmap_bdg_ops *bdg_ops)
815 {
816 	struct nm_bridge *b, *bridges;
817 	struct netmap_adapter *na;
818 	struct netmap_vp_adapter *vpna;
819 	char *name = nmr->nr_name;
820 	int cmd = nmr->nr_cmd, namelen = strlen(name);
821 	int error = 0, i, j;
822 	u_int num_bridges;
823 
824 	netmap_bns_getbridges(&bridges, &num_bridges);
825 
826 	switch (cmd) {
827 	case NETMAP_BDG_NEWIF:
828 		error = nm_vi_create(nmr);
829 		break;
830 
831 	case NETMAP_BDG_DELIF:
832 		error = nm_vi_destroy(nmr->nr_name);
833 		break;
834 
835 	case NETMAP_BDG_ATTACH:
836 		error = nm_bdg_ctl_attach(nmr);
837 		break;
838 
839 	case NETMAP_BDG_DETACH:
840 		error = nm_bdg_ctl_detach(nmr);
841 		break;
842 
843 	case NETMAP_BDG_LIST:
844 		/* this is used to enumerate bridges and ports */
845 		if (namelen) { /* look up indexes of bridge and port */
846 			if (strncmp(name, NM_NAME, strlen(NM_NAME))) {
847 				error = EINVAL;
848 				break;
849 			}
850 			NMG_LOCK();
851 			b = nm_find_bridge(name, 0 /* don't create */);
852 			if (!b) {
853 				error = ENOENT;
854 				NMG_UNLOCK();
855 				break;
856 			}
857 
858 			error = ENOENT;
859 			for (j = 0; j < b->bdg_active_ports; j++) {
860 				i = b->bdg_port_index[j];
861 				vpna = b->bdg_ports[i];
862 				if (vpna == NULL) {
863 					D("---AAAAAAAAARGH-------");
864 					continue;
865 				}
866 				/* the former and the latter identify a
867 				 * virtual port and a NIC, respectively
868 				 */
869 				if (!strcmp(vpna->up.name, name)) {
870 					/* bridge index */
871 					nmr->nr_arg1 = b - bridges;
872 					nmr->nr_arg2 = i; /* port index */
873 					error = 0;
874 					break;
875 				}
876 			}
877 			NMG_UNLOCK();
878 		} else {
879 			/* return the first non-empty entry starting from
880 			 * bridge nr_arg1 and port nr_arg2.
881 			 *
882 			 * Users can detect the end of the same bridge by
883 			 * seeing the new and old value of nr_arg1, and can
884 			 * detect the end of all the bridge by error != 0
885 			 */
886 			i = nmr->nr_arg1;
887 			j = nmr->nr_arg2;
888 
889 			NMG_LOCK();
890 			for (error = ENOENT; i < NM_BRIDGES; i++) {
891 				b = bridges + i;
892 				if (j >= b->bdg_active_ports) {
893 					j = 0; /* following bridges scan from 0 */
894 					continue;
895 				}
896 				nmr->nr_arg1 = i;
897 				nmr->nr_arg2 = j;
898 				j = b->bdg_port_index[j];
899 				vpna = b->bdg_ports[j];
900 				strncpy(name, vpna->up.name, (size_t)IFNAMSIZ);
901 				error = 0;
902 				break;
903 			}
904 			NMG_UNLOCK();
905 		}
906 		break;
907 
908 	case NETMAP_BDG_REGOPS: /* XXX this should not be available from userspace */
909 		/* register callbacks to the given bridge.
910 		 * nmr->nr_name may be just bridge's name (including ':'
911 		 * if it is not just NM_NAME).
912 		 */
913 		if (!bdg_ops) {
914 			error = EINVAL;
915 			break;
916 		}
917 		NMG_LOCK();
918 		b = nm_find_bridge(name, 0 /* don't create */);
919 		if (!b) {
920 			error = EINVAL;
921 		} else {
922 			b->bdg_ops = *bdg_ops;
923 		}
924 		NMG_UNLOCK();
925 		break;
926 
927 	case NETMAP_BDG_VNET_HDR:
928 		/* Valid lengths for the virtio-net header are 0 (no header),
929 		   10 and 12. */
930 		if (nmr->nr_arg1 != 0 &&
931 			nmr->nr_arg1 != sizeof(struct nm_vnet_hdr) &&
932 				nmr->nr_arg1 != 12) {
933 			error = EINVAL;
934 			break;
935 		}
936 		NMG_LOCK();
937 		error = netmap_get_bdg_na(nmr, &na, 0);
938 		if (na && !error) {
939 			vpna = (struct netmap_vp_adapter *)na;
940 			vpna->virt_hdr_len = nmr->nr_arg1;
941 			if (vpna->virt_hdr_len)
942 				vpna->mfs = NETMAP_BUF_SIZE(na);
943 			D("Using vnet_hdr_len %d for %p", vpna->virt_hdr_len, vpna);
944 			netmap_adapter_put(na);
945 		}
946 		NMG_UNLOCK();
947 		break;
948 
949 	default:
950 		D("invalid cmd (nmr->nr_cmd) (0x%x)", cmd);
951 		error = EINVAL;
952 		break;
953 	}
954 	return error;
955 }
956 
957 int
958 netmap_bdg_config(struct nmreq *nmr)
959 {
960 	struct nm_bridge *b;
961 	int error = EINVAL;
962 
963 	NMG_LOCK();
964 	b = nm_find_bridge(nmr->nr_name, 0);
965 	if (!b) {
966 		NMG_UNLOCK();
967 		return error;
968 	}
969 	NMG_UNLOCK();
970 	/* Don't call config() with NMG_LOCK() held */
971 	BDG_RLOCK(b);
972 	if (b->bdg_ops.config != NULL)
973 		error = b->bdg_ops.config((struct nm_ifreq *)nmr);
974 	BDG_RUNLOCK(b);
975 	return error;
976 }
977 
978 
979 /* nm_krings_create callback for VALE ports.
980  * Calls the standard netmap_krings_create, then adds leases on rx
981  * rings and bdgfwd on tx rings.
982  */
983 static int
984 netmap_vp_krings_create(struct netmap_adapter *na)
985 {
986 	u_int tailroom;
987 	int error, i;
988 	uint32_t *leases;
989 	u_int nrx = netmap_real_rings(na, NR_RX);
990 
991 	/*
992 	 * Leases are attached to RX rings on vale ports
993 	 */
994 	tailroom = sizeof(uint32_t) * na->num_rx_desc * nrx;
995 
996 	error = netmap_krings_create(na, tailroom);
997 	if (error)
998 		return error;
999 
1000 	leases = na->tailroom;
1001 
1002 	for (i = 0; i < nrx; i++) { /* Receive rings */
1003 		na->rx_rings[i].nkr_leases = leases;
1004 		leases += na->num_rx_desc;
1005 	}
1006 
1007 	error = nm_alloc_bdgfwd(na);
1008 	if (error) {
1009 		netmap_krings_delete(na);
1010 		return error;
1011 	}
1012 
1013 	return 0;
1014 }
1015 
1016 
1017 /* nm_krings_delete callback for VALE ports. */
1018 static void
1019 netmap_vp_krings_delete(struct netmap_adapter *na)
1020 {
1021 	nm_free_bdgfwd(na);
1022 	netmap_krings_delete(na);
1023 }
1024 
1025 
1026 static int
1027 nm_bdg_flush(struct nm_bdg_fwd *ft, u_int n,
1028 	struct netmap_vp_adapter *na, u_int ring_nr);
1029 
1030 
1031 /*
1032  * main dispatch routine for the bridge.
1033  * Grab packets from a kring, move them into the ft structure
1034  * associated to the tx (input) port. Max one instance per port,
1035  * filtered on input (ioctl, poll or XXX).
1036  * Returns the next position in the ring.
1037  */
1038 static int
1039 nm_bdg_preflush(struct netmap_kring *kring, u_int end)
1040 {
1041 	struct netmap_vp_adapter *na =
1042 		(struct netmap_vp_adapter*)kring->na;
1043 	struct netmap_ring *ring = kring->ring;
1044 	struct nm_bdg_fwd *ft;
1045 	u_int ring_nr = kring->ring_id;
1046 	u_int j = kring->nr_hwcur, lim = kring->nkr_num_slots - 1;
1047 	u_int ft_i = 0;	/* start from 0 */
1048 	u_int frags = 1; /* how many frags ? */
1049 	struct nm_bridge *b = na->na_bdg;
1050 
1051 	/* To protect against modifications to the bridge we acquire a
1052 	 * shared lock, waiting if we can sleep (if the source port is
1053 	 * attached to a user process) or with a trylock otherwise (NICs).
1054 	 */
1055 	ND("wait rlock for %d packets", ((j > end ? lim+1 : 0) + end) - j);
1056 	if (na->up.na_flags & NAF_BDG_MAYSLEEP)
1057 		BDG_RLOCK(b);
1058 	else if (!BDG_RTRYLOCK(b))
1059 		return 0;
1060 	ND(5, "rlock acquired for %d packets", ((j > end ? lim+1 : 0) + end) - j);
1061 	ft = kring->nkr_ft;
1062 
1063 	for (; likely(j != end); j = nm_next(j, lim)) {
1064 		struct netmap_slot *slot = &ring->slot[j];
1065 		char *buf;
1066 
1067 		ft[ft_i].ft_len = slot->len;
1068 		ft[ft_i].ft_flags = slot->flags;
1069 
1070 		ND("flags is 0x%x", slot->flags);
1071 		/* we do not use the buf changed flag, but we still need to reset it */
1072 		slot->flags &= ~NS_BUF_CHANGED;
1073 
1074 		/* this slot goes into a list so initialize the link field */
1075 		ft[ft_i].ft_next = NM_FT_NULL;
1076 		buf = ft[ft_i].ft_buf = (slot->flags & NS_INDIRECT) ?
1077 			(void *)(uintptr_t)slot->ptr : NMB(&na->up, slot);
1078 		if (unlikely(buf == NULL)) {
1079 			RD(5, "NULL %s buffer pointer from %s slot %d len %d",
1080 				(slot->flags & NS_INDIRECT) ? "INDIRECT" : "DIRECT",
1081 				kring->name, j, ft[ft_i].ft_len);
1082 			buf = ft[ft_i].ft_buf = NETMAP_BUF_BASE(&na->up);
1083 			ft[ft_i].ft_len = 0;
1084 			ft[ft_i].ft_flags = 0;
1085 		}
1086 		__builtin_prefetch(buf);
1087 		++ft_i;
1088 		if (slot->flags & NS_MOREFRAG) {
1089 			frags++;
1090 			continue;
1091 		}
1092 		if (unlikely(netmap_verbose && frags > 1))
1093 			RD(5, "%d frags at %d", frags, ft_i - frags);
1094 		ft[ft_i - frags].ft_frags = frags;
1095 		frags = 1;
1096 		if (unlikely((int)ft_i >= bridge_batch))
1097 			ft_i = nm_bdg_flush(ft, ft_i, na, ring_nr);
1098 	}
1099 	if (frags > 1) {
1100 		D("truncate incomplete fragment at %d (%d frags)", ft_i, frags);
1101 		// ft_i > 0, ft[ft_i-1].flags has NS_MOREFRAG
1102 		ft[ft_i - 1].ft_frags &= ~NS_MOREFRAG;
1103 		ft[ft_i - frags].ft_frags = frags - 1;
1104 	}
1105 	if (ft_i)
1106 		ft_i = nm_bdg_flush(ft, ft_i, na, ring_nr);
1107 	BDG_RUNLOCK(b);
1108 	return j;
1109 }
1110 
1111 
1112 /* ----- FreeBSD if_bridge hash function ------- */
1113 
1114 /*
1115  * The following hash function is adapted from "Hash Functions" by Bob Jenkins
1116  * ("Algorithm Alley", Dr. Dobbs Journal, September 1997).
1117  *
1118  * http://www.burtleburtle.net/bob/hash/spooky.html
1119  */
1120 #define mix(a, b, c)                                                    \
1121 do {                                                                    \
1122         a -= b; a -= c; a ^= (c >> 13);                                 \
1123         b -= c; b -= a; b ^= (a << 8);                                  \
1124         c -= a; c -= b; c ^= (b >> 13);                                 \
1125         a -= b; a -= c; a ^= (c >> 12);                                 \
1126         b -= c; b -= a; b ^= (a << 16);                                 \
1127         c -= a; c -= b; c ^= (b >> 5);                                  \
1128         a -= b; a -= c; a ^= (c >> 3);                                  \
1129         b -= c; b -= a; b ^= (a << 10);                                 \
1130         c -= a; c -= b; c ^= (b >> 15);                                 \
1131 } while (/*CONSTCOND*/0)
1132 
1133 
1134 static __inline uint32_t
1135 nm_bridge_rthash(const uint8_t *addr)
1136 {
1137         uint32_t a = 0x9e3779b9, b = 0x9e3779b9, c = 0; // hask key
1138 
1139         b += addr[5] << 8;
1140         b += addr[4];
1141         a += addr[3] << 24;
1142         a += addr[2] << 16;
1143         a += addr[1] << 8;
1144         a += addr[0];
1145 
1146         mix(a, b, c);
1147 #define BRIDGE_RTHASH_MASK	(NM_BDG_HASH-1)
1148         return (c & BRIDGE_RTHASH_MASK);
1149 }
1150 
1151 #undef mix
1152 
1153 
1154 /* nm_register callback for VALE ports */
1155 static int
1156 netmap_vp_reg(struct netmap_adapter *na, int onoff)
1157 {
1158 	struct netmap_vp_adapter *vpna =
1159 		(struct netmap_vp_adapter*)na;
1160 
1161 	/* persistent ports may be put in netmap mode
1162 	 * before being attached to a bridge
1163 	 */
1164 	if (vpna->na_bdg)
1165 		BDG_WLOCK(vpna->na_bdg);
1166 	if (onoff) {
1167 		na->na_flags |= NAF_NETMAP_ON;
1168 		 /* XXX on FreeBSD, persistent VALE ports should also
1169 		 * toggle IFCAP_NETMAP in na->ifp (2014-03-16)
1170 		 */
1171 	} else {
1172 		na->na_flags &= ~NAF_NETMAP_ON;
1173 	}
1174 	if (vpna->na_bdg)
1175 		BDG_WUNLOCK(vpna->na_bdg);
1176 	return 0;
1177 }
1178 
1179 
1180 /*
1181  * Lookup function for a learning bridge.
1182  * Update the hash table with the source address,
1183  * and then returns the destination port index, and the
1184  * ring in *dst_ring (at the moment, always use ring 0)
1185  */
1186 u_int
1187 netmap_bdg_learning(struct nm_bdg_fwd *ft, uint8_t *dst_ring,
1188 		struct netmap_vp_adapter *na)
1189 {
1190 	uint8_t *buf = ft->ft_buf;
1191 	u_int buf_len = ft->ft_len;
1192 	struct nm_hash_ent *ht = na->na_bdg->ht;
1193 	uint32_t sh, dh;
1194 	u_int dst, mysrc = na->bdg_port;
1195 	uint64_t smac, dmac;
1196 
1197 	/* safety check, unfortunately we have many cases */
1198 	if (buf_len >= 14 + na->virt_hdr_len) {
1199 		/* virthdr + mac_hdr in the same slot */
1200 		buf += na->virt_hdr_len;
1201 		buf_len -= na->virt_hdr_len;
1202 	} else if (buf_len == na->virt_hdr_len && ft->ft_flags & NS_MOREFRAG) {
1203 		/* only header in first fragment */
1204 		ft++;
1205 		buf = ft->ft_buf;
1206 		buf_len = ft->ft_len;
1207 	} else {
1208 		RD(5, "invalid buf format, length %d", buf_len);
1209 		return NM_BDG_NOPORT;
1210 	}
1211 	dmac = le64toh(*(uint64_t *)(buf)) & 0xffffffffffff;
1212 	smac = le64toh(*(uint64_t *)(buf + 4));
1213 	smac >>= 16;
1214 
1215 	/*
1216 	 * The hash is somewhat expensive, there might be some
1217 	 * worthwhile optimizations here.
1218 	 */
1219 	if (((buf[6] & 1) == 0) && (na->last_smac != smac)) { /* valid src */
1220 		uint8_t *s = buf+6;
1221 		sh = nm_bridge_rthash(s); // XXX hash of source
1222 		/* update source port forwarding entry */
1223 		na->last_smac = ht[sh].mac = smac;	/* XXX expire ? */
1224 		ht[sh].ports = mysrc;
1225 		if (netmap_verbose)
1226 		    D("src %02x:%02x:%02x:%02x:%02x:%02x on port %d",
1227 			s[0], s[1], s[2], s[3], s[4], s[5], mysrc);
1228 	}
1229 	dst = NM_BDG_BROADCAST;
1230 	if ((buf[0] & 1) == 0) { /* unicast */
1231 		dh = nm_bridge_rthash(buf); // XXX hash of dst
1232 		if (ht[dh].mac == dmac) {	/* found dst */
1233 			dst = ht[dh].ports;
1234 		}
1235 		/* XXX otherwise return NM_BDG_UNKNOWN ? */
1236 	}
1237 	return dst;
1238 }
1239 
1240 
1241 /*
1242  * Available space in the ring. Only used in VALE code
1243  * and only with is_rx = 1
1244  */
1245 static inline uint32_t
1246 nm_kr_space(struct netmap_kring *k, int is_rx)
1247 {
1248 	int space;
1249 
1250 	if (is_rx) {
1251 		int busy = k->nkr_hwlease - k->nr_hwcur;
1252 		if (busy < 0)
1253 			busy += k->nkr_num_slots;
1254 		space = k->nkr_num_slots - 1 - busy;
1255 	} else {
1256 		/* XXX never used in this branch */
1257 		space = k->nr_hwtail - k->nkr_hwlease;
1258 		if (space < 0)
1259 			space += k->nkr_num_slots;
1260 	}
1261 #if 0
1262 	// sanity check
1263 	if (k->nkr_hwlease >= k->nkr_num_slots ||
1264 		k->nr_hwcur >= k->nkr_num_slots ||
1265 		k->nr_tail >= k->nkr_num_slots ||
1266 		busy < 0 ||
1267 		busy >= k->nkr_num_slots) {
1268 		D("invalid kring, cur %d tail %d lease %d lease_idx %d lim %d",			k->nr_hwcur, k->nr_hwtail, k->nkr_hwlease,
1269 			k->nkr_lease_idx, k->nkr_num_slots);
1270 	}
1271 #endif
1272 	return space;
1273 }
1274 
1275 
1276 
1277 
1278 /* make a lease on the kring for N positions. return the
1279  * lease index
1280  * XXX only used in VALE code and with is_rx = 1
1281  */
1282 static inline uint32_t
1283 nm_kr_lease(struct netmap_kring *k, u_int n, int is_rx)
1284 {
1285 	uint32_t lim = k->nkr_num_slots - 1;
1286 	uint32_t lease_idx = k->nkr_lease_idx;
1287 
1288 	k->nkr_leases[lease_idx] = NR_NOSLOT;
1289 	k->nkr_lease_idx = nm_next(lease_idx, lim);
1290 
1291 	if (n > nm_kr_space(k, is_rx)) {
1292 		D("invalid request for %d slots", n);
1293 		panic("x");
1294 	}
1295 	/* XXX verify that there are n slots */
1296 	k->nkr_hwlease += n;
1297 	if (k->nkr_hwlease > lim)
1298 		k->nkr_hwlease -= lim + 1;
1299 
1300 	if (k->nkr_hwlease >= k->nkr_num_slots ||
1301 		k->nr_hwcur >= k->nkr_num_slots ||
1302 		k->nr_hwtail >= k->nkr_num_slots ||
1303 		k->nkr_lease_idx >= k->nkr_num_slots) {
1304 		D("invalid kring %s, cur %d tail %d lease %d lease_idx %d lim %d",
1305 			k->na->name,
1306 			k->nr_hwcur, k->nr_hwtail, k->nkr_hwlease,
1307 			k->nkr_lease_idx, k->nkr_num_slots);
1308 	}
1309 	return lease_idx;
1310 }
1311 
1312 /*
1313  *
1314  * This flush routine supports only unicast and broadcast but a large
1315  * number of ports, and lets us replace the learn and dispatch functions.
1316  */
1317 int
1318 nm_bdg_flush(struct nm_bdg_fwd *ft, u_int n, struct netmap_vp_adapter *na,
1319 		u_int ring_nr)
1320 {
1321 	struct nm_bdg_q *dst_ents, *brddst;
1322 	uint16_t num_dsts = 0, *dsts;
1323 	struct nm_bridge *b = na->na_bdg;
1324 	u_int i, j, me = na->bdg_port;
1325 
1326 	/*
1327 	 * The work area (pointed by ft) is followed by an array of
1328 	 * pointers to queues , dst_ents; there are NM_BDG_MAXRINGS
1329 	 * queues per port plus one for the broadcast traffic.
1330 	 * Then we have an array of destination indexes.
1331 	 */
1332 	dst_ents = (struct nm_bdg_q *)(ft + NM_BDG_BATCH_MAX);
1333 	dsts = (uint16_t *)(dst_ents + NM_BDG_MAXPORTS * NM_BDG_MAXRINGS + 1);
1334 
1335 	/* first pass: find a destination for each packet in the batch */
1336 	for (i = 0; likely(i < n); i += ft[i].ft_frags) {
1337 		uint8_t dst_ring = ring_nr; /* default, same ring as origin */
1338 		uint16_t dst_port, d_i;
1339 		struct nm_bdg_q *d;
1340 
1341 		ND("slot %d frags %d", i, ft[i].ft_frags);
1342 		/* Drop the packet if the virtio-net header is not into the first
1343 		   fragment nor at the very beginning of the second. */
1344 		if (unlikely(na->virt_hdr_len > ft[i].ft_len))
1345 			continue;
1346 		dst_port = b->bdg_ops.lookup(&ft[i], &dst_ring, na);
1347 		if (netmap_verbose > 255)
1348 			RD(5, "slot %d port %d -> %d", i, me, dst_port);
1349 		if (dst_port == NM_BDG_NOPORT)
1350 			continue; /* this packet is identified to be dropped */
1351 		else if (unlikely(dst_port > NM_BDG_MAXPORTS))
1352 			continue;
1353 		else if (dst_port == NM_BDG_BROADCAST)
1354 			dst_ring = 0; /* broadcasts always go to ring 0 */
1355 		else if (unlikely(dst_port == me ||
1356 		    !b->bdg_ports[dst_port]))
1357 			continue;
1358 
1359 		/* get a position in the scratch pad */
1360 		d_i = dst_port * NM_BDG_MAXRINGS + dst_ring;
1361 		d = dst_ents + d_i;
1362 
1363 		/* append the first fragment to the list */
1364 		if (d->bq_head == NM_FT_NULL) { /* new destination */
1365 			d->bq_head = d->bq_tail = i;
1366 			/* remember this position to be scanned later */
1367 			if (dst_port != NM_BDG_BROADCAST)
1368 				dsts[num_dsts++] = d_i;
1369 		} else {
1370 			ft[d->bq_tail].ft_next = i;
1371 			d->bq_tail = i;
1372 		}
1373 		d->bq_len += ft[i].ft_frags;
1374 	}
1375 
1376 	/*
1377 	 * Broadcast traffic goes to ring 0 on all destinations.
1378 	 * So we need to add these rings to the list of ports to scan.
1379 	 * XXX at the moment we scan all NM_BDG_MAXPORTS ports, which is
1380 	 * expensive. We should keep a compact list of active destinations
1381 	 * so we could shorten this loop.
1382 	 */
1383 	brddst = dst_ents + NM_BDG_BROADCAST * NM_BDG_MAXRINGS;
1384 	if (brddst->bq_head != NM_FT_NULL) {
1385 		for (j = 0; likely(j < b->bdg_active_ports); j++) {
1386 			uint16_t d_i;
1387 			i = b->bdg_port_index[j];
1388 			if (unlikely(i == me))
1389 				continue;
1390 			d_i = i * NM_BDG_MAXRINGS;
1391 			if (dst_ents[d_i].bq_head == NM_FT_NULL)
1392 				dsts[num_dsts++] = d_i;
1393 		}
1394 	}
1395 
1396 	ND(5, "pass 1 done %d pkts %d dsts", n, num_dsts);
1397 	/* second pass: scan destinations */
1398 	for (i = 0; i < num_dsts; i++) {
1399 		struct netmap_vp_adapter *dst_na;
1400 		struct netmap_kring *kring;
1401 		struct netmap_ring *ring;
1402 		u_int dst_nr, lim, j, d_i, next, brd_next;
1403 		u_int needed, howmany;
1404 		int retry = netmap_txsync_retry;
1405 		struct nm_bdg_q *d;
1406 		uint32_t my_start = 0, lease_idx = 0;
1407 		int nrings;
1408 		int virt_hdr_mismatch = 0;
1409 
1410 		d_i = dsts[i];
1411 		ND("second pass %d port %d", i, d_i);
1412 		d = dst_ents + d_i;
1413 		// XXX fix the division
1414 		dst_na = b->bdg_ports[d_i/NM_BDG_MAXRINGS];
1415 		/* protect from the lookup function returning an inactive
1416 		 * destination port
1417 		 */
1418 		if (unlikely(dst_na == NULL))
1419 			goto cleanup;
1420 		if (dst_na->up.na_flags & NAF_SW_ONLY)
1421 			goto cleanup;
1422 		/*
1423 		 * The interface may be in !netmap mode in two cases:
1424 		 * - when na is attached but not activated yet;
1425 		 * - when na is being deactivated but is still attached.
1426 		 */
1427 		if (unlikely(!nm_netmap_on(&dst_na->up))) {
1428 			ND("not in netmap mode!");
1429 			goto cleanup;
1430 		}
1431 
1432 		/* there is at least one either unicast or broadcast packet */
1433 		brd_next = brddst->bq_head;
1434 		next = d->bq_head;
1435 		/* we need to reserve this many slots. If fewer are
1436 		 * available, some packets will be dropped.
1437 		 * Packets may have multiple fragments, so we may not use
1438 		 * there is a chance that we may not use all of the slots
1439 		 * we have claimed, so we will need to handle the leftover
1440 		 * ones when we regain the lock.
1441 		 */
1442 		needed = d->bq_len + brddst->bq_len;
1443 
1444 		if (unlikely(dst_na->virt_hdr_len != na->virt_hdr_len)) {
1445 			RD(3, "virt_hdr_mismatch, src %d dst %d", na->virt_hdr_len, dst_na->virt_hdr_len);
1446 			/* There is a virtio-net header/offloadings mismatch between
1447 			 * source and destination. The slower mismatch datapath will
1448 			 * be used to cope with all the mismatches.
1449 			 */
1450 			virt_hdr_mismatch = 1;
1451 			if (dst_na->mfs < na->mfs) {
1452 				/* We may need to do segmentation offloadings, and so
1453 				 * we may need a number of destination slots greater
1454 				 * than the number of input slots ('needed').
1455 				 * We look for the smallest integer 'x' which satisfies:
1456 				 *	needed * na->mfs + x * H <= x * na->mfs
1457 				 * where 'H' is the length of the longest header that may
1458 				 * be replicated in the segmentation process (e.g. for
1459 				 * TCPv4 we must account for ethernet header, IP header
1460 				 * and TCPv4 header).
1461 				 */
1462 				needed = (needed * na->mfs) /
1463 						(dst_na->mfs - WORST_CASE_GSO_HEADER) + 1;
1464 				ND(3, "srcmtu=%u, dstmtu=%u, x=%u", na->mfs, dst_na->mfs, needed);
1465 			}
1466 		}
1467 
1468 		ND(5, "pass 2 dst %d is %x %s",
1469 			i, d_i, is_vp ? "virtual" : "nic/host");
1470 		dst_nr = d_i & (NM_BDG_MAXRINGS-1);
1471 		nrings = dst_na->up.num_rx_rings;
1472 		if (dst_nr >= nrings)
1473 			dst_nr = dst_nr % nrings;
1474 		kring = &dst_na->up.rx_rings[dst_nr];
1475 		ring = kring->ring;
1476 		lim = kring->nkr_num_slots - 1;
1477 
1478 retry:
1479 
1480 		if (dst_na->retry && retry) {
1481 			/* try to get some free slot from the previous run */
1482 			kring->nm_notify(kring, 0);
1483 			/* actually useful only for bwraps, since there
1484 			 * the notify will trigger a txsync on the hwna. VALE ports
1485 			 * have dst_na->retry == 0
1486 			 */
1487 		}
1488 		/* reserve the buffers in the queue and an entry
1489 		 * to report completion, and drop lock.
1490 		 * XXX this might become a helper function.
1491 		 */
1492 		mtx_lock(&kring->q_lock);
1493 		if (kring->nkr_stopped) {
1494 			mtx_unlock(&kring->q_lock);
1495 			goto cleanup;
1496 		}
1497 		my_start = j = kring->nkr_hwlease;
1498 		howmany = nm_kr_space(kring, 1);
1499 		if (needed < howmany)
1500 			howmany = needed;
1501 		lease_idx = nm_kr_lease(kring, howmany, 1);
1502 		mtx_unlock(&kring->q_lock);
1503 
1504 		/* only retry if we need more than available slots */
1505 		if (retry && needed <= howmany)
1506 			retry = 0;
1507 
1508 		/* copy to the destination queue */
1509 		while (howmany > 0) {
1510 			struct netmap_slot *slot;
1511 			struct nm_bdg_fwd *ft_p, *ft_end;
1512 			u_int cnt;
1513 
1514 			/* find the queue from which we pick next packet.
1515 			 * NM_FT_NULL is always higher than valid indexes
1516 			 * so we never dereference it if the other list
1517 			 * has packets (and if both are empty we never
1518 			 * get here).
1519 			 */
1520 			if (next < brd_next) {
1521 				ft_p = ft + next;
1522 				next = ft_p->ft_next;
1523 			} else { /* insert broadcast */
1524 				ft_p = ft + brd_next;
1525 				brd_next = ft_p->ft_next;
1526 			}
1527 			cnt = ft_p->ft_frags; // cnt > 0
1528 			if (unlikely(cnt > howmany))
1529 			    break; /* no more space */
1530 			if (netmap_verbose && cnt > 1)
1531 				RD(5, "rx %d frags to %d", cnt, j);
1532 			ft_end = ft_p + cnt;
1533 			if (unlikely(virt_hdr_mismatch)) {
1534 				bdg_mismatch_datapath(na, dst_na, ft_p, ring, &j, lim, &howmany);
1535 			} else {
1536 				howmany -= cnt;
1537 				do {
1538 					char *dst, *src = ft_p->ft_buf;
1539 					size_t copy_len = ft_p->ft_len, dst_len = copy_len;
1540 
1541 					slot = &ring->slot[j];
1542 					dst = NMB(&dst_na->up, slot);
1543 
1544 					ND("send [%d] %d(%d) bytes at %s:%d",
1545 							i, (int)copy_len, (int)dst_len,
1546 							NM_IFPNAME(dst_ifp), j);
1547 					/* round to a multiple of 64 */
1548 					copy_len = (copy_len + 63) & ~63;
1549 
1550 					if (unlikely(copy_len > NETMAP_BUF_SIZE(&dst_na->up) ||
1551 						     copy_len > NETMAP_BUF_SIZE(&na->up))) {
1552 						RD(5, "invalid len %d, down to 64", (int)copy_len);
1553 						copy_len = dst_len = 64; // XXX
1554 					}
1555 					if (ft_p->ft_flags & NS_INDIRECT) {
1556 						if (copyin(src, dst, copy_len)) {
1557 							// invalid user pointer, pretend len is 0
1558 							dst_len = 0;
1559 						}
1560 					} else {
1561 						//memcpy(dst, src, copy_len);
1562 						pkt_copy(src, dst, (int)copy_len);
1563 					}
1564 					slot->len = dst_len;
1565 					slot->flags = (cnt << 8)| NS_MOREFRAG;
1566 					j = nm_next(j, lim);
1567 					needed--;
1568 					ft_p++;
1569 				} while (ft_p != ft_end);
1570 				slot->flags = (cnt << 8); /* clear flag on last entry */
1571 			}
1572 			/* are we done ? */
1573 			if (next == NM_FT_NULL && brd_next == NM_FT_NULL)
1574 				break;
1575 		}
1576 		{
1577 		    /* current position */
1578 		    uint32_t *p = kring->nkr_leases; /* shorthand */
1579 		    uint32_t update_pos;
1580 		    int still_locked = 1;
1581 
1582 		    mtx_lock(&kring->q_lock);
1583 		    if (unlikely(howmany > 0)) {
1584 			/* not used all bufs. If i am the last one
1585 			 * i can recover the slots, otherwise must
1586 			 * fill them with 0 to mark empty packets.
1587 			 */
1588 			ND("leftover %d bufs", howmany);
1589 			if (nm_next(lease_idx, lim) == kring->nkr_lease_idx) {
1590 			    /* yes i am the last one */
1591 			    ND("roll back nkr_hwlease to %d", j);
1592 			    kring->nkr_hwlease = j;
1593 			} else {
1594 			    while (howmany-- > 0) {
1595 				ring->slot[j].len = 0;
1596 				ring->slot[j].flags = 0;
1597 				j = nm_next(j, lim);
1598 			    }
1599 			}
1600 		    }
1601 		    p[lease_idx] = j; /* report I am done */
1602 
1603 		    update_pos = kring->nr_hwtail;
1604 
1605 		    if (my_start == update_pos) {
1606 			/* all slots before my_start have been reported,
1607 			 * so scan subsequent leases to see if other ranges
1608 			 * have been completed, and to a selwakeup or txsync.
1609 		         */
1610 			while (lease_idx != kring->nkr_lease_idx &&
1611 				p[lease_idx] != NR_NOSLOT) {
1612 			    j = p[lease_idx];
1613 			    p[lease_idx] = NR_NOSLOT;
1614 			    lease_idx = nm_next(lease_idx, lim);
1615 			}
1616 			/* j is the new 'write' position. j != my_start
1617 			 * means there are new buffers to report
1618 			 */
1619 			if (likely(j != my_start)) {
1620 				kring->nr_hwtail = j;
1621 				still_locked = 0;
1622 				mtx_unlock(&kring->q_lock);
1623 				kring->nm_notify(kring, 0);
1624 				/* this is netmap_notify for VALE ports and
1625 				 * netmap_bwrap_notify for bwrap. The latter will
1626 				 * trigger a txsync on the underlying hwna
1627 				 */
1628 				if (dst_na->retry && retry--) {
1629 					/* XXX this is going to call nm_notify again.
1630 					 * Only useful for bwrap in virtual machines
1631 					 */
1632 					goto retry;
1633 				}
1634 			}
1635 		    }
1636 		    if (still_locked)
1637 			mtx_unlock(&kring->q_lock);
1638 		}
1639 cleanup:
1640 		d->bq_head = d->bq_tail = NM_FT_NULL; /* cleanup */
1641 		d->bq_len = 0;
1642 	}
1643 	brddst->bq_head = brddst->bq_tail = NM_FT_NULL; /* cleanup */
1644 	brddst->bq_len = 0;
1645 	return 0;
1646 }
1647 
1648 /* nm_txsync callback for VALE ports */
1649 static int
1650 netmap_vp_txsync(struct netmap_kring *kring, int flags)
1651 {
1652 	struct netmap_vp_adapter *na =
1653 		(struct netmap_vp_adapter *)kring->na;
1654 	u_int done;
1655 	u_int const lim = kring->nkr_num_slots - 1;
1656 	u_int const head = kring->rhead;
1657 
1658 	if (bridge_batch <= 0) { /* testing only */
1659 		done = head; // used all
1660 		goto done;
1661 	}
1662 	if (!na->na_bdg) {
1663 		done = head;
1664 		goto done;
1665 	}
1666 	if (bridge_batch > NM_BDG_BATCH)
1667 		bridge_batch = NM_BDG_BATCH;
1668 
1669 	done = nm_bdg_preflush(kring, head);
1670 done:
1671 	if (done != head)
1672 		D("early break at %d/ %d, tail %d", done, head, kring->nr_hwtail);
1673 	/*
1674 	 * packets between 'done' and 'cur' are left unsent.
1675 	 */
1676 	kring->nr_hwcur = done;
1677 	kring->nr_hwtail = nm_prev(done, lim);
1678 	if (netmap_verbose)
1679 		D("%s ring %d flags %d", na->up.name, kring->ring_id, flags);
1680 	return 0;
1681 }
1682 
1683 
1684 /* rxsync code used by VALE ports nm_rxsync callback and also
1685  * internally by the brwap
1686  */
1687 static int
1688 netmap_vp_rxsync_locked(struct netmap_kring *kring, int flags)
1689 {
1690 	struct netmap_adapter *na = kring->na;
1691 	struct netmap_ring *ring = kring->ring;
1692 	u_int nm_i, lim = kring->nkr_num_slots - 1;
1693 	u_int head = kring->rhead;
1694 	int n;
1695 
1696 	if (head > lim) {
1697 		D("ouch dangerous reset!!!");
1698 		n = netmap_ring_reinit(kring);
1699 		goto done;
1700 	}
1701 
1702 	/* First part, import newly received packets. */
1703 	/* actually nothing to do here, they are already in the kring */
1704 
1705 	/* Second part, skip past packets that userspace has released. */
1706 	nm_i = kring->nr_hwcur;
1707 	if (nm_i != head) {
1708 		/* consistency check, but nothing really important here */
1709 		for (n = 0; likely(nm_i != head); n++) {
1710 			struct netmap_slot *slot = &ring->slot[nm_i];
1711 			void *addr = NMB(na, slot);
1712 
1713 			if (addr == NETMAP_BUF_BASE(kring->na)) { /* bad buf */
1714 				D("bad buffer index %d, ignore ?",
1715 					slot->buf_idx);
1716 			}
1717 			slot->flags &= ~NS_BUF_CHANGED;
1718 			nm_i = nm_next(nm_i, lim);
1719 		}
1720 		kring->nr_hwcur = head;
1721 	}
1722 
1723 	n = 0;
1724 done:
1725 	return n;
1726 }
1727 
1728 /*
1729  * nm_rxsync callback for VALE ports
1730  * user process reading from a VALE switch.
1731  * Already protected against concurrent calls from userspace,
1732  * but we must acquire the queue's lock to protect against
1733  * writers on the same queue.
1734  */
1735 static int
1736 netmap_vp_rxsync(struct netmap_kring *kring, int flags)
1737 {
1738 	int n;
1739 
1740 	mtx_lock(&kring->q_lock);
1741 	n = netmap_vp_rxsync_locked(kring, flags);
1742 	mtx_unlock(&kring->q_lock);
1743 	return n;
1744 }
1745 
1746 
1747 /* nm_bdg_attach callback for VALE ports
1748  * The na_vp port is this same netmap_adapter. There is no host port.
1749  */
1750 static int
1751 netmap_vp_bdg_attach(const char *name, struct netmap_adapter *na)
1752 {
1753 	struct netmap_vp_adapter *vpna = (struct netmap_vp_adapter *)na;
1754 
1755 	if (vpna->na_bdg)
1756 		return EBUSY;
1757 	na->na_vp = vpna;
1758 	strncpy(na->name, name, sizeof(na->name));
1759 	na->na_hostvp = NULL;
1760 	return 0;
1761 }
1762 
1763 /* create a netmap_vp_adapter that describes a VALE port.
1764  * Only persistent VALE ports have a non-null ifp.
1765  */
1766 static int
1767 netmap_vp_create(struct nmreq *nmr, struct ifnet *ifp, struct netmap_vp_adapter **ret)
1768 {
1769 	struct netmap_vp_adapter *vpna;
1770 	struct netmap_adapter *na;
1771 	int error;
1772 	u_int npipes = 0;
1773 
1774 	vpna = malloc(sizeof(*vpna), M_DEVBUF, M_NOWAIT | M_ZERO);
1775 	if (vpna == NULL)
1776 		return ENOMEM;
1777 
1778  	na = &vpna->up;
1779 
1780 	na->ifp = ifp;
1781 	strncpy(na->name, nmr->nr_name, sizeof(na->name));
1782 
1783 	/* bound checking */
1784 	na->num_tx_rings = nmr->nr_tx_rings;
1785 	nm_bound_var(&na->num_tx_rings, 1, 1, NM_BDG_MAXRINGS, NULL);
1786 	nmr->nr_tx_rings = na->num_tx_rings; // write back
1787 	na->num_rx_rings = nmr->nr_rx_rings;
1788 	nm_bound_var(&na->num_rx_rings, 1, 1, NM_BDG_MAXRINGS, NULL);
1789 	nmr->nr_rx_rings = na->num_rx_rings; // write back
1790 	nm_bound_var(&nmr->nr_tx_slots, NM_BRIDGE_RINGSIZE,
1791 			1, NM_BDG_MAXSLOTS, NULL);
1792 	na->num_tx_desc = nmr->nr_tx_slots;
1793 	nm_bound_var(&nmr->nr_rx_slots, NM_BRIDGE_RINGSIZE,
1794 			1, NM_BDG_MAXSLOTS, NULL);
1795 	/* validate number of pipes. We want at least 1,
1796 	 * but probably can do with some more.
1797 	 * So let's use 2 as default (when 0 is supplied)
1798 	 */
1799 	npipes = nmr->nr_arg1;
1800 	nm_bound_var(&npipes, 2, 1, NM_MAXPIPES, NULL);
1801 	nmr->nr_arg1 = npipes;	/* write back */
1802 	/* validate extra bufs */
1803 	nm_bound_var(&nmr->nr_arg3, 0, 0,
1804 			128*NM_BDG_MAXSLOTS, NULL);
1805 	na->num_rx_desc = nmr->nr_rx_slots;
1806 	vpna->virt_hdr_len = 0;
1807 	vpna->mfs = 1514;
1808 	vpna->last_smac = ~0llu;
1809 	/*if (vpna->mfs > netmap_buf_size)  TODO netmap_buf_size is zero??
1810 		vpna->mfs = netmap_buf_size; */
1811         if (netmap_verbose)
1812 		D("max frame size %u", vpna->mfs);
1813 
1814 	na->na_flags |= NAF_BDG_MAYSLEEP;
1815 	/* persistent VALE ports look like hw devices
1816 	 * with a native netmap adapter
1817 	 */
1818 	if (ifp)
1819 		na->na_flags |= NAF_NATIVE;
1820 	na->nm_txsync = netmap_vp_txsync;
1821 	na->nm_rxsync = netmap_vp_rxsync;
1822 	na->nm_register = netmap_vp_reg;
1823 	na->nm_krings_create = netmap_vp_krings_create;
1824 	na->nm_krings_delete = netmap_vp_krings_delete;
1825 	na->nm_dtor = netmap_vp_dtor;
1826 	na->nm_mem = netmap_mem_private_new(na->name,
1827 			na->num_tx_rings, na->num_tx_desc,
1828 			na->num_rx_rings, na->num_rx_desc,
1829 			nmr->nr_arg3, npipes, &error);
1830 	if (na->nm_mem == NULL)
1831 		goto err;
1832 	na->nm_bdg_attach = netmap_vp_bdg_attach;
1833 	/* other nmd fields are set in the common routine */
1834 	error = netmap_attach_common(na);
1835 	if (error)
1836 		goto err;
1837 	*ret = vpna;
1838 	return 0;
1839 
1840 err:
1841 	if (na->nm_mem != NULL)
1842 		netmap_mem_delete(na->nm_mem);
1843 	free(vpna, M_DEVBUF);
1844 	return error;
1845 }
1846 
1847 /* Bridge wrapper code (bwrap).
1848  * This is used to connect a non-VALE-port netmap_adapter (hwna) to a
1849  * VALE switch.
1850  * The main task is to swap the meaning of tx and rx rings to match the
1851  * expectations of the VALE switch code (see nm_bdg_flush).
1852  *
1853  * The bwrap works by interposing a netmap_bwrap_adapter between the
1854  * rest of the system and the hwna. The netmap_bwrap_adapter looks like
1855  * a netmap_vp_adapter to the rest the system, but, internally, it
1856  * translates all callbacks to what the hwna expects.
1857  *
1858  * Note that we have to intercept callbacks coming from two sides:
1859  *
1860  *  - callbacks coming from the netmap module are intercepted by
1861  *    passing around the netmap_bwrap_adapter instead of the hwna
1862  *
1863  *  - callbacks coming from outside of the netmap module only know
1864  *    about the hwna. This, however, only happens in interrupt
1865  *    handlers, where only the hwna->nm_notify callback is called.
1866  *    What the bwrap does is to overwrite the hwna->nm_notify callback
1867  *    with its own netmap_bwrap_intr_notify.
1868  *    XXX This assumes that the hwna->nm_notify callback was the
1869  *    standard netmap_notify(), as it is the case for nic adapters.
1870  *    Any additional action performed by hwna->nm_notify will not be
1871  *    performed by netmap_bwrap_intr_notify.
1872  *
1873  * Additionally, the bwrap can optionally attach the host rings pair
1874  * of the wrapped adapter to a different port of the switch.
1875  */
1876 
1877 
1878 static void
1879 netmap_bwrap_dtor(struct netmap_adapter *na)
1880 {
1881 	struct netmap_bwrap_adapter *bna = (struct netmap_bwrap_adapter*)na;
1882 	struct netmap_adapter *hwna = bna->hwna;
1883 
1884 	ND("na %p", na);
1885 	/* drop reference to hwna->ifp.
1886 	 * If we don't do this, netmap_detach_common(na)
1887 	 * will think it has set NA(na->ifp) to NULL
1888 	 */
1889 	na->ifp = NULL;
1890 	/* for safety, also drop the possible reference
1891 	 * in the hostna
1892 	 */
1893 	bna->host.up.ifp = NULL;
1894 
1895 	hwna->nm_mem = bna->save_nmd;
1896 	hwna->na_private = NULL;
1897 	hwna->na_vp = hwna->na_hostvp = NULL;
1898 	hwna->na_flags &= ~NAF_BUSY;
1899 	netmap_adapter_put(hwna);
1900 
1901 }
1902 
1903 
1904 /*
1905  * Intr callback for NICs connected to a bridge.
1906  * Simply ignore tx interrupts (maybe we could try to recover space ?)
1907  * and pass received packets from nic to the bridge.
1908  *
1909  * XXX TODO check locking: this is called from the interrupt
1910  * handler so we should make sure that the interface is not
1911  * disconnected while passing down an interrupt.
1912  *
1913  * Note, no user process can access this NIC or the host stack.
1914  * The only part of the ring that is significant are the slots,
1915  * and head/cur/tail are set from the kring as needed
1916  * (part as a receive ring, part as a transmit ring).
1917  *
1918  * callback that overwrites the hwna notify callback.
1919  * Packets come from the outside or from the host stack and are put on an hwna rx ring.
1920  * The bridge wrapper then sends the packets through the bridge.
1921  */
1922 static int
1923 netmap_bwrap_intr_notify(struct netmap_kring *kring, int flags)
1924 {
1925 	struct netmap_adapter *na = kring->na;
1926 	struct netmap_bwrap_adapter *bna = na->na_private;
1927 	struct netmap_kring *bkring;
1928 	struct netmap_vp_adapter *vpna = &bna->up;
1929 	u_int ring_nr = kring->ring_id;
1930 	int error = 0;
1931 
1932 	if (netmap_verbose)
1933 	    D("%s %s 0x%x", na->name, kring->name, flags);
1934 
1935 	if (!nm_netmap_on(na))
1936 		return 0;
1937 
1938 	bkring = &vpna->up.tx_rings[ring_nr];
1939 
1940 	/* make sure the ring is not disabled */
1941 	if (nm_kr_tryget(kring))
1942 		return 0;
1943 
1944 	if (netmap_verbose)
1945 	    D("%s head %d cur %d tail %d",  na->name,
1946 		kring->rhead, kring->rcur, kring->rtail);
1947 
1948 	/* simulate a user wakeup on the rx ring
1949 	 * fetch packets that have arrived.
1950 	 */
1951 	error = kring->nm_sync(kring, 0);
1952 	if (error)
1953 		goto put_out;
1954 	if (kring->nr_hwcur == kring->nr_hwtail && netmap_verbose) {
1955 		D("how strange, interrupt with no packets on %s",
1956 			na->name);
1957 		goto put_out;
1958 	}
1959 
1960 	/* new packets are kring->rcur to kring->nr_hwtail, and the bkring
1961 	 * had hwcur == bkring->rhead. So advance bkring->rhead to kring->nr_hwtail
1962 	 * to push all packets out.
1963 	 */
1964 	bkring->rhead = bkring->rcur = kring->nr_hwtail;
1965 
1966 	netmap_vp_txsync(bkring, flags);
1967 
1968 	/* mark all buffers as released on this ring */
1969 	kring->rhead = kring->rcur = kring->rtail = kring->nr_hwtail;
1970 	/* another call to actually release the buffers */
1971 	error = kring->nm_sync(kring, 0);
1972 
1973 put_out:
1974 	nm_kr_put(kring);
1975 	return error;
1976 }
1977 
1978 
1979 /* nm_register callback for bwrap */
1980 static int
1981 netmap_bwrap_register(struct netmap_adapter *na, int onoff)
1982 {
1983 	struct netmap_bwrap_adapter *bna =
1984 		(struct netmap_bwrap_adapter *)na;
1985 	struct netmap_adapter *hwna = bna->hwna;
1986 	struct netmap_vp_adapter *hostna = &bna->host;
1987 	int error;
1988 	enum txrx t;
1989 
1990 	ND("%s %s", na->name, onoff ? "on" : "off");
1991 
1992 	if (onoff) {
1993 		int i;
1994 
1995 		/* netmap_do_regif has been called on the bwrap na.
1996 		 * We need to pass the information about the
1997 		 * memory allocator down to the hwna before
1998 		 * putting it in netmap mode
1999 		 */
2000 		hwna->na_lut = na->na_lut;
2001 
2002 		if (hostna->na_bdg) {
2003 			/* if the host rings have been attached to switch,
2004 			 * we need to copy the memory allocator information
2005 			 * in the hostna also
2006 			 */
2007 			hostna->up.na_lut = na->na_lut;
2008 		}
2009 
2010 		/* cross-link the netmap rings
2011 		 * The original number of rings comes from hwna,
2012 		 * rx rings on one side equals tx rings on the other.
2013 		 * We need to do this now, after the initialization
2014 		 * of the kring->ring pointers
2015 		 */
2016 		for_rx_tx(t) {
2017 			enum txrx r= nm_txrx_swap(t); /* swap NR_TX <-> NR_RX */
2018 			for (i = 0; i < nma_get_nrings(na, r) + 1; i++) {
2019 				NMR(hwna, t)[i].nkr_num_slots = NMR(na, r)[i].nkr_num_slots;
2020 				NMR(hwna, t)[i].ring = NMR(na, r)[i].ring;
2021 			}
2022 		}
2023 	}
2024 
2025 	/* forward the request to the hwna */
2026 	error = hwna->nm_register(hwna, onoff);
2027 	if (error)
2028 		return error;
2029 
2030 	/* impersonate a netmap_vp_adapter */
2031 	netmap_vp_reg(na, onoff);
2032 	if (hostna->na_bdg)
2033 		netmap_vp_reg(&hostna->up, onoff);
2034 
2035 	if (onoff) {
2036 		u_int i;
2037 		/* intercept the hwna nm_nofify callback on the hw rings */
2038 		for (i = 0; i < hwna->num_rx_rings; i++) {
2039 			hwna->rx_rings[i].save_notify = hwna->rx_rings[i].nm_notify;
2040 			hwna->rx_rings[i].nm_notify = netmap_bwrap_intr_notify;
2041 		}
2042 		i = hwna->num_rx_rings; /* for safety */
2043 		/* save the host ring notify unconditionally */
2044 		hwna->rx_rings[i].save_notify = hwna->rx_rings[i].nm_notify;
2045 		if (hostna->na_bdg) {
2046 			/* also intercept the host ring notify */
2047 			hwna->rx_rings[i].nm_notify = netmap_bwrap_intr_notify;
2048 		}
2049 	} else {
2050 		u_int i;
2051 		/* reset all notify callbacks (including host ring) */
2052 		for (i = 0; i <= hwna->num_rx_rings; i++) {
2053 			hwna->rx_rings[i].nm_notify = hwna->rx_rings[i].save_notify;
2054 			hwna->rx_rings[i].save_notify = NULL;
2055 		}
2056 		hwna->na_lut.lut = NULL;
2057 		hwna->na_lut.objtotal = 0;
2058 		hwna->na_lut.objsize = 0;
2059 	}
2060 
2061 	return 0;
2062 }
2063 
2064 /* nm_config callback for bwrap */
2065 static int
2066 netmap_bwrap_config(struct netmap_adapter *na, u_int *txr, u_int *txd,
2067 				    u_int *rxr, u_int *rxd)
2068 {
2069 	struct netmap_bwrap_adapter *bna =
2070 		(struct netmap_bwrap_adapter *)na;
2071 	struct netmap_adapter *hwna = bna->hwna;
2072 
2073 	/* forward the request */
2074 	netmap_update_config(hwna);
2075 	/* swap the results */
2076 	*txr = hwna->num_rx_rings;
2077 	*txd = hwna->num_rx_desc;
2078 	*rxr = hwna->num_tx_rings;
2079 	*rxd = hwna->num_rx_desc;
2080 
2081 	return 0;
2082 }
2083 
2084 
2085 /* nm_krings_create callback for bwrap */
2086 static int
2087 netmap_bwrap_krings_create(struct netmap_adapter *na)
2088 {
2089 	struct netmap_bwrap_adapter *bna =
2090 		(struct netmap_bwrap_adapter *)na;
2091 	struct netmap_adapter *hwna = bna->hwna;
2092 	struct netmap_adapter *hostna = &bna->host.up;
2093 	int error;
2094 
2095 	ND("%s", na->name);
2096 
2097 	/* impersonate a netmap_vp_adapter */
2098 	error = netmap_vp_krings_create(na);
2099 	if (error)
2100 		return error;
2101 
2102 	/* also create the hwna krings */
2103 	error = hwna->nm_krings_create(hwna);
2104 	if (error) {
2105 		netmap_vp_krings_delete(na);
2106 		return error;
2107 	}
2108 	/* the connection between the bwrap krings and the hwna krings
2109 	 * will be perfomed later, in the nm_register callback, since
2110 	 * now the kring->ring pointers have not been initialized yet
2111 	 */
2112 
2113 	if (na->na_flags & NAF_HOST_RINGS) {
2114 		/* the hostna rings are the host rings of the bwrap.
2115 		 * The corresponding krings must point back to the
2116 		 * hostna
2117 		 */
2118 		hostna->tx_rings = &na->tx_rings[na->num_tx_rings];
2119 		hostna->tx_rings[0].na = hostna;
2120 		hostna->rx_rings = &na->rx_rings[na->num_rx_rings];
2121 		hostna->rx_rings[0].na = hostna;
2122 	}
2123 
2124 	return 0;
2125 }
2126 
2127 
2128 static void
2129 netmap_bwrap_krings_delete(struct netmap_adapter *na)
2130 {
2131 	struct netmap_bwrap_adapter *bna =
2132 		(struct netmap_bwrap_adapter *)na;
2133 	struct netmap_adapter *hwna = bna->hwna;
2134 
2135 	ND("%s", na->name);
2136 
2137 	hwna->nm_krings_delete(hwna);
2138 	netmap_vp_krings_delete(na);
2139 }
2140 
2141 
2142 /* notify method for the bridge-->hwna direction */
2143 static int
2144 netmap_bwrap_notify(struct netmap_kring *kring, int flags)
2145 {
2146 	struct netmap_adapter *na = kring->na;
2147 	struct netmap_bwrap_adapter *bna = na->na_private;
2148 	struct netmap_adapter *hwna = bna->hwna;
2149 	u_int ring_n = kring->ring_id;
2150 	u_int lim = kring->nkr_num_slots - 1;
2151 	struct netmap_kring *hw_kring;
2152 	int error = 0;
2153 
2154 	ND("%s: na %s hwna %s",
2155 			(kring ? kring->name : "NULL!"),
2156 			(na ? na->name : "NULL!"),
2157 			(hwna ? hwna->name : "NULL!"));
2158 	hw_kring = &hwna->tx_rings[ring_n];
2159 
2160 	if (nm_kr_tryget(hw_kring))
2161 		return 0;
2162 
2163 	if (!nm_netmap_on(hwna))
2164 		return 0;
2165 	/* first step: simulate a user wakeup on the rx ring */
2166 	netmap_vp_rxsync(kring, flags);
2167 	ND("%s[%d] PRE rx(c%3d t%3d l%3d) ring(h%3d c%3d t%3d) tx(c%3d ht%3d t%3d)",
2168 		na->name, ring_n,
2169 		kring->nr_hwcur, kring->nr_hwtail, kring->nkr_hwlease,
2170 		ring->head, ring->cur, ring->tail,
2171 		hw_kring->nr_hwcur, hw_kring->nr_hwtail, hw_ring->rtail);
2172 	/* second step: the new packets are sent on the tx ring
2173 	 * (which is actually the same ring)
2174 	 */
2175 	hw_kring->rhead = hw_kring->rcur = kring->nr_hwtail;
2176 	error = hw_kring->nm_sync(hw_kring, flags);
2177 	if (error)
2178 		goto out;
2179 
2180 	/* third step: now we are back the rx ring */
2181 	/* claim ownership on all hw owned bufs */
2182 	kring->rhead = kring->rcur = nm_next(hw_kring->nr_hwtail, lim); /* skip past reserved slot */
2183 
2184 	/* fourth step: the user goes to sleep again, causing another rxsync */
2185 	netmap_vp_rxsync(kring, flags);
2186 	ND("%s[%d] PST rx(c%3d t%3d l%3d) ring(h%3d c%3d t%3d) tx(c%3d ht%3d t%3d)",
2187 		na->name, ring_n,
2188 		kring->nr_hwcur, kring->nr_hwtail, kring->nkr_hwlease,
2189 		ring->head, ring->cur, ring->tail,
2190 		hw_kring->nr_hwcur, hw_kring->nr_hwtail, hw_kring->rtail);
2191 out:
2192 	nm_kr_put(hw_kring);
2193 	return error;
2194 }
2195 
2196 
2197 /* nm_bdg_ctl callback for the bwrap.
2198  * Called on bridge-attach and detach, as an effect of vale-ctl -[ahd].
2199  * On attach, it needs to provide a fake netmap_priv_d structure and
2200  * perform a netmap_do_regif() on the bwrap. This will put both the
2201  * bwrap and the hwna in netmap mode, with the netmap rings shared
2202  * and cross linked. Moroever, it will start intercepting interrupts
2203  * directed to hwna.
2204  */
2205 static int
2206 netmap_bwrap_bdg_ctl(struct netmap_adapter *na, struct nmreq *nmr, int attach)
2207 {
2208 	struct netmap_priv_d *npriv;
2209 	struct netmap_bwrap_adapter *bna = (struct netmap_bwrap_adapter*)na;
2210 	int error = 0;
2211 
2212 	if (attach) {
2213 		if (NETMAP_OWNED_BY_ANY(na)) {
2214 			return EBUSY;
2215 		}
2216 		if (bna->na_kpriv) {
2217 			/* nothing to do */
2218 			return 0;
2219 		}
2220 		npriv = malloc(sizeof(*npriv), M_DEVBUF, M_NOWAIT|M_ZERO);
2221 		if (npriv == NULL)
2222 			return ENOMEM;
2223 		error = netmap_do_regif(npriv, na, nmr->nr_ringid, nmr->nr_flags);
2224 		if (error) {
2225 			bzero(npriv, sizeof(*npriv));
2226 			free(npriv, M_DEVBUF);
2227 			return error;
2228 		}
2229 		bna->na_kpriv = npriv;
2230 		na->na_flags |= NAF_BUSY;
2231 	} else {
2232 		int last_instance;
2233 
2234 		if (na->active_fds == 0) /* not registered */
2235 			return EINVAL;
2236 		last_instance = netmap_dtor_locked(bna->na_kpriv);
2237 		if (!last_instance) {
2238 			D("--- error, trying to detach an entry with active mmaps");
2239 			error = EINVAL;
2240 		} else {
2241 			struct nm_bridge *b = bna->up.na_bdg,
2242 				*bh = bna->host.na_bdg;
2243 			npriv = bna->na_kpriv;
2244 			bna->na_kpriv = NULL;
2245 			D("deleting priv");
2246 
2247 			bzero(npriv, sizeof(*npriv));
2248 			free(npriv, M_DEVBUF);
2249 			if (b) {
2250 				/* XXX the bwrap dtor should take care
2251 				 * of this (2014-06-16)
2252 				 */
2253 				netmap_bdg_detach_common(b, bna->up.bdg_port,
2254 				    (bh ? bna->host.bdg_port : -1));
2255 			}
2256 			na->na_flags &= ~NAF_BUSY;
2257 		}
2258 	}
2259 	return error;
2260 
2261 }
2262 
2263 /* attach a bridge wrapper to the 'real' device */
2264 int
2265 netmap_bwrap_attach(const char *nr_name, struct netmap_adapter *hwna)
2266 {
2267 	struct netmap_bwrap_adapter *bna;
2268 	struct netmap_adapter *na = NULL;
2269 	struct netmap_adapter *hostna = NULL;
2270 	int error = 0;
2271 	enum txrx t;
2272 
2273 	/* make sure the NIC is not already in use */
2274 	if (NETMAP_OWNED_BY_ANY(hwna)) {
2275 		D("NIC %s busy, cannot attach to bridge", hwna->name);
2276 		return EBUSY;
2277 	}
2278 
2279 	bna = malloc(sizeof(*bna), M_DEVBUF, M_NOWAIT | M_ZERO);
2280 	if (bna == NULL) {
2281 		return ENOMEM;
2282 	}
2283 
2284 	na = &bna->up.up;
2285 	na->na_private = bna;
2286 	strncpy(na->name, nr_name, sizeof(na->name));
2287 	/* fill the ring data for the bwrap adapter with rx/tx meanings
2288 	 * swapped. The real cross-linking will be done during register,
2289 	 * when all the krings will have been created.
2290 	 */
2291 	for_rx_tx(t) {
2292 		enum txrx r = nm_txrx_swap(t); /* swap NR_TX <-> NR_RX */
2293 		nma_set_nrings(na, t, nma_get_nrings(hwna, r));
2294 		nma_set_ndesc(na, t, nma_get_ndesc(hwna, r));
2295 	}
2296 	na->nm_dtor = netmap_bwrap_dtor;
2297 	na->nm_register = netmap_bwrap_register;
2298 	// na->nm_txsync = netmap_bwrap_txsync;
2299 	// na->nm_rxsync = netmap_bwrap_rxsync;
2300 	na->nm_config = netmap_bwrap_config;
2301 	na->nm_krings_create = netmap_bwrap_krings_create;
2302 	na->nm_krings_delete = netmap_bwrap_krings_delete;
2303 	na->nm_notify = netmap_bwrap_notify;
2304 	na->nm_bdg_ctl = netmap_bwrap_bdg_ctl;
2305 	na->pdev = hwna->pdev;
2306 	na->nm_mem = netmap_mem_private_new(na->name,
2307 			na->num_tx_rings, na->num_tx_desc,
2308 			na->num_rx_rings, na->num_rx_desc,
2309 			0, 0, &error);
2310 	na->na_flags |= NAF_MEM_OWNER;
2311 	if (na->nm_mem == NULL)
2312 		goto err_put;
2313 	bna->up.retry = 1; /* XXX maybe this should depend on the hwna */
2314 
2315 	bna->hwna = hwna;
2316 	netmap_adapter_get(hwna);
2317 	hwna->na_private = bna; /* weak reference */
2318 	hwna->na_vp = &bna->up;
2319 
2320 	if (hwna->na_flags & NAF_HOST_RINGS) {
2321 		if (hwna->na_flags & NAF_SW_ONLY)
2322 			na->na_flags |= NAF_SW_ONLY;
2323 		na->na_flags |= NAF_HOST_RINGS;
2324 		hostna = &bna->host.up;
2325 		snprintf(hostna->name, sizeof(hostna->name), "%s^", nr_name);
2326 		hostna->ifp = hwna->ifp;
2327 		for_rx_tx(t) {
2328 			enum txrx r = nm_txrx_swap(t);
2329 			nma_set_nrings(hostna, t, 1);
2330 			nma_set_ndesc(hostna, t, nma_get_ndesc(hwna, r));
2331 		}
2332 		// hostna->nm_txsync = netmap_bwrap_host_txsync;
2333 		// hostna->nm_rxsync = netmap_bwrap_host_rxsync;
2334 		hostna->nm_notify = netmap_bwrap_notify;
2335 		hostna->nm_mem = na->nm_mem;
2336 		hostna->na_private = bna;
2337 		hostna->na_vp = &bna->up;
2338 		na->na_hostvp = hwna->na_hostvp =
2339 			hostna->na_hostvp = &bna->host;
2340 		hostna->na_flags = NAF_BUSY; /* prevent NIOCREGIF */
2341 	}
2342 
2343 	ND("%s<->%s txr %d txd %d rxr %d rxd %d",
2344 		na->name, ifp->if_xname,
2345 		na->num_tx_rings, na->num_tx_desc,
2346 		na->num_rx_rings, na->num_rx_desc);
2347 
2348 	error = netmap_attach_common(na);
2349 	if (error) {
2350 		goto err_free;
2351 	}
2352 	/* make bwrap ifp point to the real ifp
2353 	 * NOTE: netmap_attach_common() interprets a non-NULL na->ifp
2354 	 * as a request to make the ifp point to the na. Since we
2355 	 * do not want to change the na already pointed to by hwna->ifp,
2356 	 * the following assignment has to be delayed until now
2357 	 */
2358 	na->ifp = hwna->ifp;
2359 	hwna->na_flags |= NAF_BUSY;
2360 	/* make hwna point to the allocator we are actually using,
2361 	 * so that monitors will be able to find it
2362 	 */
2363 	bna->save_nmd = hwna->nm_mem;
2364 	hwna->nm_mem = na->nm_mem;
2365 	return 0;
2366 
2367 err_free:
2368 	netmap_mem_delete(na->nm_mem);
2369 err_put:
2370 	hwna->na_vp = hwna->na_hostvp = NULL;
2371 	netmap_adapter_put(hwna);
2372 	free(bna, M_DEVBUF);
2373 	return error;
2374 
2375 }
2376 
2377 struct nm_bridge *
2378 netmap_init_bridges2(u_int n)
2379 {
2380 	int i;
2381 	struct nm_bridge *b;
2382 
2383 	b = malloc(sizeof(struct nm_bridge) * n, M_DEVBUF,
2384 		M_NOWAIT | M_ZERO);
2385 	if (b == NULL)
2386 		return NULL;
2387 	for (i = 0; i < n; i++)
2388 		BDG_RWINIT(&b[i]);
2389 	return b;
2390 }
2391 
2392 void
2393 netmap_uninit_bridges2(struct nm_bridge *b, u_int n)
2394 {
2395 	int i;
2396 
2397 	if (b == NULL)
2398 		return;
2399 
2400 	for (i = 0; i < n; i++)
2401 		BDG_RWDESTROY(&b[i]);
2402 	free(b, M_DEVBUF);
2403 }
2404 
2405 int
2406 netmap_init_bridges(void)
2407 {
2408 #ifdef CONFIG_NET_NS
2409 	return netmap_bns_register();
2410 #else
2411 	nm_bridges = netmap_init_bridges2(NM_BRIDGES);
2412 	if (nm_bridges == NULL)
2413 		return ENOMEM;
2414 	return 0;
2415 #endif
2416 }
2417 
2418 void
2419 netmap_uninit_bridges(void)
2420 {
2421 #ifdef CONFIG_NET_NS
2422 	netmap_bns_unregister();
2423 #else
2424 	netmap_uninit_bridges2(nm_bridges, NM_BRIDGES);
2425 #endif
2426 }
2427 #endif /* WITH_VALE */
2428