meta-google: gbmc-net: Consolidate route metrics and RA timers

Centralize and document the route metric hierarchy, SLAAC address
selection label, and RA discovery, lifetime, and reconfigure grace
timers in gbmc-net-lib.sh so their relationships and ordering are
defined in one place instead of duplicated as literals across the
bridge, NIC, and NCSI scripts.

Collapse the three 5s networkd reconfigure grace period variables
(GBMC_BR_FROM_RA_GRACE, GBMC_BR_GW_SRC_ADV_GRACE, and
GBMC_BR_GW_SRC_BR_GRACE) into a single GBMC_BR_RA_GRACE constant.

Tested: gbmc-ip-monitor, gbmc-net-lib, gbmc-nic-neigh, and network-sh
unit tests pass, shellcheck clean.

Change-Id: I9e27dfdd672ad2c138408391119bbb2a5eed4668
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/meta-google/recipes-google/ncsi/files/gbmc-ncsi-br-deprecated-ips.sh.in b/meta-google/recipes-google/ncsi/files/gbmc-ncsi-br-deprecated-ips.sh.in
index 236675e..7f4bc9b 100644
--- a/meta-google/recipes-google/ncsi/files/gbmc-ncsi-br-deprecated-ips.sh.in
+++ b/meta-google/recipes-google/ncsi/files/gbmc-ncsi-br-deprecated-ips.sh.in
@@ -122,7 +122,7 @@
     read -r -d '' brcontents <<EOF
 [Route]
 Destination=$brroute
-Metric=512
+Metric=$GBMC_ROUTE_METRIC_ONLINK
 EOF
     for file in /run/systemd/network/{00,}-bmc-gbmcbr.network.d/50-deprecated-"$ip".conf; do
       mkdir -p -m 755 "$(dirname "$file")"
@@ -163,13 +163,13 @@
       ip -6 neigh del proxy $stateless_ip dev $intf 2>/dev/null || true
     fi
     if [ -n "$brroute" ]; then
-      ip -6 route del "$brroute" dev gbmcbr metric 512 2>/dev/null || true
+      ip -6 route del "$brroute" dev gbmcbr metric "$GBMC_ROUTE_METRIC_ONLINK" 2>/dev/null || true
     fi
   else
     ip -6 rule add proto static to "$pfx/76" pref $GBMC_INTF_ROUTE_TABLE_BASE lookup main || st=$?
     ip -6 rule add proto static from "$pfx/76" pref $rt lookup $rt || st=$?
     if [ -n "$brroute" ]; then
-      ip -6 route replace "$brroute" dev gbmcbr metric 512 || st=$?
+      ip -6 route replace "$brroute" dev gbmcbr metric "$GBMC_ROUTE_METRIC_ONLINK" || st=$?
     fi
     gbmc_ncsi_br_deprecated_ips_savedconf["$pfx"]="$intf"
     gbmc_ncsi_br_deprecated_ips_savedconf["$stateless_pfx"]="$intf"
diff --git a/meta-google/recipes-google/ncsi/files/gbmc-ncsi-ra.sh.in b/meta-google/recipes-google/ncsi/files/gbmc-ncsi-ra.sh.in
index e310d8d..1866594 100644
--- a/meta-google/recipes-google/ncsi/files/gbmc-ncsi-ra.sh.in
+++ b/meta-google/recipes-google/ncsi/files/gbmc-ncsi-ra.sh.in
@@ -21,7 +21,7 @@
 RA_IF=$1
 IP_OFFSET=1
 # NCSI is known to be closer to the ToR than bridge routes. Prefer over bridge routes.
