@@ -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"
@@ -532,6 +533,16 @@ _get_device_number() {
532533# NOTE: On many instance types, this value is not defined. This
533534# function will print the empty string on those instances. On
534535# instances where it is defined, it will be a numeric value.
536+ #
537+ # The value, like device-number, may not have propagated to IMDS
538+ # when a hot-plugged interface first appears. We can't tell
539+ # "undefined for this instance type" from "not yet propagated" from
540+ # a single query, so we retry on empty. Once the first ENI on this
541+ # boot has exhausted the retry loop with no value, we touch a marker
542+ # so subsequent ENIs skip the retry entirely. Without
543+ # this retry we can silently substitute 0 for a real network-card
544+ # index on multi-card instances, colliding route metrics and
545+ # routing-table IDs across interfaces.
535546_get_network_card () {
536547 local iface ether network_card
537548 iface=" $1 "
@@ -540,8 +551,26 @@ _get_network_card() {
540551 if _is_primary_interface " $ether " ; then
541552 echo 0 ; return 0
542553 fi
543- network_card=$( get_iface_imds " $ether " network-card)
554+
555+ local marker=" ${runtimeroot} /.no-network-card"
556+ if [ -e " $marker " ]; then
557+ echo ${network_card}
558+ return 0
559+ fi
560+
561+ local -i maxtries=40 ntries=0
562+ for (( ntries = 0 ; ntries < maxtries; ntries++ )) ; do
563+ network_card=$( get_iface_imds " $ether " network-card 1)
564+ if [ -n " $network_card " ]; then
565+ echo " $network_card "
566+ return 0
567+ fi
568+ sleep 0.1
569+ done
570+
571+ touch " $marker "
544572 echo ${network_card}
573+ return 0
545574}
546575
547576
0 commit comments