summaryrefslogtreecommitdiffstats
path: root/sys/netgraph
diff options
context:
space:
mode:
authorharti <harti@FreeBSD.org>2003-11-07 09:15:14 +0000
committerharti <harti@FreeBSD.org>2003-11-07 09:15:14 +0000
commitbc878862fbc4798e04c8409847d74f17bcdc12b3 (patch)
treef5b09f10560d3951b4cb234fbce157e740860b61 /sys/netgraph
parent95fb3f9279d63e253796f0b63d8130815a577112 (diff)
downloadFreeBSD-src-bc878862fbc4798e04c8409847d74f17bcdc12b3.zip
FreeBSD-src-bc878862fbc4798e04c8409847d74f17bcdc12b3.tar.gz
The layer 3 (signalling) of NgATM netgraph node: ng_uni. This node
handles user and network side signaling and partly PNNI.
Diffstat (limited to 'sys/netgraph')
-rw-r--r--sys/netgraph/atm/ng_uni.h119
-rw-r--r--sys/netgraph/atm/uni/ng_uni.c932
-rw-r--r--sys/netgraph/atm/uni/ng_uni_cust.h152
3 files changed, 1203 insertions, 0 deletions
diff --git a/sys/netgraph/atm/ng_uni.h b/sys/netgraph/atm/ng_uni.h
new file mode 100644
index 0000000..957f3ad
--- /dev/null
+++ b/sys/netgraph/atm/ng_uni.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2001-2003
+ * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
+ * All rights reserved.
+ *
+ * Author: Hartmut Brandt <harti@freebsd.org>
+ *
+ * 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$
+ *
+ * Netgraph module for UNI 4.0
+ */
+#ifndef _NETGRAPH_ATM_NG_UNI_H_
+#define _NETGRAPH_ATM_NG_UNI_H_
+
+#define NG_UNI_NODE_TYPE "uni"
+#define NGM_UNI_COOKIE 981112392
+
+enum {
+ NGM_UNI_GETDEBUG, /* get debug flags */
+ NGM_UNI_SETDEBUG, /* set debug flags */
+ NGM_UNI_GET_CONFIG, /* get configuration */
+ NGM_UNI_SET_CONFIG, /* set configuration */
+ NGM_UNI_ENABLE, /* enable processing */
+ NGM_UNI_DISABLE, /* free resources and disable */
+ NGM_UNI_GETSTATE, /* retrieve coord state */
+};
+
+struct ngm_uni_debug {
+ uint32_t level[UNI_MAXFACILITY];
+};
+#define NGM_UNI_DEBUGLEVEL_INFO { \
+ &ng_parse_uint32_type, \
+ UNI_MAXFACILITY \
+}
+#define NGM_UNI_DEBUG_INFO \
+ { \
+ { "level", &ng_uni_debuglevel_type }, \
+ { NULL } \
+ }
+
+#define NGM_UNI_CONFIG_INFO \
+ { \
+ { "proto", &ng_parse_uint32_type }, \
+ { "popt", &ng_parse_uint32_type }, \
+ { "option", &ng_parse_uint32_type }, \
+ { "timer301", &ng_parse_uint32_type }, \
+ { "timer303", &ng_parse_uint32_type }, \
+ { "init303", &ng_parse_uint32_type }, \
+ { "timer308", &ng_parse_uint32_type }, \
+ { "init308", &ng_parse_uint32_type }, \
+ { "timer309", &ng_parse_uint32_type }, \
+ { "timer310", &ng_parse_uint32_type }, \
+ { "timer313", &ng_parse_uint32_type }, \
+ { "timer316", &ng_parse_uint32_type }, \
+ { "init316", &ng_parse_uint32_type }, \
+ { "timer317", &ng_parse_uint32_type }, \
+ { "timer322", &ng_parse_uint32_type }, \
+ { "init322", &ng_parse_uint32_type }, \
+ { "timer397", &ng_parse_uint32_type }, \
+ { "timer398", &ng_parse_uint32_type }, \
+ { "timer399", &ng_parse_uint32_type }, \
+ { NULL } \
+ }
+
+struct ngm_uni_config_mask {
+ uint32_t mask;
+ uint32_t popt_mask;
+ uint32_t option_mask;
+};
+#define NGM_UNI_CONFIG_MASK_INFO \
+ { \
+ { "mask", &ng_parse_hint32_type }, \
+ { "popt_mask", &ng_parse_hint32_type }, \
+ { "option_mask", &ng_parse_hint32_type }, \
+ { NULL } \
+ }
+
+struct ngm_uni_set_config {
+ struct uni_config config;
+ struct ngm_uni_config_mask mask;
+};
+#define NGM_UNI_SET_CONFIG_INFO \
+ { \
+ { "config", &ng_uni_config_type }, \
+ { "mask", &ng_uni_config_mask_type }, \
+ { NULL } \
+ }
+
+/*
+ * API message
+ */
+struct uni_arg {
+ uint32_t sig;
+ uint32_t cookie;
+ u_char data[];
+};
+
+#endif
diff --git a/sys/netgraph/atm/uni/ng_uni.c b/sys/netgraph/atm/uni/ng_uni.c
new file mode 100644
index 0000000..c6b6113
--- /dev/null
+++ b/sys/netgraph/atm/uni/ng_uni.c
@@ -0,0 +1,932 @@
+/*
+ * Copyright (c) 2001-2003
+ * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
+ * All rights reserved.
+ *
+ * Author: Hartmut Brandt <harti@freebsd.org>
+ *
+ * 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.
+ *
+ * Netgraph module for ATM-Forum UNI 4.0 signalling
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/errno.h>
+#include <sys/syslog.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/callout.h>
+#include <sys/sbuf.h>
+#include <machine/stdarg.h>
+
+#include <netgraph/ng_message.h>
+#include <netgraph/netgraph.h>
+#include <netgraph/ng_parse.h>
+#include <netnatm/unimsg.h>
+#include <netnatm/msg/unistruct.h>
+#include <netgraph/atm/ngatmbase.h>
+#include <netnatm/saal/sscopdef.h>
+#include <netnatm/saal/sscfudef.h>
+#include <netgraph/atm/uni/ng_uni_cust.h>
+#include <netnatm/sig/uni.h>
+#include <netnatm/sig/unisig.h>
+#include <netgraph/atm/ng_sscop.h>
+#include <netgraph/atm/ng_sscfu.h>
+#include <netgraph/atm/ng_uni.h>
+
+MALLOC_DEFINE(M_NG_UNI, "netgraph_uni", "netgraph uni node");
+MALLOC_DEFINE(M_UNI, "netgraph uni", "uni protocol data");
+
+MODULE_DEPEND(ng_uni, ngatmbase, 1, 1, 1);
+
+/*
+ * Private node data
+ */
+struct priv {
+ hook_p upper;
+ hook_p lower;
+ struct uni *uni;
+ int enabled;
+};
+
+/* UNI CONFIG MASK */
+static const struct ng_parse_struct_field ng_uni_config_mask_type_info[] =
+ NGM_UNI_CONFIG_MASK_INFO;
+static const struct ng_parse_type ng_uni_config_mask_type = {
+ &ng_parse_struct_type,
+ ng_uni_config_mask_type_info
+};
+
+/* UNI_CONFIG */
+static const struct ng_parse_struct_field ng_uni_config_type_info[] =
+ NGM_UNI_CONFIG_INFO;
+static const struct ng_parse_type ng_uni_config_type = {
+ &ng_parse_struct_type,
+ ng_uni_config_type_info
+};
+
+/* SET CONFIG */
+static const struct ng_parse_struct_field ng_uni_set_config_type_info[] =
+ NGM_UNI_SET_CONFIG_INFO;
+static const struct ng_parse_type ng_uni_set_config_type = {
+ &ng_parse_struct_type,
+ ng_uni_set_config_type_info
+};
+
+/*
+ * Parse DEBUG
+ */
+static const struct ng_parse_fixedarray_info ng_uni_debuglevel_type_info =
+ NGM_UNI_DEBUGLEVEL_INFO;
+static const struct ng_parse_type ng_uni_debuglevel_type = {
+ &ng_parse_fixedarray_type,
+ &ng_uni_debuglevel_type_info
+};
+static const struct ng_parse_struct_field ng_uni_debug_type_info[] =
+ NGM_UNI_DEBUG_INFO;
+static const struct ng_parse_type ng_uni_debug_type = {
+ &ng_parse_struct_type,
+ ng_uni_debug_type_info
+};
+
+/*
+ * Command list
+ */
+static const struct ng_cmdlist ng_uni_cmdlist[] = {
+ {
+ NGM_UNI_COOKIE,
+ NGM_UNI_GETDEBUG,
+ "getdebug",
+ NULL,
+ &ng_uni_debug_type
+ },
+ {
+ NGM_UNI_COOKIE,
+ NGM_UNI_SETDEBUG,
+ "setdebug",
+ &ng_uni_debug_type,
+ NULL
+ },
+ {
+ NGM_UNI_COOKIE,
+ NGM_UNI_GET_CONFIG,
+ "get_config",
+ NULL,
+ &ng_uni_config_type
+ },
+ {
+ NGM_UNI_COOKIE,
+ NGM_UNI_SET_CONFIG,
+ "set_config",
+ &ng_uni_set_config_type,
+ &ng_uni_config_mask_type,
+ },
+ {
+ NGM_UNI_COOKIE,
+ NGM_UNI_ENABLE,
+ "enable",
+ NULL,
+ NULL,
+ },
+ {
+ NGM_UNI_COOKIE,
+ NGM_UNI_DISABLE,
+ "disable",
+ NULL,
+ NULL,
+ },
+ {
+ NGM_UNI_COOKIE,
+ NGM_UNI_GETSTATE,
+ "getstate",
+ NULL,
+ &ng_parse_uint32_type
+ },
+ { 0 }
+};
+
+/*
+ * Netgraph module data
+ */
+static ng_constructor_t ng_uni_constructor;
+static ng_shutdown_t ng_uni_shutdown;
+static ng_rcvmsg_t ng_uni_rcvmsg;
+static ng_newhook_t ng_uni_newhook;
+static ng_disconnect_t ng_uni_disconnect;
+static ng_rcvdata_t ng_uni_rcvlower;
+static ng_rcvdata_t ng_uni_rcvupper;
+
+static int ng_uni_mod_event(module_t, int, void *);
+
+static struct ng_type ng_uni_typestruct = {
+ NG_ABI_VERSION,
+ NG_UNI_NODE_TYPE,
+ ng_uni_mod_event, /* Module event handler (optional) */
+ ng_uni_constructor, /* Node constructor */
+ ng_uni_rcvmsg, /* control messages come here */
+ ng_uni_shutdown, /* reset, and free resources */
+ ng_uni_newhook, /* first notification of new hook */
+ NULL, /* findhook */
+ NULL, /* connect */
+ ng_uni_rcvlower, /* rcvdata */
+ ng_uni_disconnect, /* notify on disconnect */
+ ng_uni_cmdlist,
+};
+NETGRAPH_INIT(uni, &ng_uni_typestruct);
+
+static void uni_uni_output(struct uni *, void *, enum uni_sig, u_int32_t,
+ struct uni_msg *);
+static void uni_saal_output(struct uni *, void *, enum saal_sig,
+ struct uni_msg *);
+static void uni_verbose(struct uni *, void *, u_int, const char *, ...)
+ __printflike(4, 5);
+static void uni_do_status(struct uni *, void *, void *, const char *, ...)
+ __printflike(4, 5);
+
+static const struct uni_funcs uni_funcs = {
+ uni_uni_output,
+ uni_saal_output,
+ uni_verbose,
+ uni_do_status
+};
+
+/************************************************************/
+/*
+ * NODE MANAGEMENT
+ */
+static int
+ng_uni_constructor(node_p node)
+{
+ struct priv *priv;
+
+ if ((priv = malloc(sizeof(*priv), M_NG_UNI, M_NOWAIT | M_ZERO)) == NULL)
+ return (ENOMEM);
+
+ if ((priv->uni = uni_create(node, &uni_funcs)) == NULL) {
+ free(priv, M_NG_UNI);
+ return (ENOMEM);
+ }
+
+ NG_NODE_SET_PRIVATE(node, priv);
+ NG_NODE_FORCE_WRITER(node);
+
+ return (0);
+}
+
+static int
+ng_uni_shutdown(node_p node)
+{
+ struct priv *priv = NG_NODE_PRIVATE(node);
+
+ uni_destroy(priv->uni);
+
+ free(priv, M_NG_UNI);
+ NG_NODE_SET_PRIVATE(node, NULL);
+
+ NG_NODE_UNREF(node);
+
+ return (0);
+}
+
+/************************************************************/
+/*
+ * CONTROL MESSAGES
+ */
+static void
+uni_do_status(struct uni *uni, void *uarg, void *sbuf, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ sbuf_printf(sbuf, fmt, ap);
+ va_end(ap);
+}
+
+static int
+text_status(node_p node, struct priv *priv, char *buf, u_int len)
+{
+ struct sbuf sbuf;
+ u_int f;
+
+ sbuf_new(&sbuf, buf, len, 0);
+
+ if (priv->lower != NULL)
+ sbuf_printf(&sbuf, "lower hook: connected to %s:%s\n",
+ NG_NODE_NAME(NG_HOOK_NODE(NG_HOOK_PEER(priv->lower))),
+ NG_HOOK_NAME(NG_HOOK_PEER(priv->lower)));
+ else
+ sbuf_printf(&sbuf, "lower hook: <not connected>\n");
+
+ if (priv->upper != NULL)
+ sbuf_printf(&sbuf, "upper hook: connected to %s:%s\n",
+ NG_NODE_NAME(NG_HOOK_NODE(NG_HOOK_PEER(priv->upper))),
+ NG_HOOK_NAME(NG_HOOK_PEER(priv->upper)));
+ else
+ sbuf_printf(&sbuf, "upper hook: <not connected>\n");
+
+ sbuf_printf(&sbuf, "debugging:");
+ for (f = 0; f < UNI_MAXFACILITY; f++)
+ if (uni_get_debug(priv->uni, f) != 0)
+ sbuf_printf(&sbuf, " %s=%u", uni_facname(f),
+ uni_get_debug(priv->uni, f));
+ sbuf_printf(&sbuf, "\n");
+
+ if (priv->uni)
+ uni_status(priv->uni, &sbuf);
+
+ sbuf_finish(&sbuf);
+ return (sbuf_len(&sbuf));
+}
+
+static int
+ng_uni_rcvmsg(node_p node, item_p item, hook_p lasthook)
+{
+ struct priv *priv = NG_NODE_PRIVATE(node);
+ struct ng_mesg *resp = NULL;
+ struct ng_mesg *msg;
+ int error = 0;
+ u_int i;
+
+ NGI_GET_MSG(item, msg);
+
+ switch (msg->header.typecookie) {
+
+ case NGM_GENERIC_COOKIE:
+ switch (msg->header.cmd) {
+
+ case NGM_TEXT_STATUS:
+ NG_MKRESPONSE(resp, msg, NG_TEXTRESPONSE, M_NOWAIT);
+ if (resp == NULL) {
+ error = ENOMEM;
+ break;
+ }
+
+ resp->header.arglen = text_status(node, priv,
+ (char *)resp->data, resp->header.arglen) + 1;
+ break;
+
+ default:
+ error = EINVAL;
+ break;
+ }
+ break;
+
+ case NGM_UNI_COOKIE:
+ switch (msg->header.cmd) {
+
+ case NGM_UNI_SETDEBUG:
+ {
+ struct ngm_uni_debug *arg;
+
+ if (msg->header.arglen > sizeof(*arg)) {
+ error = EINVAL;
+ break;
+ }
+ arg = (struct ngm_uni_debug *)msg->data;
+ for (i = 0; i < UNI_MAXFACILITY; i++)
+ uni_set_debug(priv->uni, i, arg->level[i]);
+ break;
+ }
+
+ case NGM_UNI_GETDEBUG:
+ {
+ struct ngm_uni_debug *arg;
+
+ NG_MKRESPONSE(resp, msg, sizeof(*arg), M_NOWAIT);
+ if(resp == NULL) {
+ error = ENOMEM;
+ break;
+ }
+ arg = (struct ngm_uni_debug *)resp->data;
+ for (i = 0; i < UNI_MAXFACILITY; i++)
+ arg->level[i] = uni_get_debug(priv->uni, i);
+ break;
+ }
+
+ case NGM_UNI_GET_CONFIG:
+ {
+ struct uni_config *config;
+
+ if (msg->header.arglen != 0) {
+ error = EINVAL;
+ break;
+ }
+ NG_MKRESPONSE(resp, msg, sizeof(*config), M_NOWAIT);
+ if (resp == NULL) {
+ error = ENOMEM;
+ break;
+ }
+ config = (struct uni_config *)resp->data;
+ uni_get_config(priv->uni, config);
+
+ break;
+ }
+
+ case NGM_UNI_SET_CONFIG:
+ {
+ struct ngm_uni_set_config *arg;
+ struct ngm_uni_config_mask *mask;
+
+ if (msg->header.arglen != sizeof(*arg)) {
+ error = EINVAL;
+ break;
+ }
+ arg = (struct ngm_uni_set_config *)msg->data;
+
+ NG_MKRESPONSE(resp, msg, sizeof(*mask), M_NOWAIT);
+ if (resp == NULL) {
+ error = ENOMEM;
+ break;
+ }
+ mask = (struct ngm_uni_config_mask *)resp->data;
+
+ *mask = arg->mask;
+
+ uni_set_config(priv->uni, &arg->config,
+ &mask->mask, &mask->popt_mask, &mask->option_mask);
+
+ break;
+ }
+
+ case NGM_UNI_ENABLE:
+ if (msg->header.arglen != 0) {
+ error = EINVAL;
+ break;
+ }
+ if (priv->enabled) {
+ error = EISCONN;
+ break;
+ }
+ priv->enabled = 1;
+ break;
+
+ case NGM_UNI_DISABLE:
+ if (msg->header.arglen != 0) {
+ error = EINVAL;
+ break;
+ }
+ if (!priv->enabled) {
+ error = ENOTCONN;
+ break;
+ }
+ priv->enabled = 0;
+ uni_reset(priv->uni);
+ break;
+
+ case NGM_UNI_GETSTATE:
+ if (msg->header.arglen != 0) {
+ error = EINVAL;
+ break;
+ }
+ NG_MKRESPONSE(resp, msg, sizeof(u_int32_t), M_NOWAIT);
+ if(resp == NULL) {
+ error = ENOMEM;
+ break;
+ }
+ *(u_int32_t *)resp->data =
+ priv->enabled ? (uni_getcustate(priv->uni) + 1)
+ : 0;
+ break;
+
+ default:
+ error = EINVAL;
+ break;
+ }
+ break;
+
+ default:
+ error = EINVAL;
+ break;
+ }
+
+ NG_RESPOND_MSG(error, node, item, resp);
+ NG_FREE_MSG(msg);
+ return (error);
+}
+
+/************************************************************/
+/*
+ * HOOK MANAGEMENT
+ */
+static int
+ng_uni_newhook(node_p node, hook_p hook, const char *name)
+{
+ struct priv *priv = NG_NODE_PRIVATE(node);
+
+ if (strcmp(name, "lower") == 0) {
+ priv->lower = hook;
+ } else if(strcmp(name, "upper") == 0) {
+ priv->upper = hook;
+ NG_HOOK_SET_RCVDATA(hook, ng_uni_rcvupper);
+ } else
+ return EINVAL;
+
+ return 0;
+}
+
+static int
+ng_uni_disconnect(hook_p hook)
+{
+ node_p node = NG_HOOK_NODE(hook);
+ struct priv *priv = NG_NODE_PRIVATE(node);
+
+ if(hook == priv->lower)
+ priv->lower = NULL;
+ else if(hook == priv->upper)
+ priv->upper = NULL;
+ else
+ printf("%s: bogus hook %s\n", __FUNCTION__, NG_HOOK_NAME(hook));
+
+ if (NG_NODE_NUMHOOKS(node) == 0) {
+ if (NG_NODE_IS_VALID(node))
+ ng_rmnode_self(node);
+ }
+
+ return (0);
+}
+
+/************************************************************/
+/*
+ * DATA
+ */
+/*
+ * Receive signal from USER.
+ *
+ * Repackage the data into one large buffer.
+ */
+static int
+ng_uni_rcvupper(hook_p hook, item_p item)
+{
+ node_p node = NG_HOOK_NODE(hook);
+ struct priv *priv = NG_NODE_PRIVATE(node);
+ struct mbuf *m;
+ struct uni_arg arg;
+ struct uni_msg *msg;
+ int error;
+
+ if (!priv->enabled) {
+ NG_FREE_ITEM(item);
+ return (ENOTCONN);
+ }
+
+ NGI_GET_M(item, m);
+ NG_FREE_ITEM(item);
+
+ if ((error = uni_msg_unpack_mbuf(m, &msg)) != 0) {
+ m_freem(m);
+ return (error);
+ }
+ m_freem(m);
+
+ if (uni_msg_len(msg) < sizeof(arg)) {
+ printf("%s: packet too short\n", __FUNCTION__);
+ uni_msg_destroy(msg);
+ return (EINVAL);
+ }
+
+ bcopy(msg->b_rptr, &arg, sizeof(arg));
+ msg->b_rptr += sizeof(arg);
+
+ if (arg.sig >= UNIAPI_MAXSIG) {
+ printf("%s: bogus signal\n", __FUNCTION__);
+ uni_msg_destroy(msg);
+ return (EINVAL);
+ }
+ uni_uni_input(priv->uni, arg.sig, arg.cookie, msg);
+ uni_work(priv->uni);
+
+ return (0);
+}
+
+
+/*
+ * Upper layer signal from UNI
+ */
+static void
+uni_uni_output(struct uni *uni, void *varg, enum uni_sig sig, u_int32_t cookie,
+ struct uni_msg *msg)
+{
+ node_p node = (node_p)varg;
+ struct priv *priv = NG_NODE_PRIVATE(node);
+ struct mbuf *m;
+ struct uni_arg arg;
+ int error;
+
+ if (priv->upper == NULL) {
+ if (msg != NULL)
+ uni_msg_destroy(msg);
+ return;
+ }
+ arg.sig = sig;
+ arg.cookie = cookie;
+
+ m = uni_msg_pack_mbuf(msg, &arg, sizeof(arg));
+ if (msg != NULL)
+ uni_msg_destroy(msg);
+ if (m == NULL)
+ return;
+
+ NG_SEND_DATA_ONLY(error, priv->upper, m);
+}
+
+
+static void
+dump_uni_msg(struct uni_msg *msg)
+{
+ u_int pos;
+
+ for (pos = 0; pos < uni_msg_len(msg); pos++) {
+ if (pos % 16 == 0)
+ printf("%06o ", pos);
+ if (pos % 16 == 8)
+ printf(" ");
+ printf(" %02x", msg->b_rptr[pos]);
+ if (pos % 16 == 15)
+ printf("\n");
+ }
+ if (pos % 16 != 0)
+ printf("\n");
+}
+
+
+/*
+ * Dump a SAAL signal in either direction
+ */
+static void
+dump_saal_signal(node_p node, enum saal_sig sig, struct uni_msg *msg, int to)
+{
+ struct priv *priv = NG_NODE_PRIVATE(node);
+
+ printf("signal %s SAAL: ", to ? "to" : "from");
+
+ switch (sig) {
+
+#define D(S) case S: printf("%s", #S); break
+
+ D(SAAL_ESTABLISH_request);
+ D(SAAL_ESTABLISH_indication);
+ D(SAAL_ESTABLISH_confirm);
+ D(SAAL_RELEASE_request);
+ D(SAAL_RELEASE_confirm);
+ D(SAAL_RELEASE_indication);
+ D(SAAL_DATA_request);
+ D(SAAL_DATA_indication);
+ D(SAAL_UDATA_request);
+ D(SAAL_UDATA_indication);
+
+#undef D
+ default:
+ printf("sig=%d", sig); break;
+ }
+ if (msg != NULL) {
+ printf(" data=%zu\n", uni_msg_len(msg));
+ if (uni_get_debug(priv->uni, UNI_FAC_SAAL) > 1)
+ dump_uni_msg(msg);
+ } else
+ printf("\n");
+}
+
+/*
+ * Receive signal from SSCOP.
+ *
+ * If this is a data signal, repackage the data into one large buffer.
+ * UNI shouldn't be the bottleneck in a system and this greatly simplifies
+ * parsing in UNI.
+ */
+static int
+ng_uni_rcvlower(hook_p hook __unused, item_p item)
+{
+ node_p node = NG_HOOK_NODE(hook);
+ struct priv *priv = NG_NODE_PRIVATE(node);
+ struct mbuf *m;
+ struct sscfu_arg arg;
+ struct uni_msg *msg;
+ int error;
+
+ if (!priv->enabled) {
+ NG_FREE_ITEM(item);
+ return (ENOTCONN);
+ }
+
+ NGI_GET_M(item, m);
+ NG_FREE_ITEM(item);
+
+ if ((error = uni_msg_unpack_mbuf(m, &msg)) != 0) {
+ m_freem(m);
+ return (error);
+ }
+ m_freem(m);
+
+ if (uni_msg_len(msg) < sizeof(arg)) {
+ uni_msg_destroy(msg);
+ printf("%s: packet too short\n", __FUNCTION__);
+ return (EINVAL);
+ }
+ bcopy(msg->b_rptr, &arg, sizeof(arg));
+ msg->b_rptr += sizeof(arg);
+
+ if (arg.sig > SAAL_UDATA_indication) {
+ uni_msg_destroy(msg);
+ printf("%s: bogus signal\n", __FUNCTION__);
+ return (EINVAL);
+ }
+
+ if (uni_get_debug(priv->uni, UNI_FAC_SAAL) > 0)
+ dump_saal_signal(node, arg.sig, msg, 0);
+
+ uni_saal_input(priv->uni, arg.sig, msg);
+ uni_work(priv->uni);
+
+ return (0);
+}
+
+/*
+ * Send signal to sscop.
+ * Pack the message into an mbuf chain.
+ */
+static void
+uni_saal_output(struct uni *uni, void *varg, enum saal_sig sig, struct uni_msg *msg)
+{
+ node_p node = (node_p)varg;
+ struct priv *priv = NG_NODE_PRIVATE(node);
+ struct mbuf *m;
+ struct sscfu_arg arg;
+ int error;
+
+ if (uni_get_debug(priv->uni, UNI_FAC_SAAL) > 0)
+ dump_saal_signal(node, sig, msg, 1);
+
+ if (priv->lower == NULL) {
+ if (msg != NULL)
+ uni_msg_destroy(msg);
+ return;
+ }
+
+ arg.sig = sig;
+
+ m = uni_msg_pack_mbuf(msg, &arg, sizeof(arg));
+ if (msg != NULL)
+ uni_msg_destroy(msg);
+ if (m == NULL)
+ return;
+
+ NG_SEND_DATA_ONLY(error, priv->lower, m);
+}
+
+static void
+uni_verbose(struct uni *uni, void *varg, u_int fac, const char *fmt, ...)
+{
+ va_list ap;
+
+ static char *facnames[] = {
+#define UNI_DEBUG_DEFINE(D) [UNI_FAC_##D] #D,
+ UNI_DEBUG_FACILITIES
+#undef UNI_DEBUG_DEFINE
+ };
+
+ printf("%s: ", facnames[fac]);
+
+ va_start(ap, fmt);
+ vprintf(fmt, ap);
+ va_end(ap);
+
+ printf("\n");
+}
+
+
+/************************************************************/
+/*
+ * Memory debugging
+ */
+struct unimem_debug {
+ const char *file;
+ u_int lno;
+ LIST_ENTRY(unimem_debug) link;
+ char data[0];
+};
+LIST_HEAD(unimem_debug_list, unimem_debug);
+
+static struct unimem_debug_list nguni_freemem[UNIMEM_TYPES] = {
+ LIST_HEAD_INITIALIZER(unimem_debug),
+ LIST_HEAD_INITIALIZER(unimem_debug),
+ LIST_HEAD_INITIALIZER(unimem_debug),
+ LIST_HEAD_INITIALIZER(unimem_debug),
+ LIST_HEAD_INITIALIZER(unimem_debug),
+};
+static struct unimem_debug_list nguni_usedmem[UNIMEM_TYPES] = {
+ LIST_HEAD_INITIALIZER(unimem_debug),
+ LIST_HEAD_INITIALIZER(unimem_debug),
+ LIST_HEAD_INITIALIZER(unimem_debug),
+ LIST_HEAD_INITIALIZER(unimem_debug),
+ LIST_HEAD_INITIALIZER(unimem_debug),
+};
+
+static struct mtx nguni_unilist_mtx;
+
+static const char *unimem_names[UNIMEM_TYPES] = {
+ "instance",
+ "all",
+ "signal",
+ "call",
+ "party"
+};
+
+static void
+uni_init(void)
+{
+ mtx_init(&nguni_unilist_mtx, "netgraph UNI structure lists", NULL, 0);
+}
+
+static void
+uni_fini(void)
+{
+ u_int type;
+ struct unimem_debug *h;
+
+ for (type = 0; type < UNIMEM_TYPES; type++) {
+ while ((h = LIST_FIRST(&nguni_freemem[type])) != NULL) {
+ LIST_REMOVE(h, link);
+ free(h, M_UNI);
+ }
+
+ while ((h = LIST_FIRST(&nguni_usedmem[type])) != NULL) {
+ LIST_REMOVE(h, link);
+ printf("ng_uni: %s in use: %p (%s,%u)\n",
+ unimem_names[type], (caddr_t)h->data,
+ h->file, h->lno);
+ free(h, M_UNI);
+ }
+ }
+
+ mtx_destroy(&nguni_unilist_mtx);
+}
+
+/*
+ * Allocate a chunk of memory from a given type.
+ */
+void *
+ng_uni_malloc(enum unimem type, const char *file, u_int lno)
+{
+ struct unimem_debug *d;
+ size_t full;
+
+ /*
+ * Try to allocate
+ */
+ mtx_lock(&nguni_unilist_mtx);
+ if ((d = LIST_FIRST(&nguni_freemem[type])) != NULL)
+ LIST_REMOVE(d, link);
+ mtx_unlock(&nguni_unilist_mtx);
+
+ if (d == NULL) {
+ /*
+ * allocate
+ */
+ full = unimem_sizes[type] + offsetof(struct unimem_debug, data);
+ if ((d = malloc(full, M_UNI, M_NOWAIT | M_ZERO)) == NULL)
+ return (NULL);
+ } else {
+ bzero(d->data, unimem_sizes[type]);
+ }
+ d->file = file;
+ d->lno = lno;
+
+ mtx_lock(&nguni_unilist_mtx);
+ LIST_INSERT_HEAD(&nguni_usedmem[type], d, link);
+ mtx_unlock(&nguni_unilist_mtx);
+ return (d->data);
+}
+
+void
+ng_uni_free(enum unimem type, void *ptr, const char *file, u_int lno)
+{
+ struct unimem_debug *d, *h;
+
+ d = (struct unimem_debug *)
+ ((char *)ptr - offsetof(struct unimem_debug, data));
+
+ mtx_lock(&nguni_unilist_mtx);
+
+ LIST_FOREACH(h, &nguni_usedmem[type], link)
+ if (d == h)
+ break;
+
+ if (h != NULL) {
+ LIST_REMOVE(d, link);
+ LIST_INSERT_HEAD(&nguni_freemem[type], d, link);
+ } else {
+ /*
+ * Not on used list - try free list.
+ */
+ LIST_FOREACH(h, &nguni_freemem[type], link)
+ if (d == h)
+ break;
+ if (h == NULL)
+ printf("ng_uni: %s,%u: %p(%s) was never allocated\n",
+ file, lno, ptr, unimem_names[type]);
+ else
+ printf("ng_uni: %s,%u: %p(%s) was already destroyed "
+ "in %s,%u\n",
+ file, lno, ptr, unimem_names[type],
+ h->file, h->lno);
+ }
+ mtx_unlock(&nguni_unilist_mtx);
+}
+/************************************************************/
+/*
+ * INITIALISATION
+ */
+
+/*
+ * Loading and unloading of node type
+ */
+static int
+ng_uni_mod_event(module_t mod, int event, void *data)
+{
+ int s;
+ int error = 0;
+
+ s = splnet();
+ switch(event) {
+
+ case MOD_LOAD:
+ uni_init();
+ break;
+
+ case MOD_UNLOAD:
+ uni_fini();
+ break;
+
+ default:
+ error = EOPNOTSUPP;
+ break;
+ }
+ splx(s);
+ return (error);
+}
diff --git a/sys/netgraph/atm/uni/ng_uni_cust.h b/sys/netgraph/atm/uni/ng_uni_cust.h
new file mode 100644
index 0000000..84e63e8
--- /dev/null
+++ b/sys/netgraph/atm/uni/ng_uni_cust.h
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2001-2003
+ * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
+ * All rights reserved.
+ *
+ * Author: Hartmut Brandt <harti@freebsd.org>
+ *
+ * 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.
+ *
+ * Customisation of signalling source to the NG environment.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/queue.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <netgraph/ng_message.h>
+#include <netgraph/netgraph.h>
+#include <netgraph/atm/ngatmbase.h>
+
+#define ASSERT(E, M) KASSERT(E,M)
+
+/*
+ * Memory
+ */
+enum unimem {
+ UNIMEM_INS = 0,
+ UNIMEM_ALL,
+ UNIMEM_SIG,
+ UNIMEM_CALL,
+ UNIMEM_PARTY,
+};
+#define UNIMEM_TYPES 5
+
+void *ng_uni_malloc(enum unimem, const char *, u_int);
+void ng_uni_free(enum unimem, void *, const char *, u_int);
+
+#define INS_ALLOC() ng_uni_malloc(UNIMEM_INS, __FILE__, __LINE__)
+#define INS_FREE(P) ng_uni_free(UNIMEM_INS, P, __FILE__, __LINE__)
+
+#define UNI_ALLOC() ng_uni_malloc(UNIMEM_ALL, __FILE__, __LINE__)
+#define UNI_FREE(P) ng_uni_free(UNIMEM_ALL, P, __FILE__, __LINE__)
+
+#define SIG_ALLOC() ng_uni_malloc(UNIMEM_SIG, __FILE__, __LINE__)
+#define SIG_FREE(P) ng_uni_free(UNIMEM_SIG, P, __FILE__, __LINE__)
+
+#define CALL_ALLOC() ng_uni_malloc(UNIMEM_CALL, __FILE__, __LINE__)
+#define CALL_FREE(P) ng_uni_free(UNIMEM_CALL, P, __FILE__, __LINE__)
+
+#define PARTY_ALLOC() ng_uni_malloc(UNIMEM_PARTY, __FILE__, __LINE__)
+#define PARTY_FREE(P) ng_uni_free(UNIMEM_PARTY, P, __FILE__, __LINE__)
+
+/*
+ * Timers
+ */
+struct uni_timer {
+ struct callout_handle c;
+};
+
+#define _TIMER_INIT(X,T) callout_handle_init(&(X)->T.c)
+#define _TIMER_DESTROY(UNI,FIELD) _TIMER_STOP(UNI,FIELD)
+#define _TIMER_STOP(UNI,FIELD) do { \
+ ng_untimeout(FIELD.c, (UNI)->arg); \
+ callout_handle_init(&FIELD.c); \
+ } while (0)
+#define TIMER_ISACT(UNI,T) ((UNI)->T.c.callout != NULL)
+#define _TIMER_START(UNI,ARG,FIELD,DUE,FUNC) do { \
+ _TIMER_STOP(UNI, FIELD); \
+ FIELD.c = ng_timeout((UNI)->arg, NULL, \
+ hz * (DUE) / 1000, FUNC, (ARG), 0); \
+ } while (0)
+
+#define TIMER_FUNC_UNI(T,F) \
+static void F(struct uni *); \
+static void \
+_##T##_func(node_p node, hook_p hook, void *arg1, int arg2) \
+{ \
+ struct uni *uni = (struct uni *)arg1; \
+ \
+ callout_handle_init(&uni->T.c); \
+ (F)(uni); \
+ uni_work(uni); \
+}
+
+/*
+ * Be careful: call may be invalid after the call to F
+ */
+#define TIMER_FUNC_CALL(T,F) \
+static void F(struct call *); \
+static void \
+_##T##_func(node_p node, hook_p hook, void *arg1, int arg2) \
+{ \
+ struct call *call = (struct call *)arg1; \
+ struct uni *uni = call->uni; \
+ \
+ callout_handle_init(&call->T.c); \
+ (F)(call); \
+ uni_work(uni); \
+}
+
+/*
+ * Be careful: call/party may be invalid after the call to F
+ */
+#define TIMER_FUNC_PARTY(T,F) \
+static void F(struct party *); \
+static void \
+_##T##_func(node_p node, hook_p hook, void *arg1, int arg2) \
+{ \
+ struct party *party = (struct party *)arg1; \
+ struct uni *uni = party->call->uni; \
+ \
+ callout_handle_init(&party->T.c); \
+ (F)(party); \
+ uni_work(uni); \
+}
+
+extern size_t unimem_sizes[UNIMEM_TYPES];
+
+#define UNICORE \
+size_t unimem_sizes[UNIMEM_TYPES] = { \
+ [UNIMEM_INS] sizeof(struct uni), \
+ [UNIMEM_ALL] sizeof(struct uni_all), \
+ [UNIMEM_SIG] sizeof(struct sig), \
+ [UNIMEM_CALL] sizeof(struct call), \
+ [UNIMEM_PARTY] sizeof(struct party) \
+};
+
+#define memmove(T, F, L) bcopy((F), (T), (L))
OpenPOWER on IntegriCloud