-ROUTE_METRIC=900
+ROUTE_METRIC="$GBMC_ROUTE_METRIC_NCSI"
 
 update_rtr() {
   local op="${3-add}"
diff --git a/meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-from-ra.sh b/meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-from-ra.sh
index 0b830e9..a0a0843 100644
--- a/meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-from-ra.sh
+++ b/meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-from-ra.sh
@@ -38,9 +38,8 @@
 # solicits right away. Route deletions therefore don't immediately mean the
 # prefix is gone, and acting on them would rewrite our config and reload
 # networkd, flushing the routes again. Instead, a prefix is only dropped once
-# its route stayed gone for GBMC_BR_FROM_RA_GRACE seconds. This also covers
+# its route stayed gone for GBMC_BR_RA_GRACE seconds. This also covers
 # prefixes networkd removes because they were withdrawn or expired.
-GBMC_BR_FROM_RA_GRACE=5
 GBMC_BR_FROM_RA_CONFS=(/run/systemd/network/{00,}-bmc-gbmcbr.network.d/65-ra-addrs.conf)
 
 # Writes the networkd config for the given "<addr> <pfx>" entries, only
@@ -67,7 +66,7 @@
   while read -r addr pfx; do
     [[ -n $addr ]] || continue
     contents+="[Address]"$'\n'"Address=$addr"$'\n'"AddPrefixRoute=no"$'\n'
-    contents+="[Route]"$'\n'"Destination=$pfx"$'\n'"Metric=512"$'\n'
+    contents+="[Route]"$'\n'"Destination=$pfx"$'\n'"Metric=$GBMC_ROUTE_METRIC_ONLINK"$'\n'
   done < <(printf '%s\n' "$@" | sort)
 
   local changed=
@@ -125,10 +124,10 @@
       unset 'gbmc_br_from_ra_gone[$pfx]'
       # Make sure we didn't miss it coming back
       if [[ -z "$(ip -6 route show "$pfx" dev gbmcbr proto ra 2>/dev/null)" ]]; then
-        echo "gBMC Bridge RA Addr Del: $addr (pfx $pfx label 99)" >&2
+        echo "gBMC Bridge RA Addr Del: $addr (pfx $pfx label $GBMC_SLAAC_ADDRLABEL)" >&2
         unset 'gbmc_br_from_ra_prev_addrs[$addr]'
         ip addr del "$addr" dev gbmcbr 2>/dev/null || true
-        ip addrlabel del prefix "$pfx" label 99 2>/dev/null || true
+        ip addrlabel del prefix "$pfx" label "$GBMC_SLAAC_ADDRLABEL" 2>/dev/null || true
         unset 'gbmc_br_from_ra_pfxs[$pfx]'
         continue
       fi
@@ -139,12 +138,12 @@
     fi
     addrs+=("$addr $pfx")
     if [[ -z ${gbmc_br_from_ra_prev_addrs["$addr"]-} ]]; then
-      echo "gBMC Bridge RA Addr Add: $addr (pfx $pfx label 99)" >&2
+      echo "gBMC Bridge RA Addr Add: $addr (pfx $pfx label $GBMC_SLAAC_ADDRLABEL)" >&2
       gbmc_br_from_ra_prev_addrs["$addr"]=1
       # Usable right away, networkd takes it over once it reloads
       ip addr replace "$addr" dev gbmcbr noprefixroute
-      ip -6 route replace "$pfx" dev gbmcbr metric 512 2>/dev/null || true
-      ip addrlabel add prefix "$pfx" label 99 2>/dev/null || true
+      ip -6 route replace "$pfx" dev gbmcbr metric "$GBMC_ROUTE_METRIC_ONLINK" 2>/dev/null || true
+      ip addrlabel add prefix "$pfx" label "$GBMC_SLAAC_ADDRLABEL" 2>/dev/null || true
     fi
   done
   if [[ -n $next ]]; then
@@ -179,8 +178,8 @@
       [[ -z ${gbmc_br_from_ra_gone["$pfx"]-} ]] || return 0
       local now
       gbmc_ip_monitor_uptime now || return
-      gbmc_br_from_ra_gone["$pfx"]=$(( now + GBMC_BR_FROM_RA_GRACE ))
-      gbmc_ip_monitor_timer from-ra "$GBMC_BR_FROM_RA_GRACE"
+      gbmc_br_from_ra_gone["$pfx"]=$(( now + GBMC_BR_RA_GRACE ))
+      gbmc_ip_monitor_timer from-ra "$GBMC_BR_RA_GRACE"
     fi
   elif [[ $change == link && $intf == gbmcbr ]]; then
     rdisc6 -m gbmcbr -r 1 -w 100 >/dev/null 2>&1
diff --git a/meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-gw-src.sh.in b/meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-gw-src.sh.in
index 7b71efb..7941594 100644
--- a/meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-gw-src.sh.in
+++ b/meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-gw-src.sh.in
@@ -33,9 +33,6 @@
 # The NCSI interface, empty if there isn't one
 gbmc_br_gw_src_ncsi_if='@NCSI_IF@'
 
-# primary IP priority should be higher than NCSI and NIC
-primary_rt_metric=700
-
 # For tray, priorize the route sent by host BMC
 primary_ip_from_br=""
 
@@ -50,26 +47,15 @@
 # just leaving them out don't remove them. Advertised route prefixes, starting
 # with the ones a previous instance left behind, see gbmc_br_gw_src_adv_load().
 declare -A gbmc_br_gw_src_adv_cur=()
-# A networkd reconfigure of an uplink drops the source we gave its default
-# routes, and we only put it back once networkd re-adds them. Keep advertising
-# routes that go missing for less than this many seconds, so the BMCs behind
-# gbmcbr don't lose them for a moment, and we don't reload networkd twice.
-GBMC_BR_GW_SRC_ADV_GRACE=5
-# Advertised route prefix that went missing -> uptime when we withdraw it
+# Advertised route prefix that went missing -> uptime when we withdraw it,
+# after GBMC_BR_RA_GRACE seconds
 declare -A gbmc_br_gw_src_adv_gone=()
-# The metric used on the tray for /124s from BMCs predating the metric
-# encoding, the same as the fallback route they used to get from gbmc-br-ra.
-GBMC_BR_GW_SRC_LEGACY_METRIC=2000
 
 # Advertised route prefix -> gateway, for trays
 declare -A gbmc_br_gw_src_br_routes=()
 # Advertised route prefix -> uptime when we give up on it coming back, for
-# trays. See GBMC_BR_GW_SRC_BR_GRACE.
+# trays, after GBMC_BR_RA_GRACE seconds
 declare -A gbmc_br_gw_src_br_gone=()
-# networkd flushes RA learned routes whenever it reconfigures gbmcbr, and they
-# only come back with the next RA (it solicits one right away). Only forget
-# an advertised route if it stays gone for this many seconds.
-GBMC_BR_GW_SRC_BR_GRACE=5
 # Installed default route metric -> "<gateway> <source>", for trays
 declare -A gbmc_br_gw_src_br_installed=()
 
@@ -85,9 +71,10 @@
 gbmc_br_tray_metric() {
   local -n tray_metric_out="$1"
   local metric="$2"
+  local base="$GBMC_ROUTE_METRIC_FALLBACK_OFFSET"
   [[ $metric =~ ^[0-9]+$ ]] || return 1
-  (( metric < 2000 && metric % 1000 >= 100 && metric % 10 == 0 )) || return 1
-  tray_metric_out=$(( (metric / 1000 + 1) * 1000 + metric % 1000 / 10 ))
+  (( metric < 2 * base && metric % base >= 100 && metric % 10 == 0 )) || return 1
+  tray_metric_out=$(( (metric / base + 1) * base + metric % base / 10 ))
 }
 
 # Builds the advertised /124 prefix (without length) for a head default route.
@@ -170,13 +157,13 @@
 
    local route_new
    route_new=$(echo "$route" | sed -E 's/ metric [0-9]+//')
-   echo "gBMC Bridge primary IP route $op (metric $primary_rt_metric): $route_new" >&2
+   echo "gBMC Bridge primary IP route $op (metric $GBMC_ROUTE_METRIC_PRIMARY): $route_new" >&2
    if [[ "$op" == "del" ]]; then
      # shellcheck disable=SC2086
-     ip route "$op" $route_new metric "$primary_rt_metric" 2>/dev/null
+     ip route "$op" $route_new metric "$GBMC_ROUTE_METRIC_PRIMARY" 2>/dev/null
    else
      # shellcheck disable=SC2086
-     ip route "$op" $route_new metric "$primary_rt_metric"
+     ip route "$op" $route_new metric "$GBMC_ROUTE_METRIC_PRIMARY"
    fi
 }
 
