blob: 086d8357327ec0a498af697c97d99a6819380d66 [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
William A. Kennington III48282222024-06-18 16:57:24 -070055 # Don't force networkd to reload as this can break phosphor-networkd
56 # Fall back to reload only if ip link commands fail
57 (ip -6 route replace default via "$rtr" dev "$NCSI_IF" && \
58 ip -6 neigh replace "$rtr" dev "$NCSI_IF" lladdr "$mac") || \
59 (networkctl reload && networkctl reconfigure "$NCSI_IF") || true
William A. Kennington III246bcaa2022-02-11 02:53:28 -080060
Patrick Williams59486672022-12-08 06:23:47 -060061 retries=-1
62 old_mac="$mac"
63 old_rtr="$rtr"
William A. Kennington III246bcaa2022-02-11 02:53:28 -080064}
65
66retries=1
William A. Kennington IIIa9b18222024-06-17 14:15:42 -070067min_w=10
68declare -A rtrs
69rtrs=()
William A. Kennington III246bcaa2022-02-11 02:53:28 -080070while true; do
William A. Kennington IIIa9b18222024-06-17 14:15:42 -070071 data=(${rtrs["${old_rtr}"]-})
72 curr_dl="${data[1]-$min_w}"
73 args=(-m "$NCSI_IF" -w $(( (curr_dl - SECONDS) * 1000 )))
Patrick Williams59486672022-12-08 06:23:47 -060074 if (( retries > 0 )); then
75 args+=(-r "$retries")
76 else
77 args+=(-d)
William A. Kennington III379b0612021-11-04 02:42:30 -070078 fi
Patrick Williams59486672022-12-08 06:23:47 -060079 while read line; do
William A. Kennington IIId36d9ef2024-03-19 14:02:42 -070080 # `script` terminates all lines with a CRLF, remove it
81 line="${line:0:-1}"
Patrick Williams59486672022-12-08 06:23:47 -060082 if [ -z "$line" ]; then
William A. Kennington IIIa9b18222024-06-17 14:15:42 -070083 lifetime=-1
Patrick Williams59486672022-12-08 06:23:47 -060084 mac=
85 elif [[ "$line" =~ ^Router' 'lifetime' '*:' '*([0-9]*) ]]; then
86 lifetime="${BASH_REMATCH[1]}"
87 elif [[ "$line" =~ ^Source' 'link-layer' 'address' '*:' '*([a-fA-F0-9:]*)$ ]]; then
88 mac="${BASH_REMATCH[1]}"
89 elif [[ "$line" =~ ^from' '(.*)$ ]]; then
90 rtr="${BASH_REMATCH[1]}"
William A. Kennington IIIa9b18222024-06-17 14:15:42 -070091 # Only valid default routers can be considered, 0 lifetime implies
92 # a non-default router
93 if (( lifetime > 0 )); then
94 dl=$((lifetime + SECONDS))
95 rtrs["$rtr"]="$mac $dl"
William A. Kennington III1e2289c2024-06-17 14:57:25 -070096 # We have some notoriously noisy lab environments with many routers being broadcast
97 # We always prefer "fe80::1" in prod and labs for routing, so prefer that gateway.
98 # We also want to take the first router we find to speed up acquisition on boot.
99 if [ "$rtr" = "fe80::1" -o -z "$old_rtr" ]; then
William A. Kennington IIIa9b18222024-06-17 14:15:42 -0700100 set_rtr || true
101 fi
102 fi
103 lifetime=-1
Patrick Williams59486672022-12-08 06:23:47 -0600104 mac=
Patrick Williams59486672022-12-08 06:23:47 -0600105 fi
William A. Kennington IIId36d9ef2024-03-19 14:02:42 -0700106 done < <(exec script -q -c "rdisc6 ${args[*]}" /dev/null 2>/dev/null)
William A. Kennington IIIa9b18222024-06-17 14:15:42 -0700107 # Purge any expired routers
108 for rtr in "${!rtrs[@]}"; do
109 data=(${rtrs["$rtr"]})
110 dl=${data[1]}
111 if (( dl <= SECONDS )); then
112 unset rtrs["$rtr"]
113 fi
114 done
115 # Consider changing the gateway if the old one doesn't send RAs for the entire period
116 # This ensures we don't flip flop between multiple defaults if they exist.
117 if [ -z "${rtrs["$old_rtr"]-}" ]; then
118 echo "Old router $old_rtr disappeared" >&2
119 for rtr in "${!rtrs[@]}"; do
120 data=(${rtrs["$rtr"]})
121 mac=${data[0]}
122 dl=${data[1]}
123 set_rtr && break
124 done
125 fi
126
127 # If rdisc6 exits early we still want to wait for the deadline before retrying
128 (( timeout = curr_dl - SECONDS ))
Patrick Williams59486672022-12-08 06:23:47 -0600129 sleep $(( timeout < 0 ? 0 : timeout ))
William A. Kennington III246bcaa2022-02-11 02:53:28 -0800130done