@@ -18,6 +18,7 @@ declare ether
1818declare unitdir
1919declare lockdir
2020declare reload_flag
21+ declare runtimeroot
2122
2223# Version information - substituted during installation
2324declare PACKAGE_VERSION=" AMAZON_EC2_NET_UTILS_VERSION"
@@ -534,6 +535,16 @@ _get_device_number() {
534535# NOTE: On many instance types, this value is not defined. This
535536# function will print the empty string on those instances. On
536537# 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.
537548_get_network_card () {
538549 local iface ether network_card
539550 iface=" $1 "
@@ -542,8 +553,26 @@ _get_network_card() {
542553 if _is_primary_interface " $ether " ; then
543554 echo 0 ; return 0
544555 fi
545- 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 "
546574 echo ${network_card}
575+ return 0
547576}
548577
549578
0 commit comments