@@ -221,7 +208,7 @@
       # networkd reconfigures its interface and we put its source back
       local deadline="${gbmc_br_gw_src_adv_gone["$pfx"]-}"
       if [[ -z $deadline ]]; then
-        deadline=$(( now + GBMC_BR_GW_SRC_ADV_GRACE ))
+        deadline=$(( now + GBMC_BR_RA_GRACE ))
         gbmc_br_gw_src_adv_gone["$pfx"]=$deadline
       fi
       if (( deadline > now )); then
@@ -297,7 +284,7 @@
 
   read -r -d '' ra_metric <<EOF
 [IPv6AcceptRA]
-RouteMetric=2048
+RouteMetric=$GBMC_ROUTE_METRIC_L2BR
 EOF
   mkdir -p "$(dirname "$fpath")"
   printf '%s\n' "$ra_metric" >"$fpath"
@@ -429,7 +416,7 @@
   for route in "${!gbmc_br_gw_src_routes[@]}"; do
     local new_src=
     local new_len=16
-    local new_metric=4096
+    local new_metric="$GBMC_ROUTE_METRIC_UNSET"
     [[ "$route" =~ dev' '([^ ]+) ]] || continue
     local dev="${BASH_REMATCH[1]}"
     for ip in "${!gbmc_br_gw_src_ips[@]}"; do
