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$ 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 */ 49167894Syar#include <net/if.h> /* basic part of ifnet(9) */ 50167892Syar#include <net/if_clone.h> /* network interface cloning */ 51167892Syar#include <net/if_types.h> /* IFT_ETHER and friends */ 52167894Syar#include <net/if_var.h> /* kernel-only part of ifnet(9) */ 53167892Syar 54167892Syar/* 55167894Syar * Software configuration of an interface specific to this device type. 56167892Syar */ 57167892Syarstruct edsc_softc { 58167894Syar struct ifnet *sc_ifp; /* ptr to generic interface configuration */ 59167896Syar 60167896Syar /* 61167896Syar * A non-null driver can keep various things here, for instance, 62167896Syar * the hardware revision, cached values of write-only registers, etc. 63167896Syar */ 64167892Syar}; 65167892Syar 66167892Syar/* 67167892Syar * Simple cloning methods. 68167892Syar * IFC_SIMPLE_DECLARE() expects precisely these names. 69167892Syar */ 70167892Syarstatic int edsc_clone_create(struct if_clone *, int, caddr_t); 71167892Syarstatic void edsc_clone_destroy(struct ifnet *); 72167892Syar 73167892Syar/* 74167892Syar * Interface driver methods. 75167892Syar */ 76167892Syarstatic void edsc_init(void *dummy); 77167892Syar/* static void edsc_input(struct ifnet *ifp, struct mbuf *m); would be here */ 78167892Syarstatic int edsc_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data); 79167892Syarstatic void edsc_start(struct ifnet *ifp); 80167892Syar 81167892Syar/* 82167892Syar * We'll allocate softc instances from this. 83167892Syar */ 84167892Syarstatic MALLOC_DEFINE(M_EDSC, "edsc", "Ethernet discard interface"); 85167892Syar 86167892Syar/* 87167892Syar * Attach to the interface cloning framework under the name of "edsc". 88167892Syar * The second argument is the number of units to be created from 89167892Syar * the outset. It's also the minimum number of units allowed. 90167892Syar * We don't want any units created as soon as the driver is loaded. 91167892Syar */ 92167892SyarIFC_SIMPLE_DECLARE(edsc, 0); 93167892Syar 94167892Syar/* 95167892Syar * Create an interface instance. 96167892Syar */ 97167892Syarstatic int 98167892Syaredsc_clone_create(struct if_clone *ifc, int unit, caddr_t params) 99167892Syar{ 100167892Syar struct edsc_softc *sc; 101167892Syar struct ifnet *ifp; 102167892Syar static u_char eaddr[ETHER_ADDR_LEN]; /* 0:0:0:0:0:0 */ 103167892Syar 104167892Syar /* 105167892Syar * Allocate soft and ifnet structures. Link each to the other. 106167892Syar */ 107167892Syar sc = malloc(sizeof(struct edsc_softc), M_EDSC, M_WAITOK | M_ZERO); 108167892Syar ifp = sc->sc_ifp = if_alloc(IFT_ETHER); 109167892Syar if (ifp == NULL) { 110167892Syar free(sc, M_EDSC); 111167892Syar return (ENOSPC); 112167892Syar } 113167892Syar 114167892Syar ifp->if_softc = sc; 115167892Syar 116167892Syar /* 117167892Syar * Get a name for this particular interface in its ifnet structure. 118167892Syar */ 119167892Syar if_initname(ifp, ifc->ifc_name, unit); 120167892Syar 121167892Syar /* 122167892Syar * Typical Ethernet interface flags: we can do broadcast and 123167892Syar * multicast but can't hear our own broadcasts or multicasts. 124167892Syar */ 125167892Syar ifp->if_flags = IFF_BROADCAST | IFF_MULTICAST | IFF_SIMPLEX; 126167892Syar 127167892Syar /* 128167892Syar * We can pretent we have the whole set of hardware features 129167892Syar * because we just discard all packets we get from the upper layer. 130167892Syar * However, the features are disabled initially. They can be 131167892Syar * enabled via edsc_ioctl() when needed. 132167892Syar */ 133167892Syar ifp->if_capabilities = 134167892Syar IFCAP_VLAN_MTU | IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_HWCSUM | 135167892Syar IFCAP_HWCSUM | IFCAP_TSO | 136167892Syar IFCAP_JUMBO_MTU; 137167892Syar ifp->if_capenable = 0; 138167892Syar 139167892Syar /* 140167892Syar * Set the interface driver methods. 141167892Syar */ 142167892Syar ifp->if_init = edsc_init; 143167892Syar /* ifp->if_input = edsc_input; */ 144167892Syar ifp->if_ioctl = edsc_ioctl; 145167892Syar ifp->if_start = edsc_start; 146167892Syar 147167892Syar /* 148167892Syar * Set the maximum output queue length from the global parameter. 149167892Syar */ 150167892Syar ifp->if_snd.ifq_maxlen = ifqmaxlen; 151167892Syar 152167892Syar /* 153167892Syar * Do ifnet initializations common to all Ethernet drivers 154167892Syar * and attach to the network interface framework. 155167892Syar * TODO: Pick a non-zero link level address. 156167892Syar */ 157167892Syar ether_ifattach(ifp, eaddr); 158167892Syar 159167892Syar /* 160167892Syar * Now we can mark the interface as running, i.e., ready 161167892Syar * for operation. 162167892Syar */ 163167892Syar ifp->if_drv_flags |= IFF_DRV_RUNNING; 164167892Syar 165167892Syar return (0); 166167892Syar} 167167892Syar 168167892Syar/* 169167892Syar * Destroy an interface instance. 170167892Syar */ 171167892Syarstatic void 172167892Syaredsc_clone_destroy(struct ifnet *ifp) 173167892Syar{ 174167892Syar struct edsc_softc *sc = ifp->if_softc; 175167892Syar 176167892Syar /* 177167892Syar * Detach from the network interface framework. 178167892Syar */ 179167892Syar ether_ifdetach(ifp); 180167892Syar 181167892Syar /* 182167892Syar * Free memory occupied by ifnet and softc. 183167892Syar */ 184167892Syar if_free(ifp); 185167892Syar free(sc, M_EDSC); 186167892Syar} 187167892Syar 188167892Syar/* 189167892Syar * This method is invoked from ether_ioctl() when it's time 190167892Syar * to bring up the hardware. 191167892Syar */ 192167892Syarstatic void 193167892Syaredsc_init(void *dummy) 194167892Syar{ 195167892Syar#if 0 /* what a hardware driver would do here... */ 196167892Syar struct edsc_soft *sc = (struct edsc_softc *)dummy; 197167892Syar struct ifnet *ifp = sc->sc_ifp; 198167892Syar 199167892Syar /* blah-blah-blah */ 200167892Syar#endif 201167892Syar} 202167892Syar 203167892Syar/* 204167892Syar * Network interfaces are controlled via the ioctl(2) syscall. 205167892Syar */ 206167892Syarstatic int 207167892Syaredsc_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 208167892Syar{ 209167892Syar struct ifreq *ifr = (struct ifreq *)data; 210167892Syar 211167892Syar switch (cmd) { 212167892Syar case SIOCSIFCAP: 213167892Syar#if 1 214167892Syar /* 215167892Syar * Just turn on any capabilities requested. 216167892Syar * The generic ifioctl() function has already made sure 217167892Syar * that they are supported, i.e., set in if_capabilities. 218167892Syar */ 219167892Syar ifp->if_capenable = ifr->ifr_reqcap; 220167892Syar#else 221167892Syar /* 222167892Syar * A h/w driver would need to analyze the requested 223167892Syar * bits and program the hardware, e.g.: 224167892Syar */ 225167892Syar mask = ifp->if_capenable ^ ifr->ifr_reqcap; 226167892Syar 227167892Syar if (mask & IFCAP_VLAN_HWTAGGING) { 228167892Syar ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING; 229167892Syar 230167892Syar if (ifp->if_capenable & IFCAP_VLAN_HWTAGGING) 231167892Syar /* blah-blah-blah */ 232167892Syar else 233167892Syar /* etc-etc-etc */ 234167892Syar } 235167892Syar#endif 236167892Syar break; 237167892Syar 238167892Syar default: 239167892Syar /* 240167892Syar * Offload the rest onto the common Ethernet handler. 241167892Syar */ 242167892Syar return (ether_ioctl(ifp, cmd, data)); 243167892Syar } 244167892Syar 245167892Syar return (0); 246167892Syar} 247167892Syar 248167892Syar/* 249167892Syar * Process the output queue. 250167892Syar */ 251167892Syarstatic void 252167892Syaredsc_start(struct ifnet *ifp) 253167892Syar{ 254167892Syar struct mbuf *m; 255167892Syar 256167892Syar /* 257167892Syar * A hardware interface driver can set IFF_DRV_OACTIVE 258167892Syar * in ifp->if_drv_flags: 259167892Syar * 260167892Syar * ifp->if_drv_flags |= IFF_DRV_OACTIVE; 261167892Syar * 262167892Syar * to prevent if_start from being invoked again while the 263167892Syar * transmission is under way. The flag is to protect the 264167892Syar * device's transmitter, not the method itself. The output 265167892Syar * queue is locked and several threads can process it in 266167892Syar * parallel safely, so the driver can use other means to 267167892Syar * serialize access to the transmitter. 268167892Syar * 269167892Syar * If using IFF_DRV_OACTIVE, the driver should clear the flag 270167892Syar * not earlier than the current transmission is complete, e.g., 271167892Syar * upon an interrupt from the device, not just before returning 272167892Syar * from if_start. This method merely starts the transmission, 273167892Syar * which may proceed asynchronously. 274167892Syar */ 275167892Syar 276167892Syar /* 277167892Syar * We loop getting packets from the queue until it's empty. 278167892Syar * A h/w driver would loop until the device can accept more 279167892Syar * data into its buffer, or while there are free transmit 280167892Syar * descriptors, or whatever. 281167892Syar */ 282167892Syar for (;;) { 283167892Syar /* 284167892Syar * Try to dequeue one packet. Stop if the queue is empty. 285167892Syar * Use IF_DEQUEUE() here if ALTQ(9) support is unneeded. 286167892Syar */ 287167892Syar IFQ_DEQUEUE(&ifp->if_snd, m); 288167892Syar if (m == NULL) 289167892Syar break; 290167892Syar 291167892Syar /* 292167892Syar * Let bpf(9) at the packet. 293167892Syar */ 294167892Syar BPF_MTAP(ifp, m); 295167892Syar 296167892Syar /* 297167892Syar * Update the interface counters. 298167892Syar */ 299167892Syar ifp->if_obytes += m->m_pkthdr.len; 300167892Syar ifp->if_opackets++; 301167892Syar 302167892Syar /* 303167892Syar * Finally, just drop the packet. 304167892Syar * TODO: Reply to ARP requests unless IFF_NOARP is set. 305167892Syar */ 306167892Syar m_freem(m); 307167892Syar } 308167892Syar 309167892Syar /* 310167892Syar * ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 311167892Syar * would be here only if the transmission were synchronous. 312167892Syar */ 313167892Syar} 314167892Syar 315167892Syar/* 316167892Syar * This function provides handlers for module events, namely load and unload. 317167892Syar */ 318167892Syarstatic int 319167892Syaredsc_modevent(module_t mod, int type, void *data) 320167892Syar{ 321167892Syar 322167892Syar switch (type) { 323167892Syar case MOD_LOAD: 324167892Syar /* 325167892Syar * Connect to the network interface cloning framework. 326167892Syar */ 327167892Syar if_clone_attach(&edsc_cloner); 328167892Syar break; 329167892Syar 330167892Syar case MOD_UNLOAD: 331167892Syar /* 332167892Syar * Disconnect from the cloning framework. 333167892Syar * Existing interfaces will be disposed of properly. 334167892Syar */ 335167892Syar if_clone_detach(&edsc_cloner); 336167892Syar break; 337167892Syar 338167892Syar default: 339167892Syar /* 340167892Syar * There are other event types, but we don't handle them. 341167892Syar * See module(9). 342167892Syar */ 343167892Syar return (EOPNOTSUPP); 344167892Syar } 345167892Syar return (0); 346167892Syar} 347167892Syar 348167892Syarstatic moduledata_t edsc_mod = { 349167892Syar "if_edsc", /* name */ 350167892Syar edsc_modevent, /* event handler */ 351167892Syar NULL /* additional data */ 352167892Syar}; 353167892Syar 354167892SyarDECLARE_MODULE(if_edsc, edsc_mod, SI_SUB_PSEUDO, SI_ORDER_ANY); 355