blob: d7c0f023b7c346ba77d064dbff6d8b330fe5bae0 [file] [log] [blame]
#!/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