@@ -449,11 +436,11 @@
       #      From the NIC over NCSI with the /64 shared with the CN
       #   3. BMC stateless (2620:15c:2c3:aaae:fd00:3c8d:20dc:263e/80)
       #      From the NIC, but derived from the MAC and typically never used
-      local metric="${dev_ip_to_metric["$dev-$ip"]-4097}"
+      local metric="${dev_ip_to_metric["$dev-$ip"]-$(( GBMC_ROUTE_METRIC_UNSET + 1 ))}"
       # NIC addresses always belong on their NIC path, even before the policy
       # rules routing them out there exist
-      if [[ -n ${ip_nic["$ip"]-} ]] && (( metric > 4095 )); then
-        metric=4095
+      if [[ -n ${ip_nic["$ip"]-} ]] && (( metric > GBMC_ROUTE_METRIC_NIC_FALLBACK )); then
+        metric="$GBMC_ROUTE_METRIC_NIC_FALLBACK"
       fi
       local ip_len="${gbmc_br_gw_src_ips["$ip"]}"
       if (( metric < new_metric || (metric == new_metric && ip_len < new_len) )); then
@@ -493,11 +480,11 @@
       ip route del $base_route 2>/dev/null || true
       continue
     fi
-    local rt_metric=4096  # Use a default that will be recognized as invalid
+    local rt_metric="$GBMC_ROUTE_METRIC_UNSET"  # Use a default that will be recognized as invalid
     if [[ "$route" =~ ' metric '([^ ]+) ]]; then
       rt_metric="${BASH_REMATCH[1]}"
     fi
-    if (( rt_metric <= 1536 )) && [[ "$new_src" == "$primary_ip" ]]; then
+    if (( rt_metric <= GBMC_ROUTE_METRIC_PRIMARY_MAX )) && [[ "$new_src" == "$primary_ip" ]]; then
       # Add primary src ip for the GW
       gbmc_br_config_primary_ip "$base_route src $new_src" "replace"
     fi
@@ -584,8 +571,8 @@
     local metric tray_metric
     gbmc_br_adv_metric metric "$pfx" || continue
     if (( metric == 0 )); then
-      tray_metric="$GBMC_BR_GW_SRC_LEGACY_METRIC"
-      metric=$(( tray_metric - 1000 ))
+      tray_metric="$GBMC_ROUTE_METRIC_TRAY_LEGACY"
+      metric=$(( tray_metric - GBMC_ROUTE_METRIC_FALLBACK_OFFSET ))
     else
       gbmc_br_tray_metric tray_metric "$metric" || continue
     fi
@@ -679,7 +666,7 @@
       fi
     fi
     # ignore the primary route as this script fully controls it
-    if [[ $route == *" metric $primary_rt_metric "* ]]; then
+    if [[ $route == *" metric $GBMC_ROUTE_METRIC_PRIMARY "* ]]; then
       gbmc_br_gw_src_adv_update
       return
     fi
@@ -776,8 +763,8 @@
       [[ -z ${gbmc_br_gw_src_br_gone["$brpfx"]-} ]] || return 0
       local now
       gbmc_ip_monitor_uptime now || return
-      gbmc_br_gw_src_br_gone["$brpfx"]=$(( now + GBMC_BR_GW_SRC_BR_GRACE ))
-      gbmc_ip_monitor_timer gbmc-br-gw-src-br "$GBMC_BR_GW_SRC_BR_GRACE"
+      gbmc_br_gw_src_br_gone["$brpfx"]=$(( now + GBMC_BR_RA_GRACE ))
+      gbmc_ip_monitor_timer gbmc-br-gw-src-br "$GBMC_BR_RA_GRACE"
     fi
   fi
 }
