1167892Syar/*- 2167892Syar * Copyright (c) 1982, 1986, 1993 3167892Syar * The Regents of the University of California. All rights reserved. 4167892Syar * 5167892Syar * Redistribution and use in source and binary forms, with or without 6167892Syar * modification, are permitted provided that the following conditions 7167892Syar * are met: 8167892Syar * 1. Redistributions of source code must retain the above copyright 9167892Syar * notice, this list of conditions and the following edsclaimer. 10167892Syar * 2. Redistributions in binary form must reproduce the above copyright 11167892Syar * notice, this list of conditions and the following edsclaimer in the 12167892Syar * documentation and/or other materials provided with the distribution. 13167892Syar * 4. Neither the name of the University nor the names of its contributors 14167892Syar * may be used to endorse or promote products derived from this software 15167892Syar * without specific prior written permission. 16167892Syar * 17167892Syar * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18167892Syar * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19167892Syar * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20167892Syar * ARE EDSCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21167892Syar * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22167892Syar * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23167892Syar * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24167892Syar * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25167892Syar * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26167892Syar * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27167892Syar * SUCH DAMAGE. 28167892Syar * 29167892Syar * From: @(#)if_loop.c 8.1 (Berkeley) 6/10/93 30167892Syar * $FreeBSD: releng/11.0/sys/net/if_edsc.c 302054 2016-06-21 13:48:49Z bz $ 31167892Syar */ 32167892Syar 33167892Syar/* 34167892Syar * Discard interface driver for protocol testing and timing. 35167892Syar * Mimics an Ethernet device so that VLANs can be attached to it etc. 36167892Syar */ 37167892Syar 38167892Syar#include <sys/param.h> /* types, important constants */ 39167892Syar#include <sys/kernel.h> /* SYSINIT for load-time initializations */ 40167892Syar#include <sys/malloc.h> /* malloc(9) */ 41167892Syar#include <sys/module.h> /* module(9) */ 42167892Syar#include <sys/mbuf.h> /* mbuf(9) */ 43167892Syar#include <sys/socket.h> /* struct ifreq */ 44167892Syar#include <sys/sockio.h> /* socket ioctl's */ 45167892Syar/* #include <sys/systm.h> if you need printf(9) or other all-purpose globals */ 46167892Syar 47167892Syar#include <net/bpf.h> /* bpf(9) */ 48167892Syar#include <net/ethernet.h> /* Ethernet related constants and types */ 49257176Sglebius#include <net/if.h> 50257176Sglebius#include <net/if_var.h> /* basic part of ifnet(9) */ 51167892Syar#include <net/if_clone.h> /* network interface cloning */ 52167892Syar#include <net/if_types.h> /* IFT_ETHER and friends */ 53167894Syar#include <net/if_var.h> /* kernel-only part of ifnet(9) */ 54272572Shrs#include <net/vnet.h> 55167892Syar 56241610Sglebiusstatic const char edscname[] = "edsc"; 57241610Sglebius 58167892Syar/* 59167894Syar * Software configuration of an interface specific to this device type. 60167892Syar */ 61167892Syarstruct edsc_softc { 62167894Syar struct ifnet *sc_ifp; /* ptr to generic interface configuration */ 63167896Syar 64167896Syar /* 65167896Syar * A non-null driver can keep various things here, for instance, 66167896Syar * the hardware revision, cached values of write-only registers, etc. 67167896Syar */ 68167892Syar}; 69167892Syar 70167892Syar/* 71241610Sglebius * Attach to the interface cloning framework. 72167892Syar */ 73272572Shrsstatic VNET_DEFINE(struct if_clone *, edsc_cloner); 74272572Shrs#define V_edsc_cloner VNET(edsc_cloner) 75167892Syarstatic int edsc_clone_create(struct if_clone *, int, caddr_t); 76167892Syarstatic void edsc_clone_destroy(struct ifnet *); 77167892Syar 78167892Syar/* 79167892Syar * Interface driver methods. 80167892Syar */ 81167892Syarstatic void edsc_init(void *dummy); 82167892Syar/* static void edsc_input(struct ifnet *ifp, struct mbuf *m); would be here */ 83167892Syarstatic int edsc_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data); 84167892Syarstatic void edsc_start(struct ifnet *ifp); 85167892Syar 86167892Syar/* 87167892Syar * We'll allocate softc instances from this. 88167892Syar */ 89241610Sglebiusstatic MALLOC_DEFINE(M_EDSC, edscname, "Ethernet discard interface"); 90167892Syar 91167892Syar/* 92167892Syar * Create an interface instance. 93167892Syar */ 94167892Syarstatic int 95167892Syaredsc_clone_create(struct if_clone *ifc, int unit, caddr_t params) 96167892Syar{ 97167892Syar struct edsc_softc *sc; 98167892Syar struct ifnet *ifp; 99167892Syar static u_char eaddr[ETHER_ADDR_LEN]; /* 0:0:0:0:0:0 */ 100167892Syar 101167892Syar /* 102167892Syar * Allocate soft and ifnet structures. Link each to the other. 103167892Syar */ 104167892Syar sc = malloc(sizeof(struct edsc_softc), M_EDSC, M_WAITOK | M_ZERO); 105167892Syar ifp = sc->sc_ifp = if_alloc(IFT_ETHER); 106167892Syar if (ifp == NULL) { 107167892Syar free(sc, M_EDSC); 108167892Syar return (ENOSPC); 109167892Syar } 110167892Syar 111167892Syar ifp->if_softc = sc; 112167892Syar 113167892Syar /* 114167892Syar * Get a name for this particular interface in its ifnet structure. 115167892Syar */ 116241610Sglebius if_initname(ifp, edscname, unit); 117167892Syar 118167892Syar /* 119167892Syar * Typical Ethernet interface flags: we can do broadcast and 120167892Syar * multicast but can't hear our own broadcasts or multicasts. 121167892Syar */ 122167892Syar ifp->if_flags = IFF_BROADCAST | IFF_MULTICAST | IFF_SIMPLEX; 123167892Syar 124167892Syar /* 125167892Syar * We can pretent we have the whole set of hardware features 126167892Syar * because we just discard all packets we get from the upper layer. 127167892Syar * However, the features are disabled initially. They can be 128167892Syar * enabled via edsc_ioctl() when needed. 129167892Syar */ 130167892Syar ifp->if_capabilities = 131167892Syar IFCAP_VLAN_MTU | IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_HWCSUM | 132167892Syar IFCAP_HWCSUM | IFCAP_TSO | 133167892Syar IFCAP_JUMBO_MTU; 134167892Syar ifp->if_capenable = 0; 135167892Syar 136167892Syar /* 137167892Syar * Set the interface driver methods. 138167892Syar */ 139167892Syar ifp->if_init = edsc_init; 140167892Syar /* ifp->if_input = edsc_input; */ 141167892Syar ifp->if_ioctl = edsc_ioctl; 142167892Syar ifp->if_start = edsc_start; 143167892Syar 144167892Syar /* 145167892Syar * Set the maximum output queue length from the global parameter. 146167892Syar */ 147167892Syar ifp->if_snd.ifq_maxlen = ifqmaxlen; 148167892Syar 149167892Syar /* 150167892Syar * Do ifnet initializations common to all Ethernet drivers 151167892Syar * and attach to the network interface framework. 152167892Syar * TODO: Pick a non-zero link level address. 153167892Syar */ 154167892Syar ether_ifattach(ifp, eaddr); 155167892Syar 156167892Syar /* 157167892Syar * Now we can mark the interface as running, i.e., ready 158167892Syar * for operation. 159167892Syar */ 160167892Syar ifp->if_drv_flags |= IFF_DRV_RUNNING; 161167892Syar 162167892Syar return (0); 163167892Syar} 164167892Syar 165167892Syar/* 166167892Syar * Destroy an interface instance. 167167892Syar */ 168167892Syarstatic void 169167892Syaredsc_clone_destroy(struct ifnet *ifp) 170167892Syar{ 171167892Syar struct edsc_softc *sc = ifp->if_softc; 172167892Syar 173167892Syar /* 174167892Syar * Detach from the network interface framework. 175167892Syar */ 176167892Syar ether_ifdetach(ifp); 177167892Syar 178167892Syar /* 179167892Syar * Free memory occupied by ifnet and softc. 180167892Syar */ 181167892Syar if_free(ifp); 182167892Syar free(sc, M_EDSC); 183167892Syar} 184167892Syar 185167892Syar/* 186167892Syar * This method is invoked from ether_ioctl() when it's time 187167892Syar * to bring up the hardware. 188167892Syar */ 189167892Syarstatic void 190167892Syaredsc_init(void *dummy) 191167892Syar{ 192167892Syar#if 0 /* what a hardware driver would do here... */ 193167892Syar struct edsc_soft *sc = (struct edsc_softc *)dummy; 194167892Syar struct ifnet *ifp = sc->sc_ifp; 195167892Syar 196167892Syar /* blah-blah-blah */ 197167892Syar#endif 198167892Syar} 199167892Syar 200167892Syar/* 201167892Syar * Network interfaces are controlled via the ioctl(2) syscall. 202167892Syar */ 203167892Syarstatic int 204167892Syaredsc_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 205167892Syar{ 206167892Syar struct ifreq *ifr = (struct ifreq *)data; 207167892Syar 208167892Syar switch (cmd) { 209167892Syar case SIOCSIFCAP: 210167892Syar#if 1 211167892Syar /* 212167892Syar * Just turn on any capabilities requested. 213167892Syar * The generic ifioctl() function has already made sure 214167892Syar * that they are supported, i.e., set in if_capabilities. 215167892Syar */ 216167892Syar ifp->if_capenable = ifr->ifr_reqcap; 217167892Syar#else 218167892Syar /* 219167892Syar * A h/w driver would need to analyze the requested 220167892Syar * bits and program the hardware, e.g.: 221167892Syar */ 222167892Syar mask = ifp->if_capenable ^ ifr->ifr_reqcap; 223167892Syar 224167892Syar if (mask & IFCAP_VLAN_HWTAGGING) { 225167892Syar ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING; 226167892Syar 227167892Syar if (ifp->if_capenable & IFCAP_VLAN_HWTAGGING) 228167892Syar /* blah-blah-blah */ 229167892Syar else 230167892Syar /* etc-etc-etc */ 231167892Syar } 232167892Syar#endif 233167892Syar break; 234167892Syar 235167892Syar default: 236167892Syar /* 237167892Syar * Offload the rest onto the common Ethernet handler. 238167892Syar */ 239167892Syar return (ether_ioctl(ifp, cmd, data)); 240167892Syar } 241167892Syar 242167892Syar return (0); 243167892Syar} 244167892Syar 245167892Syar/* 246167892Syar * Process the output queue. 247167892Syar */ 248167892Syarstatic void 249167892Syaredsc_start(struct ifnet *ifp) 250167892Syar{ 251167892Syar struct mbuf *m; 252167892Syar 253167892Syar /* 254167892Syar * A hardware interface driver can set IFF_DRV_OACTIVE 255167892Syar * in ifp->if_drv_flags: 256167892Syar * 257167892Syar * ifp->if_drv_flags |= IFF_DRV_OACTIVE; 258167892Syar * 259167892Syar * to prevent if_start from being invoked again while the 260167892Syar * transmission is under way. The flag is to protect the 261167892Syar * device's transmitter, not the method itself. The output 262167892Syar * queue is locked and several threads can process it in 263167892Syar * parallel safely, so the driver can use other means to 264167892Syar * serialize access to the transmitter. 265167892Syar * 266167892Syar * If using IFF_DRV_OACTIVE, the driver should clear the flag 267167892Syar * not earlier than the current transmission is complete, e.g., 268167892Syar * upon an interrupt from the device, not just before returning 269167892Syar * from if_start. This method merely starts the transmission, 270167892Syar * which may proceed asynchronously. 271167892Syar */ 272167892Syar 273167892Syar /* 274167892Syar * We loop getting packets from the queue until it's empty. 275167892Syar * A h/w driver would loop until the device can accept more 276167892Syar * data into its buffer, or while there are free transmit 277167892Syar * descriptors, or whatever. 278167892Syar */ 279167892Syar for (;;) { 280167892Syar /* 281167892Syar * Try to dequeue one packet. Stop if the queue is empty. 282167892Syar * Use IF_DEQUEUE() here if ALTQ(9) support is unneeded. 283167892Syar */ 284167892Syar IFQ_DEQUEUE(&ifp->if_snd, m); 285167892Syar if (m == NULL) 286167892Syar break; 287167892Syar 288167892Syar /* 289167892Syar * Let bpf(9) at the packet. 290167892Syar */ 291167892Syar BPF_MTAP(ifp, m); 292167892Syar 293167892Syar /* 294167892Syar * Update the interface counters. 295167892Syar */ 296271867Sglebius if_inc_counter(ifp, IFCOUNTER_OBYTES, m->m_pkthdr.len); 297271867Sglebius if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); 298167892Syar 299167892Syar /* 300167892Syar * Finally, just drop the packet. 301167892Syar * TODO: Reply to ARP requests unless IFF_NOARP is set. 302167892Syar */ 303167892Syar m_freem(m); 304167892Syar } 305167892Syar 306167892Syar /* 307167892Syar * ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 308167892Syar * would be here only if the transmission were synchronous. 309167892Syar */ 310167892Syar} 311167892Syar 312272572Shrsstatic void 313272572Shrsvnet_edsc_init(const void *unused __unused) 314272572Shrs{ 315272572Shrs 316272572Shrs /* 317272572Shrs * Connect to the network interface cloning framework. 318272572Shrs * The last argument is the number of units to be created 319272572Shrs * from the outset. It's also the minimum number of units 320272572Shrs * allowed. We don't want any units created as soon as the 321272572Shrs * driver is loaded. 322272572Shrs */ 323272572Shrs V_edsc_cloner = if_clone_simple(edscname, edsc_clone_create, 324272572Shrs edsc_clone_destroy, 0); 325272572Shrs} 326272572ShrsVNET_SYSINIT(vnet_edsc_init, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY, 327272572Shrs vnet_edsc_init, NULL); 328272572Shrs 329272572Shrsstatic void 330272572Shrsvnet_edsc_uninit(const void *unused __unused) 331272572Shrs{ 332272572Shrs 333272572Shrs /* 334272572Shrs * Disconnect from the cloning framework. 335272572Shrs * Existing interfaces will be disposed of properly. 336272572Shrs */ 337272572Shrs if_clone_detach(V_edsc_cloner); 338272572Shrs} 339302054SbzVNET_SYSUNINIT(vnet_edsc_uninit, SI_SUB_INIT_IF, SI_ORDER_ANY, 340272572Shrs vnet_edsc_uninit, NULL); 341272572Shrs 342167892Syar/* 343167892Syar * This function provides handlers for module events, namely load and unload. 344167892Syar */ 345167892Syarstatic int 346167892Syaredsc_modevent(module_t mod, int type, void *data) 347167892Syar{ 348167892Syar 349167892Syar switch (type) { 350167892Syar case MOD_LOAD: 351167892Syar case MOD_UNLOAD: 352167892Syar break; 353167892Syar default: 354167892Syar /* 355167892Syar * There are other event types, but we don't handle them. 356167892Syar * See module(9). 357167892Syar */ 358167892Syar return (EOPNOTSUPP); 359167892Syar } 360167892Syar return (0); 361167892Syar} 362167892Syar 363167892Syarstatic moduledata_t edsc_mod = { 364167892Syar "if_edsc", /* name */ 365167892Syar edsc_modevent, /* event handler */ 366167892Syar NULL /* additional data */ 367167892Syar}; 368167892Syar 369167892SyarDECLARE_MODULE(if_edsc, edsc_mod, SI_SUB_PSEUDO, SI_ORDER_ANY); 370