From 24615567082edbe4c287e994f92fb94afcedf185 Mon Sep 17 00:00:00 2001 From: "William A. Kennington III" Date: Mon, 26 Apr 2021 14:10:52 -0700 Subject: meta-google: gbmc-bridge: Assign stable addresses from RAs We want BMCs to be able to discover their machine prefix and assign a stable IPv6 based on that prefix combined with the MAC of the BMC. Change-Id: I67b8c56f50ff3a970175abcb81b429ceb1258b69 Signed-off-by: William A. Kennington III --- .../networking/gbmc-bridge/-bmc-gbmcbr.network | 2 +- .../gbmc-bridge/gbmc-br-ensure-ra.service | 5 ++ .../networking/gbmc-bridge/gbmc-br-ensure-ra.sh | 27 +++++++ .../networking/gbmc-bridge/gbmc-br-from-ra.sh | 92 ++++++++++++++++++++++ 4 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-ensure-ra.service create mode 100644 meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-ensure-ra.sh create mode 100644 meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-from-ra.sh (limited to 'meta-google/recipes-google/networking/gbmc-bridge') diff --git a/meta-google/recipes-google/networking/gbmc-bridge/-bmc-gbmcbr.network b/meta-google/recipes-google/networking/gbmc-bridge/-bmc-gbmcbr.network index 18d208a3b..37aea6c1e 100644 --- a/meta-google/recipes-google/networking/gbmc-bridge/-bmc-gbmcbr.network +++ b/meta-google/recipes-google/networking/gbmc-bridge/-bmc-gbmcbr.network @@ -2,7 +2,7 @@ Name=gbmcbr [Network] DHCP=false -IPv6AcceptRA=false +IPv6AcceptRA=true LLMNR=true MulticastDNS=true LinkLocalAddressing=ipv6 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 new file mode 100644 index 000000000..7f97cea48 --- /dev/null +++ b/meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-ensure-ra.service @@ -0,0 +1,5 @@ +[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-ensure-ra.sh b/meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-ensure-ra.sh new file mode 100644 index 000000000..60e33d89b --- /dev/null +++ b/meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-ensure-ra.sh @@ -0,0 +1,27 @@ +#!/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. + +# 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 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 new file mode 100644 index 000000000..9a5586b8a --- /dev/null +++ b/meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-from-ra.sh @@ -0,0 +1,92 @@ +# 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. + +[ -z "${gbmc_br_from_ra_lib-}" ] || return + +source /usr/share/network/lib.sh || exit + +gbmc_br_from_ra_init= +gbmc_br_from_ra_mac= +declare -A gbmc_br_from_ra_pfxs=() +declare -A gbmc_br_from_ra_prev_addrs=() + +gbmc_br_from_ra_update() { + [ -n "$gbmc_br_from_ra_init" -a -n "$gbmc_br_from_ra_mac" ] || return + + local pfx + for pfx in "${!gbmc_br_from_ra_pfxs[@]}"; do + local cidr + if ! cidr="$(ipv6_pfx_to_cidr "$pfx")"; then + unset 'gbmc_br_from_ra_pfxs[$pfx]' + continue + fi + if (( cidr == 80 )); then + local sfx + if ! sfx="$(mac_to_eui48 "$gbmc_br_from_ra_mac")"; then + unset 'gbmc_br_from_ra_pfxs[$pfx]' + continue + fi + local addr + addr="$(ipv6_pfx_concat "$pfx" "$sfx")" + else + continue + fi + local valid="${gbmc_br_from_ra_pfxs["$pfx"]}" + if (( valid > 0 )); then + if [ -z "${gbmc_br_from_ra_prev_addrs["$addr"]-}" ]; then + echo "gBMC Bridge RA Addr Add: $addr" >&2 + gbmc_br_from_ra_prev_addrs["$addr"]=1 + fi + ip addr replace "$addr" dev gbmcbr noprefixroute + else + if [ -n "${gbmc_br_from_ra_prev_addrs["$addr"]-}" ]; then + echo "gBMC Bridge RA Addr Del: $addr" >&2 + unset 'gbmc_br_from_ra_prev_addrs[$addr]' + fi + ip addr del "$addr" dev gbmcbr + unset 'gbmc_br_from_ra_pfxs[$pfx]' + fi + done +} + +gbmc_br_from_ra_hook() { + if [ "$change" = 'init' ]; then + gbmc_br_from_ra_init=1 + gbmc_br_from_ra_update + elif [[ "$change" == 'route' && "$route" != *' via '* ]] && + [[ "$route" =~ ^(.* dev gbmcbr proto ra .*)( +expires +([^ ]+)sec).*$ ]]; then + pfx="${route%% *}" + if [ "$action" = 'add' ]; then + gbmc_br_from_ra_pfxs["$pfx"]="${BASH_REMATCH[3]}" + gbmc_br_from_ra_update + elif [ "$action" = 'del' ]; then + gbmc_br_from_ra_pfxs["$pfx"]=0 + gbmc_br_from_ra_update + fi + elif [ "$change" = 'link' -a "$intf" = 'gbmcbr' ]; then + rdisc6 -m gbmcbr -r 1 -w 100 >/dev/null 2>&1 + if [ "$action" = 'add' -a "$mac" != "$gbmc_br_from_ra_mac" ]; then + gbmc_br_from_ra_mac="$mac" + gbmc_br_from_ra_update + fi + if [ "$action" = 'del' -a "$mac" = "$gbmc_br_from_ra_mac" ]; then + gbmc_br_from_ra_mac= + gbmc_br_from_ra_update + fi + fi +} + +GBMC_IP_MONITOR_HOOKS+=(gbmc_br_from_ra_hook) + +gbmc_br_from_ra_lib=1 -- cgit v1.2.3