ng_atm.c revision 117642
1116808Sharti/* 2116808Sharti * Copyright (c) 2001-2003 3116808Sharti * Fraunhofer Institute for Open Communication Systems (FhG Fokus). 4116808Sharti * All rights reserved. 5116808Sharti * 6116808Sharti * Redistribution and use in source and binary forms, with or without 7116808Sharti * modification, are permitted provided that the following conditions 8116808Sharti * are met: 9116808Sharti * 1. Redistributions of source code must retain the above copyright 10116808Sharti * notice, this list of conditions and the following disclaimer. 11116808Sharti * 2. Redistributions in binary form must reproduce the above copyright 12116808Sharti * notice, this list of conditions and the following disclaimer in the 13116808Sharti * documentation and/or other materials provided with the distribution. 14116808Sharti * 15116808Sharti * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16116808Sharti * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17116808Sharti * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18116808Sharti * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19116808Sharti * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20116808Sharti * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21116808Sharti * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22116808Sharti * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23116808Sharti * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24116808Sharti * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25116808Sharti * SUCH DAMAGE. 26116808Sharti * 27116808Sharti * Author: Hartmut Brandt <harti@freebsd.org> 28116808Sharti * 29116808Sharti * Netgraph module to connect NATM interfaces to netgraph. 30116808Sharti */ 31116808Sharti 32116808Sharti#include <sys/cdefs.h> 33116808Sharti__FBSDID("$FreeBSD: head/sys/netgraph/atm/ng_atm.c 117642 2003-07-15 15:48:10Z harti $"); 34116808Sharti 35116808Sharti#include <sys/param.h> 36116808Sharti#include <sys/systm.h> 37116808Sharti#include <sys/kernel.h> 38116808Sharti#include <sys/malloc.h> 39116808Sharti#include <sys/mbuf.h> 40116808Sharti#include <sys/errno.h> 41116808Sharti#include <sys/syslog.h> 42116808Sharti#include <sys/socket.h> 43116808Sharti#include <sys/socketvar.h> 44116808Sharti#include <sys/sbuf.h> 45116808Sharti#include <sys/ioccom.h> 46116808Sharti#include <sys/sysctl.h> 47116808Sharti 48116808Sharti#include <net/if.h> 49116808Sharti#include <net/if_types.h> 50116808Sharti#include <net/if_arp.h> 51116808Sharti#include <net/if_var.h> 52116808Sharti#include <net/if_media.h> 53116808Sharti#include <net/if_atm.h> 54116808Sharti 55116808Sharti#include <netgraph/ng_message.h> 56116808Sharti#include <netgraph/netgraph.h> 57116808Sharti#include <netgraph/ng_parse.h> 58116808Sharti#include <netgraph/atm/ng_atm.h> 59116808Sharti 60116808Sharti/* 61116808Sharti * Hooks in the NATM code 62116808Sharti */ 63116808Shartiextern void (*ng_atm_attach_p)(struct ifnet *); 64116808Shartiextern void (*ng_atm_detach_p)(struct ifnet *); 65116808Shartiextern int (*ng_atm_output_p)(struct ifnet *, struct mbuf **); 66116808Shartiextern void (*ng_atm_input_p)(struct ifnet *, struct mbuf **, 67116808Sharti struct atm_pseudohdr *, void *); 68116808Shartiextern void (*ng_atm_input_orphan_p)(struct ifnet *, struct mbuf *, 69116808Sharti struct atm_pseudohdr *, void *); 70116808Shartiextern void (*ng_atm_message_p)(struct ifnet *, uint32_t, uint32_t); 71116808Sharti 72116808Sharti/* 73116808Sharti * Sysctl stuff. 74116808Sharti */ 75116808ShartiSYSCTL_NODE(_net_graph, OID_AUTO, atm, CTLFLAG_RW, 0, "atm related stuff"); 76116808Sharti 77116808Sharti#ifdef NGATM_DEBUG 78116808Shartistatic int allow_shutdown; 79116808Sharti 80116808ShartiSYSCTL_INT(_net_graph_atm, OID_AUTO, allow_shutdown, CTLFLAG_RW, 81116808Sharti &allow_shutdown, 0, "allow ng_atm nodes to shutdown"); 82116808Sharti#endif 83116808Sharti 84116808Sharti/* 85116808Sharti * Hook private data 86116808Sharti */ 87116808Shartistruct ngvcc { 88116808Sharti uint16_t vpi; /* VPI of this hook */ 89116808Sharti uint16_t vci; /* VCI of this hook, 0 if none */ 90116808Sharti uint32_t flags; /* private flags */ 91116808Sharti hook_p hook; /* the connected hook */ 92116808Sharti 93116808Sharti LIST_ENTRY(ngvcc) link; 94116808Sharti}; 95117157Sharti#define VCC_OPEN 0x0001 /* open */ 96116808Sharti 97116808Sharti/* 98116808Sharti * Node private data 99116808Sharti */ 100116808Shartistruct priv { 101116808Sharti struct ifnet *ifp; /* the ATM interface */ 102116808Sharti hook_p input; /* raw input hook */ 103116808Sharti hook_p orphans; /* packets to nowhere */ 104116808Sharti hook_p output; /* catch output packets */ 105116808Sharti hook_p manage; /* has also entry in vccs */ 106116808Sharti uint64_t in_packets; 107116808Sharti uint64_t in_errors; 108116808Sharti uint64_t out_packets; 109116808Sharti uint64_t out_errors; 110116808Sharti 111116808Sharti LIST_HEAD(, ngvcc) vccs; 112116808Sharti}; 113116808Sharti 114116808Sharti/* 115116808Sharti * Parse carrier state 116116808Sharti */ 117116808Shartistatic const struct ng_parse_struct_field ng_atm_carrier_change_info[] = 118116808Sharti NGM_ATM_CARRIER_CHANGE_INFO; 119116808Shartistatic const struct ng_parse_type ng_atm_carrier_change_type = { 120116808Sharti &ng_parse_struct_type, 121116808Sharti &ng_atm_carrier_change_info 122116808Sharti}; 123116808Sharti 124116808Sharti/* 125116808Sharti * Parse the configuration structure ng_atm_config 126116808Sharti */ 127116808Shartistatic const struct ng_parse_struct_field ng_atm_config_type_info[] = 128116808Sharti NGM_ATM_CONFIG_INFO; 129116808Sharti 130116808Shartistatic const struct ng_parse_type ng_atm_config_type = { 131116808Sharti &ng_parse_struct_type, 132116808Sharti &ng_atm_config_type_info 133116808Sharti}; 134116808Sharti 135116808Sharti/* 136116808Sharti * Parse a single vcc structure and a variable array of these ng_atm_vccs 137116808Sharti */ 138116808Shartistatic const struct ng_parse_struct_field ng_atm_tparam_type_info[] = 139116808Sharti NGM_ATM_TPARAM_INFO; 140116808Shartistatic const struct ng_parse_type ng_atm_tparam_type = { 141116808Sharti &ng_parse_struct_type, 142116808Sharti &ng_atm_tparam_type_info 143116808Sharti}; 144116808Shartistatic const struct ng_parse_struct_field ng_atm_vcc_type_info[] = 145116808Sharti NGM_ATM_VCC_INFO; 146116808Shartistatic const struct ng_parse_type ng_atm_vcc_type = { 147116808Sharti &ng_parse_struct_type, 148116808Sharti &ng_atm_vcc_type_info 149116808Sharti}; 150116808Sharti 151116808Sharti 152116808Shartistatic int 153116808Sharting_atm_vccarray_getlen(const struct ng_parse_type *type, 154116808Sharti const u_char *start, const u_char *buf) 155116808Sharti{ 156116808Sharti const struct atmio_vcctable *vp; 157116808Sharti 158116808Sharti vp = (const struct atmio_vcctable *) 159116808Sharti (buf - offsetof(struct atmio_vcctable, vccs)); 160116808Sharti 161116808Sharti return (vp->count); 162116808Sharti} 163116808Shartistatic const struct ng_parse_array_info ng_atm_vccarray_info = 164116808Sharti NGM_ATM_VCCARRAY_INFO; 165116808Shartistatic const struct ng_parse_type ng_atm_vccarray_type = { 166116808Sharti &ng_parse_array_type, 167116808Sharti &ng_atm_vccarray_info 168116808Sharti}; 169116808Sharti 170116808Sharti 171116808Shartistatic const struct ng_parse_struct_field ng_atm_vcctable_type_info[] = 172116808Sharti NGM_ATM_VCCTABLE_INFO; 173116808Sharti 174116808Shartistatic const struct ng_parse_type ng_atm_vcctable_type = { 175116808Sharti &ng_parse_struct_type, 176116808Sharti &ng_atm_vcctable_type_info 177116808Sharti}; 178116808Sharti 179116808Sharti/* 180116808Sharti * Parse CPCS INIT structure ng_atm_cpcs_init 181116808Sharti */ 182116808Shartistatic const struct ng_parse_struct_field ng_atm_cpcs_init_type_info[] = 183116808Sharti NGM_ATM_CPCS_INIT_INFO; 184116808Sharti 185116808Shartistatic const struct ng_parse_type ng_atm_cpcs_init_type = { 186116808Sharti &ng_parse_struct_type, 187116808Sharti &ng_atm_cpcs_init_type_info 188116808Sharti}; 189116808Sharti 190116808Sharti/* 191116808Sharti * Parse CPCS TERM structure ng_atm_cpcs_term 192116808Sharti */ 193116808Shartistatic const struct ng_parse_struct_field ng_atm_cpcs_term_type_info[] = 194116808Sharti NGM_ATM_CPCS_TERM_INFO; 195116808Sharti 196116808Shartistatic const struct ng_parse_type ng_atm_cpcs_term_type = { 197116808Sharti &ng_parse_struct_type, 198116808Sharti &ng_atm_cpcs_term_type_info 199116808Sharti}; 200116808Sharti 201116808Sharti/* 202116808Sharti * Parse statistic struct 203116808Sharti */ 204116808Shartistatic const struct ng_parse_struct_field ng_atm_stats_type_info[] = 205116808Sharti NGM_ATM_STATS_INFO; 206116808Sharti 207116808Shartistatic const struct ng_parse_type ng_atm_stats_type = { 208116808Sharti &ng_parse_struct_type, 209116808Sharti &ng_atm_stats_type_info 210116808Sharti}; 211116808Sharti 212116808Shartistatic const struct ng_cmdlist ng_atm_cmdlist[] = { 213116808Sharti { 214116808Sharti NGM_ATM_COOKIE, 215116808Sharti NGM_ATM_GET_IFNAME, 216116808Sharti "getifname", 217116808Sharti NULL, 218116808Sharti &ng_parse_string_type 219116808Sharti }, 220116808Sharti { 221116808Sharti NGM_ATM_COOKIE, 222116808Sharti NGM_ATM_GET_CONFIG, 223116808Sharti "getconfig", 224116808Sharti NULL, 225116808Sharti &ng_atm_config_type 226116808Sharti }, 227116808Sharti { 228116808Sharti NGM_ATM_COOKIE, 229116808Sharti NGM_ATM_GET_VCCS, 230116808Sharti "getvccs", 231116808Sharti NULL, 232116808Sharti &ng_atm_vcctable_type 233116808Sharti }, 234116808Sharti { 235116808Sharti NGM_ATM_COOKIE, 236116808Sharti NGM_ATM_CPCS_INIT, 237116808Sharti "cpcsinit", 238116808Sharti &ng_atm_cpcs_init_type, 239116808Sharti NULL 240116808Sharti }, 241116808Sharti { 242116808Sharti NGM_ATM_COOKIE, 243116808Sharti NGM_ATM_CPCS_TERM, 244116808Sharti "cpcsterm", 245116808Sharti &ng_atm_cpcs_term_type, 246116808Sharti NULL 247116808Sharti }, 248116808Sharti { 249116808Sharti NGM_ATM_COOKIE, 250116808Sharti NGM_ATM_CARRIER_CHANGE, 251116808Sharti "carrier", 252116808Sharti &ng_atm_carrier_change_type, 253116808Sharti &ng_atm_carrier_change_type, 254116808Sharti }, 255116808Sharti { 256116808Sharti NGM_ATM_COOKIE, 257116808Sharti NGM_ATM_GET_VCC, 258116808Sharti "getvcc", 259116808Sharti &ng_parse_hookbuf_type, 260116808Sharti &ng_atm_vcc_type 261116808Sharti }, 262116808Sharti { 263116808Sharti NGM_ATM_COOKIE, 264116808Sharti NGM_ATM_GET_VCCID, 265116808Sharti "getvccid", 266116808Sharti &ng_atm_vcc_type, 267116808Sharti &ng_atm_vcc_type 268116808Sharti }, 269116808Sharti { 270116808Sharti NGM_ATM_COOKIE, 271116808Sharti NGM_ATM_GET_STATS, 272116808Sharti "getstats", 273116808Sharti NULL, 274116808Sharti &ng_atm_stats_type 275116808Sharti }, 276116808Sharti { 0 } 277116808Sharti}; 278116808Sharti 279116808Shartistatic int ng_atm_mod_event(module_t, int, void *); 280116808Sharti 281116808Shartistatic ng_constructor_t ng_atm_constructor; 282116808Shartistatic ng_shutdown_t ng_atm_shutdown; 283116808Shartistatic ng_rcvmsg_t ng_atm_rcvmsg; 284116808Shartistatic ng_newhook_t ng_atm_newhook; 285116808Shartistatic ng_connect_t ng_atm_connect; 286116808Shartistatic ng_disconnect_t ng_atm_disconnect; 287116808Shartistatic ng_rcvdata_t ng_atm_rcvdata; 288116808Shartistatic ng_rcvdata_t ng_atm_rcvdrop; 289116808Sharti 290116808Shartistatic struct ng_type ng_atm_typestruct = { 291116808Sharti NG_ABI_VERSION, 292116808Sharti NG_ATM_NODE_TYPE, 293116808Sharti ng_atm_mod_event, /* Module event handler (optional) */ 294116808Sharti ng_atm_constructor, /* Node constructor */ 295116808Sharti ng_atm_rcvmsg, /* control messages come here */ 296116808Sharti ng_atm_shutdown, /* reset, and free resources */ 297116808Sharti ng_atm_newhook, /* first notification of new hook */ 298116808Sharti NULL, /* findhook */ 299116808Sharti ng_atm_connect, /* connect */ 300116808Sharti ng_atm_rcvdata, /* rcvdata */ 301116808Sharti ng_atm_disconnect, /* notify on disconnect */ 302116808Sharti ng_atm_cmdlist, 303116808Sharti}; 304116808ShartiNETGRAPH_INIT(atm, &ng_atm_typestruct); 305116808Sharti 306116808Shartistatic const struct { 307116808Sharti u_int media; 308116808Sharti const char *name; 309116808Sharti} atmmedia[] = IFM_SUBTYPE_ATM_DESCRIPTIONS; 310116808Sharti 311116808Sharti 312116808Sharti#define IFP2NG(IFP) ((node_p)((struct ifatm *)(IFP))->ngpriv) 313116808Sharti 314116808Sharti#define IFFLAGS "\020\001UP\002BROADCAST\003DEBUG\004LOOPBACK" \ 315116808Sharti "\005POINTOPOINT\006SMART\007RUNNING\010NOARP" \ 316116808Sharti "\011PROMISC\012ALLMULTI\013OACTIVE\014SIMPLEX" \ 317116808Sharti "\015LINK0\016LINK1\017LINK2\020MULTICAST" 318116808Sharti 319116808Sharti 320116808Sharti/************************************************************/ 321116808Sharti/* 322116808Sharti * INPUT 323116808Sharti */ 324116808Sharti/* 325116808Sharti * A packet is received from an interface. 326116808Sharti * If we have an input hook, prepend the pseudoheader to the data and 327116808Sharti * deliver it out to that hook. If not, look whether it is destined for 328116808Sharti * use. If so locate the appropriate hook, deliver the packet without the 329116808Sharti * header and we are done. If it is not for us, leave it alone. 330116808Sharti */ 331116808Shartistatic void 332116808Sharting_atm_input(struct ifnet *ifp, struct mbuf **mp, 333116808Sharti struct atm_pseudohdr *ah, void *rxhand) 334116808Sharti{ 335116808Sharti node_p node = IFP2NG(ifp); 336116808Sharti struct priv *priv; 337116808Sharti const struct ngvcc *vcc; 338116808Sharti int error; 339116808Sharti 340116808Sharti if (node == NULL) 341116808Sharti return; 342116808Sharti priv = NG_NODE_PRIVATE(node); 343116808Sharti if (priv->input != NULL) { 344116808Sharti /* 345116808Sharti * Prepend the atm_pseudoheader. 346116808Sharti */ 347116808Sharti M_PREPEND(*mp, sizeof(*ah), M_DONTWAIT); 348116808Sharti if (*mp == NULL) 349116808Sharti return; 350116808Sharti memcpy(mtod(*mp, struct atm_pseudohdr *), ah, sizeof(*ah)); 351116808Sharti NG_SEND_DATA_ONLY(error, priv->input, *mp); 352116808Sharti if (error == 0) { 353116808Sharti priv->in_packets++; 354116808Sharti *mp = NULL; 355116808Sharti } else { 356116808Sharti#ifdef NGATM_DEBUG 357116808Sharti printf("%s: error=%d\n", __func__, error); 358116808Sharti#endif 359116808Sharti priv->in_errors++; 360116808Sharti } 361116808Sharti return; 362116808Sharti } 363116808Sharti if ((ATM_PH_FLAGS(ah) & ATMIO_FLAG_NG) == 0) 364116808Sharti return; 365116808Sharti 366116808Sharti vcc = (struct ngvcc *)rxhand; 367116808Sharti 368116808Sharti NG_SEND_DATA_ONLY(error, vcc->hook, *mp); 369116808Sharti if (error == 0) { 370116808Sharti priv->in_packets++; 371116808Sharti *mp = NULL; 372116808Sharti } else { 373116808Sharti#ifdef NGATM_DEBUG 374116808Sharti printf("%s: error=%d\n", __func__, error); 375116808Sharti#endif 376116808Sharti priv->in_errors++; 377116808Sharti } 378116808Sharti} 379116808Sharti 380116808Sharti/* 381116808Sharti * ATM packet is about to be output. The atm_pseudohdr is already prepended. 382116808Sharti * If the hook is set, reroute the packet to the hook. 383116808Sharti */ 384116808Shartistatic int 385116808Sharting_atm_output(struct ifnet *ifp, struct mbuf **mp) 386116808Sharti{ 387116808Sharti const node_p node = IFP2NG(ifp); 388116808Sharti const struct priv *priv; 389116808Sharti int error = 0; 390116808Sharti 391116808Sharti if (node == NULL) 392116808Sharti return (0); 393116808Sharti priv = NG_NODE_PRIVATE(node); 394116808Sharti if (priv->output) { 395116808Sharti NG_SEND_DATA_ONLY(error, priv->output, *mp); 396116808Sharti *mp = NULL; 397116808Sharti } 398116808Sharti 399116808Sharti return (error); 400116808Sharti} 401116808Sharti 402116808Sharti/* 403116808Sharti * Well, this doesn't make much sense for ATM. 404116808Sharti */ 405116808Shartistatic void 406116808Sharting_atm_input_orphans(struct ifnet *ifp, struct mbuf *m, 407116808Sharti struct atm_pseudohdr *ah, void *rxhand) 408116808Sharti{ 409116808Sharti node_p node = IFP2NG(ifp); 410116808Sharti struct priv *priv; 411116808Sharti int error; 412116808Sharti 413116808Sharti if (node == NULL) { 414116808Sharti m_freem(m); 415116808Sharti return; 416116808Sharti } 417116808Sharti priv = NG_NODE_PRIVATE(node); 418116808Sharti if (priv->orphans == NULL) { 419116808Sharti m_freem(m); 420116808Sharti return; 421116808Sharti } 422116808Sharti /* 423116808Sharti * Prepend the atm_pseudoheader. 424116808Sharti */ 425116808Sharti M_PREPEND(m, sizeof(*ah), M_DONTWAIT); 426116808Sharti if (m == NULL) 427116808Sharti return; 428116808Sharti memcpy(mtod(m, struct atm_pseudohdr *), ah, sizeof(*ah)); 429116808Sharti NG_SEND_DATA_ONLY(error, priv->orphans, m); 430116808Sharti if (error == 0) 431116808Sharti priv->in_packets++; 432116808Sharti else { 433116808Sharti priv->in_errors++; 434116808Sharti#ifdef NGATM_DEBUG 435116808Sharti printf("%s: error=%d\n", __func__, error); 436116808Sharti#endif 437116808Sharti } 438116808Sharti} 439116808Sharti 440116808Sharti/************************************************************/ 441116808Sharti/* 442116808Sharti * OUTPUT 443116808Sharti */ 444116808Shartistatic int 445116808Sharting_atm_rcvdata(hook_p hook, item_p item) 446116808Sharti{ 447116808Sharti node_p node = NG_HOOK_NODE(hook); 448116808Sharti struct priv *priv = NG_NODE_PRIVATE(node); 449116808Sharti const struct ngvcc *vcc = NG_HOOK_PRIVATE(hook); 450116808Sharti struct mbuf *m; 451116808Sharti struct atm_pseudohdr *aph; 452116808Sharti int error; 453116808Sharti 454116808Sharti if (vcc->vci == 0) { 455116808Sharti NG_FREE_ITEM(item); 456116808Sharti return (ENOTCONN); 457116808Sharti } 458116808Sharti 459116808Sharti NGI_GET_M(item, m); 460116808Sharti NG_FREE_ITEM(item); 461116808Sharti 462116808Sharti /* 463116808Sharti * Prepend pseudo-hdr. Drivers don't care about the flags. 464116808Sharti */ 465116808Sharti M_PREPEND(m, sizeof(*aph), M_DONTWAIT); 466116808Sharti if (m == NULL) { 467116808Sharti NG_FREE_M(m); 468116808Sharti return (ENOMEM); 469116808Sharti } 470116808Sharti aph = mtod(m, struct atm_pseudohdr *); 471116808Sharti ATM_PH_VPI(aph) = vcc->vpi; 472116808Sharti ATM_PH_SETVCI(aph, vcc->vci); 473116808Sharti ATM_PH_FLAGS(aph) = 0; 474116808Sharti 475116808Sharti if ((error = atm_output(priv->ifp, m, NULL, NULL)) == 0) 476116808Sharti priv->out_packets++; 477116808Sharti else 478116808Sharti priv->out_errors++; 479116808Sharti return (error); 480116808Sharti} 481116808Sharti 482116808Shartistatic int 483116808Sharting_atm_rcvdrop(hook_p hook, item_p item) 484116808Sharti{ 485116808Sharti NG_FREE_ITEM(item); 486116808Sharti return (0); 487116808Sharti} 488116808Sharti 489116808Sharti 490116808Sharti/************************************************************ 491116808Sharti * 492116808Sharti * Message from driver. 493116808Sharti */ 494116808Sharti#ifdef notyet 495116808Shartistatic void 496116808Sharting_atm_message_func(node_p node, hook_p hook, void *arg1, int arg2) 497116808Sharti{ 498116808Sharti uint32_t msg = (uintptr_t)arg1; 499116808Sharti uint32_t arg = (uint32_t)arg2; 500116808Sharti const struct priv *priv = NG_NODE_PRIVATE(node); 501116808Sharti struct ngvcc *vcc; 502116808Sharti u_int vci, vpi, state; 503116808Sharti struct ng_mesg *mesg; 504116808Sharti int error; 505116808Sharti 506116808Sharti switch (msg) { 507116808Sharti 508116808Sharti case ATM_MSG_FLOW_CONTROL: 509116808Sharti { 510116808Sharti struct ngm_queue_state *qstate; 511116808Sharti 512116808Sharti /* find the connection */ 513116808Sharti vci = arg & 0xffff; 514116808Sharti vpi = (arg >> 16) & 0xff; 515116808Sharti state = (arg >> 24) & 1; 516116808Sharti LIST_FOREACH(vcc, &priv->vccs, link) 517116808Sharti if (vcc->vci == vci && vcc->vpi == vpi) 518116808Sharti break; 519116808Sharti if (vcc == NULL) 520116808Sharti break; 521116808Sharti 522116808Sharti /* convert into a flow control message */ 523116808Sharti NG_MKMESSAGE(mesg, NGM_FLOW_COOKIE, 524116808Sharti state ? NGM_HIGH_WATER_PASSED : NGM_LOW_WATER_PASSED, 525116808Sharti sizeof(struct ngm_queue_state), M_NOWAIT); 526116808Sharti if (mesg == NULL) 527116808Sharti break; 528116808Sharti qstate = (struct ngm_queue_state *)mesg->data; 529116808Sharti 530116808Sharti /* XXX have to figure out how to get that info */ 531116808Sharti 532116808Sharti NG_SEND_MSG_HOOK(error, node, mesg, vcc->hook, NULL); 533116808Sharti break; 534116808Sharti } 535116808Sharti 536116808Sharti case ATM_MSG_VCC_CHANGED: 537116808Sharti { 538116808Sharti struct ngm_atm_vcc_change *chg; 539116808Sharti 540116808Sharti if (priv->manage == NULL) 541116808Sharti break; 542116808Sharti NG_MKMESSAGE(mesg, NGM_ATM_COOKIE, NGM_ATM_VCC_CHANGE, 543116808Sharti sizeof(struct ngm_atm_vcc_change), M_NOWAIT); 544116808Sharti if (mesg == NULL) 545116808Sharti break; 546116808Sharti chg = (struct ngm_atm_vcc_change *)mesg->data; 547116808Sharti chg->vci = arg & 0xffff; 548116808Sharti chg->vpi = (arg >> 16) & 0xff; 549116808Sharti chg->state = (arg >> 24) & 1; 550116808Sharti chg->node = NG_NODE_ID(node); 551116808Sharti NG_SEND_MSG_HOOK(error, node, mesg, priv->manage, NULL); 552116808Sharti break; 553116808Sharti } 554116808Sharti 555116808Sharti case ATM_MSG_CARRIER_CHANGE: 556116808Sharti { 557116808Sharti struct ngm_atm_carrier_change *chg; 558116808Sharti 559116808Sharti if (priv->manage == NULL) 560116808Sharti break; 561116808Sharti NG_MKMESSAGE(mesg, NGM_ATM_COOKIE, NGM_ATM_CARRIER_CHANGE, 562116808Sharti sizeof(struct ngm_atm_carrier_change), M_NOWAIT); 563116808Sharti if (mesg == NULL) 564116808Sharti break; 565116808Sharti chg = (struct ngm_atm_carrier_change *)mesg->data; 566116808Sharti chg->state = arg & 1; 567116808Sharti chg->node = NG_NODE_ID(node); 568116808Sharti NG_SEND_MSG_HOOK(error, node, mesg, priv->manage, NULL); 569116808Sharti break; 570116808Sharti } 571116808Sharti } 572116808Sharti} 573116808Sharti#endif 574116808Sharti 575116808Sharti/* 576116808Sharti * Use send_fn to get the right lock 577116808Sharti */ 578116808Shartistatic void 579116808Sharting_atm_message(struct ifnet *ifp, uint32_t msg, uint32_t arg) 580116808Sharti{ 581116808Sharti#ifdef notyet 582116808Sharti const node_p node = IFP2NG(ifp); 583116808Sharti 584116808Sharti (void)ng_send_fn(node, NULL, ng_atm_message_func, 585116808Sharti (void *)(uintptr_t)msg, arg); 586116808Sharti#endif 587116808Sharti} 588116808Sharti 589116808Sharti/************************************************************ 590116808Sharti * 591116808Sharti * CPCS 592116808Sharti */ 593116808Sharti/* 594116808Sharti * Open a channel for the user 595116808Sharti */ 596116808Shartistatic int 597116808Sharting_atm_cpcs_init(node_p node, const struct ngm_atm_cpcs_init *arg) 598116808Sharti{ 599116808Sharti struct priv *priv = NG_NODE_PRIVATE(node); 600116808Sharti const struct ifatm_mib *mib; 601116808Sharti struct ngvcc *vcc; 602116808Sharti struct atmio_openvcc data; 603116808Sharti int err; 604116808Sharti 605116808Sharti if(priv->ifp->if_ioctl == NULL) 606116808Sharti return (ENXIO); 607116808Sharti 608116808Sharti mib = (const struct ifatm_mib *)(priv->ifp->if_linkmib); 609116808Sharti 610116808Sharti LIST_FOREACH(vcc, &priv->vccs, link) 611116808Sharti if (strcmp(arg->name, NG_HOOK_NAME(vcc->hook)) == 0) 612116808Sharti break; 613116808Sharti if (vcc == NULL) 614116808Sharti return (ENOTCONN); 615117642Sharti if (vcc->flags & VCC_OPEN) 616116808Sharti return (EISCONN); 617116808Sharti 618116808Sharti /* 619116808Sharti * Check user arguments and construct ioctl argument 620116808Sharti */ 621116808Sharti memset(&data, 0, sizeof(data)); 622116808Sharti 623116808Sharti data.rxhand = vcc; 624116808Sharti 625116808Sharti switch (data.param.aal = arg->aal) { 626116808Sharti 627117157Sharti case ATMIO_AAL_34: 628116808Sharti case ATMIO_AAL_5: 629116808Sharti case ATMIO_AAL_0: 630116808Sharti case ATMIO_AAL_RAW: 631116808Sharti break; 632116808Sharti 633116808Sharti default: 634116808Sharti return (EINVAL); 635116808Sharti } 636116808Sharti 637116808Sharti if (arg->vpi > 0xff) 638116808Sharti return (EINVAL); 639116808Sharti data.param.vpi = arg->vpi; 640116808Sharti 641117157Sharti /* allow 0.0 as catch all receive channel */ 642117157Sharti if (arg->vci == 0 && (arg->vpi != 0 || !(arg->flags & ATMIO_FLAG_NOTX))) 643117157Sharti return (EINVAL); 644116808Sharti data.param.vci = arg->vci; 645116808Sharti 646116808Sharti data.param.tparam.pcr = arg->pcr; 647116808Sharti 648116808Sharti if (arg->mcr > arg->pcr) 649116808Sharti return (EINVAL); 650116808Sharti data.param.tparam.mcr = arg->mcr; 651116808Sharti 652116808Sharti if (!(arg->flags & ATMIO_FLAG_NOTX)) { 653117157Sharti if (arg->tmtu == 0) 654117157Sharti data.param.tmtu = priv->ifp->if_mtu; 655117157Sharti else { 656117157Sharti data.param.tmtu = arg->tmtu; 657117157Sharti } 658116808Sharti } 659116808Sharti if (!(arg->flags & ATMIO_FLAG_NORX)) { 660117157Sharti if (arg->rmtu == 0) 661117157Sharti data.param.rmtu = priv->ifp->if_mtu; 662117157Sharti else { 663117157Sharti data.param.rmtu = arg->rmtu; 664117157Sharti } 665116808Sharti } 666116808Sharti 667116808Sharti switch (data.param.traffic = arg->traffic) { 668116808Sharti 669116808Sharti case ATMIO_TRAFFIC_UBR: 670116808Sharti case ATMIO_TRAFFIC_CBR: 671116808Sharti break; 672116808Sharti 673116808Sharti case ATMIO_TRAFFIC_VBR: 674116808Sharti if (arg->scr > arg->pcr) 675116808Sharti return (EINVAL); 676116808Sharti data.param.tparam.scr = arg->scr; 677116808Sharti 678116808Sharti if (arg->mbs > (1 << 24)) 679116808Sharti return (EINVAL); 680116808Sharti data.param.tparam.mbs = arg->mbs; 681116808Sharti break; 682116808Sharti 683116808Sharti case ATMIO_TRAFFIC_ABR: 684116808Sharti if (arg->icr > arg->pcr || arg->icr < arg->mcr) 685116808Sharti return (EINVAL); 686116808Sharti data.param.tparam.icr = arg->icr; 687116808Sharti 688116808Sharti if (arg->tbe == 0 || arg->tbe > (1 << 24)) 689116808Sharti return (EINVAL); 690116808Sharti data.param.tparam.tbe = arg->tbe; 691116808Sharti 692116808Sharti if (arg->nrm > 0x7) 693116808Sharti return (EINVAL); 694116808Sharti data.param.tparam.nrm = arg->nrm; 695116808Sharti 696116808Sharti if (arg->trm > 0x7) 697116808Sharti return (EINVAL); 698116808Sharti data.param.tparam.trm = arg->trm; 699116808Sharti 700116808Sharti if (arg->adtf > 0x3ff) 701116808Sharti return (EINVAL); 702116808Sharti data.param.tparam.adtf = arg->adtf; 703116808Sharti 704116808Sharti if (arg->rif > 0xf) 705116808Sharti return (EINVAL); 706116808Sharti data.param.tparam.rif = arg->rif; 707116808Sharti 708116808Sharti if (arg->rdf > 0xf) 709116808Sharti return (EINVAL); 710116808Sharti data.param.tparam.rdf = arg->rdf; 711116808Sharti 712116808Sharti if (arg->cdf > 0x7) 713116808Sharti return (EINVAL); 714116808Sharti data.param.tparam.cdf = arg->cdf; 715116808Sharti 716116808Sharti break; 717116808Sharti 718116808Sharti default: 719116808Sharti return (EINVAL); 720116808Sharti } 721116808Sharti 722116808Sharti if ((arg->flags & ATMIO_FLAG_NORX) && (arg->flags & ATMIO_FLAG_NOTX)) 723116808Sharti return (EINVAL); 724116808Sharti 725116808Sharti data.param.flags = arg->flags & ~(ATM_PH_AAL5 | ATM_PH_LLCSNAP); 726116808Sharti data.param.flags |= ATMIO_FLAG_NG; 727116808Sharti 728116808Sharti err = (*priv->ifp->if_ioctl)(priv->ifp, SIOCATMOPENVCC, (caddr_t)&data); 729116808Sharti 730116808Sharti if (err == 0) { 731116808Sharti vcc->vci = data.param.vci; 732116808Sharti vcc->vpi = data.param.vpi; 733117157Sharti vcc->flags = VCC_OPEN; 734116808Sharti } 735116808Sharti 736116808Sharti return (err); 737116808Sharti} 738116808Sharti 739116808Sharti/* 740116808Sharti * Issue the close command to the driver 741116808Sharti */ 742116808Shartistatic int 743116808Sharticpcs_term(const struct priv *priv, u_int vpi, u_int vci) 744116808Sharti{ 745116808Sharti struct atmio_closevcc data; 746116808Sharti 747116808Sharti if (priv->ifp->if_ioctl == NULL) 748116808Sharti return ENXIO; 749116808Sharti 750116808Sharti data.vpi = vpi; 751116808Sharti data.vci = vci; 752116808Sharti 753116808Sharti return ((*priv->ifp->if_ioctl)(priv->ifp, 754116808Sharti SIOCATMCLOSEVCC, (caddr_t)&data)); 755116808Sharti} 756116808Sharti 757116808Sharti 758116808Sharti/* 759116808Sharti * Close a channel by request of the user 760116808Sharti */ 761116808Shartistatic int 762116808Sharting_atm_cpcs_term(node_p node, const struct ngm_atm_cpcs_term *arg) 763116808Sharti{ 764116808Sharti struct priv *priv = NG_NODE_PRIVATE(node); 765116808Sharti struct ngvcc *vcc; 766116808Sharti int error; 767116808Sharti 768116808Sharti LIST_FOREACH(vcc, &priv->vccs, link) 769116808Sharti if(strcmp(arg->name, NG_HOOK_NAME(vcc->hook)) == 0) 770116808Sharti break; 771116808Sharti if (vcc == NULL) 772116808Sharti return (ENOTCONN); 773117642Sharti if (!(vcc->flags & VCC_OPEN)) 774116808Sharti return (ENOTCONN); 775116808Sharti 776116808Sharti error = cpcs_term(priv, vcc->vpi, vcc->vci); 777116808Sharti 778116808Sharti vcc->vci = 0; 779116808Sharti vcc->vpi = 0; 780116808Sharti vcc->flags = 0; 781116808Sharti 782116808Sharti return (error); 783116808Sharti} 784116808Sharti 785116808Sharti/************************************************************/ 786116808Sharti/* 787116808Sharti * CONTROL MESSAGES 788116808Sharti */ 789116808Sharti 790116808Sharti/* 791116808Sharti * Produce a textual description of the current status 792116808Sharti */ 793116808Shartistatic int 794116808Shartitext_status(node_p node, char *arg, u_int len) 795116808Sharti{ 796116808Sharti const struct priv *priv = NG_NODE_PRIVATE(node); 797116808Sharti const struct ifatm_mib *mib; 798116808Sharti struct sbuf sbuf; 799116808Sharti u_int i; 800116808Sharti 801116808Sharti static const struct { 802116808Sharti const char *name; 803116808Sharti const char *vendor; 804116808Sharti } devices[] = { 805116808Sharti ATM_DEVICE_NAMES 806116808Sharti }; 807116808Sharti 808116808Sharti mib = (const struct ifatm_mib *)(priv->ifp->if_linkmib); 809116808Sharti 810116808Sharti sbuf_new(&sbuf, arg, len, SBUF_FIXEDLEN); 811116808Sharti sbuf_printf(&sbuf, "interface: %s%d\n", priv->ifp->if_name, 812116808Sharti priv->ifp->if_unit); 813116808Sharti 814116808Sharti if (mib->device >= sizeof(devices) / sizeof(devices[0])) 815116808Sharti sbuf_printf(&sbuf, "device=unknown\nvendor=unknown\n"); 816116808Sharti else 817116808Sharti sbuf_printf(&sbuf, "device=%s\nvendor=%s\n", 818116808Sharti devices[mib->device].name, devices[mib->device].vendor); 819116808Sharti 820116808Sharti for (i = 0; atmmedia[i].name; i++) 821116808Sharti if(mib->media == atmmedia[i].media) { 822116808Sharti sbuf_printf(&sbuf, "media=%s\n", atmmedia[i].name); 823116808Sharti break; 824116808Sharti } 825116808Sharti if(atmmedia[i].name == NULL) 826116808Sharti sbuf_printf(&sbuf, "media=unknown\n"); 827116808Sharti 828116808Sharti sbuf_printf(&sbuf, "serial=%u esi=%6D hardware=%u software=%u\n", 829116808Sharti mib->serial, mib->esi, ":", mib->hw_version, mib->sw_version); 830116808Sharti sbuf_printf(&sbuf, "pcr=%u vpi_bits=%u vci_bits=%u max_vpcs=%u " 831116808Sharti "max_vccs=%u\n", mib->pcr, mib->vpi_bits, mib->vci_bits, 832116808Sharti mib->max_vpcs, mib->max_vccs); 833116808Sharti sbuf_printf(&sbuf, "ifflags=%b\n", priv->ifp->if_flags, IFFLAGS); 834116808Sharti 835116808Sharti sbuf_finish(&sbuf); 836116808Sharti 837116808Sharti return (sbuf_len(&sbuf)); 838116808Sharti} 839116808Sharti 840116808Sharti/* 841116808Sharti * Get control message 842116808Sharti */ 843116808Shartistatic int 844116808Sharting_atm_rcvmsg(node_p node, item_p item, hook_p lasthook) 845116808Sharti{ 846116808Sharti const struct priv *priv = NG_NODE_PRIVATE(node); 847116808Sharti struct ng_mesg *resp = NULL; 848116808Sharti struct ng_mesg *msg; 849116808Sharti struct ifatm_mib *mib = (struct ifatm_mib *)(priv->ifp->if_linkmib); 850116808Sharti int error = 0; 851116808Sharti 852116808Sharti NGI_GET_MSG(item, msg); 853116808Sharti 854116808Sharti switch (msg->header.typecookie) { 855116808Sharti 856116808Sharti case NGM_GENERIC_COOKIE: 857116808Sharti switch (msg->header.cmd) { 858116808Sharti 859116808Sharti case NGM_TEXT_STATUS: 860116808Sharti NG_MKRESPONSE(resp, msg, NG_TEXTRESPONSE, M_NOWAIT); 861116808Sharti if(resp == NULL) { 862116808Sharti error = ENOMEM; 863116808Sharti break; 864116808Sharti } 865116808Sharti 866116808Sharti resp->header.arglen = text_status(node, 867116808Sharti (char *)resp->data, resp->header.arglen) + 1; 868116808Sharti break; 869116808Sharti 870116808Sharti default: 871116808Sharti error = EINVAL; 872116808Sharti break; 873116808Sharti } 874116808Sharti break; 875116808Sharti 876116808Sharti case NGM_ATM_COOKIE: 877116808Sharti switch (msg->header.cmd) { 878116808Sharti 879116808Sharti case NGM_ATM_GET_IFNAME: 880116808Sharti NG_MKRESPONSE(resp, msg, IFNAMSIZ + 1, M_NOWAIT); 881116808Sharti if (resp == NULL) { 882116808Sharti error = ENOMEM; 883116808Sharti break; 884116808Sharti } 885116808Sharti snprintf(resp->data, IFNAMSIZ + 1, "%s%d", 886116808Sharti priv->ifp->if_name, priv->ifp->if_unit); 887116808Sharti break; 888116808Sharti 889116808Sharti case NGM_ATM_GET_CONFIG: 890116808Sharti { 891116808Sharti struct ngm_atm_config *config; 892116808Sharti 893116808Sharti NG_MKRESPONSE(resp, msg, sizeof(*config), M_NOWAIT); 894116808Sharti if (resp == NULL) { 895116808Sharti error = ENOMEM; 896116808Sharti break; 897116808Sharti } 898116808Sharti config = (struct ngm_atm_config *)resp->data; 899116808Sharti config->pcr = mib->pcr; 900116808Sharti config->vpi_bits = mib->vpi_bits; 901116808Sharti config->vci_bits = mib->vci_bits; 902116808Sharti config->max_vpcs = mib->max_vpcs; 903116808Sharti config->max_vccs = mib->max_vccs; 904116808Sharti break; 905116808Sharti } 906116808Sharti 907116808Sharti case NGM_ATM_GET_VCCS: 908116808Sharti { 909116808Sharti struct atmio_vcctable *vccs; 910116808Sharti size_t len; 911116808Sharti 912116808Sharti if (priv->ifp->if_ioctl == NULL) { 913116808Sharti error = ENXIO; 914116808Sharti break; 915116808Sharti } 916116808Sharti error = (*priv->ifp->if_ioctl)(priv->ifp, 917116808Sharti SIOCATMGETVCCS, (caddr_t)&vccs); 918116808Sharti if (error) 919116808Sharti break; 920116808Sharti 921116808Sharti len = sizeof(*vccs) + 922116808Sharti vccs->count * sizeof(vccs->vccs[0]); 923116808Sharti NG_MKRESPONSE(resp, msg, len, M_NOWAIT); 924116808Sharti if (resp == NULL) { 925116808Sharti error = ENOMEM; 926116808Sharti free(vccs, M_DEVBUF); 927116808Sharti break; 928116808Sharti } 929116808Sharti 930116808Sharti (void)memcpy(resp->data, vccs, len); 931116808Sharti free(vccs, M_DEVBUF); 932116808Sharti 933116808Sharti break; 934116808Sharti } 935116808Sharti 936116808Sharti case NGM_ATM_GET_VCC: 937116808Sharti { 938116808Sharti char hook[NG_HOOKLEN + 1]; 939116808Sharti struct atmio_vcctable *vccs; 940116808Sharti struct ngvcc *vcc; 941116808Sharti u_int i; 942116808Sharti 943116808Sharti if (priv->ifp->if_ioctl == NULL) { 944116808Sharti error = ENXIO; 945116808Sharti break; 946116808Sharti } 947116808Sharti if (msg->header.arglen != NG_HOOKLEN + 1) { 948116808Sharti error = EINVAL; 949116808Sharti break; 950116808Sharti } 951116808Sharti strncpy(hook, msg->data, NG_HOOKLEN + 1); 952116808Sharti hook[NG_HOOKLEN] = '\0'; 953116808Sharti LIST_FOREACH(vcc, &priv->vccs, link) 954116808Sharti if (strcmp(NG_HOOK_NAME(vcc->hook), hook) == 0) 955116808Sharti break; 956116808Sharti if (vcc == NULL) { 957116808Sharti error = ENOTCONN; 958116808Sharti break; 959116808Sharti } 960116808Sharti error = (*priv->ifp->if_ioctl)(priv->ifp, 961116808Sharti SIOCATMGETVCCS, (caddr_t)&vccs); 962116808Sharti if (error) 963116808Sharti break; 964116808Sharti 965116808Sharti for (i = 0; i < vccs->count; i++) 966116808Sharti if (vccs->vccs[i].vpi == vcc->vpi && 967116808Sharti vccs->vccs[i].vci == vcc->vci) 968116808Sharti break; 969116808Sharti if (i == vccs->count) { 970116808Sharti error = ENOTCONN; 971116808Sharti free(vccs, M_DEVBUF); 972116808Sharti break; 973116808Sharti } 974116808Sharti 975116808Sharti NG_MKRESPONSE(resp, msg, sizeof(vccs->vccs[0]), 976116808Sharti M_NOWAIT); 977116808Sharti if (resp == NULL) { 978116808Sharti error = ENOMEM; 979116808Sharti free(vccs, M_DEVBUF); 980116808Sharti break; 981116808Sharti } 982116808Sharti 983116808Sharti *(struct atmio_vcc *)resp->data = vccs->vccs[i]; 984116808Sharti free(vccs, M_DEVBUF); 985116808Sharti break; 986116808Sharti } 987116808Sharti 988116808Sharti case NGM_ATM_GET_VCCID: 989116808Sharti { 990116808Sharti struct atmio_vcc *arg; 991116808Sharti struct atmio_vcctable *vccs; 992116808Sharti u_int i; 993116808Sharti 994116808Sharti if (priv->ifp->if_ioctl == NULL) { 995116808Sharti error = ENXIO; 996116808Sharti break; 997116808Sharti } 998116808Sharti if (msg->header.arglen != sizeof(*arg)) { 999116808Sharti error = EINVAL; 1000116808Sharti break; 1001116808Sharti } 1002116808Sharti arg = (struct atmio_vcc *)msg->data; 1003116808Sharti 1004116808Sharti error = (*priv->ifp->if_ioctl)(priv->ifp, 1005116808Sharti SIOCATMGETVCCS, (caddr_t)&vccs); 1006116808Sharti if (error) 1007116808Sharti break; 1008116808Sharti 1009116808Sharti for (i = 0; i < vccs->count; i++) 1010116808Sharti if (vccs->vccs[i].vpi == arg->vpi && 1011116808Sharti vccs->vccs[i].vci == arg->vci) 1012116808Sharti break; 1013116808Sharti if (i == vccs->count) { 1014116808Sharti error = ENOTCONN; 1015116808Sharti free(vccs, M_DEVBUF); 1016116808Sharti break; 1017116808Sharti } 1018116808Sharti 1019116808Sharti NG_MKRESPONSE(resp, msg, sizeof(vccs->vccs[0]), 1020116808Sharti M_NOWAIT); 1021116808Sharti if (resp == NULL) { 1022116808Sharti error = ENOMEM; 1023116808Sharti free(vccs, M_DEVBUF); 1024116808Sharti break; 1025116808Sharti } 1026116808Sharti 1027116808Sharti *(struct atmio_vcc *)resp->data = vccs->vccs[i]; 1028116808Sharti free(vccs, M_DEVBUF); 1029116808Sharti break; 1030116808Sharti } 1031116808Sharti 1032116808Sharti case NGM_ATM_CPCS_INIT: 1033116808Sharti if (msg->header.arglen != 1034116808Sharti sizeof(struct ngm_atm_cpcs_init)) { 1035116808Sharti error = EINVAL; 1036116808Sharti break; 1037116808Sharti } 1038116808Sharti error = ng_atm_cpcs_init(node, 1039116808Sharti (struct ngm_atm_cpcs_init *)msg->data); 1040116808Sharti break; 1041116808Sharti 1042116808Sharti case NGM_ATM_CPCS_TERM: 1043116808Sharti if (msg->header.arglen != 1044116808Sharti sizeof(struct ngm_atm_cpcs_term)) { 1045116808Sharti error = EINVAL; 1046116808Sharti break; 1047116808Sharti } 1048116808Sharti error = ng_atm_cpcs_term(node, 1049116808Sharti (struct ngm_atm_cpcs_term *)msg->data); 1050116808Sharti break; 1051116808Sharti 1052116808Sharti case NGM_ATM_GET_STATS: 1053116808Sharti { 1054116808Sharti struct ngm_atm_stats *p; 1055116808Sharti 1056116808Sharti if (msg->header.arglen != 0) { 1057116808Sharti error = EINVAL; 1058116808Sharti break; 1059116808Sharti } 1060116808Sharti NG_MKRESPONSE(resp, msg, sizeof(*p), M_NOWAIT); 1061116808Sharti if (resp == NULL) { 1062116808Sharti error = ENOMEM; 1063116808Sharti break; 1064116808Sharti } 1065116808Sharti p = (struct ngm_atm_stats *)resp->data; 1066116808Sharti p->in_packets = priv->in_packets; 1067116808Sharti p->out_packets = priv->out_packets; 1068116808Sharti p->in_errors = priv->in_errors; 1069116808Sharti p->out_errors = priv->out_errors; 1070116808Sharti 1071116808Sharti break; 1072116808Sharti } 1073116808Sharti 1074116808Sharti default: 1075116808Sharti error = EINVAL; 1076116808Sharti break; 1077116808Sharti } 1078116808Sharti break; 1079116808Sharti 1080116808Sharti default: 1081116808Sharti error = EINVAL; 1082116808Sharti break; 1083116808Sharti } 1084116808Sharti 1085116808Sharti NG_RESPOND_MSG(error, node, item, resp); 1086116808Sharti NG_FREE_MSG(msg); 1087116808Sharti return (error); 1088116808Sharti} 1089116808Sharti 1090116808Sharti/************************************************************/ 1091116808Sharti/* 1092116808Sharti * HOOK MANAGEMENT 1093116808Sharti */ 1094116808Sharti 1095116808Sharti/* 1096116808Sharti * A new hook is create that will be connected to the node. 1097116808Sharti * Check, whether the name is one of the predefined ones. 1098116808Sharti * If not, create a new entry into the vcc list. 1099116808Sharti */ 1100116808Shartistatic int 1101116808Sharting_atm_newhook(node_p node, hook_p hook, const char *name) 1102116808Sharti{ 1103116808Sharti struct priv *priv = NG_NODE_PRIVATE(node); 1104116808Sharti struct ngvcc *vcc; 1105116808Sharti 1106116808Sharti if (strcmp(name, "input") == 0) { 1107116808Sharti priv->input = hook; 1108116808Sharti NG_HOOK_SET_RCVDATA(hook, ng_atm_rcvdrop); 1109116808Sharti return (0); 1110116808Sharti } 1111116808Sharti if (strcmp(name, "output") == 0) { 1112116808Sharti priv->output = hook; 1113116808Sharti NG_HOOK_SET_RCVDATA(hook, ng_atm_rcvdrop); 1114116808Sharti return (0); 1115116808Sharti } 1116116808Sharti if (strcmp(name, "orphans") == 0) { 1117116808Sharti priv->orphans = hook; 1118116808Sharti NG_HOOK_SET_RCVDATA(hook, ng_atm_rcvdrop); 1119116808Sharti return (0); 1120116808Sharti } 1121116808Sharti 1122116808Sharti /* 1123116808Sharti * Allocate a new entry 1124116808Sharti */ 1125116808Sharti vcc = malloc(sizeof(*vcc), M_NETGRAPH, M_NOWAIT | M_ZERO); 1126116808Sharti if (vcc == NULL) 1127116808Sharti return (ENOMEM); 1128116808Sharti 1129116808Sharti vcc->hook = hook; 1130116808Sharti NG_HOOK_SET_PRIVATE(hook, vcc); 1131116808Sharti 1132116808Sharti LIST_INSERT_HEAD(&priv->vccs, vcc, link); 1133116808Sharti 1134116808Sharti if (strcmp(name, "manage") == 0) 1135116808Sharti priv->manage = hook; 1136116808Sharti 1137116808Sharti return (0); 1138116808Sharti} 1139116808Sharti 1140116808Sharti/* 1141116808Sharti * Connect. Set the peer to queuing. 1142116808Sharti */ 1143116808Shartistatic int 1144116808Sharting_atm_connect(hook_p hook) 1145116808Sharti{ 1146116808Sharti if (NG_HOOK_PRIVATE(hook) != NULL) 1147116808Sharti NG_HOOK_FORCE_QUEUE(NG_HOOK_PEER(hook)); 1148116808Sharti 1149116808Sharti return (0); 1150116808Sharti} 1151116808Sharti 1152116808Sharti/* 1153116808Sharti * Disconnect a HOOK 1154116808Sharti */ 1155116808Shartistatic int 1156116808Sharting_atm_disconnect(hook_p hook) 1157116808Sharti{ 1158116808Sharti struct priv *priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); 1159116808Sharti struct ngvcc *vcc = NG_HOOK_PRIVATE(hook); 1160116808Sharti 1161116808Sharti if (vcc == NULL) { 1162116808Sharti if (hook == priv->output) { 1163116808Sharti priv->output = NULL; 1164116808Sharti return (0); 1165116808Sharti } 1166116808Sharti if (hook == priv->input) { 1167116808Sharti priv->input = NULL; 1168116808Sharti return (0); 1169116808Sharti } 1170116808Sharti if (hook == priv->orphans) { 1171116808Sharti priv->orphans = NULL; 1172116808Sharti return (0); 1173116808Sharti } 1174116808Sharti log(LOG_ERR, "ng_atm: bad hook '%s'", NG_HOOK_NAME(hook)); 1175116808Sharti return (0); 1176116808Sharti } 1177116808Sharti 1178116808Sharti /* don't terminate if we are detaching from the interface */ 1179117157Sharti if ((vcc->flags & VCC_OPEN) && priv->ifp != NULL) 1180116808Sharti (void)cpcs_term(priv, vcc->vpi, vcc->vci); 1181116808Sharti 1182116808Sharti NG_HOOK_SET_PRIVATE(hook, NULL); 1183116808Sharti 1184116808Sharti LIST_REMOVE(vcc, link); 1185116808Sharti free(vcc, M_NETGRAPH); 1186116808Sharti 1187116808Sharti if (hook == priv->manage) 1188116808Sharti priv->manage = NULL; 1189116808Sharti 1190116808Sharti return (0); 1191116808Sharti} 1192116808Sharti 1193116808Sharti/************************************************************/ 1194116808Sharti/* 1195116808Sharti * NODE MANAGEMENT 1196116808Sharti */ 1197116808Sharti 1198116808Sharti/* 1199116808Sharti * ATM interface attached - create a node and name it like the interface. 1200116808Sharti */ 1201116808Shartistatic void 1202116808Sharting_atm_attach(struct ifnet *ifp) 1203116808Sharti{ 1204116808Sharti char name[IFNAMSIZ+1]; 1205116808Sharti node_p node; 1206116808Sharti struct priv *priv; 1207116808Sharti 1208116808Sharti KASSERT(IFP2NG(ifp) == 0, ("%s: node alreay exists?", __FUNCTION__)); 1209116808Sharti 1210116808Sharti snprintf(name, sizeof(name), "%s%d", ifp->if_name, ifp->if_unit); 1211116808Sharti 1212116808Sharti if (ng_make_node_common(&ng_atm_typestruct, &node) != 0) { 1213116808Sharti log(LOG_ERR, "%s: can't create node for %s\n", 1214116808Sharti __FUNCTION__, name); 1215116808Sharti return; 1216116808Sharti } 1217116808Sharti 1218116808Sharti priv = malloc(sizeof(*priv), M_NETGRAPH, M_NOWAIT | M_ZERO); 1219116808Sharti if (priv == NULL) { 1220116808Sharti log(LOG_ERR, "%s: can't allocate memory for %s\n", 1221116808Sharti __FUNCTION__, name); 1222116808Sharti NG_NODE_UNREF(node); 1223116808Sharti return; 1224116808Sharti } 1225116808Sharti NG_NODE_SET_PRIVATE(node, priv); 1226116808Sharti priv->ifp = ifp; 1227116808Sharti LIST_INIT(&priv->vccs); 1228116808Sharti IFP2NG(ifp) = node; 1229116808Sharti 1230116808Sharti if (ng_name_node(node, name) != 0) { 1231116808Sharti log(LOG_WARNING, "%s: can't name node %s\n", 1232116808Sharti __FUNCTION__, name); 1233116808Sharti } 1234116808Sharti} 1235116808Sharti 1236116808Sharti/* 1237116808Sharti * ATM interface detached - destroy node. 1238116808Sharti */ 1239116808Shartistatic void 1240116808Sharting_atm_detach(struct ifnet *ifp) 1241116808Sharti{ 1242116808Sharti const node_p node = IFP2NG(ifp); 1243116808Sharti struct priv *priv; 1244116808Sharti 1245116808Sharti if(node == NULL) 1246116808Sharti return; 1247116808Sharti 1248116808Sharti NG_NODE_REALLY_DIE(node); 1249116808Sharti 1250116808Sharti priv = NG_NODE_PRIVATE(node); 1251116808Sharti IFP2NG(priv->ifp) = NULL; 1252116808Sharti priv->ifp = NULL; 1253116808Sharti 1254116808Sharti ng_rmnode_self(node); 1255116808Sharti} 1256116808Sharti 1257116808Sharti/* 1258116808Sharti * Shutdown the node. This is called from the shutdown message processing. 1259116808Sharti */ 1260116808Shartistatic int 1261116808Sharting_atm_shutdown(node_p node) 1262116808Sharti{ 1263116808Sharti struct priv *priv = NG_NODE_PRIVATE(node); 1264116808Sharti 1265116808Sharti if (node->nd_flags & NG_REALLY_DIE) { 1266116808Sharti /* 1267116808Sharti * We are called from unloading the ATM driver. Really, 1268116808Sharti * really need to shutdown this node. The ifp was 1269116808Sharti * already handled in the detach routine. 1270116808Sharti */ 1271116808Sharti NG_NODE_SET_PRIVATE(node, NULL); 1272116808Sharti free(priv, M_NETGRAPH); 1273116808Sharti 1274116808Sharti NG_NODE_UNREF(node); 1275116808Sharti return (0); 1276116808Sharti } 1277116808Sharti 1278116808Sharti#ifdef NGATM_DEBUG 1279116808Sharti if (!allow_shutdown) 1280116808Sharti node->nd_flags &= ~NG_INVALID; 1281116808Sharti else { 1282116808Sharti IFP2NG(priv->ifp) = NULL; 1283116808Sharti NG_NODE_SET_PRIVATE(node, NULL); 1284116808Sharti free(priv, M_NETGRAPH); 1285116808Sharti NG_NODE_UNREF(node); 1286116808Sharti } 1287116808Sharti#else 1288116808Sharti /* 1289116808Sharti * We are persistant - reinitialize 1290116808Sharti */ 1291116808Sharti node->nd_flags &= ~NG_INVALID; 1292116808Sharti#endif 1293116808Sharti return (0); 1294116808Sharti} 1295116808Sharti 1296116808Sharti/* 1297116808Sharti * Nodes are constructed only via interface attaches. 1298116808Sharti */ 1299116808Shartistatic int 1300116808Sharting_atm_constructor(node_p nodep) 1301116808Sharti{ 1302116808Sharti return (EINVAL); 1303116808Sharti} 1304116808Sharti 1305116808Sharti/************************************************************/ 1306116808Sharti/* 1307116808Sharti * INITIALISATION 1308116808Sharti */ 1309116808Sharti/* 1310116808Sharti * Loading and unloading of node type 1311116808Sharti * 1312116808Sharti * The assignments to the globals for the hooks should be ok without 1313116808Sharti * a special hook. The use pattern is generally: check that the pointer 1314116808Sharti * is not NULL, call the function. In the attach case this is no problem. 1315116808Sharti * In the detach case we can detach only when no ATM node exists. That 1316116808Sharti * means that there is no ATM interface anymore. So we are sure that 1317116808Sharti * we are not in the code path in if_atmsubr.c. To prevent someone 1318116808Sharti * from adding an interface after we have started to unload the node, we 1319116808Sharti * take the iflist lock so an if_attach will be blocked until we are done. 1320116808Sharti * XXX: perhaps the function pointers should be 'volatile' for this to work 1321116808Sharti * properly. 1322116808Sharti */ 1323116808Shartistatic int 1324116808Sharting_atm_mod_event(module_t mod, int event, void *data) 1325116808Sharti{ 1326116808Sharti struct ifnet *ifp; 1327116808Sharti int error = 0; 1328116808Sharti 1329116808Sharti switch (event) { 1330116808Sharti 1331116808Sharti case MOD_LOAD: 1332116808Sharti /* 1333116808Sharti * Register function hooks 1334116808Sharti */ 1335116808Sharti if (ng_atm_attach_p != NULL) { 1336116808Sharti error = EEXIST; 1337116808Sharti break; 1338116808Sharti } 1339116808Sharti IFNET_RLOCK(); 1340116808Sharti 1341116808Sharti ng_atm_attach_p = ng_atm_attach; 1342116808Sharti ng_atm_detach_p = ng_atm_detach; 1343116808Sharti ng_atm_output_p = ng_atm_output; 1344116808Sharti ng_atm_input_p = ng_atm_input; 1345116808Sharti ng_atm_input_orphan_p = ng_atm_input_orphans; 1346116808Sharti ng_atm_message_p = ng_atm_message; 1347116808Sharti 1348116808Sharti /* Create nodes for existing ATM interfaces */ 1349116808Sharti TAILQ_FOREACH(ifp, &ifnet, if_link) { 1350116808Sharti if (ifp->if_type == IFT_ATM) 1351116808Sharti ng_atm_attach(ifp); 1352116808Sharti } 1353116808Sharti IFNET_RUNLOCK(); 1354116808Sharti break; 1355116808Sharti 1356116808Sharti case MOD_UNLOAD: 1357116808Sharti IFNET_RLOCK(); 1358116808Sharti 1359116808Sharti ng_atm_attach_p = NULL; 1360116808Sharti ng_atm_detach_p = NULL; 1361116808Sharti ng_atm_output_p = NULL; 1362116808Sharti ng_atm_input_p = NULL; 1363116808Sharti ng_atm_input_orphan_p = NULL; 1364116808Sharti ng_atm_message_p = NULL; 1365116808Sharti 1366116808Sharti TAILQ_FOREACH(ifp, &ifnet, if_link) { 1367116808Sharti if (ifp->if_type == IFT_ATM) 1368116808Sharti ng_atm_detach(ifp); 1369116808Sharti } 1370116808Sharti IFNET_RUNLOCK(); 1371116808Sharti break; 1372116808Sharti 1373116808Sharti default: 1374116808Sharti error = EOPNOTSUPP; 1375116808Sharti break; 1376116808Sharti } 1377116808Sharti return (error); 1378116808Sharti} 1379