diff options
Diffstat (limited to 'sys/netgraph/atm/atmpif/ng_atmpif.c')
-rw-r--r-- | sys/netgraph/atm/atmpif/ng_atmpif.c | 706 |
1 files changed, 0 insertions, 706 deletions
diff --git a/sys/netgraph/atm/atmpif/ng_atmpif.c b/sys/netgraph/atm/atmpif/ng_atmpif.c deleted file mode 100644 index 23e39b9..0000000 --- a/sys/netgraph/atm/atmpif/ng_atmpif.c +++ /dev/null @@ -1,706 +0,0 @@ -/*- - * 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 = { - .version = NG_ABI_VERSION, - .name = NG_ATMPIF_NODE_TYPE, - .mod_event = ng_atmpif_mod_event, - .constructor = ng_atmpif_constructor, - .rcvmsg = ng_atmpif_rcvmsg, - .shutdown = ng_atmpif_rmnode, - .newhook = ng_atmpif_newhook, - .rcvdata = ng_atmpif_rcvdata, - .disconnect = ng_atmpif_disconnect, - .cmdlist = ng_atmpif_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); -} |