mirror of
https://github.com/opnsense/src.git
synced 2026-05-28 04:12:45 -04:00
Add ng_atmpif: a HARP physical interface emulation. This allows one
to run the HARP ATM stack without real hardware. Submitted by: Vincent Jardin <vjardin@wanadoo.fr>
This commit is contained in:
parent
a57b72b4b9
commit
ee4080d424
11 changed files with 2131 additions and 2 deletions
|
|
@ -135,6 +135,7 @@ MAN= aac.4 \
|
|||
netgraph.4 \
|
||||
netintro.4 \
|
||||
ng_atm.4 \
|
||||
ng_atmpif.4 \
|
||||
ng_UI.4 \
|
||||
ng_async.4 \
|
||||
ng_bluetooth.4 \
|
||||
|
|
|
|||
150
share/man/man4/ng_atmpif.4
Normal file
150
share/man/man4/ng_atmpif.4
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
.\"
|
||||
.\" Copyright (c) 2001-2003
|
||||
.\" Harti Brandt.
|
||||
.\" Vincent Jardin.
|
||||
.\" 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>
|
||||
.\" Author: Vincent Jardin <vjardin@free.fr>
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.\" ng_atmpif(4) man page
|
||||
.\"
|
||||
.Dd August 7, 2003
|
||||
.Dt ng_atmpif 4
|
||||
.Os FreeBSD
|
||||
.Sh NAME
|
||||
.Nm ng_atmpif
|
||||
.Nd netgraph HARP/ATM Virtual Physical Interface
|
||||
.Sh SYNOPSIS
|
||||
.Fd #include <netgraph/netgraph.h>
|
||||
.Fd #include <netgraph/atm/ng_atmpif.h>
|
||||
.Sh DESCIPTION
|
||||
The
|
||||
.Nm
|
||||
netgraph node type allows the emulation of
|
||||
.Xr atm 8
|
||||
(netatm/HARP) Physical devices (PIF) to be connected to the
|
||||
.Xr netgraph 4
|
||||
networking subsystem.
|
||||
Moreover it includes protection of the PDU against duplication and
|
||||
desequencement.
|
||||
It supports up to 65535 VCs and up to 255 VPs. AAL0, AAL3/4 and AAL5
|
||||
emulation are provided.
|
||||
In order to optimize CPU, this node does not emulate the SAR layer.
|
||||
.Pp
|
||||
The purpose of this node is to help in debugging and testing the HARP
|
||||
stack when one does not have an ATM board or when the available boards do not
|
||||
have enough features.
|
||||
.Pp
|
||||
When a node
|
||||
.Nm
|
||||
is created, a PIF is created automatically.
|
||||
It is named hvaX.
|
||||
It has the same features as any other HARP devices.
|
||||
The PIF is removed when the node is removed.
|
||||
.Sh HOOKS
|
||||
There is only one hook: link. This hook can be connected to any other
|
||||
Netgraph node. For example, in order
|
||||
to test the HARP stack over UDP, it can be connected on a
|
||||
.Xr ksocket 4
|
||||
node.
|
||||
.Sh CONTROL MESSAGES
|
||||
This node type supports the generic messages plus the following:
|
||||
.Bl -tag -width xxx
|
||||
.It Dv NGM_ATMPIF_SET_CONFIG Ta setconfig
|
||||
Configures the debugging features of the node and a virtual
|
||||
Peak Cell Rate (PCR).
|
||||
It uses the same structure as NGM_ATMPIF_GET_CONFIG.
|
||||
.It Dv NGM_ATMPIF_GET_CONFIG Ta getconfig
|
||||
Returns a structure defining the configuration of the interface:
|
||||
.Bd -literal
|
||||
struct ng_vatmpif_config {
|
||||
uint8_t debug; /* debug bit field (see below) */
|
||||
uint32_t pcr; /* peak cell rate */
|
||||
Mac_addr macaddr; /* Mac Address */
|
||||
};
|
||||
.Ed
|
||||
Note that the following debugging flags can be used:
|
||||
.Bl -column ATM_PH_LLCSNAP -offset indent
|
||||
.It Dv VATMPIF_DEBUG_NONE Ta disable debugging
|
||||
.It Dv VATMPIF_DEBUG_PACKET Ta enable debugging
|
||||
.El
|
||||
.Pp
|
||||
.It Dv NGM_ATMPIF_GET_LINK_STATUS Ta getlinkstatus
|
||||
Returns the last received sequence number, the last sent sequence
|
||||
number and the current total PCR that is reserved among all the VCCs
|
||||
of the interface.
|
||||
.Bd -literal
|
||||
struct ng_atmpif_link_status {
|
||||
uint32_t InSeq; /* last received sequence number + 1 */
|
||||
uint32_t OutSeq; /* last sent sequence number */
|
||||
uint32_t cur_pcr; /* slot's reserved PCR */
|
||||
};
|
||||
.Ed
|
||||
.Pp
|
||||
.It Dv NGM_ATMPIF_GET_STATS Ta getstats
|
||||
.It Dv NGM_ATMPIF_CLR_STATS Ta clrstats
|
||||
.It Dv NGM_ATMPIF_GETCLR_STATS Ta getclrstats
|
||||
It returns the node's statistics, it clears them or it returns and reset
|
||||
their values to 0.
|
||||
The following stats are provided.
|
||||
.Bd -literal
|
||||
struct hva_stats_ng {
|
||||
uint32_t ng_errseq; /* Duplicate or out of order */
|
||||
uint32_t ng_lostpdu; /* PDU lost detected */
|
||||
uint32_t ng_badpdu; /* Unknown PDU type */
|
||||
uint32_t ng_rx_novcc; /* Draining PDU on closed VCC */
|
||||
uint32_t ng_rx_iqfull; /* PDU drops no room in atm_intrq */
|
||||
uint32_t ng_tx_rawcell; /* PDU raw cells transmitted */
|
||||
uint32_t ng_rx_rawcell; /* PDU raw cells received */
|
||||
uint64_t ng_tx_pdu; /* PDU transmitted */
|
||||
uint64_t ng_rx_pdu; /* PDU received */
|
||||
};
|
||||
struct hva_stats_atm {
|
||||
uint64_t atm_xmit; /* Cells transmitted */
|
||||
uint64_t atm_rcvd; /* Cells received */
|
||||
};
|
||||
struct hva_stats_aal5 {
|
||||
uint64_t aal5_xmit; /* Cells transmitted */
|
||||
uint64_t aal5_rcvd; /* Cells received */
|
||||
uint32_t aal5_crc_len; /* Cells with CRC/length errors */
|
||||
uint32_t aal5_drops; /* Cell drops */
|
||||
uint64_t aal5_pdu_xmit; /* CS PDUs transmitted */
|
||||
uint64_t aal5_pdu_rcvd; /* CS PDUs received */
|
||||
uint32_t aal5_pdu_crc; /* CS PDUs with CRC errors */
|
||||
uint32_t aal5_pdu_errs; /* CS layer protocol errors */
|
||||
uint32_t aal5_pdu_drops; /* CS PDUs dropped */
|
||||
};
|
||||
.Ed
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr netgraph 4 ,
|
||||
.Xr ng_ksocket 4 ,
|
||||
.Xr natm 4 ,
|
||||
.Xr ngctl 8
|
||||
.Sh AUTHORS
|
||||
.An Harti Brandt Aq harti@freebsd.org
|
||||
.An Vincent Jardin Aq vjardin@wanadoo.fr
|
||||
|
|
@ -442,6 +442,7 @@ options NETGRAPH_TEE
|
|||
options NETGRAPH_TTY
|
||||
options NETGRAPH_UI
|
||||
options NETGRAPH_VJC
|
||||
options NETGRAPH_ATM_ATMPIF
|
||||
|
||||
# NgATM - Netgraph ATM
|
||||
options NGATM_ATM
|
||||
|
|
|
|||
|
|
@ -1338,6 +1338,8 @@ netatm/uni/unisig_sigmgr_state.c optional atm_uni atm_core
|
|||
netatm/uni/unisig_subr.c optional atm_uni atm_core
|
||||
netatm/uni/unisig_util.c optional atm_uni atm_core
|
||||
netatm/uni/unisig_vc_state.c optional atm_uni atm_core
|
||||
netgraph/atm/atmpif/ng_atmpif.c optional netgraph_atm_atmpif
|
||||
netgraph/atm/atmpif/ng_atmpif_harp.c optional netgraph_atm_atmpif
|
||||
netgraph/atm/ng_atm.c optional ngatm_atm
|
||||
netgraph/ng_UI.c optional netgraph_UI
|
||||
netgraph/ng_async.c optional netgraph_async
|
||||
|
|
|
|||
|
|
@ -396,6 +396,7 @@ NETGRAPH_TEE opt_netgraph.h
|
|||
NETGRAPH_TTY opt_netgraph.h
|
||||
NETGRAPH_UI opt_netgraph.h
|
||||
NETGRAPH_VJC opt_netgraph.h
|
||||
NETGRAPH_ATM_ATMPIF opt_netgraph.h
|
||||
|
||||
# NgATM options
|
||||
NGATM_ATM opt_netgraph.h
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
# $FreeBSD$
|
||||
|
||||
SUBDIR= \
|
||||
atm
|
||||
SUBDIR= \
|
||||
atm \
|
||||
atmpif
|
||||
|
||||
.include <bsd.subdir.mk>
|
||||
|
||||
|
|
|
|||
10
sys/modules/netgraph/atm/atmpif/Makefile
Normal file
10
sys/modules/netgraph/atm/atmpif/Makefile
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
# $FreeBSD$
|
||||
#
|
||||
# Author: Harti Brandt <harti@freebsd.org>
|
||||
#
|
||||
.PATH: ${.CURDIR}/../../../../netgraph/atm/atmpif
|
||||
|
||||
KMOD= ng_atmpif
|
||||
SRCS= ng_atmpif.c ng_atmpif_harp.c
|
||||
|
||||
.include <bsd.kmod.mk>
|
||||
708
sys/netgraph/atm/atmpif/ng_atmpif.c
Normal file
708
sys/netgraph/atm/atmpif/ng_atmpif.c
Normal file
|
|
@ -0,0 +1,708 @@
|
|||
/*
|
||||
* Copyright 2003 Harti Brandt
|
||||
* Copyright 2003 Vincent Jardin
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* ATM Virtal Adapter Support
|
||||
* --------------------------
|
||||
*
|
||||
* Loadable kernel module and netgraph support
|
||||
*
|
||||
*/
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/socketvar.h>
|
||||
#include <sys/syslog.h>
|
||||
|
||||
#include <vm/uma.h>
|
||||
|
||||
#include <net/if.h>
|
||||
|
||||
#include <netatm/port.h>
|
||||
#include <netatm/queue.h>
|
||||
#include <netatm/atm.h>
|
||||
#include <netatm/atm_sys.h>
|
||||
#include <netatm/atm_cm.h>
|
||||
#include <netatm/atm_if.h>
|
||||
#include <netatm/atm_sap.h>
|
||||
#include <netatm/atm_pcb.h>
|
||||
#include <netatm/atm_stack.h>
|
||||
#include <netatm/atm_var.h>
|
||||
|
||||
#include <netgraph/ng_message.h>
|
||||
#include <netgraph/netgraph.h>
|
||||
#include <netgraph/ng_parse.h>
|
||||
#include <netgraph/atm/ng_atmpif.h>
|
||||
#include <netgraph/atm/atmpif/ng_atmpif_var.h>
|
||||
|
||||
#ifdef NG_SEPARATE_MALLOC
|
||||
MALLOC_DEFINE(M_NETGRAPH_ATMPIF, "netgraph_vatmpif",
|
||||
"netgraph HARP virtual Physical Interface");
|
||||
#else
|
||||
#define M_NETGRAPH_ATMPIF M_NETGRAPH
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Local definitions
|
||||
*/
|
||||
|
||||
/*
|
||||
* Protocol header
|
||||
*/
|
||||
struct vatmpif_header {
|
||||
/* The cell header (minus the HEC) is contained in the least-significant
|
||||
* 32-bits of a word.
|
||||
*/
|
||||
uint32_t cellhdr; /* Stored in network order */
|
||||
/* Let's use cellhdr = htonl(ATM_HDR_SET(vpi, vci, pt, clp))
|
||||
* and vpi = ATM_HDR_GET_VPI(ntohl(cellhdr))
|
||||
* vci = ATM_HDR_GET_VCI(ntohl(cellhdr))
|
||||
* pt = ATM_HDR_GET_PT (ntohl(cellhdr))
|
||||
* clp = ATM_HDR_GET_CLP(ntohl(cellhdr))
|
||||
*/
|
||||
int32_t seq; /* sequence number in network byte order */
|
||||
uint64_t cookie; /* optional field */
|
||||
uint8_t aal; /* AAL */
|
||||
uint8_t __pad[3];
|
||||
};
|
||||
|
||||
/*
|
||||
* Local functions
|
||||
*/
|
||||
|
||||
/* Parse type for a MAC address */
|
||||
static ng_parse_t ng_macaddr_parse;
|
||||
static ng_unparse_t ng_macaddr_unparse;
|
||||
const struct ng_parse_type ng_mac_addr_type = {
|
||||
parse: ng_macaddr_parse,
|
||||
unparse: ng_macaddr_unparse,
|
||||
};
|
||||
|
||||
|
||||
/* Parse type for struct ng_atmpif_config */
|
||||
static const struct ng_parse_struct_field
|
||||
ng_atmpif_config_type_fields[] = NG_ATMPIF_CONFIG_TYPE_INFO;
|
||||
static const struct ng_parse_type ng_atmpif_config_type = {
|
||||
&ng_parse_struct_type,
|
||||
&ng_atmpif_config_type_fields,
|
||||
};
|
||||
|
||||
/* Parse type for struct ng_atmpif_link_status */
|
||||
static const struct ng_parse_struct_field
|
||||
ng_atmpif_link_status_type_fields[] = NG_ATMPIF_LINK_STATUS_TYPE_INFO;
|
||||
static const struct ng_parse_type ng_atmpif_link_status_type = {
|
||||
&ng_parse_struct_type,
|
||||
&ng_atmpif_link_status_type_fields,
|
||||
};
|
||||
|
||||
/* Parse type for struct ng_atmpif_stats */
|
||||
static const struct ng_parse_struct_field
|
||||
ng_atmpif_stats_type_fields[] = NG_ATMPIF_STATS_TYPE_INFO;
|
||||
static const struct ng_parse_type ng_atmpif_stats_type = {
|
||||
&ng_parse_struct_type,
|
||||
&ng_atmpif_stats_type_fields,
|
||||
};
|
||||
|
||||
static const struct ng_cmdlist ng_atmpif_cmdlist[] = {
|
||||
{
|
||||
NGM_ATMPIF_COOKIE,
|
||||
NGM_ATMPIF_SET_CONFIG,
|
||||
"setconfig",
|
||||
mesgType: &ng_atmpif_config_type,
|
||||
respType: NULL
|
||||
},
|
||||
{
|
||||
NGM_ATMPIF_COOKIE,
|
||||
NGM_ATMPIF_GET_CONFIG,
|
||||
"getconfig",
|
||||
mesgType: NULL,
|
||||
respType: &ng_atmpif_config_type
|
||||
},
|
||||
{
|
||||
NGM_ATMPIF_COOKIE,
|
||||
NGM_ATMPIF_GET_LINK_STATUS,
|
||||
"getlinkstatus",
|
||||
mesgType: NULL,
|
||||
respType: &ng_atmpif_link_status_type
|
||||
},
|
||||
{
|
||||
NGM_ATMPIF_COOKIE,
|
||||
NGM_ATMPIF_GET_STATS,
|
||||
"getstats",
|
||||
mesgType: NULL,
|
||||
respType: &ng_atmpif_stats_type
|
||||
},
|
||||
{
|
||||
NGM_ATMPIF_COOKIE,
|
||||
NGM_ATMPIF_CLR_STATS,
|
||||
"clrstats",
|
||||
mesgType: NULL,
|
||||
respType: NULL
|
||||
},
|
||||
{
|
||||
NGM_ATMPIF_COOKIE,
|
||||
NGM_ATMPIF_GETCLR_STATS,
|
||||
"getclrstats",
|
||||
mesgType: NULL,
|
||||
respType: &ng_atmpif_stats_type
|
||||
},
|
||||
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
uma_zone_t vatmpif_nif_zone;
|
||||
uma_zone_t vatmpif_vcc_zone;
|
||||
|
||||
/*
|
||||
* Netgraph node methods
|
||||
*/
|
||||
static ng_constructor_t ng_atmpif_constructor;
|
||||
static ng_rcvmsg_t ng_atmpif_rcvmsg;
|
||||
static ng_shutdown_t ng_atmpif_rmnode;
|
||||
static ng_newhook_t ng_atmpif_newhook;
|
||||
static ng_rcvdata_t ng_atmpif_rcvdata;
|
||||
static ng_disconnect_t ng_atmpif_disconnect;
|
||||
static int ng_atmpif_mod_event(module_t, int, void *);
|
||||
|
||||
/*
|
||||
* Node type descriptor
|
||||
*/
|
||||
static struct ng_type ng_atmpif_typestruct = {
|
||||
NG_ABI_VERSION, /* version */
|
||||
NG_ATMPIF_NODE_TYPE, /* name */
|
||||
ng_atmpif_mod_event, /* mod_event */
|
||||
ng_atmpif_constructor, /* constructor */
|
||||
ng_atmpif_rcvmsg, /* rcvmsg */
|
||||
ng_atmpif_rmnode, /* shutdown */
|
||||
ng_atmpif_newhook, /* newhook */
|
||||
NULL, /* findhook */
|
||||
NULL, /* connect */
|
||||
ng_atmpif_rcvdata, /* rcvdata */
|
||||
ng_atmpif_disconnect, /* disconnect */
|
||||
ng_atmpif_cmdlist, /* cmdlist */
|
||||
};
|
||||
NETGRAPH_INIT(atmpif, &ng_atmpif_typestruct);
|
||||
|
||||
/******************************************************************
|
||||
NETGRAPH NODE METHODS
|
||||
******************************************************************/
|
||||
|
||||
/*
|
||||
* Node constructor
|
||||
*
|
||||
* Called at splnet()
|
||||
*/
|
||||
static int
|
||||
ng_atmpif_constructor(node_p nodep)
|
||||
{
|
||||
priv_p priv;
|
||||
|
||||
/*
|
||||
* Allocate and initialize private info
|
||||
*/
|
||||
priv = malloc(sizeof(*priv), M_NETGRAPH_ATMPIF, M_NOWAIT | M_ZERO);
|
||||
if (priv == NULL)
|
||||
return (ENOMEM);
|
||||
|
||||
priv->conf.debug = 0x00;
|
||||
priv->conf.pcr = ATM_PCR_OC3C;
|
||||
priv->conf.macaddr.ma_data[0] = 0x02; /* XXX : non unique bit */
|
||||
priv->conf.macaddr.ma_data[1] = 0x09; /* XXX */
|
||||
priv->conf.macaddr.ma_data[2] = 0xc0; /* XXX */
|
||||
priv->conf.macaddr.ma_data[3] = (u_char)((random() & 0xff0000) >> 16);
|
||||
priv->conf.macaddr.ma_data[4] = (u_char)((random() & 0x00ff00) >> 8);
|
||||
priv->conf.macaddr.ma_data[5] = (u_char)((random() & 0x0000ff) >> 0);
|
||||
|
||||
NG_NODE_SET_PRIVATE(nodep, priv);
|
||||
priv->node = nodep;
|
||||
|
||||
/* Done */
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Method for attaching a new hook
|
||||
* A hook is a virtual ATM link.
|
||||
*/
|
||||
static int
|
||||
ng_atmpif_newhook(node_p node, hook_p hook, const char *name)
|
||||
{
|
||||
const priv_p priv = NG_NODE_PRIVATE(node);
|
||||
|
||||
/*
|
||||
* Check for a link hook
|
||||
*/
|
||||
if (strcmp(name, NG_ATMPIF_HOOK_LINK) == 0) {
|
||||
int error;
|
||||
|
||||
/*
|
||||
* Do not create twice a link hook
|
||||
*/
|
||||
if (priv->link != NULL)
|
||||
return (EEXIST);
|
||||
|
||||
priv->link = malloc(sizeof(*priv->link),
|
||||
M_NETGRAPH_ATMPIF, M_NOWAIT | M_ZERO);
|
||||
if (priv->link == NULL)
|
||||
return (ENOMEM);
|
||||
|
||||
/*
|
||||
* Register as an HARP device
|
||||
*/
|
||||
if ((error = vatmpif_harp_attach(node))) {
|
||||
free(priv->link, M_NETGRAPH_ATMPIF);
|
||||
priv->link = NULL;
|
||||
return (error);
|
||||
}
|
||||
|
||||
priv->link->hook = hook;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Unknown hook name */
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Receive a control message from ngctl or the netgraph's API
|
||||
*/
|
||||
static int
|
||||
ng_atmpif_rcvmsg(node_p node, item_p item, hook_p lasthook)
|
||||
{
|
||||
const priv_p priv = NG_NODE_PRIVATE(node);
|
||||
struct ng_mesg *msg;
|
||||
struct ng_mesg *resp = NULL;
|
||||
int error = 0;
|
||||
|
||||
NGI_GET_MSG(item, msg);
|
||||
|
||||
switch (msg->header.typecookie) {
|
||||
case NGM_ATMPIF_COOKIE:
|
||||
switch (msg->header.cmd) {
|
||||
case NGM_ATMPIF_GET_CONFIG:
|
||||
{
|
||||
struct ng_vatmpif_config *conf;
|
||||
|
||||
NG_MKRESPONSE(resp, msg,
|
||||
sizeof(struct ng_vatmpif_config), M_NOWAIT);
|
||||
if (resp == NULL) {
|
||||
error = ENOMEM;
|
||||
break;
|
||||
}
|
||||
conf = (struct ng_vatmpif_config *)resp->data;
|
||||
*conf = priv->conf; /* no sanity checking needed */
|
||||
break;
|
||||
}
|
||||
case NGM_ATMPIF_SET_CONFIG:
|
||||
{
|
||||
struct ng_vatmpif_config *conf;
|
||||
|
||||
if (msg->header.arglen != sizeof(*conf)) {
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
conf = (struct ng_vatmpif_config *)msg->data;
|
||||
priv->conf = *conf;
|
||||
break;
|
||||
}
|
||||
case NGM_ATMPIF_GET_LINK_STATUS:
|
||||
{
|
||||
struct ng_vatmpif_hook *link;
|
||||
struct ng_atmpif_link_status *status;
|
||||
|
||||
if ((link = priv->link) == NULL) {
|
||||
error = ENOTCONN;
|
||||
break;
|
||||
}
|
||||
|
||||
NG_MKRESPONSE(resp, msg, sizeof(*status), M_NOWAIT);
|
||||
if (resp == NULL) {
|
||||
error = ENOMEM;
|
||||
break;
|
||||
}
|
||||
status = (struct ng_atmpif_link_status *)resp->data;
|
||||
status->InSeq = link->InSeq;
|
||||
status->OutSeq = link->OutSeq;
|
||||
status->cur_pcr = link->cur_pcr;
|
||||
break;
|
||||
}
|
||||
case NGM_ATMPIF_GET_STATS:
|
||||
case NGM_ATMPIF_CLR_STATS:
|
||||
case NGM_ATMPIF_GETCLR_STATS:
|
||||
{
|
||||
struct ng_vatmpif_hook *link;
|
||||
|
||||
if ((link = priv->link) == NULL) {
|
||||
error = ENOTCONN;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Get/clear stats */
|
||||
if (msg->header.cmd != NGM_ATMPIF_CLR_STATS) {
|
||||
NG_MKRESPONSE(resp, msg,
|
||||
sizeof(link->stats), M_NOWAIT);
|
||||
if (resp == NULL) {
|
||||
error = ENOMEM;
|
||||
break;
|
||||
}
|
||||
bcopy(&link->stats,
|
||||
resp->data, sizeof(link->stats));
|
||||
}
|
||||
if (msg->header.cmd != NGM_ATMPIF_GET_STATS)
|
||||
bzero(&link->stats, sizeof(link->stats));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Done */
|
||||
NG_RESPOND_MSG(error, node, item, resp);
|
||||
NG_FREE_MSG(msg);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Hook disconnection.
|
||||
* It shutdown the virtual ATM link however the node is kept.
|
||||
*/
|
||||
static int
|
||||
ng_atmpif_disconnect(hook_p hook)
|
||||
{
|
||||
const node_p node = NG_HOOK_NODE(hook);
|
||||
const priv_p priv = NG_NODE_PRIVATE(node);
|
||||
|
||||
/*
|
||||
* Deregister from the HARP stack
|
||||
*/
|
||||
vatmpif_harp_detach(node);
|
||||
|
||||
/*
|
||||
* Free associated link information
|
||||
*/
|
||||
KASSERT(priv->link != NULL, ("%s: no link", __func__));
|
||||
FREE(priv->link, M_NETGRAPH_ATMPIF);
|
||||
priv->link = NULL;
|
||||
|
||||
/* Shutdown the physical interface */
|
||||
priv->vu_pif.pif_flags &= ~PIF_UP;
|
||||
|
||||
/* No more hooks, however I prefer to keep the node
|
||||
* instead of going away
|
||||
* However, if we are interested in removing it, let's
|
||||
* call ng_rmnode(hook->node); here.
|
||||
*/
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Shutdown node
|
||||
*
|
||||
* Free the private data.
|
||||
*/
|
||||
static int
|
||||
ng_atmpif_rmnode(node_p node)
|
||||
{
|
||||
const priv_p priv = NG_NODE_PRIVATE(node);
|
||||
|
||||
/* Free private data */
|
||||
FREE(priv, M_NETGRAPH_ATMPIF);
|
||||
NG_NODE_SET_PRIVATE(node, NULL);
|
||||
|
||||
/* Unref node */
|
||||
NG_NODE_UNREF(node);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Receive data
|
||||
*
|
||||
* Then vatmpif_harp_recv_drain will schedule a call into the kernel
|
||||
* to process the atm_intrq.
|
||||
* It means that it should be processing at splimp() if
|
||||
* the node was a regular hw driver.
|
||||
*/
|
||||
static int
|
||||
ng_atmpif_rcvdata(hook_p hook, item_p item)
|
||||
{
|
||||
const node_p node = NG_HOOK_NODE(hook);
|
||||
const priv_p priv = NG_NODE_PRIVATE(node);
|
||||
struct vatmpif_header *h;
|
||||
struct vatmpif_header hdrbuf;
|
||||
int error = 0;
|
||||
struct mbuf *m;
|
||||
|
||||
NGI_GET_M(item, m);
|
||||
NG_FREE_ITEM(item);
|
||||
|
||||
/* Is the Physical Interface UP ? */
|
||||
if (!(priv->vu_pif.pif_flags & PIF_UP)) {
|
||||
log(LOG_ERR, "%s%d: down while %s",
|
||||
priv->vu_pif.pif_name, priv->vu_pif.pif_unit, __func__);
|
||||
error = ENETDOWN;
|
||||
goto drop;
|
||||
}
|
||||
|
||||
/* Sanity check header length */
|
||||
if (m->m_pkthdr.len < sizeof(*h)) {
|
||||
priv->link->stats.hva_st_ng.ng_badpdu++;
|
||||
error = EINVAL;
|
||||
goto drop;
|
||||
}
|
||||
|
||||
/* Get the Virtual ATM Physical Interface header */
|
||||
if (m->m_len >= sizeof(*h)) { /* the common case */
|
||||
h = mtod(m, struct vatmpif_header *);
|
||||
} else {
|
||||
m_copydata(m, 0, sizeof(*h), (caddr_t)&hdrbuf);
|
||||
h = &hdrbuf; /* allocated on the stack */
|
||||
}
|
||||
|
||||
/*
|
||||
* Consume the vatmpif header
|
||||
*/
|
||||
m_adj(m, sizeof(*h));
|
||||
|
||||
/*
|
||||
* Parse the header h
|
||||
*/
|
||||
|
||||
/*
|
||||
* duplication and out of order test.
|
||||
*
|
||||
* . let's SEQ_MAX be the highest sequence number
|
||||
* . let's assume that h->seq = SEQ_MAX, (1)
|
||||
*/
|
||||
if (ntohl(h->seq) < priv->link->InSeq) {
|
||||
/* . is false due to (1) */
|
||||
/* duplicate or out of order */
|
||||
priv->link->stats.hva_st_ng.ng_errseq++;
|
||||
error = EINVAL;
|
||||
goto drop;
|
||||
}
|
||||
/* . then the mbuf is not dropped */
|
||||
|
||||
/* PDUs have been lost ?? */
|
||||
if (priv->link->InSeq < ntohl(h->seq)) {
|
||||
/* . it is true only if a PDU has been lost,
|
||||
* . else due to (1) priv->link->InSeq is
|
||||
* . already equal to SEQ_MAX.
|
||||
*/
|
||||
priv->link->stats.hva_st_ng.ng_lostpdu++;
|
||||
priv->link->InSeq = ntohl(h->seq);
|
||||
}
|
||||
|
||||
/* Save the sequence number */
|
||||
priv->link->InSeq = ntohl(h->seq) + 1;
|
||||
/* . it leads to InSeq = SEQ_MAX + 1 = SEQ_MIN */
|
||||
|
||||
/* . it means that InSeq is always the next intended
|
||||
* . sequence number if none is lost, doesn't it ?
|
||||
*/
|
||||
|
||||
/*
|
||||
* Send the packet to the stack.
|
||||
*/
|
||||
priv->link->stats.hva_st_ng.ng_rx_pdu++;
|
||||
error = vatmpif_harp_recv_drain(priv, m,
|
||||
ATM_HDR_GET_VPI(ntohl(h->cellhdr)),
|
||||
ATM_HDR_GET_VCI(ntohl(h->cellhdr)),
|
||||
ATM_HDR_GET_PT (ntohl(h->cellhdr)),
|
||||
ATM_HDR_GET_CLP(ntohl(h->cellhdr)), h->aal);
|
||||
|
||||
return (error);
|
||||
|
||||
drop:
|
||||
m_freem(m);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Transmit data. Called by the HARP's outpout function. You should
|
||||
* notice that the return value is not returned upward by the HARP
|
||||
* stack. It is only used in order to update the stats.
|
||||
*/
|
||||
int
|
||||
ng_atmpif_transmit(const priv_p priv, struct mbuf *m,
|
||||
uint8_t vpi, uint16_t vci, uint8_t pt, uint8_t clp, Vatmpif_aal aal)
|
||||
{
|
||||
struct vatmpif_header *h;
|
||||
int error = 0;
|
||||
|
||||
/* Is the Physical Interface UP ? */
|
||||
if (!(priv->vu_pif.pif_flags & PIF_UP)) {
|
||||
log(LOG_ERR, "%s%d: down while %s",
|
||||
priv->vu_pif.pif_name, priv->vu_pif.pif_unit, __func__);
|
||||
error = ENETDOWN;
|
||||
goto drop;
|
||||
}
|
||||
|
||||
/* If the hook is not connected, free the mbuf */
|
||||
if (priv->link == NULL) {
|
||||
log(LOG_ERR, "%s%d: no hook while %s",
|
||||
priv->vu_pif.pif_name, priv->vu_pif.pif_unit, __func__);
|
||||
error = ENETDOWN;
|
||||
goto drop;
|
||||
}
|
||||
|
||||
M_PREPEND(m, sizeof(*h), M_DONTWAIT);
|
||||
if (m == NULL) {
|
||||
error = ENOBUFS;
|
||||
goto drop;
|
||||
}
|
||||
m = m_pullup(m, sizeof(*h));
|
||||
if (m == NULL) {
|
||||
error = ENOBUFS;
|
||||
goto drop;
|
||||
}
|
||||
h = mtod(m, struct vatmpif_header *);
|
||||
|
||||
/* htonl is linear */
|
||||
h->cellhdr = htonl(ATM_HDR_SET_VPI(vpi));
|
||||
h->cellhdr += htonl(ATM_HDR_SET_VCI(vci));
|
||||
h->cellhdr += htonl(ATM_HDR_SET_PT (pt));
|
||||
h->cellhdr += htonl(ATM_HDR_SET_CLP(clp));
|
||||
h->aal = aal;
|
||||
priv->link->OutSeq++;
|
||||
h->seq = htonl(priv->link->OutSeq);
|
||||
h->cookie = 0;
|
||||
|
||||
if (IS_VATMPIF_DEBUG_PACKET(priv))
|
||||
atm_pdu_print(m, __func__);
|
||||
|
||||
/* Send it out to the "link" hook */
|
||||
priv->link->stats.hva_st_ng.ng_tx_pdu++;
|
||||
NG_SEND_DATA_ONLY(error, priv->link->hook, m);
|
||||
|
||||
return (error);
|
||||
|
||||
drop:
|
||||
if (m != NULL)
|
||||
m_freem(m);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
MAC Address parser
|
||||
*****************************************************************/
|
||||
static int
|
||||
ng_macaddr_parse(const struct ng_parse_type *type, const char *s,
|
||||
int *const off, const u_char *const start, u_char *const buf,
|
||||
int *const buflen)
|
||||
{
|
||||
char *eptr;
|
||||
u_long val;
|
||||
int i;
|
||||
|
||||
if (*buflen < 6)
|
||||
return (ERANGE);
|
||||
for (i = 0; i < 6; i++) {
|
||||
val = strtoul(s + *off, &eptr, 16);
|
||||
if (val > 0xff || eptr == s + *off)
|
||||
return (EINVAL);
|
||||
buf[i] = (u_char)val;
|
||||
*off = (eptr - s);
|
||||
if (i < 6 - 1) {
|
||||
if (*eptr != ':')
|
||||
return (EINVAL);
|
||||
(*off)++;
|
||||
}
|
||||
}
|
||||
*buflen = 6;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
ng_macaddr_unparse(const struct ng_parse_type *type, const u_char *data,
|
||||
int *off, char *cbuf, int cbuflen)
|
||||
{
|
||||
int len;
|
||||
|
||||
len = snprintf(cbuf, cbuflen, "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
data[*off], data[*off + 1], data[*off + 2],
|
||||
data[*off + 3], data[*off + 4], data[*off + 5]);
|
||||
if (len >= cbuflen)
|
||||
return (ERANGE);
|
||||
*off += 6;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* this holds all the stuff that should be done at load time
|
||||
*/
|
||||
static int
|
||||
ng_atmpif_mod_event(module_t mod, int event, void *data)
|
||||
{
|
||||
int error = 0;
|
||||
|
||||
switch (event) {
|
||||
|
||||
case MOD_LOAD:
|
||||
vatmpif_nif_zone = uma_zcreate("vatmpif nif",
|
||||
sizeof(struct atm_nif), NULL, NULL, NULL, NULL,
|
||||
UMA_ALIGN_PTR, 0);
|
||||
if (vatmpif_nif_zone == NULL) {
|
||||
error = ENOMEM;
|
||||
break;
|
||||
}
|
||||
|
||||
vatmpif_vcc_zone = uma_zcreate("vatmpif vcc",
|
||||
sizeof(Vatmpif_vcc), NULL, NULL, NULL, NULL,
|
||||
UMA_ALIGN_PTR, 0);
|
||||
if (vatmpif_vcc_zone == NULL) {
|
||||
uma_zdestroy(vatmpif_nif_zone);
|
||||
error = ENOMEM;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case MOD_UNLOAD:
|
||||
uma_zdestroy(vatmpif_nif_zone);
|
||||
uma_zdestroy(vatmpif_vcc_zone);
|
||||
break;
|
||||
|
||||
default:
|
||||
error = EOPNOTSUPP;
|
||||
break;
|
||||
}
|
||||
|
||||
return (error);
|
||||
}
|
||||
933
sys/netgraph/atm/atmpif/ng_atmpif_harp.c
Normal file
933
sys/netgraph/atm/atmpif/ng_atmpif_harp.c
Normal file
|
|
@ -0,0 +1,933 @@
|
|||
/*
|
||||
* Copyright 2003 Harti Brandt
|
||||
* Copyright 2003 Vincent Jardin
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* ATM Virtal Adapter Support
|
||||
* --------------------------
|
||||
*
|
||||
* API between HARP and Netgraph
|
||||
*
|
||||
*/
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/syslog.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/socketvar.h>
|
||||
|
||||
#include <vm/uma.h>
|
||||
|
||||
#include <net/if.h>
|
||||
|
||||
#include <netatm/port.h>
|
||||
#include <netatm/queue.h>
|
||||
#include <netatm/atm.h>
|
||||
#include <netatm/atm_sys.h>
|
||||
#include <netatm/atm_cm.h>
|
||||
#include <netatm/atm_vc.h>
|
||||
#include <netatm/atm_if.h>
|
||||
#include <netatm/atm_sap.h>
|
||||
#include <netatm/atm_pcb.h>
|
||||
#include <netatm/atm_stack.h>
|
||||
#include <netatm/atm_var.h>
|
||||
#include <netatm/atm_ioctl.h>
|
||||
|
||||
#include <net/netisr.h>
|
||||
|
||||
#include <netgraph/ng_message.h>
|
||||
#include <netgraph/netgraph.h>
|
||||
#include <netgraph/atm/ng_atmpif.h>
|
||||
#include <netgraph/atm/atmpif/ng_atmpif_var.h>
|
||||
|
||||
/*
|
||||
* Local definitions
|
||||
*/
|
||||
|
||||
/*
|
||||
* Local methods
|
||||
*/
|
||||
|
||||
static int vatmpif_nunits = 0;
|
||||
|
||||
/*
|
||||
* ATM Interface services
|
||||
*
|
||||
* this virtual device does not use a soft SAR of the AAL5 PDU, neither
|
||||
* of the AAL3/4 PDU.
|
||||
*/
|
||||
static struct stack_defn vatmpif_svaal5 = {
|
||||
sd_next: NULL,
|
||||
sd_sap: SAP_CPCS_AAL5,
|
||||
sd_flag: SDF_TERM, /* no soft SAR */
|
||||
sd_inst: atm_dev_inst,
|
||||
sd_lower: atm_dev_lower,
|
||||
sd_upper: NULL,
|
||||
sd_toku: 0,
|
||||
};
|
||||
static struct stack_defn vatmpif_svaal4 = {
|
||||
sd_next: &vatmpif_svaal5,
|
||||
sd_sap: SAP_CPCS_AAL3_4,
|
||||
sd_flag: SDF_TERM, /* no soft SAR */
|
||||
sd_inst: atm_dev_inst,
|
||||
sd_lower: atm_dev_lower,
|
||||
sd_upper: NULL,
|
||||
sd_toku: 0,
|
||||
};
|
||||
static struct stack_defn vatmpif_svaal0 = {
|
||||
sd_next: &vatmpif_svaal4,
|
||||
sd_sap: SAP_ATM,
|
||||
sd_flag: SDF_TERM, /* no soft SAR */
|
||||
sd_inst: atm_dev_inst,
|
||||
sd_lower: atm_dev_lower,
|
||||
sd_upper: NULL,
|
||||
sd_toku: 0,
|
||||
};
|
||||
static struct stack_defn *vatmpif_services = &vatmpif_svaal0;
|
||||
|
||||
/******************************************************************
|
||||
HARP API METHODS
|
||||
******************************************************************/
|
||||
|
||||
/*
|
||||
* Local methods
|
||||
*/
|
||||
static int vatmpif_harp_ioctl(int code, caddr_t data, caddr_t arg);
|
||||
static int vatmpif_harp_instvcc(Cmn_unit *cup, Cmn_vcc *cvp);
|
||||
static int vatmpif_harp_openvcc(Cmn_unit *cup, Cmn_vcc *cvp);
|
||||
static int vatmpif_harp_closevcc(Cmn_unit *cup, Cmn_vcc *cvp);
|
||||
static void vatmpif_harp_output(Cmn_unit *cup, Cmn_vcc *cvp, KBuffer *m);
|
||||
static atm_intr_t vatmpif_harp_recv_stack;
|
||||
|
||||
/*
|
||||
* Attach an virtual ATM physical inteface with the HARP stack
|
||||
*
|
||||
* Each virtual ATM device interface must register itself here
|
||||
* upon completing the netgraph node constructor.
|
||||
*
|
||||
* Arguments:
|
||||
* node pointer on the netgraph node
|
||||
*
|
||||
* Returns:
|
||||
* 0 successful
|
||||
* errno failed - reason indicated
|
||||
*/
|
||||
int
|
||||
vatmpif_harp_attach(node_p node)
|
||||
{
|
||||
Vatmpif_unit *vup;
|
||||
static int unit = 0;
|
||||
int err;
|
||||
|
||||
/*
|
||||
* Sanity check
|
||||
*/
|
||||
if (node == NULL)
|
||||
return (EINVAL);
|
||||
|
||||
/*
|
||||
* Get the virtual unit structure
|
||||
*/
|
||||
vup = (Vatmpif_unit *)NG_NODE_PRIVATE(node);
|
||||
if (vup == NULL)
|
||||
return (EINVAL);
|
||||
|
||||
/*
|
||||
* Start initializing the HARP binding
|
||||
*/
|
||||
vup->vu_unit = unit;
|
||||
/* 9188 bytes: Default ATM network interface MTU + LLC/SNAP header */
|
||||
vup->vu_mtu = ATM_NIF_MTU + 8;
|
||||
vup->vu_vcc_zone = vatmpif_vcc_zone;
|
||||
vup->vu_nif_zone = vatmpif_nif_zone;
|
||||
vup->vu_ioctl = vatmpif_harp_ioctl;
|
||||
vup->vu_instvcc = vatmpif_harp_instvcc;
|
||||
vup->vu_openvcc = vatmpif_harp_openvcc;
|
||||
vup->vu_closevcc = vatmpif_harp_closevcc;
|
||||
vup->vu_output = vatmpif_harp_output;
|
||||
vup->vu_softc = vup;
|
||||
|
||||
/*
|
||||
* Consider this virtual unit assigned
|
||||
*/
|
||||
unit++;
|
||||
|
||||
/*
|
||||
* Get our device type and setup the adapter config info
|
||||
* - at least as much as we can
|
||||
*/
|
||||
vup->vu_config.ac_vendor = VENDOR_NETGRAPH;
|
||||
vup->vu_config.ac_vendapi = VENDAPI_NETGRAPH_1;
|
||||
vup->vu_config.ac_device = DEV_VATMPIF;
|
||||
vup->vu_config.ac_media = MEDIA_VIRTUAL;
|
||||
vup->vu_config.ac_serial = (u_long)node;
|
||||
vup->vu_config.ac_bustype = BUS_VIRTUAL;
|
||||
vup->vu_config.ac_busslot = NGM_ATMPIF_COOKIE;
|
||||
vup->vu_config.ac_ram = (u_long)node;
|
||||
vup->vu_config.ac_ramsize = sizeof(*node);
|
||||
vup->vu_config.ac_macaddr = vup->conf.macaddr;
|
||||
snprintf(vup->vu_config.ac_hard_vers,
|
||||
sizeof(vup->vu_config.ac_hard_vers),
|
||||
"%s", "Virt. ATM 1.0");
|
||||
snprintf(vup->vu_config.ac_firm_vers,
|
||||
sizeof(vup->vu_config.ac_firm_vers),
|
||||
"%d", __FreeBSD__);
|
||||
|
||||
/*
|
||||
* Set the interface capabilities
|
||||
*/
|
||||
vup->vu_pif.pif_maxvpi = VATMPIF_MAX_VPI;
|
||||
vup->vu_pif.pif_maxvci = VATMPIF_MAX_VCI;
|
||||
vup->vu_pif.pif_pcr = vup->conf.pcr;
|
||||
|
||||
/*
|
||||
* Register this interface with ATM core services
|
||||
*/
|
||||
if ((err = atm_physif_register((Cmn_unit *)vup,
|
||||
VATMPIF_DEV_NAME, vatmpif_services)) != 0 ) {
|
||||
/*
|
||||
* Registration failed - back everything out
|
||||
*
|
||||
* The netgraph node must not be created.
|
||||
*/
|
||||
return (err);
|
||||
}
|
||||
|
||||
vatmpif_nunits++;
|
||||
|
||||
/*
|
||||
* Mark device initialization completed
|
||||
*/
|
||||
vup->vu_flags |= CUF_INITED;
|
||||
|
||||
/* Done */
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Halt driver processing
|
||||
*
|
||||
* This will be called just prior the destruction of the Netgraph's node.
|
||||
*
|
||||
* Arguments:
|
||||
* node pointer on the netgraph node
|
||||
*
|
||||
* Returns:
|
||||
* 0 detach was successful
|
||||
* errno detach failed - reason indicated
|
||||
*/
|
||||
int
|
||||
vatmpif_harp_detach(node_p node)
|
||||
{
|
||||
Vatmpif_unit *vup = (Vatmpif_unit *)NG_NODE_PRIVATE(node);
|
||||
int err;
|
||||
|
||||
/*
|
||||
* Deregister device from kernel services
|
||||
*/
|
||||
if ((err = atm_physif_deregister((Cmn_unit *)vup)))
|
||||
return (err);
|
||||
|
||||
vatmpif_nunits--;
|
||||
|
||||
/*
|
||||
* Clear device initialized
|
||||
*/
|
||||
vup->vu_flags &= ~CUF_INITED;
|
||||
|
||||
/* Done */
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle netatm core service interface ioctl requests
|
||||
*
|
||||
* Arguments:
|
||||
* code ioctl function (sub)code
|
||||
* data data to/from ioctl
|
||||
* arg optional code-specific argument
|
||||
*
|
||||
* Returns:
|
||||
* 0 request processed successfully
|
||||
* errno request failed - reason code
|
||||
*/
|
||||
static int
|
||||
vatmpif_harp_ioctl(int code, caddr_t data, caddr_t arg)
|
||||
{
|
||||
struct atminfreq *aip = (struct atminfreq *)data;
|
||||
struct atm_pif *pip;
|
||||
Vatmpif_unit *vup;
|
||||
caddr_t buf = aip->air_buf_addr;
|
||||
struct air_vinfo_rsp *avr;
|
||||
size_t count, len, buf_len = aip->air_buf_len;
|
||||
int err = 0;
|
||||
char ifname[2 * IFNAMSIZ];
|
||||
|
||||
ATM_DEBUG3("%s: code=%d, opcode=%d\n", __func__, code, aip->air_opcode);
|
||||
|
||||
switch (aip->air_opcode) {
|
||||
|
||||
case AIOCS_INF_VST:
|
||||
/*
|
||||
* Get vendor statistics
|
||||
*/
|
||||
pip = (struct atm_pif *)arg;
|
||||
vup = (Vatmpif_unit *)pip;
|
||||
if (pip == NULL)
|
||||
return (ENXIO);
|
||||
snprintf(ifname, sizeof(ifname), "%s%d",
|
||||
pip->pif_name, pip->pif_unit);
|
||||
|
||||
/*
|
||||
* Cast response structure onto user's buffer
|
||||
*/
|
||||
avr = (struct air_vinfo_rsp *)(void *)buf;
|
||||
|
||||
/*
|
||||
* How lare is the response structure ?
|
||||
*/
|
||||
len = sizeof(struct air_vinfo_rsp);
|
||||
|
||||
/*
|
||||
* Sanity check - enough room for response structure
|
||||
*/
|
||||
if (buf_len < len)
|
||||
return ENOSPC;
|
||||
|
||||
/*
|
||||
* Copy interface name into response structure
|
||||
*/
|
||||
if ((err = copyout(ifname, avr->avsp_intf, IFNAMSIZ)) != 0)
|
||||
break;
|
||||
|
||||
/*
|
||||
* Advance the buffer address and decrement the size
|
||||
*/
|
||||
buf += len;
|
||||
buf_len -= len;
|
||||
|
||||
/*
|
||||
* Get the vendor stats
|
||||
*/
|
||||
/* vup->vu_stats */
|
||||
|
||||
/*
|
||||
* Stick as much of it as we have room for
|
||||
* into the response
|
||||
*/
|
||||
count = MIN(sizeof(Vatmpif_stats), buf_len);
|
||||
|
||||
/*
|
||||
* Copy stats into user's buffer. Return value is
|
||||
* amount of data copied.
|
||||
*/
|
||||
if ((err = copyout((caddr_t)&vup->vu_stats, buf,
|
||||
buf_len)) != 0)
|
||||
break;
|
||||
buf += count;
|
||||
buf_len -= count;
|
||||
if (count < sizeof(Vatmpif_stats))
|
||||
err = ENOSPC;
|
||||
|
||||
/*
|
||||
* Record amount we are returning as vendor info...
|
||||
*/
|
||||
if ((err = copyout(&count, &avr->avsp_len, sizeof(count))) != 0)
|
||||
break;
|
||||
|
||||
/*
|
||||
* Update the reply pointers and lengths
|
||||
*/
|
||||
aip->air_buf_addr = buf;
|
||||
aip->air_buf_len = buf_len;
|
||||
break;
|
||||
|
||||
default:
|
||||
err = ENOSYS;
|
||||
break;
|
||||
}
|
||||
|
||||
return (err);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get CBR/VBR/ABR/UBR from bearer attribute
|
||||
*
|
||||
* Arguments:
|
||||
* bearer T_ATM_BEARER_CAP option value structure
|
||||
*
|
||||
* Returns:
|
||||
* Driver traffic class
|
||||
*/
|
||||
static Vatmpif_traffic_type
|
||||
vatmpif_bearerclass(struct attr_bearer *bearer)
|
||||
{
|
||||
switch (bearer->v.bearer_class) {
|
||||
case T_ATM_CLASS_A:
|
||||
return (VATMPIF_TRAF_CBR);
|
||||
case T_ATM_CLASS_C:
|
||||
return (VATMPIF_TRAF_VBR);
|
||||
case T_ATM_CLASS_X:
|
||||
switch (bearer->v.traffic_type) {
|
||||
case T_ATM_CBR:
|
||||
return (VATMPIF_TRAF_CBR);
|
||||
case T_ATM_VBR:
|
||||
return (VATMPIF_TRAF_VBR);
|
||||
case T_ATM_ABR:
|
||||
return (VATMPIF_TRAF_ABR);
|
||||
case T_ATM_NULL:
|
||||
case T_ATM_UBR:
|
||||
return (VATMPIF_TRAF_UBR);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* never reached */
|
||||
log(LOG_ERR, "%s: could not determine the traffic type.\n", __func__);
|
||||
return (VATMPIF_TRAF_UBR);
|
||||
}
|
||||
|
||||
/*
|
||||
* VCC Stack Instantiation
|
||||
*
|
||||
* This function is called via the common driver code during a device VCC
|
||||
* stack instantiation. The common code has already validated some of
|
||||
* the request so we just need to check a few more VATMPIF-specific details.
|
||||
*
|
||||
* Arguments:
|
||||
* cup pointer to device common unit
|
||||
* cvp pointer to common VCC entry
|
||||
*
|
||||
* Returns:
|
||||
* 0 instantiation successful
|
||||
* errno instantiation failed - reason indicated
|
||||
*/
|
||||
static int
|
||||
vatmpif_harp_instvcc(Cmn_unit *cup, Cmn_vcc *cvp)
|
||||
{
|
||||
Vatmpif_unit *vup = (Vatmpif_unit *)cup;
|
||||
Vatmpif_vcc *vvp = (Vatmpif_vcc *)cvp;
|
||||
Atm_attributes *ap = &vvp->vv_connvc->cvc_attr;
|
||||
int32_t pcr = 0;
|
||||
int32_t scr = 0;
|
||||
Vatmpif_traffic_type traffic = VATMPIF_TRAF_UBR;
|
||||
|
||||
ATM_DEBUG3("%s: vup=%p, vvp=%p\n", __func__, vup, vvp);
|
||||
|
||||
if (ap->traffic.tag == T_ATM_PRESENT) {
|
||||
pcr = ap->traffic.v.forward.PCR_all_traffic;
|
||||
scr = ap->traffic.v.forward.SCR_all_traffic;
|
||||
}
|
||||
if (pcr < 0)
|
||||
pcr = 0;
|
||||
if (scr < 0)
|
||||
scr = 0;
|
||||
|
||||
KASSERT(ap->bearer.tag == T_ATM_PRESENT, ("Bearer tag is required"));
|
||||
traffic = vatmpif_bearerclass(&ap->bearer);
|
||||
/* Guarantee PCR of the PVC with CBR */
|
||||
if (traffic == VATMPIF_TRAF_CBR &&
|
||||
vup->vu_cur_pcr + pcr > vup->vu_pif.pif_pcr) {
|
||||
return (EINVAL);
|
||||
}
|
||||
/* Guarantee SCR of the PVC with VBR */
|
||||
if (traffic == VATMPIF_TRAF_VBR &&
|
||||
vup->vu_cur_pcr + scr > vup->vu_pif.pif_pcr) {
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Validate requested AAL
|
||||
*/
|
||||
KASSERT(ap->aal.tag == T_ATM_PRESENT, ("AAL tag is required"));
|
||||
switch (ap->aal.type) {
|
||||
case ATM_AAL0:
|
||||
break;
|
||||
|
||||
case ATM_AAL1:
|
||||
break;
|
||||
|
||||
case ATM_AAL2:
|
||||
return (EINVAL);
|
||||
|
||||
case ATM_AAL3_4:
|
||||
if (ap->aal.v.aal4.forward_max_SDU_size > vup->vu_mtu ||
|
||||
ap->aal.v.aal4.backward_max_SDU_size > vup->vu_mtu)
|
||||
return (EINVAL);
|
||||
break;
|
||||
|
||||
case ATM_AAL5:
|
||||
if (ap->aal.v.aal5.forward_max_SDU_size > vup->vu_mtu ||
|
||||
ap->aal.v.aal5.backward_max_SDU_size > vup->vu_mtu)
|
||||
return (EINVAL);
|
||||
break;
|
||||
|
||||
default:
|
||||
return (EINVAL);
|
||||
}
|
||||
/* Done */
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Open a VCC
|
||||
*
|
||||
* This function is called via the common driver code after receiving a
|
||||
* stack *_INIT command. The common has already validated most of
|
||||
* the request so we just need to check a few more VATMPIF-specific details.
|
||||
* Then we just forward to the Netgraph node.
|
||||
*
|
||||
* Called at splimp.
|
||||
*
|
||||
* Arguments:
|
||||
* cup pointer to device common unit
|
||||
* cvp pointer to common VCC entry
|
||||
*
|
||||
* Returns:
|
||||
* 0 open successful
|
||||
* errno open failed - reason indicated
|
||||
*/
|
||||
static int
|
||||
vatmpif_harp_openvcc(Cmn_unit *cup, Cmn_vcc *cvp)
|
||||
{
|
||||
Vatmpif_unit *vup = (Vatmpif_unit *)cup;
|
||||
Vatmpif_vcc *vvp = (Vatmpif_vcc *)cvp;
|
||||
struct vccb *vcp = vvp->vv_connvc->cvc_vcc;
|
||||
Atm_attributes *ap = &vvp->vv_connvc->cvc_attr;
|
||||
|
||||
ATM_DEBUG5("%s: vup=%p, vvp=%p, vcc=(%d,%d)\n", __func__,
|
||||
vup, vvp, vcp->vc_vpi, vcp->vc_vci);
|
||||
|
||||
/*
|
||||
* We only need to open incoming VC's so outbound VC's
|
||||
* just get set to CVS_ACTIVE state.
|
||||
*/
|
||||
if ((vcp->vc_type & VCC_IN) == 0) {
|
||||
/*
|
||||
* Set the state and return - nothing else needed
|
||||
*/
|
||||
vvp->vv_state = CVS_ACTIVE;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the AAL and traffic
|
||||
*/
|
||||
switch (ap->aal.type) {
|
||||
case ATM_AAL0:
|
||||
vvp->vv_aal = VATMPIF_AAL_0;
|
||||
break;
|
||||
case ATM_AAL2:
|
||||
return (EINVAL);
|
||||
case ATM_AAL3_4:
|
||||
vvp->vv_aal = VATMPIF_AAL_4;
|
||||
break;
|
||||
case ATM_AAL5:
|
||||
vvp->vv_aal = VATMPIF_AAL_5;
|
||||
break;
|
||||
default:
|
||||
return (EINVAL);
|
||||
}
|
||||
vvp->vv_traffic_type = vatmpif_bearerclass(&ap->bearer);
|
||||
vvp->vv_traffic = ap->traffic.v;
|
||||
|
||||
switch (vvp->vv_traffic_type) {
|
||||
case VATMPIF_TRAF_ABR:
|
||||
/* TODO */
|
||||
case VATMPIF_TRAF_UBR:
|
||||
break;
|
||||
case VATMPIF_TRAF_VBR:
|
||||
vup->vu_cur_pcr += vvp->vv_traffic.forward.SCR_all_traffic;
|
||||
break;
|
||||
case VATMPIF_TRAF_CBR:
|
||||
vup->vu_cur_pcr += vvp->vv_traffic.forward.PCR_all_traffic;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Indicate VC active
|
||||
*/
|
||||
vvp->vv_state = CVS_ACTIVE;
|
||||
|
||||
/* Done */
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Close a VCC
|
||||
*
|
||||
* This function is called via the common driver code after receiving a
|
||||
* stack *_TERM command. The common code has already validated most of
|
||||
* the request so we just need to check a few more VATMPIF-specific detail.
|
||||
* Then we just remove the entry from the list.
|
||||
*
|
||||
* Arguments:
|
||||
* cup pointer to device common unit
|
||||
* cvp pointer to common VCC entry
|
||||
*
|
||||
* Returns:
|
||||
* 0 close successful
|
||||
* errno close failed - reason indicated
|
||||
*/
|
||||
static int
|
||||
vatmpif_harp_closevcc(Cmn_unit *cup, Cmn_vcc *cvp)
|
||||
{
|
||||
Vatmpif_unit *vup = (Vatmpif_unit *)cup;
|
||||
Vatmpif_vcc *vvp = (Vatmpif_vcc *)cvp;
|
||||
struct vccb *vcp = vvp->vv_connvc->cvc_vcc;
|
||||
|
||||
/*
|
||||
* If this is an outbound only VCI, then we can close
|
||||
* immediately.
|
||||
*/
|
||||
if ((vcp->vc_type & VCC_IN) == 0) {
|
||||
/*
|
||||
* The state will be set to TERM when we return
|
||||
* to the *_TERM caller.
|
||||
*/
|
||||
return (0);
|
||||
}
|
||||
|
||||
switch (vvp->vv_traffic_type) {
|
||||
case VATMPIF_TRAF_ABR:
|
||||
/* TODO */
|
||||
case VATMPIF_TRAF_UBR:
|
||||
break;
|
||||
case VATMPIF_TRAF_VBR:
|
||||
vup->vu_cur_pcr -= vvp->vv_traffic.forward.SCR_all_traffic;
|
||||
break;
|
||||
case VATMPIF_TRAF_CBR:
|
||||
vup->vu_cur_pcr -= vvp->vv_traffic.forward.PCR_all_traffic;
|
||||
break;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Output a PDU
|
||||
*
|
||||
* This function is called via the common driver code after receiving a
|
||||
* stack *_DATA* command. The command code has already validated most of
|
||||
* the request so we just need to check a few more VATMPIF-specific detail.
|
||||
* Then we just forward the transmit mbuf to the Netgraph node.
|
||||
*
|
||||
* Arguments:
|
||||
* cup pointer to device common
|
||||
* cvp pointer to common VCC entry
|
||||
* m pointer to output PDU buffer chain head
|
||||
*
|
||||
* Returns:
|
||||
* none
|
||||
*/
|
||||
static void
|
||||
vatmpif_harp_output(Cmn_unit *cup, Cmn_vcc *cvp, KBuffer *m)
|
||||
{
|
||||
Vatmpif_unit *vup = (Vatmpif_unit *)cup;
|
||||
Vatmpif_vcc *vvp = (Vatmpif_vcc *)cvp;
|
||||
struct vccb *vcp = vvp->vv_connvc->cvc_vcc;
|
||||
Atm_attributes *ap = &vvp->vv_connvc->cvc_attr;
|
||||
int err = 0;
|
||||
u_long pdulen = 0;
|
||||
|
||||
if (IS_VATMPIF_DEBUG_PACKET(vup))
|
||||
atm_dev_pdu_print(cup, cvp, m, __func__);
|
||||
|
||||
/*
|
||||
* Get packet PDU length
|
||||
*/
|
||||
KB_PLENGET (m, pdulen);
|
||||
|
||||
err = ng_atmpif_transmit(vup, m, vcp->vc_vpi, vcp->vc_vci,
|
||||
0, 0, ap->aal.type);
|
||||
|
||||
/*
|
||||
* Now collect some statistics
|
||||
*/
|
||||
if (err) {
|
||||
vup->vu_pif.pif_oerrors++;
|
||||
vcp->vc_oerrors++;
|
||||
if (vcp->vc_nif)
|
||||
vcp->vc_nif->nif_if.if_oerrors++;
|
||||
} else {
|
||||
/*
|
||||
* Good transmission
|
||||
*/
|
||||
|
||||
switch (ap->aal.type) {
|
||||
case VATMPIF_AAL_0:
|
||||
vup->vu_stats.hva_st_ng.ng_tx_rawcell++;
|
||||
break;
|
||||
case VATMPIF_AAL_4:
|
||||
/* TODO */
|
||||
break;
|
||||
case VATMPIF_AAL_5:
|
||||
vup->vu_stats.hva_st_aal5.aal5_xmit +=
|
||||
(pdulen + 47) / 48;
|
||||
vup->vu_stats.hva_st_aal5.aal5_pdu_xmit++;
|
||||
break;
|
||||
default:
|
||||
log(LOG_ERR, "%s%d: unknown AAL while %s",
|
||||
vup->vu_pif.pif_name, vup->vu_pif.pif_unit,
|
||||
__func__);
|
||||
}
|
||||
|
||||
vup->vu_pif.pif_opdus++;
|
||||
vup->vu_pif.pif_obytes += pdulen;
|
||||
if (vvp) {
|
||||
vcp = vvp->vv_connvc->cvc_vcc;
|
||||
vcp->vc_opdus++;
|
||||
vcp->vc_obytes += pdulen;
|
||||
if (vcp->vc_nif) {
|
||||
vcp->vc_nif->nif_obytes += pdulen;
|
||||
vcp->vc_nif->nif_if.if_opackets++;
|
||||
vcp->vc_nif->nif_if.if_obytes += pdulen;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Pass Incoming PDU up to the HARP stack
|
||||
*
|
||||
* This function is called via the core ATM interrupt queue callback
|
||||
* set in vatmpif_harp_recv_drain(). It will pass the supplied incoming
|
||||
* PDU up the incoming VCC's stack.
|
||||
*
|
||||
* Arguments:
|
||||
* tok token to identify stack instantiation
|
||||
* m pointer to incoming PDU buffer chain
|
||||
*
|
||||
* Returns:
|
||||
* none
|
||||
*/
|
||||
static void
|
||||
vatmpif_harp_recv_stack(void *tok, KBuffer *m)
|
||||
{
|
||||
Vatmpif_vcc *vvp = (Vatmpif_vcc *)tok;
|
||||
int err;
|
||||
|
||||
/*
|
||||
* Send the data up the stack
|
||||
*/
|
||||
STACK_CALL(CPCS_UNITDATA_SIG, vvp->vv_upper,
|
||||
vvp->vv_toku, vvp->vv_connvc, (intptr_t)m, 0, err);
|
||||
if (err)
|
||||
KB_FREEALL(m);
|
||||
}
|
||||
|
||||
/*
|
||||
* Drain Receive Queue
|
||||
*
|
||||
* The function will process all completed entries at the head of the
|
||||
* receive queue. The received segments will be linked into a received
|
||||
* PDU buffer cahin and it will then be passed up the PDU's VCC stack
|
||||
* function processing by the next higher protocol layer.
|
||||
*
|
||||
* May be called in interrupt state.
|
||||
* Must be called with interrupts locked out.
|
||||
*
|
||||
* Arguments:
|
||||
* vup pointer to the virtual device structure
|
||||
* m pointer to incoming PDU buffer chain
|
||||
* vpi Virtual Path Identifier
|
||||
* vci Virtual Channel Identifier (host order)
|
||||
* pt Payload Type Identifier (3 bit)
|
||||
* ATM_PT_USER_SDU0
|
||||
* ATM_PT_USER_SDU1
|
||||
* ATM_PT_USER_CONG_SDU0
|
||||
* ATM_PT_USER_CONG_SDU1
|
||||
* ATM_PT_NONUSER
|
||||
* ATM_PT_OAMF5_SEG
|
||||
* ATM_PT_OAMF5_E2E
|
||||
* clp Cell Loss Priority (1 bit)
|
||||
*
|
||||
* Returns:
|
||||
* 0 close successful
|
||||
* errno close failed - reason indicated
|
||||
*/
|
||||
int
|
||||
vatmpif_harp_recv_drain(Vatmpif_unit *vup, KBuffer *m,
|
||||
uint8_t vpi, uint16_t vci, uint8_t pt, uint8_t clp, Vatmpif_aal aal)
|
||||
{
|
||||
Vatmpif_vcc *vvp;
|
||||
struct vccb *vcp;
|
||||
u_long pdulen = 0;
|
||||
caddr_t cp;
|
||||
int err = 0;
|
||||
|
||||
/*
|
||||
* Locate incoming VCC for this PDU
|
||||
*/
|
||||
vvp = (Vatmpif_vcc *)atm_dev_vcc_find((Cmn_unit *)vup,
|
||||
vpi, vci, VCC_IN);
|
||||
|
||||
if (vvp == NULL) {
|
||||
vup->vu_stats.hva_st_ng.ng_rx_novcc++;
|
||||
vup->vu_pif.pif_ierrors++;
|
||||
KB_FREEALL(m);
|
||||
err = EIO;
|
||||
goto failed;
|
||||
}
|
||||
|
||||
switch (aal) {
|
||||
case VATMPIF_AAL_0:
|
||||
vup->vu_stats.hva_st_ng.ng_rx_rawcell++;
|
||||
break;
|
||||
case VATMPIF_AAL_4:
|
||||
/* TODO */
|
||||
break;
|
||||
case VATMPIF_AAL_5:
|
||||
vup->vu_stats.hva_st_aal5.aal5_rcvd += (pdulen + 47) / 48;
|
||||
vup->vu_stats.hva_st_aal5.aal5_pdu_rcvd++;
|
||||
break;
|
||||
default:
|
||||
vup->vu_stats.hva_st_ng.ng_badpdu++;
|
||||
vup->vu_pif.pif_ierrors++;
|
||||
KB_FREEALL(m);
|
||||
err = EINVAL;
|
||||
goto failed;
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO:
|
||||
* For now, only user data PDUs are supported
|
||||
*/
|
||||
if (pt & ATM_HDR_SET_PT(ATM_PT_NONUSER)) {
|
||||
vup->vu_stats.hva_st_ng.ng_badpdu++;
|
||||
vup->vu_pif.pif_ierrors++;
|
||||
if (aal == VATMPIF_AAL_5) {
|
||||
vup->vu_stats.hva_st_aal5.aal5_drops +=
|
||||
(pdulen + 47) / 48;
|
||||
vup->vu_stats.hva_st_aal5.aal5_pdu_drops++;
|
||||
}
|
||||
err = EINVAL;
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (IS_VATMPIF_DEBUG_PACKET(vup))
|
||||
atm_dev_pdu_print((Cmn_unit *)vup, (Cmn_vcc *)vvp, m,
|
||||
__FUNCTION__);
|
||||
|
||||
/*
|
||||
* Get packet PDU length
|
||||
*/
|
||||
KB_PLENGET(m, pdulen);
|
||||
|
||||
/*
|
||||
* Only try queueing this if there is data
|
||||
* to be handed up to the next layer.
|
||||
*/
|
||||
if (pdulen == 0) {
|
||||
/*
|
||||
* Free zero-length buffer
|
||||
*/
|
||||
vup->vu_stats.hva_st_ng.ng_badpdu++;
|
||||
vup->vu_pif.pif_ierrors++;
|
||||
if (aal == VATMPIF_AAL_5)
|
||||
vup->vu_stats.hva_st_aal5.aal5_pdu_errs++;
|
||||
err = EIO;
|
||||
KB_FREEALL(m);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
/* TODO: process the AAL4 CRC, AAL5 CRC,
|
||||
* then update aal5_crc_len, aal5_drops, aal5_pdu_crc,
|
||||
* aal5_pdu_errs, aal5_pdu_drops ...
|
||||
*/
|
||||
|
||||
/*
|
||||
* Quick count the PDU
|
||||
*/
|
||||
vup->vu_pif.pif_ipdus++;
|
||||
vup->vu_pif.pif_ibytes += pdulen;
|
||||
|
||||
vup->vu_stats.hva_st_ng.ng_rx_pdu++;
|
||||
vup->vu_stats.hva_st_atm.atm_rcvd += (pdulen + 47) / 48;
|
||||
|
||||
/*
|
||||
* Update the VCC statistics:
|
||||
* XXX: This code should not be into the driver.
|
||||
*/
|
||||
vcp = vvp->vv_connvc->cvc_vcc;
|
||||
if (vcp) {
|
||||
vcp->vc_ipdus++;
|
||||
vcp->vc_ibytes += pdulen;
|
||||
/*
|
||||
* Update the NIF statistics if any
|
||||
* XXX: beurk !
|
||||
*/
|
||||
if (vcp->vc_nif) {
|
||||
vcp->vc_nif->nif_ibytes += pdulen;
|
||||
vcp->vc_nif->nif_if.if_ipackets++;
|
||||
vcp->vc_nif->nif_if.if_ibytes += pdulen;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The STACK_CALL needs to happen at splnet() in order
|
||||
* for the stack sequence processing to work. Schedule an
|
||||
* interrupt queue callback at splnet().
|
||||
*/
|
||||
|
||||
/*
|
||||
* Prepend callback function pointer and token value to buffer.
|
||||
* We have already guaranteed that the space is available in the
|
||||
* first buffer because the vatmpif_header structure is greater
|
||||
* than our callback pointer.
|
||||
* XXX
|
||||
*/
|
||||
KB_HEADADJ(m, sizeof(atm_intr_func_t) + sizeof(void *));
|
||||
KB_DATASTART(m, cp, caddr_t);
|
||||
*((atm_intr_func_t *) cp) = vatmpif_harp_recv_stack;
|
||||
cp += sizeof (atm_intr_func_t);
|
||||
*((void **)cp) = (void *)vvp;
|
||||
|
||||
/*
|
||||
* Schedule callback
|
||||
*/
|
||||
if (!netisr_queue(NETISR_ATM, m)) {
|
||||
/*
|
||||
* queue is full. Unable to pass up to the HARP stack
|
||||
* Update the stats.
|
||||
*/
|
||||
vup->vu_stats.hva_st_ng.ng_rx_iqfull++;
|
||||
vup->vu_pif.pif_ierrors++;
|
||||
goto failed;
|
||||
}
|
||||
|
||||
/* Done */
|
||||
return (0);
|
||||
|
||||
failed:
|
||||
return (err);
|
||||
}
|
||||
147
sys/netgraph/atm/atmpif/ng_atmpif_var.h
Normal file
147
sys/netgraph/atm/atmpif/ng_atmpif_var.h
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
/*
|
||||
* Copyright (c) 2003 Harti Brandt.
|
||||
* Copyright (c) 2003 Vincent Jardin.
|
||||
* 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.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/*
|
||||
* Supported AALs
|
||||
*/
|
||||
enum vatmpif_aal {
|
||||
VATMPIF_AAL_0 = 0, /* Cell Service */
|
||||
VATMPIF_AAL_4 = 4, /* AAL 3/4 */
|
||||
VATMPIF_AAL_5 = 5, /* AAL 5 */
|
||||
};
|
||||
typedef enum vatmpif_aal Vatmpif_aal;
|
||||
|
||||
/*
|
||||
* Supported traffic type
|
||||
*/
|
||||
enum vatmpif_traffic_type {
|
||||
VATMPIF_TRAF_CBR = 0x01, /* Constant bit rate */
|
||||
VATMPIF_TRAF_VBR = 0x02, /* Variable bit rate */
|
||||
VATMPIF_TRAF_ABR = 0x03, /* Available Bit Rate */
|
||||
VATMPIF_TRAF_UBR = 0x04, /* Unspecified bit rate */
|
||||
};
|
||||
typedef enum vatmpif_traffic_type Vatmpif_traffic_type;
|
||||
|
||||
typedef struct t_atm_traffic Vatmpif_traffic;
|
||||
|
||||
/*
|
||||
* Host protocol control blocks
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Device VCC Entry
|
||||
*
|
||||
* Contains the common (vv_cmn) and specific information for each VCC
|
||||
* which is opened through a ATM PIF node.
|
||||
* It is a virtual VCC. From the Netgraph poit of view it is a
|
||||
* per-node's hook private data.
|
||||
*
|
||||
* It is a polymorph object with the instances of Cmn_vcc.
|
||||
*/
|
||||
struct vatmpif_vcc {
|
||||
Cmn_vcc vv_cmn; /* Common VCC stuff */
|
||||
Vatmpif_aal vv_aal; /* AAL */
|
||||
Vatmpif_traffic vv_traffic; /* forward and backward ATM traffic */
|
||||
Vatmpif_traffic_type vv_traffic_type;/* CBR, VBR, UBR, ... */
|
||||
};
|
||||
typedef struct vatmpif_vcc Vatmpif_vcc;
|
||||
|
||||
#define vv_next vv_cmn.cv_next
|
||||
#define vv_toku vv_cmn.cv_toku
|
||||
#define vv_upper vv_cmn.cv_upper
|
||||
#define vv_connvc vv_cmn.cv_connvc
|
||||
#define vv_state vv_cmn.cv_state
|
||||
|
||||
/*
|
||||
* The hook structure describes a virtual link
|
||||
*/
|
||||
struct ng_vatmpif_hook {
|
||||
hook_p hook; /* netgraph hook */
|
||||
Vatmpif_stats stats; /* link stats */
|
||||
uint32_t InSeq; /* last received sequence number + 1 */
|
||||
uint32_t OutSeq; /* last sent sequence number */
|
||||
uint32_t cur_pcr; /* slot's reserved PCR */
|
||||
};
|
||||
|
||||
/*
|
||||
* Device Virtual Unit Structure
|
||||
*
|
||||
* Contains all the information for a single device (adapter).
|
||||
* It is a virtual device. From the Netgraph point of view it is
|
||||
* a per-node private data.
|
||||
*
|
||||
* It is a polymorph object with the instances of Cmn_unit.
|
||||
*/
|
||||
struct vatmpif_unit {
|
||||
Cmn_unit vu_cmn; /* Common unit stuff */
|
||||
node_p node; /* netgraph node */
|
||||
struct ng_vatmpif_hook* link; /* virtual link hoook */
|
||||
struct ng_vatmpif_config conf; /* node configuration */
|
||||
};
|
||||
typedef struct vatmpif_unit Vatmpif_unit;
|
||||
|
||||
#define ng_vatmpif_private vatmpif_unit
|
||||
typedef struct ng_vatmpif_private *priv_p;
|
||||
|
||||
#define vu_pif vu_cmn.cu_pif
|
||||
#define vu_unit vu_cmn.cu_unit
|
||||
#define vu_flags vu_cmn.cu_flags
|
||||
#define vu_mtu vu_cmn.cu_mtu
|
||||
#define vu_open_vcc vu_cmn.cu_open_vcc
|
||||
#define vu_vcc vu_cmn.cu_vcc
|
||||
#define vu_vcc_zone vu_cmn.cu_vcc_zone
|
||||
#define vu_nif_zone vu_cmn.cu_nif_zone
|
||||
#define vu_ioctl vu_cmn.cu_ioctl
|
||||
#define vu_instvcc vu_cmn.cu_instvcc
|
||||
#define vu_openvcc vu_cmn.cu_openvcc
|
||||
#define vu_closevcc vu_cmn.cu_closevcc
|
||||
#define vu_output vu_cmn.cu_output
|
||||
#define vu_config vu_cmn.cu_config
|
||||
#define vu_softc vu_cmn.cu_softc
|
||||
|
||||
#define vu_stats link->stats
|
||||
#define vu_cur_pcr link->cur_pcr
|
||||
|
||||
/*
|
||||
* Netgraph to HARP API
|
||||
*/
|
||||
int vatmpif_harp_attach(node_p node);
|
||||
int vatmpif_harp_detach(node_p node);
|
||||
|
||||
int vatmpif_harp_recv_drain(Vatmpif_unit *vup, KBuffer *m,
|
||||
uint8_t vpi, uint16_t vci, uint8_t pt, uint8_t clp, Vatmpif_aal aal);
|
||||
|
||||
/*
|
||||
* HARP to Netgraph API
|
||||
*/
|
||||
int ng_atmpif_transmit(const priv_p priv, struct mbuf *m,
|
||||
uint8_t vpi, uint16_t vci, uint8_t pt, uint8_t clp, Vatmpif_aal aal);
|
||||
|
||||
extern uma_zone_t vatmpif_nif_zone;
|
||||
extern uma_zone_t vatmpif_vcc_zone;
|
||||
175
sys/netgraph/atm/ng_atmpif.h
Normal file
175
sys/netgraph/atm/ng_atmpif.h
Normal file
|
|
@ -0,0 +1,175 @@
|
|||
/*
|
||||
* Copyright (c) 2003 Harti Brandt.
|
||||
* Copyright (c) 2003 Vincent Jardin.
|
||||
* 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.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _NETGRAPH_ATM_NG_ATMPIF_H_
|
||||
#define _NETGRAPH_ATM_NG_ATMPIF_H_
|
||||
|
||||
/* Node type name and magic cookie */
|
||||
#define NG_ATMPIF_NODE_TYPE "atmpif"
|
||||
#define NGM_ATMPIF_COOKIE 967239456
|
||||
|
||||
/*
|
||||
* Physical device name - used to configure HARP devices
|
||||
*/
|
||||
#ifndef VATMPIF_DEV_NAME
|
||||
#define VATMPIF_DEV_NAME "hva" /* HARP Virtual ATM */
|
||||
#endif
|
||||
|
||||
#define VATMPIF_MAX_VCI 65535
|
||||
#define VATMPIF_MAX_VPI 255
|
||||
|
||||
/* Hook name */
|
||||
#define NG_ATMPIF_HOOK_LINK "link" /* virtual link hook */
|
||||
|
||||
/*
|
||||
* Node configuration structure
|
||||
*/
|
||||
struct ng_vatmpif_config {
|
||||
uint8_t debug; /* debug bit field (see below) */
|
||||
uint32_t pcr; /* peak cell rate */
|
||||
Mac_addr macaddr; /* Mac Address */
|
||||
};
|
||||
/* Keep this in sync with the above structure definition */
|
||||
#define NG_ATMPIF_CONFIG_TYPE_INFO { \
|
||||
{ "debug", &ng_parse_uint8_type }, \
|
||||
{ "pcr", &ng_parse_uint32_type }, \
|
||||
{ "macaddr", &ng_mac_addr_type }, \
|
||||
{ NULL } \
|
||||
}
|
||||
|
||||
/*
|
||||
* Debug bit-fields
|
||||
*/
|
||||
#define VATMPIF_DEBUG_NONE 0x00
|
||||
#define VATMPIF_DEBUG_PACKET 0x01 /* enable ng_atmpif debugging */
|
||||
|
||||
#define IS_VATMPIF_DEBUG_PACKET(a) ( (a) \
|
||||
&& ((a)->conf.debug & VATMPIF_DEBUG_PACKET) )
|
||||
|
||||
/*
|
||||
* Statistics
|
||||
*/
|
||||
struct hva_stats_ng {
|
||||
uint32_t ng_errseq; /* Duplicate or out of order */
|
||||
uint32_t ng_lostpdu; /* PDU lost detected */
|
||||
uint32_t ng_badpdu; /* Unknown PDU type */
|
||||
uint32_t ng_rx_novcc; /* Draining PDU on closed VCC */
|
||||
uint32_t ng_rx_iqfull; /* PDU drops, no room in atm_intrq */
|
||||
uint32_t ng_tx_rawcell; /* PDU raw cells transmitted */
|
||||
uint32_t ng_rx_rawcell; /* PDU raw cells received */
|
||||
uint64_t ng_tx_pdu; /* PDU transmitted */
|
||||
uint64_t ng_rx_pdu; /* PDU received */
|
||||
};
|
||||
typedef struct hva_stats_ng Hva_Stats_ng;
|
||||
/* Keep this in sync with the above structure definition */
|
||||
#define HVA_STATS_NG_TYPE_INFO \
|
||||
{ "errSeqOrder", &ng_parse_uint32_type }, \
|
||||
{ "errLostPDU", &ng_parse_uint32_type }, \
|
||||
{ "recvBadPDU", &ng_parse_uint32_type }, \
|
||||
{ "ErrATMVC", &ng_parse_uint32_type }, \
|
||||
{ "ErrQfull", &ng_parse_uint32_type }, \
|
||||
{ "xmitRawCell", &ng_parse_uint32_type }, \
|
||||
{ "recvRawCell", &ng_parse_uint32_type }, \
|
||||
{ "xmitPDU", &ng_parse_uint64_type }, \
|
||||
{ "recvPDU", &ng_parse_uint64_type },
|
||||
|
||||
|
||||
struct hva_stats_atm {
|
||||
uint64_t atm_xmit; /* Cells transmitted */
|
||||
uint64_t atm_rcvd; /* Cells received */
|
||||
};
|
||||
typedef struct hva_stats_atm Hva_Stats_atm;
|
||||
/* Keep this in sync with the above structure definition */
|
||||
#define HVA_STATS_ATM_NG_TYPE_INFO \
|
||||
{ "xmitATMCells", &ng_parse_uint64_type }, \
|
||||
{ "recvATMCells", &ng_parse_uint64_type },
|
||||
|
||||
struct hva_stats_aal5 {
|
||||
uint64_t aal5_xmit; /* Cells transmitted */
|
||||
uint64_t aal5_rcvd; /* Cells received */
|
||||
uint32_t aal5_crc_len; /* Cells with CRC/length errors */
|
||||
uint32_t aal5_drops; /* Cell drops */
|
||||
uint64_t aal5_pdu_xmit; /* CS PDUs transmitted */
|
||||
uint64_t aal5_pdu_rcvd; /* CS PDUs received */
|
||||
uint32_t aal5_pdu_crc; /* CS PDUs with CRC errors */
|
||||
uint32_t aal5_pdu_errs; /* CS layer protocol errors */
|
||||
uint32_t aal5_pdu_drops; /* CS PDUs dropped */
|
||||
};
|
||||
typedef struct hva_stats_aal5 Hva_Stats_aal5;
|
||||
/* Keep this in sync with the above structure definition */
|
||||
#define HVA_STATS_AAL5_NG_TYPE_INFO \
|
||||
{ "xmitAAL5Cells", &ng_parse_uint64_type }, \
|
||||
{ "recvAAL5Cells", &ng_parse_uint64_type }, \
|
||||
{ "AAL5ErrCRCCells", &ng_parse_uint32_type }, \
|
||||
{ "AAL5DropsCells", &ng_parse_uint32_type }, \
|
||||
{ "xmitAAL5PDU", &ng_parse_uint64_type }, \
|
||||
{ "recvAAL5PDU", &ng_parse_uint64_type }, \
|
||||
{ "AAL5CRCPDU", &ng_parse_uint32_type }, \
|
||||
{ "AAL5ErrPDU", &ng_parse_uint32_type }, \
|
||||
{ "AAL5DropsPDU", &ng_parse_uint32_type },
|
||||
|
||||
struct vatmpif_stats {
|
||||
Hva_Stats_ng hva_st_ng; /* Netgraph layer stats */
|
||||
Hva_Stats_atm hva_st_atm; /* ATM layer stats */
|
||||
Hva_Stats_aal5 hva_st_aal5; /* AAL5 layer stats */
|
||||
};
|
||||
typedef struct vatmpif_stats Vatmpif_stats;
|
||||
/* Keep this in sync with the above structure definition */
|
||||
#define NG_ATMPIF_STATS_TYPE_INFO { \
|
||||
HVA_STATS_NG_TYPE_INFO \
|
||||
HVA_STATS_ATM_NG_TYPE_INFO \
|
||||
HVA_STATS_AAL5_NG_TYPE_INFO \
|
||||
{ NULL } \
|
||||
}
|
||||
|
||||
/* Structure returned by NGM_ATMPIF_GET_LINK_STATUS */
|
||||
struct ng_atmpif_link_status {
|
||||
uint32_t InSeq; /* last received sequence number + 1 */
|
||||
uint32_t OutSeq; /* last sent sequence number */
|
||||
uint32_t cur_pcr; /* slot's reserved PCR */
|
||||
};
|
||||
/* Keep this in sync with the above structure definition */
|
||||
#define NG_ATMPIF_LINK_STATUS_TYPE_INFO { \
|
||||
{ "InSeq", &ng_parse_uint32_type }, \
|
||||
{ "OutSeq", &ng_parse_uint32_type }, \
|
||||
{ "cur_pcr", &ng_parse_uint32_type }, \
|
||||
{ NULL } \
|
||||
}
|
||||
|
||||
/* Netgraph control messages */
|
||||
enum {
|
||||
NGM_ATMPIF_SET_CONFIG = 1, /* set node configuration */
|
||||
NGM_ATMPIF_GET_CONFIG, /* get node configuration */
|
||||
NGM_ATMPIF_GET_LINK_STATUS, /* get link status */
|
||||
NGM_ATMPIF_GET_STATS, /* get link stats */
|
||||
NGM_ATMPIF_CLR_STATS, /* clear link stats */
|
||||
NGM_ATMPIF_GETCLR_STATS, /* atomically get & clear link stats */
|
||||
};
|
||||
|
||||
#endif /* _NETGRAPH_NG_ATMPIF_H_ */
|
||||
Loading…
Reference in a new issue