11991Sheppo /* 21991Sheppo * CDDL HEADER START 31991Sheppo * 41991Sheppo * The contents of this file are subject to the terms of the 51991Sheppo * Common Development and Distribution License (the "License"). 61991Sheppo * You may not use this file except in compliance with the License. 71991Sheppo * 81991Sheppo * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 91991Sheppo * or http://www.opensolaris.org/os/licensing. 101991Sheppo * See the License for the specific language governing permissions 111991Sheppo * and limitations under the License. 121991Sheppo * 131991Sheppo * When distributing Covered Code, include this CDDL HEADER in each 141991Sheppo * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 151991Sheppo * If applicable, add the following below this CDDL HEADER, with the 161991Sheppo * fields enclosed by brackets "[]" replaced with your own identifying 171991Sheppo * information: Portions Copyright [yyyy] [name of copyright owner] 181991Sheppo * 191991Sheppo * CDDL HEADER END 201991Sheppo */ 211991Sheppo 221991Sheppo /* 234647Sraghuram * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 241991Sheppo * Use is subject to license terms. 251991Sheppo */ 261991Sheppo 271991Sheppo #pragma ident "%Z%%M% %I% %E% SMI" 281991Sheppo 291991Sheppo #include <sys/types.h> 301991Sheppo #include <sys/errno.h> 311991Sheppo #include <sys/param.h> 321991Sheppo #include <sys/stream.h> 331991Sheppo #include <sys/kmem.h> 341991Sheppo #include <sys/conf.h> 351991Sheppo #include <sys/devops.h> 361991Sheppo #include <sys/ksynch.h> 371991Sheppo #include <sys/stat.h> 381991Sheppo #include <sys/modctl.h> 391991Sheppo #include <sys/debug.h> 401991Sheppo #include <sys/ethernet.h> 411991Sheppo #include <sys/dlpi.h> 421991Sheppo #include <net/if.h> 431991Sheppo #include <sys/mac.h> 442311Sseb #include <sys/mac_ether.h> 451991Sheppo #include <sys/ddi.h> 461991Sheppo #include <sys/sunddi.h> 471991Sheppo #include <sys/strsun.h> 481991Sheppo #include <sys/note.h> 491991Sheppo #include <sys/vnet.h> 501991Sheppo 511991Sheppo /* 521991Sheppo * Function prototypes. 531991Sheppo */ 541991Sheppo 551991Sheppo /* DDI entrypoints */ 561991Sheppo static int vnetdevinfo(dev_info_t *, ddi_info_cmd_t, void *, void **); 571991Sheppo static int vnetattach(dev_info_t *, ddi_attach_cmd_t); 581991Sheppo static int vnetdetach(dev_info_t *, ddi_detach_cmd_t); 591991Sheppo 601991Sheppo /* MAC entrypoints */ 612311Sseb static int vnet_m_stat(void *, uint_t, uint64_t *); 621991Sheppo static int vnet_m_start(void *); 631991Sheppo static void vnet_m_stop(void *); 641991Sheppo static int vnet_m_promisc(void *, boolean_t); 651991Sheppo static int vnet_m_multicst(void *, boolean_t, const uint8_t *); 661991Sheppo static int vnet_m_unicst(void *, const uint8_t *); 671991Sheppo mblk_t *vnet_m_tx(void *, mblk_t *); 681991Sheppo 691991Sheppo /* vnet internal functions */ 701991Sheppo static int vnet_mac_register(vnet_t *); 711991Sheppo static int vnet_read_mac_address(vnet_t *vnetp); 721991Sheppo static void vnet_add_vptl(vnet_t *vnetp, vp_tl_t *vp_tlp); 731991Sheppo static void vnet_del_vptl(vnet_t *vnetp, vp_tl_t *vp_tlp); 741991Sheppo static vp_tl_t *vnet_get_vptl(vnet_t *vnetp, const char *devname); 75*5641Swentaoy static void vnet_fdb_alloc(vnet_t *vnetp); 76*5641Swentaoy static void vnet_fdb_free(vnet_t *vnetp); 771991Sheppo static fdb_t *vnet_lookup_fdb(fdb_fanout_t *fdbhp, uint8_t *macaddr); 781991Sheppo 791991Sheppo /* exported functions */ 801991Sheppo void vnet_add_fdb(void *arg, uint8_t *macaddr, mac_tx_t m_tx, void *txarg); 811991Sheppo void vnet_del_fdb(void *arg, uint8_t *macaddr); 822793Slm66018 void vnet_modify_fdb(void *arg, uint8_t *macaddr, mac_tx_t m_tx, 832793Slm66018 void *txarg, boolean_t upgrade); 841991Sheppo void vnet_add_def_rte(void *arg, mac_tx_t m_tx, void *txarg); 851991Sheppo void vnet_del_def_rte(void *arg); 862311Sseb void vnet_rx(void *arg, mac_resource_handle_t mrh, mblk_t *mp); 872311Sseb void vnet_tx_update(void *arg); 881991Sheppo 891991Sheppo /* externs */ 902311Sseb extern int vgen_init(void *vnetp, dev_info_t *vnetdip, const uint8_t *macaddr, 912311Sseb mac_register_t **vgenmacp); 922336Snarayan extern int vgen_uninit(void *arg); 931991Sheppo 942311Sseb static mac_callbacks_t vnet_m_callbacks = { 952311Sseb 0, 962311Sseb vnet_m_stat, 972311Sseb vnet_m_start, 982311Sseb vnet_m_stop, 992311Sseb vnet_m_promisc, 1002311Sseb vnet_m_multicst, 1012311Sseb vnet_m_unicst, 1022311Sseb vnet_m_tx, 1032311Sseb NULL, 1042311Sseb NULL, 1052311Sseb NULL 1062311Sseb }; 1072311Sseb 1081991Sheppo /* 1091991Sheppo * Linked list of "vnet_t" structures - one per instance. 1101991Sheppo */ 1111991Sheppo static vnet_t *vnet_headp = NULL; 1121991Sheppo static krwlock_t vnet_rw; 1131991Sheppo 1141991Sheppo /* Tunables */ 1151991Sheppo uint32_t vnet_ntxds = VNET_NTXDS; /* power of 2 transmit descriptors */ 1161991Sheppo uint32_t vnet_ldcwd_interval = VNET_LDCWD_INTERVAL; /* watchdog freq in msec */ 1171991Sheppo uint32_t vnet_ldcwd_txtimeout = VNET_LDCWD_TXTIMEOUT; /* tx timeout in msec */ 1182410Slm66018 uint32_t vnet_ldc_mtu = VNET_LDC_MTU; /* ldc mtu */ 1191991Sheppo uint32_t vnet_nfdb_hash = VNET_NFDB_HASH; /* size of fdb hash table */ 1201991Sheppo 1211991Sheppo /* 1221991Sheppo * Property names 1231991Sheppo */ 1241991Sheppo static char macaddr_propname[] = "local-mac-address"; 1251991Sheppo 1261991Sheppo /* 1271991Sheppo * This is the string displayed by modinfo(1m). 1281991Sheppo */ 1292109Slm66018 static char vnet_ident[] = "vnet driver v%I%"; 1301991Sheppo extern struct mod_ops mod_driverops; 1311991Sheppo static struct cb_ops cb_vnetops = { 1321991Sheppo nulldev, /* cb_open */ 1331991Sheppo nulldev, /* cb_close */ 1341991Sheppo nodev, /* cb_strategy */ 1351991Sheppo nodev, /* cb_print */ 1361991Sheppo nodev, /* cb_dump */ 1371991Sheppo nodev, /* cb_read */ 1381991Sheppo nodev, /* cb_write */ 1391991Sheppo nodev, /* cb_ioctl */ 1401991Sheppo nodev, /* cb_devmap */ 1411991Sheppo nodev, /* cb_mmap */ 1421991Sheppo nodev, /* cb_segmap */ 1431991Sheppo nochpoll, /* cb_chpoll */ 1441991Sheppo ddi_prop_op, /* cb_prop_op */ 1451991Sheppo NULL, /* cb_stream */ 1461991Sheppo (int)(D_MP) /* cb_flag */ 1471991Sheppo }; 1481991Sheppo 1491991Sheppo static struct dev_ops vnetops = { 1501991Sheppo DEVO_REV, /* devo_rev */ 1511991Sheppo 0, /* devo_refcnt */ 1521991Sheppo NULL, /* devo_getinfo */ 1531991Sheppo nulldev, /* devo_identify */ 1541991Sheppo nulldev, /* devo_probe */ 1551991Sheppo vnetattach, /* devo_attach */ 1561991Sheppo vnetdetach, /* devo_detach */ 1571991Sheppo nodev, /* devo_reset */ 1581991Sheppo &cb_vnetops, /* devo_cb_ops */ 1591991Sheppo (struct bus_ops *)NULL /* devo_bus_ops */ 1601991Sheppo }; 1611991Sheppo 1621991Sheppo static struct modldrv modldrv = { 1631991Sheppo &mod_driverops, /* Type of module. This one is a driver */ 1641991Sheppo vnet_ident, /* ID string */ 1651991Sheppo &vnetops /* driver specific ops */ 1661991Sheppo }; 1671991Sheppo 1681991Sheppo static struct modlinkage modlinkage = { 1691991Sheppo MODREV_1, (void *)&modldrv, NULL 1701991Sheppo }; 1711991Sheppo 1724647Sraghuram #ifdef DEBUG 1731991Sheppo 1741991Sheppo /* 1751991Sheppo * Print debug messages - set to 0xf to enable all msgs 1761991Sheppo */ 1774647Sraghuram int vnet_dbglevel = 0x8; 1781991Sheppo 1794647Sraghuram static void 1804647Sraghuram debug_printf(const char *fname, void *arg, const char *fmt, ...) 1811991Sheppo { 1821991Sheppo char buf[512]; 1831991Sheppo va_list ap; 1841991Sheppo vnet_t *vnetp = (vnet_t *)arg; 1854647Sraghuram char *bufp = buf; 1861991Sheppo 1874647Sraghuram if (vnetp == NULL) { 1884647Sraghuram (void) sprintf(bufp, "%s: ", fname); 1894647Sraghuram bufp += strlen(bufp); 1904647Sraghuram } else { 1914647Sraghuram (void) sprintf(bufp, "vnet%d:%s: ", vnetp->instance, fname); 1924647Sraghuram bufp += strlen(bufp); 1934647Sraghuram } 1944647Sraghuram va_start(ap, fmt); 1954647Sraghuram (void) vsprintf(bufp, fmt, ap); 1964647Sraghuram va_end(ap); 1974647Sraghuram cmn_err(CE_CONT, "%s\n", buf); 1984647Sraghuram } 1991991Sheppo 2001991Sheppo #endif 2011991Sheppo 2021991Sheppo /* _init(9E): initialize the loadable module */ 2031991Sheppo int 2041991Sheppo _init(void) 2051991Sheppo { 2061991Sheppo int status; 2071991Sheppo 2084647Sraghuram DBG1(NULL, "enter\n"); 2091991Sheppo 2101991Sheppo mac_init_ops(&vnetops, "vnet"); 2111991Sheppo status = mod_install(&modlinkage); 2121991Sheppo if (status != 0) { 2131991Sheppo mac_fini_ops(&vnetops); 2141991Sheppo } 2151991Sheppo 2164647Sraghuram DBG1(NULL, "exit(%d)\n", status); 2171991Sheppo return (status); 2181991Sheppo } 2191991Sheppo 2201991Sheppo /* _fini(9E): prepare the module for unloading. */ 2211991Sheppo int 2221991Sheppo _fini(void) 2231991Sheppo { 2241991Sheppo int status; 2251991Sheppo 2264647Sraghuram DBG1(NULL, "enter\n"); 2271991Sheppo 2281991Sheppo status = mod_remove(&modlinkage); 2291991Sheppo if (status != 0) 2301991Sheppo return (status); 2311991Sheppo mac_fini_ops(&vnetops); 2321991Sheppo 2334647Sraghuram DBG1(NULL, "exit(%d)\n", status); 2341991Sheppo return (status); 2351991Sheppo } 2361991Sheppo 2371991Sheppo /* _info(9E): return information about the loadable module */ 2381991Sheppo int 2391991Sheppo _info(struct modinfo *modinfop) 2401991Sheppo { 2411991Sheppo return (mod_info(&modlinkage, modinfop)); 2421991Sheppo } 2431991Sheppo 2441991Sheppo /* 2451991Sheppo * attach(9E): attach a device to the system. 2461991Sheppo * called once for each instance of the device on the system. 2471991Sheppo */ 2481991Sheppo static int 2491991Sheppo vnetattach(dev_info_t *dip, ddi_attach_cmd_t cmd) 2501991Sheppo { 2511991Sheppo vnet_t *vnetp; 2521991Sheppo vp_tl_t *vp_tlp; 2531991Sheppo int instance; 2541991Sheppo int status; 2552311Sseb mac_register_t *vgenmacp = NULL; 2564647Sraghuram enum { AST_init = 0x0, AST_vnet_alloc = 0x1, 2574647Sraghuram AST_mac_alloc = 0x2, AST_read_macaddr = 0x4, 2584647Sraghuram AST_vgen_init = 0x8, AST_vptl_alloc = 0x10, 2594647Sraghuram AST_fdbh_alloc = 0x20 } attach_state; 2601991Sheppo 2611991Sheppo attach_state = AST_init; 2621991Sheppo 2631991Sheppo switch (cmd) { 2641991Sheppo case DDI_ATTACH: 2651991Sheppo break; 2661991Sheppo case DDI_RESUME: 2671991Sheppo case DDI_PM_RESUME: 2681991Sheppo default: 2691991Sheppo goto vnet_attach_fail; 2701991Sheppo } 2711991Sheppo 2721991Sheppo instance = ddi_get_instance(dip); 2734647Sraghuram DBG1(NULL, "instance(%d) enter\n", instance); 2741991Sheppo 2751991Sheppo /* allocate vnet_t and mac_t structures */ 2761991Sheppo vnetp = kmem_zalloc(sizeof (vnet_t), KM_SLEEP); 2771991Sheppo attach_state |= AST_vnet_alloc; 2781991Sheppo 2791991Sheppo /* setup links to vnet_t from both devinfo and mac_t */ 2801991Sheppo ddi_set_driver_private(dip, (caddr_t)vnetp); 2811991Sheppo vnetp->dip = dip; 2821991Sheppo vnetp->instance = instance; 2831991Sheppo 2841991Sheppo /* read the mac address */ 2851991Sheppo status = vnet_read_mac_address(vnetp); 2861991Sheppo if (status != DDI_SUCCESS) { 2871991Sheppo goto vnet_attach_fail; 2881991Sheppo } 2891991Sheppo attach_state |= AST_read_macaddr; 2901991Sheppo 2911991Sheppo /* 2921991Sheppo * Initialize the generic vnet proxy transport. This is the first 2931991Sheppo * and default transport used by vnet. The generic transport 2941991Sheppo * is provided by using sun4v LDC (logical domain channel). On success, 2951991Sheppo * vgen_init() provides a pointer to mac_t of generic transport. 2961991Sheppo * Currently, this generic layer provides network connectivity to other 2971991Sheppo * vnets within ldoms and also to remote hosts oustide ldoms through 2981991Sheppo * the virtual switch (vsw) device on domain0. In the future, when 2991991Sheppo * physical adapters that are able to share their resources (such as 3001991Sheppo * dma channels) with guest domains become available, the vnet device 3011991Sheppo * will use hardware specific driver to communicate directly over the 3021991Sheppo * physical device to reach remote hosts without going through vswitch. 3031991Sheppo */ 3042311Sseb status = vgen_init(vnetp, vnetp->dip, (uint8_t *)vnetp->curr_macaddr, 3052311Sseb &vgenmacp); 3061991Sheppo if (status != DDI_SUCCESS) { 3074647Sraghuram DERR(vnetp, "vgen_init() failed\n"); 3081991Sheppo goto vnet_attach_fail; 3091991Sheppo } 310*5641Swentaoy rw_init(&vnetp->trwlock, NULL, RW_DRIVER, NULL); 3111991Sheppo attach_state |= AST_vgen_init; 3121991Sheppo 3131991Sheppo vp_tlp = kmem_zalloc(sizeof (vp_tl_t), KM_SLEEP); 3141991Sheppo vp_tlp->macp = vgenmacp; 3151991Sheppo (void) snprintf(vp_tlp->name, MAXNAMELEN, "%s%u", "vgen", instance); 3161991Sheppo (void) strcpy(vnetp->vgen_name, vp_tlp->name); 3171991Sheppo 3181991Sheppo /* add generic transport to the list of vnet proxy transports */ 3191991Sheppo vnet_add_vptl(vnetp, vp_tlp); 3201991Sheppo attach_state |= AST_vptl_alloc; 3211991Sheppo 322*5641Swentaoy vnet_fdb_alloc(vnetp); 3231991Sheppo attach_state |= AST_fdbh_alloc; 3241991Sheppo 3251991Sheppo /* register with MAC layer */ 3261991Sheppo status = vnet_mac_register(vnetp); 3271991Sheppo if (status != DDI_SUCCESS) { 3281991Sheppo goto vnet_attach_fail; 3291991Sheppo } 3301991Sheppo 3311991Sheppo /* add to the list of vnet devices */ 3321991Sheppo WRITE_ENTER(&vnet_rw); 3331991Sheppo vnetp->nextp = vnet_headp; 3341991Sheppo vnet_headp = vnetp; 3351991Sheppo RW_EXIT(&vnet_rw); 3361991Sheppo 3374647Sraghuram DBG1(NULL, "instance(%d) exit\n", instance); 3381991Sheppo return (DDI_SUCCESS); 3391991Sheppo 3401991Sheppo vnet_attach_fail: 3411991Sheppo if (attach_state & AST_fdbh_alloc) { 342*5641Swentaoy vnet_fdb_free(vnetp); 3431991Sheppo } 3441991Sheppo if (attach_state & AST_vptl_alloc) { 3451991Sheppo WRITE_ENTER(&vnetp->trwlock); 3461991Sheppo vnet_del_vptl(vnetp, vp_tlp); 3471991Sheppo RW_EXIT(&vnetp->trwlock); 3481991Sheppo } 3491991Sheppo if (attach_state & AST_vgen_init) { 3502336Snarayan (void) vgen_uninit(vgenmacp->m_driver); 351*5641Swentaoy rw_destroy(&vnetp->trwlock); 3521991Sheppo } 3531991Sheppo if (attach_state & AST_vnet_alloc) { 3541991Sheppo KMEM_FREE(vnetp); 3551991Sheppo } 3561991Sheppo return (DDI_FAILURE); 3571991Sheppo } 3581991Sheppo 3591991Sheppo /* 3601991Sheppo * detach(9E): detach a device from the system. 3611991Sheppo */ 3621991Sheppo static int 3631991Sheppo vnetdetach(dev_info_t *dip, ddi_detach_cmd_t cmd) 3641991Sheppo { 3651991Sheppo vnet_t *vnetp; 3661991Sheppo vnet_t **vnetpp; 3671991Sheppo vp_tl_t *vp_tlp; 3681991Sheppo int instance; 3692336Snarayan int rv; 3701991Sheppo 3711991Sheppo instance = ddi_get_instance(dip); 3724647Sraghuram DBG1(NULL, "instance(%d) enter\n", instance); 3731991Sheppo 3741991Sheppo vnetp = ddi_get_driver_private(dip); 3751991Sheppo if (vnetp == NULL) { 3761991Sheppo goto vnet_detach_fail; 3771991Sheppo } 3781991Sheppo 3791991Sheppo switch (cmd) { 3801991Sheppo case DDI_DETACH: 3811991Sheppo break; 3821991Sheppo case DDI_SUSPEND: 3831991Sheppo case DDI_PM_SUSPEND: 3841991Sheppo default: 3851991Sheppo goto vnet_detach_fail; 3861991Sheppo } 3871991Sheppo 3882336Snarayan /* uninit and free vnet proxy transports */ 3892336Snarayan WRITE_ENTER(&vnetp->trwlock); 3902336Snarayan while ((vp_tlp = vnetp->tlp) != NULL) { 3912336Snarayan if (strcmp(vnetp->vgen_name, vp_tlp->name) == 0) { 3922336Snarayan /* uninitialize generic transport */ 3932336Snarayan rv = vgen_uninit(vp_tlp->macp->m_driver); 3942336Snarayan if (rv != DDI_SUCCESS) { 3952336Snarayan RW_EXIT(&vnetp->trwlock); 3962336Snarayan goto vnet_detach_fail; 3972336Snarayan } 3982336Snarayan } 3992336Snarayan vnet_del_vptl(vnetp, vp_tlp); 4002336Snarayan } 4012336Snarayan RW_EXIT(&vnetp->trwlock); 4022336Snarayan 4031991Sheppo /* 4041991Sheppo * Unregister from the MAC subsystem. This can fail, in 4051991Sheppo * particular if there are DLPI style-2 streams still open - 4061991Sheppo * in which case we just return failure. 4071991Sheppo */ 4082311Sseb if (mac_unregister(vnetp->mh) != 0) 4091991Sheppo goto vnet_detach_fail; 4101991Sheppo 4111991Sheppo /* unlink from instance(vnet_t) list */ 4121991Sheppo WRITE_ENTER(&vnet_rw); 4131991Sheppo for (vnetpp = &vnet_headp; *vnetpp; vnetpp = &(*vnetpp)->nextp) { 4141991Sheppo if (*vnetpp == vnetp) { 4151991Sheppo *vnetpp = vnetp->nextp; 4161991Sheppo break; 4171991Sheppo } 4181991Sheppo } 4191991Sheppo RW_EXIT(&vnet_rw); 4201991Sheppo 421*5641Swentaoy vnet_fdb_free(vnetp); 4223297Ssb155480 423*5641Swentaoy rw_destroy(&vnetp->trwlock); 4241991Sheppo KMEM_FREE(vnetp); 4251991Sheppo 4261991Sheppo return (DDI_SUCCESS); 4271991Sheppo 4281991Sheppo vnet_detach_fail: 4291991Sheppo return (DDI_FAILURE); 4301991Sheppo } 4311991Sheppo 4321991Sheppo /* enable the device for transmit/receive */ 4331991Sheppo static int 4341991Sheppo vnet_m_start(void *arg) 4351991Sheppo { 4361991Sheppo vnet_t *vnetp = arg; 4371991Sheppo vp_tl_t *vp_tlp; 4382311Sseb mac_register_t *vp_macp; 4392311Sseb mac_callbacks_t *cbp; 4401991Sheppo 4414647Sraghuram DBG1(vnetp, "enter\n"); 4421991Sheppo 4431991Sheppo /* 4442793Slm66018 * NOTE: 4451991Sheppo * Currently, we only have generic transport. m_start() invokes 4461991Sheppo * vgen_start() which enables ports/channels in vgen and 4471991Sheppo * initiates handshake with peer vnets and vsw. In the future when we 4481991Sheppo * have support for hardware specific transports, this information 4491991Sheppo * needs to be propagted back to vnet from vgen and we need to revisit 4501991Sheppo * this code (see comments in vnet_attach()). 4511991Sheppo * 4521991Sheppo */ 4531991Sheppo WRITE_ENTER(&vnetp->trwlock); 4541991Sheppo for (vp_tlp = vnetp->tlp; vp_tlp != NULL; vp_tlp = vp_tlp->nextp) { 4551991Sheppo vp_macp = vp_tlp->macp; 4562311Sseb cbp = vp_macp->m_callbacks; 4572311Sseb cbp->mc_start(vp_macp->m_driver); 4581991Sheppo } 4591991Sheppo RW_EXIT(&vnetp->trwlock); 4601991Sheppo 4614647Sraghuram DBG1(vnetp, "exit\n"); 4621991Sheppo return (VNET_SUCCESS); 4631991Sheppo 4641991Sheppo } 4651991Sheppo 4661991Sheppo /* stop transmit/receive for the device */ 4671991Sheppo static void 4681991Sheppo vnet_m_stop(void *arg) 4691991Sheppo { 4701991Sheppo vnet_t *vnetp = arg; 4711991Sheppo vp_tl_t *vp_tlp; 4722311Sseb mac_register_t *vp_macp; 4732311Sseb mac_callbacks_t *cbp; 4741991Sheppo 4754647Sraghuram DBG1(vnetp, "enter\n"); 4761991Sheppo 4771991Sheppo WRITE_ENTER(&vnetp->trwlock); 4781991Sheppo for (vp_tlp = vnetp->tlp; vp_tlp != NULL; vp_tlp = vp_tlp->nextp) { 4791991Sheppo vp_macp = vp_tlp->macp; 4802311Sseb cbp = vp_macp->m_callbacks; 4812311Sseb cbp->mc_stop(vp_macp->m_driver); 4821991Sheppo } 4831991Sheppo RW_EXIT(&vnetp->trwlock); 4841991Sheppo 4854647Sraghuram DBG1(vnetp, "exit\n"); 4861991Sheppo } 4871991Sheppo 4881991Sheppo /* set the unicast mac address of the device */ 4891991Sheppo static int 4901991Sheppo vnet_m_unicst(void *arg, const uint8_t *macaddr) 4911991Sheppo { 4921991Sheppo _NOTE(ARGUNUSED(macaddr)) 4931991Sheppo 4941991Sheppo vnet_t *vnetp = arg; 4951991Sheppo 4964647Sraghuram DBG1(vnetp, "enter\n"); 4971991Sheppo /* 4982793Slm66018 * NOTE: setting mac address dynamically is not supported. 4991991Sheppo */ 5004647Sraghuram DBG1(vnetp, "exit\n"); 5011991Sheppo 5022109Slm66018 return (VNET_FAILURE); 5031991Sheppo } 5041991Sheppo 5051991Sheppo /* enable/disable a multicast address */ 5061991Sheppo static int 5071991Sheppo vnet_m_multicst(void *arg, boolean_t add, const uint8_t *mca) 5081991Sheppo { 5091991Sheppo _NOTE(ARGUNUSED(add, mca)) 5101991Sheppo 5111991Sheppo vnet_t *vnetp = arg; 5121991Sheppo vp_tl_t *vp_tlp; 5132311Sseb mac_register_t *vp_macp; 5142311Sseb mac_callbacks_t *cbp; 5151991Sheppo int rv = VNET_SUCCESS; 5161991Sheppo 5174647Sraghuram DBG1(vnetp, "enter\n"); 5181991Sheppo READ_ENTER(&vnetp->trwlock); 5191991Sheppo for (vp_tlp = vnetp->tlp; vp_tlp != NULL; vp_tlp = vp_tlp->nextp) { 5201991Sheppo if (strcmp(vnetp->vgen_name, vp_tlp->name) == 0) { 5211991Sheppo vp_macp = vp_tlp->macp; 5222311Sseb cbp = vp_macp->m_callbacks; 5232311Sseb rv = cbp->mc_multicst(vp_macp->m_driver, add, mca); 5241991Sheppo break; 5251991Sheppo } 5261991Sheppo } 5271991Sheppo RW_EXIT(&vnetp->trwlock); 5284647Sraghuram DBG1(vnetp, "exit(%d)\n", rv); 5291991Sheppo return (rv); 5301991Sheppo } 5311991Sheppo 5321991Sheppo /* set or clear promiscuous mode on the device */ 5331991Sheppo static int 5341991Sheppo vnet_m_promisc(void *arg, boolean_t on) 5351991Sheppo { 5361991Sheppo _NOTE(ARGUNUSED(on)) 5371991Sheppo 5381991Sheppo vnet_t *vnetp = arg; 5394647Sraghuram DBG1(vnetp, "enter\n"); 5401991Sheppo /* 5412793Slm66018 * NOTE: setting promiscuous mode is not supported, just return success. 5421991Sheppo */ 5434647Sraghuram DBG1(vnetp, "exit\n"); 5441991Sheppo return (VNET_SUCCESS); 5451991Sheppo } 5461991Sheppo 5471991Sheppo /* 5481991Sheppo * Transmit a chain of packets. This function provides switching functionality 5491991Sheppo * based on the destination mac address to reach other guests (within ldoms) or 5501991Sheppo * external hosts. 5511991Sheppo */ 5521991Sheppo mblk_t * 5531991Sheppo vnet_m_tx(void *arg, mblk_t *mp) 5541991Sheppo { 5551991Sheppo vnet_t *vnetp; 5561991Sheppo mblk_t *next; 5571991Sheppo uint32_t fdbhash; 5581991Sheppo fdb_t *fdbp; 5591991Sheppo fdb_fanout_t *fdbhp; 5601991Sheppo struct ether_header *ehp; 5611991Sheppo uint8_t *macaddr; 5621991Sheppo mblk_t *resid_mp; 5631991Sheppo 5641991Sheppo vnetp = (vnet_t *)arg; 5654647Sraghuram DBG1(vnetp, "enter\n"); 5661991Sheppo ASSERT(mp != NULL); 5671991Sheppo 5681991Sheppo while (mp != NULL) { 5691991Sheppo next = mp->b_next; 5701991Sheppo mp->b_next = NULL; 5711991Sheppo 5721991Sheppo /* get the destination mac address in the eth header */ 5731991Sheppo ehp = (struct ether_header *)mp->b_rptr; 5741991Sheppo macaddr = (uint8_t *)&ehp->ether_dhost; 5751991Sheppo 5761991Sheppo /* Calculate hash value and fdb fanout */ 5771991Sheppo fdbhash = MACHASH(macaddr, vnetp->nfdb_hash); 5781991Sheppo fdbhp = &(vnetp->fdbhp[fdbhash]); 5791991Sheppo 5801991Sheppo READ_ENTER(&fdbhp->rwlock); 5811991Sheppo fdbp = vnet_lookup_fdb(fdbhp, macaddr); 5821991Sheppo if (fdbp) { 5831991Sheppo /* 5841991Sheppo * If the destination is in FDB, the destination is 5851991Sheppo * a vnet device within ldoms and directly reachable, 5861991Sheppo * invoke the tx function in the fdb entry. 5871991Sheppo */ 5881991Sheppo resid_mp = fdbp->m_tx(fdbp->txarg, mp); 5891991Sheppo if (resid_mp != NULL) { 5901991Sheppo /* m_tx failed */ 5911991Sheppo mp->b_next = next; 5921991Sheppo RW_EXIT(&fdbhp->rwlock); 5931991Sheppo break; 5941991Sheppo } 5951991Sheppo RW_EXIT(&fdbhp->rwlock); 5961991Sheppo } else { 5971991Sheppo /* destination is not in FDB */ 5981991Sheppo RW_EXIT(&fdbhp->rwlock); 5991991Sheppo /* 6001991Sheppo * If the destination is broadcast/multicast 6011991Sheppo * or an unknown unicast address, forward the 6021991Sheppo * packet to vsw, using the last slot in fdb which is 6031991Sheppo * reserved for default route. 6041991Sheppo */ 6051991Sheppo fdbhp = &(vnetp->fdbhp[vnetp->nfdb_hash]); 6061991Sheppo READ_ENTER(&fdbhp->rwlock); 6071991Sheppo fdbp = fdbhp->headp; 6081991Sheppo if (fdbp) { 6091991Sheppo resid_mp = fdbp->m_tx(fdbp->txarg, mp); 6101991Sheppo if (resid_mp != NULL) { 6111991Sheppo /* m_tx failed */ 6121991Sheppo mp->b_next = next; 6131991Sheppo RW_EXIT(&fdbhp->rwlock); 6141991Sheppo break; 6151991Sheppo } 6161991Sheppo } else { 6171991Sheppo /* drop the packet */ 6181991Sheppo freemsg(mp); 6191991Sheppo } 6201991Sheppo RW_EXIT(&fdbhp->rwlock); 6211991Sheppo } 6221991Sheppo 6231991Sheppo mp = next; 6241991Sheppo } 6251991Sheppo 6264647Sraghuram DBG1(vnetp, "exit\n"); 6271991Sheppo return (mp); 6281991Sheppo } 6291991Sheppo 6302311Sseb /* get statistics from the device */ 6312311Sseb int 6322311Sseb vnet_m_stat(void *arg, uint_t stat, uint64_t *val) 6331991Sheppo { 6341991Sheppo vnet_t *vnetp = arg; 6351991Sheppo vp_tl_t *vp_tlp; 6362311Sseb mac_register_t *vp_macp; 6372311Sseb mac_callbacks_t *cbp; 6382311Sseb uint64_t val_total = 0; 6391991Sheppo 6404647Sraghuram DBG1(vnetp, "enter\n"); 6411991Sheppo 6421991Sheppo /* 6432311Sseb * get the specified statistic from each transport and return the 6442311Sseb * aggregate val. This obviously only works for counters. 6451991Sheppo */ 6462311Sseb if ((IS_MAC_STAT(stat) && !MAC_STAT_ISACOUNTER(stat)) || 6472311Sseb (IS_MACTYPE_STAT(stat) && !ETHER_STAT_ISACOUNTER(stat))) { 6482311Sseb return (ENOTSUP); 6492311Sseb } 6501991Sheppo READ_ENTER(&vnetp->trwlock); 6511991Sheppo for (vp_tlp = vnetp->tlp; vp_tlp != NULL; vp_tlp = vp_tlp->nextp) { 6521991Sheppo vp_macp = vp_tlp->macp; 6532311Sseb cbp = vp_macp->m_callbacks; 6542311Sseb if (cbp->mc_getstat(vp_macp->m_driver, stat, val) == 0) 6552311Sseb val_total += *val; 6561991Sheppo } 6571991Sheppo RW_EXIT(&vnetp->trwlock); 6581991Sheppo 6592311Sseb *val = val_total; 6602311Sseb 6614647Sraghuram DBG1(vnetp, "exit\n"); 6622311Sseb return (0); 6631991Sheppo } 6641991Sheppo 6651991Sheppo /* wrapper function for mac_register() */ 6661991Sheppo static int 6671991Sheppo vnet_mac_register(vnet_t *vnetp) 6681991Sheppo { 6692311Sseb mac_register_t *macp; 6702311Sseb int err; 6711991Sheppo 6722311Sseb if ((macp = mac_alloc(MAC_VERSION)) == NULL) 6732311Sseb return (DDI_FAILURE); 6742311Sseb macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER; 6752311Sseb macp->m_driver = vnetp; 6761991Sheppo macp->m_dip = vnetp->dip; 6772311Sseb macp->m_src_addr = vnetp->curr_macaddr; 6782311Sseb macp->m_callbacks = &vnet_m_callbacks; 6792311Sseb macp->m_min_sdu = 0; 6802311Sseb macp->m_max_sdu = ETHERMTU; 6811991Sheppo 6821991Sheppo /* 6831991Sheppo * Finally, we're ready to register ourselves with the MAC layer 6841991Sheppo * interface; if this succeeds, we're all ready to start() 6851991Sheppo */ 6862311Sseb err = mac_register(macp, &vnetp->mh); 6872311Sseb mac_free(macp); 6882311Sseb return (err == 0 ? DDI_SUCCESS : DDI_FAILURE); 6891991Sheppo } 6901991Sheppo 6911991Sheppo /* add vp_tl to the list */ 6921991Sheppo static void 6931991Sheppo vnet_add_vptl(vnet_t *vnetp, vp_tl_t *vp_tlp) 6941991Sheppo { 6951991Sheppo vp_tl_t *ttlp; 6961991Sheppo 6971991Sheppo WRITE_ENTER(&vnetp->trwlock); 6981991Sheppo if (vnetp->tlp == NULL) { 6991991Sheppo vnetp->tlp = vp_tlp; 7001991Sheppo } else { 7011991Sheppo ttlp = vnetp->tlp; 7021991Sheppo while (ttlp->nextp) 7031991Sheppo ttlp = ttlp->nextp; 7041991Sheppo ttlp->nextp = vp_tlp; 7051991Sheppo } 7061991Sheppo RW_EXIT(&vnetp->trwlock); 7071991Sheppo } 7081991Sheppo 7091991Sheppo /* remove vp_tl from the list */ 7101991Sheppo static void 7111991Sheppo vnet_del_vptl(vnet_t *vnetp, vp_tl_t *vp_tlp) 7121991Sheppo { 7131991Sheppo vp_tl_t *ttlp, **pretlp; 7141991Sheppo boolean_t found = B_FALSE; 7151991Sheppo 7161991Sheppo pretlp = &vnetp->tlp; 7171991Sheppo ttlp = *pretlp; 7181991Sheppo while (ttlp) { 7191991Sheppo if (ttlp == vp_tlp) { 7201991Sheppo found = B_TRUE; 7211991Sheppo (*pretlp) = ttlp->nextp; 7221991Sheppo ttlp->nextp = NULL; 7231991Sheppo break; 7241991Sheppo } 7251991Sheppo pretlp = &(ttlp->nextp); 7261991Sheppo ttlp = *pretlp; 7271991Sheppo } 7281991Sheppo 7291991Sheppo if (found) { 7301991Sheppo KMEM_FREE(vp_tlp); 7311991Sheppo } 7321991Sheppo } 7331991Sheppo 7341991Sheppo /* get vp_tl corresponding to the given name */ 7351991Sheppo static vp_tl_t * 7361991Sheppo vnet_get_vptl(vnet_t *vnetp, const char *name) 7371991Sheppo { 7381991Sheppo vp_tl_t *tlp; 7391991Sheppo 7401991Sheppo tlp = vnetp->tlp; 7411991Sheppo while (tlp) { 7421991Sheppo if (strcmp(tlp->name, name) == 0) { 7431991Sheppo return (tlp); 7441991Sheppo } 7451991Sheppo tlp = tlp->nextp; 7461991Sheppo } 7474647Sraghuram DWARN(vnetp, "can't find vp_tl with name (%s)\n", name); 7481991Sheppo return (NULL); 7491991Sheppo } 7501991Sheppo 7511991Sheppo /* read the mac address of the device */ 7521991Sheppo static int 7531991Sheppo vnet_read_mac_address(vnet_t *vnetp) 7541991Sheppo { 7551991Sheppo uchar_t *macaddr; 7561991Sheppo uint32_t size; 7571991Sheppo int rv; 7581991Sheppo 7591991Sheppo rv = ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, vnetp->dip, 7604650Sraghuram DDI_PROP_DONTPASS, macaddr_propname, &macaddr, &size); 7611991Sheppo if ((rv != DDI_PROP_SUCCESS) || (size != ETHERADDRL)) { 7624647Sraghuram DWARN(vnetp, "prop_lookup failed(%s) err(%d)\n", 7634647Sraghuram macaddr_propname, rv); 7641991Sheppo return (DDI_FAILURE); 7651991Sheppo } 7661991Sheppo bcopy(macaddr, (caddr_t)vnetp->vendor_addr, ETHERADDRL); 7671991Sheppo bcopy(macaddr, (caddr_t)vnetp->curr_macaddr, ETHERADDRL); 7681991Sheppo ddi_prop_free(macaddr); 7691991Sheppo 7701991Sheppo return (DDI_SUCCESS); 7711991Sheppo } 7721991Sheppo 7731991Sheppo 7741991Sheppo /* 7751991Sheppo * Functions below are called only by generic transport to add/remove/modify 7761991Sheppo * entries in forwarding database. See comments in vgen_port_init(vnet_gen.c). 7771991Sheppo */ 7781991Sheppo 7791991Sheppo /* add an entry into the forwarding database */ 7801991Sheppo void 7811991Sheppo vnet_add_fdb(void *arg, uint8_t *macaddr, mac_tx_t m_tx, void *txarg) 7821991Sheppo { 7831991Sheppo vnet_t *vnetp = (vnet_t *)arg; 7841991Sheppo uint32_t fdbhash; 7851991Sheppo fdb_t *fdbp; 7861991Sheppo fdb_fanout_t *fdbhp; 7871991Sheppo 7881991Sheppo /* Calculate hash value and fdb fanout */ 7891991Sheppo fdbhash = MACHASH(macaddr, vnetp->nfdb_hash); 7901991Sheppo fdbhp = &(vnetp->fdbhp[fdbhash]); 7911991Sheppo 7921991Sheppo WRITE_ENTER(&fdbhp->rwlock); 7931991Sheppo 7941991Sheppo fdbp = kmem_zalloc(sizeof (fdb_t), KM_NOSLEEP); 7951991Sheppo if (fdbp == NULL) { 7961991Sheppo RW_EXIT(&fdbhp->rwlock); 7971991Sheppo return; 7981991Sheppo } 7991991Sheppo bcopy(macaddr, (caddr_t)fdbp->macaddr, ETHERADDRL); 8001991Sheppo fdbp->m_tx = m_tx; 8011991Sheppo fdbp->txarg = txarg; 8021991Sheppo fdbp->nextp = fdbhp->headp; 8031991Sheppo fdbhp->headp = fdbp; 8041991Sheppo 8051991Sheppo RW_EXIT(&fdbhp->rwlock); 8061991Sheppo } 8071991Sheppo 8081991Sheppo /* delete an entry from the forwarding database */ 8091991Sheppo void 8101991Sheppo vnet_del_fdb(void *arg, uint8_t *macaddr) 8111991Sheppo { 8121991Sheppo vnet_t *vnetp = (vnet_t *)arg; 8131991Sheppo uint32_t fdbhash; 8141991Sheppo fdb_t *fdbp; 8151991Sheppo fdb_t **pfdbp; 8161991Sheppo fdb_fanout_t *fdbhp; 8171991Sheppo 8181991Sheppo /* Calculate hash value and fdb fanout */ 8191991Sheppo fdbhash = MACHASH(macaddr, vnetp->nfdb_hash); 8201991Sheppo fdbhp = &(vnetp->fdbhp[fdbhash]); 8211991Sheppo 8221991Sheppo WRITE_ENTER(&fdbhp->rwlock); 8231991Sheppo 8241991Sheppo for (pfdbp = &fdbhp->headp; (fdbp = *pfdbp) != NULL; 8251991Sheppo pfdbp = &fdbp->nextp) { 8261991Sheppo if (bcmp(fdbp->macaddr, macaddr, ETHERADDRL) == 0) { 8271991Sheppo /* Unlink it from the list */ 8281991Sheppo *pfdbp = fdbp->nextp; 8291991Sheppo KMEM_FREE(fdbp); 8301991Sheppo break; 8311991Sheppo } 8321991Sheppo } 8331991Sheppo 8341991Sheppo RW_EXIT(&fdbhp->rwlock); 8351991Sheppo } 8361991Sheppo 8371991Sheppo /* modify an existing entry in the forwarding database */ 8381991Sheppo void 8392793Slm66018 vnet_modify_fdb(void *arg, uint8_t *macaddr, mac_tx_t m_tx, void *txarg, 8402793Slm66018 boolean_t upgrade) 8411991Sheppo { 8421991Sheppo vnet_t *vnetp = (vnet_t *)arg; 8431991Sheppo uint32_t fdbhash; 8441991Sheppo fdb_t *fdbp; 8451991Sheppo fdb_fanout_t *fdbhp; 8461991Sheppo 8471991Sheppo /* Calculate hash value and fdb fanout */ 8481991Sheppo fdbhash = MACHASH(macaddr, vnetp->nfdb_hash); 8491991Sheppo fdbhp = &(vnetp->fdbhp[fdbhash]); 8501991Sheppo 8512793Slm66018 if (upgrade == B_TRUE) { 8522793Slm66018 /* 8532793Slm66018 * Caller already holds the lock as a reader. This can 8542793Slm66018 * occur if this function is invoked in the context 8552793Slm66018 * of transmit routine - vnet_m_tx(), where the lock 8562793Slm66018 * is held as a reader before calling the transmit 8572793Slm66018 * function of an fdb entry (fdbp->m_tx). 8582793Slm66018 * See comments in vgen_ldcsend() in vnet_gen.c 8592793Slm66018 */ 8602793Slm66018 if (!rw_tryupgrade(&fdbhp->rwlock)) { 8612793Slm66018 RW_EXIT(&fdbhp->rwlock); 8622793Slm66018 WRITE_ENTER(&fdbhp->rwlock); 8632793Slm66018 } 8642793Slm66018 } else { 8652793Slm66018 /* Caller does not hold the lock */ 8662793Slm66018 WRITE_ENTER(&fdbhp->rwlock); 8672793Slm66018 } 8681991Sheppo 8691991Sheppo for (fdbp = fdbhp->headp; fdbp != NULL; fdbp = fdbp->nextp) { 8701991Sheppo if (bcmp(fdbp->macaddr, macaddr, ETHERADDRL) == 0) { 8711991Sheppo /* change the entry to have new tx params */ 8721991Sheppo fdbp->m_tx = m_tx; 8731991Sheppo fdbp->txarg = txarg; 8741991Sheppo break; 8751991Sheppo } 8761991Sheppo } 8771991Sheppo 8782793Slm66018 if (upgrade == B_TRUE) { 8792793Slm66018 /* restore the caller as a reader */ 8802793Slm66018 rw_downgrade(&fdbhp->rwlock); 8812793Slm66018 } else { 8822793Slm66018 RW_EXIT(&fdbhp->rwlock); 8832793Slm66018 } 8841991Sheppo } 8851991Sheppo 886*5641Swentaoy /* allocate the forwarding database */ 887*5641Swentaoy static void 888*5641Swentaoy vnet_fdb_alloc(vnet_t *vnetp) 889*5641Swentaoy { 890*5641Swentaoy int i; 891*5641Swentaoy uint32_t nfdbh = 0; 892*5641Swentaoy 893*5641Swentaoy nfdbh = vnet_nfdb_hash; 894*5641Swentaoy if ((nfdbh < VNET_NFDB_HASH) || (nfdbh > VNET_NFDB_HASH_MAX)) { 895*5641Swentaoy vnetp->nfdb_hash = VNET_NFDB_HASH; 896*5641Swentaoy } else { 897*5641Swentaoy vnetp->nfdb_hash = nfdbh; 898*5641Swentaoy } 899*5641Swentaoy 900*5641Swentaoy /* allocate fdb hash table, with an extra slot for default route */ 901*5641Swentaoy vnetp->fdbhp = kmem_zalloc(sizeof (fdb_fanout_t) * 902*5641Swentaoy (vnetp->nfdb_hash + 1), KM_SLEEP); 903*5641Swentaoy 904*5641Swentaoy for (i = 0; i <= vnetp->nfdb_hash; i++) { 905*5641Swentaoy rw_init(&vnetp->fdbhp[i].rwlock, NULL, RW_DRIVER, NULL); 906*5641Swentaoy } 907*5641Swentaoy } 908*5641Swentaoy 909*5641Swentaoy /* free the forwarding database */ 910*5641Swentaoy static void 911*5641Swentaoy vnet_fdb_free(vnet_t *vnetp) 912*5641Swentaoy { 913*5641Swentaoy int i; 914*5641Swentaoy 915*5641Swentaoy for (i = 0; i <= vnetp->nfdb_hash; i++) { 916*5641Swentaoy rw_destroy(&vnetp->fdbhp[i].rwlock); 917*5641Swentaoy } 918*5641Swentaoy 919*5641Swentaoy /* 920*5641Swentaoy * deallocate fdb hash table, including an extra slot for default 921*5641Swentaoy * route. 922*5641Swentaoy */ 923*5641Swentaoy kmem_free(vnetp->fdbhp, sizeof (fdb_fanout_t) * (vnetp->nfdb_hash + 1)); 924*5641Swentaoy vnetp->fdbhp = NULL; 925*5641Swentaoy } 926*5641Swentaoy 9271991Sheppo /* look up an fdb entry based on the mac address, caller holds lock */ 9281991Sheppo static fdb_t * 9291991Sheppo vnet_lookup_fdb(fdb_fanout_t *fdbhp, uint8_t *macaddr) 9301991Sheppo { 9311991Sheppo fdb_t *fdbp = NULL; 9321991Sheppo 9331991Sheppo for (fdbp = fdbhp->headp; fdbp != NULL; fdbp = fdbp->nextp) { 9341991Sheppo if (bcmp(fdbp->macaddr, macaddr, ETHERADDRL) == 0) { 9351991Sheppo break; 9361991Sheppo } 9371991Sheppo } 9381991Sheppo 9391991Sheppo return (fdbp); 9401991Sheppo } 9411991Sheppo 9421991Sheppo /* add default route entry into the forwarding database */ 9431991Sheppo void 9441991Sheppo vnet_add_def_rte(void *arg, mac_tx_t m_tx, void *txarg) 9451991Sheppo { 9461991Sheppo vnet_t *vnetp = (vnet_t *)arg; 9471991Sheppo fdb_t *fdbp; 9481991Sheppo fdb_fanout_t *fdbhp; 9491991Sheppo 9501991Sheppo /* 9511991Sheppo * The last hash list is reserved for default route entry, 9521991Sheppo * and for now, we have only one entry in this list. 9531991Sheppo */ 9541991Sheppo fdbhp = &(vnetp->fdbhp[vnetp->nfdb_hash]); 9551991Sheppo 9561991Sheppo WRITE_ENTER(&fdbhp->rwlock); 9571991Sheppo 9581991Sheppo if (fdbhp->headp) { 9594647Sraghuram DWARN(vnetp, "default rte already exists\n"); 9601991Sheppo RW_EXIT(&fdbhp->rwlock); 9611991Sheppo return; 9621991Sheppo } 9631991Sheppo fdbp = kmem_zalloc(sizeof (fdb_t), KM_NOSLEEP); 9641991Sheppo if (fdbp == NULL) { 9651991Sheppo RW_EXIT(&fdbhp->rwlock); 9661991Sheppo return; 9671991Sheppo } 9681991Sheppo bzero(fdbp->macaddr, ETHERADDRL); 9691991Sheppo fdbp->m_tx = m_tx; 9701991Sheppo fdbp->txarg = txarg; 9711991Sheppo fdbp->nextp = NULL; 9721991Sheppo fdbhp->headp = fdbp; 9731991Sheppo 9741991Sheppo RW_EXIT(&fdbhp->rwlock); 9751991Sheppo } 9761991Sheppo 9771991Sheppo /* delete default route entry from the forwarding database */ 9781991Sheppo void 9791991Sheppo vnet_del_def_rte(void *arg) 9801991Sheppo { 9811991Sheppo vnet_t *vnetp = (vnet_t *)arg; 9821991Sheppo fdb_t *fdbp; 9831991Sheppo fdb_fanout_t *fdbhp; 9841991Sheppo 9851991Sheppo /* 9861991Sheppo * The last hash list is reserved for default route entry, 9871991Sheppo * and for now, we have only one entry in this list. 9881991Sheppo */ 9891991Sheppo fdbhp = &(vnetp->fdbhp[vnetp->nfdb_hash]); 9901991Sheppo 9911991Sheppo WRITE_ENTER(&fdbhp->rwlock); 9921991Sheppo 9931991Sheppo if (fdbhp->headp == NULL) { 9941991Sheppo RW_EXIT(&fdbhp->rwlock); 9951991Sheppo return; 9961991Sheppo } 9971991Sheppo fdbp = fdbhp->headp; 9981991Sheppo KMEM_FREE(fdbp); 9991991Sheppo fdbhp->headp = NULL; 10001991Sheppo 10011991Sheppo RW_EXIT(&fdbhp->rwlock); 10021991Sheppo } 10032311Sseb 10042311Sseb void 10052311Sseb vnet_rx(void *arg, mac_resource_handle_t mrh, mblk_t *mp) 10062311Sseb { 10072311Sseb vnet_t *vnetp = arg; 10082311Sseb mac_rx(vnetp->mh, mrh, mp); 10092311Sseb } 10102311Sseb 10112311Sseb void 10122311Sseb vnet_tx_update(void *arg) 10132311Sseb { 10142311Sseb vnet_t *vnetp = arg; 10152311Sseb mac_tx_update(vnetp->mh); 10162311Sseb } 1017