19815SRishi.Srivatsavai@Sun.COM /* 29815SRishi.Srivatsavai@Sun.COM * CDDL HEADER START 39815SRishi.Srivatsavai@Sun.COM * 49815SRishi.Srivatsavai@Sun.COM * The contents of this file are subject to the terms of the 59815SRishi.Srivatsavai@Sun.COM * Common Development and Distribution License (the "License"). 69815SRishi.Srivatsavai@Sun.COM * You may not use this file except in compliance with the License. 79815SRishi.Srivatsavai@Sun.COM * 89815SRishi.Srivatsavai@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 99815SRishi.Srivatsavai@Sun.COM * or http://www.opensolaris.org/os/licensing. 109815SRishi.Srivatsavai@Sun.COM * See the License for the specific language governing permissions 119815SRishi.Srivatsavai@Sun.COM * and limitations under the License. 129815SRishi.Srivatsavai@Sun.COM * 139815SRishi.Srivatsavai@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each 149815SRishi.Srivatsavai@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 159815SRishi.Srivatsavai@Sun.COM * If applicable, add the following below this CDDL HEADER, with the 169815SRishi.Srivatsavai@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying 179815SRishi.Srivatsavai@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner] 189815SRishi.Srivatsavai@Sun.COM * 199815SRishi.Srivatsavai@Sun.COM * CDDL HEADER END 209815SRishi.Srivatsavai@Sun.COM */ 219815SRishi.Srivatsavai@Sun.COM /* 22*12824SCathy.Zhou@Sun.COM * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 239815SRishi.Srivatsavai@Sun.COM */ 249815SRishi.Srivatsavai@Sun.COM 259815SRishi.Srivatsavai@Sun.COM #include <sys/types.h> 269815SRishi.Srivatsavai@Sun.COM #include <string.h> 279815SRishi.Srivatsavai@Sun.COM #include <strings.h> 289815SRishi.Srivatsavai@Sun.COM #include <sys/mac.h> 299815SRishi.Srivatsavai@Sun.COM #include <sys/dls_mgmt.h> 309815SRishi.Srivatsavai@Sun.COM #include <sys/dlpi.h> 319815SRishi.Srivatsavai@Sun.COM #include <net/simnet.h> 329815SRishi.Srivatsavai@Sun.COM #include <errno.h> 339815SRishi.Srivatsavai@Sun.COM #include <unistd.h> 349815SRishi.Srivatsavai@Sun.COM 359815SRishi.Srivatsavai@Sun.COM #include <libdladm_impl.h> 369815SRishi.Srivatsavai@Sun.COM #include <libdllink.h> 379815SRishi.Srivatsavai@Sun.COM #include <libdlaggr.h> 389815SRishi.Srivatsavai@Sun.COM #include <libdlsim.h> 399815SRishi.Srivatsavai@Sun.COM 409815SRishi.Srivatsavai@Sun.COM static dladm_status_t dladm_simnet_persist_conf(dladm_handle_t, const char *, 419815SRishi.Srivatsavai@Sun.COM dladm_simnet_attr_t *); 429815SRishi.Srivatsavai@Sun.COM 439815SRishi.Srivatsavai@Sun.COM /* New simnet instance creation */ 449815SRishi.Srivatsavai@Sun.COM static dladm_status_t 459815SRishi.Srivatsavai@Sun.COM i_dladm_create_simnet(dladm_handle_t handle, dladm_simnet_attr_t *attrp) 469815SRishi.Srivatsavai@Sun.COM { 479815SRishi.Srivatsavai@Sun.COM int rc; 489815SRishi.Srivatsavai@Sun.COM dladm_status_t status = DLADM_STATUS_OK; 499815SRishi.Srivatsavai@Sun.COM simnet_ioc_create_t ioc; 509815SRishi.Srivatsavai@Sun.COM 519815SRishi.Srivatsavai@Sun.COM bzero(&ioc, sizeof (ioc)); 529815SRishi.Srivatsavai@Sun.COM ioc.sic_link_id = attrp->sna_link_id; 539815SRishi.Srivatsavai@Sun.COM ioc.sic_type = attrp->sna_type; 549815SRishi.Srivatsavai@Sun.COM if (attrp->sna_mac_len > 0 && attrp->sna_mac_len <= MAXMACADDRLEN) { 559815SRishi.Srivatsavai@Sun.COM ioc.sic_mac_len = attrp->sna_mac_len; 569815SRishi.Srivatsavai@Sun.COM bcopy(attrp->sna_mac_addr, ioc.sic_mac_addr, ioc.sic_mac_len); 579815SRishi.Srivatsavai@Sun.COM } 589815SRishi.Srivatsavai@Sun.COM 599815SRishi.Srivatsavai@Sun.COM rc = ioctl(dladm_dld_fd(handle), SIMNET_IOC_CREATE, &ioc); 609815SRishi.Srivatsavai@Sun.COM if (rc < 0) 619815SRishi.Srivatsavai@Sun.COM status = dladm_errno2status(errno); 629815SRishi.Srivatsavai@Sun.COM 639815SRishi.Srivatsavai@Sun.COM if (status != DLADM_STATUS_OK) 649815SRishi.Srivatsavai@Sun.COM return (status); 659815SRishi.Srivatsavai@Sun.COM 669815SRishi.Srivatsavai@Sun.COM bcopy(ioc.sic_mac_addr, attrp->sna_mac_addr, MAXMACADDRLEN); 679815SRishi.Srivatsavai@Sun.COM attrp->sna_mac_len = ioc.sic_mac_len; 689815SRishi.Srivatsavai@Sun.COM return (status); 699815SRishi.Srivatsavai@Sun.COM } 709815SRishi.Srivatsavai@Sun.COM 719815SRishi.Srivatsavai@Sun.COM /* Modify existing simnet instance */ 729815SRishi.Srivatsavai@Sun.COM static dladm_status_t 739815SRishi.Srivatsavai@Sun.COM i_dladm_modify_simnet(dladm_handle_t handle, dladm_simnet_attr_t *attrp) 749815SRishi.Srivatsavai@Sun.COM { 759815SRishi.Srivatsavai@Sun.COM int rc; 769815SRishi.Srivatsavai@Sun.COM dladm_status_t status = DLADM_STATUS_OK; 779815SRishi.Srivatsavai@Sun.COM simnet_ioc_modify_t ioc; 789815SRishi.Srivatsavai@Sun.COM 799815SRishi.Srivatsavai@Sun.COM bzero(&ioc, sizeof (ioc)); 809815SRishi.Srivatsavai@Sun.COM ioc.sim_link_id = attrp->sna_link_id; 819815SRishi.Srivatsavai@Sun.COM ioc.sim_peer_link_id = attrp->sna_peer_link_id; 829815SRishi.Srivatsavai@Sun.COM 839815SRishi.Srivatsavai@Sun.COM rc = ioctl(dladm_dld_fd(handle), SIMNET_IOC_MODIFY, &ioc); 849815SRishi.Srivatsavai@Sun.COM if (rc < 0) 859815SRishi.Srivatsavai@Sun.COM status = dladm_errno2status(errno); 869815SRishi.Srivatsavai@Sun.COM 879815SRishi.Srivatsavai@Sun.COM return (status); 889815SRishi.Srivatsavai@Sun.COM } 899815SRishi.Srivatsavai@Sun.COM 909815SRishi.Srivatsavai@Sun.COM /* Delete simnet instance */ 919815SRishi.Srivatsavai@Sun.COM static dladm_status_t 929815SRishi.Srivatsavai@Sun.COM i_dladm_delete_simnet(dladm_handle_t handle, dladm_simnet_attr_t *attrp) 939815SRishi.Srivatsavai@Sun.COM { 949815SRishi.Srivatsavai@Sun.COM int rc; 959815SRishi.Srivatsavai@Sun.COM dladm_status_t status = DLADM_STATUS_OK; 969815SRishi.Srivatsavai@Sun.COM simnet_ioc_delete_t ioc; 979815SRishi.Srivatsavai@Sun.COM 989815SRishi.Srivatsavai@Sun.COM bzero(&ioc, sizeof (ioc)); 999815SRishi.Srivatsavai@Sun.COM ioc.sid_link_id = attrp->sna_link_id; 1009815SRishi.Srivatsavai@Sun.COM 1019815SRishi.Srivatsavai@Sun.COM rc = ioctl(dladm_dld_fd(handle), SIMNET_IOC_DELETE, &ioc); 1029815SRishi.Srivatsavai@Sun.COM if (rc < 0) 1039815SRishi.Srivatsavai@Sun.COM status = dladm_errno2status(errno); 1049815SRishi.Srivatsavai@Sun.COM 1059815SRishi.Srivatsavai@Sun.COM return (status); 1069815SRishi.Srivatsavai@Sun.COM } 1079815SRishi.Srivatsavai@Sun.COM 1089815SRishi.Srivatsavai@Sun.COM /* Retrieve simnet instance information */ 1099815SRishi.Srivatsavai@Sun.COM static dladm_status_t 1109815SRishi.Srivatsavai@Sun.COM i_dladm_get_simnet_info(dladm_handle_t handle, dladm_simnet_attr_t *attrp) 1119815SRishi.Srivatsavai@Sun.COM { 1129815SRishi.Srivatsavai@Sun.COM int rc; 1139815SRishi.Srivatsavai@Sun.COM dladm_status_t status = DLADM_STATUS_OK; 1149815SRishi.Srivatsavai@Sun.COM simnet_ioc_info_t ioc; 1159815SRishi.Srivatsavai@Sun.COM 1169815SRishi.Srivatsavai@Sun.COM bzero(&ioc, sizeof (ioc)); 1179815SRishi.Srivatsavai@Sun.COM ioc.sii_link_id = attrp->sna_link_id; 1189815SRishi.Srivatsavai@Sun.COM 1199815SRishi.Srivatsavai@Sun.COM rc = ioctl(dladm_dld_fd(handle), SIMNET_IOC_INFO, &ioc); 1209815SRishi.Srivatsavai@Sun.COM if (rc < 0) { 1219815SRishi.Srivatsavai@Sun.COM status = dladm_errno2status(errno); 1229815SRishi.Srivatsavai@Sun.COM return (status); 1239815SRishi.Srivatsavai@Sun.COM } 1249815SRishi.Srivatsavai@Sun.COM 1259815SRishi.Srivatsavai@Sun.COM bcopy(ioc.sii_mac_addr, attrp->sna_mac_addr, MAXMACADDRLEN); 1269815SRishi.Srivatsavai@Sun.COM attrp->sna_mac_len = ioc.sii_mac_len; 1279815SRishi.Srivatsavai@Sun.COM attrp->sna_peer_link_id = ioc.sii_peer_link_id; 1289815SRishi.Srivatsavai@Sun.COM attrp->sna_type = ioc.sii_type; 1299815SRishi.Srivatsavai@Sun.COM return (status); 1309815SRishi.Srivatsavai@Sun.COM } 1319815SRishi.Srivatsavai@Sun.COM 1329815SRishi.Srivatsavai@Sun.COM /* Retrieve simnet configuratin */ 1339815SRishi.Srivatsavai@Sun.COM static dladm_status_t 1349815SRishi.Srivatsavai@Sun.COM i_dladm_get_simnet_info_persist(dladm_handle_t handle, 1359815SRishi.Srivatsavai@Sun.COM dladm_simnet_attr_t *attrp) 1369815SRishi.Srivatsavai@Sun.COM { 1379815SRishi.Srivatsavai@Sun.COM dladm_conf_t conf; 1389815SRishi.Srivatsavai@Sun.COM dladm_status_t status; 1399815SRishi.Srivatsavai@Sun.COM char macstr[ETHERADDRL * 3]; 14010616SSebastien.Roy@Sun.COM char simnetpeer[MAXLINKNAMELEN]; 1419815SRishi.Srivatsavai@Sun.COM uint64_t u64; 1429815SRishi.Srivatsavai@Sun.COM boolean_t mac_fixed; 1439815SRishi.Srivatsavai@Sun.COM 144*12824SCathy.Zhou@Sun.COM if ((status = dladm_getsnap_conf(handle, attrp->sna_link_id, 145*12824SCathy.Zhou@Sun.COM &conf)) != DLADM_STATUS_OK) 1469815SRishi.Srivatsavai@Sun.COM return (status); 1479815SRishi.Srivatsavai@Sun.COM 1489815SRishi.Srivatsavai@Sun.COM status = dladm_get_conf_field(handle, conf, FSIMNETTYPE, &u64, 1499815SRishi.Srivatsavai@Sun.COM sizeof (u64)); 1509815SRishi.Srivatsavai@Sun.COM if (status != DLADM_STATUS_OK) 1519815SRishi.Srivatsavai@Sun.COM goto done; 1529815SRishi.Srivatsavai@Sun.COM attrp->sna_type = (uint_t)u64; 1539815SRishi.Srivatsavai@Sun.COM 1549815SRishi.Srivatsavai@Sun.COM status = dladm_get_conf_field(handle, conf, FMADDRLEN, &u64, 1559815SRishi.Srivatsavai@Sun.COM sizeof (u64)); 1569815SRishi.Srivatsavai@Sun.COM if (status != DLADM_STATUS_OK) 1579815SRishi.Srivatsavai@Sun.COM goto done; 1589815SRishi.Srivatsavai@Sun.COM attrp->sna_mac_len = (uint_t)u64; 1599815SRishi.Srivatsavai@Sun.COM 1609815SRishi.Srivatsavai@Sun.COM status = dladm_get_conf_field(handle, conf, FMACADDR, macstr, 1619815SRishi.Srivatsavai@Sun.COM sizeof (macstr)); 1629815SRishi.Srivatsavai@Sun.COM if (status != DLADM_STATUS_OK) 1639815SRishi.Srivatsavai@Sun.COM goto done; 1649815SRishi.Srivatsavai@Sun.COM (void) dladm_aggr_str2macaddr(macstr, &mac_fixed, attrp->sna_mac_addr); 1659815SRishi.Srivatsavai@Sun.COM 1669815SRishi.Srivatsavai@Sun.COM /* Peer field is optional and only set when peer is attached */ 16710616SSebastien.Roy@Sun.COM if (dladm_get_conf_field(handle, conf, FSIMNETPEER, simnetpeer, 16810616SSebastien.Roy@Sun.COM sizeof (simnetpeer)) == DLADM_STATUS_OK) { 16910616SSebastien.Roy@Sun.COM status = dladm_name2info(handle, simnetpeer, 17010616SSebastien.Roy@Sun.COM &attrp->sna_peer_link_id, NULL, NULL, NULL); 17110616SSebastien.Roy@Sun.COM } else { 1729815SRishi.Srivatsavai@Sun.COM attrp->sna_peer_link_id = DATALINK_INVALID_LINKID; 17310616SSebastien.Roy@Sun.COM } 1749815SRishi.Srivatsavai@Sun.COM done: 1759815SRishi.Srivatsavai@Sun.COM dladm_destroy_conf(handle, conf); 1769815SRishi.Srivatsavai@Sun.COM return (status); 1779815SRishi.Srivatsavai@Sun.COM } 1789815SRishi.Srivatsavai@Sun.COM 1799815SRishi.Srivatsavai@Sun.COM dladm_status_t 1809815SRishi.Srivatsavai@Sun.COM dladm_simnet_create(dladm_handle_t handle, const char *simnetname, 1819815SRishi.Srivatsavai@Sun.COM uint_t media, uint32_t flags) 1829815SRishi.Srivatsavai@Sun.COM { 1839815SRishi.Srivatsavai@Sun.COM datalink_id_t simnet_id; 1849815SRishi.Srivatsavai@Sun.COM dladm_status_t status; 1859815SRishi.Srivatsavai@Sun.COM dladm_simnet_attr_t attr; 1869815SRishi.Srivatsavai@Sun.COM 1879815SRishi.Srivatsavai@Sun.COM if (!(flags & DLADM_OPT_ACTIVE)) 1889815SRishi.Srivatsavai@Sun.COM return (DLADM_STATUS_NOTSUP); 1899815SRishi.Srivatsavai@Sun.COM 1909815SRishi.Srivatsavai@Sun.COM flags &= (DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST); 1919815SRishi.Srivatsavai@Sun.COM if ((status = dladm_create_datalink_id(handle, simnetname, 1929815SRishi.Srivatsavai@Sun.COM DATALINK_CLASS_SIMNET, media, flags, 1939815SRishi.Srivatsavai@Sun.COM &simnet_id)) != DLADM_STATUS_OK) 1949815SRishi.Srivatsavai@Sun.COM return (status); 1959815SRishi.Srivatsavai@Sun.COM 1969815SRishi.Srivatsavai@Sun.COM bzero(&attr, sizeof (attr)); 1979815SRishi.Srivatsavai@Sun.COM attr.sna_link_id = simnet_id; 1989815SRishi.Srivatsavai@Sun.COM attr.sna_type = media; 1999815SRishi.Srivatsavai@Sun.COM status = i_dladm_create_simnet(handle, &attr); 2009815SRishi.Srivatsavai@Sun.COM if (status != DLADM_STATUS_OK) 2019815SRishi.Srivatsavai@Sun.COM goto done; 2029815SRishi.Srivatsavai@Sun.COM 2039815SRishi.Srivatsavai@Sun.COM if (!(flags & DLADM_OPT_PERSIST)) 2049815SRishi.Srivatsavai@Sun.COM goto done; 2059815SRishi.Srivatsavai@Sun.COM 2069815SRishi.Srivatsavai@Sun.COM status = dladm_simnet_persist_conf(handle, simnetname, &attr); 2079815SRishi.Srivatsavai@Sun.COM if (status != DLADM_STATUS_OK) { 2089815SRishi.Srivatsavai@Sun.COM (void) i_dladm_delete_simnet(handle, &attr); 2099815SRishi.Srivatsavai@Sun.COM goto done; 2109815SRishi.Srivatsavai@Sun.COM } 2119815SRishi.Srivatsavai@Sun.COM 2129815SRishi.Srivatsavai@Sun.COM (void) dladm_set_linkprop(handle, simnet_id, NULL, NULL, 0, flags); 2139815SRishi.Srivatsavai@Sun.COM 2149815SRishi.Srivatsavai@Sun.COM done: 2159815SRishi.Srivatsavai@Sun.COM if (status != DLADM_STATUS_OK) { 2169815SRishi.Srivatsavai@Sun.COM (void) dladm_destroy_datalink_id(handle, simnet_id, flags); 2179815SRishi.Srivatsavai@Sun.COM } 2189815SRishi.Srivatsavai@Sun.COM return (status); 2199815SRishi.Srivatsavai@Sun.COM } 2209815SRishi.Srivatsavai@Sun.COM 2219815SRishi.Srivatsavai@Sun.COM /* Update existing simnet configuration */ 2229815SRishi.Srivatsavai@Sun.COM static dladm_status_t 2239815SRishi.Srivatsavai@Sun.COM i_dladm_simnet_update_conf(dladm_handle_t handle, datalink_id_t simnet_id, 2249815SRishi.Srivatsavai@Sun.COM datalink_id_t peer_simnet_id) 2259815SRishi.Srivatsavai@Sun.COM { 2269815SRishi.Srivatsavai@Sun.COM dladm_status_t status; 2279815SRishi.Srivatsavai@Sun.COM dladm_conf_t conf; 22810616SSebastien.Roy@Sun.COM char simnetpeer[MAXLINKNAMELEN]; 2299815SRishi.Srivatsavai@Sun.COM 230*12824SCathy.Zhou@Sun.COM status = dladm_open_conf(handle, simnet_id, &conf); 2319815SRishi.Srivatsavai@Sun.COM if (status != DLADM_STATUS_OK) 2329815SRishi.Srivatsavai@Sun.COM return (status); 2339815SRishi.Srivatsavai@Sun.COM 2349815SRishi.Srivatsavai@Sun.COM /* First clear previous peer if any in configuration */ 2359815SRishi.Srivatsavai@Sun.COM (void) dladm_unset_conf_field(handle, conf, FSIMNETPEER); 2369815SRishi.Srivatsavai@Sun.COM if (peer_simnet_id != DATALINK_INVALID_LINKID) { 2379815SRishi.Srivatsavai@Sun.COM if ((status = dladm_datalink_id2info(handle, 23810616SSebastien.Roy@Sun.COM peer_simnet_id, NULL, NULL, NULL, simnetpeer, 23910616SSebastien.Roy@Sun.COM sizeof (simnetpeer))) == DLADM_STATUS_OK) { 2409815SRishi.Srivatsavai@Sun.COM status = dladm_set_conf_field(handle, conf, 24110616SSebastien.Roy@Sun.COM FSIMNETPEER, DLADM_TYPE_STR, simnetpeer); 24210616SSebastien.Roy@Sun.COM } 2439815SRishi.Srivatsavai@Sun.COM if (status != DLADM_STATUS_OK) 2449815SRishi.Srivatsavai@Sun.COM goto fail; 2459815SRishi.Srivatsavai@Sun.COM } 2469815SRishi.Srivatsavai@Sun.COM 2479815SRishi.Srivatsavai@Sun.COM status = dladm_write_conf(handle, conf); 2489815SRishi.Srivatsavai@Sun.COM fail: 2499815SRishi.Srivatsavai@Sun.COM dladm_destroy_conf(handle, conf); 2509815SRishi.Srivatsavai@Sun.COM return (status); 2519815SRishi.Srivatsavai@Sun.COM } 2529815SRishi.Srivatsavai@Sun.COM 2539815SRishi.Srivatsavai@Sun.COM /* Modify attached simnet peer */ 2549815SRishi.Srivatsavai@Sun.COM dladm_status_t 2559815SRishi.Srivatsavai@Sun.COM dladm_simnet_modify(dladm_handle_t handle, datalink_id_t simnet_id, 2569815SRishi.Srivatsavai@Sun.COM datalink_id_t peer_simnet_id, uint32_t flags) 2579815SRishi.Srivatsavai@Sun.COM { 2589815SRishi.Srivatsavai@Sun.COM dladm_simnet_attr_t attr; 2599815SRishi.Srivatsavai@Sun.COM dladm_simnet_attr_t prevattr; 2609815SRishi.Srivatsavai@Sun.COM dladm_status_t status; 2619815SRishi.Srivatsavai@Sun.COM datalink_class_t class; 2629815SRishi.Srivatsavai@Sun.COM uint32_t linkflags; 2639815SRishi.Srivatsavai@Sun.COM uint32_t peerlinkflags; 2649815SRishi.Srivatsavai@Sun.COM 2659815SRishi.Srivatsavai@Sun.COM if (!(flags & DLADM_OPT_ACTIVE)) 2669815SRishi.Srivatsavai@Sun.COM return (DLADM_STATUS_NOTSUP); 2679815SRishi.Srivatsavai@Sun.COM 2689815SRishi.Srivatsavai@Sun.COM if ((dladm_datalink_id2info(handle, simnet_id, &linkflags, &class, 2699815SRishi.Srivatsavai@Sun.COM NULL, NULL, 0) != DLADM_STATUS_OK)) 2709815SRishi.Srivatsavai@Sun.COM return (DLADM_STATUS_BADARG); 2719815SRishi.Srivatsavai@Sun.COM if (class != DATALINK_CLASS_SIMNET) 2729815SRishi.Srivatsavai@Sun.COM return (DLADM_STATUS_BADARG); 2739815SRishi.Srivatsavai@Sun.COM 2749815SRishi.Srivatsavai@Sun.COM if (peer_simnet_id != DATALINK_INVALID_LINKID) { 2759815SRishi.Srivatsavai@Sun.COM if (dladm_datalink_id2info(handle, peer_simnet_id, 2769815SRishi.Srivatsavai@Sun.COM &peerlinkflags, &class, NULL, NULL, 0) != DLADM_STATUS_OK) 2779815SRishi.Srivatsavai@Sun.COM return (DLADM_STATUS_BADARG); 2789815SRishi.Srivatsavai@Sun.COM if (class != DATALINK_CLASS_SIMNET) 2799815SRishi.Srivatsavai@Sun.COM return (DLADM_STATUS_BADARG); 2809815SRishi.Srivatsavai@Sun.COM /* Check to ensure the peer link has identical flags */ 2819815SRishi.Srivatsavai@Sun.COM if (peerlinkflags != linkflags) 2829815SRishi.Srivatsavai@Sun.COM return (DLADM_STATUS_BADARG); 2839815SRishi.Srivatsavai@Sun.COM } 2849815SRishi.Srivatsavai@Sun.COM 2859815SRishi.Srivatsavai@Sun.COM /* Retrieve previous attrs before modification */ 2869815SRishi.Srivatsavai@Sun.COM bzero(&prevattr, sizeof (prevattr)); 2879815SRishi.Srivatsavai@Sun.COM if ((status = dladm_simnet_info(handle, simnet_id, &prevattr, 2889815SRishi.Srivatsavai@Sun.COM flags)) != DLADM_STATUS_OK) 2899815SRishi.Srivatsavai@Sun.COM return (status); 2909815SRishi.Srivatsavai@Sun.COM 2919815SRishi.Srivatsavai@Sun.COM bzero(&attr, sizeof (attr)); 2929815SRishi.Srivatsavai@Sun.COM attr.sna_link_id = simnet_id; 2939815SRishi.Srivatsavai@Sun.COM attr.sna_peer_link_id = peer_simnet_id; 2949815SRishi.Srivatsavai@Sun.COM status = i_dladm_modify_simnet(handle, &attr); 2959815SRishi.Srivatsavai@Sun.COM if ((status != DLADM_STATUS_OK) || !(flags & DLADM_OPT_PERSIST)) 2969815SRishi.Srivatsavai@Sun.COM return (status); 2979815SRishi.Srivatsavai@Sun.COM 2989815SRishi.Srivatsavai@Sun.COM /* First we clear link's existing peer field in config */ 2999815SRishi.Srivatsavai@Sun.COM status = i_dladm_simnet_update_conf(handle, simnet_id, 3009815SRishi.Srivatsavai@Sun.COM DATALINK_INVALID_LINKID); 3019815SRishi.Srivatsavai@Sun.COM if (status != DLADM_STATUS_OK) 3029815SRishi.Srivatsavai@Sun.COM return (status); 3039815SRishi.Srivatsavai@Sun.COM 3049815SRishi.Srivatsavai@Sun.COM /* Clear the previous peer link's existing peer field in config */ 3059815SRishi.Srivatsavai@Sun.COM if (prevattr.sna_peer_link_id != DATALINK_INVALID_LINKID) { 3069815SRishi.Srivatsavai@Sun.COM status = i_dladm_simnet_update_conf(handle, 3079815SRishi.Srivatsavai@Sun.COM prevattr.sna_peer_link_id, DATALINK_INVALID_LINKID); 3089815SRishi.Srivatsavai@Sun.COM if (status != DLADM_STATUS_OK) 3099815SRishi.Srivatsavai@Sun.COM return (status); 3109815SRishi.Srivatsavai@Sun.COM } 3119815SRishi.Srivatsavai@Sun.COM 3129815SRishi.Srivatsavai@Sun.COM /* Update the configuration in both simnets with any new peer link */ 3139815SRishi.Srivatsavai@Sun.COM if (peer_simnet_id != DATALINK_INVALID_LINKID) { 3149815SRishi.Srivatsavai@Sun.COM status = i_dladm_simnet_update_conf(handle, simnet_id, 3159815SRishi.Srivatsavai@Sun.COM peer_simnet_id); 3169815SRishi.Srivatsavai@Sun.COM if (status == DLADM_STATUS_OK) 3179815SRishi.Srivatsavai@Sun.COM status = i_dladm_simnet_update_conf(handle, 3189815SRishi.Srivatsavai@Sun.COM peer_simnet_id, simnet_id); 3199815SRishi.Srivatsavai@Sun.COM } 3209815SRishi.Srivatsavai@Sun.COM 3219815SRishi.Srivatsavai@Sun.COM return (status); 3229815SRishi.Srivatsavai@Sun.COM } 3239815SRishi.Srivatsavai@Sun.COM 3249815SRishi.Srivatsavai@Sun.COM dladm_status_t 3259815SRishi.Srivatsavai@Sun.COM dladm_simnet_delete(dladm_handle_t handle, datalink_id_t simnet_id, 3269815SRishi.Srivatsavai@Sun.COM uint32_t flags) 3279815SRishi.Srivatsavai@Sun.COM { 3289815SRishi.Srivatsavai@Sun.COM dladm_simnet_attr_t attr; 3299815SRishi.Srivatsavai@Sun.COM dladm_simnet_attr_t prevattr; 3309815SRishi.Srivatsavai@Sun.COM dladm_status_t status; 3319815SRishi.Srivatsavai@Sun.COM datalink_class_t class; 3329815SRishi.Srivatsavai@Sun.COM 3339815SRishi.Srivatsavai@Sun.COM if ((dladm_datalink_id2info(handle, simnet_id, NULL, &class, 3349815SRishi.Srivatsavai@Sun.COM NULL, NULL, 0) != DLADM_STATUS_OK)) 3359815SRishi.Srivatsavai@Sun.COM return (DLADM_STATUS_BADARG); 3369815SRishi.Srivatsavai@Sun.COM 3379815SRishi.Srivatsavai@Sun.COM if (class != DATALINK_CLASS_SIMNET) 3389815SRishi.Srivatsavai@Sun.COM return (DLADM_STATUS_BADARG); 3399815SRishi.Srivatsavai@Sun.COM 3409815SRishi.Srivatsavai@Sun.COM /* Check current simnet attributes before deletion */ 3419815SRishi.Srivatsavai@Sun.COM flags &= (DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST); 3429815SRishi.Srivatsavai@Sun.COM bzero(&prevattr, sizeof (prevattr)); 3439815SRishi.Srivatsavai@Sun.COM if ((status = dladm_simnet_info(handle, simnet_id, &prevattr, 3449815SRishi.Srivatsavai@Sun.COM flags)) != DLADM_STATUS_OK) 3459815SRishi.Srivatsavai@Sun.COM return (status); 3469815SRishi.Srivatsavai@Sun.COM 3479815SRishi.Srivatsavai@Sun.COM bzero(&attr, sizeof (attr)); 3489815SRishi.Srivatsavai@Sun.COM attr.sna_link_id = simnet_id; 3499815SRishi.Srivatsavai@Sun.COM if (flags & DLADM_OPT_ACTIVE) { 3509815SRishi.Srivatsavai@Sun.COM status = i_dladm_delete_simnet(handle, &attr); 3519815SRishi.Srivatsavai@Sun.COM if (status == DLADM_STATUS_OK) { 3529815SRishi.Srivatsavai@Sun.COM (void) dladm_set_linkprop(handle, simnet_id, NULL, 3539815SRishi.Srivatsavai@Sun.COM NULL, 0, DLADM_OPT_ACTIVE); 3549815SRishi.Srivatsavai@Sun.COM (void) dladm_destroy_datalink_id(handle, simnet_id, 3559815SRishi.Srivatsavai@Sun.COM DLADM_OPT_ACTIVE); 3569815SRishi.Srivatsavai@Sun.COM } else if (status != DLADM_STATUS_NOTFOUND) { 3579815SRishi.Srivatsavai@Sun.COM return (status); 3589815SRishi.Srivatsavai@Sun.COM } 3599815SRishi.Srivatsavai@Sun.COM } 3609815SRishi.Srivatsavai@Sun.COM 3619815SRishi.Srivatsavai@Sun.COM if (flags & DLADM_OPT_PERSIST) { 36210616SSebastien.Roy@Sun.COM (void) dladm_remove_conf(handle, simnet_id); 3639815SRishi.Srivatsavai@Sun.COM (void) dladm_destroy_datalink_id(handle, simnet_id, 3649815SRishi.Srivatsavai@Sun.COM DLADM_OPT_PERSIST); 3659815SRishi.Srivatsavai@Sun.COM 3669815SRishi.Srivatsavai@Sun.COM /* Update any attached peer configuration */ 3679815SRishi.Srivatsavai@Sun.COM if (prevattr.sna_peer_link_id != DATALINK_INVALID_LINKID) 3689815SRishi.Srivatsavai@Sun.COM status = i_dladm_simnet_update_conf(handle, 3699815SRishi.Srivatsavai@Sun.COM prevattr.sna_peer_link_id, DATALINK_INVALID_LINKID); 3709815SRishi.Srivatsavai@Sun.COM } 3719815SRishi.Srivatsavai@Sun.COM return (status); 3729815SRishi.Srivatsavai@Sun.COM } 3739815SRishi.Srivatsavai@Sun.COM 3749815SRishi.Srivatsavai@Sun.COM /* Retrieve simnet information either active or from configuration */ 3759815SRishi.Srivatsavai@Sun.COM dladm_status_t 3769815SRishi.Srivatsavai@Sun.COM dladm_simnet_info(dladm_handle_t handle, datalink_id_t simnet_id, 3779815SRishi.Srivatsavai@Sun.COM dladm_simnet_attr_t *attrp, uint32_t flags) 3789815SRishi.Srivatsavai@Sun.COM { 3799815SRishi.Srivatsavai@Sun.COM datalink_class_t class; 3809815SRishi.Srivatsavai@Sun.COM dladm_status_t status; 3819815SRishi.Srivatsavai@Sun.COM 3829815SRishi.Srivatsavai@Sun.COM if ((dladm_datalink_id2info(handle, simnet_id, NULL, &class, 3839815SRishi.Srivatsavai@Sun.COM NULL, NULL, 0) != DLADM_STATUS_OK)) 3849815SRishi.Srivatsavai@Sun.COM return (DLADM_STATUS_BADARG); 3859815SRishi.Srivatsavai@Sun.COM 3869815SRishi.Srivatsavai@Sun.COM if (class != DATALINK_CLASS_SIMNET) 3879815SRishi.Srivatsavai@Sun.COM return (DLADM_STATUS_BADARG); 3889815SRishi.Srivatsavai@Sun.COM 3899815SRishi.Srivatsavai@Sun.COM bzero(attrp, sizeof (attrp)); 3909815SRishi.Srivatsavai@Sun.COM attrp->sna_link_id = simnet_id; 3919815SRishi.Srivatsavai@Sun.COM 3929815SRishi.Srivatsavai@Sun.COM if (flags & DLADM_OPT_ACTIVE) { 3939815SRishi.Srivatsavai@Sun.COM status = i_dladm_get_simnet_info(handle, attrp); 3949815SRishi.Srivatsavai@Sun.COM /* 3959815SRishi.Srivatsavai@Sun.COM * If no active simnet found then return any simnet 3969815SRishi.Srivatsavai@Sun.COM * from stored config if requested. 3979815SRishi.Srivatsavai@Sun.COM */ 3989815SRishi.Srivatsavai@Sun.COM if (status == DLADM_STATUS_NOTFOUND && 3999815SRishi.Srivatsavai@Sun.COM (flags & DLADM_OPT_PERSIST)) 4009815SRishi.Srivatsavai@Sun.COM return (i_dladm_get_simnet_info_persist(handle, attrp)); 4019815SRishi.Srivatsavai@Sun.COM return (status); 4029815SRishi.Srivatsavai@Sun.COM } else if (flags & DLADM_OPT_PERSIST) { 4039815SRishi.Srivatsavai@Sun.COM return (i_dladm_get_simnet_info_persist(handle, attrp)); 4049815SRishi.Srivatsavai@Sun.COM } else { 4059815SRishi.Srivatsavai@Sun.COM return (DLADM_STATUS_BADARG); 4069815SRishi.Srivatsavai@Sun.COM } 4079815SRishi.Srivatsavai@Sun.COM } 4089815SRishi.Srivatsavai@Sun.COM 4099815SRishi.Srivatsavai@Sun.COM /* Bring up simnet from stored configuration */ 4109815SRishi.Srivatsavai@Sun.COM static int 4119815SRishi.Srivatsavai@Sun.COM i_dladm_simnet_up(dladm_handle_t handle, datalink_id_t simnet_id, void *arg) 4129815SRishi.Srivatsavai@Sun.COM { 4139815SRishi.Srivatsavai@Sun.COM dladm_status_t *statusp = arg; 4149815SRishi.Srivatsavai@Sun.COM dladm_status_t status; 4159815SRishi.Srivatsavai@Sun.COM dladm_simnet_attr_t attr; 4169815SRishi.Srivatsavai@Sun.COM dladm_simnet_attr_t peer_attr; 4179815SRishi.Srivatsavai@Sun.COM 4189815SRishi.Srivatsavai@Sun.COM bzero(&attr, sizeof (attr)); 4199815SRishi.Srivatsavai@Sun.COM attr.sna_link_id = simnet_id; 4209815SRishi.Srivatsavai@Sun.COM status = dladm_simnet_info(handle, simnet_id, &attr, 4219815SRishi.Srivatsavai@Sun.COM DLADM_OPT_PERSIST); 4229815SRishi.Srivatsavai@Sun.COM if (status != DLADM_STATUS_OK) 4239815SRishi.Srivatsavai@Sun.COM goto done; 4249815SRishi.Srivatsavai@Sun.COM 4259815SRishi.Srivatsavai@Sun.COM status = i_dladm_create_simnet(handle, &attr); 4269815SRishi.Srivatsavai@Sun.COM if (status != DLADM_STATUS_OK) 4279815SRishi.Srivatsavai@Sun.COM goto done; 4289815SRishi.Srivatsavai@Sun.COM 4299815SRishi.Srivatsavai@Sun.COM /* 4309815SRishi.Srivatsavai@Sun.COM * When bringing up check if the peer link is available, if it 4319815SRishi.Srivatsavai@Sun.COM * is then modify the simnet and attach the peer link. 4329815SRishi.Srivatsavai@Sun.COM */ 4339815SRishi.Srivatsavai@Sun.COM if ((attr.sna_peer_link_id != DATALINK_INVALID_LINKID) && 4349815SRishi.Srivatsavai@Sun.COM (dladm_simnet_info(handle, attr.sna_peer_link_id, &peer_attr, 4359815SRishi.Srivatsavai@Sun.COM DLADM_OPT_ACTIVE) == DLADM_STATUS_OK)) { 4369815SRishi.Srivatsavai@Sun.COM status = i_dladm_modify_simnet(handle, &attr); 4379815SRishi.Srivatsavai@Sun.COM if (status != DLADM_STATUS_OK) 4389815SRishi.Srivatsavai@Sun.COM goto done; 4399815SRishi.Srivatsavai@Sun.COM } 4409815SRishi.Srivatsavai@Sun.COM 4419815SRishi.Srivatsavai@Sun.COM if ((status = dladm_up_datalink_id(handle, simnet_id)) != 4429815SRishi.Srivatsavai@Sun.COM DLADM_STATUS_OK) { 4439815SRishi.Srivatsavai@Sun.COM (void) dladm_simnet_delete(handle, simnet_id, 4449815SRishi.Srivatsavai@Sun.COM DLADM_OPT_PERSIST); 4459815SRishi.Srivatsavai@Sun.COM goto done; 4469815SRishi.Srivatsavai@Sun.COM } 4479815SRishi.Srivatsavai@Sun.COM done: 4489815SRishi.Srivatsavai@Sun.COM *statusp = status; 4499815SRishi.Srivatsavai@Sun.COM return (DLADM_WALK_CONTINUE); 4509815SRishi.Srivatsavai@Sun.COM } 4519815SRishi.Srivatsavai@Sun.COM 4529815SRishi.Srivatsavai@Sun.COM /* Bring up simnet instance(s) from configuration */ 4539815SRishi.Srivatsavai@Sun.COM /* ARGSUSED */ 4549815SRishi.Srivatsavai@Sun.COM dladm_status_t 4559815SRishi.Srivatsavai@Sun.COM dladm_simnet_up(dladm_handle_t handle, datalink_id_t simnet_id, 4569815SRishi.Srivatsavai@Sun.COM uint32_t flags) 4579815SRishi.Srivatsavai@Sun.COM { 4589815SRishi.Srivatsavai@Sun.COM dladm_status_t status; 4599815SRishi.Srivatsavai@Sun.COM 4609815SRishi.Srivatsavai@Sun.COM if (simnet_id == DATALINK_ALL_LINKID) { 4619815SRishi.Srivatsavai@Sun.COM (void) dladm_walk_datalink_id(i_dladm_simnet_up, handle, 4629815SRishi.Srivatsavai@Sun.COM &status, DATALINK_CLASS_SIMNET, DATALINK_ANY_MEDIATYPE, 4639815SRishi.Srivatsavai@Sun.COM DLADM_OPT_PERSIST); 4649815SRishi.Srivatsavai@Sun.COM return (DLADM_STATUS_OK); 4659815SRishi.Srivatsavai@Sun.COM } else { 4669815SRishi.Srivatsavai@Sun.COM (void) i_dladm_simnet_up(handle, simnet_id, &status); 4679815SRishi.Srivatsavai@Sun.COM return (status); 4689815SRishi.Srivatsavai@Sun.COM } 4699815SRishi.Srivatsavai@Sun.COM } 4709815SRishi.Srivatsavai@Sun.COM 4719815SRishi.Srivatsavai@Sun.COM /* Store simnet configuration */ 4729815SRishi.Srivatsavai@Sun.COM static dladm_status_t 4739815SRishi.Srivatsavai@Sun.COM dladm_simnet_persist_conf(dladm_handle_t handle, const char *name, 4749815SRishi.Srivatsavai@Sun.COM dladm_simnet_attr_t *attrp) 4759815SRishi.Srivatsavai@Sun.COM { 476*12824SCathy.Zhou@Sun.COM dladm_conf_t conf; 4779815SRishi.Srivatsavai@Sun.COM dladm_status_t status; 4789815SRishi.Srivatsavai@Sun.COM char mstr[ETHERADDRL * 3]; 4799815SRishi.Srivatsavai@Sun.COM uint64_t u64; 4809815SRishi.Srivatsavai@Sun.COM 4819815SRishi.Srivatsavai@Sun.COM if ((status = dladm_create_conf(handle, name, attrp->sna_link_id, 4829815SRishi.Srivatsavai@Sun.COM DATALINK_CLASS_SIMNET, attrp->sna_type, &conf)) != DLADM_STATUS_OK) 4839815SRishi.Srivatsavai@Sun.COM return (status); 4849815SRishi.Srivatsavai@Sun.COM 4859815SRishi.Srivatsavai@Sun.COM status = dladm_set_conf_field(handle, conf, FMACADDR, 4869815SRishi.Srivatsavai@Sun.COM DLADM_TYPE_STR, dladm_aggr_macaddr2str(attrp->sna_mac_addr, mstr)); 4879815SRishi.Srivatsavai@Sun.COM if (status != DLADM_STATUS_OK) 4889815SRishi.Srivatsavai@Sun.COM goto done; 4899815SRishi.Srivatsavai@Sun.COM 4909815SRishi.Srivatsavai@Sun.COM u64 = attrp->sna_type; 4919815SRishi.Srivatsavai@Sun.COM status = dladm_set_conf_field(handle, conf, FSIMNETTYPE, 4929815SRishi.Srivatsavai@Sun.COM DLADM_TYPE_UINT64, &u64); 4939815SRishi.Srivatsavai@Sun.COM if (status != DLADM_STATUS_OK) 4949815SRishi.Srivatsavai@Sun.COM goto done; 4959815SRishi.Srivatsavai@Sun.COM 4969815SRishi.Srivatsavai@Sun.COM u64 = attrp->sna_mac_len; 4979815SRishi.Srivatsavai@Sun.COM status = dladm_set_conf_field(handle, conf, FMADDRLEN, 4989815SRishi.Srivatsavai@Sun.COM DLADM_TYPE_UINT64, &u64); 4999815SRishi.Srivatsavai@Sun.COM if (status != DLADM_STATUS_OK) 5009815SRishi.Srivatsavai@Sun.COM goto done; 5019815SRishi.Srivatsavai@Sun.COM 5029815SRishi.Srivatsavai@Sun.COM status = dladm_write_conf(handle, conf); 5039815SRishi.Srivatsavai@Sun.COM done: 5049815SRishi.Srivatsavai@Sun.COM dladm_destroy_conf(handle, conf); 5059815SRishi.Srivatsavai@Sun.COM return (status); 5069815SRishi.Srivatsavai@Sun.COM } 507