summaryrefslogtreecommitdiff
path: root/meta-google/recipes-google
diff options
context:
space:
mode:
Diffstat (limited to 'meta-google/recipes-google')
-rw-r--r--meta-google/recipes-google/google-misc/google-misc.inc2
-rw-r--r--meta-google/recipes-google/ipmi/google-ipmi-sys_git.bb2
-rw-r--r--meta-google/recipes-google/nanopb/nanopb-generator_0.4.8.bb14
-rw-r--r--meta-google/recipes-google/nanopb/nanopb-runtime_0.4.8.bb17
-rw-r--r--meta-google/recipes-google/nanopb/nanopb.bb17
-rw-r--r--meta-google/recipes-google/nanopb/nanopb.inc13
-rw-r--r--meta-google/recipes-google/ncsi/files/gbmc-ncsi-br-deprecated-ips.sh.in34
-rw-r--r--meta-google/recipes-google/ncsi/files/gbmc-ncsi-dhcrelay.service.in6
-rw-r--r--meta-google/recipes-google/ncsi/files/gbmc-ncsi-ip-from-ra.service.in15
-rwxr-xr-xmeta-google/recipes-google/ncsi/files/gbmc-ncsi-ip-from-ra.sh.in97
-rw-r--r--meta-google/recipes-google/ncsi/files/gbmc-ncsi-ra.service.in15
-rw-r--r--meta-google/recipes-google/ncsi/files/gbmc-ncsi-ra.sh91
-rw-r--r--meta-google/recipes-google/ncsi/files/gbmc-ncsi-smartnic-wa.sh.in24
-rw-r--r--meta-google/recipes-google/ncsi/gbmc-ncsi-config.bb40
-rw-r--r--meta-google/recipes-google/ncsi/ncsid_git.bb13
-rw-r--r--meta-google/recipes-google/networking/dhcp-done_git.bb5
-rw-r--r--meta-google/recipes-google/networking/gbmc-bridge.bb35
-rw-r--r--meta-google/recipes-google/networking/gbmc-bridge/-bmc-gbmcbr.network.in12
-rw-r--r--meta-google/recipes-google/networking/gbmc-bridge/50-gbmc-psu-hardreset.sh.in (renamed from meta-google/recipes-google/networking/gbmc-bridge/50-gbmc-psu-hardreset.sh)11
-rw-r--r--meta-google/recipes-google/networking/gbmc-bridge/51-gbmc-reboot.sh (renamed from meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-ensure-ra.sh)34
-rw-r--r--meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-dhcp.service9
-rw-r--r--meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-dhcp.sh15
-rw-r--r--meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-ensure-ra.service5
-rw-r--r--meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-gw-src.sh76
-rw-r--r--meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-hostname.service8
-rwxr-xr-xmeta-google/recipes-google/networking/gbmc-bridge/gbmc-br-hostname.sh35
-rw-r--r--meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-lib.sh21
-rw-r--r--meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-nft.sh5
-rw-r--r--meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-ra.service13
-rwxr-xr-xmeta-google/recipes-google/networking/gbmc-bridge/gbmc-br-ra.sh.in42
-rw-r--r--meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-ula.sh98
-rw-r--r--meta-google/recipes-google/networking/gbmc-bridge/gbmc-start-dhcp.sh4
-rw-r--r--meta-google/recipes-google/networking/gbmc-net-common.bb27
-rw-r--r--meta-google/recipes-google/networking/gbmc-net-common/gbmc-net-lib.sh31
-rw-r--r--meta-google/recipes-google/networking/gbmc-net-common/gbmc-ra.sh188
-rw-r--r--meta-google/recipes-google/networking/gbmc-nic-config.bb79
-rw-r--r--meta-google/recipes-google/networking/gbmc-nic-config/-bmc-gbmcbrnicdhcp.netdev5
-rw-r--r--meta-google/recipes-google/networking/gbmc-nic-config/-bmc-gbmcbrnicdhcp.network4
-rw-r--r--meta-google/recipes-google/networking/gbmc-nic-config/-bmc-gbmcnicdhcp.netdev5
-rw-r--r--meta-google/recipes-google/networking/gbmc-nic-config/-bmc-gbmcnicdhcp.network9
-rw-r--r--meta-google/recipes-google/networking/gbmc-nic-config/-bmc-nic.network.in8
-rw-r--r--meta-google/recipes-google/networking/gbmc-nic-config/50-gbmc-nic.rules8
-rw-r--r--meta-google/recipes-google/networking/gbmc-nic-config/50-gbmc-nic.rules.in19
-rw-r--r--meta-google/recipes-google/networking/gbmc-nic-config/gbmc-nic-dhcrelay.service.in13
-rw-r--r--meta-google/recipes-google/networking/gbmc-nic-config/gbmc-nic-neigh.sh.in98
-rwxr-xr-xmeta-google/recipes-google/networking/gbmc-nic-config/gbmc-nic-ra.sh35
-rw-r--r--meta-google/recipes-google/networking/gbmc-nic-config/gbmc-nic-ra@.service13
-rw-r--r--meta-google/recipes-google/systemd/files/40-gbmc-sysctl.conf2
48 files changed, 1028 insertions, 344 deletions
diff --git a/meta-google/recipes-google/google-misc/google-misc.inc b/meta-google/recipes-google/google-misc/google-misc.inc
index 477009357d..75c6606735 100644
--- a/meta-google/recipes-google/google-misc/google-misc.inc
+++ b/meta-google/recipes-google/google-misc/google-misc.inc
@@ -6,7 +6,7 @@ LICENSE = "Apache-2.0"
LIC_FILES_CHKSUM = "file://../../LICENSE;md5=34400b68072d710fecd0a2940a0d1658"
SRC_URI += "git://github.com/openbmc/google-misc;branch=master;protocol=https"
-SRCREV = "4dba220d361271859f824aaa2c7861ceb63ca2dd"
+SRCREV = "a06304b02fa5c4cd9f576a2191994a8259900cba"
S = "${WORKDIR}/git/subprojects/${GOOGLE_MISC_PROJ}"
inherit meson pkgconfig
diff --git a/meta-google/recipes-google/ipmi/google-ipmi-sys_git.bb b/meta-google/recipes-google/ipmi/google-ipmi-sys_git.bb
index 850d9b4715..d09eaae05a 100644
--- a/meta-google/recipes-google/ipmi/google-ipmi-sys_git.bb
+++ b/meta-google/recipes-google/ipmi/google-ipmi-sys_git.bb
@@ -23,7 +23,7 @@ RDEPENDS:${PN} += " \
S = "${WORKDIR}/git"
SRC_URI = "git://github.com/openbmc/google-ipmi-sys;branch=master;protocol=https"
-SRCREV = "9846023c7e811d6f831941d37270b10046916fef"
+SRCREV = "e89296998b00d3e92361fdb37152a18566cf4505"
FILES:${PN} += "${libdir}/ipmid-providers"
diff --git a/meta-google/recipes-google/nanopb/nanopb-generator_0.4.8.bb b/meta-google/recipes-google/nanopb/nanopb-generator_0.4.8.bb
deleted file mode 100644
index c86750f8b6..0000000000
--- a/meta-google/recipes-google/nanopb/nanopb-generator_0.4.8.bb
+++ /dev/null
@@ -1,14 +0,0 @@
-require nanopb.inc
-
-inherit python3-dir
-
-DEPENDS = "protobuf-native"
-RDEPENDS:${PN} += "python3-protobuf"
-
-EXTRA_OECMAKE += " \
- -Dnanopb_PYTHON_INSTDIR_OVERRIDE=${PYTHON_SITEPACKAGES_DIR} \
- -Dnanopb_BUILD_RUNTIME=OFF \
- -Dnanopb_BUILD_GENERATOR=ON \
- "
-
-FILES:${PN} += "${PYTHON_SITEPACKAGES_DIR}"
diff --git a/meta-google/recipes-google/nanopb/nanopb-runtime_0.4.8.bb b/meta-google/recipes-google/nanopb/nanopb-runtime_0.4.8.bb
deleted file mode 100644
index e43931a4ec..0000000000
--- a/meta-google/recipes-google/nanopb/nanopb-runtime_0.4.8.bb
+++ /dev/null
@@ -1,17 +0,0 @@
-require nanopb.inc
-
-EXTRA_OECMAKE += " \
- -Dnanopb_PROTOC_PATH=/bin/false \
- -DBUILD_SHARED_LIBS=ON \
- -Dnanopb_BUILD_RUNTIME=ON \
- -Dnanopb_BUILD_GENERATOR=OFF \
- "
-
-# Maintain compatability with old header locations for packages
-# which haven't yet migrated to `nanopb/pb*.h`
-do_install:append() {
- for hdr in ${D}${includedir}/nanopb/*; do
- ln -sv nanopb/$(basename "$hdr") ${D}${includedir}/
- done
-}
-
diff --git a/meta-google/recipes-google/nanopb/nanopb.bb b/meta-google/recipes-google/nanopb/nanopb.bb
deleted file mode 100644
index 7ad6a32782..0000000000
--- a/meta-google/recipes-google/nanopb/nanopb.bb
+++ /dev/null
@@ -1,17 +0,0 @@
-SUMMARY = "Combined nanopb package"
-PV = "1.0"
-PR = "r1"
-
-PACKAGE_ARCH = "${MACHINE_ARCH}"
-
-inherit packagegroup
-
-DEPENDS = " \
- nanopb-generator \
- nanopb-runtime \
-"
-
-RDEPENDS:${PN} = " \
- nanopb-generator \
- nanopb-runtime \
-"
diff --git a/meta-google/recipes-google/nanopb/nanopb.inc b/meta-google/recipes-google/nanopb/nanopb.inc
deleted file mode 100644
index 87dbc73e63..0000000000
--- a/meta-google/recipes-google/nanopb/nanopb.inc
+++ /dev/null
@@ -1,13 +0,0 @@
-DESCRIPTION="Protocol Buffers with small code size"
-LICENSE="Zlib"
-LIC_FILES_CHKSUM = "file://LICENSE.txt;md5=9db4b73a55a3994384112efcdb37c01f"
-
-SRC_URI = "git://github.com/nanopb/nanopb.git;branch=master;protocol=https"
-SRCREV = "6cfe48d6f1593f8fa5c0f90437f5e6522587745e"
-
-S = "${WORKDIR}/git"
-
-inherit cmake
-
-BBCLASSEXTEND = "native nativesdk"
-
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 b392176483..c2783be525 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
@@ -15,6 +15,7 @@
[ -n "${gbmc_ncsi_br_deprecated_ips_lib-}" ] && return
source /usr/share/network/lib.sh || exit
+source /usr/share/gbmc-net-lib.sh || exit
gbmc_ncsi_br_deprecated_ips_init=
gbmc_ncsi_br_deprecated_ips_confip=
@@ -22,6 +23,8 @@ gbmc_ncsi_br_deprecated_ips_lastip=
gbmc_ncsi_br_deprecated_ips_lastncsi=
gbmc_ncsi_br_deprecated_ips_confncsi=
+GBMC_NCSI_ROUTE_TABLE=900
+
gbmc_ncsi_br_deprecated_ips_update() {
[ -n "$gbmc_ncsi_br_deprecated_ips_init" ] || return
[ "$gbmc_ncsi_br_deprecated_ips_confip" != "$gbmc_ncsi_br_deprecated_ips_lastip" ] || \
@@ -62,6 +65,10 @@ IPv6ProxyNDPAddress=$pfx
IPv6ProxyNDPAddress=$stateless_pfx
${host_pfx:+IPv6ProxyNDPAddress=}$host_pfx
${stateless_ip:+IPv6ProxyNDPAddress=}$stateless_ip
+[RoutingPolicyRule]
+From=$pfx/76
+Table=$GBMC_NCSI_ROUTE_TABLE
+Priority=$GBMC_NCSI_ROUTE_TABLE
EOF
read -r -d '' nfcontents <<EOF
table inet filter {
@@ -86,14 +93,31 @@ EOF
fi
done
- # Ensure that systemd-networkd performs a reconfiguration as it doesn't
- # currently check the mtime of drop-in files.
- touch -c /etc/systemd/network/*-bmc-@NCSI_IF@.network
+ # Remove all old ncsi neighbor proxied entries, since we solely
+ # manage all of these entries and we don't want any that are stale
+ local entry
+ while read -r entry; do
+ ip -6 neigh del proxy ${entry%% *} dev @NCSI_IF@ || true
+ done < <(ip -6 neigh show proxy dev @NCSI_IF@)
+ ip -6 rule del pref $GBMC_NCSI_ROUTE_TABLE 2>/dev/null || true
- if [ "$(systemctl is-active systemd-networkd)" != 'inactive' ]; then
- networkctl reload && networkctl reconfigure @NCSI_IF@
+ local st=0
+ if [ -n "$gbmc_ncsi_br_deprecated_ips_lastip" ]; then
+ sysctl net.ipv6.conf.@NCSI_IF@.proxy_ndp=1 >/dev/null || st=$?
+ ip -6 neigh add proxy $pfx dev @NCSI_IF@ || st=$?
+ ip -6 neigh add proxy $stateless_pfx dev @NCSI_IF@ || st=$?
+ if [ -n "$host_pfx" ]; then
+ ip -6 neigh add proxy $host_pfx dev @NCSI_IF@ || st=$?
+ fi
+ if [ -n "$stateless_ip" ]; then
+ ip -6 neigh add proxy $stateless_ip dev @NCSI_IF@ || st=$?
+ fi
+ ip -6 rule add pref $GBMC_NCSI_ROUTE_TABLE from $pfx/76 \
+ lookup $GBMC_NCSI_ROUTE_TABLE || st=$?
fi
+ (( st == 0 )) || gbmc_net_networkd_reload @NCSI_IF@
+
local rfile=/run/nftables/40-gbmc-ncsi-br.rules
mkdir -p -m 755 "$(dirname "$rfile")"
if [ -z "$nfcontents" ]; then
diff --git a/meta-google/recipes-google/ncsi/files/gbmc-ncsi-dhcrelay.service.in b/meta-google/recipes-google/ncsi/files/gbmc-ncsi-dhcrelay.service.in
index 62a519a2da..c085cbcdec 100644
--- a/meta-google/recipes-google/ncsi/files/gbmc-ncsi-dhcrelay.service.in
+++ b/meta-google/recipes-google/ncsi/files/gbmc-ncsi-dhcrelay.service.in
@@ -3,11 +3,15 @@ Description=gBMC DHCP Relay Agent Daemon
After=network.target
StartLimitIntervalSec=10
StartLimitBurst=3
+LogRateLimitIntervalSec=120
+LogRateLimitBurst=100
[Service]
+Environment="RP_FLAG=-rp 3967"
+EnvironmentFile=-/run/gbmc-ncsi-dhcrelay.env
Restart=always
RestartSec=5
-ExecStart=/usr/sbin/dhcrelay -d --no-pid -rp 3967 -l gbmcncsidhcp -u ff02::1:2%%@NCSI_IF@
+ExecStart=/usr/sbin/dhcrelay -d --no-pid $RP_FLAG -l gbmcncsidhcp -u ff02::1:2%%@NCSI_IF@
[Install]
WantedBy=multi-user.target
diff --git a/meta-google/recipes-google/ncsi/files/gbmc-ncsi-ip-from-ra.service.in b/meta-google/recipes-google/ncsi/files/gbmc-ncsi-ip-from-ra.service.in
deleted file mode 100644
index 82972fffce..0000000000
--- a/meta-google/recipes-google/ncsi/files/gbmc-ncsi-ip-from-ra.service.in
+++ /dev/null
@@ -1,15 +0,0 @@
-[Unit]
-Description=gBMC NCSI RA Discovery
-After=network.target
-StartLimitIntervalSec=10
-StartLimitBurst=3
-Conflicts=nic-hostless@@NCSI_IF@.target
-Conflicts=nic-hostful@@NCSI_IF@.target
-
-[Service]
-Restart=always
-RestartSec=5
-ExecStart=/usr/libexec/gbmc-ncsi-ip-from-ra.sh
-
-[Install]
-WantedBy=multi-user.target
diff --git a/meta-google/recipes-google/ncsi/files/gbmc-ncsi-ip-from-ra.sh.in b/meta-google/recipes-google/ncsi/files/gbmc-ncsi-ip-from-ra.sh.in
deleted file mode 100755
index 4aae5c86b3..0000000000
--- a/meta-google/recipes-google/ncsi/files/gbmc-ncsi-ip-from-ra.sh.in
+++ /dev/null
@@ -1,97 +0,0 @@
-#!/bin/bash
-# Copyright 2021 Google LLC
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-[ ! -e /usr/share/gbmc-br-lib.sh ] && exit
-
-# shellcheck source=meta-google/recipes-google/networking/network-sh/lib.sh
-source /usr/share/network/lib.sh || exit
-# shellcheck source=meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-lib.sh
-source /usr/share/gbmc-br-lib.sh || exit
-
-NCSI_IF='@NCSI_IF@'
-
-old_pfx=
-old_fqdn=
-old_rtr=
-
-set_host() {
- [[ -n "$host" && -n "$domain" && -n "$hextet" ]] || return
-
- local fqdn="$host-n$hextet.$domain"
- [ "$fqdn" != "$old_fqdn" ] || return
- old_fqdn="$fqdn"
-
- echo "Found hostname $fqdn" >&2
- hostnamectl set-hostname "$fqdn" || true
-}
-
-set_net() {
- [[ -n "$pfx" && -n "$rtr" ]] || return
- [[ "$pfx" != "$old_pfx" || "$rtr" != "$old_rtr" ]] || return
- old_pfx="$pfx"
- old_rtr="$rtr"
-
- echo "Found prefix $pfx from $rtr" >&2
-
- # We no longer need NCSId if we are in this configuration
- systemctl stop --no-block ncsid@"$NCSI_IF" || true
-
- # Save the IP address for the interface
- gbmc_br_set_ip "$pfx" || true
-
- # DHCP Relay workaround until alternate source port is supported
- # TODO: Remove this once internal relaying cleanups land
- gbmc-ncsi-smartnic-wa.sh || true
-}
-
-w=60
-while true; do
- start=$SECONDS
- while read -r line; do
- # `script` terminates all lines with a CRLF, remove it
- line="${line:0:-1}"
- if [ -z "$line" ]; then
- hextet=
- pfx=
- host=
- domain=
- elif [[ "$line" =~ ^Prefix' '*:' '*(.*)/([0-9]+)$ ]]; then
- t_pfx="${BASH_REMATCH[1]}"
- t_pfx_len="${BASH_REMATCH[2]}"
- ip_to_bytes t_pfx_b "$t_pfx" || continue
- (( t_pfx_len == 76 && (t_pfx_b[8] & 0xfd) == 0xfd )) || continue
- (( t_pfx_b[9] |= 1 ))
- hextet="fd$(printf '%02x' "${t_pfx_b[9]}")"
- pfx="$(ip_bytes_to_str t_pfx_b)"
- elif [[ "$line" =~ ^'DNS search list'' '*:' '*([^.]+)(.*[.]google[.]com)' '*$ ]]; then
- # Ideally, we use PCRE and with lookahead and can do this in a single regex
- # ^([a-zA-Z0-9-]+(?=-n[a-fA-F0-9]{1,4})|[a-zA-Z0-9-]+(?!-n[a-fA-F0-9]{1,4}))[^.]*[.]((?:[a-zA-Z0-9]*[.])*google[.]com)$
- # Instead we do multiple steps to extract the needed info
- host="${BASH_REMATCH[1]}"
- domain="${BASH_REMATCH[2]#.}"
- if [[ "$host" =~ (-n[a-fA-F0-9]{1,4})$ ]]; then
- host="${host%"${BASH_REMATCH[1]}"}"
- fi
- elif [[ "$line" =~ ^from' '(.*)$ ]]; then
- rtr="${BASH_REMATCH[1]}"
- set_net || true
- set_host || true
- fi
- done < <(exec script -q -c "rdisc6 -d -m $NCSI_IF -w $(( w * 1000 ))" /dev/null 2>/dev/null)
- # If rdisc6 exits early we still want to wait the full `w` time before
- # starting again.
- (( timeout = start + w - SECONDS ))
- sleep $(( timeout < 0 ? 0 : timeout ))
-done
diff --git a/meta-google/recipes-google/ncsi/files/gbmc-ncsi-ra.service.in b/meta-google/recipes-google/ncsi/files/gbmc-ncsi-ra.service.in
new file mode 100644
index 0000000000..d389740b1f
--- /dev/null
+++ b/meta-google/recipes-google/ncsi/files/gbmc-ncsi-ra.service.in
@@ -0,0 +1,15 @@
+[Unit]
+Description=RA Gateway Updater
+Wants=mapper-wait@-xyz-openbmc_project-network-@NCSI_IF@.service
+After=mapper-wait@-xyz-openbmc_project-network-@NCSI_IF@.service
+After=ncsid@NCSI_IF@.service
+StartLimitIntervalSec=1min
+StartLimitBurst=5
+
+[Service]
+Restart=always
+RestartSec=5
+ExecStart=/usr/libexec/gbmc-ncsi-ra.sh @NCSI_IF@
+
+[Install]
+WantedBy=multi-user.target
diff --git a/meta-google/recipes-google/ncsi/files/gbmc-ncsi-ra.sh b/meta-google/recipes-google/ncsi/files/gbmc-ncsi-ra.sh
new file mode 100644
index 0000000000..ca8fa05caa
--- /dev/null
+++ b/meta-google/recipes-google/ncsi/files/gbmc-ncsi-ra.sh
@@ -0,0 +1,91 @@
+#!/bin/bash
+# Copyright 2024 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# 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=1
+# NCSI is known to be closer to the ToR than bridge routes. Prefer over bridge routes.
+ROUTE_METRIC=900
+ROUTE_TABLE=900
+
+update_rtr() {
+ busctl set-property xyz.openbmc_project.Network /xyz/openbmc_project/network/"$RA_IF" \
+ xyz.openbmc_project.Network.EthernetInterface DefaultGateway6 s "" || true
+
+ default_update_rtr "$@"
+
+ # Add additional gateway information
+ for file in /run/systemd/network/{00,}-bmc-$RA_IF.network; do
+ mkdir -p "$file.d"
+ printf '[Route]\nGateway=%s\nGatewayOnLink=true\nTable=%d' \
+ "$rtr" "$ROUTE_TABLE" >"$file.d"/10-gateway-table.conf
+ done
+
+ ip -6 route replace default via "$rtr" onlink dev "$RA_IF" table "$ROUTE_TABLE" || \
+ gbmc_net_networkd_reload "$RA_IF"
+}
+
+ncsi_is_active() {
+ systemctl is-active -q nic-hostless@"$RA_IF".target && return
+ systemctl is-active -q nic-hostful@"$RA_IF".target && return
+ return 1
+}
+
+update_fqdn() {
+ true
+}
+
+old_ncsi_pfx=
+
+update_pfx() {
+ local pfx="$1"
+
+ # We only do this for smartNICs (which don't use NCSI)
+ ncsi_is_active && return
+
+ # Don't change anything for an empty prefix
+ [ -z "$pfx" ] && return
+
+ # We no longer need NCSId if we are in this configuration
+ systemctl stop --no-block ncsid@"$RA_IF" || true
+
+ # DHCP Relay workaround until alternate source port is supported
+ # TODO: Remove this once internal relaying cleanups land
+ gbmc-ncsi-smartnic-wa.sh || true
+
+ # Override any existing address information within files
+ # Make sure we cover `00-*` and `-*` files
+ for file in /run/systemd/network/{00,}-bmc-gbmcbr.network; do
+ mkdir -p "$file.d"
+ printf '[Network]\nAddress=%s/128' \
+ "$pfx" >"$file.d"/10-ncsi-addr.conf
+ done
+
+ # Don't force networkd to reload as this can break phosphor-networkd
+ # Fall back to reload only if ip link commands fail
+ if [ -n "$old_ncsi_pfx" ]; then
+ ip -6 addr del "$old_ncsi_pfx/128" dev gbmcbr || true
+ fi
+ ip -6 addr replace "$pfx/128" dev gbmcbr || \
+ gbmc_net_networkd_reload gbmcbr || true
+ old_ncsi_pfx=$pfx
+
+ echo "Set NCSI addr $pfx on gbmcbr" >&2
+}
+
+# shellcheck source=meta-google/recipes-google/networking/gbmc-net-common/gbmc-ra.sh
+source /usr/share/gbmc-ra.sh || exit
diff --git a/meta-google/recipes-google/ncsi/files/gbmc-ncsi-smartnic-wa.sh.in b/meta-google/recipes-google/ncsi/files/gbmc-ncsi-smartnic-wa.sh.in
index 88f52d38e8..c05e239f7f 100644
--- a/meta-google/recipes-google/ncsi/files/gbmc-ncsi-smartnic-wa.sh.in
+++ b/meta-google/recipes-google/ncsi/files/gbmc-ncsi-smartnic-wa.sh.in
@@ -13,34 +13,18 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-HAS_DHCRELAY='@GBMC_NCSI_DHCP_RELAY@'
+HAS_DHCRELAY='@GBMC_DHCP_RELAY@'
if [ "$HAS_DHCRELAY" = 1 ]; then
- override=/run/systemd/system/gbmc-ncsi-dhcrelay.service.d/10-nosp.conf
- mkdir -p "$(dirname "$override")"
- echo '[Service]' >"$override"
- echo 'ExecStart=' >>"$override"
# Remove the source relay port from the relay, bringing it back to run on
# the default port 547. Our relays don't support the source port option needed
# to run on 3967 for our legacy NICs.
- grep '^ExecStart=' /lib/systemd/system/gbmc-ncsi-dhcrelay.service | \
- sed 's, -rp 3967,,' >>"$override"
-fi
-
-override=/run/systemd/system/gbmc-br-dhcp.service.d/10-direct.conf
-mkdir -p "$(dirname "$override")"
-echo '[Service]' >"$override"
-echo 'ExecStart=' >>"$override"
-# Switch the gbmcbr interface for the NCSI one to avoid passing the SOLICIT
-# message through the BMC relay.
-grep '^ExecStart=' /lib/systemd/system/gbmc-br-dhcp.service | \
- sed 's, -i gbmcbr, -i @NCSI_IF@,' >>"$override"
-
-systemctl daemon-reload
-if [ "$HAS_DHCRELAY" = 1 ]; then
+ echo 'RP_FLAG=' >/run/gbmc-ncsi-dhcrelay.env
systemctl reset-failed gbmc-ncsi-dhcrelay
systemctl restart --no-block gbmc-ncsi-dhcrelay
fi
+
+echo 'INTF=@NCSI_IF@' >/run/gbmc-br-dhcp.env
systemctl reset-failed gbmc-br-dhcp
systemctl restart --no-block gbmc-br-dhcp
diff --git a/meta-google/recipes-google/ncsi/gbmc-ncsi-config.bb b/meta-google/recipes-google/ncsi/gbmc-ncsi-config.bb
index 29ec5bd19e..aac9935642 100644
--- a/meta-google/recipes-google/ncsi/gbmc-ncsi-config.bb
+++ b/meta-google/recipes-google/ncsi/gbmc-ncsi-config.bb
@@ -5,20 +5,20 @@ LIC_FILES_CHKSUM = "file://${COREBASE}/meta/files/common-licenses/Apache-2.0;md5
inherit systemd
-GBMC_NCSI_DHCP_RELAY ??= "${@'' if int(d.getVar('FLASH_SIZE')) < 65536 else '1'}"
+GBMC_DHCP_RELAY ??= "${@'' if int(d.getVar('FLASH_SIZE')) < 65536 else '1'}"
GBMC_NCSI_IF_OLD ??= ""
GBMC_NCSI_PURGE_ETC ??= ""
GBMC_NCSI_DHCP_IMPERSONATE_HOST ??= "1"
SRC_URI += " \
- ${@'' if d.getVar('GBMC_NCSI_DHCP_RELAY') != '1' else 'file://-bmc-gbmcbrncsidhcp.netdev'} \
- ${@'' if d.getVar('GBMC_NCSI_DHCP_RELAY') != '1' else 'file://-bmc-gbmcbrncsidhcp.network'} \
- ${@'' if d.getVar('GBMC_NCSI_DHCP_RELAY') != '1' else 'file://-bmc-gbmcncsidhcp.netdev'} \
- ${@'' if d.getVar('GBMC_NCSI_DHCP_RELAY') != '1' else 'file://-bmc-gbmcncsidhcp.network'} \
+ ${@'' if d.getVar('GBMC_DHCP_RELAY') != '1' else 'file://-bmc-gbmcbrncsidhcp.netdev'} \
+ ${@'' if d.getVar('GBMC_DHCP_RELAY') != '1' else 'file://-bmc-gbmcbrncsidhcp.network'} \
+ ${@'' if d.getVar('GBMC_DHCP_RELAY') != '1' else 'file://-bmc-gbmcncsidhcp.netdev'} \
+ ${@'' if d.getVar('GBMC_DHCP_RELAY') != '1' else 'file://-bmc-gbmcncsidhcp.network'} \
file://50-gbmc-ncsi.rules.in \
- ${@'' if d.getVar('GBMC_NCSI_DHCP_RELAY') != '1' else 'file://gbmc-ncsi-dhcrelay.service.in'} \
- file://gbmc-ncsi-ip-from-ra.service.in \
- file://gbmc-ncsi-ip-from-ra.sh.in \
+ ${@'' if d.getVar('GBMC_DHCP_RELAY') != '1' else 'file://gbmc-ncsi-dhcrelay.service.in'} \
+ file://gbmc-ncsi-ra.service.in \
+ file://gbmc-ncsi-ra.sh \
file://gbmc-ncsi-smartnic-wa.sh.in \
file://gbmc-ncsi-sslh.socket.in \
file://gbmc-ncsi-sslh.service \
@@ -36,13 +36,13 @@ S = "${WORKDIR}"
RDEPENDS:${PN} += " \
bash \
- ${@'' if d.getVar('GBMC_NCSI_DHCP_RELAY') != '1' else 'dhcp-relay'} \
+ ${@'' if d.getVar('GBMC_DHCP_RELAY') != '1' else 'dhcp-relay'} \
gbmc-ip-monitor \
+ gbmc-net-common \
ncsid \
network-sh \
nftables-systemd \
sslh \
- ndisc6-rdisc6 \
"
FILES:${PN} += " \
@@ -52,11 +52,11 @@ FILES:${PN} += " \
"
SYSTEMD_SERVICE:${PN} += " \
- ${@'' if d.getVar('GBMC_NCSI_DHCP_RELAY') != '1' else 'gbmc-ncsi-dhcrelay.service'} \
+ ${@'' if d.getVar('GBMC_DHCP_RELAY') != '1' else 'gbmc-ncsi-dhcrelay.service'} \
gbmc-ncsi-sslh.service \
gbmc-ncsi-sslh.socket \
gbmc-ncsi-set-nicenabled.service \
- gbmc-ncsi-ip-from-ra.service \
+ gbmc-ncsi-ra.service \
${@'' if d.getVar('GBMC_NCSI_IF_OLD') == '' else 'gbmc-ncsi-old.service'} \
${@'' if d.getVar('GBMC_NCSI_PURGE_ETC') == '' else 'gbmc-ncsi-purge.service'} \
"
@@ -74,7 +74,7 @@ do_install:append() {
echo "net.ipv6.conf.$if_name.dad_transmits=0" \
>>${D}${sysconfdir}/sysctl.d/25-gbmc-ncsi.conf
- if [ "${GBMC_NCSI_DHCP_RELAY}" = 1 ]; then
+ if [ "${GBMC_DHCP_RELAY}" = 1 ]; then
install -d -m0755 ${D}${systemd_unitdir}/network
install -m0644 ${WORKDIR}/-bmc-gbmcbrncsidhcp.netdev \
${D}${systemd_unitdir}/network/
@@ -136,7 +136,7 @@ do_install:append() {
sed "s,@NCSI_IF@,$if_name,g" ${WORKDIR}/gbmc-ncsi-set-nicenabled.service.in \
>${D}${systemd_system_unitdir}/gbmc-ncsi-set-nicenabled.service
- if [ "${GBMC_NCSI_DHCP_RELAY}" = "1" ]; then
+ if [ "${GBMC_DHCP_RELAY}" = "1" ]; then
sed "s,@NCSI_IF@,$if_name,g" ${WORKDIR}/gbmc-ncsi-dhcrelay.service.in \
>${D}${systemd_system_unitdir}/gbmc-ncsi-dhcrelay.service
fi
@@ -151,15 +151,13 @@ do_install:append() {
>${D}${systemd_system_unitdir}/gbmc-ncsi-purge.service
fi
- sed "s,@NCSI_IF@,$if_name,g" ${WORKDIR}/gbmc-ncsi-ip-from-ra.service.in \
- >${WORKDIR}/gbmc-ncsi-ip-from-ra.service
- install -m0644 ${WORKDIR}/gbmc-ncsi-ip-from-ra.service ${D}${systemd_system_unitdir}
- sed "s,@NCSI_IF@,$if_name,g" ${WORKDIR}/gbmc-ncsi-ip-from-ra.sh.in \
- >${WORKDIR}/gbmc-ncsi-ip-from-ra.sh
+ sed "s,@NCSI_IF@,$if_name,g" ${WORKDIR}/gbmc-ncsi-ra.service.in \
+ >${WORKDIR}/gbmc-ncsi-ra.service
+ install -m0644 ${WORKDIR}/gbmc-ncsi-ra.service ${D}${systemd_system_unitdir}
install -d -m0755 ${D}${libexecdir}
- install -m0755 ${WORKDIR}/gbmc-ncsi-ip-from-ra.sh ${D}${libexecdir}/
+ install -m0755 ${WORKDIR}/gbmc-ncsi-ra.sh ${D}${libexecdir}/
- sed -e "s,@NCSI_IF@,$if_name,g" -e "s,@GBMC_NCSI_DHCP_RELAY@,${GBMC_NCSI_DHCP_RELAY},g" \
+ sed -e "s,@NCSI_IF@,$if_name,g" -e "s,@GBMC_DHCP_RELAY@,${GBMC_DHCP_RELAY},g" \
${WORKDIR}/gbmc-ncsi-smartnic-wa.sh.in >${WORKDIR}/gbmc-ncsi-smartnic-wa.sh
install -d -m0755 ${D}${bindir}
install -m0755 ${WORKDIR}/gbmc-ncsi-smartnic-wa.sh ${D}${bindir}/
diff --git a/meta-google/recipes-google/ncsi/ncsid_git.bb b/meta-google/recipes-google/ncsi/ncsid_git.bb
index 12a8d03407..d746c278cd 100644
--- a/meta-google/recipes-google/ncsi/ncsid_git.bb
+++ b/meta-google/recipes-google/ncsi/ncsid_git.bb
@@ -11,16 +11,9 @@ EXTRA_OEMESON = " \
"
SYSTEMD_SERVICE:${PN} += " \
- dhcp4@.service \
- dhcp6@.service \
ncsid@.service \
nic-hostful@.target \
nic-hostless@.target \
- update-ra-gw@.service \
- update-ra-neighbor@.service \
- update-ra-neighbor@.timer \
- update-static-neighbors@.service \
- update-static-neighbors@.timer \
"
DEPENDS += " \
@@ -37,3 +30,9 @@ RDEPENDS:${PN} += " \
ndisc6-rdisc6 \
systemd \
"
+
+# TODO: Remove when package is bumped to formally delete this service
+do_install:append() {
+ rm ${D}${systemd_system_unitdir}/update-ra-gw@.service
+ rm ${D}${libexecdir}/update_ra_gw.sh
+}
diff --git a/meta-google/recipes-google/networking/dhcp-done_git.bb b/meta-google/recipes-google/networking/dhcp-done_git.bb
index 12e3903837..2cc9b95c88 100644
--- a/meta-google/recipes-google/networking/dhcp-done_git.bb
+++ b/meta-google/recipes-google/networking/dhcp-done_git.bb
@@ -4,9 +4,12 @@ GOOGLE_MISC_PROJ = "dhcp-done"
require ../google-misc/google-misc.inc
+EXTRA_OEMESON = " \
+ -Dtests=disabled \
+ "
inherit systemd
-SYSTEMD_SERVICE:${PN} += "dhcp-done@.service"
+SYSTEMD_SERVICE:${PN} += "dhcp-done.service"
DEPENDS += " \
sdeventplus \
diff --git a/meta-google/recipes-google/networking/gbmc-bridge.bb b/meta-google/recipes-google/networking/gbmc-bridge.bb
index 3f20530291..0a6f40eda7 100644
--- a/meta-google/recipes-google/networking/gbmc-bridge.bb
+++ b/meta-google/recipes-google/networking/gbmc-bridge.bb
@@ -15,12 +15,15 @@ SRC_URI += " \
file://50-gbmc-br.rules \
file://gbmc-br-ula.sh \
file://gbmc-br-from-ra.sh \
- file://gbmc-br-ensure-ra.sh \
- file://gbmc-br-ensure-ra.service \
+ file://gbmc-br-hostname.sh \
+ file://gbmc-br-hostname.service \
+ file://gbmc-br-ra.sh.in \
+ file://gbmc-br-ra.service \
file://gbmc-br-gw-src.sh \
file://gbmc-br-nft.sh \
file://gbmc-br-dhcp.sh \
- file://50-gbmc-psu-hardreset.sh \
+ file://50-gbmc-psu-hardreset.sh.in \
+ file://51-gbmc-reboot.sh \
file://gbmc-br-dhcp.service \
file://gbmc-br-dhcp-term.sh \
file://gbmc-br-dhcp-term.service \
@@ -42,25 +45,38 @@ RDEPENDS:${PN}:append = " \
bash \
dhcp-done \
gbmc-ip-monitor \
+ gbmc-net-common \
network-sh \
ndisc6-rdisc6 \
nftables-systemd \
"
SYSTEMD_SERVICE:${PN} += " \
- gbmc-br-ensure-ra.service \
+ gbmc-br-hostname.service \
gbmc-br-dhcp.service \
gbmc-br-dhcp-term.service \
gbmc-br-load-ip.service \
+ gbmc-br-ra.service \
"
GBMC_BR_MAC_ADDR ?= ""
+# Enables the assignment of IP address and hostname by discovering the
+# machine name and BMC prefix from another BMC on the bridge network.
+# This is intended only to be used when there is a single expansion tray
+# on the BMC network. If more than one machine uses this feature with the
+# same offset in the same machine network, it will collide with others.
+# A value of 0 implies that this feature is disabled.
+GBMC_BR_FIXED_OFFSET ?= "0"
+
# Generated via https://cd34.com/rfc4193/ based on a MAC from a machine I own
# and we allocated it downstream. Intended to only be used within a complete
# system of multiple network endpoints.
GBMC_ULA_PREFIX = "fdb5:0481:10ce:0"
+# coordinated powercycle
+GBMC_COORDINATED_POWERCYCLE ?= "true"
+
def mac_to_eui64(mac):
if not mac:
return ''
@@ -122,21 +138,28 @@ do_install() {
install -m0644 ${WORKDIR}/gbmc-br-nft.sh "$mondir"/
install -d -m0755 ${D}${libexecdir}
- install -m0755 ${WORKDIR}/gbmc-br-ensure-ra.sh ${D}${libexecdir}/
+ install -m0755 ${WORKDIR}/gbmc-br-hostname.sh ${D}${libexecdir}/
install -m0755 ${WORKDIR}/gbmc-br-dhcp.sh ${D}${libexecdir}/
install -m0755 ${WORKDIR}/gbmc-br-dhcp-term.sh ${D}${libexecdir}/
install -d -m0755 ${D}${systemd_system_unitdir}
- install -m0644 ${WORKDIR}/gbmc-br-ensure-ra.service ${D}${systemd_system_unitdir}/
+ install -m0644 ${WORKDIR}/gbmc-br-hostname.service ${D}${systemd_system_unitdir}/
install -m0644 ${WORKDIR}/gbmc-br-dhcp.service ${D}${systemd_system_unitdir}/
install -m0644 ${WORKDIR}/gbmc-br-dhcp-term.service ${D}${systemd_system_unitdir}/
install -m0644 ${WORKDIR}/gbmc-br-load-ip.service ${D}${systemd_system_unitdir}/
install -d -m0755 ${D}${datadir}/gbmc-br-dhcp
+
+ sed 's,@COORDINATED_POWERCYCLE@,${GBMC_COORDINATED_POWERCYCLE},' ${WORKDIR}/50-gbmc-psu-hardreset.sh.in >${WORKDIR}/50-gbmc-psu-hardreset.sh
install -m0644 ${WORKDIR}/50-gbmc-psu-hardreset.sh ${D}${datadir}/gbmc-br-dhcp/
+ install -m0644 ${WORKDIR}/51-gbmc-reboot.sh ${D}${datadir}/gbmc-br-dhcp/
install -m0644 ${WORKDIR}/gbmc-br-lib.sh ${D}${datadir}/
install -d ${D}/${bindir}
install -m0755 ${WORKDIR}/gbmc-start-dhcp.sh ${D}${bindir}/
+
+ sed 's,@IP_OFFSET@,${GBMC_BR_FIXED_OFFSET},' ${WORKDIR}/gbmc-br-ra.sh.in >${WORKDIR}/gbmc-br-ra.sh
+ install -m0755 ${WORKDIR}/gbmc-br-ra.sh ${D}${libexecdir}/
+ install -m0644 ${WORKDIR}/gbmc-br-ra.service ${D}${systemd_system_unitdir}/
}
do_rm_work:prepend() {
diff --git a/meta-google/recipes-google/networking/gbmc-bridge/-bmc-gbmcbr.network.in b/meta-google/recipes-google/networking/gbmc-bridge/-bmc-gbmcbr.network.in
index d77557e8e3..dab65a91b2 100644
--- a/meta-google/recipes-google/networking/gbmc-bridge/-bmc-gbmcbr.network.in
+++ b/meta-google/recipes-google/networking/gbmc-bridge/-bmc-gbmcbr.network.in
@@ -6,10 +6,18 @@ IPv6AcceptRA=true
LLMNR=true
MulticastDNS=true
LinkLocalAddressing=ipv6
-IPv6PrefixDelegation=yes
+IPv6SendRA=yes
@ADDR@
[IPv6AcceptRA]
DHCPv6Client=false
RouteMetric=1056
-[IPv6PrefixDelegation]
+[IPv6SendRA]
RouterLifetimeSec=0
+[RoutingPolicyRule]
+To=fdb5:481:10ce::/64
+Table=main
+Priority=500
+[RoutingPolicyRule]
+To=fe80::/64
+Table=main
+Priority=500
diff --git a/meta-google/recipes-google/networking/gbmc-bridge/50-gbmc-psu-hardreset.sh b/meta-google/recipes-google/networking/gbmc-bridge/50-gbmc-psu-hardreset.sh.in
index c0974a00d1..588efcb351 100644
--- a/meta-google/recipes-google/networking/gbmc-bridge/50-gbmc-psu-hardreset.sh
+++ b/meta-google/recipes-google/networking/gbmc-bridge/50-gbmc-psu-hardreset.sh.in
@@ -17,6 +17,8 @@
gbmc_psu_hardreset_needed=
+COORDINATED_POWERCYCLE=@COORDINATED_POWERCYCLE@
+
gbmc_psu_hardreset_hook() {
# We don't always need a powercycle, allow skipping
if [ -z "${gbmc_psu_hardreset_needed-}" ]; then
@@ -24,8 +26,13 @@ gbmc_psu_hardreset_hook() {
return 0
fi
- echo "Powercycling" >&2
- systemctl start gbmc-psu-hardreset.target || return
+ if [[ "${COORDINATED_POWERCYCLE}" == "true" ]]; then
+ echo "Requesting powercycle" >&2
+ update-dhcp-status 'POWERCYCLE' "netboot powercycle" || return
+ else
+ echo "Powercycling" >&2
+ systemctl start gbmc-psu-hardreset.target || return
+ fi
# Ensure that we don't continue the DHCP process while waiting for the
# powercycle.
diff --git a/meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-ensure-ra.sh b/meta-google/recipes-google/networking/gbmc-bridge/51-gbmc-reboot.sh
index 60e33d89b3..41dd883d06 100644
--- a/meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-ensure-ra.sh
+++ b/meta-google/recipes-google/networking/gbmc-bridge/51-gbmc-reboot.sh
@@ -1,5 +1,5 @@
#!/bin/bash
-# Copyright 2021 Google LLC
+# Copyright 2024 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -13,15 +13,23 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-# Every 30 seconds, send out an RA so that the kernel will receive a response.
-# This ensures that all BMCs (even ones that think they are routers) get updated
-# information from the other systems on the network.
-w=30
-while true; do
- start=$SECONDS
- rdisc6 -m gbmcbr -r 1 -w $(( w * 1000 )) >/dev/null 2>/dev/null
- # If rdisc6 exits early we still want to wait the full `w` time before
- # starting again.
- (( timeout = start + w - SECONDS ))
- sleep $(( timeout < 0 ? 0 : timeout ))
-done
+[ -n "${gbmc_reboot-}" ] && return
+
+gbmc_reboot_needed=
+
+gbmc_reboot_hook() {
+ # We don't always need a warm reset, allow skipping
+ if [ -z "${gbmc_reboot_needed-}" ]; then
+ echo "Skipping bmc reboot" >&2
+ return 0
+ fi
+
+ update-dhcp-status 'ONGOING' "triggerring bmc reboot"
+
+ reboot -f
+ exit 0
+}
+
+GBMC_BR_DHCP_HOOKS+=(gbmc_reboot_hook)
+
+gbmc_reboot=1
diff --git a/meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-dhcp.service b/meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-dhcp.service
index 60ea0fb9ea..48f53abde7 100644
--- a/meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-dhcp.service
+++ b/meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-dhcp.service
@@ -1,14 +1,17 @@
[Unit]
Description=gBMC DHCP Client
-After=network.target
+After=network.target dhcp-done.service
+Wants=dhcp-done.service
StartLimitIntervalSec=10
StartLimitBurst=3
[Service]
+Environment=INTF=gbmcbr
+EnvironmentFile=-/run/gbmc-br-dhcp.env
Restart=on-failure
RestartSec=5
-ExecCondition=/bin/bash -c "! /bin/systemctl is-active -q dhcp-done@*"
-ExecStart=/usr/bin/udhcpc6 -f -q -O fqdn -O bootfile_url -O bootfile_param -i gbmcbr -s /usr/libexec/gbmc-br-dhcp.sh
+ExecStartPre=/usr/bin/update-dhcp-status 'ONGOING' 'Starting dhcp process'
+ExecStart=/usr/bin/udhcpc6 -f -q -O fqdn -O bootfile_url -O bootfile_param -i $INTF -s /usr/libexec/gbmc-br-dhcp.sh
[Install]
WantedBy=multi-user.target
diff --git a/meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-dhcp.sh b/meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-dhcp.sh
index 4360e11277..c31090b656 100644
--- a/meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-dhcp.sh
+++ b/meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-dhcp.sh
@@ -42,21 +42,26 @@ if [ "$1" = bound ]; then
# shellcheck disable=SC2154
echo "DHCPv6(gbmcbr): $ipv6/128" >&2
+ update-dhcp-status 'ONGOING' "Received dhcp response ${ipv6}"
pfx_bytes=()
ip_to_bytes pfx_bytes "$ipv6"
# Ensure we are a BMC and have a suffix nibble, the 0th index is reserved
if (( pfx_bytes[8] != 0xfd || (pfx_bytes[9] & 0xf) == 0 )); then
- echo "Invalid address" >&2
+ echo "Invalid address prefix ${ipv6}" >&2
+ update-dhcp-status 'ONGOING' "Invalid address prefix ${ipv6}"
exit 1
fi
# Ensure we don't have more than a /80 address
for (( i = 10; i < 16; ++i )); do
if (( pfx_bytes[i] != 0 )); then
- echo "Invalid address" >&2
+ echo "Invalid address ${ipv6}" >&2
+ update-dhcp-status 'ONGOING' "Invalid address ${ipv6}"
exit 1
fi
done
+ update-dhcp-status 'ONGOING' "Setting hostname ${fqdn} and ip ${ipv6}"
+
pfx="$(ip_bytes_to_str pfx_bytes)"
gbmc_br_set_ip "$pfx" || exit
@@ -70,11 +75,13 @@ if [ "$1" = bound ]; then
# If any of our hooks had expectations we should fail here
if [ "${#GBMC_BR_DHCP_OUTSTANDING[@]}" -gt 0 ]; then
echo "Not done with DHCP process: ${!GBMC_BR_DHCP_OUTSTANDING[*]}" >&2
+ update-dhcp-status 'ONGOING' "Outstanding DHCP hooks ${!GBMC_BR_DHCP_OUTSTANDING[*]}"
exit 1
fi
# Ensure that the installer knows we have completed processing DHCP by
# running a service that reports completion
- echo 'Start DHCP Done' >&2
- systemctl start dhcp-done@DONE --no-block
+ echo 'Signaling dhcp done' >&2
+ update-dhcp-status 'DONE' "Netboot finished"
+
fi
diff --git a/meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-ensure-ra.service b/meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-ensure-ra.service
deleted file mode 100644
index 7f97cea48d..0000000000
--- a/meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-ensure-ra.service
+++ /dev/null
@@ -1,5 +0,0 @@
-[Service]
-ExecStart=/usr/libexec/gbmc-br-ensure-ra.sh
-
-[Install]
-WantedBy=multi-user.target
diff --git a/meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-gw-src.sh b/meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-gw-src.sh
index 3c57b66af3..5865946e04 100644
--- a/meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-gw-src.sh
+++ b/meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-gw-src.sh
@@ -17,9 +17,10 @@
# shellcheck source=meta-google/recipes-google/networking/network-sh/lib.sh
source /usr/share/network/lib.sh || exit
+# shellcheck source=meta-google/recipes-google/networking/gbmc-net-common/gbmc-net-lib.sh
+source /usr/share/gbmc-net-lib.sh || exit
-gbmc_br_gw_src_ip_stateful=
-gbmc_br_gw_src_ip_stateless=
+declare -A gbmc_br_gw_src_ips=()
declare -A gbmc_br_gw_src_routes=()
gbmc_br_gw_defgw=
@@ -32,6 +33,11 @@ gbmc_br_set_router() {
break
fi
done
+ # Make becoming a router sticky, if we ever have a default route we are
+ # always treated as a router. Otherwise, we end up reloading unnecessarily
+ # a number of times. The reload causes the network configuration to be
+ # reappplied with packet drops for a short amount of time.
+ [[ -z $defgw ]] && return
[[ $defgw == "$gbmc_br_gw_defgw" ]] && return
gbmc_br_gw_defgw="$defgw"
@@ -40,27 +46,44 @@ gbmc_br_set_router() {
local file
for file in "${files[@]}"; do
mkdir -p "$(dirname "$file")"
- printf '[IPv6PrefixDelegation]\nRouterLifetimeSec=30\n' >"$file"
+ printf '[IPv6SendRA]\nRouterLifetimeSec=120\n' >"$file"
done
else
rm -f "${files[@]}"
fi
- if [[ $(systemctl is-active systemd-networkd) != inactive ]]; then
- networkctl reload && networkctl reconfigure gbmcbr
- fi
+ # shellcheck disable=SC2119
+ gbmc_net_networkd_reload
}
gbmc_br_gw_src_update() {
- local gbmc_br_gw_src_ip="${gbmc_br_gw_src_ip_stateful:-$gbmc_br_gw_src_ip_stateless}"
- [[ -n $gbmc_br_gw_src_ip ]] || return
+ # Pick the shortest address, we always want to use the most root level
+ # The order of preference looks roughly like
+ # 1. Root /64 address (2620:15c:2c3:aaae::/64)
+ # This is generally used by the OOB RJ45 port and is our primary preference
+ # 2. BMC subordonate root (2620:15c:2c3:aaae:fd01::/80)
+ # 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 new_src=
+ local new_len=16
+ local ip
+ for ip in "${!gbmc_br_gw_src_ips[@]}"; do
+ local ip_len="${gbmc_br_gw_src_ips["$ip"]}"
+ if (( ip_len < new_len )); then
+ new_src="$ip"
+ new_len="$ip_len"
+ fi
+ done
+ (( new_len >= 16 )) && return
local route
for route in "${!gbmc_br_gw_src_routes[@]}"; do
- [[ $route != *" src $gbmc_br_gw_src_ip "* ]] || continue
- echo "gBMC Bridge Updating GW source [$gbmc_br_gw_src_ip]: $route" >&2
+ [[ $route != *" src $new_src "* ]] || continue
+ echo "gBMC Bridge Updating GW source [$new_src]: $route" >&2
# shellcheck disable=SC2086
- ip route change $route src "$gbmc_br_gw_src_ip" && \
+ ip route change $route src "$new_src" && \
unset 'gbmc_br_gw_src_routes[$route]'
done
}
@@ -83,8 +106,8 @@ gbmc_br_gw_src_hook() {
gbmc_br_gw_src_update
gbmc_br_set_router
fi
- # Match only global IP addresses on the bridge that match the BMC stateless
- # prefix (<mpfx>:fd00:). So 2002:af4:3480:2248:fd00:6345:3069:9186 would be
+ # Match only global IP addresses on the bridge that are non-ULA addresses.
+ # So 2002:af4:3480:2248:fd00:6345:3069:9186 would be
# matched as the preferred source IP for outoging traffic.
elif [[ $change == addr && $intf == gbmcbr && $scope == global ]] &&
[[ $fam == inet6 && $flags != *tentative* ]]; then
@@ -93,22 +116,23 @@ gbmc_br_gw_src_hook() {
echo "gBMC Bridge Ensure RA Invalid IP: $ip" >&2
return 1
fi
- # Ignore ULAs and non-gBMC addresses
- if (( (ip_bytes[0] & 0xfe) == 0xfc || ip_bytes[8] != 0xfd )); then
+ # Ignore ULAs
+ if (( (ip_bytes[0] & 0xfe) == 0xfc )); then
return 0
fi
- if (( (ip_bytes[9] & 0xf) != 0 )); then
- local -n gbmc_br_gw_src_ip=gbmc_br_gw_src_ip_stateful
- else
- local -n gbmc_br_gw_src_ip=gbmc_br_gw_src_ip_stateless
- fi
- if [[ $action == add && $ip != "$gbmc_br_gw_src_ip" ]]; then
- gbmc_br_gw_src_ip="$ip"
- gbmc_br_gw_src_update
- fi
- if [[ $action == del && $ip == "$gbmc_br_gw_src_ip" ]]; then
- gbmc_br_gw_src_ip=
+ if [[ $action == add ]]; then
+ local i=0
+ local non_zero=0
+ for (( i=0; i<16; ++i )); do
+ if (( ip_bytes[i] != 0 )); then
+ non_zero="$i"
+ fi
+ done
+ gbmc_br_gw_src_ips["$ip"]="$non_zero"
+ elif [[ $action == del ]]; then
+ unset 'gbmc_br_gw_src_ips[$ip]'
fi
+ gbmc_br_gw_src_update
fi
}
diff --git a/meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-hostname.service b/meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-hostname.service
new file mode 100644
index 0000000000..9841419454
--- /dev/null
+++ b/meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-hostname.service
@@ -0,0 +1,8 @@
+[Unit]
+Before=systemd-networkd.service
+
+[Service]
+ExecStart=/usr/libexec/gbmc-br-hostname.sh
+
+[Install]
+WantedBy=multi-user.target
diff --git a/meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-hostname.sh b/meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-hostname.sh
new file mode 100755
index 0000000000..d680e148f4
--- /dev/null
+++ b/meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-hostname.sh
@@ -0,0 +1,35 @@
+#!/bin/bash
+# Copyright 2024 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# shellcheck source=meta-google/recipes-google/networking/gbmc-net-common/gbmc-net-lib.sh
+source /usr/share/gbmc-net-lib.sh || exit
+
+oldname=
+while read -r _; do
+ # Don't bother parsing the output, just read the final hostname
+ name="$(</etc/hostname)" || continue
+ [[ "$oldname" == "$name" ]] && continue
+ oldname="$name"
+ echo "Updating BMC RA Hostname $name" >&2
+
+ contents='[IPv6SendRA]'$'\n'"Domains=$name"
+ for netfile in /run/systemd/network/{00,}-bmc-gbmcbr.network.d/60-domains.conf; do
+ mkdir -p "$(dirname "$netfile")"
+ printf '%s' "$contents" >"$netfile"
+ done
+
+ # shellcheck disable=SC2119
+ gbmc_net_networkd_reload
+done < <(dbus-monitor --system "type='signal',interface='org.freedesktop.DBus.Properties',member='PropertiesChanged',arg0='org.freedesktop.hostname1'")
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 1b31ef9f6f..912a3c119d 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
@@ -15,9 +15,10 @@
[ -n "${gbmc_br_lib_init-}" ] && return
-# SC can't find this path during repotest
-# shellcheck disable=SC1091
+# shellcheck source=meta-google/recipes-google/networking/network-sh/lib.sh
source /usr/share/network/lib.sh || exit
+# shellcheck source=meta-google/recipes-google/networking/gbmc-net-common/gbmc-net-lib.sh
+source /usr/share/gbmc-net-lib.sh || exit
# A list of functions which get executed for each configured IP.
# These are configured by the files included below.
@@ -49,16 +50,10 @@ gbmc_br_run_hooks() {
done
}
-gbmc_br_reload() {
- if [ "$(systemctl is-active systemd-networkd)" != 'inactive' ]; then
- networkctl reload && networkctl reconfigure gbmcbr
- fi
-}
-
gbmc_br_no_ip() {
echo "Runtime removing gbmcbr IP" >&2
rm -f /run/systemd/network/{00,}-bmc-gbmcbr.network.d/50-public.conf
- gbmc_br_reload
+ gbmc_net_networkd_reload gbmcbr
}
gbmc_br_reload_ip() {
@@ -91,11 +86,11 @@ gbmc_br_reload_ip() {
Address=$pfx/128
[IPv6Prefix]
Prefix=$stateless_pfx/80
-PreferredLifetimeSec=60
-ValidLifetimeSec=60
+PreferredLifetimeSec=120
+ValidLifetimeSec=120
[IPv6RoutePrefix]
Route=$pfx/80
-LifetimeSec=60
+LifetimeSec=120
[Route]
Destination=$stateless_pfx/76
Type=unreachable
@@ -109,7 +104,7 @@ EOF
printf '%s' "$contents" >"$file"
done
- gbmc_br_reload
+ gbmc_net_networkd_reload gbmcbr
}
gbmc_br_set_ip() {
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 7aa2158989..79ea76f974 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
@@ -57,8 +57,11 @@ gbmc_br_nft_hook() {
if (( ip_bytes[8] != 0xfd )); then
return 0
fi
+
+ (( ip_bytes[9] &= 0xf0 ))
+
local i
- for (( i=9; i<16; i++ )); do
+ for (( i=10; i<16; i++ )); do
ip_bytes["$i"]=0
done
pfx="$(ip_bytes_to_str ip_bytes)/76"
diff --git a/meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-ra.service b/meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-ra.service
new file mode 100644
index 0000000000..08fd15fa4f
--- /dev/null
+++ b/meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-ra.service
@@ -0,0 +1,13 @@
+[Unit]
+Description=gBMC Bridge RA Discovery
+After=network.target
+StartLimitIntervalSec=10
+StartLimitBurst=3
+
+[Service]
+Restart=always
+RestartSec=5
+ExecStart=/usr/libexec/gbmc-br-ra.sh
+
+[Install]
+WantedBy=multi-user.target
diff --git a/meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-ra.sh.in b/meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-ra.sh.in
new file mode 100755
index 0000000000..66d7a7d2da
--- /dev/null
+++ b/meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-ra.sh.in
@@ -0,0 +1,42 @@
+#!/bin/bash
+# Copyright 2024 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# shellcheck source=meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-lib.sh
+source /usr/share/gbmc-br-lib.sh || exit
+
+update_rtr() {
+ true
+}
+
+update_fqdn() {
+ (( IP_OFFSET == 0 )) && return
+ default_update_fqdn "$@"
+}
+
+update_pfx() {
+ local pfx="$1"
+ (( IP_OFFSET == 0 )) && return
+ gbmc_br_set_ip "$pfx" || true
+ echo "IP $pfx set on $RA_IF" >&2
+}
+
+RA_IF=gbmcbr
+IP_OFFSET=@IP_OFFSET@
+# Use the lowest priority, except for kernel RA discovered routes.
+# We want closer NICs to provide a default route if existing.
+ROUTE_METRIC=1000
+
+# shellcheck source=meta-google/recipes-google/networking/gbmc-net-common/gbmc-ra.sh
+source /usr/share/gbmc-ra.sh || exit
diff --git a/meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-ula.sh b/meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-ula.sh
index 42bb566c8a..b79e25fe4a 100644
--- a/meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-ula.sh
+++ b/meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-ula.sh
@@ -18,53 +18,81 @@
# shellcheck source=meta-google/recipes-google/networking/network-sh/lib.sh
source /usr/share/network/lib.sh || exit
-gbmc_br_ula_init=
-gbmc_br_ula_mac=
+declare -A gbmc_br_ulas=()
-gbmc_br_ula_update() {
- [[ -n $gbmc_br_ula_init ]] || return
+# BITs set for address suffixes
+GBMC_BR_ULA_SFX_HAS_LL=1
+GBMC_BR_ULA_SFX_HAS_ULA=2
- echo "gBMC Bridge ULA MAC: ${gbmc_br_ula_mac:-(deleted)}" >&2
-
- local addr=
- contents='[Network]'$'\n'
- if [[ -n $gbmc_br_ula_mac ]]; then
- local sfx
- if sfx="$(mac_to_eui64 "$gbmc_br_ula_mac")" &&
- addr="$(ip_pfx_concat "fdb5:0481:10ce::/64" "$sfx")"; then
- contents+="Address=$addr"$'\n'
+gbmc_br_ula_cleanup() {
+ local addr
+ for addr in "${!gbmc_br_ulas[@]}"; do
+ local val="${gbmc_br_ulas["$addr"]}"
+ if (( val & GBMC_BR_ULA_SFX_HAS_LL == 0 )); then
+ echo "Removing Stale ULA: $addr" >&2
+ ip addr del "$addr"/64 dev gbmcbr || true
fi
- fi
-
- local netfile
- for netfile in /run/systemd/network/{00,}-bmc-gbmcbr.network.d/60-ula.conf; do
- mkdir -p "$(dirname "$netfile")"
- printf '%s' "$contents" >"$netfile"
done
+}
- # Ensure that systemd-networkd performs a reconfiguration as it doesn't
- # currently check the mtime of drop-in files.
- touch -c /lib/systemd/network/*-bmc-gbmcbr.network
+gbmc_br_ula_is_ll() {
+ # shellcheck disable=SC2178
+ local -n bytes="$1"
+ (( bytes[0] == 0xfe && bytes[1] == 0x80 && bytes[2] == 0x00 &&
+ bytes[3] == 0x00 && bytes[4] == 0x00 && bytes[5] == 0x00 &&
+ bytes[6] == 0x00 && bytes[7] == 0x00 ))
+}
- if [[ $(systemctl is-active systemd-networkd) != inactive ]]; then
- networkctl reload
- networkctl reconfigure gbmcbr
- fi
+gbmc_br_ula_is_ula() {
+ # shellcheck disable=SC2178
+ local -n bytes="$1"
+ (( bytes[0] == 0xfd && bytes[1] == 0xb5 && bytes[2] == 0x04 &&
+ bytes[3] == 0x81 && bytes[4] == 0x10 && bytes[5] == 0xce &&
+ bytes[6] == 0x00 && bytes[7] == 0x00 ))
}
gbmc_br_ula_hook() {
# shellcheck disable=SC2154
if [[ $change == init ]]; then
- gbmc_br_ula_init=1
- gbmc_br_ula_update
- elif [[ $change == link && $intf == gbmcbr ]]; then
- if [[ $action == add && $mac != "$gbmc_br_ula_mac" ]]; then
- gbmc_br_ula_mac="$mac"
- gbmc_br_ula_update
+ gbmc_br_ula_cleanup
+ elif [[ $change == addr && $intf == gbmcbr && $fam == inet6 ]]; then
+ local pfx_bytes=()
+ ip_to_bytes pfx_bytes "$ip" || return
+ local val=0
+ if gbmc_br_ula_is_ll pfx_bytes; then
+ val="$GBMC_BR_ULA_SFX_HAS_LL"
+ elif gbmc_br_ula_is_ula pfx_bytes; then
+ val="$GBMC_BR_ULA_SFX_HAS_ULA"
+ else
+ return 0
+ fi
+ # Force all addresses into what they would be as a ULA so that we can
+ # store bits about the assigned addresses on the interface
+ pfx_bytes[0]=0xfd
+ pfx_bytes[1]=0xb5
+ pfx_bytes[2]=0x04
+ pfx_bytes[3]=0x81
+ pfx_bytes[4]=0x10
+ pfx_bytes[5]=0xce
+ addr="$(ip_bytes_to_str pfx_bytes)"
+ local old=${gbmc_br_ulas["$addr"]-0}
+ if [[ $action == add ]]; then
+ val=$((old | val))
+ elif [[ $action == del ]]; then
+ val=$((old & ~val))
fi
- if [[ $action == del && $mac == "$gbmc_br_ula_mac" ]]; then
- gbmc_br_ula_mac=
- gbmc_br_ula_update
+ gbmc_br_ulas["$addr"]=$val
+ if (( val == GBMC_BR_ULA_SFX_HAS_LL )); then
+ # We have a link local address but no ULA, so we need to add the ULA
+ echo "Adding ULA: $addr" >&2
+ ip addr replace "$addr"/64 dev gbmcbr
+ elif (( val == GBMC_BR_ULA_SFX_HAS_ULA )); then
+ # We have a ULA without a link local, so we should not longer have this ULA
+ echo "Removing ULA: $addr" >&2
+ ip addr del "$addr"/64 dev gbmcbr || true
+ elif (( val == 0 )); then
+ # Cleanup the map if we no longer have any addresses for the suffix
+ unset 'gbmc_br_ulas[$addr]'
fi
fi
}
diff --git a/meta-google/recipes-google/networking/gbmc-bridge/gbmc-start-dhcp.sh b/meta-google/recipes-google/networking/gbmc-bridge/gbmc-start-dhcp.sh
index c6fddbb9cf..b968573daf 100644
--- a/meta-google/recipes-google/networking/gbmc-bridge/gbmc-start-dhcp.sh
+++ b/meta-google/recipes-google/networking/gbmc-bridge/gbmc-start-dhcp.sh
@@ -15,10 +15,6 @@
systemctl stop gbmc-br-dhcp
-# in some cases dhcp-done might be run already, in this case we want
-# a powercycle for a clean install
-systemctl is-active -q dhcp-done@* && exit 1
-
# stop dhcp term service to prevent race condition
systemctl is-active --quiet gbmc-br-dhcp-term && systemctl stop gbmc-br-dhcp-term
diff --git a/meta-google/recipes-google/networking/gbmc-net-common.bb b/meta-google/recipes-google/networking/gbmc-net-common.bb
new file mode 100644
index 0000000000..1a3ca7722c
--- /dev/null
+++ b/meta-google/recipes-google/networking/gbmc-net-common.bb
@@ -0,0 +1,27 @@
+SUMMARY = "gBMC common networking components"
+PR = "r1"
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://${COREBASE}/meta/files/common-licenses/Apache-2.0;md5=89aea4e17d99a7cacdbeed46a0096b10"
+
+SRC_URI += " \
+ file://gbmc-net-lib.sh \
+ file://gbmc-ra.sh \
+ "
+S = "${WORKDIR}"
+
+FILES:${PN} += " \
+ ${datadir}/ \
+ "
+
+RDEPENDS:${PN}:append = " \
+ bash \
+ network-sh \
+ ndisc6-rdisc6 \
+ "
+
+do_install() {
+ install -d -m0755 ${D}${datadir}
+ install -m0644 ${S}/gbmc-net-lib.sh ${D}${datadir}/
+ install -m0644 ${S}/gbmc-ra.sh ${D}${datadir}/
+}
+
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
new file mode 100644
index 0000000000..6e4ba365e0
--- /dev/null
+++ b/meta-google/recipes-google/networking/gbmc-net-common/gbmc-net-lib.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+# Copyright 2024 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+[ -n "${gbmc_net_lib_init-}" ] && return
+
+gbmc_net_networkd_reload() {
+ if [ "$(systemctl is-active systemd-networkd)" != 'inactive' ]; then
+ echo "Reloading networkd + reconfiguring ($*) from $(caller 0)" >&2
+ networkctl reload || return
+ local st=0
+ local intf
+ for intf in "$@"; do
+ networkctl reconfigure "$intf" || st=$?
+ done
+ return $st
+ fi
+}
+
+gbmc_net_lib_init=1
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
new file mode 100644
index 0000000000..280083a8c9
--- /dev/null
+++ b/meta-google/recipes-google/networking/gbmc-net-common/gbmc-ra.sh
@@ -0,0 +1,188 @@
+#!/bin/bash
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# shellcheck source=meta-google/recipes-google/networking/network-sh/lib.sh
+source /usr/share/network/lib.sh || exit
+# shellcheck source=meta-google/recipes-google/networking/gbmc-net-common/gbmc-net-lib.sh
+source /usr/share/gbmc-net-lib.sh || exit
+
+: "${RA_IF:?No RA interface set}"
+: "${IP_OFFSET=?1}"
+: "${ROUTE_METRIC:?No Metric set}"
+
+# We would prefer empty string but it's easier for associative array handling
+# to use invalid
+old_rtr=invalid
+old_mac=invalid
+old_pfx=invalid
+old_fqdn=invalid
+
+default_update_rtr() {
+ local rtr="$1"
+ local mac="$2"
+
+ if ip addr show | grep -q "^[ ]*inet6 $rtr/"; then
+ echo "Router is ourself, ignoring" >&2
+ return 0
+ fi
+
+ # In case we don't have a base network file, make one
+ # this is intentionally 00- as it will not preceed /etc/systemd/network/00-*
+ # or /lib/systemd/network/-* files.
+ local file=/run/systemd/network/00-bmc-$RA_IF.network
+ printf '[Match]\nName=%s\n[Network]\nDHCP=false\nIPv6AcceptRA=false\nLinkLocalAddressing=yes' \
+ "$RA_IF" >"$file"
+
+ # Override any existing gateway information within files
+ # Make sure we cover `00-*` and `-*` files
+ for file in /run/systemd/network/{00,}-bmc-$RA_IF.network; do
+ mkdir -p "$file.d"
+ printf '[Route]\nGateway=%s\nGatewayOnLink=true\nMetric=%d\n[Neighbor]\nMACAddress=%s\nAddress=%s' \
+ "$rtr" "$ROUTE_METRIC" "$mac" "$rtr" >"$file.d"/10-gateway.conf
+ done
+
+ # Don't force networkd to reload as this can break phosphor-networkd
+ # Fall back to reload only if ip link commands fail
+ (ip -6 route replace default via "$rtr" onlink dev "$RA_IF" metric "$ROUTE_METRIC" && \
+ ip -6 neigh replace "$rtr" dev "$RA_IF" lladdr "$mac") || \
+ gbmc_net_networkd_reload "$RA_IF" || true
+
+ echo "Set router $rtr on $RA_IF" >&2
+}
+
+default_update_fqdn() {
+ local fqdn="$1"
+ [ -z "$fqdn" ] && return
+ hostnamectl set-hostname "$fqdn" || true
+ echo "Set hostname $fqdn on $RA_IF" >&2
+}
+
+retries=1
+min_w=10
+declare -A rtrs
+rtrs=()
+while true; do
+ # shellcheck disable=SC2206
+ data=(${rtrs["${old_rtr}"]-})
+ curr_dl="${data[1]-$(( min_w + SECONDS ))}"
+ args=(-m "$RA_IF" -w $(( (curr_dl - SECONDS) * 1000 )))
+ if (( retries > 0 )); then
+ args+=(-r "$retries")
+ else
+ args+=(-d)
+ fi
+ while read -r line; do
+ # `script` terminates all lines with a CRLF, remove it
+ line="${line:0:-1}"
+ # shellcheck disable=SC2026
+ if [ -z "$line" ]; then
+ lifetime=-1
+ mac=
+ hextet=
+ pfx=
+ host=
+ domain=
+ elif [[ "$line" =~ ^Router' 'lifetime' '*:' '*([0-9]*) ]]; then
+ lifetime="${BASH_REMATCH[1]}"
+ elif [[ "$line" =~ ^Source' 'link-layer' 'address' '*:' '*([a-fA-F0-9:]*)$ ]]; then
+ mac="${BASH_REMATCH[1]}"
+ elif [[ "$line" =~ ^Prefix' '*:' '*(.*)/([0-9]+)$ ]]; then
+ t_pfx="${BASH_REMATCH[1]}"
+ t_pfx_len="${BASH_REMATCH[2]}"
+ ip_to_bytes t_pfx_b "$t_pfx" || continue
+ (( (t_pfx_len == 76 || t_pfx_len == 80) && (t_pfx_b[8] & 0xfd) == 0xfd )) || continue
+ (( t_pfx_b[9] &= 0xf0 ))
+ (( t_pfx_b[9] |= IP_OFFSET ))
+ hextet="fd$(printf '%02x' "${t_pfx_b[9]}")"
+ pfx="$(ip_bytes_to_str t_pfx_b)"
+ elif [[ "$line" =~ ^'DNS search list'' '*:' '*([^.]+)(.*[.]google[.]com)' '*$ ]]; then
+ # Ideally, we use PCRE and with lookahead and can do this in a single regex
+ # ^([a-zA-Z0-9-]+(?=-n[a-fA-F0-9]{1,4})|[a-zA-Z0-9-]+(?!-n[a-fA-F0-9]{1,4}))[^.]*[.]((?:[a-zA-Z0-9]*[.])*google[.]com)$
+ # Instead we do multiple steps to extract the needed info
+ host="${BASH_REMATCH[1]}"
+ domain="${BASH_REMATCH[2]#.}"
+ if [[ "$host" =~ (-n[a-fA-F0-9]{1,4})$ ]]; then
+ host="${host%"${BASH_REMATCH[1]}"}"
+ fi
+ elif [[ "$line" =~ ^from' '(.*)$ ]]; then
+ rtr="${BASH_REMATCH[1]}"
+ # Only valid default routers can be considered, 0 lifetime implies
+ # a non-default router
+ (( lifetime > 0 )) || continue
+
+ dl=$((lifetime + SECONDS))
+ fqdn=
+ if [[ -n $host && -n $hextet && -n $domain ]]; then
+ fqdn="$host-n$hextet.$domain"
+ fi
+ rtrs["$rtr"]="$mac $dl $pfx $fqdn"
+ # We have some notoriously noisy lab environments with many routers being broadcast
+ # We always prefer "fe80::1" in prod and labs for routing, so prefer that gateway.
+ # We also want to take the first router we find to speed up acquisition on boot.
+ if [[ "$rtr" = "fe80::1" || "$old_rtr" = "invalid" ]]; then
+ if [[ "$rtr" != "$old_rtr" && "$mac" != "$old_mac" ]]; then
+ echo "Got defgw $rtr at $mac on $RA_IF" >&2
+ update_rtr "$rtr" "$mac" || true
+ retries=-1
+ old_mac="$mac"
+ old_rtr="$rtr"
+ fi
+ fi
+ # Only update router properties if we use this router
+ [[ "$rtr" == "$old_rtr" ]] || continue
+ if [[ $pfx != "$old_pfx" ]]; then
+ echo "Got PFX $pfx from $rtr on $RA_IF" >&2
+ old_pfx="$pfx"
+ update_pfx "$pfx" || true
+ fi
+ if [[ $fqdn != "$old_fqdn" ]]; then
+ echo "Got FQDN $fqdn from $rtr on $RA_IF" >&2
+ old_fqdn="$fqdn"
+ update_fqdn "$fqdn" || true
+ fi
+ fi
+ done < <(exec script -q -c "rdisc6 ${args[*]}" /dev/null 2>/dev/null)
+ # Purge any expired routers
+ for rtr in "${!rtrs[@]}"; do
+ # shellcheck disable=SC2206
+ data=(${rtrs["$rtr"]})
+ dl=${data[1]}
+ if (( dl <= SECONDS )); then
+ unset "rtrs[$rtr]"
+ fi
+ done
+ # Consider changing the gateway if the old one doesn't send RAs for the entire period
+ # This ensures we don't flip flop between multiple defaults if they exist.
+ if [[ "$old_rtr" != "invalid" && -z "${rtrs["$old_rtr"]-}" ]]; then
+ echo "Old router $old_rtr disappeared" >&2
+ old_rtr=invalid
+ for rtr in "${!rtrs[@]}"; do
+ # shellcheck disable=SC2206
+ data=(${rtrs["$rtr"]})
+ mac=${data[0]}
+ dl=${data[1]}
+ pfx=${data[2]}
+ fqdn=${data[3]}
+ update_rtr "$rtr" "$mac" || true
+ update_pfx "$pfx" || true
+ update_fqdn "$fqdn" || true
+ break
+ done
+ fi
+
+ # If rdisc6 exits early we still want to wait for the deadline before retrying
+ (( timeout = curr_dl - SECONDS ))
+ sleep $(( timeout < 0 ? 0 : timeout ))
+done
diff --git a/meta-google/recipes-google/networking/gbmc-nic-config.bb b/meta-google/recipes-google/networking/gbmc-nic-config.bb
new file mode 100644
index 0000000000..e804e2628d
--- /dev/null
+++ b/meta-google/recipes-google/networking/gbmc-nic-config.bb
@@ -0,0 +1,79 @@
+SUMMARY = "Configured gBMC non-NCSI interface"
+PR = "r1"
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://${COREBASE}/meta/files/common-licenses/Apache-2.0;md5=89aea4e17d99a7cacdbeed46a0096b10"
+
+GBMC_EXT_NICS ?= ""
+GBMC_DHCP_RELAY ??= "${@'' if int(d.getVar('FLASH_SIZE')) < 65536 else '1'}"
+
+inherit systemd
+
+SRC_URI += " \
+ file://50-gbmc-nic.rules \
+ file://50-gbmc-nic.rules.in \
+ file://-bmc-nic.network.in \
+ file://gbmc-nic-neigh.sh.in \
+ file://gbmc-nic-ra.sh \
+ file://gbmc-nic-ra@.service \
+ ${@'' if d.getVar('GBMC_DHCP_RELAY') != '1' else 'file://-bmc-gbmcbrnicdhcp.netdev'} \
+ ${@'' if d.getVar('GBMC_DHCP_RELAY') != '1' else 'file://-bmc-gbmcbrnicdhcp.network'} \
+ ${@'' if d.getVar('GBMC_DHCP_RELAY') != '1' else 'file://-bmc-gbmcnicdhcp.netdev'} \
+ ${@'' if d.getVar('GBMC_DHCP_RELAY') != '1' else 'file://-bmc-gbmcnicdhcp.network'} \
+ ${@'' if d.getVar('GBMC_DHCP_RELAY') != '1' else 'file://gbmc-nic-dhcrelay.service.in'} \
+ "
+S = "${WORKDIR}"
+
+FILES:${PN} += " \
+ ${systemd_unitdir}/network \
+ ${sysconfdir}/nftables \
+ ${systemd_system_unitdir} \
+ ${datadir}/gbmc-ip-monitor \
+ "
+
+RDEPENDS:${PN}:append = " \
+ bash \
+ gbmc-ip-monitor \
+ gbmc-net-common \
+ nftables-systemd \
+ "
+
+do_install() {
+ netdir=${D}${systemd_unitdir}/network
+ install -d -m0755 $netdir
+ nftdir=${D}${sysconfdir}/nftables
+ install -d -m0755 $nftdir
+ unitdir=${D}${systemd_system_unitdir}
+ install -d -m0755 $unitdir
+ wantdir=$unitdir/multi-user.target.wants
+ install -d -m0755 $wantdir
+
+ install -d -m0755 ${D}${libexecdir}
+ install -m0755 ${WORKDIR}/gbmc-nic-ra.sh ${D}${libexecdir}/
+ install -m0644 ${WORKDIR}/gbmc-nic-ra@.service $unitdir/
+
+ mondir=${D}${datadir}/gbmc-ip-monitor
+ install -d -m0755 $mondir
+ sed 's,@IFS@,${GBMC_EXT_NICS},g' <${WORKDIR}/gbmc-nic-neigh.sh.in \
+ >$mondir/gbmc-nic-neigh.sh
+
+ uppers=
+ for intf in ${GBMC_EXT_NICS}; do
+ sed "s,@IF@,$intf,g" <${WORKDIR}/50-gbmc-nic.rules.in >$nftdir/50-gbmc-$intf.rules
+ sed "s,@IF@,$intf,g" <${WORKDIR}/-bmc-nic.network.in >$netdir/-bmc-$intf.network
+ uppers="$uppers -u ff02::1:2%%$intf"
+ ln -sv ../gbmc-nic-ra@.service $wantdir/gbmc-nic-ra@$intf.service
+ done
+
+ if [ "${GBMC_DHCP_RELAY}" = 1 ]; then
+ install -m0644 ${WORKDIR}/-bmc-gbmcbrnicdhcp.network $netdir/
+ install -m0644 ${WORKDIR}/-bmc-gbmcbrnicdhcp.netdev $netdir/
+ install -m0644 ${WORKDIR}/-bmc-gbmcnicdhcp.network $netdir/
+ install -m0644 ${WORKDIR}/-bmc-gbmcnicdhcp.netdev $netdir/
+ install -m0644 ${WORKDIR}/50-gbmc-nic.rules $nftdir/
+
+ sed "s,@UPPERS@,$uppers,g" <${WORKDIR}/gbmc-nic-dhcrelay.service.in \
+ >$unitdir/gbmc-nic-dhcrelay.service
+ ln -sv ../gbmc-nic-dhcrelay.service $wantdir/
+ fi
+}
+
diff --git a/meta-google/recipes-google/networking/gbmc-nic-config/-bmc-gbmcbrnicdhcp.netdev b/meta-google/recipes-google/networking/gbmc-nic-config/-bmc-gbmcbrnicdhcp.netdev
new file mode 100644
index 0000000000..1d9ca4a734
--- /dev/null
+++ b/meta-google/recipes-google/networking/gbmc-nic-config/-bmc-gbmcbrnicdhcp.netdev
@@ -0,0 +1,5 @@
+[NetDev]
+Name=gbmcbrnicdhcp
+Kind=veth
+[Peer]
+Name=gbmcnicdhcp
diff --git a/meta-google/recipes-google/networking/gbmc-nic-config/-bmc-gbmcbrnicdhcp.network b/meta-google/recipes-google/networking/gbmc-nic-config/-bmc-gbmcbrnicdhcp.network
new file mode 100644
index 0000000000..73212db0c3
--- /dev/null
+++ b/meta-google/recipes-google/networking/gbmc-nic-config/-bmc-gbmcbrnicdhcp.network
@@ -0,0 +1,4 @@
+[Match]
+Name=gbmcbrnicdhcp
+[Network]
+Bridge=gbmcbr
diff --git a/meta-google/recipes-google/networking/gbmc-nic-config/-bmc-gbmcnicdhcp.netdev b/meta-google/recipes-google/networking/gbmc-nic-config/-bmc-gbmcnicdhcp.netdev
new file mode 100644
index 0000000000..24a78fbfa4
--- /dev/null
+++ b/meta-google/recipes-google/networking/gbmc-nic-config/-bmc-gbmcnicdhcp.netdev
@@ -0,0 +1,5 @@
+[NetDev]
+Name=gbmcnicdhcp
+Kind=veth
+[Peer]
+Name=gbmcbrnicdhcp
diff --git a/meta-google/recipes-google/networking/gbmc-nic-config/-bmc-gbmcnicdhcp.network b/meta-google/recipes-google/networking/gbmc-nic-config/-bmc-gbmcnicdhcp.network
new file mode 100644
index 0000000000..1eae55a662
--- /dev/null
+++ b/meta-google/recipes-google/networking/gbmc-nic-config/-bmc-gbmcnicdhcp.network
@@ -0,0 +1,9 @@
+[Match]
+Name=gbmcnicdhcp
+[Network]
+DHCP=false
+IPv6AcceptRA=false
+LLMNR=false
+MulticastDNS=false
+LinkLocalAddressing=ipv6
+Address=fdb5:0481:10ce::3/64
diff --git a/meta-google/recipes-google/networking/gbmc-nic-config/-bmc-nic.network.in b/meta-google/recipes-google/networking/gbmc-nic-config/-bmc-nic.network.in
new file mode 100644
index 0000000000..08c2eee178
--- /dev/null
+++ b/meta-google/recipes-google/networking/gbmc-nic-config/-bmc-nic.network.in
@@ -0,0 +1,8 @@
+[Match]
+Name=@IF@
+[Network]
+DHCP=false
+IPv6AcceptRA=false
+LLMNR=false
+MulticastDNS=false
+LinkLocalAddressing=ipv6
diff --git a/meta-google/recipes-google/networking/gbmc-nic-config/50-gbmc-nic.rules b/meta-google/recipes-google/networking/gbmc-nic-config/50-gbmc-nic.rules
new file mode 100644
index 0000000000..cbedfb9710
--- /dev/null
+++ b/meta-google/recipes-google/networking/gbmc-nic-config/50-gbmc-nic.rules
@@ -0,0 +1,8 @@
+table inet filter {
+ chain nic_dhcp_input {
+ type filter hook input priority 0; policy drop;
+ iifname != gbmcnicdhcp accept
+ ip6 nexthdr icmpv6 accept
+ udp dport 547 accept
+ }
+}
diff --git a/meta-google/recipes-google/networking/gbmc-nic-config/50-gbmc-nic.rules.in b/meta-google/recipes-google/networking/gbmc-nic-config/50-gbmc-nic.rules.in
new file mode 100644
index 0000000000..feba64d292
--- /dev/null
+++ b/meta-google/recipes-google/networking/gbmc-nic-config/50-gbmc-nic.rules.in
@@ -0,0 +1,19 @@
+table inet filter {
+ chain @IF@_input {
+ type filter hook input priority 0; policy drop;
+ iifname != @IF@ accept
+ ct state established accept
+ udp dport 547 accept
+ jump gbmc_br_pub_input
+ }
+ chain gbmc_br_pub_input {
+ ip6 nexthdr icmpv6 accept
+ }
+ chain @IF@_forward {
+ type filter hook forward priority 0; policy drop;
+ iifname != @IF@ accept
+ oifname != gbmcbr drop
+ ip6 daddr fdb5:0481:10ce::/64 drop
+ ip6 saddr fdb5:0481:10ce::/64 drop
+ }
+}
diff --git a/meta-google/recipes-google/networking/gbmc-nic-config/gbmc-nic-dhcrelay.service.in b/meta-google/recipes-google/networking/gbmc-nic-config/gbmc-nic-dhcrelay.service.in
new file mode 100644
index 0000000000..8571ae1e67
--- /dev/null
+++ b/meta-google/recipes-google/networking/gbmc-nic-config/gbmc-nic-dhcrelay.service.in
@@ -0,0 +1,13 @@
+[Unit]
+Description=gBMC DHCP Relay Agent Daemon
+After=network.target
+StartLimitIntervalSec=10
+StartLimitBurst=3
+
+[Service]
+Restart=always
+RestartSec=5
+ExecStart=/usr/sbin/dhcrelay -d --no-pid -l gbmcnicdhcp @UPPERS@
+
+[Install]
+WantedBy=multi-user.target
diff --git a/meta-google/recipes-google/networking/gbmc-nic-config/gbmc-nic-neigh.sh.in b/meta-google/recipes-google/networking/gbmc-nic-config/gbmc-nic-neigh.sh.in
new file mode 100644
index 0000000000..d7c0f023b7
--- /dev/null
+++ b/meta-google/recipes-google/networking/gbmc-nic-config/gbmc-nic-neigh.sh.in
@@ -0,0 +1,98 @@
+#!/bin/bash
+# Copyright 2024 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+[[ -n ${gbmc_nic_neigh_lib-} ]] && return
+
+# shellcheck source=meta-google/recipes-google/networking/network-sh/lib.sh
+source /usr/share/network/lib.sh || exit
+# shellcheck source=meta-google/recipes-google/networking/gbmc-net-common/gbmc-net-lib.sh
+source /usr/share/gbmc-net-lib.sh || exit
+
+gbmc_nic_neigh_intfs=(@IFS@)
+gbmc_nic_neigh_addr=
+
+gbmc_nic_neigh_set() {
+ local act="$1"
+ local ip="$2"
+
+ echo "gBMC NIC Neigh $act $ip: ${gbmc_nic_neigh_intfs[*]}" >&2
+
+ local intf
+ local failed_intfs=()
+ for intf in "${gbmc_nic_neigh_intfs[@]}"; do
+ # In case we don't have a base network file, make one
+ # this is intentionally 00- as it will not preceed /etc/systemd/network/00-*
+ # or /lib/systemd/network/-* files.
+ local file=/run/systemd/network/00-bmc-$intf.network
+ printf '[Match]\nName=%s\n[Network]\nDHCP=false\nIPv6AcceptRA=false\nLinkLocalAddressing=yes' \
+ "$intf" >"$file"
+
+ # Override any existing gateway information within files
+ # Make sure we cover `00-*` and `-*` files
+ for file in /run/systemd/network/{00,}-bmc-"$intf".network; do
+ mkdir -p "$file.d"
+ if [[ "$act" == add ]]; then
+ printf '[Network]\nIPv6ProxyNDP=yes\nIPv6ProxyNDPAddress=%s\n' \
+ "$ip" >"$file.d"/10-nic-neigh.conf
+ else
+ rm -f "$file.d"/10-nic-neigh.conf
+ fi
+ done
+
+ sysctl net.ipv6.conf."$intf".proxy_ndp=1 >/dev/null && \
+ ip -6 neigh "$act" proxy "$ip" dev "$intf" || \
+ failed_intfs+=("$intf")
+ done
+ [[ "$act" == del ]] && return
+ if (( "${#failed_intfs[@]}" > 0 )); then
+ gbmc_net_networkd_reload "${failed_intfs[@]}"
+ fi
+}
+
+gbmc_nic_neigh_hook() {
+ # shellcheck disable=SC2154
+ if [[ $change == addr && $intf == gbmcbr && $scope == global ]] &&
+ [[ $fam == inet6 && $flags != *tentative* ]]; then
+ local ip_bytes=()
+ if ! ip_to_bytes ip_bytes "$ip"; then
+ echo "gBMC Bridge Ensure RA Invalid IP: $ip" >&2
+ return 1
+ fi
+ # Ignore ULAs
+ if (( (ip_bytes[0] & 0xfe) == 0xfc )); then
+ return 0
+ fi
+ # Addresses must be /64 to the upstack switch
+ for (( i = 8; i < 16; ++i )); do
+ if (( ip_bytes[i] != 0 )); then
+ return 0
+ fi
+ done
+ if [[ $action == add && "$gbmc_nic_neigh_addr" != "$ip" ]]; then
+ if [ -n "$gbmc_nic_neigh_addr" ]; then
+ gbmc_nic_neigh_set del "$gbmc_nic_neigh_addr"
+ fi
+ gbmc_nic_neigh_addr="$ip"
+ gbmc_nic_neigh_set add "$ip"
+ elif [[ $action == del && "$gbmc_nic_neigh_addr" == "$ip" ]]; then
+ gbmc_nic_neigh_addr=
+ gbmc_nic_neigh_set del "$ip"
+ fi
+ fi
+}
+
+GBMC_IP_MONITOR_HOOKS+=(gbmc_nic_neigh_hook)
+
+gbmc_nic_neigh_lib=1
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
new file mode 100755
index 0000000000..98239c33f6
--- /dev/null
+++ b/meta-google/recipes-google/networking/gbmc-nic-config/gbmc-nic-ra.sh
@@ -0,0 +1,35 @@
+#!/bin/bash
+# Copyright 2024 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+update_rtr() {
+ default_update_rtr "$@"
+}
+
+update_fqdn() {
+ true
+}
+
+update_pfx() {
+ true
+}
+
+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
+
+# shellcheck source=meta-google/recipes-google/networking/gbmc-net-common/gbmc-ra.sh
+source /usr/share/gbmc-ra.sh || exit
diff --git a/meta-google/recipes-google/networking/gbmc-nic-config/gbmc-nic-ra@.service b/meta-google/recipes-google/networking/gbmc-nic-config/gbmc-nic-ra@.service
new file mode 100644
index 0000000000..54d77dfeb7
--- /dev/null
+++ b/meta-google/recipes-google/networking/gbmc-nic-config/gbmc-nic-ra@.service
@@ -0,0 +1,13 @@
+[Unit]
+Description=gBMC %i RA Discovery
+After=network.target
+StartLimitIntervalSec=10
+StartLimitBurst=3
+
+[Service]
+Restart=always
+RestartSec=5
+ExecStart=/usr/libexec/gbmc-nic-ra.sh %i
+
+[Install]
+WantedBy=multi-user.target
diff --git a/meta-google/recipes-google/systemd/files/40-gbmc-sysctl.conf b/meta-google/recipes-google/systemd/files/40-gbmc-sysctl.conf
index ee4b4859a7..5b3fa9e43d 100644
--- a/meta-google/recipes-google/systemd/files/40-gbmc-sysctl.conf
+++ b/meta-google/recipes-google/systemd/files/40-gbmc-sysctl.conf
@@ -1 +1,3 @@
kernel.oops_all_cpu_backtrace = 1
+# limit PID numbers to 32k for metrics collector
+kernel.pid_max = 32768