xref: /freebsd/sys/dev/netmap/netmap_legacy.c (revision 71625ec9)
12ff91c17SVincenzo Maffione /*-
24d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
32ff91c17SVincenzo Maffione  *
42ff91c17SVincenzo Maffione  * Copyright (C) 2018 Vincenzo Maffione
52ff91c17SVincenzo Maffione  * All rights reserved.
62ff91c17SVincenzo Maffione  *
72ff91c17SVincenzo Maffione  * Redistribution and use in source and binary forms, with or without
82ff91c17SVincenzo Maffione  * modification, are permitted provided that the following conditions
92ff91c17SVincenzo Maffione  * are met:
102ff91c17SVincenzo Maffione  *   1. Redistributions of source code must retain the above copyright
112ff91c17SVincenzo Maffione  *      notice, this list of conditions and the following disclaimer.
122ff91c17SVincenzo Maffione  *   2. Redistributions in binary form must reproduce the above copyright
132ff91c17SVincenzo Maffione  *      notice, this list of conditions and the following disclaimer in the
142ff91c17SVincenzo Maffione  *      documentation and/or other materials provided with the distribution.
152ff91c17SVincenzo Maffione  *
162ff91c17SVincenzo Maffione  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
172ff91c17SVincenzo Maffione  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
182ff91c17SVincenzo Maffione  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
192ff91c17SVincenzo Maffione  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
202ff91c17SVincenzo Maffione  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
212ff91c17SVincenzo Maffione  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
222ff91c17SVincenzo Maffione  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
232ff91c17SVincenzo Maffione  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
242ff91c17SVincenzo Maffione  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
252ff91c17SVincenzo Maffione  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
262ff91c17SVincenzo Maffione  * SUCH DAMAGE.
272ff91c17SVincenzo Maffione  */
282ff91c17SVincenzo Maffione 
292ff91c17SVincenzo Maffione 
302ff91c17SVincenzo Maffione #if defined(__FreeBSD__)
312ff91c17SVincenzo Maffione #include <sys/cdefs.h> /* prerequisite */
322ff91c17SVincenzo Maffione #include <sys/types.h>
332ff91c17SVincenzo Maffione #include <sys/param.h>	/* defines used in kernel.h */
342ff91c17SVincenzo Maffione #include <sys/filio.h>	/* FIONBIO */
352ff91c17SVincenzo Maffione #include <sys/malloc.h>
362ff91c17SVincenzo Maffione #include <sys/socketvar.h>	/* struct socket */
372ff91c17SVincenzo Maffione #include <sys/socket.h> /* sockaddrs */
382ff91c17SVincenzo Maffione #include <sys/sysctl.h>
392ff91c17SVincenzo Maffione #include <net/if.h>
402ff91c17SVincenzo Maffione #include <net/if_var.h>
412ff91c17SVincenzo Maffione #include <net/bpf.h>		/* BIOCIMMEDIATE */
422ff91c17SVincenzo Maffione #include <machine/bus.h>	/* bus_dmamap_* */
432ff91c17SVincenzo Maffione #include <sys/endian.h>
442ff91c17SVincenzo Maffione #elif defined(linux)
452ff91c17SVincenzo Maffione #include "bsd_glue.h"
462ff91c17SVincenzo Maffione #elif defined(__APPLE__)
472ff91c17SVincenzo Maffione #warning OSX support is only partial
482ff91c17SVincenzo Maffione #include "osx_glue.h"
492ff91c17SVincenzo Maffione #elif defined (_WIN32)
502ff91c17SVincenzo Maffione #include "win_glue.h"
512ff91c17SVincenzo Maffione #endif
522ff91c17SVincenzo Maffione 
532ff91c17SVincenzo Maffione /*
542ff91c17SVincenzo Maffione  * common headers
552ff91c17SVincenzo Maffione  */
562ff91c17SVincenzo Maffione #include <net/netmap.h>
572ff91c17SVincenzo Maffione #include <dev/netmap/netmap_kern.h>
58b6e66be2SVincenzo Maffione #include <dev/netmap/netmap_bdg.h>
592ff91c17SVincenzo Maffione 
602ff91c17SVincenzo Maffione static int
nmreq_register_from_legacy(struct nmreq * nmr,struct nmreq_header * hdr,struct nmreq_register * req)612ff91c17SVincenzo Maffione nmreq_register_from_legacy(struct nmreq *nmr, struct nmreq_header *hdr,
622ff91c17SVincenzo Maffione 				struct nmreq_register *req)
632ff91c17SVincenzo Maffione {
642ff91c17SVincenzo Maffione 	req->nr_offset = nmr->nr_offset;
652ff91c17SVincenzo Maffione 	req->nr_memsize = nmr->nr_memsize;
662ff91c17SVincenzo Maffione 	req->nr_tx_slots = nmr->nr_tx_slots;
672ff91c17SVincenzo Maffione 	req->nr_rx_slots = nmr->nr_rx_slots;
682ff91c17SVincenzo Maffione 	req->nr_tx_rings = nmr->nr_tx_rings;
692ff91c17SVincenzo Maffione 	req->nr_rx_rings = nmr->nr_rx_rings;
70d12354a5SVincenzo Maffione 	req->nr_host_tx_rings = 0;
71d12354a5SVincenzo Maffione 	req->nr_host_rx_rings = 0;
722ff91c17SVincenzo Maffione 	req->nr_mem_id = nmr->nr_arg2;
732ff91c17SVincenzo Maffione 	req->nr_ringid = nmr->nr_ringid & NETMAP_RING_MASK;
742ff91c17SVincenzo Maffione 	if ((nmr->nr_flags & NR_REG_MASK) == NR_REG_DEFAULT) {
752ff91c17SVincenzo Maffione 		/* Convert the older nmr->nr_ringid (original
762ff91c17SVincenzo Maffione 		 * netmap control API) to nmr->nr_flags. */
772ff91c17SVincenzo Maffione 		u_int regmode = NR_REG_DEFAULT;
78ff48ef48SVincenzo Maffione 		if (nmr->nr_ringid & NETMAP_SW_RING) {
792ff91c17SVincenzo Maffione 			regmode = NR_REG_SW;
80ff48ef48SVincenzo Maffione 		} else if (nmr->nr_ringid & NETMAP_HW_RING) {
812ff91c17SVincenzo Maffione 			regmode = NR_REG_ONE_NIC;
822ff91c17SVincenzo Maffione 		} else {
832ff91c17SVincenzo Maffione 			regmode = NR_REG_ALL_NIC;
842ff91c17SVincenzo Maffione 		}
85b6e66be2SVincenzo Maffione 		req->nr_mode = regmode;
86b6e66be2SVincenzo Maffione 	} else {
872ff91c17SVincenzo Maffione 		req->nr_mode = nmr->nr_flags & NR_REG_MASK;
88b6e66be2SVincenzo Maffione 	}
89b6e66be2SVincenzo Maffione 
902ff91c17SVincenzo Maffione 	/* Fix nr_name, nr_mode and nr_ringid to handle pipe requests. */
912ff91c17SVincenzo Maffione 	if (req->nr_mode == NR_REG_PIPE_MASTER ||
922ff91c17SVincenzo Maffione 			req->nr_mode == NR_REG_PIPE_SLAVE) {
932ff91c17SVincenzo Maffione 		char suffix[10];
942ff91c17SVincenzo Maffione 		snprintf(suffix, sizeof(suffix), "%c%d",
952ff91c17SVincenzo Maffione 			(req->nr_mode == NR_REG_PIPE_MASTER ? '{' : '}'),
962ff91c17SVincenzo Maffione 			req->nr_ringid);
972ff91c17SVincenzo Maffione 		if (strlen(hdr->nr_name) + strlen(suffix)
982ff91c17SVincenzo Maffione 					>= sizeof(hdr->nr_name)) {
992ff91c17SVincenzo Maffione 			/* No space for the pipe suffix. */
1002ff91c17SVincenzo Maffione 			return ENOBUFS;
1012ff91c17SVincenzo Maffione 		}
102760fa2abSVincenzo Maffione 		strlcat(hdr->nr_name, suffix, sizeof(hdr->nr_name));
1032ff91c17SVincenzo Maffione 		req->nr_mode = NR_REG_ALL_NIC;
1042ff91c17SVincenzo Maffione 		req->nr_ringid = 0;
1052ff91c17SVincenzo Maffione 	}
1062ff91c17SVincenzo Maffione 	req->nr_flags = nmr->nr_flags & (~NR_REG_MASK);
1072ff91c17SVincenzo Maffione 	if (nmr->nr_ringid & NETMAP_NO_TX_POLL) {
1082ff91c17SVincenzo Maffione 		req->nr_flags |= NR_NO_TX_POLL;
1092ff91c17SVincenzo Maffione 	}
1102ff91c17SVincenzo Maffione 	if (nmr->nr_ringid & NETMAP_DO_RX_POLL) {
1112ff91c17SVincenzo Maffione 		req->nr_flags |= NR_DO_RX_POLL;
1122ff91c17SVincenzo Maffione 	}
1132ff91c17SVincenzo Maffione 	/* nmr->nr_arg1 (nr_pipes) ignored */
1142ff91c17SVincenzo Maffione 	req->nr_extra_bufs = nmr->nr_arg3;
1152ff91c17SVincenzo Maffione 
1162ff91c17SVincenzo Maffione 	return 0;
1172ff91c17SVincenzo Maffione }
1182ff91c17SVincenzo Maffione 
1192ff91c17SVincenzo Maffione /* Convert the legacy 'nmr' struct into one of the nmreq_xyz structs
1202ff91c17SVincenzo Maffione  * (new API). The new struct is dynamically allocated. */
1212ff91c17SVincenzo Maffione static struct nmreq_header *
nmreq_from_legacy(struct nmreq * nmr,u_long ioctl_cmd)1222ff91c17SVincenzo Maffione nmreq_from_legacy(struct nmreq *nmr, u_long ioctl_cmd)
1232ff91c17SVincenzo Maffione {
1242ff91c17SVincenzo Maffione 	struct nmreq_header *hdr = nm_os_malloc(sizeof(*hdr));
1252ff91c17SVincenzo Maffione 
1262ff91c17SVincenzo Maffione 	if (hdr == NULL) {
1272ff91c17SVincenzo Maffione 		goto oom;
1282ff91c17SVincenzo Maffione 	}
1292ff91c17SVincenzo Maffione 
1302ff91c17SVincenzo Maffione 	/* Sanitize nmr->nr_name by adding the string terminator. */
1312ff91c17SVincenzo Maffione 	if (ioctl_cmd == NIOCGINFO || ioctl_cmd == NIOCREGIF) {
1322ff91c17SVincenzo Maffione 		nmr->nr_name[sizeof(nmr->nr_name) - 1] = '\0';
1332ff91c17SVincenzo Maffione 	}
1342ff91c17SVincenzo Maffione 
1352ff91c17SVincenzo Maffione 	/* First prepare the request header. */
1362ff91c17SVincenzo Maffione 	hdr->nr_version = NETMAP_API; /* new API */
137b6e66be2SVincenzo Maffione 	strlcpy(hdr->nr_name, nmr->nr_name, sizeof(nmr->nr_name));
138cfa866f6SMatt Macy 	hdr->nr_options = (uintptr_t)NULL;
139cfa866f6SMatt Macy 	hdr->nr_body = (uintptr_t)NULL;
1402ff91c17SVincenzo Maffione 
1412ff91c17SVincenzo Maffione 	switch (ioctl_cmd) {
1422ff91c17SVincenzo Maffione 	case NIOCREGIF: {
1432ff91c17SVincenzo Maffione 		switch (nmr->nr_cmd) {
1442ff91c17SVincenzo Maffione 		case 0: {
1452ff91c17SVincenzo Maffione 			/* Regular NIOCREGIF operation. */
1462ff91c17SVincenzo Maffione 			struct nmreq_register *req = nm_os_malloc(sizeof(*req));
1472ff91c17SVincenzo Maffione 			if (!req) { goto oom; }
148cfa866f6SMatt Macy 			hdr->nr_body = (uintptr_t)req;
1492ff91c17SVincenzo Maffione 			hdr->nr_reqtype = NETMAP_REQ_REGISTER;
1502ff91c17SVincenzo Maffione 			if (nmreq_register_from_legacy(nmr, hdr, req)) {
1512ff91c17SVincenzo Maffione 				goto oom;
1522ff91c17SVincenzo Maffione 			}
1532ff91c17SVincenzo Maffione 			break;
1542ff91c17SVincenzo Maffione 		}
1552ff91c17SVincenzo Maffione 		case NETMAP_BDG_ATTACH: {
1562ff91c17SVincenzo Maffione 			struct nmreq_vale_attach *req = nm_os_malloc(sizeof(*req));
1572ff91c17SVincenzo Maffione 			if (!req) { goto oom; }
158cfa866f6SMatt Macy 			hdr->nr_body = (uintptr_t)req;
1592ff91c17SVincenzo Maffione 			hdr->nr_reqtype = NETMAP_REQ_VALE_ATTACH;
1602ff91c17SVincenzo Maffione 			if (nmreq_register_from_legacy(nmr, hdr, &req->reg)) {
1612ff91c17SVincenzo Maffione 				goto oom;
1622ff91c17SVincenzo Maffione 			}
1632ff91c17SVincenzo Maffione 			/* Fix nr_mode, starting from nr_arg1. */
1642ff91c17SVincenzo Maffione 			if (nmr->nr_arg1 & NETMAP_BDG_HOST) {
1652ff91c17SVincenzo Maffione 				req->reg.nr_mode = NR_REG_NIC_SW;
1662ff91c17SVincenzo Maffione 			} else {
1672ff91c17SVincenzo Maffione 				req->reg.nr_mode = NR_REG_ALL_NIC;
1682ff91c17SVincenzo Maffione 			}
1692ff91c17SVincenzo Maffione 			break;
1702ff91c17SVincenzo Maffione 		}
1712ff91c17SVincenzo Maffione 		case NETMAP_BDG_DETACH: {
1722ff91c17SVincenzo Maffione 			hdr->nr_reqtype = NETMAP_REQ_VALE_DETACH;
173cfa866f6SMatt Macy 			hdr->nr_body = (uintptr_t)nm_os_malloc(sizeof(struct nmreq_vale_detach));
1742ff91c17SVincenzo Maffione 			break;
1752ff91c17SVincenzo Maffione 		}
1762ff91c17SVincenzo Maffione 		case NETMAP_BDG_VNET_HDR:
1772ff91c17SVincenzo Maffione 		case NETMAP_VNET_HDR_GET: {
1782ff91c17SVincenzo Maffione 			struct nmreq_port_hdr *req = nm_os_malloc(sizeof(*req));
1792ff91c17SVincenzo Maffione 			if (!req) { goto oom; }
180cfa866f6SMatt Macy 			hdr->nr_body = (uintptr_t)req;
1812ff91c17SVincenzo Maffione 			hdr->nr_reqtype = (nmr->nr_cmd == NETMAP_BDG_VNET_HDR) ?
1822ff91c17SVincenzo Maffione 				NETMAP_REQ_PORT_HDR_SET : NETMAP_REQ_PORT_HDR_GET;
1832ff91c17SVincenzo Maffione 			req->nr_hdr_len = nmr->nr_arg1;
1842ff91c17SVincenzo Maffione 			break;
1852ff91c17SVincenzo Maffione 		}
1862ff91c17SVincenzo Maffione 		case NETMAP_BDG_NEWIF : {
1872ff91c17SVincenzo Maffione 			struct nmreq_vale_newif *req = nm_os_malloc(sizeof(*req));
1882ff91c17SVincenzo Maffione 			if (!req) { goto oom; }
189cfa866f6SMatt Macy 			hdr->nr_body = (uintptr_t)req;
1902ff91c17SVincenzo Maffione 			hdr->nr_reqtype = NETMAP_REQ_VALE_NEWIF;
1912ff91c17SVincenzo Maffione 			req->nr_tx_slots = nmr->nr_tx_slots;
1922ff91c17SVincenzo Maffione 			req->nr_rx_slots = nmr->nr_rx_slots;
1932ff91c17SVincenzo Maffione 			req->nr_tx_rings = nmr->nr_tx_rings;
1942ff91c17SVincenzo Maffione 			req->nr_rx_rings = nmr->nr_rx_rings;
1952ff91c17SVincenzo Maffione 			req->nr_mem_id = nmr->nr_arg2;
1962ff91c17SVincenzo Maffione 			break;
1972ff91c17SVincenzo Maffione 		}
1982ff91c17SVincenzo Maffione 		case NETMAP_BDG_DELIF: {
1992ff91c17SVincenzo Maffione 			hdr->nr_reqtype = NETMAP_REQ_VALE_DELIF;
2002ff91c17SVincenzo Maffione 			break;
2012ff91c17SVincenzo Maffione 		}
2022ff91c17SVincenzo Maffione 		case NETMAP_BDG_POLLING_ON:
2032ff91c17SVincenzo Maffione 		case NETMAP_BDG_POLLING_OFF: {
2042ff91c17SVincenzo Maffione 			struct nmreq_vale_polling *req = nm_os_malloc(sizeof(*req));
2052ff91c17SVincenzo Maffione 			if (!req) { goto oom; }
206cfa866f6SMatt Macy 			hdr->nr_body = (uintptr_t)req;
2072ff91c17SVincenzo Maffione 			hdr->nr_reqtype = (nmr->nr_cmd == NETMAP_BDG_POLLING_ON) ?
2082ff91c17SVincenzo Maffione 				NETMAP_REQ_VALE_POLLING_ENABLE :
2092ff91c17SVincenzo Maffione 				NETMAP_REQ_VALE_POLLING_DISABLE;
2102ff91c17SVincenzo Maffione 			switch (nmr->nr_flags & NR_REG_MASK) {
2112ff91c17SVincenzo Maffione 			default:
2122ff91c17SVincenzo Maffione 				req->nr_mode = 0; /* invalid */
2132ff91c17SVincenzo Maffione 				break;
2142ff91c17SVincenzo Maffione 			case NR_REG_ONE_NIC:
2152ff91c17SVincenzo Maffione 				req->nr_mode = NETMAP_POLLING_MODE_MULTI_CPU;
2162ff91c17SVincenzo Maffione 				break;
2172ff91c17SVincenzo Maffione 			case NR_REG_ALL_NIC:
2182ff91c17SVincenzo Maffione 				req->nr_mode = NETMAP_POLLING_MODE_SINGLE_CPU;
2192ff91c17SVincenzo Maffione 				break;
2202ff91c17SVincenzo Maffione 			}
2212ff91c17SVincenzo Maffione 			req->nr_first_cpu_id = nmr->nr_ringid & NETMAP_RING_MASK;
2222ff91c17SVincenzo Maffione 			req->nr_num_polling_cpus = nmr->nr_arg1;
2232ff91c17SVincenzo Maffione 			break;
2242ff91c17SVincenzo Maffione 		}
2252ff91c17SVincenzo Maffione 		case NETMAP_PT_HOST_CREATE:
2262ff91c17SVincenzo Maffione 		case NETMAP_PT_HOST_DELETE: {
227b6e66be2SVincenzo Maffione 			nm_prerr("Netmap passthrough not supported yet");
2282ff91c17SVincenzo Maffione 			return NULL;
2292ff91c17SVincenzo Maffione 			break;
2302ff91c17SVincenzo Maffione 		}
2312ff91c17SVincenzo Maffione 		}
2322ff91c17SVincenzo Maffione 		break;
2332ff91c17SVincenzo Maffione 	}
2342ff91c17SVincenzo Maffione 	case NIOCGINFO: {
2352ff91c17SVincenzo Maffione 		if (nmr->nr_cmd == NETMAP_BDG_LIST) {
2362ff91c17SVincenzo Maffione 			struct nmreq_vale_list *req = nm_os_malloc(sizeof(*req));
2372ff91c17SVincenzo Maffione 			if (!req) { goto oom; }
238cfa866f6SMatt Macy 			hdr->nr_body = (uintptr_t)req;
2392ff91c17SVincenzo Maffione 			hdr->nr_reqtype = NETMAP_REQ_VALE_LIST;
2402ff91c17SVincenzo Maffione 			req->nr_bridge_idx = nmr->nr_arg1;
2412ff91c17SVincenzo Maffione 			req->nr_port_idx = nmr->nr_arg2;
2422ff91c17SVincenzo Maffione 		} else {
2432ff91c17SVincenzo Maffione 			/* Regular NIOCGINFO. */
2442ff91c17SVincenzo Maffione 			struct nmreq_port_info_get *req = nm_os_malloc(sizeof(*req));
2452ff91c17SVincenzo Maffione 			if (!req) { goto oom; }
246cfa866f6SMatt Macy 			hdr->nr_body = (uintptr_t)req;
2472ff91c17SVincenzo Maffione 			hdr->nr_reqtype = NETMAP_REQ_PORT_INFO_GET;
2482ff91c17SVincenzo Maffione 			req->nr_memsize = nmr->nr_memsize;
2492ff91c17SVincenzo Maffione 			req->nr_tx_slots = nmr->nr_tx_slots;
2502ff91c17SVincenzo Maffione 			req->nr_rx_slots = nmr->nr_rx_slots;
2512ff91c17SVincenzo Maffione 			req->nr_tx_rings = nmr->nr_tx_rings;
2522ff91c17SVincenzo Maffione 			req->nr_rx_rings = nmr->nr_rx_rings;
253d12354a5SVincenzo Maffione 			req->nr_host_tx_rings = 0;
254d12354a5SVincenzo Maffione 			req->nr_host_rx_rings = 0;
2552ff91c17SVincenzo Maffione 			req->nr_mem_id = nmr->nr_arg2;
2562ff91c17SVincenzo Maffione 		}
2572ff91c17SVincenzo Maffione 		break;
2582ff91c17SVincenzo Maffione 	}
2592ff91c17SVincenzo Maffione 	}
2602ff91c17SVincenzo Maffione 
2612ff91c17SVincenzo Maffione 	return hdr;
2622ff91c17SVincenzo Maffione oom:
2632ff91c17SVincenzo Maffione 	if (hdr) {
2642ff91c17SVincenzo Maffione 		if (hdr->nr_body) {
265cfa866f6SMatt Macy 			nm_os_free((void *)(uintptr_t)hdr->nr_body);
2662ff91c17SVincenzo Maffione 		}
2672ff91c17SVincenzo Maffione 		nm_os_free(hdr);
2682ff91c17SVincenzo Maffione 	}
269b6e66be2SVincenzo Maffione 	nm_prerr("Failed to allocate memory for nmreq_xyz struct");
2702ff91c17SVincenzo Maffione 
2712ff91c17SVincenzo Maffione 	return NULL;
2722ff91c17SVincenzo Maffione }
2732ff91c17SVincenzo Maffione 
2742ff91c17SVincenzo Maffione static void
nmreq_register_to_legacy(const struct nmreq_register * req,struct nmreq * nmr)2752ff91c17SVincenzo Maffione nmreq_register_to_legacy(const struct nmreq_register *req, struct nmreq *nmr)
2762ff91c17SVincenzo Maffione {
2772ff91c17SVincenzo Maffione 	nmr->nr_offset = req->nr_offset;
2782ff91c17SVincenzo Maffione 	nmr->nr_memsize = req->nr_memsize;
2792ff91c17SVincenzo Maffione 	nmr->nr_tx_slots = req->nr_tx_slots;
2802ff91c17SVincenzo Maffione 	nmr->nr_rx_slots = req->nr_rx_slots;
2812ff91c17SVincenzo Maffione 	nmr->nr_tx_rings = req->nr_tx_rings;
2822ff91c17SVincenzo Maffione 	nmr->nr_rx_rings = req->nr_rx_rings;
2832ff91c17SVincenzo Maffione 	nmr->nr_arg2 = req->nr_mem_id;
2842ff91c17SVincenzo Maffione 	nmr->nr_arg3 = req->nr_extra_bufs;
2852ff91c17SVincenzo Maffione }
2862ff91c17SVincenzo Maffione 
2872ff91c17SVincenzo Maffione /* Convert a nmreq_xyz struct (new API) to the legacy 'nmr' struct.
2882ff91c17SVincenzo Maffione  * It also frees the nmreq_xyz struct, as it was allocated by
2892ff91c17SVincenzo Maffione  * nmreq_from_legacy(). */
2902ff91c17SVincenzo Maffione static int
nmreq_to_legacy(struct nmreq_header * hdr,struct nmreq * nmr)2912ff91c17SVincenzo Maffione nmreq_to_legacy(struct nmreq_header *hdr, struct nmreq *nmr)
2922ff91c17SVincenzo Maffione {
2932ff91c17SVincenzo Maffione 	int ret = 0;
2942ff91c17SVincenzo Maffione 
2952ff91c17SVincenzo Maffione 	/* We only write-back the fields that the user expects to be
2962ff91c17SVincenzo Maffione 	 * written back. */
2972ff91c17SVincenzo Maffione 	switch (hdr->nr_reqtype) {
2982ff91c17SVincenzo Maffione 	case NETMAP_REQ_REGISTER: {
2992ff91c17SVincenzo Maffione 		struct nmreq_register *req =
300cfa866f6SMatt Macy 			(struct nmreq_register *)(uintptr_t)hdr->nr_body;
3012ff91c17SVincenzo Maffione 		nmreq_register_to_legacy(req, nmr);
3022ff91c17SVincenzo Maffione 		break;
3032ff91c17SVincenzo Maffione 	}
3042ff91c17SVincenzo Maffione 	case NETMAP_REQ_PORT_INFO_GET: {
3052ff91c17SVincenzo Maffione 		struct nmreq_port_info_get *req =
306cfa866f6SMatt Macy 			(struct nmreq_port_info_get *)(uintptr_t)hdr->nr_body;
3072ff91c17SVincenzo Maffione 		nmr->nr_memsize = req->nr_memsize;
3082ff91c17SVincenzo Maffione 		nmr->nr_tx_slots = req->nr_tx_slots;
3092ff91c17SVincenzo Maffione 		nmr->nr_rx_slots = req->nr_rx_slots;
3102ff91c17SVincenzo Maffione 		nmr->nr_tx_rings = req->nr_tx_rings;
3112ff91c17SVincenzo Maffione 		nmr->nr_rx_rings = req->nr_rx_rings;
3122ff91c17SVincenzo Maffione 		nmr->nr_arg2 = req->nr_mem_id;
3132ff91c17SVincenzo Maffione 		break;
3142ff91c17SVincenzo Maffione 	}
3152ff91c17SVincenzo Maffione 	case NETMAP_REQ_VALE_ATTACH: {
3162ff91c17SVincenzo Maffione 		struct nmreq_vale_attach *req =
317cfa866f6SMatt Macy 			(struct nmreq_vale_attach *)(uintptr_t)hdr->nr_body;
3182ff91c17SVincenzo Maffione 		nmreq_register_to_legacy(&req->reg, nmr);
3192ff91c17SVincenzo Maffione 		break;
3202ff91c17SVincenzo Maffione 	}
3212ff91c17SVincenzo Maffione 	case NETMAP_REQ_VALE_DETACH: {
3222ff91c17SVincenzo Maffione 		break;
3232ff91c17SVincenzo Maffione 	}
3242ff91c17SVincenzo Maffione 	case NETMAP_REQ_VALE_LIST: {
3252ff91c17SVincenzo Maffione 		struct nmreq_vale_list *req =
326cfa866f6SMatt Macy 			(struct nmreq_vale_list *)(uintptr_t)hdr->nr_body;
327b6e66be2SVincenzo Maffione 		strlcpy(nmr->nr_name, hdr->nr_name, sizeof(nmr->nr_name));
3282ff91c17SVincenzo Maffione 		nmr->nr_arg1 = req->nr_bridge_idx;
3292ff91c17SVincenzo Maffione 		nmr->nr_arg2 = req->nr_port_idx;
3302ff91c17SVincenzo Maffione 		break;
3312ff91c17SVincenzo Maffione 	}
3322ff91c17SVincenzo Maffione 	case NETMAP_REQ_PORT_HDR_SET:
3332ff91c17SVincenzo Maffione 	case NETMAP_REQ_PORT_HDR_GET: {
3342ff91c17SVincenzo Maffione 		struct nmreq_port_hdr *req =
335cfa866f6SMatt Macy 			(struct nmreq_port_hdr *)(uintptr_t)hdr->nr_body;
3362ff91c17SVincenzo Maffione 		nmr->nr_arg1 = req->nr_hdr_len;
3372ff91c17SVincenzo Maffione 		break;
3382ff91c17SVincenzo Maffione 	}
3392ff91c17SVincenzo Maffione 	case NETMAP_REQ_VALE_NEWIF: {
3402ff91c17SVincenzo Maffione 		struct nmreq_vale_newif *req =
341cfa866f6SMatt Macy 			(struct nmreq_vale_newif *)(uintptr_t)hdr->nr_body;
3422ff91c17SVincenzo Maffione 		nmr->nr_tx_slots = req->nr_tx_slots;
3432ff91c17SVincenzo Maffione 		nmr->nr_rx_slots = req->nr_rx_slots;
3442ff91c17SVincenzo Maffione 		nmr->nr_tx_rings = req->nr_tx_rings;
3452ff91c17SVincenzo Maffione 		nmr->nr_rx_rings = req->nr_rx_rings;
3462ff91c17SVincenzo Maffione 		nmr->nr_arg2 = req->nr_mem_id;
3472ff91c17SVincenzo Maffione 		break;
3482ff91c17SVincenzo Maffione 	}
3492ff91c17SVincenzo Maffione 	case NETMAP_REQ_VALE_DELIF:
3502ff91c17SVincenzo Maffione 	case NETMAP_REQ_VALE_POLLING_ENABLE:
3512ff91c17SVincenzo Maffione 	case NETMAP_REQ_VALE_POLLING_DISABLE: {
3522ff91c17SVincenzo Maffione 		break;
3532ff91c17SVincenzo Maffione 	}
3542ff91c17SVincenzo Maffione 	}
3552ff91c17SVincenzo Maffione 
3562ff91c17SVincenzo Maffione 	return ret;
3572ff91c17SVincenzo Maffione }
3582ff91c17SVincenzo Maffione 
3592ff91c17SVincenzo Maffione int
netmap_ioctl_legacy(struct netmap_priv_d * priv,u_long cmd,caddr_t data,struct thread * td)3602ff91c17SVincenzo Maffione netmap_ioctl_legacy(struct netmap_priv_d *priv, u_long cmd, caddr_t data,
3612ff91c17SVincenzo Maffione 			struct thread *td)
3622ff91c17SVincenzo Maffione {
3632ff91c17SVincenzo Maffione 	int error = 0;
3642ff91c17SVincenzo Maffione 
3652ff91c17SVincenzo Maffione 	switch (cmd) {
3662ff91c17SVincenzo Maffione 	case NIOCGINFO:
3672ff91c17SVincenzo Maffione 	case NIOCREGIF: {
3682ff91c17SVincenzo Maffione 		/* Request for the legacy control API. Convert it to a
3692ff91c17SVincenzo Maffione 		 * NIOCCTRL request. */
3702ff91c17SVincenzo Maffione 		struct nmreq *nmr = (struct nmreq *) data;
37175f4f3edSVincenzo Maffione 		struct nmreq_header *hdr;
37275f4f3edSVincenzo Maffione 
373d12354a5SVincenzo Maffione 		if (nmr->nr_version < 14) {
374d12354a5SVincenzo Maffione 			nm_prerr("Minimum supported API is 14 (requested %u)",
37575f4f3edSVincenzo Maffione 			    nmr->nr_version);
37675f4f3edSVincenzo Maffione 			return EINVAL;
37775f4f3edSVincenzo Maffione 		}
37875f4f3edSVincenzo Maffione 		hdr = nmreq_from_legacy(nmr, cmd);
3792ff91c17SVincenzo Maffione 		if (hdr == NULL) { /* out of memory */
3802ff91c17SVincenzo Maffione 			return ENOMEM;
3812ff91c17SVincenzo Maffione 		}
3822ff91c17SVincenzo Maffione 		error = netmap_ioctl(priv, NIOCCTRL, (caddr_t)hdr, td,
3832ff91c17SVincenzo Maffione 					/*nr_body_is_user=*/0);
3842ff91c17SVincenzo Maffione 		if (error == 0) {
3852ff91c17SVincenzo Maffione 			nmreq_to_legacy(hdr, nmr);
3862ff91c17SVincenzo Maffione 		}
3872ff91c17SVincenzo Maffione 		if (hdr->nr_body) {
388cfa866f6SMatt Macy 			nm_os_free((void *)(uintptr_t)hdr->nr_body);
3892ff91c17SVincenzo Maffione 		}
3902ff91c17SVincenzo Maffione 		nm_os_free(hdr);
3912ff91c17SVincenzo Maffione 		break;
3922ff91c17SVincenzo Maffione 	}
3932ff91c17SVincenzo Maffione #ifdef WITH_VALE
3942ff91c17SVincenzo Maffione 	case NIOCCONFIG: {
3952ff91c17SVincenzo Maffione 		struct nm_ifreq *nr = (struct nm_ifreq *)data;
3962ff91c17SVincenzo Maffione 		error = netmap_bdg_config(nr);
3972ff91c17SVincenzo Maffione 		break;
3982ff91c17SVincenzo Maffione 	}
3992ff91c17SVincenzo Maffione #endif
4002ff91c17SVincenzo Maffione #ifdef __FreeBSD__
4012ff91c17SVincenzo Maffione 	case FIONBIO:
4022ff91c17SVincenzo Maffione 	case FIOASYNC:
40375f4f3edSVincenzo Maffione 		/* FIONBIO/FIOASYNC are no-ops. */
4042ff91c17SVincenzo Maffione 		break;
4052ff91c17SVincenzo Maffione 
4062ff91c17SVincenzo Maffione 	case BIOCIMMEDIATE:
4072ff91c17SVincenzo Maffione 	case BIOCGHDRCMPLT:
4082ff91c17SVincenzo Maffione 	case BIOCSHDRCMPLT:
4092ff91c17SVincenzo Maffione 	case BIOCSSEESENT:
41075f4f3edSVincenzo Maffione 		/* Ignore these commands. */
4112ff91c17SVincenzo Maffione 		break;
4122ff91c17SVincenzo Maffione 
4132ff91c17SVincenzo Maffione 	default:	/* allow device-specific ioctls */
4142ff91c17SVincenzo Maffione 	    {
4152ff91c17SVincenzo Maffione 		struct nmreq *nmr = (struct nmreq *)data;
416e330262fSJustin Hibbits 		if_t ifp = ifunit_ref(nmr->nr_name);
4172ff91c17SVincenzo Maffione 		if (ifp == NULL) {
4182ff91c17SVincenzo Maffione 			error = ENXIO;
4192ff91c17SVincenzo Maffione 		} else {
4202ff91c17SVincenzo Maffione 			struct socket so;
4212ff91c17SVincenzo Maffione 
4222ff91c17SVincenzo Maffione 			bzero(&so, sizeof(so));
423e330262fSJustin Hibbits 			so.so_vnet = if_getvnet(ifp);
4242ff91c17SVincenzo Maffione 			// so->so_proto not null.
4252ff91c17SVincenzo Maffione 			error = ifioctl(&so, cmd, data, td);
4262ff91c17SVincenzo Maffione 			if_rele(ifp);
4272ff91c17SVincenzo Maffione 		}
4282ff91c17SVincenzo Maffione 		break;
4292ff91c17SVincenzo Maffione 	    }
4302ff91c17SVincenzo Maffione 
4312ff91c17SVincenzo Maffione #else /* linux */
4322ff91c17SVincenzo Maffione 	default:
4332ff91c17SVincenzo Maffione 		error = EOPNOTSUPP;
4342ff91c17SVincenzo Maffione #endif /* linux */
4352ff91c17SVincenzo Maffione 	}
4362ff91c17SVincenzo Maffione 
4372ff91c17SVincenzo Maffione 	return error;
4382ff91c17SVincenzo Maffione }
439