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$
   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 "opt_inet.h"
   37 
   38 #include <sys/param.h>
   39 #include <sys/socket.h>
   40 #include <sys/sockio.h>
   41 #if defined(__bsdi__) || defined(__NetBSD__)
   42 #include <sys/device.h>
   43 #endif
   44 
   45 #include <net/if.h>
   46 #include <net/if_dl.h>
   47 
   48 #include "bpfilter.h"
   49 #if NBPFILTER > 0
   50 #include <net/bpf.h>
   51 #endif
   52 
   53 #if defined(__FreeBSD__)
   54 #ifdef INET
   55 #include <netinet/in.h>
   56 #include <netinet/if_ether.h>
   57 #endif
   58 #include <netinet/if_fddi.h>
   59 #else
   60 #include <net/if_fddi.h>
   61 #endif
   62 
   63 #if defined(__bsdi__)
   64 #include <i386/isa/isavar.h>
   65 #endif
   66 
   67 #ifdef NS
   68 #include <netns/ns.h>
   69 #include <netns/ns_if.h>
   70 #endif
   71 
   72 #if defined(__FreeBSD__)
   73 #include <dev/pdq/pdqvar.h>
   74 #include <dev/pdq/pdqreg.h>
   75 #else
   76 #include "pdqvar.h"
   77 #include "pdqreg.h"
   78 #endif
   79 
   80 #if defined(__bsdi__) && _BSDI_VERSION < 199506 /* XXX */
   81 static void
   82 arp_ifinit(
   83     struct arpcom *ac,
   84     struct ifaddr *ifa)
   85 {
   86     sc->sc_ac.ac_ipaddr = IA_SIN(ifa)->sin_addr;
   87     arpwhohas(&sc->sc_ac, &IA_SIN(ifa)->sin_addr);
   88 #if _BSDI_VERSION >= 199401
   89     ifa->ifa_rtrequest = arp_rtrequest;
   90     ifa->ifa_flags |= RTF_CLONING;
   91 #endif
   92 #endif
   93 
   94 
   95 void
   96 pdq_ifinit(
   97     pdq_softc_t *sc)
   98 {
   99     if (sc->sc_if.if_flags & IFF_UP) {
  100         sc->sc_if.if_flags |= IFF_RUNNING;
  101         if (sc->sc_if.if_flags & IFF_PROMISC) {
  102             sc->sc_pdq->pdq_flags |= PDQ_PROMISC;
  103         } else {
  104             sc->sc_pdq->pdq_flags &= ~PDQ_PROMISC;
  105         }
  106         if (sc->sc_if.if_flags & IFF_ALLMULTI) {
  107             sc->sc_pdq->pdq_flags |= PDQ_ALLMULTI;
  108         } else {
  109             sc->sc_pdq->pdq_flags &= ~PDQ_ALLMULTI;
  110         }
  111         if (sc->sc_if.if_flags & IFF_LINK1) {
  112             sc->sc_pdq->pdq_flags |= PDQ_PASS_SMT;
  113         } else {
  114             sc->sc_pdq->pdq_flags &= ~PDQ_PASS_SMT;
  115         }
  116         sc->sc_pdq->pdq_flags |= PDQ_RUNNING;
  117         pdq_run(sc->sc_pdq);
  118     } else {
  119         sc->sc_if.if_flags &= ~IFF_RUNNING;
  120         sc->sc_pdq->pdq_flags &= ~PDQ_RUNNING;
  121         pdq_stop(sc->sc_pdq);
  122     }
  123 }
  124 
  125 void
  126 pdq_ifwatchdog(
  127     struct ifnet *ifp)
  128 {
  129     /*
  130      * No progress was made on the transmit queue for PDQ_OS_TX_TRANSMIT
  131      * seconds.  Remove all queued packets.
  132      */
  133 
  134     ifp->if_flags &= ~IFF_OACTIVE;
  135     ifp->if_timer = 0;
  136     for (;;) {
  137         struct mbuf *m;
  138         IF_DEQUEUE(&ifp->if_snd, m);
  139         if (m == NULL)
  140             return;
  141         m_freem(m);
  142     }
  143 }
  144 
  145 ifnet_ret_t
  146 pdq_ifstart(
  147     struct ifnet *ifp)
  148 {
  149     pdq_softc_t *sc = (pdq_softc_t *) ((caddr_t) ifp - offsetof(pdq_softc_t, sc_ac.ac_if));
  150     struct ifqueue *ifq = &ifp->if_snd;
  151     struct mbuf *m;
  152     int tx = 0;
  153 
  154     if ((ifp->if_flags & IFF_RUNNING) == 0)
  155         return;
  156 
  157     if (sc->sc_if.if_timer == 0)
  158         sc->sc_if.if_timer = PDQ_OS_TX_TIMEOUT;
  159 
  160     if ((sc->sc_pdq->pdq_flags & PDQ_TXOK) == 0) {
  161         sc->sc_if.if_flags |= IFF_OACTIVE;
  162         return;
  163     }
  164     for (;; tx = 1) {
  165         IF_DEQUEUE(ifq, m);
  166         if (m == NULL)
  167             break;
  168 
  169         if (pdq_queue_transmit_data(sc->sc_pdq, m) == PDQ_FALSE) {
  170             ifp->if_flags |= IFF_OACTIVE;
  171             IF_PREPEND(ifq, m);
  172             break;
  173         }
  174     }
  175     if (tx)
  176         PDQ_DO_TYPE2_PRODUCER(sc->sc_pdq);
  177 }
  178 
  179 void
  180 pdq_os_receive_pdu(
  181     pdq_t *pdq,
  182     struct mbuf *m,
  183     size_t pktlen)
  184 {
  185     pdq_softc_t *sc = (pdq_softc_t *) pdq->pdq_os_ctx;
  186     struct fddi_header *fh = mtod(m, struct fddi_header *);
  187 
  188     sc->sc_if.if_ipackets++;
  189 #if NBPFILTER > 0
  190     if (sc->sc_bpf != NULL)
  191         PDQ_BPF_MTAP(sc, m);
  192     if ((fh->fddi_fc & (FDDIFC_L|FDDIFC_F)) != FDDIFC_LLC_ASYNC) {
  193         m_freem(m);
  194         return;
  195     }
  196 #endif
  197 
  198     m->m_data += sizeof(struct fddi_header);
  199     m->m_len  -= sizeof(struct fddi_header);
  200     m->m_pkthdr.len = pktlen - sizeof(struct fddi_header);
  201     m->m_pkthdr.rcvif = &sc->sc_if;
  202     fddi_input(&sc->sc_if, fh, m);
  203 }
  204 
  205 void
  206 pdq_os_restart_transmitter(
  207     pdq_t *pdq)
  208 {
  209     pdq_softc_t *sc = (pdq_softc_t *) pdq->pdq_os_ctx;
  210     sc->sc_if.if_flags &= ~IFF_OACTIVE;
  211     if (sc->sc_if.if_snd.ifq_head != NULL) {
  212         sc->sc_if.if_timer = PDQ_OS_TX_TIMEOUT;
  213         pdq_ifstart(&sc->sc_if);
  214     } else {
  215         sc->sc_if.if_timer = 0;
  216     }
  217 }
  218 
  219 void
  220 pdq_os_transmit_done(
  221     pdq_t *pdq,
  222     struct mbuf *m)
  223 {
  224     pdq_softc_t *sc = (pdq_softc_t *) pdq->pdq_os_ctx;
  225 #if NBPFILTER > 0
  226     if (sc->sc_bpf != NULL)
  227         PDQ_BPF_MTAP(sc, m);
  228 #endif
  229     m_freem(m);
  230     sc->sc_if.if_opackets++;
  231 }
  232 
  233 void
  234 pdq_os_addr_fill(
  235     pdq_t *pdq,
  236     pdq_lanaddr_t *addr,
  237     size_t num_addrs)
  238 {
  239     pdq_softc_t *sc = (pdq_softc_t *) pdq->pdq_os_ctx;
  240     struct ifmultiaddr *ifma;
  241 
  242     for (ifma = sc->sc_if.if_multiaddrs.lh_first; ifma && num_addrs > 0;
  243          ifma = ifma->ifma_link.le_next) {
  244             char *mcaddr;
  245             if (ifma->ifma_addr->sa_family != AF_LINK)
  246                     continue;
  247             mcaddr = LLADDR((struct sockaddr_dl *)ifma->ifma_addr);
  248             ((u_short *) addr->lanaddr_bytes)[0] = ((u_short *) mcaddr)[0];
  249             ((u_short *) addr->lanaddr_bytes)[1] = ((u_short *) mcaddr)[1];
  250             ((u_short *) addr->lanaddr_bytes)[2] = ((u_short *) mcaddr)[2];
  251             addr++;
  252             num_addrs--;
  253     }
  254 }
  255 
  256 int
  257 pdq_ifioctl(
  258     struct ifnet *ifp,
  259     ioctl_cmd_t cmd,
  260     caddr_t data)
  261 {
  262     pdq_softc_t *sc = (pdq_softc_t *) ((caddr_t) ifp - offsetof(pdq_softc_t, sc_ac.ac_if));
  263     int s, error = 0;
  264 
  265     s = splimp();
  266 
  267     switch (cmd) {
  268         case SIOCSIFADDR: {
  269             struct ifaddr *ifa = (struct ifaddr *)data;
  270 
  271             ifp->if_flags |= IFF_UP;
  272             switch(ifa->ifa_addr->sa_family) {
  273 #if defined(INET)
  274                 case AF_INET: {
  275                     pdq_ifinit(sc);
  276                     arp_ifinit(&sc->sc_ac, ifa);
  277                     break;
  278                 }
  279 #endif /* INET */
  280 
  281 #if defined(NS)
  282                 /* This magic copied from if_is.c; I don't use XNS,
  283                  * so I have no way of telling if this actually
  284                  * works or not.
  285                  */
  286                 case AF_NS: {
  287                     struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
  288                     if (ns_nullhost(*ina)) {
  289                         ina->x_host = *(union ns_host *)(sc->sc_ac.ac_enaddr);
  290                     } else {
  291                         ifp->if_flags &= ~IFF_RUNNING;
  292                         bcopy((caddr_t)ina->x_host.c_host,
  293                               (caddr_t)sc->sc_ac.ac_enaddr,
  294                               sizeof sc->sc_ac.ac_enaddr);
  295                     }
  296 
  297                     pdq_ifinit(sc);
  298                     break;
  299                 }
  300 #endif /* NS */
  301 
  302                 default: {
  303                     pdq_ifinit(sc);
  304                     break;
  305                 }
  306             }
  307             break;
  308         }
  309         case SIOCGIFADDR: {
  310             struct ifreq *ifr = (struct ifreq *)data;
  311             bcopy((caddr_t) sc->sc_ac.ac_enaddr,
  312                   (caddr_t) ((struct sockaddr *)&ifr->ifr_data)->sa_data,
  313                   6);
  314             break;
  315         }
  316 
  317         case SIOCSIFFLAGS: {
  318             pdq_ifinit(sc);
  319             break;
  320         }
  321 
  322         case SIOCADDMULTI:
  323         case SIOCDELMULTI:
  324                 /*
  325                  * Update multicast listeners
  326                  */
  327                 if (sc->sc_if.if_flags & IFF_RUNNING)
  328                         pdq_run(sc->sc_pdq);
  329                 error = 0;
  330                 break;
  331 
  332 #if defined(SIOCSIFMTU)
  333 #if !defined(ifr_mtu)
  334 #define ifr_mtu ifr_metric
  335 #endif
  336         case SIOCSIFMTU: {
  337             struct ifreq *ifr = (struct ifreq *)data;
  338             /*
  339              * Set the interface MTU.
  340              */
  341             if (ifr->ifr_mtu > FDDIMTU) {
  342                 error = EINVAL;
  343                 break;
  344             }
  345             ifp->if_mtu = ifr->ifr_mtu;
  346             break;
  347         }
  348 #endif /* SIOCSIFMTU */
  349 
  350         default: {
  351             error = EINVAL;
  352             break;
  353         }
  354     }
  355 
  356     splx(s);
  357     return error;
  358 }
  359 
  360 #ifndef IFF_NOTRAILERS
  361 #define IFF_NOTRAILERS  0
  362 #endif
  363 
  364 void
  365 pdq_ifattach(
  366     pdq_softc_t *sc,
  367     ifnet_ret_t (*ifwatchdog)(int unit))
  368 {
  369     struct ifnet *ifp = &sc->sc_if;
  370 
  371     ifp->if_flags = IFF_BROADCAST|IFF_SIMPLEX|IFF_NOTRAILERS|IFF_MULTICAST;
  372 
  373 #if (defined(__FreeBSD__) && BSD >= 199506) || defined(__NetBSD__)
  374     ifp->if_watchdog = pdq_ifwatchdog;
  375 #else
  376     ifp->if_watchdog = ifwatchdog;
  377 #endif
  378 
  379     ifp->if_ioctl = pdq_ifioctl;
  380     ifp->if_output = fddi_output;
  381     ifp->if_start = pdq_ifstart;
  382 #warning "Implement fddi_resolvemulti!"
  383 /*    ifp->if_resolvemulti = ether_resolvemulti; XXX */
  384   
  385     if_attach(ifp);
  386     fddi_ifattach(ifp);
  387 #if NBPFILTER > 0
  388     PDQ_BPFATTACH(sc, DLT_FDDI, sizeof(struct fddi_header));
  389 #endif
  390 }

Cache object: a8b959964fe4fdbf1096b652501d0761


[ 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.