1*2ff91c17SVincenzo Maffione /*- 2*2ff91c17SVincenzo Maffione * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3*2ff91c17SVincenzo Maffione * 4*2ff91c17SVincenzo Maffione * Copyright (C) 2018 Vincenzo Maffione 5*2ff91c17SVincenzo Maffione * All rights reserved. 6*2ff91c17SVincenzo Maffione * 7*2ff91c17SVincenzo Maffione * Redistribution and use in source and binary forms, with or without 8*2ff91c17SVincenzo Maffione * modification, are permitted provided that the following conditions 9*2ff91c17SVincenzo Maffione * are met: 10*2ff91c17SVincenzo Maffione * 1. Redistributions of source code must retain the above copyright 11*2ff91c17SVincenzo Maffione * notice, this list of conditions and the following disclaimer. 12*2ff91c17SVincenzo Maffione * 2. Redistributions in binary form must reproduce the above copyright 13*2ff91c17SVincenzo Maffione * notice, this list of conditions and the following disclaimer in the 14*2ff91c17SVincenzo Maffione * documentation and/or other materials provided with the distribution. 15*2ff91c17SVincenzo Maffione * 16*2ff91c17SVincenzo Maffione * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17*2ff91c17SVincenzo Maffione * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18*2ff91c17SVincenzo Maffione * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19*2ff91c17SVincenzo Maffione * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20*2ff91c17SVincenzo Maffione * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21*2ff91c17SVincenzo Maffione * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22*2ff91c17SVincenzo Maffione * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23*2ff91c17SVincenzo Maffione * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24*2ff91c17SVincenzo Maffione * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25*2ff91c17SVincenzo Maffione * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26*2ff91c17SVincenzo Maffione * SUCH DAMAGE. 27*2ff91c17SVincenzo Maffione */ 28*2ff91c17SVincenzo Maffione 29*2ff91c17SVincenzo Maffione /* $FreeBSD$ */ 30*2ff91c17SVincenzo Maffione 31*2ff91c17SVincenzo Maffione #if defined(__FreeBSD__) 32*2ff91c17SVincenzo Maffione #include <sys/cdefs.h> /* prerequisite */ 33*2ff91c17SVincenzo Maffione #include <sys/types.h> 34*2ff91c17SVincenzo Maffione #include <sys/param.h> /* defines used in kernel.h */ 35*2ff91c17SVincenzo Maffione #include <sys/filio.h> /* FIONBIO */ 36*2ff91c17SVincenzo Maffione #include <sys/malloc.h> 37*2ff91c17SVincenzo Maffione #include <sys/socketvar.h> /* struct socket */ 38*2ff91c17SVincenzo Maffione #include <sys/socket.h> /* sockaddrs */ 39*2ff91c17SVincenzo Maffione #include <sys/sysctl.h> 40*2ff91c17SVincenzo Maffione #include <net/if.h> 41*2ff91c17SVincenzo Maffione #include <net/if_var.h> 42*2ff91c17SVincenzo Maffione #include <net/bpf.h> /* BIOCIMMEDIATE */ 43*2ff91c17SVincenzo Maffione #include <machine/bus.h> /* bus_dmamap_* */ 44*2ff91c17SVincenzo Maffione #include <sys/endian.h> 45*2ff91c17SVincenzo Maffione #elif defined(linux) 46*2ff91c17SVincenzo Maffione #include "bsd_glue.h" 47*2ff91c17SVincenzo Maffione #elif defined(__APPLE__) 48*2ff91c17SVincenzo Maffione #warning OSX support is only partial 49*2ff91c17SVincenzo Maffione #include "osx_glue.h" 50*2ff91c17SVincenzo Maffione #elif defined (_WIN32) 51*2ff91c17SVincenzo Maffione #include "win_glue.h" 52*2ff91c17SVincenzo Maffione #endif 53*2ff91c17SVincenzo Maffione 54*2ff91c17SVincenzo Maffione /* 55*2ff91c17SVincenzo Maffione * common headers 56*2ff91c17SVincenzo Maffione */ 57*2ff91c17SVincenzo Maffione #include <net/netmap.h> 58*2ff91c17SVincenzo Maffione #include <dev/netmap/netmap_kern.h> 59*2ff91c17SVincenzo Maffione 60*2ff91c17SVincenzo Maffione static int 61*2ff91c17SVincenzo Maffione nmreq_register_from_legacy(struct nmreq *nmr, struct nmreq_header *hdr, 62*2ff91c17SVincenzo Maffione struct nmreq_register *req) 63*2ff91c17SVincenzo Maffione { 64*2ff91c17SVincenzo Maffione req->nr_offset = nmr->nr_offset; 65*2ff91c17SVincenzo Maffione req->nr_memsize = nmr->nr_memsize; 66*2ff91c17SVincenzo Maffione req->nr_tx_slots = nmr->nr_tx_slots; 67*2ff91c17SVincenzo Maffione req->nr_rx_slots = nmr->nr_rx_slots; 68*2ff91c17SVincenzo Maffione req->nr_tx_rings = nmr->nr_tx_rings; 69*2ff91c17SVincenzo Maffione req->nr_rx_rings = nmr->nr_rx_rings; 70*2ff91c17SVincenzo Maffione req->nr_mem_id = nmr->nr_arg2; 71*2ff91c17SVincenzo Maffione req->nr_ringid = nmr->nr_ringid & NETMAP_RING_MASK; 72*2ff91c17SVincenzo Maffione if ((nmr->nr_flags & NR_REG_MASK) == NR_REG_DEFAULT) { 73*2ff91c17SVincenzo Maffione /* Convert the older nmr->nr_ringid (original 74*2ff91c17SVincenzo Maffione * netmap control API) to nmr->nr_flags. */ 75*2ff91c17SVincenzo Maffione u_int regmode = NR_REG_DEFAULT; 76*2ff91c17SVincenzo Maffione if (req->nr_ringid & NETMAP_SW_RING) { 77*2ff91c17SVincenzo Maffione regmode = NR_REG_SW; 78*2ff91c17SVincenzo Maffione } else if (req->nr_ringid & NETMAP_HW_RING) { 79*2ff91c17SVincenzo Maffione regmode = NR_REG_ONE_NIC; 80*2ff91c17SVincenzo Maffione } else { 81*2ff91c17SVincenzo Maffione regmode = NR_REG_ALL_NIC; 82*2ff91c17SVincenzo Maffione } 83*2ff91c17SVincenzo Maffione nmr->nr_flags = regmode | 84*2ff91c17SVincenzo Maffione (nmr->nr_flags & (~NR_REG_MASK)); 85*2ff91c17SVincenzo Maffione } 86*2ff91c17SVincenzo Maffione req->nr_mode = nmr->nr_flags & NR_REG_MASK; 87*2ff91c17SVincenzo Maffione /* Fix nr_name, nr_mode and nr_ringid to handle pipe requests. */ 88*2ff91c17SVincenzo Maffione if (req->nr_mode == NR_REG_PIPE_MASTER || 89*2ff91c17SVincenzo Maffione req->nr_mode == NR_REG_PIPE_SLAVE) { 90*2ff91c17SVincenzo Maffione char suffix[10]; 91*2ff91c17SVincenzo Maffione snprintf(suffix, sizeof(suffix), "%c%d", 92*2ff91c17SVincenzo Maffione (req->nr_mode == NR_REG_PIPE_MASTER ? '{' : '}'), 93*2ff91c17SVincenzo Maffione req->nr_ringid); 94*2ff91c17SVincenzo Maffione if (strlen(hdr->nr_name) + strlen(suffix) 95*2ff91c17SVincenzo Maffione >= sizeof(hdr->nr_name)) { 96*2ff91c17SVincenzo Maffione /* No space for the pipe suffix. */ 97*2ff91c17SVincenzo Maffione return ENOBUFS; 98*2ff91c17SVincenzo Maffione } 99*2ff91c17SVincenzo Maffione strncat(hdr->nr_name, suffix, strlen(suffix)); 100*2ff91c17SVincenzo Maffione req->nr_mode = NR_REG_ALL_NIC; 101*2ff91c17SVincenzo Maffione req->nr_ringid = 0; 102*2ff91c17SVincenzo Maffione } 103*2ff91c17SVincenzo Maffione req->nr_flags = nmr->nr_flags & (~NR_REG_MASK); 104*2ff91c17SVincenzo Maffione if (nmr->nr_ringid & NETMAP_NO_TX_POLL) { 105*2ff91c17SVincenzo Maffione req->nr_flags |= NR_NO_TX_POLL; 106*2ff91c17SVincenzo Maffione } 107*2ff91c17SVincenzo Maffione if (nmr->nr_ringid & NETMAP_DO_RX_POLL) { 108*2ff91c17SVincenzo Maffione req->nr_flags |= NR_DO_RX_POLL; 109*2ff91c17SVincenzo Maffione } 110*2ff91c17SVincenzo Maffione /* nmr->nr_arg1 (nr_pipes) ignored */ 111*2ff91c17SVincenzo Maffione req->nr_extra_bufs = nmr->nr_arg3; 112*2ff91c17SVincenzo Maffione 113*2ff91c17SVincenzo Maffione return 0; 114*2ff91c17SVincenzo Maffione } 115*2ff91c17SVincenzo Maffione 116*2ff91c17SVincenzo Maffione /* Convert the legacy 'nmr' struct into one of the nmreq_xyz structs 117*2ff91c17SVincenzo Maffione * (new API). The new struct is dynamically allocated. */ 118*2ff91c17SVincenzo Maffione static struct nmreq_header * 119*2ff91c17SVincenzo Maffione nmreq_from_legacy(struct nmreq *nmr, u_long ioctl_cmd) 120*2ff91c17SVincenzo Maffione { 121*2ff91c17SVincenzo Maffione struct nmreq_header *hdr = nm_os_malloc(sizeof(*hdr)); 122*2ff91c17SVincenzo Maffione 123*2ff91c17SVincenzo Maffione if (hdr == NULL) { 124*2ff91c17SVincenzo Maffione goto oom; 125*2ff91c17SVincenzo Maffione } 126*2ff91c17SVincenzo Maffione 127*2ff91c17SVincenzo Maffione /* Sanitize nmr->nr_name by adding the string terminator. */ 128*2ff91c17SVincenzo Maffione if (ioctl_cmd == NIOCGINFO || ioctl_cmd == NIOCREGIF) { 129*2ff91c17SVincenzo Maffione nmr->nr_name[sizeof(nmr->nr_name) - 1] = '\0'; 130*2ff91c17SVincenzo Maffione } 131*2ff91c17SVincenzo Maffione 132*2ff91c17SVincenzo Maffione /* First prepare the request header. */ 133*2ff91c17SVincenzo Maffione hdr->nr_version = NETMAP_API; /* new API */ 134*2ff91c17SVincenzo Maffione strncpy(hdr->nr_name, nmr->nr_name, sizeof(nmr->nr_name)); 135*2ff91c17SVincenzo Maffione hdr->nr_options = (uint64_t)NULL; 136*2ff91c17SVincenzo Maffione hdr->nr_body = (uint64_t)NULL; 137*2ff91c17SVincenzo Maffione 138*2ff91c17SVincenzo Maffione switch (ioctl_cmd) { 139*2ff91c17SVincenzo Maffione case NIOCREGIF: { 140*2ff91c17SVincenzo Maffione switch (nmr->nr_cmd) { 141*2ff91c17SVincenzo Maffione case 0: { 142*2ff91c17SVincenzo Maffione /* Regular NIOCREGIF operation. */ 143*2ff91c17SVincenzo Maffione struct nmreq_register *req = nm_os_malloc(sizeof(*req)); 144*2ff91c17SVincenzo Maffione if (!req) { goto oom; } 145*2ff91c17SVincenzo Maffione hdr->nr_body = (uint64_t)req; 146*2ff91c17SVincenzo Maffione hdr->nr_reqtype = NETMAP_REQ_REGISTER; 147*2ff91c17SVincenzo Maffione if (nmreq_register_from_legacy(nmr, hdr, req)) { 148*2ff91c17SVincenzo Maffione goto oom; 149*2ff91c17SVincenzo Maffione } 150*2ff91c17SVincenzo Maffione break; 151*2ff91c17SVincenzo Maffione } 152*2ff91c17SVincenzo Maffione case NETMAP_BDG_ATTACH: { 153*2ff91c17SVincenzo Maffione struct nmreq_vale_attach *req = nm_os_malloc(sizeof(*req)); 154*2ff91c17SVincenzo Maffione if (!req) { goto oom; } 155*2ff91c17SVincenzo Maffione hdr->nr_body = (uint64_t)req; 156*2ff91c17SVincenzo Maffione hdr->nr_reqtype = NETMAP_REQ_VALE_ATTACH; 157*2ff91c17SVincenzo Maffione if (nmreq_register_from_legacy(nmr, hdr, &req->reg)) { 158*2ff91c17SVincenzo Maffione goto oom; 159*2ff91c17SVincenzo Maffione } 160*2ff91c17SVincenzo Maffione /* Fix nr_mode, starting from nr_arg1. */ 161*2ff91c17SVincenzo Maffione if (nmr->nr_arg1 & NETMAP_BDG_HOST) { 162*2ff91c17SVincenzo Maffione req->reg.nr_mode = NR_REG_NIC_SW; 163*2ff91c17SVincenzo Maffione } else { 164*2ff91c17SVincenzo Maffione req->reg.nr_mode = NR_REG_ALL_NIC; 165*2ff91c17SVincenzo Maffione } 166*2ff91c17SVincenzo Maffione break; 167*2ff91c17SVincenzo Maffione } 168*2ff91c17SVincenzo Maffione case NETMAP_BDG_DETACH: { 169*2ff91c17SVincenzo Maffione hdr->nr_reqtype = NETMAP_REQ_VALE_DETACH; 170*2ff91c17SVincenzo Maffione hdr->nr_body = (uint64_t)nm_os_malloc(sizeof(struct nmreq_vale_detach)); 171*2ff91c17SVincenzo Maffione break; 172*2ff91c17SVincenzo Maffione } 173*2ff91c17SVincenzo Maffione case NETMAP_BDG_VNET_HDR: 174*2ff91c17SVincenzo Maffione case NETMAP_VNET_HDR_GET: { 175*2ff91c17SVincenzo Maffione struct nmreq_port_hdr *req = nm_os_malloc(sizeof(*req)); 176*2ff91c17SVincenzo Maffione if (!req) { goto oom; } 177*2ff91c17SVincenzo Maffione hdr->nr_body = (uint64_t)req; 178*2ff91c17SVincenzo Maffione hdr->nr_reqtype = (nmr->nr_cmd == NETMAP_BDG_VNET_HDR) ? 179*2ff91c17SVincenzo Maffione NETMAP_REQ_PORT_HDR_SET : NETMAP_REQ_PORT_HDR_GET; 180*2ff91c17SVincenzo Maffione req->nr_hdr_len = nmr->nr_arg1; 181*2ff91c17SVincenzo Maffione break; 182*2ff91c17SVincenzo Maffione } 183*2ff91c17SVincenzo Maffione case NETMAP_BDG_NEWIF : { 184*2ff91c17SVincenzo Maffione struct nmreq_vale_newif *req = nm_os_malloc(sizeof(*req)); 185*2ff91c17SVincenzo Maffione if (!req) { goto oom; } 186*2ff91c17SVincenzo Maffione hdr->nr_body = (uint64_t)req; 187*2ff91c17SVincenzo Maffione hdr->nr_reqtype = NETMAP_REQ_VALE_NEWIF; 188*2ff91c17SVincenzo Maffione req->nr_tx_slots = nmr->nr_tx_slots; 189*2ff91c17SVincenzo Maffione req->nr_rx_slots = nmr->nr_rx_slots; 190*2ff91c17SVincenzo Maffione req->nr_tx_rings = nmr->nr_tx_rings; 191*2ff91c17SVincenzo Maffione req->nr_rx_rings = nmr->nr_rx_rings; 192*2ff91c17SVincenzo Maffione req->nr_mem_id = nmr->nr_arg2; 193*2ff91c17SVincenzo Maffione break; 194*2ff91c17SVincenzo Maffione } 195*2ff91c17SVincenzo Maffione case NETMAP_BDG_DELIF: { 196*2ff91c17SVincenzo Maffione hdr->nr_reqtype = NETMAP_REQ_VALE_DELIF; 197*2ff91c17SVincenzo Maffione break; 198*2ff91c17SVincenzo Maffione } 199*2ff91c17SVincenzo Maffione case NETMAP_BDG_POLLING_ON: 200*2ff91c17SVincenzo Maffione case NETMAP_BDG_POLLING_OFF: { 201*2ff91c17SVincenzo Maffione struct nmreq_vale_polling *req = nm_os_malloc(sizeof(*req)); 202*2ff91c17SVincenzo Maffione if (!req) { goto oom; } 203*2ff91c17SVincenzo Maffione hdr->nr_body = (uint64_t)req; 204*2ff91c17SVincenzo Maffione hdr->nr_reqtype = (nmr->nr_cmd == NETMAP_BDG_POLLING_ON) ? 205*2ff91c17SVincenzo Maffione NETMAP_REQ_VALE_POLLING_ENABLE : 206*2ff91c17SVincenzo Maffione NETMAP_REQ_VALE_POLLING_DISABLE; 207*2ff91c17SVincenzo Maffione switch (nmr->nr_flags & NR_REG_MASK) { 208*2ff91c17SVincenzo Maffione default: 209*2ff91c17SVincenzo Maffione req->nr_mode = 0; /* invalid */ 210*2ff91c17SVincenzo Maffione break; 211*2ff91c17SVincenzo Maffione case NR_REG_ONE_NIC: 212*2ff91c17SVincenzo Maffione req->nr_mode = NETMAP_POLLING_MODE_MULTI_CPU; 213*2ff91c17SVincenzo Maffione break; 214*2ff91c17SVincenzo Maffione case NR_REG_ALL_NIC: 215*2ff91c17SVincenzo Maffione req->nr_mode = NETMAP_POLLING_MODE_SINGLE_CPU; 216*2ff91c17SVincenzo Maffione break; 217*2ff91c17SVincenzo Maffione } 218*2ff91c17SVincenzo Maffione req->nr_first_cpu_id = nmr->nr_ringid & NETMAP_RING_MASK; 219*2ff91c17SVincenzo Maffione req->nr_num_polling_cpus = nmr->nr_arg1; 220*2ff91c17SVincenzo Maffione break; 221*2ff91c17SVincenzo Maffione } 222*2ff91c17SVincenzo Maffione case NETMAP_PT_HOST_CREATE: 223*2ff91c17SVincenzo Maffione case NETMAP_PT_HOST_DELETE: { 224*2ff91c17SVincenzo Maffione D("Netmap passthrough not supported yet"); 225*2ff91c17SVincenzo Maffione return NULL; 226*2ff91c17SVincenzo Maffione break; 227*2ff91c17SVincenzo Maffione } 228*2ff91c17SVincenzo Maffione } 229*2ff91c17SVincenzo Maffione break; 230*2ff91c17SVincenzo Maffione } 231*2ff91c17SVincenzo Maffione case NIOCGINFO: { 232*2ff91c17SVincenzo Maffione if (nmr->nr_cmd == NETMAP_BDG_LIST) { 233*2ff91c17SVincenzo Maffione struct nmreq_vale_list *req = nm_os_malloc(sizeof(*req)); 234*2ff91c17SVincenzo Maffione if (!req) { goto oom; } 235*2ff91c17SVincenzo Maffione hdr->nr_body = (uint64_t)req; 236*2ff91c17SVincenzo Maffione hdr->nr_reqtype = NETMAP_REQ_VALE_LIST; 237*2ff91c17SVincenzo Maffione req->nr_bridge_idx = nmr->nr_arg1; 238*2ff91c17SVincenzo Maffione req->nr_port_idx = nmr->nr_arg2; 239*2ff91c17SVincenzo Maffione } else { 240*2ff91c17SVincenzo Maffione /* Regular NIOCGINFO. */ 241*2ff91c17SVincenzo Maffione struct nmreq_port_info_get *req = nm_os_malloc(sizeof(*req)); 242*2ff91c17SVincenzo Maffione if (!req) { goto oom; } 243*2ff91c17SVincenzo Maffione hdr->nr_body = (uint64_t)req; 244*2ff91c17SVincenzo Maffione hdr->nr_reqtype = NETMAP_REQ_PORT_INFO_GET; 245*2ff91c17SVincenzo Maffione req->nr_offset = nmr->nr_offset; 246*2ff91c17SVincenzo Maffione req->nr_memsize = nmr->nr_memsize; 247*2ff91c17SVincenzo Maffione req->nr_tx_slots = nmr->nr_tx_slots; 248*2ff91c17SVincenzo Maffione req->nr_rx_slots = nmr->nr_rx_slots; 249*2ff91c17SVincenzo Maffione req->nr_tx_rings = nmr->nr_tx_rings; 250*2ff91c17SVincenzo Maffione req->nr_rx_rings = nmr->nr_rx_rings; 251*2ff91c17SVincenzo Maffione req->nr_mem_id = nmr->nr_arg2; 252*2ff91c17SVincenzo Maffione } 253*2ff91c17SVincenzo Maffione break; 254*2ff91c17SVincenzo Maffione } 255*2ff91c17SVincenzo Maffione } 256*2ff91c17SVincenzo Maffione 257*2ff91c17SVincenzo Maffione return hdr; 258*2ff91c17SVincenzo Maffione oom: 259*2ff91c17SVincenzo Maffione if (hdr) { 260*2ff91c17SVincenzo Maffione if (hdr->nr_body) { 261*2ff91c17SVincenzo Maffione nm_os_free((void *)hdr->nr_body); 262*2ff91c17SVincenzo Maffione } 263*2ff91c17SVincenzo Maffione nm_os_free(hdr); 264*2ff91c17SVincenzo Maffione } 265*2ff91c17SVincenzo Maffione D("Failed to allocate memory for nmreq_xyz struct"); 266*2ff91c17SVincenzo Maffione 267*2ff91c17SVincenzo Maffione return NULL; 268*2ff91c17SVincenzo Maffione } 269*2ff91c17SVincenzo Maffione 270*2ff91c17SVincenzo Maffione static void 271*2ff91c17SVincenzo Maffione nmreq_register_to_legacy(const struct nmreq_register *req, struct nmreq *nmr) 272*2ff91c17SVincenzo Maffione { 273*2ff91c17SVincenzo Maffione nmr->nr_offset = req->nr_offset; 274*2ff91c17SVincenzo Maffione nmr->nr_memsize = req->nr_memsize; 275*2ff91c17SVincenzo Maffione nmr->nr_tx_slots = req->nr_tx_slots; 276*2ff91c17SVincenzo Maffione nmr->nr_rx_slots = req->nr_rx_slots; 277*2ff91c17SVincenzo Maffione nmr->nr_tx_rings = req->nr_tx_rings; 278*2ff91c17SVincenzo Maffione nmr->nr_rx_rings = req->nr_rx_rings; 279*2ff91c17SVincenzo Maffione nmr->nr_arg2 = req->nr_mem_id; 280*2ff91c17SVincenzo Maffione nmr->nr_arg3 = req->nr_extra_bufs; 281*2ff91c17SVincenzo Maffione } 282*2ff91c17SVincenzo Maffione 283*2ff91c17SVincenzo Maffione /* Convert a nmreq_xyz struct (new API) to the legacy 'nmr' struct. 284*2ff91c17SVincenzo Maffione * It also frees the nmreq_xyz struct, as it was allocated by 285*2ff91c17SVincenzo Maffione * nmreq_from_legacy(). */ 286*2ff91c17SVincenzo Maffione static int 287*2ff91c17SVincenzo Maffione nmreq_to_legacy(struct nmreq_header *hdr, struct nmreq *nmr) 288*2ff91c17SVincenzo Maffione { 289*2ff91c17SVincenzo Maffione int ret = 0; 290*2ff91c17SVincenzo Maffione 291*2ff91c17SVincenzo Maffione /* We only write-back the fields that the user expects to be 292*2ff91c17SVincenzo Maffione * written back. */ 293*2ff91c17SVincenzo Maffione switch (hdr->nr_reqtype) { 294*2ff91c17SVincenzo Maffione case NETMAP_REQ_REGISTER: { 295*2ff91c17SVincenzo Maffione struct nmreq_register *req = 296*2ff91c17SVincenzo Maffione (struct nmreq_register *)hdr->nr_body; 297*2ff91c17SVincenzo Maffione nmreq_register_to_legacy(req, nmr); 298*2ff91c17SVincenzo Maffione break; 299*2ff91c17SVincenzo Maffione } 300*2ff91c17SVincenzo Maffione case NETMAP_REQ_PORT_INFO_GET: { 301*2ff91c17SVincenzo Maffione struct nmreq_port_info_get *req = 302*2ff91c17SVincenzo Maffione (struct nmreq_port_info_get *)hdr->nr_body; 303*2ff91c17SVincenzo Maffione nmr->nr_offset = req->nr_offset; 304*2ff91c17SVincenzo Maffione nmr->nr_memsize = req->nr_memsize; 305*2ff91c17SVincenzo Maffione nmr->nr_tx_slots = req->nr_tx_slots; 306*2ff91c17SVincenzo Maffione nmr->nr_rx_slots = req->nr_rx_slots; 307*2ff91c17SVincenzo Maffione nmr->nr_tx_rings = req->nr_tx_rings; 308*2ff91c17SVincenzo Maffione nmr->nr_rx_rings = req->nr_rx_rings; 309*2ff91c17SVincenzo Maffione nmr->nr_arg2 = req->nr_mem_id; 310*2ff91c17SVincenzo Maffione break; 311*2ff91c17SVincenzo Maffione } 312*2ff91c17SVincenzo Maffione case NETMAP_REQ_VALE_ATTACH: { 313*2ff91c17SVincenzo Maffione struct nmreq_vale_attach *req = 314*2ff91c17SVincenzo Maffione (struct nmreq_vale_attach *)hdr->nr_body; 315*2ff91c17SVincenzo Maffione nmreq_register_to_legacy(&req->reg, nmr); 316*2ff91c17SVincenzo Maffione break; 317*2ff91c17SVincenzo Maffione } 318*2ff91c17SVincenzo Maffione case NETMAP_REQ_VALE_DETACH: { 319*2ff91c17SVincenzo Maffione break; 320*2ff91c17SVincenzo Maffione } 321*2ff91c17SVincenzo Maffione case NETMAP_REQ_VALE_LIST: { 322*2ff91c17SVincenzo Maffione struct nmreq_vale_list *req = 323*2ff91c17SVincenzo Maffione (struct nmreq_vale_list *)hdr->nr_body; 324*2ff91c17SVincenzo Maffione strncpy(nmr->nr_name, hdr->nr_name, sizeof(nmr->nr_name)); 325*2ff91c17SVincenzo Maffione nmr->nr_arg1 = req->nr_bridge_idx; 326*2ff91c17SVincenzo Maffione nmr->nr_arg2 = req->nr_port_idx; 327*2ff91c17SVincenzo Maffione break; 328*2ff91c17SVincenzo Maffione } 329*2ff91c17SVincenzo Maffione case NETMAP_REQ_PORT_HDR_SET: 330*2ff91c17SVincenzo Maffione case NETMAP_REQ_PORT_HDR_GET: { 331*2ff91c17SVincenzo Maffione struct nmreq_port_hdr *req = 332*2ff91c17SVincenzo Maffione (struct nmreq_port_hdr *)hdr->nr_body; 333*2ff91c17SVincenzo Maffione nmr->nr_arg1 = req->nr_hdr_len; 334*2ff91c17SVincenzo Maffione break; 335*2ff91c17SVincenzo Maffione } 336*2ff91c17SVincenzo Maffione case NETMAP_REQ_VALE_NEWIF: { 337*2ff91c17SVincenzo Maffione struct nmreq_vale_newif *req = 338*2ff91c17SVincenzo Maffione (struct nmreq_vale_newif *)hdr->nr_body; 339*2ff91c17SVincenzo Maffione nmr->nr_tx_slots = req->nr_tx_slots; 340*2ff91c17SVincenzo Maffione nmr->nr_rx_slots = req->nr_rx_slots; 341*2ff91c17SVincenzo Maffione nmr->nr_tx_rings = req->nr_tx_rings; 342*2ff91c17SVincenzo Maffione nmr->nr_rx_rings = req->nr_rx_rings; 343*2ff91c17SVincenzo Maffione nmr->nr_arg2 = req->nr_mem_id; 344*2ff91c17SVincenzo Maffione break; 345*2ff91c17SVincenzo Maffione } 346*2ff91c17SVincenzo Maffione case NETMAP_REQ_VALE_DELIF: 347*2ff91c17SVincenzo Maffione case NETMAP_REQ_VALE_POLLING_ENABLE: 348*2ff91c17SVincenzo Maffione case NETMAP_REQ_VALE_POLLING_DISABLE: { 349*2ff91c17SVincenzo Maffione break; 350*2ff91c17SVincenzo Maffione } 351*2ff91c17SVincenzo Maffione } 352*2ff91c17SVincenzo Maffione 353*2ff91c17SVincenzo Maffione return ret; 354*2ff91c17SVincenzo Maffione } 355*2ff91c17SVincenzo Maffione 356*2ff91c17SVincenzo Maffione int 357*2ff91c17SVincenzo Maffione netmap_ioctl_legacy(struct netmap_priv_d *priv, u_long cmd, caddr_t data, 358*2ff91c17SVincenzo Maffione struct thread *td) 359*2ff91c17SVincenzo Maffione { 360*2ff91c17SVincenzo Maffione int error = 0; 361*2ff91c17SVincenzo Maffione 362*2ff91c17SVincenzo Maffione switch (cmd) { 363*2ff91c17SVincenzo Maffione case NIOCGINFO: 364*2ff91c17SVincenzo Maffione case NIOCREGIF: { 365*2ff91c17SVincenzo Maffione /* Request for the legacy control API. Convert it to a 366*2ff91c17SVincenzo Maffione * NIOCCTRL request. */ 367*2ff91c17SVincenzo Maffione struct nmreq *nmr = (struct nmreq *) data; 368*2ff91c17SVincenzo Maffione struct nmreq_header *hdr = nmreq_from_legacy(nmr, cmd); 369*2ff91c17SVincenzo Maffione if (hdr == NULL) { /* out of memory */ 370*2ff91c17SVincenzo Maffione return ENOMEM; 371*2ff91c17SVincenzo Maffione } 372*2ff91c17SVincenzo Maffione error = netmap_ioctl(priv, NIOCCTRL, (caddr_t)hdr, td, 373*2ff91c17SVincenzo Maffione /*nr_body_is_user=*/0); 374*2ff91c17SVincenzo Maffione if (error == 0) { 375*2ff91c17SVincenzo Maffione nmreq_to_legacy(hdr, nmr); 376*2ff91c17SVincenzo Maffione } 377*2ff91c17SVincenzo Maffione if (hdr->nr_body) { 378*2ff91c17SVincenzo Maffione nm_os_free((void *)hdr->nr_body); 379*2ff91c17SVincenzo Maffione } 380*2ff91c17SVincenzo Maffione nm_os_free(hdr); 381*2ff91c17SVincenzo Maffione break; 382*2ff91c17SVincenzo Maffione } 383*2ff91c17SVincenzo Maffione #ifdef WITH_VALE 384*2ff91c17SVincenzo Maffione case NIOCCONFIG: { 385*2ff91c17SVincenzo Maffione struct nm_ifreq *nr = (struct nm_ifreq *)data; 386*2ff91c17SVincenzo Maffione error = netmap_bdg_config(nr); 387*2ff91c17SVincenzo Maffione break; 388*2ff91c17SVincenzo Maffione } 389*2ff91c17SVincenzo Maffione #endif 390*2ff91c17SVincenzo Maffione #ifdef __FreeBSD__ 391*2ff91c17SVincenzo Maffione case FIONBIO: 392*2ff91c17SVincenzo Maffione case FIOASYNC: 393*2ff91c17SVincenzo Maffione ND("FIONBIO/FIOASYNC are no-ops"); 394*2ff91c17SVincenzo Maffione break; 395*2ff91c17SVincenzo Maffione 396*2ff91c17SVincenzo Maffione case BIOCIMMEDIATE: 397*2ff91c17SVincenzo Maffione case BIOCGHDRCMPLT: 398*2ff91c17SVincenzo Maffione case BIOCSHDRCMPLT: 399*2ff91c17SVincenzo Maffione case BIOCSSEESENT: 400*2ff91c17SVincenzo Maffione D("ignore BIOCIMMEDIATE/BIOCSHDRCMPLT/BIOCSHDRCMPLT/BIOCSSEESENT"); 401*2ff91c17SVincenzo Maffione break; 402*2ff91c17SVincenzo Maffione 403*2ff91c17SVincenzo Maffione default: /* allow device-specific ioctls */ 404*2ff91c17SVincenzo Maffione { 405*2ff91c17SVincenzo Maffione struct nmreq *nmr = (struct nmreq *)data; 406*2ff91c17SVincenzo Maffione struct ifnet *ifp = ifunit_ref(nmr->nr_name); 407*2ff91c17SVincenzo Maffione if (ifp == NULL) { 408*2ff91c17SVincenzo Maffione error = ENXIO; 409*2ff91c17SVincenzo Maffione } else { 410*2ff91c17SVincenzo Maffione struct socket so; 411*2ff91c17SVincenzo Maffione 412*2ff91c17SVincenzo Maffione bzero(&so, sizeof(so)); 413*2ff91c17SVincenzo Maffione so.so_vnet = ifp->if_vnet; 414*2ff91c17SVincenzo Maffione // so->so_proto not null. 415*2ff91c17SVincenzo Maffione error = ifioctl(&so, cmd, data, td); 416*2ff91c17SVincenzo Maffione if_rele(ifp); 417*2ff91c17SVincenzo Maffione } 418*2ff91c17SVincenzo Maffione break; 419*2ff91c17SVincenzo Maffione } 420*2ff91c17SVincenzo Maffione 421*2ff91c17SVincenzo Maffione #else /* linux */ 422*2ff91c17SVincenzo Maffione default: 423*2ff91c17SVincenzo Maffione error = EOPNOTSUPP; 424*2ff91c17SVincenzo Maffione #endif /* linux */ 425*2ff91c17SVincenzo Maffione } 426*2ff91c17SVincenzo Maffione 427*2ff91c17SVincenzo Maffione return error; 428*2ff91c17SVincenzo Maffione } 429