diff --git a/meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-lib.sh b/meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-lib.sh
index 6414c33..a60c758 100644
--- a/meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-lib.sh
+++ b/meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-lib.sh
@@ -89,10 +89,6 @@
   return $rc
 }
 
-# Lifetime of everything we advertise to the BMCs behind gbmcbr, the same as
-# our RouterLifetimeSec. networkd sends unsolicited RAs at least that often
-# and the BMCs behind us solicit one every 30s.
-GBMC_BR_RA_LIFETIME=120
 GBMC_BR_WITHDRAWN_DIRS=(/run/systemd/network/{00,}-bmc-gbmcbr.network.d)
 
 # shellcheck disable=SC2034  # nameref
@@ -289,11 +285,11 @@
 ValidLifetimeSec=$GBMC_BR_RA_LIFETIME
 [Route]
 Destination=$stateless_pfx/80
-Metric=512
+Metric=$GBMC_ROUTE_METRIC_ONLINK
 [Route]
 Destination=$stateless_pfx/$stateless_size
 Type=unreachable
-Metric=1024
+Metric=$GBMC_ROUTE_METRIC_CATCHALL
 EOF
   fi
   echo "Adding runtime gbmcbr IP: $name $pfx stateless($stateless_pfx/$stateless_size)" >&2
diff --git a/meta-google/recipes-google/networking/gbmc-net-common/gbmc-net-lib.sh b/meta-google/recipes-google/networking/gbmc-net-common/gbmc-net-lib.sh
index 0a6f1f9..930ed6c 100644
--- a/meta-google/recipes-google/networking/gbmc-net-common/gbmc-net-lib.sh
+++ b/meta-google/recipes-google/networking/gbmc-net-common/gbmc-net-lib.sh
@@ -366,6 +366,102 @@
 
 GBMC_INTF_ROUTE_TABLE_BASE=1000
 
