diff options
Diffstat (limited to 'usr/src/lib')
| -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 |
7 files changed, 192 insertions, 145 deletions
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; |
