15084Sjohnlev /* 25084Sjohnlev * CDDL HEADER START 35084Sjohnlev * 45084Sjohnlev * The contents of this file are subject to the terms of the 55084Sjohnlev * Common Development and Distribution License (the "License"). 65084Sjohnlev * You may not use this file except in compliance with the License. 75084Sjohnlev * 85084Sjohnlev * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 95084Sjohnlev * or http://www.opensolaris.org/os/licensing. 105084Sjohnlev * See the License for the specific language governing permissions 115084Sjohnlev * and limitations under the License. 125084Sjohnlev * 135084Sjohnlev * When distributing Covered Code, include this CDDL HEADER in each 145084Sjohnlev * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 155084Sjohnlev * If applicable, add the following below this CDDL HEADER, with the 165084Sjohnlev * fields enclosed by brackets "[]" replaced with your own identifying 175084Sjohnlev * information: Portions Copyright [yyyy] [name of copyright owner] 185084Sjohnlev * 195084Sjohnlev * CDDL HEADER END 205084Sjohnlev */ 215084Sjohnlev /* 22*12824SCathy.Zhou@Sun.COM * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 235084Sjohnlev */ 245084Sjohnlev 255084Sjohnlev #include <stdio.h> 265084Sjohnlev #include <sys/types.h> 275084Sjohnlev #include <sys/stat.h> 285084Sjohnlev #include <string.h> 295084Sjohnlev #include <fcntl.h> 305084Sjohnlev #include <unistd.h> 315084Sjohnlev #include <stropts.h> 325084Sjohnlev #include <stdlib.h> 335084Sjohnlev #include <errno.h> 345084Sjohnlev #include <strings.h> 355084Sjohnlev #include <libintl.h> 365084Sjohnlev #include <net/if_types.h> 375084Sjohnlev #include <net/if_dl.h> 388275SEric Cheng #include <sys/dld.h> 395084Sjohnlev #include <libdladm_impl.h> 4011076SCathy.Zhou@Sun.COM #include <libvrrpadm.h> 415895Syz147064 #include <libdllink.h> 4210491SRishi.Srivatsavai@Sun.COM #include <libdlbridge.h> 435084Sjohnlev #include <libdlvnic.h> 445084Sjohnlev 455084Sjohnlev /* 465084Sjohnlev * VNIC administration library. 475084Sjohnlev */ 485084Sjohnlev 498275SEric Cheng /* 508275SEric Cheng * Default random MAC address prefix (locally administered). 518275SEric Cheng */ 528275SEric Cheng static char dladm_vnic_def_prefix[] = {0x02, 0x08, 0x20}; 538275SEric Cheng 548453SAnurag.Maskey@Sun.COM static dladm_status_t dladm_vnic_persist_conf(dladm_handle_t, 558453SAnurag.Maskey@Sun.COM const char *name, dladm_vnic_attr_t *, 568453SAnurag.Maskey@Sun.COM datalink_class_t); 578275SEric Cheng static const char *dladm_vnic_macaddr2str(const uchar_t *, char *); 588275SEric Cheng static dladm_status_t dladm_vnic_str2macaddr(const char *, uchar_t *); 595084Sjohnlev 608275SEric Cheng /* 618275SEric Cheng * Convert a diagnostic returned by the kernel into a dladm_status_t. 628275SEric Cheng */ 638275SEric Cheng static dladm_status_t 648275SEric Cheng dladm_vnic_diag2status(vnic_ioc_diag_t ioc_diag) 658275SEric Cheng { 668275SEric Cheng switch (ioc_diag) { 6711076SCathy.Zhou@Sun.COM case VNIC_IOC_DIAG_NONE: 6811076SCathy.Zhou@Sun.COM return (DLADM_STATUS_OK); 698275SEric Cheng case VNIC_IOC_DIAG_MACADDRLEN_INVALID: 708275SEric Cheng return (DLADM_STATUS_INVALIDMACADDRLEN); 718275SEric Cheng case VNIC_IOC_DIAG_MACADDR_NIC: 728275SEric Cheng return (DLADM_STATUS_INVALIDMACADDRNIC); 738275SEric Cheng case VNIC_IOC_DIAG_MACADDR_INUSE: 748275SEric Cheng return (DLADM_STATUS_INVALIDMACADDRINUSE); 758275SEric Cheng case VNIC_IOC_DIAG_MACFACTORYSLOTINVALID: 768275SEric Cheng return (DLADM_STATUS_MACFACTORYSLOTINVALID); 778275SEric Cheng case VNIC_IOC_DIAG_MACFACTORYSLOTUSED: 788275SEric Cheng return (DLADM_STATUS_MACFACTORYSLOTUSED); 798275SEric Cheng case VNIC_IOC_DIAG_MACFACTORYSLOTALLUSED: 808275SEric Cheng return (DLADM_STATUS_MACFACTORYSLOTALLUSED); 818275SEric Cheng case VNIC_IOC_DIAG_MACFACTORYNOTSUP: 828275SEric Cheng return (DLADM_STATUS_MACFACTORYNOTSUP); 838275SEric Cheng case VNIC_IOC_DIAG_MACPREFIX_INVALID: 848275SEric Cheng return (DLADM_STATUS_INVALIDMACPREFIX); 858275SEric Cheng case VNIC_IOC_DIAG_MACPREFIXLEN_INVALID: 868275SEric Cheng return (DLADM_STATUS_INVALIDMACPREFIXLEN); 878275SEric Cheng case VNIC_IOC_DIAG_MACMARGIN_INVALID: 888275SEric Cheng return (DLADM_STATUS_INVALID_MACMARGIN); 898275SEric Cheng case VNIC_IOC_DIAG_NO_HWRINGS: 908275SEric Cheng return (DLADM_STATUS_NO_HWRINGS); 9111076SCathy.Zhou@Sun.COM case VNIC_IOC_DIAG_MACADDR_INVALID: 9211076SCathy.Zhou@Sun.COM return (DLADM_STATUS_INVALIDMACADDR); 9311076SCathy.Zhou@Sun.COM default: 9411076SCathy.Zhou@Sun.COM return (DLADM_STATUS_FAILED); 958275SEric Cheng } 968275SEric Cheng } 975084Sjohnlev 985084Sjohnlev /* 995084Sjohnlev * Send a create command to the VNIC driver. 1005084Sjohnlev */ 1018275SEric Cheng dladm_status_t 1028453SAnurag.Maskey@Sun.COM i_dladm_vnic_create_sys(dladm_handle_t handle, dladm_vnic_attr_t *attr) 1035084Sjohnlev { 1048453SAnurag.Maskey@Sun.COM int rc; 1055084Sjohnlev vnic_ioc_create_t ioc; 1068275SEric Cheng dladm_status_t status = DLADM_STATUS_OK; 1075084Sjohnlev 1088275SEric Cheng bzero(&ioc, sizeof (ioc)); 1098275SEric Cheng ioc.vc_vnic_id = attr->va_vnic_id; 1108275SEric Cheng ioc.vc_link_id = attr->va_link_id; 1118275SEric Cheng ioc.vc_mac_addr_type = attr->va_mac_addr_type; 1128275SEric Cheng ioc.vc_mac_len = attr->va_mac_len; 1138275SEric Cheng ioc.vc_mac_slot = attr->va_mac_slot; 1148275SEric Cheng ioc.vc_mac_prefix_len = attr->va_mac_prefix_len; 1158275SEric Cheng ioc.vc_vid = attr->va_vid; 11611076SCathy.Zhou@Sun.COM ioc.vc_vrid = attr->va_vrid; 11711076SCathy.Zhou@Sun.COM ioc.vc_af = attr->va_af; 1188275SEric Cheng ioc.vc_flags = attr->va_force ? VNIC_IOC_CREATE_FORCE : 0; 1195084Sjohnlev 1208275SEric Cheng if (attr->va_mac_len > 0 || ioc.vc_mac_prefix_len > 0) 1218275SEric Cheng bcopy(attr->va_mac_addr, ioc.vc_mac_addr, MAXMACADDRLEN); 1228275SEric Cheng bcopy(&attr->va_resource_props, &ioc.vc_resource_props, 1238275SEric Cheng sizeof (mac_resource_props_t)); 1248275SEric Cheng if (attr->va_link_id == DATALINK_INVALID_LINKID) 1258275SEric Cheng ioc.vc_flags |= VNIC_IOC_CREATE_ANCHOR; 1265084Sjohnlev 1278453SAnurag.Maskey@Sun.COM rc = ioctl(dladm_dld_fd(handle), VNIC_IOC_CREATE, &ioc); 1288275SEric Cheng if (rc < 0) 1298275SEric Cheng status = dladm_errno2status(errno); 1308275SEric Cheng 1318275SEric Cheng if (status != DLADM_STATUS_OK) { 1328275SEric Cheng if (ioc.vc_diag != VNIC_IOC_DIAG_NONE) 1338275SEric Cheng status = dladm_vnic_diag2status(ioc.vc_diag); 1348275SEric Cheng } 1358275SEric Cheng if (status != DLADM_STATUS_OK) 1368275SEric Cheng return (status); 1378275SEric Cheng 1388275SEric Cheng attr->va_mac_addr_type = ioc.vc_mac_addr_type; 1398275SEric Cheng switch (ioc.vc_mac_addr_type) { 1408275SEric Cheng case VNIC_MAC_ADDR_TYPE_FACTORY: 1418275SEric Cheng attr->va_mac_slot = ioc.vc_mac_slot; 1428275SEric Cheng break; 1438275SEric Cheng case VNIC_MAC_ADDR_TYPE_RANDOM: 1448275SEric Cheng bcopy(ioc.vc_mac_addr, attr->va_mac_addr, MAXMACADDRLEN); 1458275SEric Cheng attr->va_mac_len = ioc.vc_mac_len; 1468275SEric Cheng break; 1478275SEric Cheng } 1488275SEric Cheng return (status); 1498275SEric Cheng } 1508275SEric Cheng 1518275SEric Cheng /* 1528275SEric Cheng * Get the configuration information of the given VNIC. 1538275SEric Cheng */ 1548275SEric Cheng static dladm_status_t 1558453SAnurag.Maskey@Sun.COM i_dladm_vnic_info_active(dladm_handle_t handle, datalink_id_t linkid, 1568453SAnurag.Maskey@Sun.COM dladm_vnic_attr_t *attrp) 1578275SEric Cheng { 1588275SEric Cheng vnic_ioc_info_t ioc; 1598275SEric Cheng vnic_info_t *vnic; 1608453SAnurag.Maskey@Sun.COM int rc; 1618275SEric Cheng dladm_status_t status = DLADM_STATUS_OK; 1628275SEric Cheng 1638275SEric Cheng bzero(&ioc, sizeof (ioc)); 1648275SEric Cheng vnic = &ioc.vi_info; 1658275SEric Cheng vnic->vn_vnic_id = linkid; 1668275SEric Cheng 1678453SAnurag.Maskey@Sun.COM rc = ioctl(dladm_dld_fd(handle), VNIC_IOC_INFO, &ioc); 1688275SEric Cheng if (rc != 0) { 1698275SEric Cheng status = dladm_errno2status(errno); 1708275SEric Cheng goto bail; 1718275SEric Cheng } 1728275SEric Cheng 1738275SEric Cheng attrp->va_vnic_id = vnic->vn_vnic_id; 1748275SEric Cheng attrp->va_link_id = vnic->vn_link_id; 1758275SEric Cheng attrp->va_mac_addr_type = vnic->vn_mac_addr_type; 1768275SEric Cheng bcopy(vnic->vn_mac_addr, attrp->va_mac_addr, MAXMACADDRLEN); 1778275SEric Cheng attrp->va_mac_len = vnic->vn_mac_len; 1788275SEric Cheng attrp->va_mac_slot = vnic->vn_mac_slot; 1798275SEric Cheng attrp->va_mac_prefix_len = vnic->vn_mac_prefix_len; 1808275SEric Cheng attrp->va_vid = vnic->vn_vid; 18111076SCathy.Zhou@Sun.COM attrp->va_vrid = vnic->vn_vrid; 18211076SCathy.Zhou@Sun.COM attrp->va_af = vnic->vn_af; 1838275SEric Cheng attrp->va_force = vnic->vn_force; 1848275SEric Cheng 1858275SEric Cheng bail: 1868275SEric Cheng return (status); 1878275SEric Cheng } 1888275SEric Cheng 1898275SEric Cheng static dladm_status_t 1908453SAnurag.Maskey@Sun.COM i_dladm_vnic_info_persist(dladm_handle_t handle, datalink_id_t linkid, 1918453SAnurag.Maskey@Sun.COM dladm_vnic_attr_t *attrp) 1928275SEric Cheng { 1938275SEric Cheng dladm_conf_t conf; 1948275SEric Cheng dladm_status_t status; 1958275SEric Cheng char macstr[ETHERADDRL * 3]; 19610616SSebastien.Roy@Sun.COM char linkover[MAXLINKNAMELEN]; 1978275SEric Cheng uint64_t u64; 1988275SEric Cheng datalink_class_t class; 1998275SEric Cheng 2008275SEric Cheng attrp->va_vnic_id = linkid; 201*12824SCathy.Zhou@Sun.COM if ((status = dladm_getsnap_conf(handle, linkid, &conf)) != 2028453SAnurag.Maskey@Sun.COM DLADM_STATUS_OK) 2038275SEric Cheng return (status); 2048275SEric Cheng 20510616SSebastien.Roy@Sun.COM status = dladm_get_conf_field(handle, conf, FLINKOVER, linkover, 20610616SSebastien.Roy@Sun.COM sizeof (linkover)); 20710616SSebastien.Roy@Sun.COM if (status != DLADM_STATUS_OK) { 20810616SSebastien.Roy@Sun.COM /* 20910616SSebastien.Roy@Sun.COM * This isn't an error, etherstubs don't have a FLINKOVER 21010616SSebastien.Roy@Sun.COM * property. 21110616SSebastien.Roy@Sun.COM */ 21210616SSebastien.Roy@Sun.COM attrp->va_link_id = DATALINK_INVALID_LINKID; 21310616SSebastien.Roy@Sun.COM } else { 21410616SSebastien.Roy@Sun.COM if ((status = dladm_name2info(handle, linkover, 21510616SSebastien.Roy@Sun.COM &attrp->va_link_id, NULL, NULL, NULL)) != DLADM_STATUS_OK) 21610616SSebastien.Roy@Sun.COM goto done; 21710616SSebastien.Roy@Sun.COM } 2188275SEric Cheng 2198453SAnurag.Maskey@Sun.COM if ((status = dladm_datalink_id2info(handle, linkid, NULL, &class, 2208275SEric Cheng NULL, NULL, 0)) != DLADM_STATUS_OK) 2218275SEric Cheng goto done; 2228275SEric Cheng 2238275SEric Cheng if (class == DATALINK_CLASS_VLAN) { 2248275SEric Cheng if (attrp->va_link_id == DATALINK_INVALID_LINKID) { 2258275SEric Cheng status = DLADM_STATUS_BADARG; 2268275SEric Cheng goto done; 2278275SEric Cheng } 2288275SEric Cheng attrp->va_mac_addr_type = VNIC_MAC_ADDR_TYPE_PRIMARY; 2298275SEric Cheng attrp->va_mac_len = 0; 2308275SEric Cheng } else { 2318453SAnurag.Maskey@Sun.COM status = dladm_get_conf_field(handle, conf, FMADDRTYPE, &u64, 2328275SEric Cheng sizeof (u64)); 2338275SEric Cheng if (status != DLADM_STATUS_OK) 2348275SEric Cheng goto done; 2358275SEric Cheng 2368275SEric Cheng attrp->va_mac_addr_type = (vnic_mac_addr_type_t)u64; 2378275SEric Cheng 23811076SCathy.Zhou@Sun.COM if ((status = dladm_get_conf_field(handle, conf, FVRID, 23911076SCathy.Zhou@Sun.COM &u64, sizeof (u64))) != DLADM_STATUS_OK) { 24011076SCathy.Zhou@Sun.COM attrp->va_vrid = VRRP_VRID_NONE; 24111076SCathy.Zhou@Sun.COM } else { 24211076SCathy.Zhou@Sun.COM attrp->va_vrid = (vrid_t)u64; 24311076SCathy.Zhou@Sun.COM } 24411076SCathy.Zhou@Sun.COM 24511076SCathy.Zhou@Sun.COM if ((status = dladm_get_conf_field(handle, conf, FVRAF, 24611076SCathy.Zhou@Sun.COM &u64, sizeof (u64))) != DLADM_STATUS_OK) { 24711076SCathy.Zhou@Sun.COM attrp->va_af = AF_UNSPEC; 24811076SCathy.Zhou@Sun.COM } else { 24911076SCathy.Zhou@Sun.COM attrp->va_af = (int)u64; 25011076SCathy.Zhou@Sun.COM } 25111076SCathy.Zhou@Sun.COM 2528453SAnurag.Maskey@Sun.COM status = dladm_get_conf_field(handle, conf, FMADDRLEN, &u64, 2538275SEric Cheng sizeof (u64)); 2548275SEric Cheng attrp->va_mac_len = ((status == DLADM_STATUS_OK) ? 2558275SEric Cheng (uint_t)u64 : ETHERADDRL); 2568275SEric Cheng 2578453SAnurag.Maskey@Sun.COM status = dladm_get_conf_field(handle, conf, FMADDRSLOT, &u64, 2588275SEric Cheng sizeof (u64)); 2598275SEric Cheng attrp->va_mac_slot = ((status == DLADM_STATUS_OK) ? 2608275SEric Cheng (int)u64 : -1); 2618275SEric Cheng 2628453SAnurag.Maskey@Sun.COM status = dladm_get_conf_field(handle, conf, FMADDRPREFIXLEN, 2638453SAnurag.Maskey@Sun.COM &u64, sizeof (u64)); 2648275SEric Cheng attrp->va_mac_prefix_len = ((status == DLADM_STATUS_OK) ? 2658275SEric Cheng (uint_t)u64 : sizeof (dladm_vnic_def_prefix)); 2668275SEric Cheng 2678453SAnurag.Maskey@Sun.COM status = dladm_get_conf_field(handle, conf, FMACADDR, macstr, 2688275SEric Cheng sizeof (macstr)); 2698275SEric Cheng if (status != DLADM_STATUS_OK) 2708275SEric Cheng goto done; 2718275SEric Cheng 2728275SEric Cheng status = dladm_vnic_str2macaddr(macstr, attrp->va_mac_addr); 2738275SEric Cheng if (status != DLADM_STATUS_OK) 2748275SEric Cheng goto done; 2758275SEric Cheng } 2768275SEric Cheng 2778453SAnurag.Maskey@Sun.COM status = dladm_get_conf_field(handle, conf, FVLANID, &u64, 2788453SAnurag.Maskey@Sun.COM sizeof (u64)); 2798275SEric Cheng attrp->va_vid = ((status == DLADM_STATUS_OK) ? (uint16_t)u64 : 0); 2808275SEric Cheng 2818275SEric Cheng status = DLADM_STATUS_OK; 2828275SEric Cheng done: 2838453SAnurag.Maskey@Sun.COM dladm_destroy_conf(handle, conf); 2848275SEric Cheng return (status); 2858275SEric Cheng } 2868275SEric Cheng 2878275SEric Cheng dladm_status_t 2888453SAnurag.Maskey@Sun.COM dladm_vnic_info(dladm_handle_t handle, datalink_id_t linkid, 2898453SAnurag.Maskey@Sun.COM dladm_vnic_attr_t *attrp, uint32_t flags) 2908275SEric Cheng { 2918275SEric Cheng if (flags == DLADM_OPT_ACTIVE) 2928453SAnurag.Maskey@Sun.COM return (i_dladm_vnic_info_active(handle, linkid, attrp)); 2938275SEric Cheng else if (flags == DLADM_OPT_PERSIST) 2948453SAnurag.Maskey@Sun.COM return (i_dladm_vnic_info_persist(handle, linkid, attrp)); 2958275SEric Cheng else 2968275SEric Cheng return (DLADM_STATUS_BADARG); 2978275SEric Cheng } 2988275SEric Cheng 2998275SEric Cheng /* 3008275SEric Cheng * Remove a VNIC from the kernel. 3018275SEric Cheng */ 3028275SEric Cheng dladm_status_t 3038453SAnurag.Maskey@Sun.COM i_dladm_vnic_delete_sys(dladm_handle_t handle, datalink_id_t linkid) 3048275SEric Cheng { 3058275SEric Cheng vnic_ioc_delete_t ioc; 3068275SEric Cheng dladm_status_t status = DLADM_STATUS_OK; 3078453SAnurag.Maskey@Sun.COM int rc; 3088275SEric Cheng 3098275SEric Cheng ioc.vd_vnic_id = linkid; 3108275SEric Cheng 3118453SAnurag.Maskey@Sun.COM rc = ioctl(dladm_dld_fd(handle), VNIC_IOC_DELETE, &ioc); 3128275SEric Cheng if (rc < 0) 3137408SSebastien.Roy@Sun.COM status = dladm_errno2status(errno); 3145084Sjohnlev 3157408SSebastien.Roy@Sun.COM return (status); 3165084Sjohnlev } 3175084Sjohnlev 3185084Sjohnlev /* 3195084Sjohnlev * Convert between MAC address types and their string representations. 3205084Sjohnlev */ 3215084Sjohnlev 3225084Sjohnlev typedef struct dladm_vnic_addr_type_s { 3238275SEric Cheng const char *va_str; 3248275SEric Cheng vnic_mac_addr_type_t va_type; 3255084Sjohnlev } dladm_vnic_addr_type_t; 3265084Sjohnlev 3275084Sjohnlev static dladm_vnic_addr_type_t addr_types[] = { 3285084Sjohnlev {"fixed", VNIC_MAC_ADDR_TYPE_FIXED}, 3298275SEric Cheng {"random", VNIC_MAC_ADDR_TYPE_RANDOM}, 3308275SEric Cheng {"factory", VNIC_MAC_ADDR_TYPE_FACTORY}, 3318275SEric Cheng {"auto", VNIC_MAC_ADDR_TYPE_AUTO}, 33211076SCathy.Zhou@Sun.COM {"fixed", VNIC_MAC_ADDR_TYPE_PRIMARY}, 33311076SCathy.Zhou@Sun.COM {"vrrp", VNIC_MAC_ADDR_TYPE_VRID} 3345084Sjohnlev }; 3355084Sjohnlev 3365084Sjohnlev #define NADDR_TYPES (sizeof (addr_types) / sizeof (dladm_vnic_addr_type_t)) 3375084Sjohnlev 3388275SEric Cheng static const char * 3398275SEric Cheng dladm_vnic_macaddrtype2str(vnic_mac_addr_type_t type) 3408275SEric Cheng { 3418275SEric Cheng int i; 3428275SEric Cheng 3438275SEric Cheng for (i = 0; i < NADDR_TYPES; i++) { 3448275SEric Cheng if (type == addr_types[i].va_type) 3458275SEric Cheng return (addr_types[i].va_str); 3468275SEric Cheng } 3478275SEric Cheng return (NULL); 3488275SEric Cheng } 3498275SEric Cheng 3505895Syz147064 dladm_status_t 3515895Syz147064 dladm_vnic_str2macaddrtype(const char *str, vnic_mac_addr_type_t *val) 3525084Sjohnlev { 3535084Sjohnlev int i; 3545084Sjohnlev dladm_vnic_addr_type_t *type; 3555084Sjohnlev 3565084Sjohnlev for (i = 0; i < NADDR_TYPES; i++) { 3575084Sjohnlev type = &addr_types[i]; 3585084Sjohnlev if (strncmp(str, type->va_str, strlen(type->va_str)) == 0) { 3595084Sjohnlev *val = type->va_type; 3605895Syz147064 return (DLADM_STATUS_OK); 3615084Sjohnlev } 3625084Sjohnlev } 3635895Syz147064 return (DLADM_STATUS_BADARG); 3645084Sjohnlev } 3655084Sjohnlev 3665084Sjohnlev /* 36711076SCathy.Zhou@Sun.COM * Based on the VRRP specification, the virtual router MAC address associated 36811076SCathy.Zhou@Sun.COM * with a virtual router is an IEEE 802 MAC address in the following format: 36911076SCathy.Zhou@Sun.COM * 37011076SCathy.Zhou@Sun.COM * IPv4 case: 00-00-5E-00-01-{VRID} (in hex in internet standard bit-order) 37111076SCathy.Zhou@Sun.COM * 37211076SCathy.Zhou@Sun.COM * IPv6 case: 00-00-5E-00-02-{VRID} (in hex in internet standard bit-order) 37311076SCathy.Zhou@Sun.COM */ 37411076SCathy.Zhou@Sun.COM static dladm_status_t 37511076SCathy.Zhou@Sun.COM i_dladm_vnic_vrrp_mac(vrid_t vrid, int af, uint8_t *mac, uint_t maclen) 37611076SCathy.Zhou@Sun.COM { 37711076SCathy.Zhou@Sun.COM if (maclen < ETHERADDRL || vrid < VRRP_VRID_MIN || 37811076SCathy.Zhou@Sun.COM vrid > VRRP_VRID_MAX || (af != AF_INET && af != AF_INET6)) { 37911076SCathy.Zhou@Sun.COM return (DLADM_STATUS_BADARG); 38011076SCathy.Zhou@Sun.COM } 38111076SCathy.Zhou@Sun.COM 38211076SCathy.Zhou@Sun.COM mac[0] = mac[1] = mac[3] = 0x0; 38311076SCathy.Zhou@Sun.COM mac[2] = 0x5e; 38411076SCathy.Zhou@Sun.COM mac[4] = (af == AF_INET) ? 0x01 : 0x02; 38511076SCathy.Zhou@Sun.COM mac[5] = vrid; 38611076SCathy.Zhou@Sun.COM return (DLADM_STATUS_OK); 38711076SCathy.Zhou@Sun.COM } 38811076SCathy.Zhou@Sun.COM 38911076SCathy.Zhou@Sun.COM /* 3908275SEric Cheng * Create a new VNIC / VLAN. Update the configuration file and bring it up. 39111076SCathy.Zhou@Sun.COM * The "vrid" and "af" arguments are only required if the mac_addr_type is 39211076SCathy.Zhou@Sun.COM * VNIC_MAC_ADDR_TYPE_VRID. In that case, the MAC address will be caculated 39311076SCathy.Zhou@Sun.COM * based on the above algorithm. 3945084Sjohnlev */ 3955084Sjohnlev dladm_status_t 3968453SAnurag.Maskey@Sun.COM dladm_vnic_create(dladm_handle_t handle, const char *vnic, datalink_id_t linkid, 39711076SCathy.Zhou@Sun.COM vnic_mac_addr_type_t mac_addr_type, uchar_t *mac_addr, uint_t mac_len, 39811076SCathy.Zhou@Sun.COM int *mac_slot, uint_t mac_prefix_len, uint16_t vid, vrid_t vrid, 39911076SCathy.Zhou@Sun.COM int af, datalink_id_t *vnic_id_out, dladm_arg_list_t *proplist, 40011076SCathy.Zhou@Sun.COM uint32_t flags) 4015084Sjohnlev { 4028275SEric Cheng dladm_vnic_attr_t attr; 4035895Syz147064 datalink_id_t vnic_id; 4045895Syz147064 datalink_class_t class; 4058275SEric Cheng uint32_t media = DL_ETHER; 4068275SEric Cheng char name[MAXLINKNAMELEN]; 4078275SEric Cheng uchar_t tmp_addr[MAXMACADDRLEN]; 4085084Sjohnlev dladm_status_t status; 4098275SEric Cheng boolean_t is_vlan; 4108275SEric Cheng boolean_t is_etherstub; 4118275SEric Cheng int i; 41210491SRishi.Srivatsavai@Sun.COM boolean_t vnic_created = B_FALSE; 41310491SRishi.Srivatsavai@Sun.COM boolean_t conf_set = B_FALSE; 4145084Sjohnlev 4155084Sjohnlev /* 4165084Sjohnlev * Sanity test arguments. 4175084Sjohnlev */ 4188275SEric Cheng if ((flags & DLADM_OPT_ACTIVE) == 0) 4198275SEric Cheng return (DLADM_STATUS_NOTSUP); 4208275SEric Cheng 4218275SEric Cheng is_vlan = ((flags & DLADM_OPT_VLAN) != 0); 4228275SEric Cheng if (is_vlan && ((vid < 1 || vid > 4094))) 4238275SEric Cheng return (DLADM_STATUS_VIDINVAL); 4248275SEric Cheng 4258275SEric Cheng is_etherstub = (linkid == DATALINK_INVALID_LINKID); 4265084Sjohnlev 4278275SEric Cheng if (!dladm_vnic_macaddrtype2str(mac_addr_type)) 4285084Sjohnlev return (DLADM_STATUS_INVALIDMACADDRTYPE); 4295084Sjohnlev 43011076SCathy.Zhou@Sun.COM if ((flags & DLADM_OPT_ANCHOR) == 0) { 43111076SCathy.Zhou@Sun.COM if ((status = dladm_datalink_id2info(handle, linkid, NULL, 43211076SCathy.Zhou@Sun.COM &class, &media, NULL, 0)) != DLADM_STATUS_OK) 43311076SCathy.Zhou@Sun.COM return (status); 43411076SCathy.Zhou@Sun.COM 43511076SCathy.Zhou@Sun.COM if (class == DATALINK_CLASS_VNIC || 43611076SCathy.Zhou@Sun.COM class == DATALINK_CLASS_VLAN) 43711076SCathy.Zhou@Sun.COM return (DLADM_STATUS_BADARG); 43811076SCathy.Zhou@Sun.COM } else { 43911076SCathy.Zhou@Sun.COM /* it's an anchor VNIC */ 44011076SCathy.Zhou@Sun.COM if (linkid != DATALINK_INVALID_LINKID || vid != 0) 44111076SCathy.Zhou@Sun.COM return (DLADM_STATUS_BADARG); 44211076SCathy.Zhou@Sun.COM } 44311076SCathy.Zhou@Sun.COM 44411076SCathy.Zhou@Sun.COM /* 44511076SCathy.Zhou@Sun.COM * Only VRRP VNIC need VRID and address family specified. 44611076SCathy.Zhou@Sun.COM */ 44711076SCathy.Zhou@Sun.COM if (mac_addr_type != VNIC_MAC_ADDR_TYPE_VRID && 44811076SCathy.Zhou@Sun.COM (af != AF_UNSPEC || vrid != VRRP_VRID_NONE)) { 44911076SCathy.Zhou@Sun.COM return (DLADM_STATUS_BADARG); 45011076SCathy.Zhou@Sun.COM } 45111076SCathy.Zhou@Sun.COM 4528275SEric Cheng /* 4538275SEric Cheng * If a random address might be generated, but no prefix 4548275SEric Cheng * was specified by the caller, use the default MAC address 4558275SEric Cheng * prefix. 4568275SEric Cheng */ 4578275SEric Cheng if ((mac_addr_type == VNIC_MAC_ADDR_TYPE_RANDOM || 4588275SEric Cheng mac_addr_type == VNIC_MAC_ADDR_TYPE_AUTO) && 4598275SEric Cheng mac_prefix_len == 0) { 4608275SEric Cheng mac_prefix_len = sizeof (dladm_vnic_def_prefix); 4618275SEric Cheng mac_addr = tmp_addr; 4628275SEric Cheng bcopy(dladm_vnic_def_prefix, mac_addr, mac_prefix_len); 4635895Syz147064 } 4645895Syz147064 46511076SCathy.Zhou@Sun.COM /* 46611076SCathy.Zhou@Sun.COM * If this is a VRRP VNIC, generate its MAC address using the given 46711076SCathy.Zhou@Sun.COM * VRID and address family. 46811076SCathy.Zhou@Sun.COM */ 46911076SCathy.Zhou@Sun.COM if (mac_addr_type == VNIC_MAC_ADDR_TYPE_VRID) { 47011076SCathy.Zhou@Sun.COM /* 47111076SCathy.Zhou@Sun.COM * VRRP VNICs must be created over ethernet data-links. 47211076SCathy.Zhou@Sun.COM */ 47311076SCathy.Zhou@Sun.COM if (vrid < VRRP_VRID_MIN || vrid > VRRP_VRID_MAX || 47411076SCathy.Zhou@Sun.COM (af != AF_INET && af != AF_INET6) || mac_addr != NULL || 47511076SCathy.Zhou@Sun.COM mac_len != 0 || mac_prefix_len != 0 || 47611076SCathy.Zhou@Sun.COM (mac_slot != NULL && *mac_slot != -1) || is_etherstub || 47711076SCathy.Zhou@Sun.COM media != DL_ETHER) { 47811076SCathy.Zhou@Sun.COM return (DLADM_STATUS_BADARG); 47911076SCathy.Zhou@Sun.COM } 48011076SCathy.Zhou@Sun.COM mac_len = ETHERADDRL; 48111076SCathy.Zhou@Sun.COM mac_addr = tmp_addr; 48211076SCathy.Zhou@Sun.COM status = i_dladm_vnic_vrrp_mac(vrid, af, mac_addr, mac_len); 48311076SCathy.Zhou@Sun.COM if (status != DLADM_STATUS_OK) 4848275SEric Cheng return (status); 48511076SCathy.Zhou@Sun.COM } 4868275SEric Cheng 48711076SCathy.Zhou@Sun.COM if (mac_len > MAXMACADDRLEN) 48811076SCathy.Zhou@Sun.COM return (DLADM_STATUS_INVALIDMACADDRLEN); 4895084Sjohnlev 4905895Syz147064 if (vnic == NULL) { 4915895Syz147064 flags |= DLADM_OPT_PREFIX; 4928275SEric Cheng (void) strlcpy(name, "vnic", sizeof (name)); 4938275SEric Cheng } else { 4948275SEric Cheng (void) strlcpy(name, vnic, sizeof (name)); 4955895Syz147064 } 4965895Syz147064 4978275SEric Cheng class = is_vlan ? DATALINK_CLASS_VLAN : 4988275SEric Cheng (is_etherstub ? DATALINK_CLASS_ETHERSTUB : DATALINK_CLASS_VNIC); 4998453SAnurag.Maskey@Sun.COM if ((status = dladm_create_datalink_id(handle, name, class, 5008275SEric Cheng media, flags, &vnic_id)) != DLADM_STATUS_OK) 5015895Syz147064 return (status); 5028275SEric Cheng 5038275SEric Cheng if ((flags & DLADM_OPT_PREFIX) != 0) { 5048275SEric Cheng (void) snprintf(name + 4, sizeof (name), "%llu", vnic_id); 5058275SEric Cheng flags &= ~DLADM_OPT_PREFIX; 5065084Sjohnlev } 5075084Sjohnlev 5085084Sjohnlev bzero(&attr, sizeof (attr)); 5098275SEric Cheng 5108275SEric Cheng /* Extract resource_ctl and cpu_list from proplist */ 5118275SEric Cheng if (proplist != NULL) { 5128453SAnurag.Maskey@Sun.COM status = dladm_link_proplist_extract(handle, proplist, 51311878SVenu.Iyer@Sun.COM &attr.va_resource_props, 0); 5148275SEric Cheng if (status != DLADM_STATUS_OK) 5158275SEric Cheng goto done; 5168275SEric Cheng } 5175084Sjohnlev 5188275SEric Cheng attr.va_vnic_id = vnic_id; 5198275SEric Cheng attr.va_link_id = linkid; 5208275SEric Cheng attr.va_mac_addr_type = mac_addr_type; 5218275SEric Cheng attr.va_mac_len = mac_len; 5228275SEric Cheng if (mac_slot != NULL) 5238275SEric Cheng attr.va_mac_slot = *mac_slot; 5248275SEric Cheng if (mac_len > 0) 5258275SEric Cheng bcopy(mac_addr, attr.va_mac_addr, mac_len); 5268275SEric Cheng else if (mac_prefix_len > 0) 5278275SEric Cheng bcopy(mac_addr, attr.va_mac_addr, mac_prefix_len); 5288275SEric Cheng attr.va_mac_prefix_len = mac_prefix_len; 5298275SEric Cheng attr.va_vid = vid; 53011076SCathy.Zhou@Sun.COM attr.va_vrid = vrid; 53111076SCathy.Zhou@Sun.COM attr.va_af = af; 5328275SEric Cheng attr.va_force = (flags & DLADM_OPT_FORCE) != 0; 5338275SEric Cheng 5348453SAnurag.Maskey@Sun.COM status = i_dladm_vnic_create_sys(handle, &attr); 5358275SEric Cheng if (status != DLADM_STATUS_OK) 5368275SEric Cheng goto done; 53710491SRishi.Srivatsavai@Sun.COM vnic_created = B_TRUE; 5388275SEric Cheng 5398275SEric Cheng /* Save vnic configuration and its properties */ 5408275SEric Cheng if (!(flags & DLADM_OPT_PERSIST)) 5418275SEric Cheng goto done; 5428275SEric Cheng 5438453SAnurag.Maskey@Sun.COM status = dladm_vnic_persist_conf(handle, name, &attr, class); 54410491SRishi.Srivatsavai@Sun.COM if (status != DLADM_STATUS_OK) 5455895Syz147064 goto done; 54610491SRishi.Srivatsavai@Sun.COM conf_set = B_TRUE; 5475895Syz147064 5488275SEric Cheng if (proplist != NULL) { 5498275SEric Cheng for (i = 0; i < proplist->al_count; i++) { 5508275SEric Cheng dladm_arg_info_t *aip = &proplist->al_info[i]; 5518275SEric Cheng 5528453SAnurag.Maskey@Sun.COM status = dladm_set_linkprop(handle, vnic_id, 5538453SAnurag.Maskey@Sun.COM aip->ai_name, aip->ai_val, aip->ai_count, 5548453SAnurag.Maskey@Sun.COM DLADM_OPT_PERSIST); 5558275SEric Cheng if (status != DLADM_STATUS_OK) 5568275SEric Cheng break; 5578275SEric Cheng } 5588275SEric Cheng } 5595084Sjohnlev 5605895Syz147064 done: 5615895Syz147064 if (status != DLADM_STATUS_OK) { 56210491SRishi.Srivatsavai@Sun.COM if (conf_set) 56310491SRishi.Srivatsavai@Sun.COM (void) dladm_remove_conf(handle, vnic_id); 56410491SRishi.Srivatsavai@Sun.COM if (vnic_created) 56510491SRishi.Srivatsavai@Sun.COM (void) i_dladm_vnic_delete_sys(handle, vnic_id); 5668453SAnurag.Maskey@Sun.COM (void) dladm_destroy_datalink_id(handle, vnic_id, flags); 5675895Syz147064 } else { 5688275SEric Cheng if (vnic_id_out != NULL) 5698275SEric Cheng *vnic_id_out = vnic_id; 5708275SEric Cheng if (mac_slot != NULL) 5718275SEric Cheng *mac_slot = attr.va_mac_slot; 5725895Syz147064 } 57310491SRishi.Srivatsavai@Sun.COM 57410491SRishi.Srivatsavai@Sun.COM if (is_vlan) { 57510491SRishi.Srivatsavai@Sun.COM dladm_status_t stat2; 57610491SRishi.Srivatsavai@Sun.COM 57710491SRishi.Srivatsavai@Sun.COM stat2 = dladm_bridge_refresh(handle, linkid); 57810491SRishi.Srivatsavai@Sun.COM if (status == DLADM_STATUS_OK && stat2 != DLADM_STATUS_OK) 57910491SRishi.Srivatsavai@Sun.COM status = stat2; 58010491SRishi.Srivatsavai@Sun.COM } 5815084Sjohnlev return (status); 5825084Sjohnlev } 5835084Sjohnlev 5845084Sjohnlev /* 5858275SEric Cheng * Delete a VNIC / VLAN. 5865084Sjohnlev */ 5875084Sjohnlev dladm_status_t 5888453SAnurag.Maskey@Sun.COM dladm_vnic_delete(dladm_handle_t handle, datalink_id_t linkid, uint32_t flags) 5895084Sjohnlev { 5908275SEric Cheng dladm_status_t status; 5918275SEric Cheng datalink_class_t class; 5928275SEric Cheng 5938275SEric Cheng if (flags == 0) 5948275SEric Cheng return (DLADM_STATUS_BADARG); 5955084Sjohnlev 5968453SAnurag.Maskey@Sun.COM if ((dladm_datalink_id2info(handle, linkid, NULL, &class, NULL, NULL, 0) 5978453SAnurag.Maskey@Sun.COM != DLADM_STATUS_OK)) 5988275SEric Cheng return (DLADM_STATUS_BADARG); 5995084Sjohnlev 6008275SEric Cheng if ((flags & DLADM_OPT_VLAN) != 0) { 6018275SEric Cheng if (class != DATALINK_CLASS_VLAN) 6028275SEric Cheng return (DLADM_STATUS_BADARG); 6038275SEric Cheng } else { 6048275SEric Cheng if (class != DATALINK_CLASS_VNIC && 6058275SEric Cheng class != DATALINK_CLASS_ETHERSTUB) 6068275SEric Cheng return (DLADM_STATUS_BADARG); 6075084Sjohnlev } 6085084Sjohnlev 6098275SEric Cheng if ((flags & DLADM_OPT_ACTIVE) != 0) { 6108453SAnurag.Maskey@Sun.COM status = i_dladm_vnic_delete_sys(handle, linkid); 6118275SEric Cheng if (status == DLADM_STATUS_OK) { 6128453SAnurag.Maskey@Sun.COM (void) dladm_set_linkprop(handle, linkid, NULL, NULL, 0, 6138275SEric Cheng DLADM_OPT_ACTIVE); 6148453SAnurag.Maskey@Sun.COM (void) dladm_destroy_datalink_id(handle, linkid, 6158275SEric Cheng DLADM_OPT_ACTIVE); 6168275SEric Cheng } else if (status != DLADM_STATUS_NOTFOUND || 6178275SEric Cheng !(flags & DLADM_OPT_PERSIST)) { 6188275SEric Cheng return (status); 6198275SEric Cheng } 6208275SEric Cheng } 6218275SEric Cheng if ((flags & DLADM_OPT_PERSIST) != 0) { 62210616SSebastien.Roy@Sun.COM (void) dladm_remove_conf(handle, linkid); 6238453SAnurag.Maskey@Sun.COM (void) dladm_destroy_datalink_id(handle, linkid, 6248453SAnurag.Maskey@Sun.COM DLADM_OPT_PERSIST); 6258275SEric Cheng } 62610491SRishi.Srivatsavai@Sun.COM return (dladm_bridge_refresh(handle, linkid)); 6278275SEric Cheng } 6288275SEric Cheng 6298275SEric Cheng static const char * 6308275SEric Cheng dladm_vnic_macaddr2str(const uchar_t *mac, char *buf) 6318275SEric Cheng { 6328275SEric Cheng static char unknown_mac[] = {0, 0, 0, 0, 0, 0}; 6338275SEric Cheng 6348275SEric Cheng if (buf == NULL) 6358275SEric Cheng return (NULL); 6368275SEric Cheng 6378275SEric Cheng if (bcmp(unknown_mac, mac, ETHERADDRL) == 0) 6388275SEric Cheng (void) strlcpy(buf, "unknown", DLADM_STRSIZE); 6398275SEric Cheng else 6408275SEric Cheng return (_link_ntoa(mac, buf, ETHERADDRL, IFT_OTHER)); 6418275SEric Cheng 6428275SEric Cheng return (buf); 6438275SEric Cheng } 6448275SEric Cheng 6458275SEric Cheng static dladm_status_t 6468275SEric Cheng dladm_vnic_str2macaddr(const char *str, uchar_t *buf) 6478275SEric Cheng { 6488275SEric Cheng int len = 0; 6498275SEric Cheng uchar_t *b = _link_aton(str, &len); 6508275SEric Cheng 6518275SEric Cheng if (b == NULL || len >= MAXMACADDRLEN) 6528275SEric Cheng return (DLADM_STATUS_BADARG); 6538275SEric Cheng 6548275SEric Cheng bcopy(b, buf, len); 6558275SEric Cheng free(b); 6568275SEric Cheng return (DLADM_STATUS_OK); 6575084Sjohnlev } 6585084Sjohnlev 6595084Sjohnlev 6608275SEric Cheng static dladm_status_t 6618453SAnurag.Maskey@Sun.COM dladm_vnic_persist_conf(dladm_handle_t handle, const char *name, 6628453SAnurag.Maskey@Sun.COM dladm_vnic_attr_t *attrp, datalink_class_t class) 6638275SEric Cheng { 664*12824SCathy.Zhou@Sun.COM dladm_conf_t conf; 6658275SEric Cheng dladm_status_t status; 6668275SEric Cheng char macstr[ETHERADDRL * 3]; 66710616SSebastien.Roy@Sun.COM char linkover[MAXLINKNAMELEN]; 6688275SEric Cheng uint64_t u64; 6695084Sjohnlev 6708453SAnurag.Maskey@Sun.COM if ((status = dladm_create_conf(handle, name, attrp->va_vnic_id, 6718275SEric Cheng class, DL_ETHER, &conf)) != DLADM_STATUS_OK) 6725895Syz147064 return (status); 6735895Syz147064 6748275SEric Cheng if (attrp->va_link_id != DATALINK_INVALID_LINKID) { 67510616SSebastien.Roy@Sun.COM status = dladm_datalink_id2info(handle, attrp->va_link_id, NULL, 67610616SSebastien.Roy@Sun.COM NULL, NULL, linkover, sizeof (linkover)); 67710616SSebastien.Roy@Sun.COM if (status != DLADM_STATUS_OK) 67810616SSebastien.Roy@Sun.COM goto done; 6798453SAnurag.Maskey@Sun.COM status = dladm_set_conf_field(handle, conf, FLINKOVER, 68010616SSebastien.Roy@Sun.COM DLADM_TYPE_STR, linkover); 6818275SEric Cheng if (status != DLADM_STATUS_OK) 6828275SEric Cheng goto done; 6838275SEric Cheng } 6848275SEric Cheng 6858275SEric Cheng if (class != DATALINK_CLASS_VLAN) { 6868275SEric Cheng u64 = attrp->va_mac_addr_type; 6878453SAnurag.Maskey@Sun.COM status = dladm_set_conf_field(handle, conf, FMADDRTYPE, 6888275SEric Cheng DLADM_TYPE_UINT64, &u64); 6898275SEric Cheng if (status != DLADM_STATUS_OK) 6908275SEric Cheng goto done; 6918275SEric Cheng 69211076SCathy.Zhou@Sun.COM u64 = attrp->va_vrid; 69311076SCathy.Zhou@Sun.COM status = dladm_set_conf_field(handle, conf, FVRID, 69411076SCathy.Zhou@Sun.COM DLADM_TYPE_UINT64, &u64); 69511076SCathy.Zhou@Sun.COM if (status != DLADM_STATUS_OK) 69611076SCathy.Zhou@Sun.COM goto done; 69711076SCathy.Zhou@Sun.COM 69811076SCathy.Zhou@Sun.COM u64 = attrp->va_af; 69911076SCathy.Zhou@Sun.COM status = dladm_set_conf_field(handle, conf, FVRAF, 70011076SCathy.Zhou@Sun.COM DLADM_TYPE_UINT64, &u64); 70111076SCathy.Zhou@Sun.COM if (status != DLADM_STATUS_OK) 70211076SCathy.Zhou@Sun.COM goto done; 70311076SCathy.Zhou@Sun.COM 7048275SEric Cheng if (attrp->va_mac_len != ETHERADDRL) { 7058275SEric Cheng u64 = attrp->va_mac_len; 7068453SAnurag.Maskey@Sun.COM status = dladm_set_conf_field(handle, conf, FMADDRLEN, 7078275SEric Cheng DLADM_TYPE_UINT64, &u64); 7088275SEric Cheng if (status != DLADM_STATUS_OK) 7098275SEric Cheng goto done; 7108275SEric Cheng } 7118275SEric Cheng 7128275SEric Cheng if (attrp->va_mac_slot != -1) { 7138275SEric Cheng u64 = attrp->va_mac_slot; 71411076SCathy.Zhou@Sun.COM status = dladm_set_conf_field(handle, conf, 71511076SCathy.Zhou@Sun.COM FMADDRSLOT, DLADM_TYPE_UINT64, &u64); 7168275SEric Cheng if (status != DLADM_STATUS_OK) 7178275SEric Cheng goto done; 7188275SEric Cheng } 7198275SEric Cheng 7208275SEric Cheng if (attrp->va_mac_prefix_len != 7218275SEric Cheng sizeof (dladm_vnic_def_prefix)) { 7228275SEric Cheng u64 = attrp->va_mac_prefix_len; 7238453SAnurag.Maskey@Sun.COM status = dladm_set_conf_field(handle, conf, 7248453SAnurag.Maskey@Sun.COM FMADDRPREFIXLEN, DLADM_TYPE_UINT64, &u64); 7258275SEric Cheng if (status != DLADM_STATUS_OK) 7268275SEric Cheng goto done; 7278275SEric Cheng } 7288275SEric Cheng 7298275SEric Cheng (void) dladm_vnic_macaddr2str(attrp->va_mac_addr, macstr); 7308453SAnurag.Maskey@Sun.COM status = dladm_set_conf_field(handle, conf, FMACADDR, 7318453SAnurag.Maskey@Sun.COM DLADM_TYPE_STR, macstr); 7328275SEric Cheng if (status != DLADM_STATUS_OK) 7338275SEric Cheng goto done; 7348275SEric Cheng } 7358275SEric Cheng 7368275SEric Cheng if (attrp->va_vid != 0) { 7378275SEric Cheng u64 = attrp->va_vid; 7388453SAnurag.Maskey@Sun.COM status = dladm_set_conf_field(handle, conf, FVLANID, 7398275SEric Cheng DLADM_TYPE_UINT64, &u64); 7408275SEric Cheng if (status != DLADM_STATUS_OK) 7418275SEric Cheng goto done; 7428275SEric Cheng } 7438275SEric Cheng 7448275SEric Cheng /* 7458275SEric Cheng * Commit the link configuration. 7468275SEric Cheng */ 7478453SAnurag.Maskey@Sun.COM status = dladm_write_conf(handle, conf); 7488275SEric Cheng 7498275SEric Cheng done: 7508453SAnurag.Maskey@Sun.COM dladm_destroy_conf(handle, conf); 7515895Syz147064 return (status); 7525084Sjohnlev } 7538275SEric Cheng 7548275SEric Cheng typedef struct dladm_vnic_up_arg_s { 7558275SEric Cheng uint32_t flags; 7568275SEric Cheng dladm_status_t status; 7578275SEric Cheng } dladm_vnic_up_arg_t; 7588275SEric Cheng 7598275SEric Cheng static int 7608453SAnurag.Maskey@Sun.COM i_dladm_vnic_up(dladm_handle_t handle, datalink_id_t linkid, void *arg) 7618275SEric Cheng { 7628275SEric Cheng dladm_status_t *statusp = &(((dladm_vnic_up_arg_t *)arg)->status); 7638275SEric Cheng dladm_vnic_attr_t attr; 7648275SEric Cheng dladm_status_t status; 7658275SEric Cheng dladm_arg_list_t *proplist; 7668275SEric Cheng 7678275SEric Cheng bzero(&attr, sizeof (attr)); 7688275SEric Cheng 7698453SAnurag.Maskey@Sun.COM status = dladm_vnic_info(handle, linkid, &attr, DLADM_OPT_PERSIST); 7708275SEric Cheng if (status != DLADM_STATUS_OK) 7718275SEric Cheng goto done; 7728275SEric Cheng 7738275SEric Cheng /* Get all properties for this vnic */ 7748453SAnurag.Maskey@Sun.COM status = dladm_link_get_proplist(handle, linkid, &proplist); 7758275SEric Cheng if (status != DLADM_STATUS_OK) 7768275SEric Cheng goto done; 7778275SEric Cheng 7788275SEric Cheng if (proplist != NULL) { 7798453SAnurag.Maskey@Sun.COM status = dladm_link_proplist_extract(handle, proplist, 78011878SVenu.Iyer@Sun.COM &attr.va_resource_props, DLADM_OPT_BOOT); 7818275SEric Cheng } 7828275SEric Cheng 7838453SAnurag.Maskey@Sun.COM status = i_dladm_vnic_create_sys(handle, &attr); 78410491SRishi.Srivatsavai@Sun.COM if (status == DLADM_STATUS_OK) { 78510491SRishi.Srivatsavai@Sun.COM status = dladm_up_datalink_id(handle, linkid); 78610491SRishi.Srivatsavai@Sun.COM if (status != DLADM_STATUS_OK) 78710491SRishi.Srivatsavai@Sun.COM (void) i_dladm_vnic_delete_sys(handle, linkid); 78810491SRishi.Srivatsavai@Sun.COM } 7898275SEric Cheng 7908275SEric Cheng done: 7918275SEric Cheng *statusp = status; 7928275SEric Cheng return (DLADM_WALK_CONTINUE); 7938275SEric Cheng } 7948275SEric Cheng 7958275SEric Cheng dladm_status_t 7968453SAnurag.Maskey@Sun.COM dladm_vnic_up(dladm_handle_t handle, datalink_id_t linkid, uint32_t flags) 7978275SEric Cheng { 7988275SEric Cheng dladm_vnic_up_arg_t vnic_arg; 7998275SEric Cheng datalink_class_t class; 8008275SEric Cheng 8018275SEric Cheng class = ((flags & DLADM_OPT_VLAN) != 0) ? DATALINK_CLASS_VLAN : 8028275SEric Cheng (DATALINK_CLASS_VNIC | DATALINK_CLASS_ETHERSTUB); 8038275SEric Cheng 8048275SEric Cheng if (linkid == DATALINK_ALL_LINKID) { 8058453SAnurag.Maskey@Sun.COM (void) dladm_walk_datalink_id(i_dladm_vnic_up, handle, 8068453SAnurag.Maskey@Sun.COM &vnic_arg, class, DATALINK_ANY_MEDIATYPE, 8078453SAnurag.Maskey@Sun.COM DLADM_OPT_PERSIST); 8088275SEric Cheng return (DLADM_STATUS_OK); 8098275SEric Cheng } else { 8108453SAnurag.Maskey@Sun.COM (void) i_dladm_vnic_up(handle, linkid, &vnic_arg); 8118275SEric Cheng return (vnic_arg.status); 8128275SEric Cheng } 8138275SEric Cheng } 814