+# Route metrics. The default route metrics form a preference order for
+# reaching the ToR (lower wins); the other metrics mostly keep a route we add
+# with `ip route` identical to the copy networkd installs from our drop-ins,
+# so the two merge instead of duplicating, and distinct from the kernel's own
+# prefix routes (256) and networkd's RA routes (RouteMetric=1056 on gbmcbr).
+#
+# Default routes in the main table, by uplink:
+#   700  Whichever uplink route below is sourced from the primary IP, copied
+#        to this metric so the primary address always wins source selection.
+#   800  Front panel RJ45, from a live RA (gbmc-nic-ra). Closest to the ToR.
+#   900  NCSI / in-band NIC, from a live RA (gbmc-ncsi-ra).
+#   +1000 (1800, 1900)  The same uplinks from the last RA we saw, cached in
+#        /run and /var so we have a gateway before the first live RA arrives.
+#   1536 Highest metric still eligible for the 700 copy, i.e. live uplinks
+#        only, never a cached route. Routes through gbmcbr never get copied
+#        either, whatever their metric.
+#
+# Default routes on a tray, through the head BMC over gbmcbr. The head
+# advertises each of its uplinks with its metric (see gbmc_br_adv_pfx) and the
+# tray bumps it to the next thousand, keeping the uplink digit in the tens
+# (800 -> 1080, 1800 -> 2080, see gbmc_br_tray_metric):
+#   1070, 1080, 1090  The head's live uplinks. Below the tray's own cached
+#        routes (1800+) so a head with a live ToR beats a stale cache, above
+#        its own live uplinks (800, 900) so a tray with its own ToR uses it.
+#   2080, 2090  The head's cached uplinks.
+#   2000 A head too old to encode the metric in its advertisement.
+#   2048 l2br RA routes once the head is advertising, so they lose to it.
+#
+# Prefix routes on gbmcbr:
+#   512  Specific on-link prefixes: the /80s downstream BMCs autoconfigure in,
+#        RA prefixes we hold an address in, and the per-interface routing
+#        table (GBMC_INTF_ROUTE_TABLE_BASE + ifindex) default routes.
+#   1024 Catch-all routes for a whole allocation: unreachable for the unused
+#        rest of a /64 or /76, and the compute node's half (/65) of its /64.
+#
+# Source selection pseudo-metrics in gbmc-br-gw-src, not installed anywhere:
+#   4095 An NCSI NIC address on its own NIC before its policy rules exist.
+#   4096 No route / unknown metric.
+# shellcheck disable=SC2034
+GBMC_ROUTE_METRIC_PRIMARY=700
+# shellcheck disable=SC2034
+GBMC_ROUTE_METRIC_FRONT_PANEL=800
+# shellcheck disable=SC2034
+GBMC_ROUTE_METRIC_NCSI=900
+# shellcheck disable=SC2034
+GBMC_ROUTE_METRIC_FALLBACK_OFFSET=1000
+# shellcheck disable=SC2034
+GBMC_ROUTE_METRIC_PRIMARY_MAX=1536
+# shellcheck disable=SC2034
+GBMC_ROUTE_METRIC_TRAY_LEGACY=2000
+# shellcheck disable=SC2034
+GBMC_ROUTE_METRIC_L2BR=2048
+# shellcheck disable=SC2034
+GBMC_ROUTE_METRIC_ONLINK=512
+# shellcheck disable=SC2034
+GBMC_ROUTE_METRIC_CATCHALL=1024
+# shellcheck disable=SC2034
+GBMC_ROUTE_METRIC_NIC_FALLBACK=4095
+# shellcheck disable=SC2034
+GBMC_ROUTE_METRIC_UNSET=4096
+
+# Address label (RFC 6724 rule 6) for the /80 prefixes we autoconfigure an
+# address in from gbmcbr RAs. Global destinations carry the default label 1,
+# as does our primary /128, so a source with a different label only gets
+# picked for destinations inside its own /80 or when a route names it.
+# shellcheck disable=SC2034
+GBMC_SLAAC_ADDRLABEL=99
+
+# Router discovery timers, in seconds:
+#   GBMC_RA_TIMEOUT      How long each rdisc6 solicitation waits for RAs.
+#   GBMC_RA_MIN_RETRY    Solicitation interval until we have a router.
+#   GBMC_RA_RS_INTERVAL  Solicitation interval once we do.
+#   GBMC_RA_EXPIRE       Without an RA for this long a router is dropped and
+#                        the next one we heard from takes over.
+#   GBMC_BR_RA_LIFETIME  Lifetime of the router, prefixes and routes we
+#                        advertise on gbmcbr, 4 solicitation intervals so the
+#                        BMCs behind us refresh well before it runs out.
+#   GBMC_BR_RA_GRACE     How long an RA route may be missing before we act on
+#                        it. A networkd reconfigure flushes the RA routes and
+#                        strips the source off our uplink routes; it solicits a
+#                        new RA right away and we put the source back, so
+#                        waiting this long avoids tearing down addresses and
+#                        advertisements that are about to come back.
+# shellcheck disable=SC2034
+GBMC_RA_TIMEOUT=10
+# shellcheck disable=SC2034
+GBMC_RA_MIN_RETRY=10
+# shellcheck disable=SC2034
+GBMC_RA_RS_INTERVAL=30
+# shellcheck disable=SC2034
+GBMC_RA_EXPIRE=180
+# shellcheck disable=SC2034
+GBMC_BR_RA_LIFETIME=120
+# shellcheck disable=SC2034
+GBMC_BR_RA_GRACE=5
+
 # Calculate and print the deterministic routing table number for a network
 # interface based on its kernel ifindex.
 # The table number is calculated as GBMC_INTF_ROUTE_TABLE_BASE (1000) + ifindex.
diff --git a/meta-google/recipes-google/networking/gbmc-net-common/gbmc-ra.sh b/meta-google/recipes-google/networking/gbmc-net-common/gbmc-ra.sh
index 5d90bf0..323ed4b 100644
--- a/meta-google/recipes-google/networking/gbmc-net-common/gbmc-ra.sh
+++ b/meta-google/recipes-google/networking/gbmc-net-common/gbmc-ra.sh
@@ -25,7 +25,7 @@
 # routing table, without any default routes in the main table.
 ROUTE_METRIC_LO=
 if [ -n "$ROUTE_METRIC" ]; then
-  ROUTE_METRIC_LO="$((ROUTE_METRIC+1000))"
+  ROUTE_METRIC_LO="$((ROUTE_METRIC + GBMC_ROUTE_METRIC_FALLBACK_OFFSET))"
 fi
 
 # We would prefer empty string but it's easier for associative array handling
@@ -58,8 +58,8 @@
     mkdir -p "$file.d"
     printf '[Neighbor]\nMACAddress=%s\nAddress=%s\n' \
       "$mac" "$rtr" >"$file.d"/10-gateway.conf
