diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile index 8099c6dc32b1..93af5fee29ed 100644 --- a/share/man/man4/Makefile +++ b/share/man/man4/Makefile @@ -71,6 +71,7 @@ MAN= aac.4 \ gre.4 \ gusc.4 \ gx.4 \ + harp.4 \ hatm.4 \ hifn.4 \ hme.4 \ diff --git a/share/man/man4/harp.4 b/share/man/man4/harp.4 new file mode 100644 index 000000000000..912da8042cb4 --- /dev/null +++ b/share/man/man4/harp.4 @@ -0,0 +1,64 @@ +.\" +.\" Copyright (c) 2003 +.\" Fraunhofer Institute for Open Communication Systems (FhG Fokus). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" Author: Hartmut Brandt +.\" +.\" $FreeBSD$ +.\" +.\" harp(4) man page +.\" +.Dd July 21, 2003 +.Dt HARP 4 +.Os FreeBSD +.Sh NAME +.Nm harp +.Nd Pseudo physical interface driver for HARP +.Sh SYNOPSIS +.Cd options atm +.Cd options NATM +.Cd options ATM_CORE +.Cd device harp +.Sh DESCRIPTION +The +.Nm +driver when loaded attaches to all netgraph ATM interface in the system and for +each of these interfaces presents a physical interface to the HARP stack. +The name of the harp physical interface is the same as the name of the +netgraph interface (they are in different namespaces). +.Sh SEE ALSO +.Xr fatm 4 , +.Xr hatm 4 , +.Xr patm 4 , +.Xr ng_atm 4 , +.Xr atm 8 +.Sh CAVEATS +When +.Xr fatm 4 +is used it must be started before +.Nm +is loaded to get the correct configuration for the HARP physical interface. +.Sh AUTHORS +.An Harti Brandt Aq harti@freebsd.org . diff --git a/sys/conf/NOTES b/sys/conf/NOTES index bb3e2c98dfce..18f5ad011353 100644 --- a/sys/conf/NOTES +++ b/sys/conf/NOTES @@ -645,6 +645,8 @@ options ZERO_COPY_SOCKETS # The `hfa' driver provides support for the FORE Systems, Inc. # PCA-200E ATM PCI Adapter. # +# The `harp' pseudo-driver makes all NATM interface drivers available to HARP. +# options ATM_CORE #core ATM protocol family options ATM_IP #IP over ATM support options ATM_SIGPVC #SIGPVC signalling manager @@ -653,6 +655,7 @@ options ATM_UNI #UNI signalling manager device hea #Efficient ENI-155p ATM PCI device hfa #FORE PCA-200E ATM PCI +device harp #Pseudo-interface for NATM ##################################################################### diff --git a/sys/conf/files b/sys/conf/files index e6fcd16fb6c0..3904610a5729 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -415,6 +415,7 @@ dev/fxp/if_fxp.c optional fxp dev/gem/if_gem.c optional gem dev/gem/if_gem_pci.c optional gem pci dev/gx/if_gx.c optional gx +dev/harp/if_harp.c optional harp pci dev/hatm/if_hatm.c optional hatm pci dev/hatm/if_hatm_intr.c optional hatm pci dev/hatm/if_hatm_ioctl.c optional hatm pci diff --git a/sys/dev/harp/if_harp.c b/sys/dev/harp/if_harp.c new file mode 100644 index 000000000000..d9f2c920579d --- /dev/null +++ b/sys/dev/harp/if_harp.c @@ -0,0 +1,652 @@ +/* + * Copyright (c) 2003 + * Fraunhofer Institute for Open Communication Systems (FhG Fokus). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Author: Harti Brandt + * + * HARP pseudo-driver. This driver when loaded attaches to all ngATM drivers + * in the system and creates a HARP physical interface for each of them. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define HARP_MTU 9188 + +/* + * Physical interface softc + */ +struct harp_softc { + Cmn_unit cmn; + struct ifnet *parent; + LIST_ENTRY(harp_softc) link; +}; + +struct harp_vcc { + struct cmn_vcc cmn; +}; + +MODULE_VERSION(harp, 1); +MODULE_DEPEND(harp, atm, 1, 1, 1); + +/* hooks from if_atmsubr.c */ +extern void (*atm_harp_input_p)(struct ifnet *ifp, struct mbuf **m, + struct atm_pseudohdr *ah, void *rxhand); +extern void (*atm_harp_attach_p)(struct ifnet *); +extern void (*atm_harp_detach_p)(struct ifnet *); + +static MALLOC_DEFINE(M_HARP, "harp", "Harp pseudo interface"); + +static uma_zone_t harp_nif_zone; +static uma_zone_t harp_vcc_zone; + +/* List of all existing 'harp' interfaces */ +static LIST_HEAD(, harp_softc) harp_softc_list = + LIST_HEAD_INITIALIZER(harp_softc_list); + +static struct stack_defn harp_svaal5 = { + NULL, + SAP_CPCS_AAL5, + SDF_TERM, + atm_dev_inst, + atm_dev_lower, + NULL, + 0, +}; + +static struct stack_defn *harp_services = &harp_svaal5; + +/* + * Map between constants + */ +static const struct { + u_int vendor; + u_int api; + u_int dev; +} map_devs[] = { + [ATM_DEVICE_UNKNOWN] = + { VENDOR_UNKNOWN, VENDAPI_UNKNOWN, DEV_UNKNOWN }, + [ATM_DEVICE_PCA200E] = + { VENDOR_FORE, VENDAPI_FORE_1, DEV_FORE_PCA200E }, + [ATM_DEVICE_HE155] = + { VENDOR_FORE, VENDAPI_FORE_2, DEV_FORE_HE155 }, + [ATM_DEVICE_HE622] = + { VENDOR_FORE, VENDAPI_FORE_2, DEV_FORE_HE622 }, + [ATM_DEVICE_ENI155P] = + { VENDOR_ENI, VENDAPI_ENI_1, DEV_ENI_155P }, + [ATM_DEVICE_ADP155P] = + { VENDOR_ENI, VENDAPI_ENI_1, DEV_ENI_155P }, + [ATM_DEVICE_FORELE25] = + { VENDOR_FORE, VENDAPI_IDT_1, DEV_FORE_LE25 }, + [ATM_DEVICE_FORELE155] = + { VENDOR_FORE, VENDAPI_IDT_1, DEV_FORE_LE155 }, + [ATM_DEVICE_NICSTAR25] = + { VENDOR_IDT, VENDAPI_IDT_1, DEV_IDT_25 }, + [ATM_DEVICE_NICSTAR155] = + { VENDOR_IDT, VENDAPI_IDT_1, DEV_IDT_155 }, + [ATM_DEVICE_IDTABR25] = + { VENDOR_IDT, VENDAPI_IDT_2, DEV_IDTABR_25 }, + [ATM_DEVICE_IDTABR155] = + { VENDOR_IDT, VENDAPI_IDT_2, DEV_IDTABR_155 }, + [ATM_DEVICE_PROATM25] = + { VENDOR_PROSUM, VENDAPI_IDT_2, DEV_PROATM_25 }, + [ATM_DEVICE_PROATM155] = + { VENDOR_PROSUM, VENDAPI_IDT_2, DEV_PROATM_155 }, +}; + +/* + * Return zero if this interface is ok for us. + * XXX This should go away when we have full ngATM-ified the en driver. + */ +static int +harp_check_if(const struct ifnet *ifp) +{ + if (ifp->if_type == IFT_ATM && strcmp(ifp->if_name, "en")) + return (0); + else + return (-1); +} + +/* + * Instantiate a VCC stack. + * + * Could check for correct attributes here. + */ +static int +harp_instvcc(Cmn_unit *up, Cmn_vcc *vp) +{ + struct harp_softc *sc; + + if (up == NULL || vp == NULL || vp->cv_connvc == NULL) + return (EINVAL); + + sc = (struct harp_softc *)up; + + return (0); +} + +/* + * Open a VCC. + */ +static int +harp_openvcc(Cmn_unit *up, Cmn_vcc *vp) +{ + struct harp_softc *sc; + struct atmio_openvcc data; + Atm_attributes *attrib; + struct vccb *vccinf; + const struct ifatm_mib *mib; + int err; + + if (up == NULL || vp == NULL || vp->cv_connvc == NULL) + return (EINVAL); + + sc = (struct harp_softc *)up; + mib = sc->parent->if_linkmib; + + attrib = &vp->cv_connvc->cvc_attr; + vccinf = vp->cv_connvc->cvc_vcc; + + if (attrib == NULL || vccinf == NULL) + return (EINVAL); + + if (vccinf->vc_vpi >= (1 << mib->vpi_bits) || + vccinf->vc_vci >= (1 << mib->vci_bits)) + return (EINVAL); + + memset(&data, 0, sizeof(data)); + + switch (attrib->aal.type) { + + case ATM_AAL0: + data.param.aal = ATMIO_AAL_0; + break; + + case ATM_AAL5: + data.param.aal = ATMIO_AAL_5; + break; + + default: + return (EINVAL); + } + data.param.vpi = vccinf->vc_vpi; + data.param.vci = vccinf->vc_vci; + data.param.rmtu = HARP_MTU; + data.param.tmtu = HARP_MTU; + + switch (attrib->bearer.v.bearer_class) { + + case T_ATM_CLASS_C: + data.param.traffic = ATMIO_TRAFFIC_VBR; + break; + + case T_ATM_CLASS_X: + switch (attrib->bearer.v.traffic_type) { + + case T_ATM_CBR: + data.param.traffic = ATMIO_TRAFFIC_CBR; + break; + + case T_ATM_VBR: + data.param.traffic = ATMIO_TRAFFIC_VBR; + break; + + case T_ATM_ABR: + /* not really supported by HARP */ + return (EINVAL); + + default: + case T_ATM_UBR: + data.param.traffic = ATMIO_TRAFFIC_UBR; + break; + } + break; + + default: + return (EINVAL); + } + data.param.tparam.pcr = attrib->traffic.v.forward.PCR_all_traffic; + data.param.tparam.scr = attrib->traffic.v.forward.SCR_all_traffic; + data.param.tparam.mbs = attrib->traffic.v.forward.MBS_all_traffic; + + data.rxhand = sc; + data.param.flags = ATMIO_FLAG_HARP; + + err = (*sc->parent->if_ioctl)(sc->parent, SIOCATMOPENVCC, + (caddr_t)&data); + + return (err); +} + +/* + * Close VCC + */ +static int +harp_closevcc(Cmn_unit *up, Cmn_vcc *vp) +{ + struct harp_softc *sc; + struct atmio_closevcc data; + int err; + + if (vp == NULL || vp->cv_connvc == NULL || + vp->cv_connvc->cvc_vcc == NULL) + return (EINVAL); + + sc = (struct harp_softc *)up; + + data.vpi = vp->cv_connvc->cvc_vcc->vc_vpi; + data.vci = vp->cv_connvc->cvc_vcc->vc_vci; + + err = (*sc->parent->if_ioctl)(sc->parent, SIOCATMCLOSEVCC, + (caddr_t)&data); + + return (err); +} + +/* + * IOCTLs + */ +static int +harp_ioctl(int code, caddr_t addr, caddr_t arg) +{ + return (ENOSYS); +} + +/* + * Output data + */ +static void +harp_output(Cmn_unit *cu, Cmn_vcc *cv, KBuffer *m) +{ + struct harp_softc *sc = (struct harp_softc *)cu; + struct atm_pseudohdr *aph; + int error; + int mlen; + + if (cv == NULL || cv->cv_connvc == NULL || + cv->cv_connvc->cvc_vcc == NULL) { + m_freem(m); + return; + } + M_ASSERTPKTHDR(m); + + /* + * Harp seems very broken with regard to mbuf handling. The length + * in the packet header is mostly broken here so recompute it. + */ + m->m_pkthdr.len = mlen = m_length(m, NULL); + + /* + * Prepend pseudo-hdr. Drivers don't care about the flags. + */ + M_PREPEND(m, sizeof(*aph), M_DONTWAIT); + if (m == NULL) + return; + + aph = mtod(m, struct atm_pseudohdr *); + ATM_PH_VPI(aph) = cv->cv_connvc->cvc_vcc->vc_vpi; + ATM_PH_SETVCI(aph, cv->cv_connvc->cvc_vcc->vc_vci); + ATM_PH_FLAGS(aph) = 0; + + error = atm_output(sc->parent, m, NULL, NULL); + + if (error) { + printf("%s: error %d\n", __func__, error); + sc->cmn.cu_pif.pif_oerrors++; + cv->cv_connvc->cvc_vcc->vc_oerrors++; + if (cv->cv_connvc->cvc_vcc->vc_nif) + cv->cv_connvc->cvc_vcc->vc_nif->nif_if.if_oerrors++; + return; + } + + /* statistics */ + sc->cmn.cu_pif.pif_opdus++; + sc->cmn.cu_pif.pif_obytes += mlen; + cv->cv_connvc->cvc_vcc->vc_opdus++; + cv->cv_connvc->cvc_vcc->vc_obytes += mlen; + if (cv->cv_connvc->cvc_vcc->vc_nif) { + cv->cv_connvc->cvc_vcc->vc_nif->nif_obytes += mlen; + cv->cv_connvc->cvc_vcc->vc_nif->nif_if.if_obytes += mlen; + cv->cv_connvc->cvc_vcc->vc_nif->nif_if.if_opackets++; + } +} + +/* + * Attach a new interface + */ +static void +harp_attach(struct ifnet *parent) +{ + struct harp_softc *sc; + const struct ifatm_mib *mib; + int error; + + if (harp_check_if(parent) != 0) + return; + + sc = malloc(sizeof(*sc), M_HARP, M_WAITOK | M_ZERO); + + sc->parent = parent; + sc->cmn.cu_unit = parent->if_unit; + sc->cmn.cu_mtu = HARP_MTU; + sc->cmn.cu_ioctl = harp_ioctl; + sc->cmn.cu_instvcc = harp_instvcc; + sc->cmn.cu_openvcc = harp_openvcc; + sc->cmn.cu_closevcc = harp_closevcc; + sc->cmn.cu_output = harp_output; + sc->cmn.cu_vcc_zone = harp_vcc_zone; + sc->cmn.cu_nif_zone = harp_nif_zone; + sc->cmn.cu_softc = sc; + + /* config */ + mib = parent->if_linkmib; + if (mib->device >= sizeof(map_devs) / sizeof(map_devs[0])) { + sc->cmn.cu_config.ac_vendor = VENDOR_UNKNOWN; + sc->cmn.cu_config.ac_vendapi = VENDAPI_UNKNOWN; + sc->cmn.cu_config.ac_device = DEV_UNKNOWN; + } else { + sc->cmn.cu_config.ac_vendor = map_devs[mib->device].vendor; + sc->cmn.cu_config.ac_vendapi = map_devs[mib->device].api; + sc->cmn.cu_config.ac_device = map_devs[mib->device].dev; + } + + switch (mib->media) { + + case IFM_ATM_UTP_25: + sc->cmn.cu_config.ac_media = MEDIA_UTP25;; + break; + + case IFM_ATM_TAXI_100: + sc->cmn.cu_config.ac_media = MEDIA_TAXI_100; + break; + + case IFM_ATM_TAXI_140: + sc->cmn.cu_config.ac_media = MEDIA_TAXI_140; + break; + + case IFM_ATM_MM_155: + case IFM_ATM_SM_155: + sc->cmn.cu_config.ac_media = MEDIA_OC3C; + break; + + case IFM_ATM_MM_622: + case IFM_ATM_SM_622: + sc->cmn.cu_config.ac_media = MEDIA_OC12C; + break; + + case IFM_ATM_UTP_155: + sc->cmn.cu_config.ac_media = MEDIA_UTP155; + break; + + default: + sc->cmn.cu_config.ac_media = MEDIA_UNKNOWN; + break; + } + sc->cmn.cu_config.ac_bustype = BUS_PCI; + sc->cmn.cu_pif.pif_pcr = mib->pcr; + sc->cmn.cu_pif.pif_maxvpi = (1 << mib->vpi_bits) - 1; + sc->cmn.cu_pif.pif_maxvci = (1 << mib->vci_bits) - 1; + + snprintf(sc->cmn.cu_config.ac_hard_vers, + sizeof(sc->cmn.cu_config.ac_hard_vers), "0x%lx", + (u_long)mib->hw_version); + snprintf(sc->cmn.cu_config.ac_firm_vers, + sizeof(sc->cmn.cu_config.ac_firm_vers), "0x%lx", + (u_long)mib->sw_version); + sc->cmn.cu_config.ac_serial = mib->serial; + sc->cmn.cu_config.ac_ram = 0; + sc->cmn.cu_config.ac_ramsize = 0; + + sc->cmn.cu_config.ac_macaddr.ma_data[0] = + sc->cmn.cu_pif.pif_macaddr.ma_data[0] = mib->esi[0]; + sc->cmn.cu_config.ac_macaddr.ma_data[1] = + sc->cmn.cu_pif.pif_macaddr.ma_data[1] = mib->esi[1]; + sc->cmn.cu_config.ac_macaddr.ma_data[2] = + sc->cmn.cu_pif.pif_macaddr.ma_data[2] = mib->esi[2]; + sc->cmn.cu_config.ac_macaddr.ma_data[3] = + sc->cmn.cu_pif.pif_macaddr.ma_data[3] = mib->esi[3]; + sc->cmn.cu_config.ac_macaddr.ma_data[4] = + sc->cmn.cu_pif.pif_macaddr.ma_data[4] = mib->esi[4]; + sc->cmn.cu_config.ac_macaddr.ma_data[5] = + sc->cmn.cu_pif.pif_macaddr.ma_data[5] = mib->esi[5]; + + error = atm_physif_register(&sc->cmn, parent->if_name, harp_services); + if (error) { + log(LOG_ERR, "%s: pif registration failed %d\n", + parent->if_name, error); + free(sc, M_HARP); + return; + } + LIST_INSERT_HEAD(&harp_softc_list, sc, link); + + sc->cmn.cu_flags |= CUF_INITED; +} + +/* + * Destroy a cloned device + */ +static void +harp_detach(struct ifnet *ifp) +{ + struct harp_softc *sc; + int error; + + LIST_FOREACH(sc, &harp_softc_list, link) + if (sc->parent == ifp) + break; + if (sc == NULL) + return; + + error = atm_physif_deregister(&sc->cmn); + if (error) + log(LOG_ERR, "%s: de-registration failed %d\n", ifp->if_name, + error); + + LIST_REMOVE(sc, link); + + free(sc, M_HARP); +} + +/* + * Pass PDU up the stack + */ +static void +harp_recv_stack(void *tok, KBuffer *m) +{ + Cmn_vcc *vcc = tok; + int err; + + M_ASSERTPKTHDR(m); + STACK_CALL(CPCS_UNITDATA_SIG, vcc->cv_upper, vcc->cv_toku, + vcc->cv_connvc, (intptr_t)m, 0, err); + if (err) { + printf("%s: error %d\n", __func__, err); + KB_FREEALL(m); + } +} + +/* + * Possible input from NATM + */ +static void +harp_input(struct ifnet *ifp, struct mbuf **mp, struct atm_pseudohdr *ah, + void *rxhand) +{ + struct harp_softc *sc = rxhand; + Cmn_vcc *vcc; + char *cp; + u_int pfxlen; + struct mbuf *m, *m0; + int mlen; + + if ((ATM_PH_FLAGS(ah) & ATMIO_FLAG_HARP) == 0) + return; + + /* grab the packet */ + m = *mp; + *mp = NULL; + + if (sc->parent != ifp) { + printf("%s: parent=%p ifp=%p\n", __func__, sc->parent, ifp); + goto drop; + } + + vcc = atm_dev_vcc_find(&sc->cmn, ATM_PH_VPI(ah), + ATM_PH_VCI(ah), VCC_IN); + if (vcc == NULL) { + printf("%s: VCC %u/%u not found\n", __func__,ATM_PH_VPI(ah), + ATM_PH_VCI(ah)); + goto drop; + } + + /* fit two pointers into the mbuf - assume, that the the data is + * pointer aligned. If it doesn't fit into the first mbuf, prepend + * another one, but leave the packet header where it is. atm_intr + * relies on this. */ + mlen = m->m_pkthdr.len; + pfxlen = sizeof(atm_intr_func_t) + sizeof(void *); + if (M_LEADINGSPACE(m) < pfxlen) { + MGET(m0, 0, MT_DATA); + if (m0 == NULL) { + printf("%s: no leading space in buffer\n", __func__); + goto drop; + } + m0->m_len = 0; + m0->m_next = m; + m = m0; + } + m->m_len += pfxlen; + m->m_data -= pfxlen; + KB_DATASTART(m, cp, char *); + *((atm_intr_func_t *)cp) = harp_recv_stack; + cp += sizeof(atm_intr_func_t); + *((void **)cp) = (void *)vcc; + + /* count the packet */ + sc->cmn.cu_pif.pif_ipdus++; + sc->cmn.cu_pif.pif_ibytes += mlen; + vcc->cv_connvc->cvc_vcc->vc_ipdus++; + vcc->cv_connvc->cvc_vcc->vc_ibytes += mlen; + if (vcc->cv_connvc->cvc_vcc->vc_nif) { + vcc->cv_connvc->cvc_vcc->vc_nif->nif_ibytes += mlen; + vcc->cv_connvc->cvc_vcc->vc_nif->nif_if.if_ipackets++; + vcc->cv_connvc->cvc_vcc->vc_nif->nif_if.if_ibytes += mlen; + } + + /* hand it off */ + netisr_dispatch(NETISR_ATM, m); + return; + + drop: + m_freem(m); +} + +/* + * Module loading/unloading + */ +static int +harp_modevent(module_t mod, int event, void *data) +{ + struct ifnet *ifp; + + switch (event) { + + case MOD_LOAD: + harp_nif_zone = uma_zcreate("harp nif", sizeof(struct atm_nif), + NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0); + if (harp_nif_zone == NULL) + panic("%s: nif_zone", __func__); + + harp_vcc_zone = uma_zcreate("harp vcc", sizeof(struct harp_vcc), + NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0); + if (harp_vcc_zone == NULL) + panic("%s: vcc_zone", __func__); + + /* Create harp interfaces for all existing ATM interfaces */ + TAILQ_FOREACH(ifp, &ifnet, if_link) + harp_attach(ifp); + + atm_harp_attach_p = harp_attach; + atm_harp_detach_p = harp_detach; + atm_harp_input_p = harp_input; + break; + + case MOD_UNLOAD: + atm_harp_attach_p = NULL; + atm_harp_detach_p = NULL; + atm_harp_input_p = NULL; + + while (!LIST_EMPTY(&harp_softc_list)) + harp_detach(LIST_FIRST(&harp_softc_list)->parent); + + uma_zdestroy(harp_nif_zone); + uma_zdestroy(harp_vcc_zone); + + break; + } + return (0); +} + +static moduledata_t harp_mod = { + "if_harp", + harp_modevent, + 0 +}; + +DECLARE_MODULE(harp, harp_mod, SI_SUB_PSEUDO, SI_ORDER_ANY); diff --git a/sys/modules/Makefile b/sys/modules/Makefile index 3828eeb95d48..6a42ef768c6c 100644 --- a/sys/modules/Makefile +++ b/sys/modules/Makefile @@ -40,6 +40,7 @@ SUBDIR= accf_data \ fxp \ geom \ gx \ + harp \ hatm \ hifn \ if_disc \ diff --git a/sys/modules/harp/Makefile b/sys/modules/harp/Makefile new file mode 100644 index 000000000000..b60cac98de33 --- /dev/null +++ b/sys/modules/harp/Makefile @@ -0,0 +1,14 @@ +# $FreeBSD$ +# +# Author: Harti Brandt +# +.PATH: ${.CURDIR}/../../dev/harp + +KMOD= if_harp +SRCS= if_harp.c device_if.h + +CFLAGS+= -I${.CURDIR} -I${.CURDIR}/../include +CFLAGS+= -DDEBUG -DINVARIANTS -g +LDFLAGS+= -g + +.include