summaryrefslogtreecommitdiff
path: root/usr/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib')
-rw-r--r--usr/src/lib/brand/joyent/zone/poststate.ksh139
-rw-r--r--usr/src/lib/brand/joyent/zone/prestate.ksh122
-rw-r--r--usr/src/lib/libdladm/common/libdllink.c28
-rw-r--r--usr/src/lib/libdladm/common/libdllink.h6
-rw-r--r--usr/src/lib/libdladm/common/libdlmgmt.c20
-rw-r--r--usr/src/lib/libdladm/common/libdlvnic.c20
-rw-r--r--usr/src/lib/libdladm/common/mapfile-vers2
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;