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