-    printf '[Route]\nGateway=%s\nGatewayOnLink=true\nMetric=512\nTable=%d\n' \
-      "$rtr" "$route_table" >>"$file.d"/10-gateway.conf
+    printf '[Route]\nGateway=%s\nGatewayOnLink=true\nMetric=%d\nTable=%d\n' \
+      "$rtr" "$GBMC_ROUTE_METRIC_ONLINK" "$route_table" >>"$file.d"/10-gateway.conf
     if [ -n "$ROUTE_METRIC" ]; then
       printf '[Route]\nGateway=%s\nGatewayOnLink=true\nMetric=%d\n' \
         "$rtr" "$ROUTE_METRIC_LO" >>"$file.d"/10-gateway.conf
@@ -84,7 +84,7 @@
   # Fall back to reload only if ip link commands fail
   local st=0
   ip -6 neigh replace "$rtr" dev "$RA_IF" lladdr "$mac" || st=$?
-  ip -6 route replace default via "$rtr" onlink dev "$RA_IF" metric 512 table "$route_table" || st=$?
+  ip -6 route replace default via "$rtr" onlink dev "$RA_IF" metric "$GBMC_ROUTE_METRIC_ONLINK" table "$route_table" || st=$?
   if [ -n "$ROUTE_METRIC" ]; then
     ip -6 route replace default via "$rtr" onlink dev "$RA_IF" metric "$ROUTE_METRIC_LO" || st=$?
   fi
@@ -153,13 +153,13 @@
 }
 
 # mininum retry time
-min_w=10
+min_w="$GBMC_RA_MIN_RETRY"
 # rdisc time
-r_timeout=10
+r_timeout="$GBMC_RA_TIMEOUT"
 # routing expiration time
-expire_time=180
+expire_time="$GBMC_RA_EXPIRE"
 # rs intervals
-rs_intervals=30
+rs_intervals="$GBMC_RA_RS_INTERVAL"
 declare -A rtrs
 rtrs=()
 while true; do
diff --git a/meta-google/recipes-google/networking/gbmc-nic-config/gbmc-nic-cn.sh.in b/meta-google/recipes-google/networking/gbmc-nic-config/gbmc-nic-cn.sh.in
index 7e8b909..5e49a4d 100644
--- a/meta-google/recipes-google/networking/gbmc-nic-config/gbmc-nic-cn.sh.in
+++ b/meta-google/recipes-google/networking/gbmc-nic-config/gbmc-nic-cn.sh.in
@@ -39,7 +39,7 @@
   read -r -d '' contents <<EOF
 [Route]
 Destination=$ip/65
-Metric=1024
+Metric=$GBMC_ROUTE_METRIC_CATCHALL
 EOF
   local i
   local cn_ip
@@ -60,7 +60,7 @@
   done
 
   local st=0
-  ip -6 route add "$ip/65" dev gbmcbr metric 1024 2>dev/null || true
+  ip -6 route add "$ip/65" dev gbmcbr metric "$GBMC_ROUTE_METRIC_CATCHALL" 2>dev/null || true
   for intf in "${gbmc_nic_cn_intfs[@]}"; do
     if [[ "$act" == add ]]; then
       for cn_ip in "${cn_ips[@]}"; do
diff --git a/meta-google/recipes-google/networking/gbmc-nic-config/gbmc-nic-ra.sh b/meta-google/recipes-google/networking/gbmc-nic-config/gbmc-nic-ra.sh
index 98239c3..65ae3d5 100755
--- a/meta-google/recipes-google/networking/gbmc-nic-config/gbmc-nic-ra.sh
+++ b/meta-google/recipes-google/networking/gbmc-nic-config/gbmc-nic-ra.sh
@@ -25,11 +25,14 @@
   true
 }
 
+# shellcheck source=meta-google/recipes-google/networking/gbmc-net-common/gbmc-net-lib.sh
+source /usr/share/gbmc-net-lib.sh || exit
+
 RA_IF=$1
 IP_OFFSET=0
 # This is guaranteed to be closer to the ToR than NCSI, for reliability
 # and bandwidth we want to prefer this path.
-ROUTE_METRIC=800
+ROUTE_METRIC="$GBMC_ROUTE_METRIC_FRONT_PANEL"
 
 # shellcheck source=meta-google/recipes-google/networking/gbmc-net-common/gbmc-ra.sh
 source /usr/share/gbmc-ra.sh || exit