meta-google: gbmc-bridge: Handle multiple internal prefixes

Since we have a direct path and sideband path for networking now, we
need both to register as trusted internal paths when communicating with
BMCs inside the node.

Change-Id: I91d72e7cddf6c919422a4fcceec6b386bab2ea2b
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-nft.sh b/meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-nft.sh
index 79ea76f..f64e53e 100644
--- a/meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-nft.sh
+++ b/meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-nft.sh
@@ -18,19 +18,18 @@
 # shellcheck source=meta-google/recipes-google/networking/network-sh/lib.sh
 source /usr/share/network/lib.sh || exit
 
-gbmc_br_nft_pfx=
+declare -A gbmc_br_nft_pfx=()
 
 gbmc_br_nft_update() {
-  printf 'gBMC Bridge input firewall for %s\n' \
-    "${gbmc_br_nft_pfx:-(deleted)}" >&2
+  printf 'gBMC Bridge input firewall for %s\n' "${!gbmc_br_nft_pfx[*]}" >&2
 
   local contents=
   contents+='table inet filter {'$'\n'
   contents+='    chain gbmc_br_int_input {'$'\n'
-  if [[ -n ${gbmc_br_nft_pfx-} ]]; then
-    contents+="        ip6 saddr $gbmc_br_nft_pfx"
-    contents+=" ip6 daddr $gbmc_br_nft_pfx accept"$'\n'
-  fi
+  local pfx
+  for pfx in "${!gbmc_br_nft_pfx[@]}"; do
+    contents+="        ip6 saddr $pfx accept"$'\n'
+  done
   contents+='    }'$'\n'
   contents+='}'$'\n'
 
@@ -54,19 +53,33 @@
       echo "gBMC Bridge NFT Invalid IP: $ip" >&2
       return 1
     fi
-    if (( ip_bytes[8] != 0xfd )); then
+    # Ignore ULAs
+    if (( (ip_bytes[0] & 0xfe) == 0xfc )); then
       return 0
     fi
 
-    (( ip_bytes[9] &= 0xf0 ))
-
+    # We assume the entire machine /64 is allowed, so remove the suffix of the address
     local i
-    for (( i=10; i<16; i++ )); do
+    for (( i=8; i<16; ++i )); do
       ip_bytes["$i"]=0
     done
-    pfx="$(ip_bytes_to_str ip_bytes)/76"
-    if [[ $action == add && $pfx != "$gbmc_br_nft_pfx" ]]; then
-      gbmc_br_nft_pfx="$pfx"
+
+    # Update the value tracking the number of users for a subnet
+    pfx="$(ip_bytes_to_str ip_bytes)/64"
+    local old=${gbmc_br_nft_pfx["$pfx"]-0}
+    local new
+    if [[ $action == add ]]; then
+      new=$((old + 1))
+    elif [[ $action == del ]]; then
+      new=$((old - 1))
+    fi
+    if (( new <= 0 )); then
+      unset 'gbmc_br_nft_pfx["$pfx"]'
+    else
+      gbmc_br_nft_pfx["$pfx"]=$new
+    fi
+
+    if (( old <= 0 && new >= 1 || old >= 1 && new <= 0 )); then
       gbmc_br_nft_update
     fi
   fi