ng_atm.c revision 121816
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 121816 2003-10-31 18:32:15Z brooks $"); 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 *); 70118175Shartiextern void (*ng_atm_event_p)(struct ifnet *, uint32_t, void *); 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/* 115118175Sharti * Parse ifstate state 116116808Sharti */ 117118175Shartistatic const struct ng_parse_struct_field ng_atm_if_change_info[] = 118118175Sharti NGM_ATM_IF_CHANGE_INFO; 119118175Shartistatic const struct ng_parse_type ng_atm_if_change_type = { 120116808Sharti &ng_parse_struct_type, 121118175Sharti &ng_atm_if_change_info 122116808Sharti}; 123116808Sharti 124116808Sharti/* 125118175Sharti * Parse vcc state change 126118175Sharti */ 127118175Shartistatic const struct ng_parse_struct_field ng_atm_vcc_change_info[] = 128118175Sharti NGM_ATM_VCC_CHANGE_INFO; 129118175Shartistatic const struct ng_parse_type ng_atm_vcc_change_type = { 130118175Sharti &ng_parse_struct_type, 131118175Sharti &ng_atm_vcc_change_info 132118175Sharti}; 133118175Sharti 134118175Sharti/* 135118175Sharti * Parse acr change 136118175Sharti */ 137118175Shartistatic const struct ng_parse_struct_field ng_atm_acr_change_info[] = 138118175Sharti NGM_ATM_ACR_CHANGE_INFO; 139118175Shartistatic const struct ng_parse_type ng_atm_acr_change_type = { 140118175Sharti &ng_parse_struct_type, 141118175Sharti &ng_atm_acr_change_info 142118175Sharti}; 143118175Sharti 144118175Sharti/* 145116808Sharti * Parse the configuration structure ng_atm_config 146116808Sharti */ 147116808Shartistatic const struct ng_parse_struct_field ng_atm_config_type_info[] = 148116808Sharti NGM_ATM_CONFIG_INFO; 149116808Sharti 150116808Shartistatic const struct ng_parse_type ng_atm_config_type = { 151116808Sharti &ng_parse_struct_type, 152116808Sharti &ng_atm_config_type_info 153116808Sharti}; 154116808Sharti 155116808Sharti/* 156116808Sharti * Parse a single vcc structure and a variable array of these ng_atm_vccs 157116808Sharti */ 158116808Shartistatic const struct ng_parse_struct_field ng_atm_tparam_type_info[] = 159116808Sharti NGM_ATM_TPARAM_INFO; 160116808Shartistatic const struct ng_parse_type ng_atm_tparam_type = { 161116808Sharti &ng_parse_struct_type, 162116808Sharti &ng_atm_tparam_type_info 163116808Sharti}; 164116808Shartistatic const struct ng_parse_struct_field ng_atm_vcc_type_info[] = 165116808Sharti NGM_ATM_VCC_INFO; 166116808Shartistatic const struct ng_parse_type ng_atm_vcc_type = { 167116808Sharti &ng_parse_struct_type, 168116808Sharti &ng_atm_vcc_type_info 169116808Sharti}; 170116808Sharti 171116808Sharti 172116808Shartistatic int 173116808Sharting_atm_vccarray_getlen(const struct ng_parse_type *type, 174116808Sharti const u_char *start, const u_char *buf) 175116808Sharti{ 176116808Sharti const struct atmio_vcctable *vp; 177116808Sharti 178116808Sharti vp = (const struct atmio_vcctable *) 179116808Sharti (buf - offsetof(struct atmio_vcctable, vccs)); 180116808Sharti 181116808Sharti return (vp->count); 182116808Sharti} 183116808Shartistatic const struct ng_parse_array_info ng_atm_vccarray_info = 184116808Sharti NGM_ATM_VCCARRAY_INFO; 185116808Shartistatic const struct ng_parse_type ng_atm_vccarray_type = { 186116808Sharti &ng_parse_array_type, 187116808Sharti &ng_atm_vccarray_info 188116808Sharti}; 189116808Sharti 190116808Sharti 191116808Shartistatic const struct ng_parse_struct_field ng_atm_vcctable_type_info[] = 192116808Sharti NGM_ATM_VCCTABLE_INFO; 193116808Sharti 194116808Shartistatic const struct ng_parse_type ng_atm_vcctable_type = { 195116808Sharti &ng_parse_struct_type, 196116808Sharti &ng_atm_vcctable_type_info 197116808Sharti}; 198116808Sharti 199116808Sharti/* 200116808Sharti * Parse CPCS INIT structure ng_atm_cpcs_init 201116808Sharti */ 202116808Shartistatic const struct ng_parse_struct_field ng_atm_cpcs_init_type_info[] = 203116808Sharti NGM_ATM_CPCS_INIT_INFO; 204116808Sharti 205116808Shartistatic const struct ng_parse_type ng_atm_cpcs_init_type = { 206116808Sharti &ng_parse_struct_type, 207116808Sharti &ng_atm_cpcs_init_type_info 208116808Sharti}; 209116808Sharti 210116808Sharti/* 211116808Sharti * Parse CPCS TERM structure ng_atm_cpcs_term 212116808Sharti */ 213116808Shartistatic const struct ng_parse_struct_field ng_atm_cpcs_term_type_info[] = 214116808Sharti NGM_ATM_CPCS_TERM_INFO; 215116808Sharti 216116808Shartistatic const struct ng_parse_type ng_atm_cpcs_term_type = { 217116808Sharti &ng_parse_struct_type, 218116808Sharti &ng_atm_cpcs_term_type_info 219116808Sharti}; 220116808Sharti 221116808Sharti/* 222116808Sharti * Parse statistic struct 223116808Sharti */ 224116808Shartistatic const struct ng_parse_struct_field ng_atm_stats_type_info[] = 225116808Sharti NGM_ATM_STATS_INFO; 226116808Sharti 227116808Shartistatic const struct ng_parse_type ng_atm_stats_type = { 228116808Sharti &ng_parse_struct_type, 229116808Sharti &ng_atm_stats_type_info 230116808Sharti}; 231116808Sharti 232116808Shartistatic const struct ng_cmdlist ng_atm_cmdlist[] = { 233116808Sharti { 234116808Sharti NGM_ATM_COOKIE, 235116808Sharti NGM_ATM_GET_IFNAME, 236116808Sharti "getifname", 237116808Sharti NULL, 238116808Sharti &ng_parse_string_type 239116808Sharti }, 240116808Sharti { 241116808Sharti NGM_ATM_COOKIE, 242116808Sharti NGM_ATM_GET_CONFIG, 243116808Sharti "getconfig", 244116808Sharti NULL, 245116808Sharti &ng_atm_config_type 246116808Sharti }, 247116808Sharti { 248116808Sharti NGM_ATM_COOKIE, 249116808Sharti NGM_ATM_GET_VCCS, 250116808Sharti "getvccs", 251116808Sharti NULL, 252116808Sharti &ng_atm_vcctable_type 253116808Sharti }, 254116808Sharti { 255116808Sharti NGM_ATM_COOKIE, 256116808Sharti NGM_ATM_CPCS_INIT, 257116808Sharti "cpcsinit", 258116808Sharti &ng_atm_cpcs_init_type, 259116808Sharti NULL 260116808Sharti }, 261116808Sharti { 262116808Sharti NGM_ATM_COOKIE, 263116808Sharti NGM_ATM_CPCS_TERM, 264116808Sharti "cpcsterm", 265116808Sharti &ng_atm_cpcs_term_type, 266116808Sharti NULL 267116808Sharti }, 268116808Sharti { 269116808Sharti NGM_ATM_COOKIE, 270116808Sharti NGM_ATM_GET_VCC, 271116808Sharti "getvcc", 272116808Sharti &ng_parse_hookbuf_type, 273116808Sharti &ng_atm_vcc_type 274116808Sharti }, 275116808Sharti { 276116808Sharti NGM_ATM_COOKIE, 277116808Sharti NGM_ATM_GET_VCCID, 278116808Sharti "getvccid", 279116808Sharti &ng_atm_vcc_type, 280116808Sharti &ng_atm_vcc_type 281116808Sharti }, 282116808Sharti { 283116808Sharti NGM_ATM_COOKIE, 284116808Sharti NGM_ATM_GET_STATS, 285116808Sharti "getstats", 286116808Sharti NULL, 287116808Sharti &ng_atm_stats_type 288116808Sharti }, 289118175Sharti 290118175Sharti /* events */ 291118175Sharti { 292118175Sharti NGM_ATM_COOKIE, 293118175Sharti NGM_ATM_IF_CHANGE, 294118175Sharti "if_change", 295118175Sharti &ng_atm_if_change_type, 296118175Sharti &ng_atm_if_change_type, 297118175Sharti }, 298118175Sharti { 299118175Sharti NGM_ATM_COOKIE, 300118175Sharti NGM_ATM_VCC_CHANGE, 301118175Sharti "vcc_change", 302118175Sharti &ng_atm_vcc_change_type, 303118175Sharti &ng_atm_vcc_change_type, 304118175Sharti }, 305118175Sharti { 306118175Sharti NGM_ATM_COOKIE, 307118175Sharti NGM_ATM_ACR_CHANGE, 308118175Sharti "acr_change", 309118175Sharti &ng_atm_acr_change_type, 310118175Sharti &ng_atm_acr_change_type, 311118175Sharti }, 312116808Sharti { 0 } 313116808Sharti}; 314116808Sharti 315116808Shartistatic int ng_atm_mod_event(module_t, int, void *); 316116808Sharti 317116808Shartistatic ng_constructor_t ng_atm_constructor; 318116808Shartistatic ng_shutdown_t ng_atm_shutdown; 319116808Shartistatic ng_rcvmsg_t ng_atm_rcvmsg; 320116808Shartistatic ng_newhook_t ng_atm_newhook; 321116808Shartistatic ng_connect_t ng_atm_connect; 322116808Shartistatic ng_disconnect_t ng_atm_disconnect; 323116808Shartistatic ng_rcvdata_t ng_atm_rcvdata; 324116808Shartistatic ng_rcvdata_t ng_atm_rcvdrop; 325116808Sharti 326116808Shartistatic struct ng_type ng_atm_typestruct = { 327116808Sharti NG_ABI_VERSION, 328116808Sharti NG_ATM_NODE_TYPE, 329116808Sharti ng_atm_mod_event, /* Module event handler (optional) */ 330116808Sharti ng_atm_constructor, /* Node constructor */ 331116808Sharti ng_atm_rcvmsg, /* control messages come here */ 332116808Sharti ng_atm_shutdown, /* reset, and free resources */ 333116808Sharti ng_atm_newhook, /* first notification of new hook */ 334116808Sharti NULL, /* findhook */ 335116808Sharti ng_atm_connect, /* connect */ 336116808Sharti ng_atm_rcvdata, /* rcvdata */ 337116808Sharti ng_atm_disconnect, /* notify on disconnect */ 338116808Sharti ng_atm_cmdlist, 339116808Sharti}; 340116808ShartiNETGRAPH_INIT(atm, &ng_atm_typestruct); 341116808Sharti 342116808Shartistatic const struct { 343116808Sharti u_int media; 344116808Sharti const char *name; 345116808Sharti} atmmedia[] = IFM_SUBTYPE_ATM_DESCRIPTIONS; 346116808Sharti 347116808Sharti 348116808Sharti#define IFP2NG(IFP) ((node_p)((struct ifatm *)(IFP))->ngpriv) 349116808Sharti 350116808Sharti#define IFFLAGS "\020\001UP\002BROADCAST\003DEBUG\004LOOPBACK" \ 351116808Sharti "\005POINTOPOINT\006SMART\007RUNNING\010NOARP" \ 352116808Sharti "\011PROMISC\012ALLMULTI\013OACTIVE\014SIMPLEX" \ 353116808Sharti "\015LINK0\016LINK1\017LINK2\020MULTICAST" 354116808Sharti 355116808Sharti 356116808Sharti/************************************************************/ 357116808Sharti/* 358116808Sharti * INPUT 359116808Sharti */ 360116808Sharti/* 361116808Sharti * A packet is received from an interface. 362116808Sharti * If we have an input hook, prepend the pseudoheader to the data and 363116808Sharti * deliver it out to that hook. If not, look whether it is destined for 364116808Sharti * use. If so locate the appropriate hook, deliver the packet without the 365116808Sharti * header and we are done. If it is not for us, leave it alone. 366116808Sharti */ 367116808Shartistatic void 368116808Sharting_atm_input(struct ifnet *ifp, struct mbuf **mp, 369116808Sharti struct atm_pseudohdr *ah, void *rxhand) 370116808Sharti{ 371116808Sharti node_p node = IFP2NG(ifp); 372116808Sharti struct priv *priv; 373116808Sharti const struct ngvcc *vcc; 374116808Sharti int error; 375116808Sharti 376116808Sharti if (node == NULL) 377116808Sharti return; 378116808Sharti priv = NG_NODE_PRIVATE(node); 379116808Sharti if (priv->input != NULL) { 380116808Sharti /* 381116808Sharti * Prepend the atm_pseudoheader. 382116808Sharti */ 383116808Sharti M_PREPEND(*mp, sizeof(*ah), M_DONTWAIT); 384116808Sharti if (*mp == NULL) 385116808Sharti return; 386116808Sharti memcpy(mtod(*mp, struct atm_pseudohdr *), ah, sizeof(*ah)); 387116808Sharti NG_SEND_DATA_ONLY(error, priv->input, *mp); 388116808Sharti if (error == 0) { 389116808Sharti priv->in_packets++; 390116808Sharti *mp = NULL; 391116808Sharti } else { 392116808Sharti#ifdef NGATM_DEBUG 393116808Sharti printf("%s: error=%d\n", __func__, error); 394116808Sharti#endif 395116808Sharti priv->in_errors++; 396116808Sharti } 397116808Sharti return; 398116808Sharti } 399116808Sharti if ((ATM_PH_FLAGS(ah) & ATMIO_FLAG_NG) == 0) 400116808Sharti return; 401116808Sharti 402116808Sharti vcc = (struct ngvcc *)rxhand; 403116808Sharti 404116808Sharti NG_SEND_DATA_ONLY(error, vcc->hook, *mp); 405116808Sharti if (error == 0) { 406116808Sharti priv->in_packets++; 407116808Sharti *mp = NULL; 408116808Sharti } else { 409116808Sharti#ifdef NGATM_DEBUG 410116808Sharti printf("%s: error=%d\n", __func__, error); 411116808Sharti#endif 412116808Sharti priv->in_errors++; 413116808Sharti } 414116808Sharti} 415116808Sharti 416116808Sharti/* 417116808Sharti * ATM packet is about to be output. The atm_pseudohdr is already prepended. 418116808Sharti * If the hook is set, reroute the packet to the hook. 419116808Sharti */ 420116808Shartistatic int 421116808Sharting_atm_output(struct ifnet *ifp, struct mbuf **mp) 422116808Sharti{ 423116808Sharti const node_p node = IFP2NG(ifp); 424116808Sharti const struct priv *priv; 425116808Sharti int error = 0; 426116808Sharti 427116808Sharti if (node == NULL) 428116808Sharti return (0); 429116808Sharti priv = NG_NODE_PRIVATE(node); 430116808Sharti if (priv->output) { 431116808Sharti NG_SEND_DATA_ONLY(error, priv->output, *mp); 432116808Sharti *mp = NULL; 433116808Sharti } 434116808Sharti 435116808Sharti return (error); 436116808Sharti} 437116808Sharti 438116808Sharti/* 439116808Sharti * Well, this doesn't make much sense for ATM. 440116808Sharti */ 441116808Shartistatic void 442116808Sharting_atm_input_orphans(struct ifnet *ifp, struct mbuf *m, 443116808Sharti struct atm_pseudohdr *ah, void *rxhand) 444116808Sharti{ 445116808Sharti node_p node = IFP2NG(ifp); 446116808Sharti struct priv *priv; 447116808Sharti int error; 448116808Sharti 449116808Sharti if (node == NULL) { 450116808Sharti m_freem(m); 451116808Sharti return; 452116808Sharti } 453116808Sharti priv = NG_NODE_PRIVATE(node); 454116808Sharti if (priv->orphans == NULL) { 455116808Sharti m_freem(m); 456116808Sharti return; 457116808Sharti } 458116808Sharti /* 459116808Sharti * Prepend the atm_pseudoheader. 460116808Sharti */ 461116808Sharti M_PREPEND(m, sizeof(*ah), M_DONTWAIT); 462116808Sharti if (m == NULL) 463116808Sharti return; 464116808Sharti memcpy(mtod(m, struct atm_pseudohdr *), ah, sizeof(*ah)); 465116808Sharti NG_SEND_DATA_ONLY(error, priv->orphans, m); 466116808Sharti if (error == 0) 467116808Sharti priv->in_packets++; 468116808Sharti else { 469116808Sharti priv->in_errors++; 470116808Sharti#ifdef NGATM_DEBUG 471116808Sharti printf("%s: error=%d\n", __func__, error); 472116808Sharti#endif 473116808Sharti } 474116808Sharti} 475116808Sharti 476116808Sharti/************************************************************/ 477116808Sharti/* 478116808Sharti * OUTPUT 479116808Sharti */ 480116808Shartistatic int 481116808Sharting_atm_rcvdata(hook_p hook, item_p item) 482116808Sharti{ 483116808Sharti node_p node = NG_HOOK_NODE(hook); 484116808Sharti struct priv *priv = NG_NODE_PRIVATE(node); 485116808Sharti const struct ngvcc *vcc = NG_HOOK_PRIVATE(hook); 486116808Sharti struct mbuf *m; 487116808Sharti struct atm_pseudohdr *aph; 488116808Sharti int error; 489116808Sharti 490116808Sharti if (vcc->vci == 0) { 491116808Sharti NG_FREE_ITEM(item); 492116808Sharti return (ENOTCONN); 493116808Sharti } 494116808Sharti 495116808Sharti NGI_GET_M(item, m); 496116808Sharti NG_FREE_ITEM(item); 497116808Sharti 498116808Sharti /* 499116808Sharti * Prepend pseudo-hdr. Drivers don't care about the flags. 500116808Sharti */ 501116808Sharti M_PREPEND(m, sizeof(*aph), M_DONTWAIT); 502116808Sharti if (m == NULL) { 503116808Sharti NG_FREE_M(m); 504116808Sharti return (ENOMEM); 505116808Sharti } 506116808Sharti aph = mtod(m, struct atm_pseudohdr *); 507116808Sharti ATM_PH_VPI(aph) = vcc->vpi; 508116808Sharti ATM_PH_SETVCI(aph, vcc->vci); 509116808Sharti ATM_PH_FLAGS(aph) = 0; 510116808Sharti 511116808Sharti if ((error = atm_output(priv->ifp, m, NULL, NULL)) == 0) 512116808Sharti priv->out_packets++; 513116808Sharti else 514116808Sharti priv->out_errors++; 515116808Sharti return (error); 516116808Sharti} 517116808Sharti 518116808Shartistatic int 519116808Sharting_atm_rcvdrop(hook_p hook, item_p item) 520116808Sharti{ 521116808Sharti NG_FREE_ITEM(item); 522116808Sharti return (0); 523116808Sharti} 524116808Sharti 525116808Sharti 526116808Sharti/************************************************************ 527116808Sharti * 528118175Sharti * Event from driver. 529116808Sharti */ 530116808Shartistatic void 531118175Sharting_atm_event_func(node_p node, hook_p hook, void *arg, int event) 532116808Sharti{ 533116808Sharti const struct priv *priv = NG_NODE_PRIVATE(node); 534116808Sharti struct ngvcc *vcc; 535116808Sharti struct ng_mesg *mesg; 536116808Sharti int error; 537116808Sharti 538118175Sharti switch (event) { 539116808Sharti 540118175Sharti case ATMEV_FLOW_CONTROL: 541116808Sharti { 542118175Sharti struct atmev_flow_control *ev = arg; 543116808Sharti struct ngm_queue_state *qstate; 544116808Sharti 545116808Sharti /* find the connection */ 546116808Sharti LIST_FOREACH(vcc, &priv->vccs, link) 547118175Sharti if (vcc->vci == ev->vci && vcc->vpi == ev->vpi) 548116808Sharti break; 549116808Sharti if (vcc == NULL) 550116808Sharti break; 551116808Sharti 552116808Sharti /* convert into a flow control message */ 553116808Sharti NG_MKMESSAGE(mesg, NGM_FLOW_COOKIE, 554118175Sharti ev->busy ? NGM_HIGH_WATER_PASSED : NGM_LOW_WATER_PASSED, 555116808Sharti sizeof(struct ngm_queue_state), M_NOWAIT); 556116808Sharti if (mesg == NULL) 557116808Sharti break; 558116808Sharti qstate = (struct ngm_queue_state *)mesg->data; 559116808Sharti 560116808Sharti /* XXX have to figure out how to get that info */ 561116808Sharti 562116808Sharti NG_SEND_MSG_HOOK(error, node, mesg, vcc->hook, NULL); 563116808Sharti break; 564116808Sharti } 565116808Sharti 566118175Sharti case ATMEV_VCC_CHANGED: 567116808Sharti { 568118175Sharti struct atmev_vcc_changed *ev = arg; 569116808Sharti struct ngm_atm_vcc_change *chg; 570116808Sharti 571116808Sharti if (priv->manage == NULL) 572116808Sharti break; 573116808Sharti NG_MKMESSAGE(mesg, NGM_ATM_COOKIE, NGM_ATM_VCC_CHANGE, 574116808Sharti sizeof(struct ngm_atm_vcc_change), M_NOWAIT); 575116808Sharti if (mesg == NULL) 576116808Sharti break; 577116808Sharti chg = (struct ngm_atm_vcc_change *)mesg->data; 578118175Sharti chg->vci = ev->vci; 579118175Sharti chg->vpi = ev->vpi; 580118175Sharti chg->state = (ev->up != 0); 581116808Sharti chg->node = NG_NODE_ID(node); 582116808Sharti NG_SEND_MSG_HOOK(error, node, mesg, priv->manage, NULL); 583116808Sharti break; 584116808Sharti } 585116808Sharti 586118175Sharti case ATMEV_IFSTATE_CHANGED: 587116808Sharti { 588118175Sharti struct atmev_ifstate_changed *ev = arg; 589118175Sharti struct ngm_atm_if_change *chg; 590116808Sharti 591116808Sharti if (priv->manage == NULL) 592116808Sharti break; 593118175Sharti NG_MKMESSAGE(mesg, NGM_ATM_COOKIE, NGM_ATM_IF_CHANGE, 594118175Sharti sizeof(struct ngm_atm_if_change), M_NOWAIT); 595116808Sharti if (mesg == NULL) 596116808Sharti break; 597118175Sharti chg = (struct ngm_atm_if_change *)mesg->data; 598118175Sharti chg->carrier = (ev->carrier != 0); 599118175Sharti chg->running = (ev->running != 0); 600116808Sharti chg->node = NG_NODE_ID(node); 601116808Sharti NG_SEND_MSG_HOOK(error, node, mesg, priv->manage, NULL); 602116808Sharti break; 603116808Sharti } 604118175Sharti 605118175Sharti case ATMEV_ACR_CHANGED: 606118175Sharti { 607118175Sharti struct atmev_acr_changed *ev = arg; 608118175Sharti struct ngm_atm_acr_change *acr; 609118175Sharti 610118175Sharti /* find the connection */ 611118175Sharti LIST_FOREACH(vcc, &priv->vccs, link) 612118175Sharti if (vcc->vci == ev->vci && vcc->vpi == ev->vpi) 613118175Sharti break; 614118175Sharti if (vcc == NULL) 615118175Sharti break; 616118175Sharti 617118175Sharti /* convert into a flow control message */ 618118175Sharti NG_MKMESSAGE(mesg, NGM_ATM_COOKIE, NGM_ATM_ACR_CHANGE, 619118175Sharti sizeof(struct ngm_atm_acr_change), M_NOWAIT); 620118175Sharti if (mesg == NULL) 621118175Sharti break; 622118175Sharti acr = (struct ngm_atm_acr_change *)mesg->data; 623118175Sharti acr->node = NG_NODE_ID(node); 624118175Sharti acr->vci = ev->vci; 625118175Sharti acr->vpi = ev->vpi; 626118175Sharti acr->acr = ev->acr; 627118175Sharti 628118175Sharti NG_SEND_MSG_HOOK(error, node, mesg, vcc->hook, NULL); 629118175Sharti break; 630118175Sharti } 631116808Sharti } 632116808Sharti} 633116808Sharti 634116808Sharti/* 635116808Sharti * Use send_fn to get the right lock 636116808Sharti */ 637116808Shartistatic void 638118175Sharting_atm_event(struct ifnet *ifp, uint32_t event, void *arg) 639116808Sharti{ 640116808Sharti const node_p node = IFP2NG(ifp); 641116808Sharti 642118175Sharti if (node != NULL) 643118175Sharti /* may happen during attach/detach */ 644118175Sharti (void)ng_send_fn(node, NULL, ng_atm_event_func, arg, event); 645116808Sharti} 646116808Sharti 647116808Sharti/************************************************************ 648116808Sharti * 649116808Sharti * CPCS 650116808Sharti */ 651116808Sharti/* 652116808Sharti * Open a channel for the user 653116808Sharti */ 654116808Shartistatic int 655116808Sharting_atm_cpcs_init(node_p node, const struct ngm_atm_cpcs_init *arg) 656116808Sharti{ 657116808Sharti struct priv *priv = NG_NODE_PRIVATE(node); 658116808Sharti const struct ifatm_mib *mib; 659116808Sharti struct ngvcc *vcc; 660116808Sharti struct atmio_openvcc data; 661116808Sharti int err; 662116808Sharti 663116808Sharti if(priv->ifp->if_ioctl == NULL) 664116808Sharti return (ENXIO); 665116808Sharti 666116808Sharti mib = (const struct ifatm_mib *)(priv->ifp->if_linkmib); 667116808Sharti 668116808Sharti LIST_FOREACH(vcc, &priv->vccs, link) 669116808Sharti if (strcmp(arg->name, NG_HOOK_NAME(vcc->hook)) == 0) 670116808Sharti break; 671116808Sharti if (vcc == NULL) 672116808Sharti return (ENOTCONN); 673117642Sharti if (vcc->flags & VCC_OPEN) 674116808Sharti return (EISCONN); 675116808Sharti 676116808Sharti /* 677116808Sharti * Check user arguments and construct ioctl argument 678116808Sharti */ 679116808Sharti memset(&data, 0, sizeof(data)); 680116808Sharti 681116808Sharti data.rxhand = vcc; 682116808Sharti 683116808Sharti switch (data.param.aal = arg->aal) { 684116808Sharti 685117157Sharti case ATMIO_AAL_34: 686116808Sharti case ATMIO_AAL_5: 687116808Sharti case ATMIO_AAL_0: 688116808Sharti case ATMIO_AAL_RAW: 689116808Sharti break; 690116808Sharti 691116808Sharti default: 692116808Sharti return (EINVAL); 693116808Sharti } 694116808Sharti 695116808Sharti if (arg->vpi > 0xff) 696116808Sharti return (EINVAL); 697116808Sharti data.param.vpi = arg->vpi; 698116808Sharti 699117157Sharti /* allow 0.0 as catch all receive channel */ 700117157Sharti if (arg->vci == 0 && (arg->vpi != 0 || !(arg->flags & ATMIO_FLAG_NOTX))) 701117157Sharti return (EINVAL); 702116808Sharti data.param.vci = arg->vci; 703116808Sharti 704116808Sharti data.param.tparam.pcr = arg->pcr; 705116808Sharti 706116808Sharti if (arg->mcr > arg->pcr) 707116808Sharti return (EINVAL); 708116808Sharti data.param.tparam.mcr = arg->mcr; 709116808Sharti 710116808Sharti if (!(arg->flags & ATMIO_FLAG_NOTX)) { 711117157Sharti if (arg->tmtu == 0) 712117157Sharti data.param.tmtu = priv->ifp->if_mtu; 713117157Sharti else { 714117157Sharti data.param.tmtu = arg->tmtu; 715117157Sharti } 716116808Sharti } 717116808Sharti if (!(arg->flags & ATMIO_FLAG_NORX)) { 718117157Sharti if (arg->rmtu == 0) 719117157Sharti data.param.rmtu = priv->ifp->if_mtu; 720117157Sharti else { 721117157Sharti data.param.rmtu = arg->rmtu; 722117157Sharti } 723116808Sharti } 724116808Sharti 725116808Sharti switch (data.param.traffic = arg->traffic) { 726116808Sharti 727116808Sharti case ATMIO_TRAFFIC_UBR: 728116808Sharti case ATMIO_TRAFFIC_CBR: 729116808Sharti break; 730116808Sharti 731116808Sharti case ATMIO_TRAFFIC_VBR: 732116808Sharti if (arg->scr > arg->pcr) 733116808Sharti return (EINVAL); 734116808Sharti data.param.tparam.scr = arg->scr; 735116808Sharti 736116808Sharti if (arg->mbs > (1 << 24)) 737116808Sharti return (EINVAL); 738116808Sharti data.param.tparam.mbs = arg->mbs; 739116808Sharti break; 740116808Sharti 741116808Sharti case ATMIO_TRAFFIC_ABR: 742116808Sharti if (arg->icr > arg->pcr || arg->icr < arg->mcr) 743116808Sharti return (EINVAL); 744116808Sharti data.param.tparam.icr = arg->icr; 745116808Sharti 746116808Sharti if (arg->tbe == 0 || arg->tbe > (1 << 24)) 747116808Sharti return (EINVAL); 748116808Sharti data.param.tparam.tbe = arg->tbe; 749116808Sharti 750116808Sharti if (arg->nrm > 0x7) 751116808Sharti return (EINVAL); 752116808Sharti data.param.tparam.nrm = arg->nrm; 753116808Sharti 754116808Sharti if (arg->trm > 0x7) 755116808Sharti return (EINVAL); 756116808Sharti data.param.tparam.trm = arg->trm; 757116808Sharti 758116808Sharti if (arg->adtf > 0x3ff) 759116808Sharti return (EINVAL); 760116808Sharti data.param.tparam.adtf = arg->adtf; 761116808Sharti 762116808Sharti if (arg->rif > 0xf) 763116808Sharti return (EINVAL); 764116808Sharti data.param.tparam.rif = arg->rif; 765116808Sharti 766116808Sharti if (arg->rdf > 0xf) 767116808Sharti return (EINVAL); 768116808Sharti data.param.tparam.rdf = arg->rdf; 769116808Sharti 770116808Sharti if (arg->cdf > 0x7) 771116808Sharti return (EINVAL); 772116808Sharti data.param.tparam.cdf = arg->cdf; 773116808Sharti 774116808Sharti break; 775116808Sharti 776116808Sharti default: 777116808Sharti return (EINVAL); 778116808Sharti } 779116808Sharti 780116808Sharti if ((arg->flags & ATMIO_FLAG_NORX) && (arg->flags & ATMIO_FLAG_NOTX)) 781116808Sharti return (EINVAL); 782116808Sharti 783116808Sharti data.param.flags = arg->flags & ~(ATM_PH_AAL5 | ATM_PH_LLCSNAP); 784116808Sharti data.param.flags |= ATMIO_FLAG_NG; 785116808Sharti 786116808Sharti err = (*priv->ifp->if_ioctl)(priv->ifp, SIOCATMOPENVCC, (caddr_t)&data); 787116808Sharti 788116808Sharti if (err == 0) { 789116808Sharti vcc->vci = data.param.vci; 790116808Sharti vcc->vpi = data.param.vpi; 791117157Sharti vcc->flags = VCC_OPEN; 792116808Sharti } 793116808Sharti 794116808Sharti return (err); 795116808Sharti} 796116808Sharti 797116808Sharti/* 798116808Sharti * Issue the close command to the driver 799116808Sharti */ 800116808Shartistatic int 801116808Sharticpcs_term(const struct priv *priv, u_int vpi, u_int vci) 802116808Sharti{ 803116808Sharti struct atmio_closevcc data; 804116808Sharti 805116808Sharti if (priv->ifp->if_ioctl == NULL) 806116808Sharti return ENXIO; 807116808Sharti 808116808Sharti data.vpi = vpi; 809116808Sharti data.vci = vci; 810116808Sharti 811116808Sharti return ((*priv->ifp->if_ioctl)(priv->ifp, 812116808Sharti SIOCATMCLOSEVCC, (caddr_t)&data)); 813116808Sharti} 814116808Sharti 815116808Sharti 816116808Sharti/* 817116808Sharti * Close a channel by request of the user 818116808Sharti */ 819116808Shartistatic int 820116808Sharting_atm_cpcs_term(node_p node, const struct ngm_atm_cpcs_term *arg) 821116808Sharti{ 822116808Sharti struct priv *priv = NG_NODE_PRIVATE(node); 823116808Sharti struct ngvcc *vcc; 824116808Sharti int error; 825116808Sharti 826116808Sharti LIST_FOREACH(vcc, &priv->vccs, link) 827116808Sharti if(strcmp(arg->name, NG_HOOK_NAME(vcc->hook)) == 0) 828116808Sharti break; 829116808Sharti if (vcc == NULL) 830116808Sharti return (ENOTCONN); 831117642Sharti if (!(vcc->flags & VCC_OPEN)) 832116808Sharti return (ENOTCONN); 833116808Sharti 834116808Sharti error = cpcs_term(priv, vcc->vpi, vcc->vci); 835116808Sharti 836116808Sharti vcc->vci = 0; 837116808Sharti vcc->vpi = 0; 838116808Sharti vcc->flags = 0; 839116808Sharti 840116808Sharti return (error); 841116808Sharti} 842116808Sharti 843116808Sharti/************************************************************/ 844116808Sharti/* 845116808Sharti * CONTROL MESSAGES 846116808Sharti */ 847116808Sharti 848116808Sharti/* 849116808Sharti * Produce a textual description of the current status 850116808Sharti */ 851116808Shartistatic int 852116808Shartitext_status(node_p node, char *arg, u_int len) 853116808Sharti{ 854116808Sharti const struct priv *priv = NG_NODE_PRIVATE(node); 855116808Sharti const struct ifatm_mib *mib; 856116808Sharti struct sbuf sbuf; 857116808Sharti u_int i; 858116808Sharti 859116808Sharti static const struct { 860116808Sharti const char *name; 861116808Sharti const char *vendor; 862116808Sharti } devices[] = { 863116808Sharti ATM_DEVICE_NAMES 864116808Sharti }; 865116808Sharti 866116808Sharti mib = (const struct ifatm_mib *)(priv->ifp->if_linkmib); 867116808Sharti 868116808Sharti sbuf_new(&sbuf, arg, len, SBUF_FIXEDLEN); 869121816Sbrooks sbuf_printf(&sbuf, "interface: %s\n", priv->ifp->if_xname); 870116808Sharti 871116808Sharti if (mib->device >= sizeof(devices) / sizeof(devices[0])) 872116808Sharti sbuf_printf(&sbuf, "device=unknown\nvendor=unknown\n"); 873116808Sharti else 874116808Sharti sbuf_printf(&sbuf, "device=%s\nvendor=%s\n", 875116808Sharti devices[mib->device].name, devices[mib->device].vendor); 876116808Sharti 877116808Sharti for (i = 0; atmmedia[i].name; i++) 878116808Sharti if(mib->media == atmmedia[i].media) { 879116808Sharti sbuf_printf(&sbuf, "media=%s\n", atmmedia[i].name); 880116808Sharti break; 881116808Sharti } 882116808Sharti if(atmmedia[i].name == NULL) 883116808Sharti sbuf_printf(&sbuf, "media=unknown\n"); 884116808Sharti 885116808Sharti sbuf_printf(&sbuf, "serial=%u esi=%6D hardware=%u software=%u\n", 886116808Sharti mib->serial, mib->esi, ":", mib->hw_version, mib->sw_version); 887116808Sharti sbuf_printf(&sbuf, "pcr=%u vpi_bits=%u vci_bits=%u max_vpcs=%u " 888116808Sharti "max_vccs=%u\n", mib->pcr, mib->vpi_bits, mib->vci_bits, 889116808Sharti mib->max_vpcs, mib->max_vccs); 890116808Sharti sbuf_printf(&sbuf, "ifflags=%b\n", priv->ifp->if_flags, IFFLAGS); 891116808Sharti 892116808Sharti sbuf_finish(&sbuf); 893116808Sharti 894116808Sharti return (sbuf_len(&sbuf)); 895116808Sharti} 896116808Sharti 897116808Sharti/* 898116808Sharti * Get control message 899116808Sharti */ 900116808Shartistatic int 901116808Sharting_atm_rcvmsg(node_p node, item_p item, hook_p lasthook) 902116808Sharti{ 903116808Sharti const struct priv *priv = NG_NODE_PRIVATE(node); 904116808Sharti struct ng_mesg *resp = NULL; 905116808Sharti struct ng_mesg *msg; 906116808Sharti struct ifatm_mib *mib = (struct ifatm_mib *)(priv->ifp->if_linkmib); 907116808Sharti int error = 0; 908116808Sharti 909116808Sharti NGI_GET_MSG(item, msg); 910116808Sharti 911116808Sharti switch (msg->header.typecookie) { 912116808Sharti 913116808Sharti case NGM_GENERIC_COOKIE: 914116808Sharti switch (msg->header.cmd) { 915116808Sharti 916116808Sharti case NGM_TEXT_STATUS: 917116808Sharti NG_MKRESPONSE(resp, msg, NG_TEXTRESPONSE, M_NOWAIT); 918116808Sharti if(resp == NULL) { 919116808Sharti error = ENOMEM; 920116808Sharti break; 921116808Sharti } 922116808Sharti 923116808Sharti resp->header.arglen = text_status(node, 924116808Sharti (char *)resp->data, resp->header.arglen) + 1; 925116808Sharti break; 926116808Sharti 927116808Sharti default: 928116808Sharti error = EINVAL; 929116808Sharti break; 930116808Sharti } 931116808Sharti break; 932116808Sharti 933116808Sharti case NGM_ATM_COOKIE: 934116808Sharti switch (msg->header.cmd) { 935116808Sharti 936116808Sharti case NGM_ATM_GET_IFNAME: 937116808Sharti NG_MKRESPONSE(resp, msg, IFNAMSIZ + 1, M_NOWAIT); 938116808Sharti if (resp == NULL) { 939116808Sharti error = ENOMEM; 940116808Sharti break; 941116808Sharti } 942121816Sbrooks strlcpy(resp->data, priv->ifp->if_xname, IFNAMSIZ + 1); 943116808Sharti break; 944116808Sharti 945116808Sharti case NGM_ATM_GET_CONFIG: 946116808Sharti { 947116808Sharti struct ngm_atm_config *config; 948116808Sharti 949116808Sharti NG_MKRESPONSE(resp, msg, sizeof(*config), M_NOWAIT); 950116808Sharti if (resp == NULL) { 951116808Sharti error = ENOMEM; 952116808Sharti break; 953116808Sharti } 954116808Sharti config = (struct ngm_atm_config *)resp->data; 955116808Sharti config->pcr = mib->pcr; 956116808Sharti config->vpi_bits = mib->vpi_bits; 957116808Sharti config->vci_bits = mib->vci_bits; 958116808Sharti config->max_vpcs = mib->max_vpcs; 959116808Sharti config->max_vccs = mib->max_vccs; 960116808Sharti break; 961116808Sharti } 962116808Sharti 963116808Sharti case NGM_ATM_GET_VCCS: 964116808Sharti { 965116808Sharti struct atmio_vcctable *vccs; 966116808Sharti size_t len; 967116808Sharti 968116808Sharti if (priv->ifp->if_ioctl == NULL) { 969116808Sharti error = ENXIO; 970116808Sharti break; 971116808Sharti } 972116808Sharti error = (*priv->ifp->if_ioctl)(priv->ifp, 973116808Sharti SIOCATMGETVCCS, (caddr_t)&vccs); 974116808Sharti if (error) 975116808Sharti break; 976116808Sharti 977116808Sharti len = sizeof(*vccs) + 978116808Sharti vccs->count * sizeof(vccs->vccs[0]); 979116808Sharti NG_MKRESPONSE(resp, msg, len, M_NOWAIT); 980116808Sharti if (resp == NULL) { 981116808Sharti error = ENOMEM; 982116808Sharti free(vccs, M_DEVBUF); 983116808Sharti break; 984116808Sharti } 985116808Sharti 986116808Sharti (void)memcpy(resp->data, vccs, len); 987116808Sharti free(vccs, M_DEVBUF); 988116808Sharti 989116808Sharti break; 990116808Sharti } 991116808Sharti 992116808Sharti case NGM_ATM_GET_VCC: 993116808Sharti { 994116808Sharti char hook[NG_HOOKLEN + 1]; 995116808Sharti struct atmio_vcctable *vccs; 996116808Sharti struct ngvcc *vcc; 997116808Sharti u_int i; 998116808Sharti 999116808Sharti if (priv->ifp->if_ioctl == NULL) { 1000116808Sharti error = ENXIO; 1001116808Sharti break; 1002116808Sharti } 1003116808Sharti if (msg->header.arglen != NG_HOOKLEN + 1) { 1004116808Sharti error = EINVAL; 1005116808Sharti break; 1006116808Sharti } 1007116808Sharti strncpy(hook, msg->data, NG_HOOKLEN + 1); 1008116808Sharti hook[NG_HOOKLEN] = '\0'; 1009116808Sharti LIST_FOREACH(vcc, &priv->vccs, link) 1010116808Sharti if (strcmp(NG_HOOK_NAME(vcc->hook), hook) == 0) 1011116808Sharti break; 1012116808Sharti if (vcc == NULL) { 1013116808Sharti error = ENOTCONN; 1014116808Sharti break; 1015116808Sharti } 1016116808Sharti error = (*priv->ifp->if_ioctl)(priv->ifp, 1017116808Sharti SIOCATMGETVCCS, (caddr_t)&vccs); 1018116808Sharti if (error) 1019116808Sharti break; 1020116808Sharti 1021116808Sharti for (i = 0; i < vccs->count; i++) 1022116808Sharti if (vccs->vccs[i].vpi == vcc->vpi && 1023116808Sharti vccs->vccs[i].vci == vcc->vci) 1024116808Sharti break; 1025116808Sharti if (i == vccs->count) { 1026116808Sharti error = ENOTCONN; 1027116808Sharti free(vccs, M_DEVBUF); 1028116808Sharti break; 1029116808Sharti } 1030116808Sharti 1031116808Sharti NG_MKRESPONSE(resp, msg, sizeof(vccs->vccs[0]), 1032116808Sharti M_NOWAIT); 1033116808Sharti if (resp == NULL) { 1034116808Sharti error = ENOMEM; 1035116808Sharti free(vccs, M_DEVBUF); 1036116808Sharti break; 1037116808Sharti } 1038116808Sharti 1039116808Sharti *(struct atmio_vcc *)resp->data = vccs->vccs[i]; 1040116808Sharti free(vccs, M_DEVBUF); 1041116808Sharti break; 1042116808Sharti } 1043116808Sharti 1044116808Sharti case NGM_ATM_GET_VCCID: 1045116808Sharti { 1046116808Sharti struct atmio_vcc *arg; 1047116808Sharti struct atmio_vcctable *vccs; 1048116808Sharti u_int i; 1049116808Sharti 1050116808Sharti if (priv->ifp->if_ioctl == NULL) { 1051116808Sharti error = ENXIO; 1052116808Sharti break; 1053116808Sharti } 1054116808Sharti if (msg->header.arglen != sizeof(*arg)) { 1055116808Sharti error = EINVAL; 1056116808Sharti break; 1057116808Sharti } 1058116808Sharti arg = (struct atmio_vcc *)msg->data; 1059116808Sharti 1060116808Sharti error = (*priv->ifp->if_ioctl)(priv->ifp, 1061116808Sharti SIOCATMGETVCCS, (caddr_t)&vccs); 1062116808Sharti if (error) 1063116808Sharti break; 1064116808Sharti 1065116808Sharti for (i = 0; i < vccs->count; i++) 1066116808Sharti if (vccs->vccs[i].vpi == arg->vpi && 1067116808Sharti vccs->vccs[i].vci == arg->vci) 1068116808Sharti break; 1069116808Sharti if (i == vccs->count) { 1070116808Sharti error = ENOTCONN; 1071116808Sharti free(vccs, M_DEVBUF); 1072116808Sharti break; 1073116808Sharti } 1074116808Sharti 1075116808Sharti NG_MKRESPONSE(resp, msg, sizeof(vccs->vccs[0]), 1076116808Sharti M_NOWAIT); 1077116808Sharti if (resp == NULL) { 1078116808Sharti error = ENOMEM; 1079116808Sharti free(vccs, M_DEVBUF); 1080116808Sharti break; 1081116808Sharti } 1082116808Sharti 1083116808Sharti *(struct atmio_vcc *)resp->data = vccs->vccs[i]; 1084116808Sharti free(vccs, M_DEVBUF); 1085116808Sharti break; 1086116808Sharti } 1087116808Sharti 1088116808Sharti case NGM_ATM_CPCS_INIT: 1089116808Sharti if (msg->header.arglen != 1090116808Sharti sizeof(struct ngm_atm_cpcs_init)) { 1091116808Sharti error = EINVAL; 1092116808Sharti break; 1093116808Sharti } 1094116808Sharti error = ng_atm_cpcs_init(node, 1095116808Sharti (struct ngm_atm_cpcs_init *)msg->data); 1096116808Sharti break; 1097116808Sharti 1098116808Sharti case NGM_ATM_CPCS_TERM: 1099116808Sharti if (msg->header.arglen != 1100116808Sharti sizeof(struct ngm_atm_cpcs_term)) { 1101116808Sharti error = EINVAL; 1102116808Sharti break; 1103116808Sharti } 1104116808Sharti error = ng_atm_cpcs_term(node, 1105116808Sharti (struct ngm_atm_cpcs_term *)msg->data); 1106116808Sharti break; 1107116808Sharti 1108116808Sharti case NGM_ATM_GET_STATS: 1109116808Sharti { 1110116808Sharti struct ngm_atm_stats *p; 1111116808Sharti 1112116808Sharti if (msg->header.arglen != 0) { 1113116808Sharti error = EINVAL; 1114116808Sharti break; 1115116808Sharti } 1116116808Sharti NG_MKRESPONSE(resp, msg, sizeof(*p), M_NOWAIT); 1117116808Sharti if (resp == NULL) { 1118116808Sharti error = ENOMEM; 1119116808Sharti break; 1120116808Sharti } 1121116808Sharti p = (struct ngm_atm_stats *)resp->data; 1122116808Sharti p->in_packets = priv->in_packets; 1123116808Sharti p->out_packets = priv->out_packets; 1124116808Sharti p->in_errors = priv->in_errors; 1125116808Sharti p->out_errors = priv->out_errors; 1126116808Sharti 1127116808Sharti break; 1128116808Sharti } 1129116808Sharti 1130116808Sharti default: 1131116808Sharti error = EINVAL; 1132116808Sharti break; 1133116808Sharti } 1134116808Sharti break; 1135116808Sharti 1136116808Sharti default: 1137116808Sharti error = EINVAL; 1138116808Sharti break; 1139116808Sharti } 1140116808Sharti 1141116808Sharti NG_RESPOND_MSG(error, node, item, resp); 1142116808Sharti NG_FREE_MSG(msg); 1143116808Sharti return (error); 1144116808Sharti} 1145116808Sharti 1146116808Sharti/************************************************************/ 1147116808Sharti/* 1148116808Sharti * HOOK MANAGEMENT 1149116808Sharti */ 1150116808Sharti 1151116808Sharti/* 1152116808Sharti * A new hook is create that will be connected to the node. 1153116808Sharti * Check, whether the name is one of the predefined ones. 1154116808Sharti * If not, create a new entry into the vcc list. 1155116808Sharti */ 1156116808Shartistatic int 1157116808Sharting_atm_newhook(node_p node, hook_p hook, const char *name) 1158116808Sharti{ 1159116808Sharti struct priv *priv = NG_NODE_PRIVATE(node); 1160116808Sharti struct ngvcc *vcc; 1161116808Sharti 1162116808Sharti if (strcmp(name, "input") == 0) { 1163116808Sharti priv->input = hook; 1164116808Sharti NG_HOOK_SET_RCVDATA(hook, ng_atm_rcvdrop); 1165116808Sharti return (0); 1166116808Sharti } 1167116808Sharti if (strcmp(name, "output") == 0) { 1168116808Sharti priv->output = hook; 1169116808Sharti NG_HOOK_SET_RCVDATA(hook, ng_atm_rcvdrop); 1170116808Sharti return (0); 1171116808Sharti } 1172116808Sharti if (strcmp(name, "orphans") == 0) { 1173116808Sharti priv->orphans = hook; 1174116808Sharti NG_HOOK_SET_RCVDATA(hook, ng_atm_rcvdrop); 1175116808Sharti return (0); 1176116808Sharti } 1177116808Sharti 1178116808Sharti /* 1179116808Sharti * Allocate a new entry 1180116808Sharti */ 1181116808Sharti vcc = malloc(sizeof(*vcc), M_NETGRAPH, M_NOWAIT | M_ZERO); 1182116808Sharti if (vcc == NULL) 1183116808Sharti return (ENOMEM); 1184116808Sharti 1185116808Sharti vcc->hook = hook; 1186116808Sharti NG_HOOK_SET_PRIVATE(hook, vcc); 1187116808Sharti 1188116808Sharti LIST_INSERT_HEAD(&priv->vccs, vcc, link); 1189116808Sharti 1190116808Sharti if (strcmp(name, "manage") == 0) 1191116808Sharti priv->manage = hook; 1192116808Sharti 1193116808Sharti return (0); 1194116808Sharti} 1195116808Sharti 1196116808Sharti/* 1197116808Sharti * Connect. Set the peer to queuing. 1198116808Sharti */ 1199116808Shartistatic int 1200116808Sharting_atm_connect(hook_p hook) 1201116808Sharti{ 1202116808Sharti if (NG_HOOK_PRIVATE(hook) != NULL) 1203116808Sharti NG_HOOK_FORCE_QUEUE(NG_HOOK_PEER(hook)); 1204116808Sharti 1205116808Sharti return (0); 1206116808Sharti} 1207116808Sharti 1208116808Sharti/* 1209116808Sharti * Disconnect a HOOK 1210116808Sharti */ 1211116808Shartistatic int 1212116808Sharting_atm_disconnect(hook_p hook) 1213116808Sharti{ 1214116808Sharti struct priv *priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); 1215116808Sharti struct ngvcc *vcc = NG_HOOK_PRIVATE(hook); 1216116808Sharti 1217116808Sharti if (vcc == NULL) { 1218116808Sharti if (hook == priv->output) { 1219116808Sharti priv->output = NULL; 1220116808Sharti return (0); 1221116808Sharti } 1222116808Sharti if (hook == priv->input) { 1223116808Sharti priv->input = NULL; 1224116808Sharti return (0); 1225116808Sharti } 1226116808Sharti if (hook == priv->orphans) { 1227116808Sharti priv->orphans = NULL; 1228116808Sharti return (0); 1229116808Sharti } 1230116808Sharti log(LOG_ERR, "ng_atm: bad hook '%s'", NG_HOOK_NAME(hook)); 1231116808Sharti return (0); 1232116808Sharti } 1233116808Sharti 1234116808Sharti /* don't terminate if we are detaching from the interface */ 1235117157Sharti if ((vcc->flags & VCC_OPEN) && priv->ifp != NULL) 1236116808Sharti (void)cpcs_term(priv, vcc->vpi, vcc->vci); 1237116808Sharti 1238116808Sharti NG_HOOK_SET_PRIVATE(hook, NULL); 1239116808Sharti 1240116808Sharti LIST_REMOVE(vcc, link); 1241116808Sharti free(vcc, M_NETGRAPH); 1242116808Sharti 1243116808Sharti if (hook == priv->manage) 1244116808Sharti priv->manage = NULL; 1245116808Sharti 1246116808Sharti return (0); 1247116808Sharti} 1248116808Sharti 1249116808Sharti/************************************************************/ 1250116808Sharti/* 1251116808Sharti * NODE MANAGEMENT 1252116808Sharti */ 1253116808Sharti 1254116808Sharti/* 1255116808Sharti * ATM interface attached - create a node and name it like the interface. 1256116808Sharti */ 1257116808Shartistatic void 1258116808Sharting_atm_attach(struct ifnet *ifp) 1259116808Sharti{ 1260116808Sharti char name[IFNAMSIZ+1]; 1261116808Sharti node_p node; 1262116808Sharti struct priv *priv; 1263116808Sharti 1264116808Sharti KASSERT(IFP2NG(ifp) == 0, ("%s: node alreay exists?", __FUNCTION__)); 1265116808Sharti 1266121816Sbrooks strlcpy(name, ifp->if_xname, sizeof(name)); 1267116808Sharti 1268116808Sharti if (ng_make_node_common(&ng_atm_typestruct, &node) != 0) { 1269116808Sharti log(LOG_ERR, "%s: can't create node for %s\n", 1270116808Sharti __FUNCTION__, name); 1271116808Sharti return; 1272116808Sharti } 1273116808Sharti 1274116808Sharti priv = malloc(sizeof(*priv), M_NETGRAPH, M_NOWAIT | M_ZERO); 1275116808Sharti if (priv == NULL) { 1276116808Sharti log(LOG_ERR, "%s: can't allocate memory for %s\n", 1277116808Sharti __FUNCTION__, name); 1278116808Sharti NG_NODE_UNREF(node); 1279116808Sharti return; 1280116808Sharti } 1281116808Sharti NG_NODE_SET_PRIVATE(node, priv); 1282116808Sharti priv->ifp = ifp; 1283116808Sharti LIST_INIT(&priv->vccs); 1284116808Sharti IFP2NG(ifp) = node; 1285116808Sharti 1286116808Sharti if (ng_name_node(node, name) != 0) { 1287116808Sharti log(LOG_WARNING, "%s: can't name node %s\n", 1288116808Sharti __FUNCTION__, name); 1289116808Sharti } 1290116808Sharti} 1291116808Sharti 1292116808Sharti/* 1293116808Sharti * ATM interface detached - destroy node. 1294116808Sharti */ 1295116808Shartistatic void 1296116808Sharting_atm_detach(struct ifnet *ifp) 1297116808Sharti{ 1298116808Sharti const node_p node = IFP2NG(ifp); 1299116808Sharti struct priv *priv; 1300116808Sharti 1301116808Sharti if(node == NULL) 1302116808Sharti return; 1303116808Sharti 1304116808Sharti NG_NODE_REALLY_DIE(node); 1305116808Sharti 1306116808Sharti priv = NG_NODE_PRIVATE(node); 1307116808Sharti IFP2NG(priv->ifp) = NULL; 1308116808Sharti priv->ifp = NULL; 1309116808Sharti 1310116808Sharti ng_rmnode_self(node); 1311116808Sharti} 1312116808Sharti 1313116808Sharti/* 1314116808Sharti * Shutdown the node. This is called from the shutdown message processing. 1315116808Sharti */ 1316116808Shartistatic int 1317116808Sharting_atm_shutdown(node_p node) 1318116808Sharti{ 1319116808Sharti struct priv *priv = NG_NODE_PRIVATE(node); 1320116808Sharti 1321116808Sharti if (node->nd_flags & NG_REALLY_DIE) { 1322116808Sharti /* 1323116808Sharti * We are called from unloading the ATM driver. Really, 1324116808Sharti * really need to shutdown this node. The ifp was 1325116808Sharti * already handled in the detach routine. 1326116808Sharti */ 1327116808Sharti NG_NODE_SET_PRIVATE(node, NULL); 1328116808Sharti free(priv, M_NETGRAPH); 1329116808Sharti 1330116808Sharti NG_NODE_UNREF(node); 1331116808Sharti return (0); 1332116808Sharti } 1333116808Sharti 1334116808Sharti#ifdef NGATM_DEBUG 1335116808Sharti if (!allow_shutdown) 1336116808Sharti node->nd_flags &= ~NG_INVALID; 1337116808Sharti else { 1338116808Sharti IFP2NG(priv->ifp) = NULL; 1339116808Sharti NG_NODE_SET_PRIVATE(node, NULL); 1340116808Sharti free(priv, M_NETGRAPH); 1341116808Sharti NG_NODE_UNREF(node); 1342116808Sharti } 1343116808Sharti#else 1344116808Sharti /* 1345116808Sharti * We are persistant - reinitialize 1346116808Sharti */ 1347116808Sharti node->nd_flags &= ~NG_INVALID; 1348116808Sharti#endif 1349116808Sharti return (0); 1350116808Sharti} 1351116808Sharti 1352116808Sharti/* 1353116808Sharti * Nodes are constructed only via interface attaches. 1354116808Sharti */ 1355116808Shartistatic int 1356116808Sharting_atm_constructor(node_p nodep) 1357116808Sharti{ 1358116808Sharti return (EINVAL); 1359116808Sharti} 1360116808Sharti 1361116808Sharti/************************************************************/ 1362116808Sharti/* 1363116808Sharti * INITIALISATION 1364116808Sharti */ 1365116808Sharti/* 1366116808Sharti * Loading and unloading of node type 1367116808Sharti * 1368116808Sharti * The assignments to the globals for the hooks should be ok without 1369116808Sharti * a special hook. The use pattern is generally: check that the pointer 1370116808Sharti * is not NULL, call the function. In the attach case this is no problem. 1371116808Sharti * In the detach case we can detach only when no ATM node exists. That 1372116808Sharti * means that there is no ATM interface anymore. So we are sure that 1373116808Sharti * we are not in the code path in if_atmsubr.c. To prevent someone 1374116808Sharti * from adding an interface after we have started to unload the node, we 1375116808Sharti * take the iflist lock so an if_attach will be blocked until we are done. 1376116808Sharti * XXX: perhaps the function pointers should be 'volatile' for this to work 1377116808Sharti * properly. 1378116808Sharti */ 1379116808Shartistatic int 1380116808Sharting_atm_mod_event(module_t mod, int event, void *data) 1381116808Sharti{ 1382116808Sharti struct ifnet *ifp; 1383116808Sharti int error = 0; 1384116808Sharti 1385116808Sharti switch (event) { 1386116808Sharti 1387116808Sharti case MOD_LOAD: 1388116808Sharti /* 1389116808Sharti * Register function hooks 1390116808Sharti */ 1391116808Sharti if (ng_atm_attach_p != NULL) { 1392116808Sharti error = EEXIST; 1393116808Sharti break; 1394116808Sharti } 1395116808Sharti IFNET_RLOCK(); 1396116808Sharti 1397116808Sharti ng_atm_attach_p = ng_atm_attach; 1398116808Sharti ng_atm_detach_p = ng_atm_detach; 1399116808Sharti ng_atm_output_p = ng_atm_output; 1400116808Sharti ng_atm_input_p = ng_atm_input; 1401116808Sharti ng_atm_input_orphan_p = ng_atm_input_orphans; 1402118175Sharti ng_atm_event_p = ng_atm_event; 1403116808Sharti 1404116808Sharti /* Create nodes for existing ATM interfaces */ 1405116808Sharti TAILQ_FOREACH(ifp, &ifnet, if_link) { 1406116808Sharti if (ifp->if_type == IFT_ATM) 1407116808Sharti ng_atm_attach(ifp); 1408116808Sharti } 1409116808Sharti IFNET_RUNLOCK(); 1410116808Sharti break; 1411116808Sharti 1412116808Sharti case MOD_UNLOAD: 1413116808Sharti IFNET_RLOCK(); 1414116808Sharti 1415116808Sharti ng_atm_attach_p = NULL; 1416116808Sharti ng_atm_detach_p = NULL; 1417116808Sharti ng_atm_output_p = NULL; 1418116808Sharti ng_atm_input_p = NULL; 1419116808Sharti ng_atm_input_orphan_p = NULL; 1420118175Sharti ng_atm_event_p = NULL; 1421116808Sharti 1422116808Sharti TAILQ_FOREACH(ifp, &ifnet, if_link) { 1423116808Sharti if (ifp->if_type == IFT_ATM) 1424116808Sharti ng_atm_detach(ifp); 1425116808Sharti } 1426116808Sharti IFNET_RUNLOCK(); 1427116808Sharti break; 1428116808Sharti 1429116808Sharti default: 1430116808Sharti error = EOPNOTSUPP; 1431116808Sharti break; 1432116808Sharti } 1433116808Sharti return (error); 1434116808Sharti} 1435