summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--share/man/man4/Makefile1
-rw-r--r--share/man/man4/harp.464
-rw-r--r--sys/conf/NOTES3
-rw-r--r--sys/conf/files1
-rw-r--r--sys/dev/harp/if_harp.c652
-rw-r--r--sys/modules/Makefile1
-rw-r--r--sys/modules/harp/Makefile14
7 files changed, 736 insertions, 0 deletions
diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile
index 8099c6d..93af5fe 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 0000000..912da80
--- /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 <harti@freebsd.org>
+.\"
+.\" $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 bb3e2c9..18f5ad0 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 e6fcd16..3904610 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 0000000..d9f2c92
--- /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 <harti@freebsd.org>
+ *
+ * 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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/kernel.h>
+#include <sys/conf.h>
+#include <sys/module.h>
+#include <sys/queue.h>
+#include <sys/syslog.h>
+
+#include <sys/sockio.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+
+#include <net/if.h>
+#include <net/if_var.h>
+#include <net/if_types.h>
+#include <net/if_media.h>
+#include <net/netisr.h>
+
+#include <netatm/port.h>
+#include <netatm/queue.h>
+#include <netatm/atm.h>
+#include <netatm/atm_sys.h>
+#include <netatm/atm_sap.h>
+#include <netatm/atm_cm.h>
+#include <netatm/atm_if.h>
+#include <netatm/atm_stack.h>
+#include <netatm/atm_pcb.h>
+#include <netatm/atm_var.h>
+#include <netatm/atm_vc.h>
+
+#include <net/if_atm.h>
+
+#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 3828eeb..6a42ef7 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 0000000..b60cac9
--- /dev/null
+++ b/sys/modules/harp/Makefile
@@ -0,0 +1,14 @@
+# $FreeBSD$
+#
+# Author: Harti Brandt <brandt@fokus.gmd.de>
+#
+.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 <bsd.kmod.mk>
OpenPOWER on IntegriCloud