ng_atm.c revision 132464
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 132464 2004-07-20 17:15:38Z julian $"); 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 = { 327129823Sjulian .version = NG_ABI_VERSION, 328129823Sjulian .name = NG_ATM_NODE_TYPE, 329129823Sjulian .mod_event = ng_atm_mod_event, 330129823Sjulian .constructor = ng_atm_constructor, 331129823Sjulian .rcvmsg = ng_atm_rcvmsg, 332129823Sjulian .shutdown = ng_atm_shutdown, 333129823Sjulian .newhook = ng_atm_newhook, 334129823Sjulian .connect = ng_atm_connect, 335129823Sjulian .rcvdata = ng_atm_rcvdata, 336129823Sjulian .disconnect = ng_atm_disconnect, 337129823Sjulian .cmdlist = ng_atm_cmdlist, 338116808Sharti}; 339116808ShartiNETGRAPH_INIT(atm, &ng_atm_typestruct); 340116808Sharti 341116808Shartistatic const struct { 342116808Sharti u_int media; 343116808Sharti const char *name; 344116808Sharti} atmmedia[] = IFM_SUBTYPE_ATM_DESCRIPTIONS; 345116808Sharti 346116808Sharti 347116808Sharti#define IFP2NG(IFP) ((node_p)((struct ifatm *)(IFP))->ngpriv) 348116808Sharti 349116808Sharti#define IFFLAGS "\020\001UP\002BROADCAST\003DEBUG\004LOOPBACK" \ 350116808Sharti "\005POINTOPOINT\006SMART\007RUNNING\010NOARP" \ 351116808Sharti "\011PROMISC\012ALLMULTI\013OACTIVE\014SIMPLEX" \ 352116808Sharti "\015LINK0\016LINK1\017LINK2\020MULTICAST" 353116808Sharti 354116808Sharti 355116808Sharti/************************************************************/ 356116808Sharti/* 357116808Sharti * INPUT 358116808Sharti */ 359116808Sharti/* 360116808Sharti * A packet is received from an interface. 361116808Sharti * If we have an input hook, prepend the pseudoheader to the data and 362116808Sharti * deliver it out to that hook. If not, look whether it is destined for 363116808Sharti * use. If so locate the appropriate hook, deliver the packet without the 364116808Sharti * header and we are done. If it is not for us, leave it alone. 365116808Sharti */ 366116808Shartistatic void 367116808Sharting_atm_input(struct ifnet *ifp, struct mbuf **mp, 368116808Sharti struct atm_pseudohdr *ah, void *rxhand) 369116808Sharti{ 370116808Sharti node_p node = IFP2NG(ifp); 371116808Sharti struct priv *priv; 372116808Sharti const struct ngvcc *vcc; 373116808Sharti int error; 374116808Sharti 375116808Sharti if (node == NULL) 376116808Sharti return; 377116808Sharti priv = NG_NODE_PRIVATE(node); 378116808Sharti if (priv->input != NULL) { 379116808Sharti /* 380116808Sharti * Prepend the atm_pseudoheader. 381116808Sharti */ 382116808Sharti M_PREPEND(*mp, sizeof(*ah), M_DONTWAIT); 383116808Sharti if (*mp == NULL) 384116808Sharti return; 385116808Sharti memcpy(mtod(*mp, struct atm_pseudohdr *), ah, sizeof(*ah)); 386116808Sharti NG_SEND_DATA_ONLY(error, priv->input, *mp); 387116808Sharti if (error == 0) { 388116808Sharti priv->in_packets++; 389116808Sharti *mp = NULL; 390116808Sharti } else { 391116808Sharti#ifdef NGATM_DEBUG 392116808Sharti printf("%s: error=%d\n", __func__, error); 393116808Sharti#endif 394116808Sharti priv->in_errors++; 395116808Sharti } 396116808Sharti return; 397116808Sharti } 398116808Sharti if ((ATM_PH_FLAGS(ah) & ATMIO_FLAG_NG) == 0) 399116808Sharti return; 400116808Sharti 401116808Sharti vcc = (struct ngvcc *)rxhand; 402116808Sharti 403116808Sharti NG_SEND_DATA_ONLY(error, vcc->hook, *mp); 404116808Sharti if (error == 0) { 405116808Sharti priv->in_packets++; 406116808Sharti *mp = NULL; 407116808Sharti } else { 408116808Sharti#ifdef NGATM_DEBUG 409116808Sharti printf("%s: error=%d\n", __func__, error); 410116808Sharti#endif 411116808Sharti priv->in_errors++; 412116808Sharti } 413116808Sharti} 414116808Sharti 415116808Sharti/* 416116808Sharti * ATM packet is about to be output. The atm_pseudohdr is already prepended. 417116808Sharti * If the hook is set, reroute the packet to the hook. 418116808Sharti */ 419116808Shartistatic int 420116808Sharting_atm_output(struct ifnet *ifp, struct mbuf **mp) 421116808Sharti{ 422116808Sharti const node_p node = IFP2NG(ifp); 423116808Sharti const struct priv *priv; 424116808Sharti int error = 0; 425116808Sharti 426116808Sharti if (node == NULL) 427116808Sharti return (0); 428116808Sharti priv = NG_NODE_PRIVATE(node); 429116808Sharti if (priv->output) { 430116808Sharti NG_SEND_DATA_ONLY(error, priv->output, *mp); 431116808Sharti *mp = NULL; 432116808Sharti } 433116808Sharti 434116808Sharti return (error); 435116808Sharti} 436116808Sharti 437116808Sharti/* 438116808Sharti * Well, this doesn't make much sense for ATM. 439116808Sharti */ 440116808Shartistatic void 441116808Sharting_atm_input_orphans(struct ifnet *ifp, struct mbuf *m, 442116808Sharti struct atm_pseudohdr *ah, void *rxhand) 443116808Sharti{ 444116808Sharti node_p node = IFP2NG(ifp); 445116808Sharti struct priv *priv; 446116808Sharti int error; 447116808Sharti 448116808Sharti if (node == NULL) { 449116808Sharti m_freem(m); 450116808Sharti return; 451116808Sharti } 452116808Sharti priv = NG_NODE_PRIVATE(node); 453116808Sharti if (priv->orphans == NULL) { 454116808Sharti m_freem(m); 455116808Sharti return; 456116808Sharti } 457116808Sharti /* 458116808Sharti * Prepend the atm_pseudoheader. 459116808Sharti */ 460116808Sharti M_PREPEND(m, sizeof(*ah), M_DONTWAIT); 461116808Sharti if (m == NULL) 462116808Sharti return; 463116808Sharti memcpy(mtod(m, struct atm_pseudohdr *), ah, sizeof(*ah)); 464116808Sharti NG_SEND_DATA_ONLY(error, priv->orphans, m); 465116808Sharti if (error == 0) 466116808Sharti priv->in_packets++; 467116808Sharti else { 468116808Sharti priv->in_errors++; 469116808Sharti#ifdef NGATM_DEBUG 470116808Sharti printf("%s: error=%d\n", __func__, error); 471116808Sharti#endif 472116808Sharti } 473116808Sharti} 474116808Sharti 475116808Sharti/************************************************************/ 476116808Sharti/* 477116808Sharti * OUTPUT 478116808Sharti */ 479116808Shartistatic int 480116808Sharting_atm_rcvdata(hook_p hook, item_p item) 481116808Sharti{ 482116808Sharti node_p node = NG_HOOK_NODE(hook); 483116808Sharti struct priv *priv = NG_NODE_PRIVATE(node); 484116808Sharti const struct ngvcc *vcc = NG_HOOK_PRIVATE(hook); 485116808Sharti struct mbuf *m; 486116808Sharti struct atm_pseudohdr *aph; 487116808Sharti int error; 488116808Sharti 489116808Sharti if (vcc->vci == 0) { 490116808Sharti NG_FREE_ITEM(item); 491116808Sharti return (ENOTCONN); 492116808Sharti } 493116808Sharti 494116808Sharti NGI_GET_M(item, m); 495116808Sharti NG_FREE_ITEM(item); 496116808Sharti 497116808Sharti /* 498116808Sharti * Prepend pseudo-hdr. Drivers don't care about the flags. 499116808Sharti */ 500116808Sharti M_PREPEND(m, sizeof(*aph), M_DONTWAIT); 501116808Sharti if (m == NULL) { 502116808Sharti NG_FREE_M(m); 503116808Sharti return (ENOMEM); 504116808Sharti } 505116808Sharti aph = mtod(m, struct atm_pseudohdr *); 506116808Sharti ATM_PH_VPI(aph) = vcc->vpi; 507116808Sharti ATM_PH_SETVCI(aph, vcc->vci); 508116808Sharti ATM_PH_FLAGS(aph) = 0; 509116808Sharti 510116808Sharti if ((error = atm_output(priv->ifp, m, NULL, NULL)) == 0) 511116808Sharti priv->out_packets++; 512116808Sharti else 513116808Sharti priv->out_errors++; 514116808Sharti return (error); 515116808Sharti} 516116808Sharti 517116808Shartistatic int 518116808Sharting_atm_rcvdrop(hook_p hook, item_p item) 519116808Sharti{ 520116808Sharti NG_FREE_ITEM(item); 521116808Sharti return (0); 522116808Sharti} 523116808Sharti 524116808Sharti 525116808Sharti/************************************************************ 526116808Sharti * 527118175Sharti * Event from driver. 528116808Sharti */ 529116808Shartistatic void 530118175Sharting_atm_event_func(node_p node, hook_p hook, void *arg, int event) 531116808Sharti{ 532116808Sharti const struct priv *priv = NG_NODE_PRIVATE(node); 533116808Sharti struct ngvcc *vcc; 534116808Sharti struct ng_mesg *mesg; 535116808Sharti int error; 536116808Sharti 537118175Sharti switch (event) { 538116808Sharti 539118175Sharti case ATMEV_FLOW_CONTROL: 540116808Sharti { 541118175Sharti struct atmev_flow_control *ev = arg; 542116808Sharti struct ngm_queue_state *qstate; 543116808Sharti 544116808Sharti /* find the connection */ 545116808Sharti LIST_FOREACH(vcc, &priv->vccs, link) 546118175Sharti if (vcc->vci == ev->vci && vcc->vpi == ev->vpi) 547116808Sharti break; 548116808Sharti if (vcc == NULL) 549116808Sharti break; 550116808Sharti 551116808Sharti /* convert into a flow control message */ 552116808Sharti NG_MKMESSAGE(mesg, NGM_FLOW_COOKIE, 553118175Sharti ev->busy ? NGM_HIGH_WATER_PASSED : NGM_LOW_WATER_PASSED, 554116808Sharti sizeof(struct ngm_queue_state), M_NOWAIT); 555116808Sharti if (mesg == NULL) 556116808Sharti break; 557116808Sharti qstate = (struct ngm_queue_state *)mesg->data; 558116808Sharti 559116808Sharti /* XXX have to figure out how to get that info */ 560116808Sharti 561123812Salfred NG_SEND_MSG_HOOK(error, node, mesg, vcc->hook, 0); 562116808Sharti break; 563116808Sharti } 564116808Sharti 565118175Sharti case ATMEV_VCC_CHANGED: 566116808Sharti { 567118175Sharti struct atmev_vcc_changed *ev = arg; 568116808Sharti struct ngm_atm_vcc_change *chg; 569116808Sharti 570116808Sharti if (priv->manage == NULL) 571116808Sharti break; 572116808Sharti NG_MKMESSAGE(mesg, NGM_ATM_COOKIE, NGM_ATM_VCC_CHANGE, 573116808Sharti sizeof(struct ngm_atm_vcc_change), M_NOWAIT); 574116808Sharti if (mesg == NULL) 575116808Sharti break; 576116808Sharti chg = (struct ngm_atm_vcc_change *)mesg->data; 577118175Sharti chg->vci = ev->vci; 578118175Sharti chg->vpi = ev->vpi; 579118175Sharti chg->state = (ev->up != 0); 580116808Sharti chg->node = NG_NODE_ID(node); 581123812Salfred NG_SEND_MSG_HOOK(error, node, mesg, priv->manage, 0); 582116808Sharti break; 583116808Sharti } 584116808Sharti 585118175Sharti case ATMEV_IFSTATE_CHANGED: 586116808Sharti { 587118175Sharti struct atmev_ifstate_changed *ev = arg; 588118175Sharti struct ngm_atm_if_change *chg; 589116808Sharti 590116808Sharti if (priv->manage == NULL) 591116808Sharti break; 592118175Sharti NG_MKMESSAGE(mesg, NGM_ATM_COOKIE, NGM_ATM_IF_CHANGE, 593118175Sharti sizeof(struct ngm_atm_if_change), M_NOWAIT); 594116808Sharti if (mesg == NULL) 595116808Sharti break; 596118175Sharti chg = (struct ngm_atm_if_change *)mesg->data; 597118175Sharti chg->carrier = (ev->carrier != 0); 598118175Sharti chg->running = (ev->running != 0); 599116808Sharti chg->node = NG_NODE_ID(node); 600123812Salfred NG_SEND_MSG_HOOK(error, node, mesg, priv->manage, 0); 601116808Sharti break; 602116808Sharti } 603118175Sharti 604118175Sharti case ATMEV_ACR_CHANGED: 605118175Sharti { 606118175Sharti struct atmev_acr_changed *ev = arg; 607118175Sharti struct ngm_atm_acr_change *acr; 608118175Sharti 609118175Sharti /* find the connection */ 610118175Sharti LIST_FOREACH(vcc, &priv->vccs, link) 611118175Sharti if (vcc->vci == ev->vci && vcc->vpi == ev->vpi) 612118175Sharti break; 613118175Sharti if (vcc == NULL) 614118175Sharti break; 615118175Sharti 616118175Sharti /* convert into a flow control message */ 617118175Sharti NG_MKMESSAGE(mesg, NGM_ATM_COOKIE, NGM_ATM_ACR_CHANGE, 618118175Sharti sizeof(struct ngm_atm_acr_change), M_NOWAIT); 619118175Sharti if (mesg == NULL) 620118175Sharti break; 621118175Sharti acr = (struct ngm_atm_acr_change *)mesg->data; 622118175Sharti acr->node = NG_NODE_ID(node); 623118175Sharti acr->vci = ev->vci; 624118175Sharti acr->vpi = ev->vpi; 625118175Sharti acr->acr = ev->acr; 626118175Sharti 627123812Salfred NG_SEND_MSG_HOOK(error, node, mesg, vcc->hook, 0); 628118175Sharti break; 629118175Sharti } 630116808Sharti } 631116808Sharti} 632116808Sharti 633116808Sharti/* 634116808Sharti * Use send_fn to get the right lock 635116808Sharti */ 636116808Shartistatic void 637118175Sharting_atm_event(struct ifnet *ifp, uint32_t event, void *arg) 638116808Sharti{ 639116808Sharti const node_p node = IFP2NG(ifp); 640116808Sharti 641118175Sharti if (node != NULL) 642118175Sharti /* may happen during attach/detach */ 643118175Sharti (void)ng_send_fn(node, NULL, ng_atm_event_func, arg, event); 644116808Sharti} 645116808Sharti 646116808Sharti/************************************************************ 647116808Sharti * 648116808Sharti * CPCS 649116808Sharti */ 650116808Sharti/* 651116808Sharti * Open a channel for the user 652116808Sharti */ 653116808Shartistatic int 654116808Sharting_atm_cpcs_init(node_p node, const struct ngm_atm_cpcs_init *arg) 655116808Sharti{ 656116808Sharti struct priv *priv = NG_NODE_PRIVATE(node); 657116808Sharti const struct ifatm_mib *mib; 658116808Sharti struct ngvcc *vcc; 659116808Sharti struct atmio_openvcc data; 660116808Sharti int err; 661116808Sharti 662116808Sharti if(priv->ifp->if_ioctl == NULL) 663116808Sharti return (ENXIO); 664116808Sharti 665116808Sharti mib = (const struct ifatm_mib *)(priv->ifp->if_linkmib); 666116808Sharti 667116808Sharti LIST_FOREACH(vcc, &priv->vccs, link) 668116808Sharti if (strcmp(arg->name, NG_HOOK_NAME(vcc->hook)) == 0) 669116808Sharti break; 670116808Sharti if (vcc == NULL) 671116808Sharti return (ENOTCONN); 672117642Sharti if (vcc->flags & VCC_OPEN) 673116808Sharti return (EISCONN); 674116808Sharti 675116808Sharti /* 676116808Sharti * Check user arguments and construct ioctl argument 677116808Sharti */ 678116808Sharti memset(&data, 0, sizeof(data)); 679116808Sharti 680116808Sharti data.rxhand = vcc; 681116808Sharti 682116808Sharti switch (data.param.aal = arg->aal) { 683116808Sharti 684117157Sharti case ATMIO_AAL_34: 685116808Sharti case ATMIO_AAL_5: 686116808Sharti case ATMIO_AAL_0: 687116808Sharti case ATMIO_AAL_RAW: 688116808Sharti break; 689116808Sharti 690116808Sharti default: 691116808Sharti return (EINVAL); 692116808Sharti } 693116808Sharti 694116808Sharti if (arg->vpi > 0xff) 695116808Sharti return (EINVAL); 696116808Sharti data.param.vpi = arg->vpi; 697116808Sharti 698117157Sharti /* allow 0.0 as catch all receive channel */ 699117157Sharti if (arg->vci == 0 && (arg->vpi != 0 || !(arg->flags & ATMIO_FLAG_NOTX))) 700117157Sharti return (EINVAL); 701116808Sharti data.param.vci = arg->vci; 702116808Sharti 703116808Sharti data.param.tparam.pcr = arg->pcr; 704116808Sharti 705116808Sharti if (arg->mcr > arg->pcr) 706116808Sharti return (EINVAL); 707116808Sharti data.param.tparam.mcr = arg->mcr; 708116808Sharti 709116808Sharti if (!(arg->flags & ATMIO_FLAG_NOTX)) { 710117157Sharti if (arg->tmtu == 0) 711117157Sharti data.param.tmtu = priv->ifp->if_mtu; 712117157Sharti else { 713117157Sharti data.param.tmtu = arg->tmtu; 714117157Sharti } 715116808Sharti } 716116808Sharti if (!(arg->flags & ATMIO_FLAG_NORX)) { 717117157Sharti if (arg->rmtu == 0) 718117157Sharti data.param.rmtu = priv->ifp->if_mtu; 719117157Sharti else { 720117157Sharti data.param.rmtu = arg->rmtu; 721117157Sharti } 722116808Sharti } 723116808Sharti 724116808Sharti switch (data.param.traffic = arg->traffic) { 725116808Sharti 726116808Sharti case ATMIO_TRAFFIC_UBR: 727116808Sharti case ATMIO_TRAFFIC_CBR: 728116808Sharti break; 729116808Sharti 730116808Sharti case ATMIO_TRAFFIC_VBR: 731116808Sharti if (arg->scr > arg->pcr) 732116808Sharti return (EINVAL); 733116808Sharti data.param.tparam.scr = arg->scr; 734116808Sharti 735116808Sharti if (arg->mbs > (1 << 24)) 736116808Sharti return (EINVAL); 737116808Sharti data.param.tparam.mbs = arg->mbs; 738116808Sharti break; 739116808Sharti 740116808Sharti case ATMIO_TRAFFIC_ABR: 741116808Sharti if (arg->icr > arg->pcr || arg->icr < arg->mcr) 742116808Sharti return (EINVAL); 743116808Sharti data.param.tparam.icr = arg->icr; 744116808Sharti 745116808Sharti if (arg->tbe == 0 || arg->tbe > (1 << 24)) 746116808Sharti return (EINVAL); 747116808Sharti data.param.tparam.tbe = arg->tbe; 748116808Sharti 749116808Sharti if (arg->nrm > 0x7) 750116808Sharti return (EINVAL); 751116808Sharti data.param.tparam.nrm = arg->nrm; 752116808Sharti 753116808Sharti if (arg->trm > 0x7) 754116808Sharti return (EINVAL); 755116808Sharti data.param.tparam.trm = arg->trm; 756116808Sharti 757116808Sharti if (arg->adtf > 0x3ff) 758116808Sharti return (EINVAL); 759116808Sharti data.param.tparam.adtf = arg->adtf; 760116808Sharti 761116808Sharti if (arg->rif > 0xf) 762116808Sharti return (EINVAL); 763116808Sharti data.param.tparam.rif = arg->rif; 764116808Sharti 765116808Sharti if (arg->rdf > 0xf) 766116808Sharti return (EINVAL); 767116808Sharti data.param.tparam.rdf = arg->rdf; 768116808Sharti 769116808Sharti if (arg->cdf > 0x7) 770116808Sharti return (EINVAL); 771116808Sharti data.param.tparam.cdf = arg->cdf; 772116808Sharti 773116808Sharti break; 774116808Sharti 775116808Sharti default: 776116808Sharti return (EINVAL); 777116808Sharti } 778116808Sharti 779116808Sharti if ((arg->flags & ATMIO_FLAG_NORX) && (arg->flags & ATMIO_FLAG_NOTX)) 780116808Sharti return (EINVAL); 781116808Sharti 782116808Sharti data.param.flags = arg->flags & ~(ATM_PH_AAL5 | ATM_PH_LLCSNAP); 783116808Sharti data.param.flags |= ATMIO_FLAG_NG; 784116808Sharti 785116808Sharti err = (*priv->ifp->if_ioctl)(priv->ifp, SIOCATMOPENVCC, (caddr_t)&data); 786116808Sharti 787116808Sharti if (err == 0) { 788116808Sharti vcc->vci = data.param.vci; 789116808Sharti vcc->vpi = data.param.vpi; 790117157Sharti vcc->flags = VCC_OPEN; 791116808Sharti } 792116808Sharti 793116808Sharti return (err); 794116808Sharti} 795116808Sharti 796116808Sharti/* 797116808Sharti * Issue the close command to the driver 798116808Sharti */ 799116808Shartistatic int 800116808Sharticpcs_term(const struct priv *priv, u_int vpi, u_int vci) 801116808Sharti{ 802116808Sharti struct atmio_closevcc data; 803116808Sharti 804116808Sharti if (priv->ifp->if_ioctl == NULL) 805116808Sharti return ENXIO; 806116808Sharti 807116808Sharti data.vpi = vpi; 808116808Sharti data.vci = vci; 809116808Sharti 810116808Sharti return ((*priv->ifp->if_ioctl)(priv->ifp, 811116808Sharti SIOCATMCLOSEVCC, (caddr_t)&data)); 812116808Sharti} 813116808Sharti 814116808Sharti 815116808Sharti/* 816116808Sharti * Close a channel by request of the user 817116808Sharti */ 818116808Shartistatic int 819116808Sharting_atm_cpcs_term(node_p node, const struct ngm_atm_cpcs_term *arg) 820116808Sharti{ 821116808Sharti struct priv *priv = NG_NODE_PRIVATE(node); 822116808Sharti struct ngvcc *vcc; 823116808Sharti int error; 824116808Sharti 825116808Sharti LIST_FOREACH(vcc, &priv->vccs, link) 826116808Sharti if(strcmp(arg->name, NG_HOOK_NAME(vcc->hook)) == 0) 827116808Sharti break; 828116808Sharti if (vcc == NULL) 829116808Sharti return (ENOTCONN); 830117642Sharti if (!(vcc->flags & VCC_OPEN)) 831116808Sharti return (ENOTCONN); 832116808Sharti 833116808Sharti error = cpcs_term(priv, vcc->vpi, vcc->vci); 834116808Sharti 835116808Sharti vcc->vci = 0; 836116808Sharti vcc->vpi = 0; 837116808Sharti vcc->flags = 0; 838116808Sharti 839116808Sharti return (error); 840116808Sharti} 841116808Sharti 842116808Sharti/************************************************************/ 843116808Sharti/* 844116808Sharti * CONTROL MESSAGES 845116808Sharti */ 846116808Sharti 847116808Sharti/* 848116808Sharti * Produce a textual description of the current status 849116808Sharti */ 850116808Shartistatic int 851116808Shartitext_status(node_p node, char *arg, u_int len) 852116808Sharti{ 853116808Sharti const struct priv *priv = NG_NODE_PRIVATE(node); 854116808Sharti const struct ifatm_mib *mib; 855116808Sharti struct sbuf sbuf; 856116808Sharti u_int i; 857116808Sharti 858116808Sharti static const struct { 859116808Sharti const char *name; 860116808Sharti const char *vendor; 861116808Sharti } devices[] = { 862116808Sharti ATM_DEVICE_NAMES 863116808Sharti }; 864116808Sharti 865116808Sharti mib = (const struct ifatm_mib *)(priv->ifp->if_linkmib); 866116808Sharti 867116808Sharti sbuf_new(&sbuf, arg, len, SBUF_FIXEDLEN); 868121816Sbrooks sbuf_printf(&sbuf, "interface: %s\n", priv->ifp->if_xname); 869116808Sharti 870116808Sharti if (mib->device >= sizeof(devices) / sizeof(devices[0])) 871116808Sharti sbuf_printf(&sbuf, "device=unknown\nvendor=unknown\n"); 872116808Sharti else 873116808Sharti sbuf_printf(&sbuf, "device=%s\nvendor=%s\n", 874116808Sharti devices[mib->device].name, devices[mib->device].vendor); 875116808Sharti 876116808Sharti for (i = 0; atmmedia[i].name; i++) 877116808Sharti if(mib->media == atmmedia[i].media) { 878116808Sharti sbuf_printf(&sbuf, "media=%s\n", atmmedia[i].name); 879116808Sharti break; 880116808Sharti } 881116808Sharti if(atmmedia[i].name == NULL) 882116808Sharti sbuf_printf(&sbuf, "media=unknown\n"); 883116808Sharti 884116808Sharti sbuf_printf(&sbuf, "serial=%u esi=%6D hardware=%u software=%u\n", 885116808Sharti mib->serial, mib->esi, ":", mib->hw_version, mib->sw_version); 886116808Sharti sbuf_printf(&sbuf, "pcr=%u vpi_bits=%u vci_bits=%u max_vpcs=%u " 887116808Sharti "max_vccs=%u\n", mib->pcr, mib->vpi_bits, mib->vci_bits, 888116808Sharti mib->max_vpcs, mib->max_vccs); 889116808Sharti sbuf_printf(&sbuf, "ifflags=%b\n", priv->ifp->if_flags, IFFLAGS); 890116808Sharti 891116808Sharti sbuf_finish(&sbuf); 892116808Sharti 893116808Sharti return (sbuf_len(&sbuf)); 894116808Sharti} 895116808Sharti 896116808Sharti/* 897116808Sharti * Get control message 898116808Sharti */ 899116808Shartistatic int 900116808Sharting_atm_rcvmsg(node_p node, item_p item, hook_p lasthook) 901116808Sharti{ 902116808Sharti const struct priv *priv = NG_NODE_PRIVATE(node); 903116808Sharti struct ng_mesg *resp = NULL; 904116808Sharti struct ng_mesg *msg; 905116808Sharti struct ifatm_mib *mib = (struct ifatm_mib *)(priv->ifp->if_linkmib); 906116808Sharti int error = 0; 907116808Sharti 908116808Sharti NGI_GET_MSG(item, msg); 909116808Sharti 910116808Sharti switch (msg->header.typecookie) { 911116808Sharti 912116808Sharti case NGM_GENERIC_COOKIE: 913116808Sharti switch (msg->header.cmd) { 914116808Sharti 915116808Sharti case NGM_TEXT_STATUS: 916116808Sharti NG_MKRESPONSE(resp, msg, NG_TEXTRESPONSE, M_NOWAIT); 917116808Sharti if(resp == NULL) { 918116808Sharti error = ENOMEM; 919116808Sharti break; 920116808Sharti } 921116808Sharti 922116808Sharti resp->header.arglen = text_status(node, 923116808Sharti (char *)resp->data, resp->header.arglen) + 1; 924116808Sharti break; 925116808Sharti 926116808Sharti default: 927116808Sharti error = EINVAL; 928116808Sharti break; 929116808Sharti } 930116808Sharti break; 931116808Sharti 932116808Sharti case NGM_ATM_COOKIE: 933116808Sharti switch (msg->header.cmd) { 934116808Sharti 935116808Sharti case NGM_ATM_GET_IFNAME: 936116808Sharti NG_MKRESPONSE(resp, msg, IFNAMSIZ + 1, M_NOWAIT); 937116808Sharti if (resp == NULL) { 938116808Sharti error = ENOMEM; 939116808Sharti break; 940116808Sharti } 941121816Sbrooks strlcpy(resp->data, priv->ifp->if_xname, IFNAMSIZ + 1); 942116808Sharti break; 943116808Sharti 944116808Sharti case NGM_ATM_GET_CONFIG: 945116808Sharti { 946116808Sharti struct ngm_atm_config *config; 947116808Sharti 948116808Sharti NG_MKRESPONSE(resp, msg, sizeof(*config), M_NOWAIT); 949116808Sharti if (resp == NULL) { 950116808Sharti error = ENOMEM; 951116808Sharti break; 952116808Sharti } 953116808Sharti config = (struct ngm_atm_config *)resp->data; 954116808Sharti config->pcr = mib->pcr; 955116808Sharti config->vpi_bits = mib->vpi_bits; 956116808Sharti config->vci_bits = mib->vci_bits; 957116808Sharti config->max_vpcs = mib->max_vpcs; 958116808Sharti config->max_vccs = mib->max_vccs; 959116808Sharti break; 960116808Sharti } 961116808Sharti 962116808Sharti case NGM_ATM_GET_VCCS: 963116808Sharti { 964116808Sharti struct atmio_vcctable *vccs; 965116808Sharti size_t len; 966116808Sharti 967116808Sharti if (priv->ifp->if_ioctl == NULL) { 968116808Sharti error = ENXIO; 969116808Sharti break; 970116808Sharti } 971116808Sharti error = (*priv->ifp->if_ioctl)(priv->ifp, 972116808Sharti SIOCATMGETVCCS, (caddr_t)&vccs); 973116808Sharti if (error) 974116808Sharti break; 975116808Sharti 976116808Sharti len = sizeof(*vccs) + 977116808Sharti vccs->count * sizeof(vccs->vccs[0]); 978116808Sharti NG_MKRESPONSE(resp, msg, len, M_NOWAIT); 979116808Sharti if (resp == NULL) { 980116808Sharti error = ENOMEM; 981116808Sharti free(vccs, M_DEVBUF); 982116808Sharti break; 983116808Sharti } 984116808Sharti 985116808Sharti (void)memcpy(resp->data, vccs, len); 986116808Sharti free(vccs, M_DEVBUF); 987116808Sharti 988116808Sharti break; 989116808Sharti } 990116808Sharti 991116808Sharti case NGM_ATM_GET_VCC: 992116808Sharti { 993125035Sharti char hook[NG_HOOKSIZ]; 994116808Sharti struct atmio_vcctable *vccs; 995116808Sharti struct ngvcc *vcc; 996116808Sharti u_int i; 997116808Sharti 998116808Sharti if (priv->ifp->if_ioctl == NULL) { 999116808Sharti error = ENXIO; 1000116808Sharti break; 1001116808Sharti } 1002125035Sharti if (msg->header.arglen != NG_HOOKSIZ) { 1003116808Sharti error = EINVAL; 1004116808Sharti break; 1005116808Sharti } 1006125035Sharti strncpy(hook, msg->data, NG_HOOKSIZ); 1007125035Sharti hook[NG_HOOKSIZ - 1] = '\0'; 1008116808Sharti LIST_FOREACH(vcc, &priv->vccs, link) 1009116808Sharti if (strcmp(NG_HOOK_NAME(vcc->hook), hook) == 0) 1010116808Sharti break; 1011116808Sharti if (vcc == NULL) { 1012116808Sharti error = ENOTCONN; 1013116808Sharti break; 1014116808Sharti } 1015116808Sharti error = (*priv->ifp->if_ioctl)(priv->ifp, 1016116808Sharti SIOCATMGETVCCS, (caddr_t)&vccs); 1017116808Sharti if (error) 1018116808Sharti break; 1019116808Sharti 1020116808Sharti for (i = 0; i < vccs->count; i++) 1021116808Sharti if (vccs->vccs[i].vpi == vcc->vpi && 1022116808Sharti vccs->vccs[i].vci == vcc->vci) 1023116808Sharti break; 1024116808Sharti if (i == vccs->count) { 1025116808Sharti error = ENOTCONN; 1026116808Sharti free(vccs, M_DEVBUF); 1027116808Sharti break; 1028116808Sharti } 1029116808Sharti 1030116808Sharti NG_MKRESPONSE(resp, msg, sizeof(vccs->vccs[0]), 1031116808Sharti M_NOWAIT); 1032116808Sharti if (resp == NULL) { 1033116808Sharti error = ENOMEM; 1034116808Sharti free(vccs, M_DEVBUF); 1035116808Sharti break; 1036116808Sharti } 1037116808Sharti 1038116808Sharti *(struct atmio_vcc *)resp->data = vccs->vccs[i]; 1039116808Sharti free(vccs, M_DEVBUF); 1040116808Sharti break; 1041116808Sharti } 1042116808Sharti 1043116808Sharti case NGM_ATM_GET_VCCID: 1044116808Sharti { 1045116808Sharti struct atmio_vcc *arg; 1046116808Sharti struct atmio_vcctable *vccs; 1047116808Sharti u_int i; 1048116808Sharti 1049116808Sharti if (priv->ifp->if_ioctl == NULL) { 1050116808Sharti error = ENXIO; 1051116808Sharti break; 1052116808Sharti } 1053116808Sharti if (msg->header.arglen != sizeof(*arg)) { 1054116808Sharti error = EINVAL; 1055116808Sharti break; 1056116808Sharti } 1057116808Sharti arg = (struct atmio_vcc *)msg->data; 1058116808Sharti 1059116808Sharti error = (*priv->ifp->if_ioctl)(priv->ifp, 1060116808Sharti SIOCATMGETVCCS, (caddr_t)&vccs); 1061116808Sharti if (error) 1062116808Sharti break; 1063116808Sharti 1064116808Sharti for (i = 0; i < vccs->count; i++) 1065116808Sharti if (vccs->vccs[i].vpi == arg->vpi && 1066116808Sharti vccs->vccs[i].vci == arg->vci) 1067116808Sharti break; 1068116808Sharti if (i == vccs->count) { 1069116808Sharti error = ENOTCONN; 1070116808Sharti free(vccs, M_DEVBUF); 1071116808Sharti break; 1072116808Sharti } 1073116808Sharti 1074116808Sharti NG_MKRESPONSE(resp, msg, sizeof(vccs->vccs[0]), 1075116808Sharti M_NOWAIT); 1076116808Sharti if (resp == NULL) { 1077116808Sharti error = ENOMEM; 1078116808Sharti free(vccs, M_DEVBUF); 1079116808Sharti break; 1080116808Sharti } 1081116808Sharti 1082116808Sharti *(struct atmio_vcc *)resp->data = vccs->vccs[i]; 1083116808Sharti free(vccs, M_DEVBUF); 1084116808Sharti break; 1085116808Sharti } 1086116808Sharti 1087116808Sharti case NGM_ATM_CPCS_INIT: 1088116808Sharti if (msg->header.arglen != 1089116808Sharti sizeof(struct ngm_atm_cpcs_init)) { 1090116808Sharti error = EINVAL; 1091116808Sharti break; 1092116808Sharti } 1093116808Sharti error = ng_atm_cpcs_init(node, 1094116808Sharti (struct ngm_atm_cpcs_init *)msg->data); 1095116808Sharti break; 1096116808Sharti 1097116808Sharti case NGM_ATM_CPCS_TERM: 1098116808Sharti if (msg->header.arglen != 1099116808Sharti sizeof(struct ngm_atm_cpcs_term)) { 1100116808Sharti error = EINVAL; 1101116808Sharti break; 1102116808Sharti } 1103116808Sharti error = ng_atm_cpcs_term(node, 1104116808Sharti (struct ngm_atm_cpcs_term *)msg->data); 1105116808Sharti break; 1106116808Sharti 1107116808Sharti case NGM_ATM_GET_STATS: 1108116808Sharti { 1109116808Sharti struct ngm_atm_stats *p; 1110116808Sharti 1111116808Sharti if (msg->header.arglen != 0) { 1112116808Sharti error = EINVAL; 1113116808Sharti break; 1114116808Sharti } 1115116808Sharti NG_MKRESPONSE(resp, msg, sizeof(*p), M_NOWAIT); 1116116808Sharti if (resp == NULL) { 1117116808Sharti error = ENOMEM; 1118116808Sharti break; 1119116808Sharti } 1120116808Sharti p = (struct ngm_atm_stats *)resp->data; 1121116808Sharti p->in_packets = priv->in_packets; 1122116808Sharti p->out_packets = priv->out_packets; 1123116808Sharti p->in_errors = priv->in_errors; 1124116808Sharti p->out_errors = priv->out_errors; 1125116808Sharti 1126116808Sharti break; 1127116808Sharti } 1128116808Sharti 1129116808Sharti default: 1130116808Sharti error = EINVAL; 1131116808Sharti break; 1132116808Sharti } 1133116808Sharti break; 1134116808Sharti 1135116808Sharti default: 1136116808Sharti error = EINVAL; 1137116808Sharti break; 1138116808Sharti } 1139116808Sharti 1140116808Sharti NG_RESPOND_MSG(error, node, item, resp); 1141116808Sharti NG_FREE_MSG(msg); 1142116808Sharti return (error); 1143116808Sharti} 1144116808Sharti 1145116808Sharti/************************************************************/ 1146116808Sharti/* 1147116808Sharti * HOOK MANAGEMENT 1148116808Sharti */ 1149116808Sharti 1150116808Sharti/* 1151116808Sharti * A new hook is create that will be connected to the node. 1152116808Sharti * Check, whether the name is one of the predefined ones. 1153116808Sharti * If not, create a new entry into the vcc list. 1154116808Sharti */ 1155116808Shartistatic int 1156116808Sharting_atm_newhook(node_p node, hook_p hook, const char *name) 1157116808Sharti{ 1158116808Sharti struct priv *priv = NG_NODE_PRIVATE(node); 1159116808Sharti struct ngvcc *vcc; 1160116808Sharti 1161116808Sharti if (strcmp(name, "input") == 0) { 1162116808Sharti priv->input = hook; 1163116808Sharti NG_HOOK_SET_RCVDATA(hook, ng_atm_rcvdrop); 1164116808Sharti return (0); 1165116808Sharti } 1166116808Sharti if (strcmp(name, "output") == 0) { 1167116808Sharti priv->output = hook; 1168116808Sharti NG_HOOK_SET_RCVDATA(hook, ng_atm_rcvdrop); 1169116808Sharti return (0); 1170116808Sharti } 1171116808Sharti if (strcmp(name, "orphans") == 0) { 1172116808Sharti priv->orphans = hook; 1173116808Sharti NG_HOOK_SET_RCVDATA(hook, ng_atm_rcvdrop); 1174116808Sharti return (0); 1175116808Sharti } 1176116808Sharti 1177116808Sharti /* 1178116808Sharti * Allocate a new entry 1179116808Sharti */ 1180116808Sharti vcc = malloc(sizeof(*vcc), M_NETGRAPH, M_NOWAIT | M_ZERO); 1181116808Sharti if (vcc == NULL) 1182116808Sharti return (ENOMEM); 1183116808Sharti 1184116808Sharti vcc->hook = hook; 1185116808Sharti NG_HOOK_SET_PRIVATE(hook, vcc); 1186116808Sharti 1187116808Sharti LIST_INSERT_HEAD(&priv->vccs, vcc, link); 1188116808Sharti 1189116808Sharti if (strcmp(name, "manage") == 0) 1190116808Sharti priv->manage = hook; 1191116808Sharti 1192116808Sharti return (0); 1193116808Sharti} 1194116808Sharti 1195116808Sharti/* 1196116808Sharti * Connect. Set the peer to queuing. 1197116808Sharti */ 1198116808Shartistatic int 1199116808Sharting_atm_connect(hook_p hook) 1200116808Sharti{ 1201116808Sharti if (NG_HOOK_PRIVATE(hook) != NULL) 1202116808Sharti NG_HOOK_FORCE_QUEUE(NG_HOOK_PEER(hook)); 1203116808Sharti 1204116808Sharti return (0); 1205116808Sharti} 1206116808Sharti 1207116808Sharti/* 1208116808Sharti * Disconnect a HOOK 1209116808Sharti */ 1210116808Shartistatic int 1211116808Sharting_atm_disconnect(hook_p hook) 1212116808Sharti{ 1213116808Sharti struct priv *priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); 1214116808Sharti struct ngvcc *vcc = NG_HOOK_PRIVATE(hook); 1215116808Sharti 1216116808Sharti if (vcc == NULL) { 1217116808Sharti if (hook == priv->output) { 1218116808Sharti priv->output = NULL; 1219116808Sharti return (0); 1220116808Sharti } 1221116808Sharti if (hook == priv->input) { 1222116808Sharti priv->input = NULL; 1223116808Sharti return (0); 1224116808Sharti } 1225116808Sharti if (hook == priv->orphans) { 1226116808Sharti priv->orphans = NULL; 1227116808Sharti return (0); 1228116808Sharti } 1229116808Sharti log(LOG_ERR, "ng_atm: bad hook '%s'", NG_HOOK_NAME(hook)); 1230116808Sharti return (0); 1231116808Sharti } 1232116808Sharti 1233116808Sharti /* don't terminate if we are detaching from the interface */ 1234117157Sharti if ((vcc->flags & VCC_OPEN) && priv->ifp != NULL) 1235116808Sharti (void)cpcs_term(priv, vcc->vpi, vcc->vci); 1236116808Sharti 1237116808Sharti NG_HOOK_SET_PRIVATE(hook, NULL); 1238116808Sharti 1239116808Sharti LIST_REMOVE(vcc, link); 1240116808Sharti free(vcc, M_NETGRAPH); 1241116808Sharti 1242116808Sharti if (hook == priv->manage) 1243116808Sharti priv->manage = NULL; 1244116808Sharti 1245116808Sharti return (0); 1246116808Sharti} 1247116808Sharti 1248116808Sharti/************************************************************/ 1249116808Sharti/* 1250116808Sharti * NODE MANAGEMENT 1251116808Sharti */ 1252116808Sharti 1253116808Sharti/* 1254116808Sharti * ATM interface attached - create a node and name it like the interface. 1255116808Sharti */ 1256116808Shartistatic void 1257116808Sharting_atm_attach(struct ifnet *ifp) 1258116808Sharti{ 1259116808Sharti char name[IFNAMSIZ+1]; 1260116808Sharti node_p node; 1261116808Sharti struct priv *priv; 1262116808Sharti 1263116808Sharti KASSERT(IFP2NG(ifp) == 0, ("%s: node alreay exists?", __FUNCTION__)); 1264116808Sharti 1265121816Sbrooks strlcpy(name, ifp->if_xname, sizeof(name)); 1266116808Sharti 1267116808Sharti if (ng_make_node_common(&ng_atm_typestruct, &node) != 0) { 1268116808Sharti log(LOG_ERR, "%s: can't create node for %s\n", 1269116808Sharti __FUNCTION__, name); 1270116808Sharti return; 1271116808Sharti } 1272116808Sharti 1273116808Sharti priv = malloc(sizeof(*priv), M_NETGRAPH, M_NOWAIT | M_ZERO); 1274116808Sharti if (priv == NULL) { 1275116808Sharti log(LOG_ERR, "%s: can't allocate memory for %s\n", 1276116808Sharti __FUNCTION__, name); 1277116808Sharti NG_NODE_UNREF(node); 1278116808Sharti return; 1279116808Sharti } 1280116808Sharti NG_NODE_SET_PRIVATE(node, priv); 1281116808Sharti priv->ifp = ifp; 1282116808Sharti LIST_INIT(&priv->vccs); 1283116808Sharti IFP2NG(ifp) = node; 1284116808Sharti 1285116808Sharti if (ng_name_node(node, name) != 0) { 1286116808Sharti log(LOG_WARNING, "%s: can't name node %s\n", 1287116808Sharti __FUNCTION__, name); 1288116808Sharti } 1289116808Sharti} 1290116808Sharti 1291116808Sharti/* 1292116808Sharti * ATM interface detached - destroy node. 1293116808Sharti */ 1294116808Shartistatic void 1295116808Sharting_atm_detach(struct ifnet *ifp) 1296116808Sharti{ 1297116808Sharti const node_p node = IFP2NG(ifp); 1298116808Sharti struct priv *priv; 1299116808Sharti 1300116808Sharti if(node == NULL) 1301116808Sharti return; 1302116808Sharti 1303116808Sharti NG_NODE_REALLY_DIE(node); 1304116808Sharti 1305116808Sharti priv = NG_NODE_PRIVATE(node); 1306116808Sharti IFP2NG(priv->ifp) = NULL; 1307116808Sharti priv->ifp = NULL; 1308116808Sharti 1309116808Sharti ng_rmnode_self(node); 1310116808Sharti} 1311116808Sharti 1312116808Sharti/* 1313116808Sharti * Shutdown the node. This is called from the shutdown message processing. 1314116808Sharti */ 1315116808Shartistatic int 1316116808Sharting_atm_shutdown(node_p node) 1317116808Sharti{ 1318116808Sharti struct priv *priv = NG_NODE_PRIVATE(node); 1319116808Sharti 1320132464Sjulian if (node->nd_flags & NGF_REALLY_DIE) { 1321116808Sharti /* 1322116808Sharti * We are called from unloading the ATM driver. Really, 1323116808Sharti * really need to shutdown this node. The ifp was 1324116808Sharti * already handled in the detach routine. 1325116808Sharti */ 1326116808Sharti NG_NODE_SET_PRIVATE(node, NULL); 1327116808Sharti free(priv, M_NETGRAPH); 1328116808Sharti 1329116808Sharti NG_NODE_UNREF(node); 1330116808Sharti return (0); 1331116808Sharti } 1332116808Sharti 1333116808Sharti#ifdef NGATM_DEBUG 1334116808Sharti if (!allow_shutdown) 1335132464Sjulian NG_NODE_REVIVE(node); /* we persist */ 1336116808Sharti else { 1337116808Sharti IFP2NG(priv->ifp) = NULL; 1338116808Sharti NG_NODE_SET_PRIVATE(node, NULL); 1339116808Sharti free(priv, M_NETGRAPH); 1340116808Sharti NG_NODE_UNREF(node); 1341116808Sharti } 1342116808Sharti#else 1343116808Sharti /* 1344116808Sharti * We are persistant - reinitialize 1345116808Sharti */ 1346132464Sjulian NG_NODE_REVIVE(node); 1347116808Sharti#endif 1348116808Sharti return (0); 1349116808Sharti} 1350116808Sharti 1351116808Sharti/* 1352116808Sharti * Nodes are constructed only via interface attaches. 1353116808Sharti */ 1354116808Shartistatic int 1355116808Sharting_atm_constructor(node_p nodep) 1356116808Sharti{ 1357116808Sharti return (EINVAL); 1358116808Sharti} 1359116808Sharti 1360116808Sharti/************************************************************/ 1361116808Sharti/* 1362116808Sharti * INITIALISATION 1363116808Sharti */ 1364116808Sharti/* 1365116808Sharti * Loading and unloading of node type 1366116808Sharti * 1367116808Sharti * The assignments to the globals for the hooks should be ok without 1368116808Sharti * a special hook. The use pattern is generally: check that the pointer 1369116808Sharti * is not NULL, call the function. In the attach case this is no problem. 1370116808Sharti * In the detach case we can detach only when no ATM node exists. That 1371116808Sharti * means that there is no ATM interface anymore. So we are sure that 1372116808Sharti * we are not in the code path in if_atmsubr.c. To prevent someone 1373116808Sharti * from adding an interface after we have started to unload the node, we 1374116808Sharti * take the iflist lock so an if_attach will be blocked until we are done. 1375116808Sharti * XXX: perhaps the function pointers should be 'volatile' for this to work 1376116808Sharti * properly. 1377116808Sharti */ 1378116808Shartistatic int 1379116808Sharting_atm_mod_event(module_t mod, int event, void *data) 1380116808Sharti{ 1381116808Sharti struct ifnet *ifp; 1382116808Sharti int error = 0; 1383116808Sharti 1384116808Sharti switch (event) { 1385116808Sharti 1386116808Sharti case MOD_LOAD: 1387116808Sharti /* 1388116808Sharti * Register function hooks 1389116808Sharti */ 1390116808Sharti if (ng_atm_attach_p != NULL) { 1391116808Sharti error = EEXIST; 1392116808Sharti break; 1393116808Sharti } 1394116808Sharti IFNET_RLOCK(); 1395116808Sharti 1396116808Sharti ng_atm_attach_p = ng_atm_attach; 1397116808Sharti ng_atm_detach_p = ng_atm_detach; 1398116808Sharti ng_atm_output_p = ng_atm_output; 1399116808Sharti ng_atm_input_p = ng_atm_input; 1400116808Sharti ng_atm_input_orphan_p = ng_atm_input_orphans; 1401118175Sharti ng_atm_event_p = ng_atm_event; 1402116808Sharti 1403116808Sharti /* Create nodes for existing ATM interfaces */ 1404116808Sharti TAILQ_FOREACH(ifp, &ifnet, if_link) { 1405116808Sharti if (ifp->if_type == IFT_ATM) 1406116808Sharti ng_atm_attach(ifp); 1407116808Sharti } 1408116808Sharti IFNET_RUNLOCK(); 1409116808Sharti break; 1410116808Sharti 1411116808Sharti case MOD_UNLOAD: 1412116808Sharti IFNET_RLOCK(); 1413116808Sharti 1414116808Sharti ng_atm_attach_p = NULL; 1415116808Sharti ng_atm_detach_p = NULL; 1416116808Sharti ng_atm_output_p = NULL; 1417116808Sharti ng_atm_input_p = NULL; 1418116808Sharti ng_atm_input_orphan_p = NULL; 1419118175Sharti ng_atm_event_p = NULL; 1420116808Sharti 1421116808Sharti TAILQ_FOREACH(ifp, &ifnet, if_link) { 1422116808Sharti if (ifp->if_type == IFT_ATM) 1423116808Sharti ng_atm_detach(ifp); 1424116808Sharti } 1425116808Sharti IFNET_RUNLOCK(); 1426116808Sharti break; 1427116808Sharti 1428116808Sharti default: 1429116808Sharti error = EOPNOTSUPP; 1430116808Sharti break; 1431116808Sharti } 1432116808Sharti return (error); 1433116808Sharti} 1434