blob: 2090f738f93457808986fa014c992fc7fe135bd7 [file] [log] [blame]
William A. Kennington III379b0612021-11-04 02:42:30 -07001#!/bin/bash
2# Copyright 2021 Google LLC
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16source "$(dirname "${BASH_SOURCE[0]}")"/ncsid_lib.sh
17
William A. Kennington III246bcaa2022-02-11 02:53:28 -080018NCSI_IF="$1"
William A. Kennington III379b0612021-11-04 02:42:30 -070019
William A. Kennington IIIa9b18222024-06-17 14:15:42 -070020# We would prefer empty string but it's easier for associative array handling
21# to use invalid
22old_rtr=invalid
William A. Kennington III246bcaa2022-02-11 02:53:28 -080023old_mac=
24
Patrick Williams59486672022-12-08 06:23:47 -060025function set_rtr() {
Yuxiao Zhangb47ca0d2024-05-30 16:33:51 -070026 if ! ip -6 route show | grep -q '^default'; then
27 echo 'default route missing, reconfiguring...' >&2
William A. Kennington IIIa9b18222024-06-17 14:15:42 -070028 old_rtr=invalid
Yuxiao Zhangb47ca0d2024-05-30 16:33:51 -070029 old_mac=
30 fi
Patrick Williams59486672022-12-08 06:23:47 -060031 [ "$rtr" != "$old_rtr" -a "$mac" != "$old_mac" ] || return
William A. Kennington III246bcaa2022-02-11 02:53:28 -080032
Patrick Williams59486672022-12-08 06:23:47 -060033 echo "Setting default router: $rtr at $mac" >&2
William A. Kennington III5034c562024-03-19 14:00:52 -070034
35 # Delete and static gateways and neighbors
36 while read entry; do
37 eval "$(echo "$entry" | JSONToVars)" || return
38 echo "Deleting neighbor $object"
39 DeleteObject "$service" "$object" || true
40 done < <(GetNeighborObjects "$netdev" 2>/dev/null)
41
42 busctl set-property xyz.openbmc_project.Network "$(EthObjRoot "$NCSI_IF")" \
43 xyz.openbmc_project.Network.EthernetInterface DefaultGateway6 s "" || true
44
45 # In case we don't have a base network file, make one
46 net_file=/run/systemd/network/00-bmc-$NCSI_IF.network
47 printf '[Match]\nName=%s\n[Network]\nDHCP=false\nIPv6AcceptRA=false\nLinkLocalAddressing=yes' \
48 "$NCSI_IF" >$net_file
49
50 # Override any existing gateway info
51 mkdir -p $net_file.d
52 printf '[Network]\nGateway=%s\n[Neighbor]\nMACAddress=%s\nAddress=%s' \
53 "$rtr" "$mac" "$rtr" >$net_file.d/10-gateway.conf
54
55 networkctl reload && networkctl reconfigure "$NCSI_IF" || true
William A. Kennington III246bcaa2022-02-11 02:53:28 -080056
Patrick Williams59486672022-12-08 06:23:47 -060057 retries=-1
58 old_mac="$mac"
59 old_rtr="$rtr"
William A. Kennington III246bcaa2022-02-11 02:53:28 -080060}
61
62retries=1
William A. Kennington IIIa9b18222024-06-17 14:15:42 -070063min_w=10
64declare -A rtrs
65rtrs=()
William A. Kennington III246bcaa2022-02-11 02:53:28 -080066while true; do
William A. Kennington IIIa9b18222024-06-17 14:15:42 -070067 data=(${rtrs["${old_rtr}"]-})
68 curr_dl="${data[1]-$min_w}"
69 args=(-m "$NCSI_IF" -w $(( (curr_dl - SECONDS) * 1000 )))
Patrick Williams59486672022-12-08 06:23:47 -060070 if (( retries > 0 )); then
71 args+=(-r "$retries")
72 else
73 args+=(-d)
William A. Kennington III379b0612021-11-04 02:42:30 -070074 fi
Patrick Williams59486672022-12-08 06:23:47 -060075 while read line; do
William A. Kennington IIId36d9ef2024-03-19 14:02:42 -070076 # `script` terminates all lines with a CRLF, remove it
77 line="${line:0:-1}"
Patrick Williams59486672022-12-08 06:23:47 -060078 if [ -z "$line" ]; then
William A. Kennington IIIa9b18222024-06-17 14:15:42 -070079 lifetime=-1
Patrick Williams59486672022-12-08 06:23:47 -060080 mac=
81 elif [[ "$line" =~ ^Router' 'lifetime' '*:' '*([0-9]*) ]]; then
82 lifetime="${BASH_REMATCH[1]}"
83 elif [[ "$line" =~ ^Source' 'link-layer' 'address' '*:' '*([a-fA-F0-9:]*)$ ]]; then
84 mac="${BASH_REMATCH[1]}"
85 elif [[ "$line" =~ ^from' '(.*)$ ]]; then
86 rtr="${BASH_REMATCH[1]}"
William A. Kennington IIIa9b18222024-06-17 14:15:42 -070087 # Only valid default routers can be considered, 0 lifetime implies
88 # a non-default router
89 if (( lifetime > 0 )); then
90 dl=$((lifetime + SECONDS))
91 rtrs["$rtr"]="$mac $dl"
William A. Kennington III1e2289c2024-06-17 14:57:25 -070092 # We have some notoriously noisy lab environments with many routers being broadcast
93 # We always prefer "fe80::1" in prod and labs for routing, so prefer that gateway.
94 # We also want to take the first router we find to speed up acquisition on boot.
95 if [ "$rtr" = "fe80::1" -o -z "$old_rtr" ]; then
William A. Kennington IIIa9b18222024-06-17 14:15:42 -070096 set_rtr || true
97 fi
98 fi
99 lifetime=-1
Patrick Williams59486672022-12-08 06:23:47 -0600100 mac=
Patrick Williams59486672022-12-08 06:23:47 -0600101 fi
William A. Kennington IIId36d9ef2024-03-19 14:02:42 -0700102 done < <(exec script -q -c "rdisc6 ${args[*]}" /dev/null 2>/dev/null)
William A. Kennington IIIa9b18222024-06-17 14:15:42 -0700103 # Purge any expired routers
104 for rtr in "${!rtrs[@]}"; do
105 data=(${rtrs["$rtr"]})
106 dl=${data[1]}
107 if (( dl <= SECONDS )); then
108 unset rtrs["$rtr"]
109 fi
110 done
111 # Consider changing the gateway if the old one doesn't send RAs for the entire period
112 # This ensures we don't flip flop between multiple defaults if they exist.
113 if [ -z "${rtrs["$old_rtr"]-}" ]; then
114 echo "Old router $old_rtr disappeared" >&2
115 for rtr in "${!rtrs[@]}"; do
116 data=(${rtrs["$rtr"]})
117 mac=${data[0]}
118 dl=${data[1]}
119 set_rtr && break
120 done
121 fi
122
123 # If rdisc6 exits early we still want to wait for the deadline before retrying
124 (( timeout = curr_dl - SECONDS ))
Patrick Williams59486672022-12-08 06:23:47 -0600125 sleep $(( timeout < 0 ? 0 : timeout ))
William A. Kennington III246bcaa2022-02-11 02:53:28 -0800126done