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