Vendor import of netgraph from FreeBSD-current 20080626
[dragonfly.git] / sys / netgraph7 / atm / uni / ng_uni.c
blob3eb0584ce1cf95f49154d9920f265a308a29eaf1
1 /*-
2 * Copyright (c) 2001-2003
3 * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
4 * All rights reserved.
6 * Author: Hartmut Brandt <harti@freebsd.org>
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
29 * Netgraph module for ATM-Forum UNI 4.0 signalling
32 #include <sys/cdefs.h>
33 __FBSDID("$FreeBSD: src/sys/netgraph/atm/uni/ng_uni.c,v 1.6 2005/10/31 15:41:26 rwatson Exp $");
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/kernel.h>
38 #include <sys/malloc.h>
39 #include <sys/mbuf.h>
40 #include <sys/errno.h>
41 #include <sys/syslog.h>
42 #include <sys/socket.h>
43 #include <sys/socketvar.h>
44 #include <sys/callout.h>
45 #include <sys/sbuf.h>
46 #include <machine/stdarg.h>
48 #include <netgraph/ng_message.h>
49 #include <netgraph/netgraph.h>
50 #include <netgraph/ng_parse.h>
51 #include <netnatm/unimsg.h>
52 #include <netnatm/msg/unistruct.h>
53 #include <netgraph/atm/ngatmbase.h>
54 #include <netnatm/saal/sscopdef.h>
55 #include <netnatm/saal/sscfudef.h>
56 #include <netgraph/atm/uni/ng_uni_cust.h>
57 #include <netnatm/sig/uni.h>
58 #include <netnatm/sig/unisig.h>
59 #include <netgraph/atm/ng_sscop.h>
60 #include <netgraph/atm/ng_sscfu.h>
61 #include <netgraph/atm/ng_uni.h>
63 MALLOC_DEFINE(M_NG_UNI, "netgraph_uni_node", "netgraph uni node");
64 MALLOC_DEFINE(M_UNI, "netgraph_uni_data", "uni protocol data");
66 MODULE_DEPEND(ng_uni, ngatmbase, 1, 1, 1);
69 * Private node data
71 struct priv {
72 hook_p upper;
73 hook_p lower;
74 struct uni *uni;
75 int enabled;
78 /* UNI CONFIG MASK */
79 static const struct ng_parse_struct_field ng_uni_config_mask_type_info[] =
80 NGM_UNI_CONFIG_MASK_INFO;
81 static const struct ng_parse_type ng_uni_config_mask_type = {
82 &ng_parse_struct_type,
83 ng_uni_config_mask_type_info
86 /* UNI_CONFIG */
87 static const struct ng_parse_struct_field ng_uni_config_type_info[] =
88 NGM_UNI_CONFIG_INFO;
89 static const struct ng_parse_type ng_uni_config_type = {
90 &ng_parse_struct_type,
91 ng_uni_config_type_info
94 /* SET CONFIG */
95 static const struct ng_parse_struct_field ng_uni_set_config_type_info[] =
96 NGM_UNI_SET_CONFIG_INFO;
97 static const struct ng_parse_type ng_uni_set_config_type = {
98 &ng_parse_struct_type,
99 ng_uni_set_config_type_info
103 * Parse DEBUG
105 static const struct ng_parse_fixedarray_info ng_uni_debuglevel_type_info =
106 NGM_UNI_DEBUGLEVEL_INFO;
107 static const struct ng_parse_type ng_uni_debuglevel_type = {
108 &ng_parse_fixedarray_type,
109 &ng_uni_debuglevel_type_info
111 static const struct ng_parse_struct_field ng_uni_debug_type_info[] =
112 NGM_UNI_DEBUG_INFO;
113 static const struct ng_parse_type ng_uni_debug_type = {
114 &ng_parse_struct_type,
115 ng_uni_debug_type_info
119 * Command list
121 static const struct ng_cmdlist ng_uni_cmdlist[] = {
123 NGM_UNI_COOKIE,
124 NGM_UNI_GETDEBUG,
125 "getdebug",
126 NULL,
127 &ng_uni_debug_type
130 NGM_UNI_COOKIE,
131 NGM_UNI_SETDEBUG,
132 "setdebug",
133 &ng_uni_debug_type,
134 NULL
137 NGM_UNI_COOKIE,
138 NGM_UNI_GET_CONFIG,
139 "get_config",
140 NULL,
141 &ng_uni_config_type
144 NGM_UNI_COOKIE,
145 NGM_UNI_SET_CONFIG,
146 "set_config",
147 &ng_uni_set_config_type,
148 &ng_uni_config_mask_type,
151 NGM_UNI_COOKIE,
152 NGM_UNI_ENABLE,
153 "enable",
154 NULL,
155 NULL,
158 NGM_UNI_COOKIE,
159 NGM_UNI_DISABLE,
160 "disable",
161 NULL,
162 NULL,
165 NGM_UNI_COOKIE,
166 NGM_UNI_GETSTATE,
167 "getstate",
168 NULL,
169 &ng_parse_uint32_type
171 { 0 }
175 * Netgraph module data
177 static ng_constructor_t ng_uni_constructor;
178 static ng_shutdown_t ng_uni_shutdown;
179 static ng_rcvmsg_t ng_uni_rcvmsg;
180 static ng_newhook_t ng_uni_newhook;
181 static ng_disconnect_t ng_uni_disconnect;
182 static ng_rcvdata_t ng_uni_rcvlower;
183 static ng_rcvdata_t ng_uni_rcvupper;
185 static int ng_uni_mod_event(module_t, int, void *);
187 static struct ng_type ng_uni_typestruct = {
188 .version = NG_ABI_VERSION,
189 .name = NG_UNI_NODE_TYPE,
190 .mod_event = ng_uni_mod_event,
191 .constructor = ng_uni_constructor,
192 .rcvmsg = ng_uni_rcvmsg,
193 .shutdown = ng_uni_shutdown,
194 .newhook = ng_uni_newhook,
195 .rcvdata = ng_uni_rcvlower,
196 .disconnect = ng_uni_disconnect,
197 .cmdlist = ng_uni_cmdlist,
199 NETGRAPH_INIT(uni, &ng_uni_typestruct);
201 static void uni_uni_output(struct uni *, void *, enum uni_sig, u_int32_t,
202 struct uni_msg *);
203 static void uni_saal_output(struct uni *, void *, enum saal_sig,
204 struct uni_msg *);
205 static void uni_verbose(struct uni *, void *, u_int, const char *, ...)
206 __printflike(4, 5);
207 static void uni_do_status(struct uni *, void *, void *, const char *, ...)
208 __printflike(4, 5);
210 static const struct uni_funcs uni_funcs = {
211 uni_uni_output,
212 uni_saal_output,
213 uni_verbose,
214 uni_do_status
217 /************************************************************/
219 * NODE MANAGEMENT
221 static int
222 ng_uni_constructor(node_p node)
224 struct priv *priv;
226 if ((priv = malloc(sizeof(*priv), M_NG_UNI, M_NOWAIT | M_ZERO)) == NULL)
227 return (ENOMEM);
229 if ((priv->uni = uni_create(node, &uni_funcs)) == NULL) {
230 free(priv, M_NG_UNI);
231 return (ENOMEM);
234 NG_NODE_SET_PRIVATE(node, priv);
235 NG_NODE_FORCE_WRITER(node);
237 return (0);
240 static int
241 ng_uni_shutdown(node_p node)
243 struct priv *priv = NG_NODE_PRIVATE(node);
245 uni_destroy(priv->uni);
247 free(priv, M_NG_UNI);
248 NG_NODE_SET_PRIVATE(node, NULL);
250 NG_NODE_UNREF(node);
252 return (0);
255 /************************************************************/
257 * CONTROL MESSAGES
259 static void
260 uni_do_status(struct uni *uni, void *uarg, void *sbuf, const char *fmt, ...)
262 va_list ap;
264 va_start(ap, fmt);
265 sbuf_printf(sbuf, fmt, ap);
266 va_end(ap);
269 static int
270 text_status(node_p node, struct priv *priv, char *buf, u_int len)
272 struct sbuf sbuf;
273 u_int f;
275 sbuf_new(&sbuf, buf, len, 0);
277 if (priv->lower != NULL)
278 sbuf_printf(&sbuf, "lower hook: connected to %s:%s\n",
279 NG_NODE_NAME(NG_HOOK_NODE(NG_HOOK_PEER(priv->lower))),
280 NG_HOOK_NAME(NG_HOOK_PEER(priv->lower)));
281 else
282 sbuf_printf(&sbuf, "lower hook: <not connected>\n");
284 if (priv->upper != NULL)
285 sbuf_printf(&sbuf, "upper hook: connected to %s:%s\n",
286 NG_NODE_NAME(NG_HOOK_NODE(NG_HOOK_PEER(priv->upper))),
287 NG_HOOK_NAME(NG_HOOK_PEER(priv->upper)));
288 else
289 sbuf_printf(&sbuf, "upper hook: <not connected>\n");
291 sbuf_printf(&sbuf, "debugging:");
292 for (f = 0; f < UNI_MAXFACILITY; f++)
293 if (uni_get_debug(priv->uni, f) != 0)
294 sbuf_printf(&sbuf, " %s=%u", uni_facname(f),
295 uni_get_debug(priv->uni, f));
296 sbuf_printf(&sbuf, "\n");
298 if (priv->uni)
299 uni_status(priv->uni, &sbuf);
301 sbuf_finish(&sbuf);
302 return (sbuf_len(&sbuf));
305 static int
306 ng_uni_rcvmsg(node_p node, item_p item, hook_p lasthook)
308 struct priv *priv = NG_NODE_PRIVATE(node);
309 struct ng_mesg *resp = NULL;
310 struct ng_mesg *msg;
311 int error = 0;
312 u_int i;
314 NGI_GET_MSG(item, msg);
316 switch (msg->header.typecookie) {
318 case NGM_GENERIC_COOKIE:
319 switch (msg->header.cmd) {
321 case NGM_TEXT_STATUS:
322 NG_MKRESPONSE(resp, msg, NG_TEXTRESPONSE, M_NOWAIT);
323 if (resp == NULL) {
324 error = ENOMEM;
325 break;
328 resp->header.arglen = text_status(node, priv,
329 (char *)resp->data, resp->header.arglen) + 1;
330 break;
332 default:
333 error = EINVAL;
334 break;
336 break;
338 case NGM_UNI_COOKIE:
339 switch (msg->header.cmd) {
341 case NGM_UNI_SETDEBUG:
343 struct ngm_uni_debug *arg;
345 if (msg->header.arglen > sizeof(*arg)) {
346 error = EINVAL;
347 break;
349 arg = (struct ngm_uni_debug *)msg->data;
350 for (i = 0; i < UNI_MAXFACILITY; i++)
351 uni_set_debug(priv->uni, i, arg->level[i]);
352 break;
355 case NGM_UNI_GETDEBUG:
357 struct ngm_uni_debug *arg;
359 NG_MKRESPONSE(resp, msg, sizeof(*arg), M_NOWAIT);
360 if(resp == NULL) {
361 error = ENOMEM;
362 break;
364 arg = (struct ngm_uni_debug *)resp->data;
365 for (i = 0; i < UNI_MAXFACILITY; i++)
366 arg->level[i] = uni_get_debug(priv->uni, i);
367 break;
370 case NGM_UNI_GET_CONFIG:
372 struct uni_config *config;
374 if (msg->header.arglen != 0) {
375 error = EINVAL;
376 break;
378 NG_MKRESPONSE(resp, msg, sizeof(*config), M_NOWAIT);
379 if (resp == NULL) {
380 error = ENOMEM;
381 break;
383 config = (struct uni_config *)resp->data;
384 uni_get_config(priv->uni, config);
386 break;
389 case NGM_UNI_SET_CONFIG:
391 struct ngm_uni_set_config *arg;
392 struct ngm_uni_config_mask *mask;
394 if (msg->header.arglen != sizeof(*arg)) {
395 error = EINVAL;
396 break;
398 arg = (struct ngm_uni_set_config *)msg->data;
400 NG_MKRESPONSE(resp, msg, sizeof(*mask), M_NOWAIT);
401 if (resp == NULL) {
402 error = ENOMEM;
403 break;
405 mask = (struct ngm_uni_config_mask *)resp->data;
407 *mask = arg->mask;
409 uni_set_config(priv->uni, &arg->config,
410 &mask->mask, &mask->popt_mask, &mask->option_mask);
412 break;
415 case NGM_UNI_ENABLE:
416 if (msg->header.arglen != 0) {
417 error = EINVAL;
418 break;
420 if (priv->enabled) {
421 error = EISCONN;
422 break;
424 priv->enabled = 1;
425 break;
427 case NGM_UNI_DISABLE:
428 if (msg->header.arglen != 0) {
429 error = EINVAL;
430 break;
432 if (!priv->enabled) {
433 error = ENOTCONN;
434 break;
436 priv->enabled = 0;
437 uni_reset(priv->uni);
438 break;
440 case NGM_UNI_GETSTATE:
441 if (msg->header.arglen != 0) {
442 error = EINVAL;
443 break;
445 NG_MKRESPONSE(resp, msg, sizeof(u_int32_t), M_NOWAIT);
446 if(resp == NULL) {
447 error = ENOMEM;
448 break;
450 *(u_int32_t *)resp->data =
451 priv->enabled ? (uni_getcustate(priv->uni) + 1)
452 : 0;
453 break;
455 default:
456 error = EINVAL;
457 break;
459 break;
461 default:
462 error = EINVAL;
463 break;
466 NG_RESPOND_MSG(error, node, item, resp);
467 NG_FREE_MSG(msg);
468 return (error);
471 /************************************************************/
473 * HOOK MANAGEMENT
475 static int
476 ng_uni_newhook(node_p node, hook_p hook, const char *name)
478 struct priv *priv = NG_NODE_PRIVATE(node);
480 if (strcmp(name, "lower") == 0) {
481 priv->lower = hook;
482 } else if(strcmp(name, "upper") == 0) {
483 priv->upper = hook;
484 NG_HOOK_SET_RCVDATA(hook, ng_uni_rcvupper);
485 } else
486 return EINVAL;
488 return 0;
491 static int
492 ng_uni_disconnect(hook_p hook)
494 node_p node = NG_HOOK_NODE(hook);
495 struct priv *priv = NG_NODE_PRIVATE(node);
497 if(hook == priv->lower)
498 priv->lower = NULL;
499 else if(hook == priv->upper)
500 priv->upper = NULL;
501 else
502 printf("%s: bogus hook %s\n", __func__, NG_HOOK_NAME(hook));
504 if (NG_NODE_NUMHOOKS(node) == 0) {
505 if (NG_NODE_IS_VALID(node))
506 ng_rmnode_self(node);
509 return (0);
512 /************************************************************/
514 * DATA
517 * Receive signal from USER.
519 * Repackage the data into one large buffer.
521 static int
522 ng_uni_rcvupper(hook_p hook, item_p item)
524 node_p node = NG_HOOK_NODE(hook);
525 struct priv *priv = NG_NODE_PRIVATE(node);
526 struct mbuf *m;
527 struct uni_arg arg;
528 struct uni_msg *msg;
529 int error;
531 if (!priv->enabled) {
532 NG_FREE_ITEM(item);
533 return (ENOTCONN);
536 NGI_GET_M(item, m);
537 NG_FREE_ITEM(item);
539 if ((error = uni_msg_unpack_mbuf(m, &msg)) != 0) {
540 m_freem(m);
541 return (error);
543 m_freem(m);
545 if (uni_msg_len(msg) < sizeof(arg)) {
546 printf("%s: packet too short\n", __func__);
547 uni_msg_destroy(msg);
548 return (EINVAL);
551 bcopy(msg->b_rptr, &arg, sizeof(arg));
552 msg->b_rptr += sizeof(arg);
554 if (arg.sig >= UNIAPI_MAXSIG) {
555 printf("%s: bogus signal\n", __func__);
556 uni_msg_destroy(msg);
557 return (EINVAL);
559 uni_uni_input(priv->uni, arg.sig, arg.cookie, msg);
560 uni_work(priv->uni);
562 return (0);
567 * Upper layer signal from UNI
569 static void
570 uni_uni_output(struct uni *uni, void *varg, enum uni_sig sig, u_int32_t cookie,
571 struct uni_msg *msg)
573 node_p node = (node_p)varg;
574 struct priv *priv = NG_NODE_PRIVATE(node);
575 struct mbuf *m;
576 struct uni_arg arg;
577 int error;
579 if (priv->upper == NULL) {
580 if (msg != NULL)
581 uni_msg_destroy(msg);
582 return;
584 arg.sig = sig;
585 arg.cookie = cookie;
587 m = uni_msg_pack_mbuf(msg, &arg, sizeof(arg));
588 if (msg != NULL)
589 uni_msg_destroy(msg);
590 if (m == NULL)
591 return;
593 NG_SEND_DATA_ONLY(error, priv->upper, m);
597 static void
598 dump_uni_msg(struct uni_msg *msg)
600 u_int pos;
602 for (pos = 0; pos < uni_msg_len(msg); pos++) {
603 if (pos % 16 == 0)
604 printf("%06o ", pos);
605 if (pos % 16 == 8)
606 printf(" ");
607 printf(" %02x", msg->b_rptr[pos]);
608 if (pos % 16 == 15)
609 printf("\n");
611 if (pos % 16 != 0)
612 printf("\n");
617 * Dump a SAAL signal in either direction
619 static void
620 dump_saal_signal(node_p node, enum saal_sig sig, struct uni_msg *msg, int to)
622 struct priv *priv = NG_NODE_PRIVATE(node);
624 printf("signal %s SAAL: ", to ? "to" : "from");
626 switch (sig) {
628 #define D(S) case S: printf("%s", #S); break
630 D(SAAL_ESTABLISH_request);
631 D(SAAL_ESTABLISH_indication);
632 D(SAAL_ESTABLISH_confirm);
633 D(SAAL_RELEASE_request);
634 D(SAAL_RELEASE_confirm);
635 D(SAAL_RELEASE_indication);
636 D(SAAL_DATA_request);
637 D(SAAL_DATA_indication);
638 D(SAAL_UDATA_request);
639 D(SAAL_UDATA_indication);
641 #undef D
642 default:
643 printf("sig=%d", sig); break;
645 if (msg != NULL) {
646 printf(" data=%zu\n", uni_msg_len(msg));
647 if (uni_get_debug(priv->uni, UNI_FAC_SAAL) > 1)
648 dump_uni_msg(msg);
649 } else
650 printf("\n");
654 * Receive signal from SSCOP.
656 * If this is a data signal, repackage the data into one large buffer.
657 * UNI shouldn't be the bottleneck in a system and this greatly simplifies
658 * parsing in UNI.
660 static int
661 ng_uni_rcvlower(hook_p hook __unused, item_p item)
663 node_p node = NG_HOOK_NODE(hook);
664 struct priv *priv = NG_NODE_PRIVATE(node);
665 struct mbuf *m;
666 struct sscfu_arg arg;
667 struct uni_msg *msg;
668 int error;
670 if (!priv->enabled) {
671 NG_FREE_ITEM(item);
672 return (ENOTCONN);
675 NGI_GET_M(item, m);
676 NG_FREE_ITEM(item);
678 if ((error = uni_msg_unpack_mbuf(m, &msg)) != 0) {
679 m_freem(m);
680 return (error);
682 m_freem(m);
684 if (uni_msg_len(msg) < sizeof(arg)) {
685 uni_msg_destroy(msg);
686 printf("%s: packet too short\n", __func__);
687 return (EINVAL);
689 bcopy(msg->b_rptr, &arg, sizeof(arg));
690 msg->b_rptr += sizeof(arg);
692 if (arg.sig > SAAL_UDATA_indication) {
693 uni_msg_destroy(msg);
694 printf("%s: bogus signal\n", __func__);
695 return (EINVAL);
698 if (uni_get_debug(priv->uni, UNI_FAC_SAAL) > 0)
699 dump_saal_signal(node, arg.sig, msg, 0);
701 uni_saal_input(priv->uni, arg.sig, msg);
702 uni_work(priv->uni);
704 return (0);
708 * Send signal to sscop.
709 * Pack the message into an mbuf chain.
711 static void
712 uni_saal_output(struct uni *uni, void *varg, enum saal_sig sig, struct uni_msg *msg)
714 node_p node = (node_p)varg;
715 struct priv *priv = NG_NODE_PRIVATE(node);
716 struct mbuf *m;
717 struct sscfu_arg arg;
718 int error;
720 if (uni_get_debug(priv->uni, UNI_FAC_SAAL) > 0)
721 dump_saal_signal(node, sig, msg, 1);
723 if (priv->lower == NULL) {
724 if (msg != NULL)
725 uni_msg_destroy(msg);
726 return;
729 arg.sig = sig;
731 m = uni_msg_pack_mbuf(msg, &arg, sizeof(arg));
732 if (msg != NULL)
733 uni_msg_destroy(msg);
734 if (m == NULL)
735 return;
737 NG_SEND_DATA_ONLY(error, priv->lower, m);
740 static void
741 uni_verbose(struct uni *uni, void *varg, u_int fac, const char *fmt, ...)
743 va_list ap;
745 static char *facnames[] = {
746 #define UNI_DEBUG_DEFINE(D) [UNI_FAC_##D] #D,
747 UNI_DEBUG_FACILITIES
748 #undef UNI_DEBUG_DEFINE
751 printf("%s: ", facnames[fac]);
753 va_start(ap, fmt);
754 vprintf(fmt, ap);
755 va_end(ap);
757 printf("\n");
761 /************************************************************/
763 * Memory debugging
765 struct unimem_debug {
766 const char *file;
767 u_int lno;
768 LIST_ENTRY(unimem_debug) link;
769 char data[0];
771 LIST_HEAD(unimem_debug_list, unimem_debug);
773 static struct unimem_debug_list nguni_freemem[UNIMEM_TYPES] = {
774 LIST_HEAD_INITIALIZER(unimem_debug),
775 LIST_HEAD_INITIALIZER(unimem_debug),
776 LIST_HEAD_INITIALIZER(unimem_debug),
777 LIST_HEAD_INITIALIZER(unimem_debug),
778 LIST_HEAD_INITIALIZER(unimem_debug),
780 static struct unimem_debug_list nguni_usedmem[UNIMEM_TYPES] = {
781 LIST_HEAD_INITIALIZER(unimem_debug),
782 LIST_HEAD_INITIALIZER(unimem_debug),
783 LIST_HEAD_INITIALIZER(unimem_debug),
784 LIST_HEAD_INITIALIZER(unimem_debug),
785 LIST_HEAD_INITIALIZER(unimem_debug),
788 static struct mtx nguni_unilist_mtx;
790 static const char *unimem_names[UNIMEM_TYPES] = {
791 "instance",
792 "all",
793 "signal",
794 "call",
795 "party"
798 static void
799 uni_init(void)
801 mtx_init(&nguni_unilist_mtx, "netgraph UNI structure lists", NULL,
802 MTX_DEF);
805 static void
806 uni_fini(void)
808 u_int type;
809 struct unimem_debug *h;
811 for (type = 0; type < UNIMEM_TYPES; type++) {
812 while ((h = LIST_FIRST(&nguni_freemem[type])) != NULL) {
813 LIST_REMOVE(h, link);
814 free(h, M_UNI);
817 while ((h = LIST_FIRST(&nguni_usedmem[type])) != NULL) {
818 LIST_REMOVE(h, link);
819 printf("ng_uni: %s in use: %p (%s,%u)\n",
820 unimem_names[type], (caddr_t)h->data,
821 h->file, h->lno);
822 free(h, M_UNI);
826 mtx_destroy(&nguni_unilist_mtx);
830 * Allocate a chunk of memory from a given type.
832 void *
833 ng_uni_malloc(enum unimem type, const char *file, u_int lno)
835 struct unimem_debug *d;
836 size_t full;
839 * Try to allocate
841 mtx_lock(&nguni_unilist_mtx);
842 if ((d = LIST_FIRST(&nguni_freemem[type])) != NULL)
843 LIST_REMOVE(d, link);
844 mtx_unlock(&nguni_unilist_mtx);
846 if (d == NULL) {
848 * allocate
850 full = unimem_sizes[type] + offsetof(struct unimem_debug, data);
851 if ((d = malloc(full, M_UNI, M_NOWAIT | M_ZERO)) == NULL)
852 return (NULL);
853 } else {
854 bzero(d->data, unimem_sizes[type]);
856 d->file = file;
857 d->lno = lno;
859 mtx_lock(&nguni_unilist_mtx);
860 LIST_INSERT_HEAD(&nguni_usedmem[type], d, link);
861 mtx_unlock(&nguni_unilist_mtx);
862 return (d->data);
865 void
866 ng_uni_free(enum unimem type, void *ptr, const char *file, u_int lno)
868 struct unimem_debug *d, *h;
870 d = (struct unimem_debug *)
871 ((char *)ptr - offsetof(struct unimem_debug, data));
873 mtx_lock(&nguni_unilist_mtx);
875 LIST_FOREACH(h, &nguni_usedmem[type], link)
876 if (d == h)
877 break;
879 if (h != NULL) {
880 LIST_REMOVE(d, link);
881 LIST_INSERT_HEAD(&nguni_freemem[type], d, link);
882 } else {
884 * Not on used list - try free list.
886 LIST_FOREACH(h, &nguni_freemem[type], link)
887 if (d == h)
888 break;
889 if (h == NULL)
890 printf("ng_uni: %s,%u: %p(%s) was never allocated\n",
891 file, lno, ptr, unimem_names[type]);
892 else
893 printf("ng_uni: %s,%u: %p(%s) was already destroyed "
894 "in %s,%u\n",
895 file, lno, ptr, unimem_names[type],
896 h->file, h->lno);
898 mtx_unlock(&nguni_unilist_mtx);
900 /************************************************************/
902 * INITIALISATION
906 * Loading and unloading of node type
908 static int
909 ng_uni_mod_event(module_t mod, int event, void *data)
911 int s;
912 int error = 0;
914 s = splnet();
915 switch(event) {
917 case MOD_LOAD:
918 uni_init();
919 break;
921 case MOD_UNLOAD:
922 uni_fini();
923 break;
925 default:
926 error = EOPNOTSUPP;
927 break;
929 splx(s);
930 return (error);