The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/pdq/pdq_ifsubr.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 1995, 1996 Matt Thomas <matt@3am-software.com>
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. The name of the author may not be used to endorse or promote products
   11  *    derived from this software withough specific prior written permission
   12  *
   13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   14  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   15  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   16  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   17  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   18  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   19  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   20  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   21  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   22  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   23  *
   24  * $FreeBSD: src/sys/dev/pdq/pdq_ifsubr.c,v 1.2.2.1 1999/09/05 08:09:27 peter Exp $
   25  *
   26  */
   27 
   28 /*
   29  * DEC PDQ FDDI Controller; code for BSD derived operating systems
   30  *
   31  *      This module provide bus independent BSD specific O/S functions.
   32  *      (ie. it provides an ifnet interface to the rest of the system)
   33  */
   34 
   35 
   36 #include <sys/param.h>
   37 #include <sys/kernel.h>
   38 #include <sys/mbuf.h>
   39 #include <sys/protosw.h>
   40 #include <sys/socket.h>
   41 #include <sys/ioctl.h>
   42 #include <sys/errno.h>
   43 #include <sys/malloc.h>
   44 #if defined(__bsdi__) || defined(__NetBSD__)
   45 #include <sys/device.h>
   46 #endif
   47 
   48 #include <net/if.h>
   49 #include <net/if_types.h>
   50 #include <net/if_dl.h>
   51 #include <net/route.h>
   52 
   53 #include "bpfilter.h"
   54 #if NBPFILTER > 0
   55 #include <net/bpf.h>
   56 #include <net/bpfdesc.h>
   57 #endif
   58 
   59 #ifdef INET
   60 #include <netinet/in.h>
   61 #include <netinet/in_systm.h>
   62 #include <netinet/in_var.h>
   63 #include <netinet/ip.h>
   64 #include <netinet/if_ether.h>
   65 #endif
   66 #if defined(__FreeBSD__)
   67 #include <netinet/if_fddi.h>
   68 #else
   69 #include <net/if_fddi.h>
   70 #endif
   71 
   72 #if defined(__bsdi__)
   73 #include <i386/isa/isavar.h>
   74 #endif
   75 
   76 #ifdef NS
   77 #include <netns/ns.h>
   78 #include <netns/ns_if.h>
   79 #endif
   80 
   81 #include <vm/vm.h>
   82 #include <vm/vm_kern.h>
   83 #include <vm/vm_param.h>
   84 
   85 #if defined(__FreeBSD__)
   86 #include <dev/pdq/pdqvar.h>
   87 #include <dev/pdq/pdqreg.h>
   88 #else
   89 #include "pdqvar.h"
   90 #include "pdqreg.h"
   91 #endif
   92 
   93 #if defined(__bsdi__) && _BSDI_VERSION < 199506 /* XXX */
   94 static void
   95 arp_ifinit(
   96     struct arpcom *ac,
   97     struct ifaddr *ifa)
   98 {
   99     sc->sc_ac.ac_ipaddr = IA_SIN(ifa)->sin_addr;
  100     arpwhohas(&sc->sc_ac, &IA_SIN(ifa)->sin_addr);
  101 #if _BSDI_VERSION >= 199401
  102     ifa->ifa_rtrequest = arp_rtrequest;
  103     ifa->ifa_flags |= RTF_CLONING;
  104 #endif
  105 #endif
  106 
  107 
  108 void
  109 pdq_ifinit(
  110     pdq_softc_t *sc)
  111 {
  112     if (sc->sc_if.if_flags & IFF_UP) {
  113         sc->sc_if.if_flags |= IFF_RUNNING;
  114         if (sc->sc_if.if_flags & IFF_PROMISC) {
  115             sc->sc_pdq->pdq_flags |= PDQ_PROMISC;
  116         } else {
  117             sc->sc_pdq->pdq_flags &= ~PDQ_PROMISC;
  118         }
  119         if (sc->sc_if.if_flags & IFF_ALLMULTI) {
  120             sc->sc_pdq->pdq_flags |= PDQ_ALLMULTI;
  121         } else {
  122             sc->sc_pdq->pdq_flags &= ~PDQ_ALLMULTI;
  123         }
  124         if (sc->sc_if.if_flags & IFF_LINK1) {
  125             sc->sc_pdq->pdq_flags |= PDQ_PASS_SMT;
  126         } else {
  127             sc->sc_pdq->pdq_flags &= ~PDQ_PASS_SMT;
  128         }
  129         sc->sc_pdq->pdq_flags |= PDQ_RUNNING;
  130         pdq_run(sc->sc_pdq);
  131     } else {
  132         sc->sc_if.if_flags &= ~IFF_RUNNING;
  133         sc->sc_pdq->pdq_flags &= ~PDQ_RUNNING;
  134         pdq_stop(sc->sc_pdq);
  135     }
  136 }
  137 
  138 void
  139 pdq_ifwatchdog(
  140     struct ifnet *ifp)
  141 {
  142     /*
  143      * No progress was made on the transmit queue for PDQ_OS_TX_TRANSMIT
  144      * seconds.  Remove all queued packets.
  145      */
  146 
  147     ifp->if_flags &= ~IFF_OACTIVE;
  148     ifp->if_timer = 0;
  149     for (;;) {
  150         struct mbuf *m;
  151         IF_DEQUEUE(&ifp->if_snd, m);
  152         if (m == NULL)
  153             return;
  154         m_freem(m);
  155     }
  156 }
  157 
  158 ifnet_ret_t
  159 pdq_ifstart(
  160     struct ifnet *ifp)
  161 {
  162     pdq_softc_t *sc = (pdq_softc_t *) ((caddr_t) ifp - offsetof(pdq_softc_t, sc_ac.ac_if));
  163     struct ifqueue *ifq = &ifp->if_snd;
  164     struct mbuf *m;
  165     int tx = 0;
  166 
  167     if ((ifp->if_flags & IFF_RUNNING) == 0)
  168         return;
  169 
  170     if (sc->sc_if.if_timer == 0)
  171         sc->sc_if.if_timer = PDQ_OS_TX_TIMEOUT;
  172 
  173     if ((sc->sc_pdq->pdq_flags & PDQ_TXOK) == 0) {
  174         sc->sc_if.if_flags |= IFF_OACTIVE;
  175         return;
  176     }
  177     for (;; tx = 1) {
  178         IF_DEQUEUE(ifq, m);
  179         if (m == NULL)
  180             break;
  181 
  182         if (pdq_queue_transmit_data(sc->sc_pdq, m) == PDQ_FALSE) {
  183             ifp->if_flags |= IFF_OACTIVE;
  184             IF_PREPEND(ifq, m);
  185             break;
  186         }
  187     }
  188     if (tx)
  189         PDQ_DO_TYPE2_PRODUCER(sc->sc_pdq);
  190 }
  191 
  192 void
  193 pdq_os_receive_pdu(
  194     pdq_t *pdq,
  195     struct mbuf *m,
  196     size_t pktlen)
  197 {
  198     pdq_softc_t *sc = (pdq_softc_t *) pdq->pdq_os_ctx;
  199     struct fddi_header *fh = mtod(m, struct fddi_header *);
  200 
  201     sc->sc_if.if_ipackets++;
  202 #if NBPFILTER > 0
  203     if (sc->sc_bpf != NULL)
  204         PDQ_BPF_MTAP(sc, m);
  205     if ((fh->fddi_fc & (FDDIFC_L|FDDIFC_F)) != FDDIFC_LLC_ASYNC) {
  206         m_freem(m);
  207         return;
  208     }
  209 #endif
  210 
  211     m->m_data += sizeof(struct fddi_header);
  212     m->m_len  -= sizeof(struct fddi_header);
  213     m->m_pkthdr.len = pktlen - sizeof(struct fddi_header);
  214     m->m_pkthdr.rcvif = &sc->sc_if;
  215     fddi_input(&sc->sc_if, fh, m);
  216 }
  217 
  218 void
  219 pdq_os_restart_transmitter(
  220     pdq_t *pdq)
  221 {
  222     pdq_softc_t *sc = (pdq_softc_t *) pdq->pdq_os_ctx;
  223     sc->sc_if.if_flags &= ~IFF_OACTIVE;
  224     if (sc->sc_if.if_snd.ifq_head != NULL) {
  225         sc->sc_if.if_timer = PDQ_OS_TX_TIMEOUT;
  226         pdq_ifstart(&sc->sc_if);
  227     } else {
  228         sc->sc_if.if_timer = 0;
  229     }
  230 }
  231 
  232 void
  233 pdq_os_transmit_done(
  234     pdq_t *pdq,
  235     struct mbuf *m)
  236 {
  237     pdq_softc_t *sc = (pdq_softc_t *) pdq->pdq_os_ctx;
  238 #if NBPFILTER > 0
  239     if (sc->sc_bpf != NULL)
  240         PDQ_BPF_MTAP(sc, m);
  241 #endif
  242     m_freem(m);
  243     sc->sc_if.if_opackets++;
  244 }
  245 
  246 void
  247 pdq_os_addr_fill(
  248     pdq_t *pdq,
  249     pdq_lanaddr_t *addr,
  250     size_t num_addrs)
  251 {
  252     pdq_softc_t *sc = (pdq_softc_t *) pdq->pdq_os_ctx;
  253     struct ether_multistep step;
  254     struct ether_multi *enm;
  255 
  256     ETHER_FIRST_MULTI(step, &sc->sc_ac, enm);
  257     while (enm != NULL && num_addrs > 0) {
  258         ((u_short *) addr->lanaddr_bytes)[0] = ((u_short *) enm->enm_addrlo)[0];
  259         ((u_short *) addr->lanaddr_bytes)[1] = ((u_short *) enm->enm_addrlo)[1];
  260         ((u_short *) addr->lanaddr_bytes)[2] = ((u_short *) enm->enm_addrlo)[2];
  261         ETHER_NEXT_MULTI(step, enm);
  262         addr++;
  263         num_addrs--;
  264     }
  265 }
  266 
  267 int
  268 pdq_ifioctl(
  269     struct ifnet *ifp,
  270     ioctl_cmd_t cmd,
  271     caddr_t data)
  272 {
  273     pdq_softc_t *sc = (pdq_softc_t *) ((caddr_t) ifp - offsetof(pdq_softc_t, sc_ac.ac_if));
  274     int s, error = 0;
  275 
  276     s = splimp();
  277 
  278     switch (cmd) {
  279         case SIOCSIFADDR: {
  280             struct ifaddr *ifa = (struct ifaddr *)data;
  281 
  282             ifp->if_flags |= IFF_UP;
  283             switch(ifa->ifa_addr->sa_family) {
  284 #if defined(INET)
  285                 case AF_INET: {
  286                     pdq_ifinit(sc);
  287                     arp_ifinit(&sc->sc_ac, ifa);
  288                     break;
  289                 }
  290 #endif /* INET */
  291 
  292 #if defined(NS)
  293                 /* This magic copied from if_is.c; I don't use XNS,
  294                  * so I have no way of telling if this actually
  295                  * works or not.
  296                  */
  297                 case AF_NS: {
  298                     struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
  299                     if (ns_nullhost(*ina)) {
  300                         ina->x_host = *(union ns_host *)(sc->sc_ac.ac_enaddr);
  301                     } else {
  302                         ifp->if_flags &= ~IFF_RUNNING;
  303                         bcopy((caddr_t)ina->x_host.c_host,
  304                               (caddr_t)sc->sc_ac.ac_enaddr,
  305                               sizeof sc->sc_ac.ac_enaddr);
  306                     }
  307 
  308                     pdq_ifinit(sc);
  309                     break;
  310                 }
  311 #endif /* NS */
  312 
  313                 default: {
  314                     pdq_ifinit(sc);
  315                     break;
  316                 }
  317             }
  318             break;
  319         }
  320         case SIOCGIFADDR: {
  321             struct ifreq *ifr = (struct ifreq *)data;
  322             bcopy((caddr_t) sc->sc_ac.ac_enaddr,
  323                   (caddr_t) ((struct sockaddr *)&ifr->ifr_data)->sa_data,
  324                   6);
  325             break;
  326         }
  327 
  328         case SIOCSIFFLAGS: {
  329             pdq_ifinit(sc);
  330             break;
  331         }
  332 
  333         case SIOCADDMULTI:
  334         case SIOCDELMULTI: {
  335             /*
  336              * Update multicast listeners
  337              */
  338             if (cmd == SIOCADDMULTI)
  339                 error = ether_addmulti((struct ifreq *)data, &sc->sc_ac);
  340             else
  341                 error = ether_delmulti((struct ifreq *)data, &sc->sc_ac);
  342 
  343             if (error == ENETRESET) {
  344                 if (sc->sc_if.if_flags & IFF_RUNNING)
  345                     pdq_run(sc->sc_pdq);
  346                 error = 0;
  347             }
  348             break;
  349         }
  350 
  351 #if defined(SIOCSIFMTU)
  352 #if !defined(ifr_mtu)
  353 #define ifr_mtu ifr_metric
  354 #endif
  355         case SIOCSIFMTU: {
  356             struct ifreq *ifr = (struct ifreq *)data;
  357             /*
  358              * Set the interface MTU.
  359              */
  360             if (ifr->ifr_mtu > FDDIMTU) {
  361                 error = EINVAL;
  362                 break;
  363             }
  364             ifp->if_mtu = ifr->ifr_mtu;
  365             break;
  366         }
  367 #endif /* SIOCSIFMTU */
  368 
  369         default: {
  370             error = EINVAL;
  371             break;
  372         }
  373     }
  374 
  375     splx(s);
  376     return error;
  377 }
  378 
  379 #ifndef IFF_NOTRAILERS
  380 #define IFF_NOTRAILERS  0
  381 #endif
  382 
  383 void
  384 pdq_ifattach(
  385     pdq_softc_t *sc,
  386     ifnet_ret_t (*ifwatchdog)(int unit))
  387 {
  388     struct ifnet *ifp = &sc->sc_if;
  389 
  390     ifp->if_flags = IFF_BROADCAST|IFF_SIMPLEX|IFF_NOTRAILERS|IFF_MULTICAST;
  391 
  392 #if (defined(__FreeBSD__) && BSD >= 199506) || defined(__NetBSD__)
  393     ifp->if_watchdog = pdq_ifwatchdog;
  394 #else
  395     ifp->if_watchdog = ifwatchdog;
  396 #endif
  397 
  398     ifp->if_ioctl = pdq_ifioctl;
  399     ifp->if_output = fddi_output;
  400     ifp->if_start = pdq_ifstart;
  401   
  402     if_attach(ifp);
  403     fddi_ifattach(ifp);
  404 #if NBPFILTER > 0
  405     PDQ_BPFATTACH(sc, DLT_FDDI, sizeof(struct fddi_header));
  406 #endif
  407 }

Cache object: b00ddb9649eb876a39d59e4155ce1b63


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.