diff options
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/cmd/dladm/dladm.c | 115 | ||||
-rw-r--r-- | usr/src/cmd/dlmgmtd/dlmgmt_db.c | 23 | ||||
-rw-r--r-- | usr/src/cmd/dlmgmtd/dlmgmt_door.c | 20 | ||||
-rw-r--r-- | usr/src/cmd/dlmgmtd/dlmgmt_util.c | 16 | ||||
-rw-r--r-- | usr/src/cmd/ibd_upgrade/ibd_delete_link.c | 2 | ||||
-rw-r--r-- | usr/src/cmd/zoneadmd/vplat.c | 10 | ||||
-rw-r--r-- | usr/src/lib/brand/joyent/zone/poststate.ksh | 139 | ||||
-rw-r--r-- | usr/src/lib/brand/joyent/zone/prestate.ksh | 122 | ||||
-rw-r--r-- | usr/src/lib/libdladm/common/libdllink.c | 28 | ||||
-rw-r--r-- | usr/src/lib/libdladm/common/libdllink.h | 6 | ||||
-rw-r--r-- | usr/src/lib/libdladm/common/libdlmgmt.c | 20 | ||||
-rw-r--r-- | usr/src/lib/libdladm/common/libdlvnic.c | 20 | ||||
-rw-r--r-- | usr/src/lib/libdladm/common/mapfile-vers | 2 | ||||
-rw-r--r-- | usr/src/uts/common/io/dld/dld_drv.c | 3 | ||||
-rw-r--r-- | usr/src/uts/common/io/dls/dls_mgmt.c | 38 | ||||
-rw-r--r-- | usr/src/uts/common/sys/dld.h | 2 | ||||
-rw-r--r-- | usr/src/uts/common/sys/dls.h | 3 | ||||
-rw-r--r-- | usr/src/uts/common/sys/dls_mgmt.h | 2 |
18 files changed, 362 insertions, 209 deletions
diff --git a/usr/src/cmd/dladm/dladm.c b/usr/src/cmd/dladm/dladm.c index 8efdb32d0e..c368a8c21b 100644 --- a/usr/src/cmd/dladm/dladm.c +++ b/usr/src/cmd/dladm/dladm.c @@ -20,6 +20,7 @@ */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011 Joyent Inc. All rights reserved. */ #include <stdio.h> @@ -154,6 +155,7 @@ typedef struct show_vnic_state { dladm_status_t vs_status; uint32_t vs_flags; ofmt_handle_t vs_ofmt; + char *vs_zonename; } show_vnic_state_t; typedef struct show_part_state { @@ -265,7 +267,7 @@ typedef struct cmd { static cmd_t cmds[] = { { "rename-link", do_rename_link, - " rename-link <oldlink> <newlink>" }, + " rename-link [-z zonename] <oldlink> <newlink>" }, { "show-link", do_show_link, " show-link [-pP] [-o <field>,..] [-s [-i <interval>]] " "[<link>]\n" }, @@ -300,12 +302,13 @@ static cmd_t cmds[] = { { "show-wifi", do_show_wifi, " show-wifi [-p] [-o <field>,...] [<link>]\n" }, { "set-linkprop", do_set_linkprop, - " set-linkprop [-t] -p <prop>=<value>[,...] <name>" }, + " set-linkprop [-t] [-z zonename] -p <prop>=<value>[,...] " + "<name>" }, { "reset-linkprop", do_reset_linkprop, - " reset-linkprop [-t] [-p <prop>,...] <name>" }, + " reset-linkprop [-t] [-z zonename] [-p <prop>,...] <name>"}, { "show-linkprop", do_show_linkprop, - " show-linkprop [-cP] [-o <field>,...] [-p <prop>,...] " - "<name>\n" }, + " show-linkprop [-cP] [-o <field>,...] [-z zonename] " + "[-p <prop>,...] <name>\n" }, { "show-ether", do_show_ether, " show-ether [-px][-o <field>,...] <link>\n" }, { "create-secobj", do_create_secobj, @@ -346,10 +349,10 @@ static cmd_t cmds[] = { "\t\t {vrrp -V <vrid> -A {inet | inet6}} [-v <vid> [-f]]\n" "\t\t [-p <prop>=<value>[,...]] <vnic-link>" }, { "delete-vnic", do_delete_vnic, - " delete-vnic [-t] <vnic-link>" }, + " delete-vnic [-t] [-z zonename] <vnic-link>" }, { "show-vnic", do_show_vnic, - " show-vnic [-pP] [-l <link>] [-s [-i <interval>]] " - "[<link>]\n" }, + " show-vnic [-pP] [-l <link>] [-z zonename] " + "[-s [-i <interval>]] [<link>]\n" }, { "up-vnic", do_up_vnic, NULL }, { "create-part", do_create_part, " create-part [-t] [-f] -l <link> [-P <pkey>]\n" @@ -1010,21 +1013,24 @@ typedef struct vnic_fields_buf_s char vnic_macaddr[18]; char vnic_macaddrtype[19]; char vnic_vid[6]; + char vnic_zone[ZONENAME_MAX]; } vnic_fields_buf_t; static const ofmt_field_t vnic_fields[] = { { "LINK", 13, offsetof(vnic_fields_buf_t, vnic_link), print_default_cb}, -{ "OVER", 13, +{ "OVER", 11, offsetof(vnic_fields_buf_t, vnic_over), print_default_cb}, -{ "SPEED", 7, +{ "SPEED", 6, offsetof(vnic_fields_buf_t, vnic_speed), print_default_cb}, { "MACADDRESS", 18, offsetof(vnic_fields_buf_t, vnic_macaddr), print_default_cb}, -{ "MACADDRTYPE", 20, +{ "MACADDRTYPE", 12, offsetof(vnic_fields_buf_t, vnic_macaddrtype), print_default_cb}, -{ "VID", 7, +{ "VID", 5, offsetof(vnic_fields_buf_t, vnic_vid), print_default_cb}, +{ "ZONE", 20, + offsetof(vnic_fields_buf_t, vnic_zone), print_default_cb}, { NULL, 0, 0, NULL}} ; @@ -2494,13 +2500,17 @@ do_rename_link(int argc, char *argv[], const char *use) char *link1, *link2; char *altroot = NULL; dladm_status_t status; + char *zonename = NULL; opterr = 0; - while ((option = getopt_long(argc, argv, ":R:", lopts, NULL)) != -1) { + while ((option = getopt_long(argc, argv, ":R:z:", lopts, NULL)) != -1) { switch (option) { case 'R': altroot = optarg; break; + case 'z': + zonename = optarg; + break; default: die_opterr(optopt, option, use); break; @@ -2516,7 +2526,7 @@ do_rename_link(int argc, char *argv[], const char *use) link1 = argv[optind++]; link2 = argv[optind]; - if ((status = dladm_rename_link(handle, link1, link2)) != + if ((status = dladm_rename_link(handle, zonename, link1, link2)) != DLADM_STATUS_OK) die_dlerr(status, "rename operation failed"); } @@ -3406,11 +3416,12 @@ do_show_link(int argc, char *argv[], const char *use) ofmt_handle_t ofmt; ofmt_status_t oferr; uint_t ofmtflags = 0; + char *zonename = NULL; bzero(&state, sizeof (state)); opterr = 0; - while ((option = getopt_long(argc, argv, ":pPsSi:o:", + while ((option = getopt_long(argc, argv, ":pPsSi:o:z:", show_lopts, NULL)) != -1) { switch (option) { case 'p': @@ -3449,6 +3460,9 @@ do_show_link(int argc, char *argv[], const char *use) if (!dladm_str2interval(optarg, &interval)) die("invalid interval value '%s'", optarg); break; + case 'z': + zonename = optarg; + break; default: die_opterr(optopt, option, use); break; @@ -3474,8 +3488,8 @@ do_show_link(int argc, char *argv[], const char *use) if (strlcpy(linkname, argv[optind], MAXLINKNAMELEN) >= MAXLINKNAMELEN) die("link name too long"); - if ((status = dladm_name2info(handle, linkname, &linkid, &f, - NULL, NULL)) != DLADM_STATUS_OK) { + if ((status = dladm_zname2info(handle, zonename, linkname, + &linkid, &f, NULL, NULL)) != DLADM_STATUS_OK) { die_dlerr(status, "link %s is not valid", linkname); } @@ -4831,9 +4845,10 @@ do_delete_vnic_common(int argc, char *argv[], const char *use, datalink_id_t linkid; char *altroot = NULL; dladm_status_t status; + char *zonename = NULL; opterr = 0; - while ((option = getopt_long(argc, argv, ":R:t", lopts, + while ((option = getopt_long(argc, argv, ":R:tz:", lopts, NULL)) != -1) { switch (option) { case 't': @@ -4842,6 +4857,9 @@ do_delete_vnic_common(int argc, char *argv[], const char *use, case 'R': altroot = optarg; break; + case 'z': + zonename = optarg; + break; default: die_opterr(optopt, option, use); } @@ -4854,8 +4872,8 @@ do_delete_vnic_common(int argc, char *argv[], const char *use, if (altroot != NULL) altroot_cmd(altroot, argc, argv); - status = dladm_name2info(handle, argv[optind], &linkid, NULL, NULL, - NULL); + status = dladm_zname2info(handle, zonename, argv[optind], &linkid, NULL, + NULL, NULL); if (status != DLADM_STATUS_OK) die("invalid link name '%s'", argv[optind]); @@ -4987,6 +5005,9 @@ print_vnic(show_vnic_state_t *state, datalink_id_t linkid) char vnic_name[MAXLINKNAMELEN]; char mstr[MAXMACADDRLEN * 3]; vnic_fields_buf_t vbuf; + uint_t valcnt = 1; + char zonename[DLADM_PROP_VAL_MAX + 1]; + char *valptr[1]; if ((status = dladm_vnic_info(handle, linkid, vnic, state->vs_flags)) != DLADM_STATUS_OK) @@ -5016,6 +5037,18 @@ print_vnic(show_vnic_state_t *state, datalink_id_t linkid) NULL, devname, sizeof (devname)) != DLADM_STATUS_OK) (void) sprintf(devname, "?"); + + zonename[0] = '\0'; + if (!is_etherstub) { + valptr[0] = zonename; + (void) dladm_get_linkprop(handle, linkid, + DLADM_PROP_VAL_CURRENT, "zone", (char **)valptr, &valcnt); + } + + if (state->vs_zonename != NULL && + strcmp(state->vs_zonename, zonename) != 0) + return (DLADM_STATUS_OK); + state->vs_found = B_TRUE; if (state->vs_stats) { /* print vnic statistics */ @@ -5091,6 +5124,13 @@ print_vnic(show_vnic_state_t *state, datalink_id_t linkid) (void) snprintf(vbuf.vnic_vid, sizeof (vbuf.vnic_vid), "%d", vnic->va_vid); + + if (zonename[0] != '\0') + (void) snprintf(vbuf.vnic_zone, + sizeof (vbuf.vnic_zone), "%s", zonename); + else + (void) strlcpy(vbuf.vnic_zone, "--", + sizeof (vbuf.vnic_zone)); } ofmt_print(state->vs_ofmt, &vbuf); @@ -5129,10 +5169,11 @@ do_show_vnic_common(int argc, char *argv[], const char *use, ofmt_handle_t ofmt; ofmt_status_t oferr; uint_t ofmtflags = 0; + char *zonename = NULL; bzero(&state, sizeof (state)); opterr = 0; - while ((option = getopt_long(argc, argv, ":pPl:si:o:", lopts, + while ((option = getopt_long(argc, argv, ":pPl:si:o:z:", lopts, NULL)) != -1) { switch (option) { case 'p': @@ -5171,6 +5212,9 @@ do_show_vnic_common(int argc, char *argv[], const char *use, o_arg = B_TRUE; fields_str = optarg; break; + case 'z': + zonename = optarg; + break; default: die_opterr(optopt, option, use); } @@ -5181,8 +5225,8 @@ do_show_vnic_common(int argc, char *argv[], const char *use, /* get vnic ID (optional last argument) */ if (optind == (argc - 1)) { - status = dladm_name2info(handle, argv[optind], &linkid, NULL, - NULL, NULL); + status = dladm_zname2info(handle, zonename, argv[optind], + &linkid, NULL, NULL, NULL); if (status != DLADM_STATUS_OK) { die_dlerr(status, "invalid vnic name '%s'", argv[optind]); @@ -5193,8 +5237,8 @@ do_show_vnic_common(int argc, char *argv[], const char *use, } if (l_arg) { - status = dladm_name2info(handle, state.vs_link, &dev_linkid, - NULL, NULL, NULL); + status = dladm_zname2info(handle, zonename, state.vs_link, + &dev_linkid, NULL, NULL, NULL); if (status != DLADM_STATUS_OK) { die_dlerr(status, "invalid link name '%s'", state.vs_link); @@ -5206,6 +5250,7 @@ do_show_vnic_common(int argc, char *argv[], const char *use, state.vs_etherstub = etherstub; state.vs_found = B_FALSE; state.vs_flags = flags; + state.vs_zonename = zonename; if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) { if (etherstub) @@ -6694,6 +6739,7 @@ do_show_linkprop(int argc, char **argv, const char *use) ofmt_handle_t ofmt; ofmt_status_t oferr; uint_t ofmtflags = 0; + char *zonename = NULL; bzero(propstr, DLADM_STRSIZE); opterr = 0; @@ -6704,7 +6750,7 @@ do_show_linkprop(int argc, char **argv, const char *use) state.ls_header = B_TRUE; state.ls_retstatus = DLADM_STATUS_OK; - while ((option = getopt_long(argc, argv, ":p:cPo:", + while ((option = getopt_long(argc, argv, ":p:cPo:z:", prop_longopts, NULL)) != -1) { switch (option) { case 'p': @@ -6723,6 +6769,9 @@ do_show_linkprop(int argc, char **argv, const char *use) case 'o': fields_str = optarg; break; + case 'z': + zonename = optarg; + break; default: die_opterr(optopt, option, use); break; @@ -6730,8 +6779,8 @@ do_show_linkprop(int argc, char **argv, const char *use) } if (optind == (argc - 1)) { - if ((status = dladm_name2info(handle, argv[optind], &linkid, - NULL, NULL, NULL)) != DLADM_STATUS_OK) { + if ((status = dladm_zname2info(handle, zonename, argv[optind], + &linkid, NULL, NULL, NULL)) != DLADM_STATUS_OK) { die_dlerr(status, "link %s is not valid", argv[optind]); } } else if (optind != argc) { @@ -6868,11 +6917,12 @@ set_linkprop(int argc, char **argv, boolean_t reset, const char *use) dladm_status_t status = DLADM_STATUS_OK; char propstr[DLADM_STRSIZE]; dladm_arg_list_t *proplist = NULL; + char *zonename = NULL; opterr = 0; bzero(propstr, DLADM_STRSIZE); - while ((option = getopt_long(argc, argv, ":p:R:t", + while ((option = getopt_long(argc, argv, ":p:R:tz:", prop_longopts, NULL)) != -1) { switch (option) { case 'p': @@ -6887,6 +6937,9 @@ set_linkprop(int argc, char **argv, boolean_t reset, const char *use) case 'R': altroot = optarg; break; + case 'z': + zonename = optarg; + break; default: die_opterr(optopt, option, use); @@ -6909,8 +6962,8 @@ set_linkprop(int argc, char **argv, boolean_t reset, const char *use) altroot_cmd(altroot, argc, argv); } - status = dladm_name2info(handle, argv[optind], &linkid, NULL, NULL, - NULL); + status = dladm_zname2info(handle, zonename, argv[optind], &linkid, + NULL, NULL, NULL); if (status != DLADM_STATUS_OK) die_dlerr(status, "link %s is not valid", argv[optind]); diff --git a/usr/src/cmd/dlmgmtd/dlmgmt_db.c b/usr/src/cmd/dlmgmtd/dlmgmt_db.c index 99307dbc03..7838322f42 100644 --- a/usr/src/cmd/dlmgmtd/dlmgmt_db.c +++ b/usr/src/cmd/dlmgmtd/dlmgmt_db.c @@ -21,6 +21,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, Joyent Inc. All rights reserved. */ #include <assert.h> @@ -43,6 +44,7 @@ #include <libcontract.h> #include <libcontract_priv.h> #include <sys/contract/process.h> +#include <sys/vnic.h> #include "dlmgmt_impl.h" typedef enum dlmgmt_db_op { @@ -1451,8 +1453,29 @@ dlmgmt_db_fini(zoneid_t zoneid) while (linkp != NULL) { next_linkp = AVL_NEXT(&dlmgmt_name_avl, linkp); if (linkp->ll_zoneid == zoneid) { + vnic_ioc_delete_t ioc; + boolean_t onloan; + + ioc.vd_vnic_id = linkp->ll_linkid; + onloan = linkp->ll_onloan; + + /* + * Cleanup any VNICs that were loaned to the zone + * before the zone goes away and we can no longer + * refer to the VNIC by the name/zoneid. + */ + if (onloan) + (void) dlmgmt_delete_db_entry(linkp, + DLMGMT_ACTIVE); + (void) dlmgmt_destroy_common(linkp, DLMGMT_ACTIVE | DLMGMT_PERSIST); + + if (onloan && ioctl(dladm_dld_fd(dld_handle), + VNIC_IOC_DELETE, &ioc) < 0) + dlmgmt_log(LOG_WARNING, "dlmgmt_db_fini " + "delete VNIC ioctl failed %d %d", + ioc.vd_vnic_id, errno); } linkp = next_linkp; } diff --git a/usr/src/cmd/dlmgmtd/dlmgmt_door.c b/usr/src/cmd/dlmgmtd/dlmgmt_door.c index 11e4329669..b80ffcc280 100644 --- a/usr/src/cmd/dlmgmtd/dlmgmt_door.c +++ b/usr/src/cmd/dlmgmtd/dlmgmt_door.c @@ -21,6 +21,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, Joyent Inc. All rights reserved. */ /* @@ -439,6 +440,10 @@ dlmgmt_getlinkid(void *argp, void *retp, size_t *sz, zoneid_t zoneid, dlmgmt_link_t *linkp; int err = 0; + /* Enable the global zone to lookup links it has given away. */ + if (zoneid == GLOBAL_ZONEID && getlinkid->ld_zoneid != -1) + zoneid = getlinkid->ld_zoneid; + /* * Hold the reader lock to access the link */ @@ -1245,7 +1250,19 @@ dlmgmt_setzoneid(void *argp, void *retp, size_t *sz, zoneid_t zoneid, "zone %d: %s", linkid, oldzoneid, strerror(err)); goto done; } - avl_remove(&dlmgmt_loan_avl, linkp); + + if (newzoneid == GLOBAL_ZONEID && linkp->ll_onloan) { + /* + * We can only reassign a loaned VNIC back to the + * global zone when the zone is shutting down, since + * otherwise the VNIC is in use by the zone and will be + * busy. Leave the VNIC assigned to the zone so we can + * still see it and delete it when dlmgmt_zonehalt() + * runs. + */ + goto done; + } + linkp->ll_onloan = B_FALSE; } if (newzoneid != GLOBAL_ZONEID) { @@ -1256,7 +1273,6 @@ dlmgmt_setzoneid(void *argp, void *retp, size_t *sz, zoneid_t zoneid, (void) zone_add_datalink(oldzoneid, linkid); goto done; } - avl_add(&dlmgmt_loan_avl, linkp); linkp->ll_onloan = B_TRUE; } diff --git a/usr/src/cmd/dlmgmtd/dlmgmt_util.c b/usr/src/cmd/dlmgmtd/dlmgmt_util.c index 004c8f257b..a2d9800b7b 100644 --- a/usr/src/cmd/dlmgmtd/dlmgmt_util.c +++ b/usr/src/cmd/dlmgmtd/dlmgmt_util.c @@ -21,6 +21,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, Joyent Inc. All rights reserved. */ /* @@ -45,13 +46,10 @@ /* * There are three datalink AVL tables. The dlmgmt_name_avl tree contains all * datalinks and is keyed by zoneid and link name. The dlmgmt_id_avl also - * contains all datalinks, and it is keyed by link ID. The dlmgmt_loan_avl is - * keyed by link name, and contains the set of global-zone links that are - * currently on loan to non-global zones. + * contains all datalinks, and it is keyed by link ID. */ avl_tree_t dlmgmt_name_avl; avl_tree_t dlmgmt_id_avl; -avl_tree_t dlmgmt_loan_avl; avl_tree_t dlmgmt_dlconf_avl; @@ -162,8 +160,6 @@ dlmgmt_linktable_init(void) offsetof(dlmgmt_link_t, ll_name_node)); avl_create(&dlmgmt_id_avl, cmp_link_by_id, sizeof (dlmgmt_link_t), offsetof(dlmgmt_link_t, ll_id_node)); - avl_create(&dlmgmt_loan_avl, cmp_link_by_name, sizeof (dlmgmt_link_t), - offsetof(dlmgmt_link_t, ll_loan_node)); avl_create(&dlmgmt_dlconf_avl, cmp_dlconf_by_id, sizeof (dlmgmt_dlconf_t), offsetof(dlmgmt_dlconf_t, ld_node)); dlmgmt_nextlinkid = 1; @@ -181,7 +177,6 @@ dlmgmt_linktable_fini(void) avl_destroy(&dlmgmt_dlconf_avl); avl_destroy(&dlmgmt_name_avl); - avl_destroy(&dlmgmt_loan_avl); avl_destroy(&dlmgmt_id_avl); } @@ -385,7 +380,6 @@ link_activate(dlmgmt_link_t *linkp) linkp->ll_zoneid = zoneid; avl_add(&dlmgmt_name_avl, linkp); - avl_add(&dlmgmt_loan_avl, linkp); linkp->ll_onloan = B_TRUE; } } else if (linkp->ll_zoneid != GLOBAL_ZONEID) { @@ -429,10 +423,6 @@ link_by_name(const char *name, zoneid_t zoneid) (void) strlcpy(link.ll_link, name, MAXLINKNAMELEN); link.ll_zoneid = zoneid; linkp = avl_find(&dlmgmt_name_avl, &link, NULL); - if (linkp == NULL && zoneid == GLOBAL_ZONEID) { - /* The link could be on loan to a non-global zone? */ - linkp = avl_find(&dlmgmt_loan_avl, &link, NULL); - } return (linkp); } @@ -510,8 +500,6 @@ dlmgmt_destroy_common(dlmgmt_link_t *linkp, uint32_t flags) if ((flags & DLMGMT_ACTIVE) && linkp->ll_zoneid != GLOBAL_ZONEID) { (void) zone_remove_datalink(linkp->ll_zoneid, linkp->ll_linkid); - if (linkp->ll_onloan) - avl_remove(&dlmgmt_loan_avl, linkp); } if (linkp->ll_flags == 0) { diff --git a/usr/src/cmd/ibd_upgrade/ibd_delete_link.c b/usr/src/cmd/ibd_upgrade/ibd_delete_link.c index b9d10a56cd..f63630207d 100644 --- a/usr/src/cmd/ibd_upgrade/ibd_delete_link.c +++ b/usr/src/cmd/ibd_upgrade/ibd_delete_link.c @@ -21,6 +21,7 @@ /* * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, Joyent Inc. All rights reserved. */ #include <stdio.h> @@ -86,6 +87,7 @@ ibd_delete_link(dladm_handle_t dlh, char *link) getlinkid.ld_cmd = DLMGMT_CMD_GETLINKID; (void) strlcpy(getlinkid.ld_link, link, MAXLINKNAMELEN); + getlinkid.ld_zoneid = -1; if ((status = ibd_dladm_door_call(dlh, &getlinkid, sizeof (getlinkid), &retval, sizeof (retval))) != DLADM_STATUS_OK) { diff --git a/usr/src/cmd/zoneadmd/vplat.c b/usr/src/cmd/zoneadmd/vplat.c index 70cb1c4d75..d708567764 100644 --- a/usr/src/cmd/zoneadmd/vplat.c +++ b/usr/src/cmd/zoneadmd/vplat.c @@ -2947,12 +2947,10 @@ configure_exclusive_network_interfaces(zlog_t *zlogp, zoneid_t zoneid) nwiftab.zone_nwif_physical) == 0) { added = B_TRUE; } else { - char emsg[80 + LIFNAMSIZ]; - - (void) snprintf(emsg, sizeof (emsg), - "failed to add network device %s", - nwiftab.zone_nwif_physical); - zerror(zlogp, B_FALSE, emsg); + /* + * Failed to add network device, but the brand hook + * might be doing this for us, so keep silent. + */ continue; } /* set up the new IP interface, and add them all later */ diff --git a/usr/src/lib/brand/joyent/zone/poststate.ksh b/usr/src/lib/brand/joyent/zone/poststate.ksh index bad727516a..694c3820c7 100644 --- a/usr/src/lib/brand/joyent/zone/poststate.ksh +++ b/usr/src/lib/brand/joyent/zone/poststate.ksh @@ -27,6 +27,8 @@ unset LD_LIBRARY_PATH PATH=/usr/bin:/usr/sbin export PATH +. /lib/sdc/config.sh + # state # ZONE_STATE_CONFIGURED 0 (script will never see this) # ZONE_STATE_INCOMPLETE 1 (script will never see this) @@ -49,13 +51,144 @@ state=$3 cmd=$4 ALTROOT=$5 -# We only do work if we're halting the zone. -(( $cmd != 4 )) && exit 0; +# Only do the rest of the script if we're readying the zone. +(( $cmd != 0 )) && exit 0 + +# +# Set up the vnic(s) for the zone. +# + +# Load sysinfo variables with SYSINFO_ prefix +load_sdc_sysinfo +# Load config variables with CONFIG_ prefix, and sets the headnode variable +load_sdc_config for nic in $_ZONECFG_net_resources do - dladm delete-vnic $nic + # Get simplified versions of the network config. variables. + address=$(eval echo \$_ZONECFG_net_${nic}_address) + dhcp_server=$(eval echo \$_ZONECFG_net_${nic}_dhcp_server) + global_nic=$(eval echo \$_ZONECFG_net_${nic}_global_nic) + mac_addr=$(eval echo \$_ZONECFG_net_${nic}_mac_addr) + vlan_id=$(eval echo \$_ZONECFG_net_${nic}_vlan_id) + blocked_outgoing_ports=$(eval echo \$_ZONECFG_net_${nic}_blocked_outgoing_ports) + + # If address set, must be a shared stack zone + [[ -n $address ]] && exit 0 + + # If no global-nic, must be a dedicated physical NIC instead of a vnic + [[ -z $global_nic ]] && continue + + orig_global=$global_nic + [[ "$global_nic" == "admin" ]] && global_nic=$SYSINFO_NIC_admin + [[ "$global_nic" == "external" ]] && global_nic=$SYSINFO_NIC_external + [[ "$global_nic" == "internal" ]] && global_nic=$SYSINFO_NIC_internal + + # For backwards compatibility with the other parts of the + # system, check if this zone already has this vnic setup. + # If so, move on to the next vnic. + dladm show-vnic -p -o LINK -z $ZONENAME $nic >/dev/null 2>&1 + (( $? == 0 )) && continue + + if [[ -z $global_nic ]]; then + echo "skipping undefined VNIC $nic (global NIC $orig_global)" + logger -p daemon.err "zone $ZONENAME skipping undefined " \ + "VNIC $nic (global NIC $orig_global)" + continue + fi + + # + # Create the vnic. + # + + opt_str="-p zone=$ZONENAME" + [[ -n $mac_addr ]] && opt_str="$opt_str -m $mac_addr" + + [[ -n $vlan_id && $vlan_id != 0 ]] && opt_str="$opt_str -v $vlan_id" + + # + # Creating a VNIC in a zone is a multi-step process internally. + # This means there is a short window where the VNIC exists in the + # global zone and that could lead to a race condition if two zones + # boot at the same time with the same VNIC name. Use a temp. name + # to create the VNIC then rename it to have the correct name. + # + tname=${ZONENAME}0 + dout=`dladm create-vnic -t -l $global_nic $opt_str $tname 2>&1` + if (( $? != 0 )); then + echo "error creating VNIC $nic (global NIC $orig_global)" + echo "msg: $dout" + logger -p daemon.err "zone $ZONENAME error creating " \ + "VNIC $nic (global NIC $orig_global $global_nic)" + logger -p daemon.err "msg: $dout" + logger -p daemon.err "Failed cmd: dladm create-vnic -t -l " \ + "$global_nic $opt_str $tname" + exit 1 + fi + dladm rename-link -z $ZONENAME $tname $nic + + if [[ -z $mac_addr ]]; then + # There was no assigned mac address + + # Get newly assigned mac address. + mac_addr=$(dladm show-vnic -z $ZONENAME -p -o MACADDRESS ${nic}) + + # Save newly assigned mac address + [[ -n $mac_addr ]] && zonecfg -z $ZONENAME \ + "select net physical=$nic; " \ + "set mac-addr=$mac_addr; end; exit" + fi + + if [[ -n $dhcp_server ]]; then + spoof_opts="mac-nospoof" + else + # XXX For backwards compatibility, special handling for zone + # named "dhcpd". Remove this check once property is added to + # zone. + if [[ $ZONENAME == "dhcpd" ]]; then + spoof_opts="mac-nospoof" + else + # Enable full antispoof if the zone is not a dhcp server. + spoof_opts="ip-nospoof,mac-nospoof,restricted,dhcp-nospoof" + fi + fi + dladm set-linkprop -t -z $ZONENAME -p "protection=${spoof_opts}" ${nic} + + # Get the static IP for the vnic from the zone config file. + hostname_file="/zones/$ZONENAME/root/etc/hostname.$nic" + if [ -e $hostname_file ]; then + zone_ip=`nawk '{if ($1 ~ /[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/) + print $1}' $hostname_file` + + [[ -n "${zone_ip}" ]] && dladm set-linkprop -t -z $ZONENAME \ + -p "allowed-ips=${zone_ip}" ${nic} + + fi + + # If on VMWare and we have external IPs, create a bridge to allow + # zones to reach the external gateway + if [[ ${headnode} == "true" && ${orig_global} == "external" && \ + "${SYSINFO_Product}" == "VMware Virtual Platform" ]]; then + dladm show-bridge -p -o BRIDGE vmwareextbr >/dev/null 2>&1 + (( $? != 0 )) && dladm create-bridge \ + -l ${SYSINFO_NIC_external} vmwareextbr + fi + + if [[ -n $blocked_outgoing_ports ]]; then + OLDIFS=$IFS + IFS=, + for port in $blocked_outgoing_ports; do + # br='block remote'. Flow names should be < 31 chars + # in length so that they get unique kstats + flowadm add-flow -l $nic \ + -a transport=tcp,remote_port=$port \ + -p maxbw=0 ${nic}_br_${port} + done + IFS=$OLDIFS + fi + done + exit 0 diff --git a/usr/src/lib/brand/joyent/zone/prestate.ksh b/usr/src/lib/brand/joyent/zone/prestate.ksh index 8ff75bccae..2c5b7bd1b5 100644 --- a/usr/src/lib/brand/joyent/zone/prestate.ksh +++ b/usr/src/lib/brand/joyent/zone/prestate.ksh @@ -67,126 +67,4 @@ fi # Force zone snapshots to get mounted ls $ZONEPATH/.zfs/snapshot/* >/dev/null 2>&1 -# -# Finish by setting up the vnic(s) for the zone. -# - -# Load sysinfo variables with SYSINFO_ prefix -load_sdc_sysinfo -# Load config variables with CONFIG_ prefix, and sets the headnode variable -load_sdc_config - -for nic in $_ZONECFG_net_resources -do - # Get simplified versions of the network config. variables. - address=$(eval echo \$_ZONECFG_net_${nic}_address) - dhcp_server=$(eval echo \$_ZONECFG_net_${nic}_dhcp_server) - global_nic=$(eval echo \$_ZONECFG_net_${nic}_global_nic) - mac_addr=$(eval echo \$_ZONECFG_net_${nic}_mac_addr) - vlan_id=$(eval echo \$_ZONECFG_net_${nic}_vlan_id) - blocked_outgoing_ports=$(eval echo \$_ZONECFG_net_${nic}_blocked_outgoing_ports) - - # If address set, must be a shared stack zone - [[ -n $address ]] && exit 0 - - # If no global-nic, must be a dedicated physical NIC instead of a vnic - [[ -z $global_nic ]] && continue - - orig_global=$global_nic - [[ "$global_nic" == "admin" ]] && global_nic=$SYSINFO_NIC_admin - [[ "$global_nic" == "external" ]] && global_nic=$SYSINFO_NIC_external - [[ "$global_nic" == "internal" ]] && global_nic=$SYSINFO_NIC_internal - - # For backwards compatibility with the other parts of the - # system, check if this zone already has this vnic setup. - # If so, move on to the next vnic. - dladm show-vnic -p -o LINK $nic >/dev/null 2>&1 - (( $? == 0 )) && continue - - if [[ -z $global_nic ]]; then - echo "skipping undefined VNIC $nic (global NIC $orig_global)" - logger -p daemon.err "zone $ZONENAME skipping undefined " \ - "VNIC $nic (global NIC $orig_global)" - continue - fi - - # - # Create the vnic. - # - - opt_str="" - [[ -n $mac_addr ]] && opt_str="$opt_str -m $mac_addr" - - [[ -n $vlan_id && $vlan_id != 0 ]] && opt_str="$opt_str -v $vlan_id" - - dladm create-vnic -t -l $global_nic $opt_str $nic - if (( $? != 0 )); then - echo "error creating VNIC $nic (global NIC $orig_global)" - logger -p daemon.err "zone $ZONENAME error creating " \ - "VNIC $nic (global NIC $orig_global)" - continue - fi - - if [[ -z $mac_addr ]]; then - # There was no assigned mac address - - # Get newly assigned mac address. - mac_addr=$(dladm show-vnic -p -o MACADDRESS ${nic}) - - # Save newly assigned mac address - [[ -n $mac_addr ]] && zonecfg -z $ZONENAME \ - "select net physical=$nic; " \ - "set mac-addr=$mac_addr; end; exit" - fi - - if [[ -n $dhcp_server ]]; then - spoof_opts="mac-nospoof" - else - # XXX For backwards compatibility, special handling for zone - # named "dhcpd". Remove this check once property is added to - # zone. - if [[ $ZONENAME == "dhcpd" ]]; then - spoof_opts="mac-nospoof" - else - # Enable full antispoof if the zone is not a dhcp server. - spoof_opts="ip-nospoof,mac-nospoof,restricted,dhcp-nospoof" - fi - fi - dladm set-linkprop -t -p "protection=${spoof_opts}" ${nic} - - # Get the static IP for the vnic from the zone config file. - hostname_file="/zones/$ZONENAME/root/etc/hostname.$nic" - if [ -e $hostname_file ]; then - zone_ip=`nawk '{if ($1 ~ /[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/) - print $1}' $hostname_file` - - [[ -n "${zone_ip}" ]] && \ - dladm set-linkprop -t -p "allowed-ips=${zone_ip}" ${nic} - - fi - - # If on VMWare and we have external IPs, create a bridge to allow - # zones to reach the external gateway - if [[ ${headnode} == "true" && ${orig_global} == "external" && \ - "${SYSINFO_Product}" == "VMware Virtual Platform" ]]; then - dladm show-bridge -p -o BRIDGE vmwareextbr >/dev/null 2>&1 - (( $? != 0 )) && dladm create-bridge \ - -l ${SYSINFO_NIC_external} vmwareextbr - fi - - if [[ -n $blocked_outgoing_ports ]]; then - OLDIFS=$IFS - IFS=, - for port in $blocked_outgoing_ports; do - # br='block remote'. Flow names should be < 31 chars - # in length so that they get unique kstats - flowadm add-flow -l $nic \ - -a transport=tcp,remote_port=$port \ - -p maxbw=0 ${nic}_br_${port} - done - IFS=$OLDIFS - fi - -done - exit 0 diff --git a/usr/src/lib/libdladm/common/libdllink.c b/usr/src/lib/libdladm/common/libdllink.c index 8a3c5759ee..303885e929 100644 --- a/usr/src/lib/libdladm/common/libdllink.c +++ b/usr/src/lib/libdladm/common/libdllink.c @@ -20,6 +20,7 @@ */ /* * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, Joyent Inc. All rights reserved. */ #include <sys/types.h> @@ -386,10 +387,14 @@ dladm_linkduplex2str(link_duplex_t duplex, char *buf) /* * Case 1: rename an existing link1 to a link2 that does not exist. * Result: <linkid1, link2> + * The zonename parameter is used to allow us to create a VNIC in the global + * zone which is assigned to a non-global zone. Since there is a race condition + * in the create process if two VNICs have the same name, we need to rename it + * after it has been assigned to the zone. */ static dladm_status_t i_dladm_rename_link_c1(dladm_handle_t handle, datalink_id_t linkid1, - const char *link1, const char *link2, uint32_t flags) + const char *link1, const char *link2, uint32_t flags, const char *zonename) { dld_ioc_rename_t dir; dladm_status_t status = DLADM_STATUS_OK; @@ -402,6 +407,10 @@ i_dladm_rename_link_c1(dladm_handle_t handle, datalink_id_t linkid1, dir.dir_linkid1 = linkid1; dir.dir_linkid2 = DATALINK_INVALID_LINKID; (void) strlcpy(dir.dir_link, link2, MAXLINKNAMELEN); + if (zonename != NULL) + dir.dir_zoneinit = B_TRUE; + else + dir.dir_zoneinit = B_FALSE; if (ioctl(dladm_dld_fd(handle), DLDIOC_RENAME, &dir) < 0) { status = dladm_errno2status(errno); @@ -412,6 +421,7 @@ i_dladm_rename_link_c1(dladm_handle_t handle, datalink_id_t linkid1, status = dladm_remap_datalink_id(handle, linkid1, link2); if (status != DLADM_STATUS_OK && (flags & DLADM_OPT_ACTIVE)) { (void) strlcpy(dir.dir_link, link1, MAXLINKNAMELEN); + dir.dir_zoneinit = B_FALSE; (void) ioctl(dladm_dld_fd(handle), DLDIOC_RENAME, &dir); } return (status); @@ -508,6 +518,7 @@ i_dladm_rename_link_c2(dladm_handle_t handle, datalink_id_t linkid1, */ dir.dir_linkid1 = linkid1; dir.dir_linkid2 = linkid2; + dir.dir_zoneinit = B_FALSE; if (ioctl(dladm_dld_fd(handle), DLDIOC_RENAME, &dir) < 0) status = dladm_errno2status(errno); @@ -617,7 +628,8 @@ done: } dladm_status_t -dladm_rename_link(dladm_handle_t handle, const char *link1, const char *link2) +dladm_rename_link(dladm_handle_t handle, const char *zonename, + const char *link1, const char *link2) { datalink_id_t linkid1 = DATALINK_INVALID_LINKID; datalink_id_t linkid2 = DATALINK_INVALID_LINKID; @@ -627,11 +639,11 @@ dladm_rename_link(dladm_handle_t handle, const char *link1, const char *link2) boolean_t remphy2 = B_FALSE; dladm_status_t status; - (void) dladm_name2info(handle, link1, &linkid1, &flags1, &class1, - &media1); - if ((dladm_name2info(handle, link2, &linkid2, &flags2, &class2, - &media2) == DLADM_STATUS_OK) && (class2 == DATALINK_CLASS_PHYS) && - (flags2 == DLADM_OPT_PERSIST)) { + (void) dladm_zname2info(handle, zonename, link1, &linkid1, &flags1, + &class1, &media1); + if ((dladm_zname2info(handle, zonename, link2, &linkid2, &flags2, + &class2, &media2) == DLADM_STATUS_OK) && + (class2 == DATALINK_CLASS_PHYS) && (flags2 == DLADM_OPT_PERSIST)) { /* * see whether link2 is a removed physical link. */ @@ -645,7 +657,7 @@ dladm_rename_link(dladm_handle_t handle, const char *link1, const char *link2) * does not exist. */ status = i_dladm_rename_link_c1(handle, linkid1, link1, - link2, flags1); + link2, flags1, zonename); } else if (remphy2) { /* * case 2: rename an available link to a REMOVED diff --git a/usr/src/lib/libdladm/common/libdllink.h b/usr/src/lib/libdladm/common/libdllink.h index a2830b5e37..a858e78aa3 100644 --- a/usr/src/lib/libdladm/common/libdllink.h +++ b/usr/src/lib/libdladm/common/libdllink.h @@ -20,6 +20,7 @@ */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, Joyent Inc. All rights reserved. */ #ifndef _LIBDLLINK_H @@ -121,7 +122,7 @@ extern dladm_status_t dladm_info(dladm_handle_t, datalink_id_t, dladm_attr_t *); extern dladm_status_t dladm_rename_link(dladm_handle_t, const char *, - const char *); + const char *, const char *); extern dladm_status_t dladm_set_linkprop(dladm_handle_t, datalink_id_t, const char *, char **, uint_t, uint_t); @@ -170,6 +171,9 @@ extern dladm_status_t dladm_up_datalink_id(dladm_handle_t, datalink_id_t); extern dladm_status_t dladm_name2info(dladm_handle_t, const char *, datalink_id_t *, uint32_t *, datalink_class_t *, uint32_t *); +extern dladm_status_t dladm_zname2info(dladm_handle_t, const char *, + const char *, datalink_id_t *, uint32_t *, + datalink_class_t *, uint32_t *); extern dladm_status_t dladm_datalink_id2info(dladm_handle_t, datalink_id_t, uint32_t *, datalink_class_t *, uint32_t *, char *, size_t); diff --git a/usr/src/lib/libdladm/common/libdlmgmt.c b/usr/src/lib/libdladm/common/libdlmgmt.c index 4b0753417c..abb956f94c 100644 --- a/usr/src/lib/libdladm/common/libdlmgmt.c +++ b/usr/src/lib/libdladm/common/libdlmgmt.c @@ -20,6 +20,7 @@ */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, Joyent Inc. All rights reserved. */ #include <door.h> @@ -528,20 +529,37 @@ dladm_getnext_conf_linkprop(dladm_handle_t handle, dladm_conf_t conf, } /* - * Get the link ID that is associated with the given name. + * Get the link ID that is associated with the given name in the current zone. */ dladm_status_t dladm_name2info(dladm_handle_t handle, const char *link, datalink_id_t *linkidp, uint32_t *flagp, datalink_class_t *classp, uint32_t *mediap) { + return (dladm_zname2info(handle, NULL, link, linkidp, flagp, classp, + mediap)); +} + +/* + * Get the link ID that is associated with the given zone/name pair. + */ +dladm_status_t +dladm_zname2info(dladm_handle_t handle, const char *zonename, const char *link, + datalink_id_t *linkidp, uint32_t *flagp, datalink_class_t *classp, + uint32_t *mediap) +{ dlmgmt_door_getlinkid_t getlinkid; dlmgmt_getlinkid_retval_t retval; datalink_id_t linkid; dladm_status_t status; size_t sz = sizeof (retval); + zoneid_t curr_zoneid; getlinkid.ld_cmd = DLMGMT_CMD_GETLINKID; (void) strlcpy(getlinkid.ld_link, link, MAXLINKNAMELEN); + if (zonename != NULL) + getlinkid.ld_zoneid = getzoneidbyname(zonename); + else + getlinkid.ld_zoneid = -1; if ((status = dladm_door_call(handle, &getlinkid, sizeof (getlinkid), &retval, &sz)) != DLADM_STATUS_OK) { diff --git a/usr/src/lib/libdladm/common/libdlvnic.c b/usr/src/lib/libdladm/common/libdlvnic.c index 6dba8d6fad..a5655cddae 100644 --- a/usr/src/lib/libdladm/common/libdlvnic.c +++ b/usr/src/lib/libdladm/common/libdlvnic.c @@ -20,6 +20,7 @@ */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, Joyent Inc. All rights reserved. */ #include <stdio.h> @@ -537,27 +538,26 @@ dladm_vnic_create(dladm_handle_t handle, const char *vnic, datalink_id_t linkid, vnic_created = B_TRUE; /* Save vnic configuration and its properties */ - if (!(flags & DLADM_OPT_PERSIST)) - goto done; - - status = dladm_vnic_persist_conf(handle, name, &attr, class); - if (status != DLADM_STATUS_OK) - goto done; - conf_set = B_TRUE; + if (flags & DLADM_OPT_PERSIST) { + status = dladm_vnic_persist_conf(handle, name, &attr, class); + if (status == DLADM_STATUS_OK) + conf_set = B_TRUE; + } - if (proplist != NULL) { +done: + if (status == DLADM_STATUS_OK && proplist != NULL) { for (i = 0; i < proplist->al_count; i++) { dladm_arg_info_t *aip = &proplist->al_info[i]; status = dladm_set_linkprop(handle, vnic_id, aip->ai_name, aip->ai_val, aip->ai_count, - DLADM_OPT_PERSIST); + ((flags & DLADM_OPT_PERSIST) ? + DLADM_OPT_PERSIST : DLADM_OPT_ACTIVE)); if (status != DLADM_STATUS_OK) break; } } -done: if (status != DLADM_STATUS_OK) { if (conf_set) (void) dladm_remove_conf(handle, vnic_id); diff --git a/usr/src/lib/libdladm/common/mapfile-vers b/usr/src/lib/libdladm/common/mapfile-vers index b781c93aff..3eaeea656e 100644 --- a/usr/src/lib/libdladm/common/mapfile-vers +++ b/usr/src/lib/libdladm/common/mapfile-vers @@ -20,6 +20,7 @@ # # # Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, Joyent Inc. All rights reserved. # # @@ -134,6 +135,7 @@ SYMBOL_VERSION SUNWprivate_1.1 { dladm_remap_datalink_id; dladm_up_datalink_id; dladm_name2info; + dladm_zname2info; dladm_datalink_id2info; dladm_walk_datalink_id; dladm_create_conf; diff --git a/usr/src/uts/common/io/dld/dld_drv.c b/usr/src/uts/common/io/dld/dld_drv.c index 40cbe86170..0c297fac44 100644 --- a/usr/src/uts/common/io/dld/dld_drv.c +++ b/usr/src/uts/common/io/dld/dld_drv.c @@ -20,6 +20,7 @@ */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, Joyent Inc. All rights reserved. */ /* @@ -865,7 +866,7 @@ drv_ioc_rename(void *karg, intptr_t arg, int mode, cred_t *cred, int *rvalp) return (err); if ((err = dls_devnet_rename(dir->dir_linkid1, dir->dir_linkid2, - dir->dir_link)) != 0) + dir->dir_link, dir->dir_zoneinit)) != 0) return (err); if (dir->dir_linkid2 == DATALINK_INVALID_LINKID) diff --git a/usr/src/uts/common/io/dls/dls_mgmt.c b/usr/src/uts/common/io/dls/dls_mgmt.c index 049c4bd757..43cfab6d6a 100644 --- a/usr/src/uts/common/io/dls/dls_mgmt.c +++ b/usr/src/uts/common/io/dls/dls_mgmt.c @@ -21,6 +21,7 @@ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * Copyright 2011 Joyent, Inc. All rights reserved. */ /* @@ -526,6 +527,7 @@ dls_mgmt_get_linkid(const char *link, datalink_id_t *linkid) getlinkid.ld_cmd = DLMGMT_CMD_GETLINKID; (void) strlcpy(getlinkid.ld_link, link, MAXLINKNAMELEN); + getlinkid.ld_zoneid = getzoneid(); if ((err = i_dls_mgmt_upcall(&getlinkid, sizeof (getlinkid), &retval, sizeof (retval))) == 0) { @@ -781,15 +783,24 @@ dls_devnet_stat_destroy(dls_devnet_t *ddp, zoneid_t zoneid) * and create the new set using the new name. */ static void -dls_devnet_stat_rename(dls_devnet_t *ddp) +dls_devnet_stat_rename(dls_devnet_t *ddp, boolean_t zoneinit) { if (ddp->dd_ksp != NULL) { kstat_delete(ddp->dd_ksp); ddp->dd_ksp = NULL; } - /* We can't rename a link while it's assigned to a non-global zone. */ + if (zoneinit && ddp->dd_zone_ksp != NULL) { + kstat_delete(ddp->dd_zone_ksp); + ddp->dd_zone_ksp = NULL; + } + /* + * We can't rename a link while it's assigned to a non-global zone + * unless we're first initializing the zone while readying it. + */ ASSERT(ddp->dd_zone_ksp == NULL); dls_devnet_stat_create(ddp, ddp->dd_owner_zid); + if (zoneinit) + dls_devnet_stat_create(ddp, ddp->dd_zid); } /* @@ -1261,9 +1272,15 @@ dls_devnet_phydev(datalink_id_t vlanid, dev_t *devp) * * This case does not change the <link name, linkid> mapping, so the link's * kstats need to be updated with using name associated the given id2. + * + * The zonename parameter is used to allow us to create a VNIC in the global + * zone which is assigned to a non-global zone. Since there is a race condition + * in the create process if two VNICs have the same name, we need to rename it + * after it has been assigned to the zone. */ int -dls_devnet_rename(datalink_id_t id1, datalink_id_t id2, const char *link) +dls_devnet_rename(datalink_id_t id1, datalink_id_t id2, const char *link, + boolean_t zoneinit) { dls_dev_handle_t ddh = NULL; int err = 0; @@ -1313,13 +1330,16 @@ dls_devnet_rename(datalink_id_t id1, datalink_id_t id2, const char *link) * is currently accessing the link kstats, or if the link is on-loan * to a non-global zone. Then set the DD_KSTAT_CHANGING flag to * prevent any access to the kstats while we delete and recreate - * kstats below. + * kstats below. However, we skip this check if we're renaming the + * vnic as part of bringing it up for a zone. */ mutex_enter(&ddp->dd_mutex); - if (ddp->dd_ref > 1) { - mutex_exit(&ddp->dd_mutex); - err = EBUSY; - goto done; + if (!zoneinit) { + if (ddp->dd_ref > 1) { + mutex_exit(&ddp->dd_mutex); + err = EBUSY; + goto done; + } } ddp->dd_flags |= DD_KSTAT_CHANGING; @@ -1406,7 +1426,7 @@ done: */ rw_exit(&i_dls_devnet_lock); if (err == 0) - dls_devnet_stat_rename(ddp); + dls_devnet_stat_rename(ddp, zoneinit); if (clear_dd_flag) { mutex_enter(&ddp->dd_mutex); diff --git a/usr/src/uts/common/sys/dld.h b/usr/src/uts/common/sys/dld.h index fb2a0749d3..50cb34260b 100644 --- a/usr/src/uts/common/sys/dld.h +++ b/usr/src/uts/common/sys/dld.h @@ -21,6 +21,7 @@ /* * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * Copyright 2011 Joyent, Inc. All rights reserved. */ #ifndef _SYS_DLD_H @@ -191,6 +192,7 @@ typedef struct dld_ioc_rename { datalink_id_t dir_linkid1; datalink_id_t dir_linkid2; char dir_link[MAXLINKNAMELEN]; + boolean_t dir_zoneinit; } dld_ioc_rename_t; /* diff --git a/usr/src/uts/common/sys/dls.h b/usr/src/uts/common/sys/dls.h index 6bd2bbe35a..e0df775deb 100644 --- a/usr/src/uts/common/sys/dls.h +++ b/usr/src/uts/common/sys/dls.h @@ -21,6 +21,7 @@ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * Copyright 2011 Joyent, Inc. All rights reserved. */ #ifndef _SYS_DLS_H @@ -110,7 +111,7 @@ extern void dls_devnet_close(dls_dl_handle_t); extern boolean_t dls_devnet_rebuild(); extern int dls_devnet_rename(datalink_id_t, datalink_id_t, - const char *); + const char *, boolean_t); extern int dls_devnet_create(mac_handle_t, datalink_id_t, zoneid_t); extern int dls_devnet_destroy(mac_handle_t, datalink_id_t *, diff --git a/usr/src/uts/common/sys/dls_mgmt.h b/usr/src/uts/common/sys/dls_mgmt.h index b4032c24d6..4f73d92118 100644 --- a/usr/src/uts/common/sys/dls_mgmt.h +++ b/usr/src/uts/common/sys/dls_mgmt.h @@ -20,6 +20,7 @@ */ /* * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, Joyent Inc. All rights reserved. */ #ifndef _DLS_MGMT_H @@ -165,6 +166,7 @@ typedef struct dlmgmt_door_getname { typedef struct dlmgmt_door_getlinkid { int ld_cmd; char ld_link[MAXLINKNAMELEN]; + zoneid_t ld_zoneid; } dlmgmt_door_getlinkid_t; typedef struct dlmgmt_door_getnext_s { |