summaryrefslogtreecommitdiff
path: root/usr/src/cmd/svc/milestone/net-early-admin
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd/svc/milestone/net-early-admin')
-rw-r--r--usr/src/cmd/svc/milestone/net-early-admin260
1 files changed, 260 insertions, 0 deletions
diff --git a/usr/src/cmd/svc/milestone/net-early-admin b/usr/src/cmd/svc/milestone/net-early-admin
new file mode 100644
index 0000000000..a01881c904
--- /dev/null
+++ b/usr/src/cmd/svc/milestone/net-early-admin
@@ -0,0 +1,260 @@
+#!/bin/ksh93
+#
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2020 Joyent, Inc.
+#
+
+# Traditionally, when a Triton compute node boots, the network is not
+# configured until after the local filesystems are mounted (in fact
+# network/physical:default depends upon /system/filesystem/smartdc). Most
+# obviously, in the case of a head node or a standalone SmartOS install, the
+# network configuration is stored on the local zpool, so the network cannot
+# be configured until this happens.
+#
+# For Triton compute nodes with encrypted zpools, we must enable the admin
+# network before the local zpool filesytems are online -- we have to be able
+# to communicate to the head node services to obtain the pin to unlock the
+# local zpool. For PXE booted Triton compute nodes, we therefore configure
+# the admin network sooner via the network/early-admin:default service. When
+# network/physical:default runs, it will skip the configuration of the admin
+# network and configuring the remaining interfaces.
+#
+# If we are not a Triton compute node, we exit successfully almost immediately
+# without configuring the admin network. When the network/physical:default
+# service runs, it will configure all the network interfaces as it traditionally
+# has
+
+PATH=/bin:/usr/bin:/sbin:/usr/sbin
+
+. /lib/svc/share/smf_include.sh
+. /lib/sdc/config.sh
+. /lib/sdc/network.sh
+
+PS4='+ [$LINENO] '
+
+set -o xtrace
+
+if ! smf_is_globalzone; then
+ echo "Non-global zone; no action required; exiting"
+ exit $SMT_EXIT_OK
+fi
+
+# XXX Until OS-8367 is sorted out, immediately enable the varpd service.
+# SMF will properly cope with things if it fails (and blocks both
+# network/physical and zones).
+svcadm enable varpd
+
+if ! boot_file_config_enabled; then
+ echo "Boot-time networking files not present; exiting"
+ exit $SMF_EXIT_OK
+fi
+
+function fatal
+{
+ # XXX: For SMF methods, does it matter/better to redirect to stderr?
+ echo "Error: $*" >&2
+ exit $SMF_EXIT_ERR_FATAL
+}
+
+if ! boot_file_config_valid; then
+ echo "ERROR: boot-time network config file incorrect" >&2
+ exit $SMF_EXIT_ERR_CONFIG
+fi
+
+unset aggrs
+unset tags
+typeset -A tagv
+typeset -A aggr_links aggr_mode
+typeset -A ip ip6 netmask gateway gateway6 mtu mac
+/usr/lib/sdc/net-boot-config | while IFS="=" read var value; do
+ if [[ "$var" =~ _nic$ ]]; then
+ name=${var%_nic}
+ tags+=("${name}")
+ tagv[$name]="$value"
+ elif [[ "$var" =~ _aggr$ ]]; then
+ name=${var%_aggr}
+ aggrs+=(${name})
+ aggr_links[$name]="${value//,/ }"
+ elif [[ "$var" =~ _lacp_mode$ ]]; then
+ name=${var%_lacp_mode}
+ aggr_mode[$name]="$value"
+ elif [[ "$var" =~ _mtu$ ]]; then
+ (( value < 1500 || value > 65535 )) &&
+ fatal "ERROR: $var MTU value \'$value\' is not in" \
+ "range [1500, 65535]"
+
+ name=${var%_mtu}
+ mtu[$name]="$value"
+ elif [[ "$var" =~ _ip$ ]]; then
+ name=${var%_ip}
+ ip[$name]="$value"
+ elif [[ "$var" =~ _ip6$ ]]; then
+ name=${var%_ip6}
+ ip6[$name]="$value"
+ elif [[ "$var" =~ _netmask$ ]]; then
+ name=${var%_netmask}
+ netmask[$name]="$value"
+ elif [[ "$var" =~ _gateway$ ]]; then
+ name=${var%_gateway}
+ gateway[$name]="$value"
+ elif [[ "$var" =~ _gateway6$ ]]; then
+ name=${var%_gateway6}
+ gateway6[$name]="$value"
+ elif [[ "$var" =~ _mac$ ]]; then
+ name=${var%_mac}
+ mac[$name]="$value"
+ elif [[ "$var" == "dns_resolvers" ]]; then
+ dns_resolvers=(${value//,/ })
+ fi
+
+ eval "CONFIG_$var"="$value"
+done
+
+# This must happen befor any other dladm commands (which includes log_if_state)
+# or else dladm commands can fail
+dladm init-phys
+
+log_if_state before
+
+typeset -A mac_to_link
+out=$(dladm show-phys -mpo link,address)
+(( $? == 0 )) || fatal "dladm show-phys failed"
+while IFS=: read link addr; do
+ macaddr=$(normalize_mac $addr)
+ mac_to_link["$macaddr"]="$link"
+done <<< "$out"
+
+ADMIN_NIC_TAG=${CONFIG_admin_tag:-"admin"}
+[[ -n "${tagv[$ADMIN_NIC_TAG]}" ]] || \
+ fatal "ERROR: admin nic tag '$ADMIN_NIC_TAG' not present"
+
+# Set $nic to the link that has the admin nic tag. For unfortunate
+# historic reasons, for aggrs, the MAC address and link name of an aggr
+# are the same value by net-boot-config (and the source of many errors).
+# If ${aggr_links[$nic]} is non-empty, it means $nic isn't a MAC address
+# but an aggr name (and we're done). Otherwise we must map the MAC address
+# from $tagv back to the link.
+nic="${tagv[$ADMIN_NIC_TAG]}"
+if [[ -z "${aggr_links[$nic]}" ]]; then
+ if !valid_mac "$nic"; then
+ fatal "ERROR: admin mac address $nic not found on system"
+ fi
+
+ _nic=${mac_to_link[$nic]}
+ if [[ -z "$_nic" ]]; then
+ fatal "ERROR: Invalid value of ${ADMIN_NIC_TAG}_nic ($nic)"
+ fi
+ nic=$_nic
+fi
+
+# If there are other nic tags configured on the same link as
+# the admin tag, find the largest MTU to use to set the
+# datalink MTU
+dlmtu="${mtu[$ADMIN_NIC_TAG]}"
+
+for tag in ${tags[@]}; do
+ tagmac="${tagv[$tag]}"
+
+ # If the 'mac' for the nic tag is actually an aggr, the
+ # tag will appear in $aggr_links (and we want to use that as
+ # the link name). If it is not an aggr, we need to map the
+ # MAC address to the link name so we can check if $tag
+ # resides on the same link as the admin interface
+ if [[ -n "${aggr_links[$tagmac]}" ]]; then
+ link="$tagmac"
+ else
+ link="${mac_to_link[$tagmac]}"
+ fi
+
+ if [[ "$link" == "$nic" && $dlmtu -lt ${mtu[$tag]} ]]; then
+ dlmtu=${mtu[$tag]}
+ fi
+done
+
+
+if [[ -n "${aggr_links[$nic]}" ]]; then
+ mode=${aggr_mode[$nic]:-"off"}
+
+ for l in ${aggr_links[$nic]}; do
+ [[ -n "${mac_to_link[$l]}" ]] || fatal "MAC '$l' not present"
+ link="${mac_to_link[$l]}"
+ if [[ -n "$dlmtu" ]]; then
+ dladm set-linkprop -p mtu=$dlmtu $link || \
+ fatal "ERROR: Failed to set mtu on $link to $dlmtu"
+ fi
+ links+="${link} "
+ done
+ links="${links% }"
+
+ echo "Creating aggr: $nic (mode=$mode, links=${links})"
+ dladm create-aggr -l ${links// / -l } -L $mode $nic
+fi
+
+if [[ -n "$dlmtu" ]]; then
+ dladm set-linkprop -p mtu=$dlmtu $nic || \
+ fatal "ERROR: Failed to set mtu on aggr $nic to $dlmtu"
+fi
+
+driver=${nic%%+([0-9])}
+get_link_state $nic
+if [[ "$link_state" == "down" ]]; then
+ echo "admin nic '${nic}' is down: unplumbing"
+ /sbin/ifconfig $nic down unplumb
+ wait_for_nic_state $nic "unknown"
+fi
+
+# There's some sort of race condition in the bnx driver: if the plumb
+# command comes too soon after the unplumb, the interface can come up
+# in a state where it never fires interrupts for link state changes.
+if [[ "$driver" == "bnx" ]]; then
+ sleep 5
+fi
+
+/sbin/ifconfig $nic plumb mtu ${mtu[$ADMIN_NIC_TAG]}
+wait_for_nic_state $nic "up"
+
+if [[ -n "${ip[$ADMIN_NIC_TAG]}" ]]; then
+ /sbin/ifconfig $nic inet ${ip[$ADMIN_NIC_TAG]} \
+ netmask ${netmask[$ADMIN_NIC_TAG]:-"+"} up
+ [[ -n "${gateway[$ADMIN_NIC_TAG]}" ]] && \
+ /usr/sbin/route add default ${gateway[$ADMIN_NIC_TAG]}
+fi
+
+if [[ -n "${ip6[$ADMIN_NIC_TAG]}" ]]; then
+ /sbin/ifconfig $nic inet6 plumb mtu ${mtu[$ADMIN_NIC_TAG]}
+ [[ "${ip6[$ADMIN_NIC_TAG]}" != "addrconf" ]] && \
+ /sbin/ifconfig $nic inet6 addif ${ip6[$ADMIN_NIC_TAG]} preferred up
+ [[ -n "${gateway6[$ADMIN_NIC_TAG]}" ]] && \
+ /usr/sbin/route add -inet6 default ${gateway6[$ADMIN_NIC_TAG]}
+fi
+
+# Add just the routes reachable through the admin network -- usually these are
+# only present with rack aware networking (RAN)
+/usr/lib/sdc/net-boot-config --routes | while read dst gw; do
+ if ! ip_in_net $gw ${ip[$ADMIN_NIC_TAG]} ${netmask[$ADMIN_NIC_TAG]}; then
+ continue
+ fi
+ route add "$dst" "$gw"
+done
+
+if [[ -n "${CONFIG_dns_domain}" && -n ${dns_resolvers[0]} ]]; then
+ echo "search ${CONFIG_dns_domain}" > /etc/resolv.conf
+ for serv in ${dns_resolvers[@]}; do
+ echo "nameserver $serv" >> /etc/resolv.conf
+ done
+fi
+
+touch /etc/svc/volatile/.early_admin_setup
+
+log_if_state after