Skip to content

Commit c248420

Browse files
authored
Merge branch 'amazonlinux:main' into add-gitignore
2 parents f5ab0c2 + 9408f18 commit c248420

3 files changed

Lines changed: 58 additions & 6 deletions

File tree

bin/setup-policy-routes.sh

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,18 @@ refresh)
5050
start)
5151
register_networkd_reloader
5252
counter=0
53+
max_wait=3000 # 5 minute timeout to avoid infinite loop if sysfs node never appears
5354
while [ ! -e "/sys/class/net/${iface}" ]; do
5455
if ((counter % 1000 == 0)); then
5556
debug "Waiting for sysfs node to exist for ${iface} (iteration $counter)"
5657
fi
5758
sleep 0.1
58-
((counter++))
59+
((counter++)) || true
60+
if ((counter >= max_wait)); then
61+
error "Timed out waiting for sysfs node for ${iface} after $((counter / 10)) seconds"
62+
/usr/bin/systemctl disable --now refresh-policy-routes@${iface}.timer 2>/dev/null || true
63+
exit 2
64+
fi
5965
done
6066
debug "Starting configuration for $iface"
6167
debug /lib/systemd/systemd-networkd-wait-online -i "$iface"

lib/lib.sh

Lines changed: 50 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ declare ether
1818
declare unitdir
1919
declare lockdir
2020
declare reload_flag
21+
declare runtimeroot
2122

2223
# Version information - substituted during installation
2324
declare PACKAGE_VERSION="AMAZON_EC2_NET_UTILS_VERSION"
@@ -140,7 +141,9 @@ get_meta() {
140141
local key=$1
141142
local max_tries=${2:-10}
142143
declare -i attempts=0
143-
[ -v EC2_IF_INITIAL_SETUP ] && debug "[get_meta] Querying IMDS for ${key}"
144+
if [ -v EC2_IF_INITIAL_SETUP ]; then
145+
debug "[get_meta] Querying IMDS for ${key}"
146+
fi
144147

145148
if [[ -z $imds_endpoint || -z $imds_token || -z $imds_interface ]]; then
146149
error "[get_meta] Unable to obtain IMDS token, endpoint, or interface"
@@ -532,6 +535,16 @@ _get_device_number() {
532535
# NOTE: On many instance types, this value is not defined. This
533536
# function will print the empty string on those instances. On
534537
# instances where it is defined, it will be a numeric value.
538+
#
539+
# The value, like device-number, may not have propagated to IMDS
540+
# when a hot-plugged interface first appears. We can't tell
541+
# "undefined for this instance type" from "not yet propagated" from
542+
# a single query, so we retry on empty. Once the first ENI on this
543+
# boot has exhausted the retry loop with no value, we touch a marker
544+
# so subsequent ENIs skip the retry entirely. Without
545+
# this retry we can silently substitute 0 for a real network-card
546+
# index on multi-card instances, colliding route metrics and
547+
# routing-table IDs across interfaces.
535548
_get_network_card() {
536549
local iface ether network_card
537550
iface="$1"
@@ -540,8 +553,26 @@ _get_network_card() {
540553
if _is_primary_interface "$ether"; then
541554
echo 0 ; return 0
542555
fi
543-
network_card=$(get_iface_imds "$ether" network-card)
556+
557+
local marker="${runtimeroot}/.no-network-card"
558+
if [ -e "$marker" ]; then
559+
echo ${network_card}
560+
return 0
561+
fi
562+
563+
local -i maxtries=40 ntries=0
564+
for (( ntries = 0; ntries < maxtries; ntries++ )); do
565+
network_card=$(get_iface_imds "$ether" network-card 1)
566+
if [ -n "$network_card" ]; then
567+
echo "$network_card"
568+
return 0
569+
fi
570+
sleep 0.1
571+
done
572+
573+
touch "$marker"
544574
echo ${network_card}
575+
return 0
545576
}
546577

547578

@@ -617,7 +648,9 @@ maybe_reload_networkd() {
617648
networkctl reload
618649
debug "Reloaded networkd"
619650
else
620-
[ -v EC2_IF_INITIAL_SETUP ] && debug "No networkd reload needed"
651+
if [ -v EC2_IF_INITIAL_SETUP ]; then
652+
debug "No networkd reload needed"
653+
fi
621654
fi
622655
else
623656
debug "Deferring networkd reload to another process"
@@ -627,18 +660,30 @@ maybe_reload_networkd() {
627660

628661
register_networkd_reloader() {
629662
local -i registered=1 cnt=0
630-
local -i max=10000
663+
local -i max=3000 # 300s (3000 × 0.1s); matches sysfs wait timeout in setup-policy-routes.sh
631664
local -r lockfile="${lockdir}/${iface}"
632665
local old_opts=$-
633666

667+
# If the existing lock owner is no longer alive, remove the stale lockfile
668+
# so subsequent invocations don't spin for up to 1000 seconds waiting on a
669+
# process that will never release it.
670+
if [ -f "${lockfile}" ]; then
671+
local existing_pid
672+
existing_pid=$(cat "${lockfile}" 2>/dev/null)
673+
if [ -n "$existing_pid" ] && ! kill -0 "$existing_pid" 2>/dev/null; then
674+
debug "Removing stale lock from dead process $existing_pid for ${iface}"
675+
rm -f "${lockfile}"
676+
fi
677+
fi
678+
634679
# Disable -o errexit in the following block so we can capture
635680
# nonzero exit codes from a redirect without considering them
636681
# fatal errors
637682
set +e
638683
while [ $cnt -lt $max ]; do
639684
cnt+=1
640685
mkdir -p "$lockdir"
641-
trap '[ -v EC2_IF_INITIAL_SETUP ] && debug "Called trap" ; maybe_reload_networkd' EXIT
686+
trap 'if [ -v EC2_IF_INITIAL_SETUP ]; then debug "Called trap"; fi; maybe_reload_networkd' EXIT
642687
# If the redirect fails, most likely because the target file
643688
# already exists and -o noclobber is in effect, $? will be set
644689
# nonzero. If it succeeds, it is set to 0

systemd/system/policy-routes@.service

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,5 @@ User=root
1717
ExecStart=/usr/bin/setup-policy-routes %i start
1818
Restart=on-failure
1919
RestartSec=1
20+
RestartPreventExitStatus=2
2021
KillMode=process

0 commit comments

Comments
 (0)