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/harp/if_harp.c

Version: -  FREEBSD  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-2  -  FREEBSD-11-1  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-4  -  FREEBSD-10-3  -  FREEBSD-10-2  -  FREEBSD-10-1  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-3  -  FREEBSD-9-2  -  FREEBSD-9-1  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-4  -  FREEBSD-8-3  -  FREEBSD-8-2  -  FREEBSD-8-1  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-4  -  FREEBSD-7-3  -  FREEBSD-7-2  -  FREEBSD-7-1  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-4  -  FREEBSD-6-3  -  FREEBSD-6-2  -  FREEBSD-6-1  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-5  -  FREEBSD-5-4  -  FREEBSD-5-3  -  FREEBSD-5-2  -  FREEBSD-5-1  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2003
    3  *      Fraunhofer Institute for Open Communication Systems (FhG Fokus).
    4  *      All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   25  * SUCH DAMAGE.
   26  *
   27  * Author: Harti Brandt <harti@freebsd.org>
   28  *
   29  * HARP pseudo-driver. This driver when loaded attaches to all ngATM drivers
   30  * in the system and creates a HARP physical interface for each of them.
   31  */
   32 
   33 #include <sys/cdefs.h>
   34 __FBSDID("$FreeBSD$");
   35 
   36 #include <sys/cdefs.h>
   37 __FBSDID("$FreeBSD$");
   38 
   39 #include <sys/param.h>
   40 #include <sys/systm.h>
   41 #include <sys/malloc.h>
   42 #include <sys/kernel.h>
   43 #include <sys/conf.h>
   44 #include <sys/module.h>
   45 #include <sys/queue.h>
   46 #include <sys/syslog.h>
   47 
   48 #include <sys/sockio.h>
   49 #include <sys/mbuf.h>
   50 #include <sys/socket.h>
   51 #include <sys/socketvar.h>
   52 
   53 #include <net/if.h>
   54 #include <net/if_var.h>
   55 #include <net/if_types.h>
   56 #include <net/if_media.h>
   57 #include <net/netisr.h>
   58 
   59 #include <netatm/port.h>
   60 #include <netatm/queue.h>
   61 #include <netatm/atm.h>
   62 #include <netatm/atm_sys.h>
   63 #include <netatm/atm_sap.h>
   64 #include <netatm/atm_cm.h>
   65 #include <netatm/atm_if.h>
   66 #include <netatm/atm_stack.h>
   67 #include <netatm/atm_pcb.h>
   68 #include <netatm/atm_var.h>
   69 #include <netatm/atm_vc.h>
   70 
   71 #include <net/if_atm.h>
   72 
   73 #define HARP_MTU        9188
   74 
   75 /*
   76  * Physical interface softc
   77  */
   78 struct harp_softc {
   79         Cmn_unit        cmn;
   80         struct ifnet    *parent;
   81         LIST_ENTRY(harp_softc) link;
   82 };
   83 
   84 struct harp_vcc {
   85         struct cmn_vcc  cmn;
   86 };
   87 
   88 MODULE_VERSION(harp, 1);
   89 MODULE_DEPEND(harp, atm, 1, 1, 1);
   90 
   91 /* hooks from if_atmsubr.c */
   92 extern void (*atm_harp_input_p)(struct ifnet *ifp, struct mbuf **m,
   93     struct atm_pseudohdr *ah, void *rxhand);
   94 extern void (*atm_harp_attach_p)(struct ifnet *);
   95 extern void (*atm_harp_detach_p)(struct ifnet *);
   96 
   97 static MALLOC_DEFINE(M_HARP, "harp", "Harp pseudo interface");
   98 
   99 static uma_zone_t harp_nif_zone;
  100 static uma_zone_t harp_vcc_zone;
  101 
  102 /* List of all existing 'harp' interfaces */
  103 static LIST_HEAD(, harp_softc) harp_softc_list =
  104     LIST_HEAD_INITIALIZER(harp_softc_list);
  105 
  106 static struct stack_defn harp_svaal5 = {
  107         NULL,
  108         SAP_CPCS_AAL5,
  109         SDF_TERM,
  110         atm_dev_inst,
  111         atm_dev_lower,
  112         NULL,
  113         0,
  114 };
  115 
  116 static struct stack_defn *harp_services = &harp_svaal5;
  117 
  118 /*
  119  * Map between constants
  120  */
  121 static const struct {
  122         u_int   vendor;
  123         u_int   api;
  124         u_int   dev;
  125 } map_devs[] = {
  126         [ATM_DEVICE_UNKNOWN] =
  127                 { VENDOR_UNKNOWN, VENDAPI_UNKNOWN, DEV_UNKNOWN },
  128         [ATM_DEVICE_PCA200E] =
  129                 { VENDOR_FORE, VENDAPI_FORE_1, DEV_FORE_PCA200E },
  130         [ATM_DEVICE_HE155] =
  131                 { VENDOR_FORE, VENDAPI_FORE_2, DEV_FORE_HE155 },
  132         [ATM_DEVICE_HE622] =
  133                 { VENDOR_FORE, VENDAPI_FORE_2, DEV_FORE_HE622 },
  134         [ATM_DEVICE_ENI155P] =
  135                 { VENDOR_ENI, VENDAPI_ENI_1, DEV_ENI_155P },
  136         [ATM_DEVICE_ADP155P] =
  137                 { VENDOR_ENI, VENDAPI_ENI_1, DEV_ENI_155P },
  138         [ATM_DEVICE_FORELE25] =
  139                 { VENDOR_FORE, VENDAPI_IDT_1, DEV_FORE_LE25 },
  140         [ATM_DEVICE_FORELE155] =
  141                 { VENDOR_FORE, VENDAPI_IDT_1, DEV_FORE_LE155 },
  142         [ATM_DEVICE_NICSTAR25] =
  143                 { VENDOR_IDT, VENDAPI_IDT_1, DEV_IDT_25 },
  144         [ATM_DEVICE_NICSTAR155] =
  145                 { VENDOR_IDT, VENDAPI_IDT_1, DEV_IDT_155 },
  146         [ATM_DEVICE_IDTABR25] =
  147                 { VENDOR_IDT, VENDAPI_IDT_2, DEV_IDTABR_25 },
  148         [ATM_DEVICE_IDTABR155] =
  149                 { VENDOR_IDT, VENDAPI_IDT_2, DEV_IDTABR_155 },
  150         [ATM_DEVICE_PROATM25] =
  151                 { VENDOR_PROSUM, VENDAPI_IDT_2, DEV_PROATM_25 },
  152         [ATM_DEVICE_PROATM155] =
  153                 { VENDOR_PROSUM, VENDAPI_IDT_2, DEV_PROATM_155 },
  154 };
  155 
  156 /*
  157  * Return zero if this interface is ok for us.
  158  * XXX This should go away when we have full ngATM-ified the en driver.
  159  */
  160 static int
  161 harp_check_if(const struct ifnet *ifp)
  162 {
  163         if (ifp->if_type == IFT_ATM && strcmp(ifp->if_dname, "en"))
  164                 return (0);
  165         else
  166                 return (-1);
  167 }
  168 
  169 /*
  170  * Instantiate a VCC stack.
  171  *
  172  * Could check for correct attributes here.
  173  */
  174 static int
  175 harp_instvcc(Cmn_unit *up, Cmn_vcc *vp)
  176 {
  177         struct harp_softc *sc;
  178 
  179         if (up == NULL || vp == NULL || vp->cv_connvc == NULL)
  180                 return (EINVAL);
  181 
  182         sc = (struct harp_softc *)up;
  183 
  184         return (0);
  185 }
  186 
  187 /*
  188  * Open a VCC.
  189  */
  190 static int
  191 harp_openvcc(Cmn_unit *up, Cmn_vcc *vp)
  192 {
  193         struct harp_softc *sc;
  194         struct atmio_openvcc data;
  195         Atm_attributes *attrib;
  196         struct vccb *vccinf;
  197         const struct ifatm_mib *mib;
  198         int err;
  199 
  200         if (up == NULL || vp == NULL || vp->cv_connvc == NULL)
  201                 return (EINVAL);
  202 
  203         sc = (struct harp_softc *)up;
  204         mib = sc->parent->if_linkmib;
  205 
  206         attrib = &vp->cv_connvc->cvc_attr;
  207         vccinf = vp->cv_connvc->cvc_vcc;
  208 
  209         if (attrib == NULL || vccinf == NULL)
  210                 return (EINVAL);
  211 
  212         if (vccinf->vc_vpi >= (1 << mib->vpi_bits) ||
  213             vccinf->vc_vci >= (1 << mib->vci_bits))
  214                 return (EINVAL);
  215 
  216         memset(&data, 0, sizeof(data));
  217 
  218         switch (attrib->aal.type) {
  219 
  220           case ATM_AAL0:
  221                 data.param.aal = ATMIO_AAL_0;
  222                 break;
  223 
  224           case ATM_AAL5:
  225                 data.param.aal = ATMIO_AAL_5;
  226                 break;
  227 
  228           default:
  229                 return (EINVAL);
  230         }
  231         data.param.vpi = vccinf->vc_vpi;
  232         data.param.vci = vccinf->vc_vci;
  233         data.param.rmtu = HARP_MTU;
  234         data.param.tmtu = HARP_MTU;
  235 
  236         switch (attrib->bearer.v.bearer_class) {
  237 
  238           case T_ATM_CLASS_C:
  239                 data.param.traffic = ATMIO_TRAFFIC_VBR;
  240                 break;
  241 
  242           case T_ATM_CLASS_X:
  243                 switch (attrib->bearer.v.traffic_type) {
  244 
  245                   case T_ATM_CBR:
  246                         data.param.traffic = ATMIO_TRAFFIC_CBR;
  247                         break;
  248 
  249                   case T_ATM_VBR:
  250                         data.param.traffic = ATMIO_TRAFFIC_VBR;
  251                         break;
  252 
  253                   case T_ATM_ABR:
  254                         /* not really supported by HARP */
  255                         return (EINVAL);
  256 
  257                   default:
  258                   case T_ATM_UBR:
  259                         data.param.traffic = ATMIO_TRAFFIC_UBR;
  260                         break;
  261                 }
  262                 break;
  263 
  264           default:
  265                 return (EINVAL);
  266         }
  267         data.param.tparam.pcr = attrib->traffic.v.forward.PCR_all_traffic;
  268         data.param.tparam.scr = attrib->traffic.v.forward.SCR_all_traffic;
  269         data.param.tparam.mbs = attrib->traffic.v.forward.MBS_all_traffic;
  270 
  271         data.rxhand = sc;
  272         data.param.flags = ATMIO_FLAG_HARP;
  273 
  274         err = (*sc->parent->if_ioctl)(sc->parent, SIOCATMOPENVCC,
  275             (caddr_t)&data);
  276 
  277         return (err);
  278 }
  279 
  280 /*
  281  * Close VCC
  282  */
  283 static int
  284 harp_closevcc(Cmn_unit *up, Cmn_vcc *vp)
  285 {
  286         struct harp_softc *sc;
  287         struct atmio_closevcc data;
  288         int err;
  289 
  290         if (vp == NULL || vp->cv_connvc == NULL ||
  291             vp->cv_connvc->cvc_vcc == NULL)
  292                 return (EINVAL);
  293 
  294         sc = (struct harp_softc *)up;
  295         
  296         data.vpi = vp->cv_connvc->cvc_vcc->vc_vpi;
  297         data.vci = vp->cv_connvc->cvc_vcc->vc_vci;
  298 
  299         err = (*sc->parent->if_ioctl)(sc->parent, SIOCATMCLOSEVCC,
  300             (caddr_t)&data);
  301 
  302         return (err);
  303 }
  304 
  305 /*
  306  * IOCTLs
  307  */
  308 static int
  309 harp_ioctl(int code, caddr_t addr, caddr_t arg)
  310 {
  311         return (ENOSYS);
  312 }
  313 
  314 /*
  315  * Output data
  316  */
  317 static void
  318 harp_output(Cmn_unit *cu, Cmn_vcc *cv, KBuffer *m)
  319 {
  320         struct harp_softc *sc = (struct harp_softc *)cu;
  321         struct atm_pseudohdr *aph;
  322         int error;
  323         int mlen;
  324 
  325         if (cv == NULL || cv->cv_connvc == NULL ||
  326             cv->cv_connvc->cvc_vcc == NULL) {
  327                 m_freem(m);
  328                 return;
  329         }
  330         M_ASSERTPKTHDR(m);
  331 
  332         /*
  333          * Harp seems very broken with regard to mbuf handling. The length
  334          * in the packet header is mostly broken here so recompute it.
  335          */
  336         m->m_pkthdr.len = mlen = m_length(m, NULL);
  337 
  338         /*
  339          * Prepend pseudo-hdr. Drivers don't care about the flags.
  340          */
  341         M_PREPEND(m, sizeof(*aph), M_DONTWAIT);
  342         if (m == NULL)
  343                 return;
  344 
  345         aph = mtod(m, struct atm_pseudohdr *);
  346         ATM_PH_VPI(aph) = cv->cv_connvc->cvc_vcc->vc_vpi;
  347         ATM_PH_SETVCI(aph, cv->cv_connvc->cvc_vcc->vc_vci);
  348         ATM_PH_FLAGS(aph) = 0;
  349 
  350         error = atm_output(sc->parent, m, NULL, NULL);
  351 
  352         if (error) {
  353                 printf("%s: error %d\n", __func__, error);
  354                 sc->cmn.cu_pif.pif_oerrors++;
  355                 cv->cv_connvc->cvc_vcc->vc_oerrors++;
  356                 if (cv->cv_connvc->cvc_vcc->vc_nif)
  357                         cv->cv_connvc->cvc_vcc->vc_nif->nif_if.if_oerrors++;
  358                 return;
  359         }
  360 
  361         /* statistics */
  362         sc->cmn.cu_pif.pif_opdus++;
  363         sc->cmn.cu_pif.pif_obytes += mlen;
  364         cv->cv_connvc->cvc_vcc->vc_opdus++;
  365         cv->cv_connvc->cvc_vcc->vc_obytes += mlen;
  366         if (cv->cv_connvc->cvc_vcc->vc_nif) {
  367                 cv->cv_connvc->cvc_vcc->vc_nif->nif_obytes += mlen;
  368                 cv->cv_connvc->cvc_vcc->vc_nif->nif_if.if_obytes += mlen;
  369                 cv->cv_connvc->cvc_vcc->vc_nif->nif_if.if_opackets++;
  370         }
  371 }
  372 
  373 /*
  374  * Attach a new interface
  375  */
  376 static void
  377 harp_attach(struct ifnet *parent)
  378 {
  379         struct harp_softc *sc;
  380         const struct ifatm_mib *mib;
  381         int error;
  382 
  383         if (harp_check_if(parent) != 0)
  384                 return;
  385 
  386         sc = malloc(sizeof(*sc), M_HARP, M_WAITOK | M_ZERO);
  387 
  388         sc->parent = parent;
  389         sc->cmn.cu_unit = parent->if_dunit;
  390         sc->cmn.cu_mtu = HARP_MTU;
  391         sc->cmn.cu_ioctl = harp_ioctl;
  392         sc->cmn.cu_instvcc = harp_instvcc;
  393         sc->cmn.cu_openvcc = harp_openvcc;
  394         sc->cmn.cu_closevcc = harp_closevcc;
  395         sc->cmn.cu_output = harp_output;
  396         sc->cmn.cu_vcc_zone = harp_vcc_zone;
  397         sc->cmn.cu_nif_zone = harp_nif_zone;
  398         sc->cmn.cu_softc = sc;
  399 
  400         /* config */
  401         mib = parent->if_linkmib;
  402         if (mib->device >= sizeof(map_devs) / sizeof(map_devs[0])) {
  403                 sc->cmn.cu_config.ac_vendor = VENDOR_UNKNOWN;
  404                 sc->cmn.cu_config.ac_vendapi = VENDAPI_UNKNOWN;
  405                 sc->cmn.cu_config.ac_device = DEV_UNKNOWN;
  406         } else {
  407                 sc->cmn.cu_config.ac_vendor = map_devs[mib->device].vendor;
  408                 sc->cmn.cu_config.ac_vendapi = map_devs[mib->device].api;
  409                 sc->cmn.cu_config.ac_device = map_devs[mib->device].dev;
  410         }
  411 
  412         switch (mib->media) {
  413 
  414           case IFM_ATM_UTP_25:
  415                 sc->cmn.cu_config.ac_media = MEDIA_UTP25;;
  416                 break;
  417 
  418           case IFM_ATM_TAXI_100:
  419                 sc->cmn.cu_config.ac_media = MEDIA_TAXI_100;
  420                 break;
  421 
  422           case IFM_ATM_TAXI_140:
  423                 sc->cmn.cu_config.ac_media = MEDIA_TAXI_140;
  424                 break;
  425 
  426           case IFM_ATM_MM_155:
  427           case IFM_ATM_SM_155:
  428                 sc->cmn.cu_config.ac_media = MEDIA_OC3C;
  429                 break;
  430 
  431           case IFM_ATM_MM_622:
  432           case IFM_ATM_SM_622:
  433                 sc->cmn.cu_config.ac_media = MEDIA_OC12C;
  434                 break;
  435 
  436           case IFM_ATM_UTP_155:
  437                 sc->cmn.cu_config.ac_media = MEDIA_UTP155;
  438                 break;
  439 
  440           default:
  441                 sc->cmn.cu_config.ac_media = MEDIA_UNKNOWN;
  442                 break;
  443         }
  444         sc->cmn.cu_config.ac_bustype = BUS_PCI;
  445         sc->cmn.cu_pif.pif_pcr = mib->pcr;
  446         sc->cmn.cu_pif.pif_maxvpi = (1 << mib->vpi_bits) - 1;
  447         sc->cmn.cu_pif.pif_maxvci = (1 << mib->vci_bits) - 1;
  448 
  449         snprintf(sc->cmn.cu_config.ac_hard_vers,
  450             sizeof(sc->cmn.cu_config.ac_hard_vers), "0x%lx",
  451             (u_long)mib->hw_version);
  452         snprintf(sc->cmn.cu_config.ac_firm_vers,
  453             sizeof(sc->cmn.cu_config.ac_firm_vers), "0x%lx",
  454             (u_long)mib->sw_version);
  455         sc->cmn.cu_config.ac_serial = mib->serial;
  456         sc->cmn.cu_config.ac_ram = 0;
  457         sc->cmn.cu_config.ac_ramsize = 0;
  458 
  459         sc->cmn.cu_config.ac_macaddr.ma_data[0] =
  460             sc->cmn.cu_pif.pif_macaddr.ma_data[0] = mib->esi[0];
  461         sc->cmn.cu_config.ac_macaddr.ma_data[1] =
  462             sc->cmn.cu_pif.pif_macaddr.ma_data[1] = mib->esi[1];
  463         sc->cmn.cu_config.ac_macaddr.ma_data[2] =
  464             sc->cmn.cu_pif.pif_macaddr.ma_data[2] = mib->esi[2];
  465         sc->cmn.cu_config.ac_macaddr.ma_data[3] =
  466             sc->cmn.cu_pif.pif_macaddr.ma_data[3] = mib->esi[3];
  467         sc->cmn.cu_config.ac_macaddr.ma_data[4] =
  468             sc->cmn.cu_pif.pif_macaddr.ma_data[4] = mib->esi[4];
  469         sc->cmn.cu_config.ac_macaddr.ma_data[5] =
  470             sc->cmn.cu_pif.pif_macaddr.ma_data[5] = mib->esi[5];
  471 
  472         error = atm_physif_register(&sc->cmn, parent->if_dname, harp_services);
  473         if (error) {
  474                 log(LOG_ERR, "%s: pif registration failed %d\n",
  475                     parent->if_dname, error);
  476                 free(sc, M_HARP);
  477                 return;
  478         }
  479         LIST_INSERT_HEAD(&harp_softc_list, sc, link);
  480 
  481         sc->cmn.cu_flags |= CUF_INITED;
  482 }
  483 
  484 /*
  485  * Destroy a cloned device
  486  */
  487 static void
  488 harp_detach(struct ifnet *ifp)
  489 {
  490         struct harp_softc *sc;
  491         int error;
  492 
  493         LIST_FOREACH(sc, &harp_softc_list, link)
  494                 if (sc->parent == ifp)
  495                         break;
  496         if (sc == NULL)
  497                 return;
  498 
  499         error = atm_physif_deregister(&sc->cmn);
  500         if (error)
  501                 log(LOG_ERR, "%s: de-registration failed %d\n", ifp->if_dname,
  502                     error);
  503 
  504         LIST_REMOVE(sc, link);
  505 
  506         free(sc, M_HARP);
  507 }
  508 
  509 /*
  510  * Pass PDU up the stack
  511  */
  512 static void
  513 harp_recv_stack(void *tok, KBuffer *m)
  514 {
  515         Cmn_vcc *vcc = tok;
  516         int err;
  517 
  518         M_ASSERTPKTHDR(m);
  519         STACK_CALL(CPCS_UNITDATA_SIG, vcc->cv_upper, vcc->cv_toku,
  520             vcc->cv_connvc, (intptr_t)m, 0, err);
  521         if (err) {
  522                 printf("%s: error %d\n", __func__, err);
  523                 KB_FREEALL(m);
  524         }
  525 }
  526 
  527 /*
  528  * Possible input from NATM
  529  */
  530 static void
  531 harp_input(struct ifnet *ifp, struct mbuf **mp, struct atm_pseudohdr *ah,
  532     void *rxhand)
  533 {
  534         struct harp_softc *sc = rxhand;
  535         Cmn_vcc *vcc;
  536         char *cp;
  537         u_int pfxlen;
  538         struct mbuf *m, *m0;
  539         int mlen;
  540 
  541         if ((ATM_PH_FLAGS(ah) & ATMIO_FLAG_HARP) == 0)
  542                 return;
  543 
  544         /* grab the packet */
  545         m = *mp;
  546         *mp = NULL;
  547 
  548         if (sc->parent != ifp) {
  549                 printf("%s: parent=%p ifp=%p\n", __func__, sc->parent, ifp);
  550                 goto drop;
  551         }
  552 
  553         vcc = atm_dev_vcc_find(&sc->cmn, ATM_PH_VPI(ah),
  554             ATM_PH_VCI(ah), VCC_IN);
  555         if (vcc == NULL) {
  556                 printf("%s: VCC %u/%u not found\n", __func__,ATM_PH_VPI(ah),
  557                     ATM_PH_VCI(ah));
  558                 goto drop;
  559         }
  560 
  561         /* fit two pointers into the mbuf - assume, that the the data is
  562          * pointer aligned. If it doesn't fit into the first mbuf, prepend
  563          * another one.
  564          * Don't count the new fields in the packet length (XXX)
  565          */
  566         mlen = m->m_pkthdr.len;
  567         pfxlen = sizeof(atm_intr_func_t) + sizeof(void *);
  568         if (M_LEADINGSPACE(m) < pfxlen) {
  569                 MGETHDR(m0, 0, MT_DATA);
  570                 if (m0 == NULL) {
  571                         printf("%s: no leading space in buffer\n", __func__);
  572                         goto drop;
  573                 }
  574                 m0->m_len = 0;
  575                 m0->m_next = m;
  576 
  577                 M_MOVE_PKTHDR(m0, m);
  578 
  579                 m = m0;
  580         }
  581         m->m_len += pfxlen;
  582         m->m_data -= pfxlen;
  583         cp = mtod(m, char *);
  584         *((atm_intr_func_t *)cp) = harp_recv_stack;
  585         cp += sizeof(atm_intr_func_t);
  586         *((void **)cp) = (void *)vcc;
  587 
  588         /* count the packet */
  589         sc->cmn.cu_pif.pif_ipdus++;
  590         sc->cmn.cu_pif.pif_ibytes += mlen;
  591         vcc->cv_connvc->cvc_vcc->vc_ipdus++;
  592         vcc->cv_connvc->cvc_vcc->vc_ibytes += mlen;
  593         if (vcc->cv_connvc->cvc_vcc->vc_nif) {
  594                 vcc->cv_connvc->cvc_vcc->vc_nif->nif_ibytes += mlen;
  595                 vcc->cv_connvc->cvc_vcc->vc_nif->nif_if.if_ipackets++;
  596                 vcc->cv_connvc->cvc_vcc->vc_nif->nif_if.if_ibytes += mlen;
  597         }
  598 
  599         /* hand it off */
  600         netisr_dispatch(NETISR_ATM, m);
  601         return;
  602 
  603   drop:
  604         m_freem(m);
  605 }
  606 
  607 /*
  608  * Module loading/unloading
  609  */
  610 static int
  611 harp_modevent(module_t mod, int event, void *data)
  612 {
  613         struct ifnet *ifp;
  614 
  615         switch (event) {
  616 
  617           case MOD_LOAD:
  618                 harp_nif_zone = uma_zcreate("harp nif", sizeof(struct atm_nif),
  619                     NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
  620                 if (harp_nif_zone == NULL)
  621                         panic("%s: nif_zone", __func__);
  622 
  623                 harp_vcc_zone = uma_zcreate("harp vcc", sizeof(struct harp_vcc),
  624                     NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
  625                 if (harp_vcc_zone == NULL)
  626                         panic("%s: vcc_zone", __func__);
  627 
  628                 /* Create harp interfaces for all existing ATM interfaces */
  629                 TAILQ_FOREACH(ifp, &ifnet, if_link)
  630                         harp_attach(ifp);
  631 
  632                 atm_harp_attach_p = harp_attach;
  633                 atm_harp_detach_p = harp_detach;
  634                 atm_harp_input_p = harp_input;
  635                 break;
  636 
  637           case MOD_UNLOAD:
  638                 atm_harp_attach_p = NULL;
  639                 atm_harp_detach_p = NULL;
  640                 atm_harp_input_p = NULL;
  641 
  642                 while (!LIST_EMPTY(&harp_softc_list))
  643                         harp_detach(LIST_FIRST(&harp_softc_list)->parent);
  644 
  645                 uma_zdestroy(harp_nif_zone);
  646                 uma_zdestroy(harp_vcc_zone);
  647 
  648                 break;
  649           default:
  650                 return (EOPNOTSUPP);
  651         }
  652         return (0);
  653 }
  654 
  655 static moduledata_t harp_mod = {
  656         "if_harp",
  657         harp_modevent,
  658         0
  659 };
  660 
  661 DECLARE_MODULE(harp, harp_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);

Cache object: ff17b5cbbb57717625bddd286f6d0a15


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