summaryrefslogtreecommitdiff
path: root/meta-google/recipes-google
diff options
context:
space:
mode:
authorJason M. Bills <jason.m.bills@linux.intel.com>2021-06-24 01:22:00 +0300
committerJason M. Bills <jason.m.bills@linux.intel.com>2021-06-24 01:22:00 +0300
commit5565c9abcc817b88098b849b2de5c017a8fb559f (patch)
tree2d2a10f694c3793a003a3cb1e2f9db52173cd3cb /meta-google/recipes-google
parent2a64b8ae9b952b18b4aef38cb7c41ce6dba16c50 (diff)
parent000fd965915b31e7e613f7e9dfe7042f76dcc951 (diff)
downloadopenbmc-5565c9abcc817b88098b849b2de5c017a8fb559f.tar.xz
Merge tag '0.57' of ssh://git-amr-1.devtools.intel.com:29418/openbmc-openbmc into update
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/ncsi/files/50-gbmc-ncsi.rules.in20
-rw-r--r--meta-google/recipes-google/ncsi/files/gbmc-ncsi-br-pub-addr.sh.in101
-rw-r--r--meta-google/recipes-google/ncsi/files/gbmc-ncsi-nft.sh.in101
-rw-r--r--meta-google/recipes-google/ncsi/gbmc-ncsi-config.bb21
-rwxr-xr-xmeta-google/recipes-google/networking/files/gbmc-ip-monitor.sh2
-rw-r--r--meta-google/recipes-google/networking/gbmc-bridge.bb105
-rw-r--r--meta-google/recipes-google/networking/gbmc-bridge/+-bmc-gbmcbrusb.network8
-rw-r--r--meta-google/recipes-google/networking/gbmc-bridge/-bmc-gbmcbr.netdev5
-rw-r--r--meta-google/recipes-google/networking/gbmc-bridge/-bmc-gbmcbr.network.in9
-rw-r--r--meta-google/recipes-google/networking/gbmc-bridge/-bmc-gbmcbrdummy.netdev3
-rw-r--r--meta-google/recipes-google/networking/gbmc-bridge/-bmc-gbmcbrdummy.network4
-rw-r--r--meta-google/recipes-google/networking/gbmc-bridge/50-gbmc-br.rules27
-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-ensure-ra.sh27
-rw-r--r--meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-from-ra.sh96
-rw-r--r--meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-gw-src.sh74
-rw-r--r--meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-nft.sh76
-rw-r--r--meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-ula.sh71
-rw-r--r--meta-google/recipes-google/networking/gbmc-bridge/ipmi.service.in11
-rw-r--r--meta-google/recipes-google/networking/gbmc-iperf3.bb4
-rw-r--r--meta-google/recipes-google/networking/network-sh/lib.sh236
-rwxr-xr-xmeta-google/recipes-google/networking/network-sh/test.sh169
-rw-r--r--meta-google/recipes-google/systemd/files/40-gbmc-forward.conf5
-rw-r--r--meta-google/recipes-google/systemd/gbmc-systemd-config.bb29
25 files changed, 1141 insertions, 70 deletions
diff --git a/meta-google/recipes-google/google-misc/google-misc.inc b/meta-google/recipes-google/google-misc/google-misc.inc
index 95f52613a..85acb9353 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"
-SRCREV = "4c68ffb8b08fa4484824586ef4a981bcfabd38bb"
+SRCREV = "4a0e2e3c10327dac1c923d263929be9a20478b24"
S = "${WORKDIR}/git/subprojects/${GOOGLE_MISC_PROJ}"
inherit meson
diff --git a/meta-google/recipes-google/ncsi/files/50-gbmc-ncsi.rules.in b/meta-google/recipes-google/ncsi/files/50-gbmc-ncsi.rules.in
index 33031f0db..938dca34b 100644
--- a/meta-google/recipes-google/ncsi/files/50-gbmc-ncsi.rules.in
+++ b/meta-google/recipes-google/ncsi/files/50-gbmc-ncsi.rules.in
@@ -3,12 +3,32 @@ table inet filter {
type filter hook input priority 0; policy drop;
iifname != @NCSI_IF@ accept
ct state established accept
+ ip6 daddr ff00::/8 goto ncsi_brd_input
+ ip6 daddr fe80::/64 goto ncsi_legacy_input
+ }
+ chain ncsi_gbmc_br_pub_input {
+ jump gbmc_br_pub_input
+ reject
+ }
+ chain gbmc_br_pub_input {
+ }
+ chain ncsi_legacy_input {
+ jump ncsi_brd_input
tcp dport 3959 accept
udp dport 3959 accept
tcp dport 3967 accept
udp dport 3967 accept
+ }
+ chain ncsi_brd_input {
icmpv6 type nd-neighbor-advert accept
icmpv6 type nd-neighbor-solicit accept
icmpv6 type nd-router-advert accept
}
+ chain ncsi_forward {
+ type filter hook forward priority 0; policy drop;
+ iifname != @NCSI_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/ncsi/files/gbmc-ncsi-br-pub-addr.sh.in b/meta-google/recipes-google/ncsi/files/gbmc-ncsi-br-pub-addr.sh.in
new file mode 100644
index 000000000..961da5095
--- /dev/null
+++ b/meta-google/recipes-google/ncsi/files/gbmc-ncsi-br-pub-addr.sh.in
@@ -0,0 +1,101 @@
+# 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_ncsi_br_pub_addr_lib-}" ] || return
+
+gbmc_ncsi_br_pub_addr_init=
+gbmc_ncsi_br_pub_addr_lastip=
+
+gbmc_ncsi_br_pub_addr_update() {
+ [ -n "$gbmc_ncsi_br_pub_addr_init" ] || return
+
+ printf 'gBMC Bridge Pub Addr from NCSI: %s\n' \
+ "${gbmc_ncsi_br_pub_addr_lastip:-(deleted)}" >&2
+
+ local pfx_bytes=()
+ if [ -n "$gbmc_ncsi_br_pub_addr_lastip" ]; then
+ ip_to_bytes pfx_bytes "$gbmc_ncsi_br_pub_addr_lastip"
+ # Ensure we don't have more than a /64 address
+ local i
+ for (( i = 8; i < 16; ++i )); do
+ if (( pfx_bytes[$i] != 0 )); then
+ pfx_bytes=()
+ break
+ fi
+ done
+ fi
+
+ local contents='[Network]'$'\n'
+ if (( ${#pfx_bytes[@]} != 0 )); then
+ pfx_bytes[8]=0xfd
+ local stateless_pfx="$(ip_bytes_to_str pfx_bytes)"
+ pfx_bytes[9]=0x01
+ local ncsi_pfx="$(ip_bytes_to_str pfx_bytes)"
+ local here=
+ read -r -d '' here <<EOF
+Address=$ncsi_pfx/128
+IPv6PrefixDelegation=yes
+[IPv6PrefixDelegation]
+RouterLifetimeSec=60
+[IPv6Prefix]
+Prefix=$stateless_pfx/80
+PreferredLifetimeSec=60
+ValidLifetimeSec=60
+[IPv6RoutePrefix]
+Route=$ncsi_pfx/80
+LifetimeSec=60
+[Route]
+Destination=$stateless_pfx/72
+Type=unreachable
+Metric=1024
+EOF
+ contents+="$here"$'\n'
+ fi
+
+ local file
+ for file in /run/systemd/network/{00,}-bmc-gbmcbr.network.d/50-public.conf; do
+ mkdir -p -m 755 "$(dirname "$file")"
+ printf '%s' "$contents" >"$file"
+ 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
+
+ if [ "$(systemctl is-active systemd-networkd)" != 'inactive' ]; then
+ networkctl reload
+ networkctl reconfigure gbmcbr
+ fi
+}
+
+gbmc_ncsi_br_pub_addr_hook() {
+ if [ "$change" = 'init' ]; then
+ gbmc_ncsi_br_pub_addr_init=1
+ gbmc_ncsi_br_pub_addr_update
+ elif [ "$change" = 'addr' -a "$intf" = '@NCSI_IF@' ] &&
+ [ "$scope" = 'global' -a "$fam" = 'inet6' ]; then
+ if [ "$action" = 'add' -a "$ip" != "$gbmc_ncsi_br_pub_addr_lastip" ]; then
+ gbmc_ncsi_br_pub_addr_lastip="$ip"
+ gbmc_ncsi_br_pub_addr_update
+ fi
+ if [ "$action" = 'del' -a "$ip" = "$gbmc_ncsi_br_pub_addr_lastip" ]; then
+ gbmc_ncsi_br_pub_addr_lastip=
+ gbmc_ncsi_br_pub_addr_update
+ fi
+ fi
+}
+
+GBMC_IP_MONITOR_HOOKS+=(gbmc_ncsi_br_pub_addr_hook)
+
+gbmc_ncsi_br_pub_addr_lib=1
diff --git a/meta-google/recipes-google/ncsi/files/gbmc-ncsi-nft.sh.in b/meta-google/recipes-google/ncsi/files/gbmc-ncsi-nft.sh.in
new file mode 100644
index 000000000..93d1a4ad2
--- /dev/null
+++ b/meta-google/recipes-google/ncsi/files/gbmc-ncsi-nft.sh.in
@@ -0,0 +1,101 @@
+# 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_ncsi_nft_lib-}" ] || return
+
+gbmc_ncsi_nft_init=
+gbmc_ncsi_nft_lastip4=
+gbmc_ncsi_nft_lastip6=
+
+gbmc_ncsi_nft_update() {
+ [ -n "$gbmc_ncsi_nft_init" ] || return
+
+ printf 'NCSI firewall for IPv4(%s) IPv6(%s)\n' \
+ "${gbmc_ncsi_nft_lastip4:-(deleted)}" \
+ "${gbmc_ncsi_nft_lastip6:-(deleted)}" >&2
+
+ local contents=
+ contents+='table inet filter {'$'\n'
+ contents+=' chain ncsi_input {'$'\n'
+
+ local ip4="$gbmc_ncsi_nft_lastip4"
+ if [ -n "$ip4" ]; then
+ contents+=" ip daddr $ip4 goto ncsi_legacy_input"$'\n'
+ fi
+
+ local ip6="$gbmc_ncsi_nft_lastip6"
+ if [ -n "$ip6" ]; then
+ contents+=" ip6 daddr $ip6/128 goto ncsi_legacy_input"$'\n'
+
+ local ip_bytes=()
+ ip_to_bytes ip_bytes "$ip6"
+ # If our address has enough spare bits for appending the BMC suffix
+ # then we add a rule that allows the BMC subnet. That is, we need a /64
+ # as input.
+ local i
+ for (( i = 8; i < 16; i++ )); do
+ if (( ip_bytes[$i] != 0 )); then
+ ip_bytes=()
+ break
+ fi
+ done
+ if (( ${#ip_bytes[@]} != 0 )); then
+ ip_bytes[8]=0xfd
+ local pfx="$(ip_bytes_to_str ip_bytes)"
+ contents+=" ip6 saddr != $pfx/72 ip6 daddr"
+ contents+=" $pfx/72 goto ncsi_gbmc_br_pub_input"$'\n'
+ fi
+ fi
+
+ contents+=' }'$'\n'
+ contents+=' chain ncsi_forward {'$'\n'
+ if [ -n "$pfx" ]; then
+ contents+=" ip6 saddr != $pfx/72 ip6 daddr $pfx/72 accept"$'\n'
+ fi
+ contents+=' }'$'\n'
+ contents+='}'$'\n'
+
+ local rfile=/run/nftables/40-gbmc-ncsi-in.rules
+ mkdir -p -m 755 "$(dirname "$rfile")"
+ printf '%s' "$contents" >"$rfile"
+
+ echo 'Restarting nftables' >&2
+ systemctl reset-failed nftables
+ systemctl --no-block restart nftables
+}
+
+gbmc_ncsi_nft_hook() {
+ if [ "$change" = 'init' ]; then
+ gbmc_ncsi_nft_init=1
+ gbmc_ncsi_nft_update
+ elif [ "$change" = 'addr' -a "$intf" = '@NCSI_IF@' -a "$scope" = 'global' ]; then
+ if [ "$fam" = 'inet6' ]; then
+ local -n lastip='gbmc_ncsi_nft_lastip6'
+ else
+ local -n lastip='gbmc_ncsi_nft_lastip4'
+ fi
+ if [ "$action" = 'add' -a "$ip" != "$lastip" ]; then
+ lastip="$ip"
+ gbmc_ncsi_nft_update
+ fi
+ if [ "$action" = 'del' -a "$ip" = "$lastip" ]; then
+ lastip=
+ gbmc_ncsi_nft_update
+ fi
+ fi
+}
+
+GBMC_IP_MONITOR_HOOKS+=(gbmc_ncsi_nft_hook)
+
+gbmc_ncsi_nft_lib=1
diff --git a/meta-google/recipes-google/ncsi/gbmc-ncsi-config.bb b/meta-google/recipes-google/ncsi/gbmc-ncsi-config.bb
index ecdda2cb6..098819988 100644
--- a/meta-google/recipes-google/ncsi/gbmc-ncsi-config.bb
+++ b/meta-google/recipes-google/ncsi/gbmc-ncsi-config.bb
@@ -9,17 +9,23 @@ SRC_URI += " \
file://50-gbmc-ncsi.rules.in \
file://gbmc-ncsi-sslh.socket.in \
file://gbmc-ncsi-sslh.service \
+ file://gbmc-ncsi-nft.sh.in \
+ file://gbmc-ncsi-br-pub-addr.sh.in \
"
S = "${WORKDIR}"
RDEPENDS_${PN} += " \
+ gbmc-ip-monitor \
ncsid \
nftables-systemd \
sslh \
"
-FILES_${PN} += "${systemd_unitdir}"
+FILES_${PN} += " \
+ ${datadir}/gbmc-ip-monitor \
+ ${systemd_unitdir} \
+ "
SYSTEMD_SERVICE_${PN} += " \
gbmc-ncsi-sslh.service \
@@ -50,7 +56,7 @@ do_install_append() {
nftdir=${D}${sysconfdir}/nftables
install -d -m0755 "$nftdir"
- sed "s,@NCSI_IF@,$if_name," ${WORKDIR}/50-gbmc-ncsi.rules.in \
+ sed "s,@NCSI_IF@,$if_name,g" ${WORKDIR}/50-gbmc-ncsi.rules.in \
>"$nftdir"/50-gbmc-ncsi.rules
wantdir=${D}${systemd_system_unitdir}/multi-user.target.wants
@@ -58,6 +64,15 @@ do_install_append() {
ln -sv ../ncsid@.service "$wantdir"/ncsid@$if_name.service
install -m 0644 ${WORKDIR}/gbmc-ncsi-sslh.service ${D}${systemd_system_unitdir}
- sed "s,@NCSI_IF@,$if_name," ${WORKDIR}/gbmc-ncsi-sslh.socket.in \
+ sed "s,@NCSI_IF@,$if_name,g" ${WORKDIR}/gbmc-ncsi-sslh.socket.in \
>${D}${systemd_system_unitdir}/gbmc-ncsi-sslh.socket
+
+ mondir=${D}${datadir}/gbmc-ip-monitor/
+ install -d -m0755 $mondir
+ sed "s,@NCSI_IF@,$if_name,g" ${WORKDIR}/gbmc-ncsi-nft.sh.in \
+ >${WORKDIR}/gbmc-ncsi-nft.sh
+ install -m644 ${WORKDIR}/gbmc-ncsi-nft.sh $mondir
+ sed "s,@NCSI_IF@,$if_name,g" ${WORKDIR}/gbmc-ncsi-br-pub-addr.sh.in \
+ >${WORKDIR}/gbmc-ncsi-br-pub-addr.sh
+ install -m644 ${WORKDIR}/gbmc-ncsi-br-pub-addr.sh $mondir
}
diff --git a/meta-google/recipes-google/networking/files/gbmc-ip-monitor.sh b/meta-google/recipes-google/networking/files/gbmc-ip-monitor.sh
index baeff9a85..e64c8675e 100755
--- a/meta-google/recipes-google/networking/files/gbmc-ip-monitor.sh
+++ b/meta-google/recipes-google/networking/files/gbmc-ip-monitor.sh
@@ -114,7 +114,7 @@ trap cleanup HUP INT QUIT ABRT TERM EXIT
return 0 2>/dev/null
while read line; do
- gbmc_ip_monitor_parse_line || continue
+ gbmc_ip_monitor_parse_line "$line" || continue
gbmc_ip_monitor_run_hooks || continue
if [ "$change" = 'init' ]; then
systemd-notify --ready
diff --git a/meta-google/recipes-google/networking/gbmc-bridge.bb b/meta-google/recipes-google/networking/gbmc-bridge.bb
new file mode 100644
index 000000000..37af84baf
--- /dev/null
+++ b/meta-google/recipes-google/networking/gbmc-bridge.bb
@@ -0,0 +1,105 @@
+SUMMARY = "Configures the gbmc bridge and filter rules"
+PR = "r1"
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://${COREBASE}/meta/files/common-licenses/Apache-2.0;md5=89aea4e17d99a7cacdbeed46a0096b10"
+
+inherit systemd
+
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+SRC_URI += " \
+ file://-bmc-gbmcbr.netdev \
+ file://-bmc-gbmcbr.network.in \
+ file://-bmc-gbmcbrdummy.netdev \
+ file://-bmc-gbmcbrdummy.network \
+ file://+-bmc-gbmcbrusb.network \
+ file://ipmi.service.in \
+ 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-gw-src.sh \
+ file://gbmc-br-nft.sh \
+ "
+
+FILES_${PN}_append = " \
+ ${datadir}/gbmc-ip-monitor \
+ ${systemd_unitdir}/network \
+ ${sysconfdir}/nftables \
+ ${sysconfdir}/avahi/services \
+ "
+
+RDEPENDS_${PN}_append = " \
+ bash \
+ gbmc-ip-monitor \
+ mstpd-mstpd \
+ network-sh \
+ ndisc6-rdisc6 \
+ "
+
+SYSTEMD_SERVICE_${PN} += "gbmc-br-ensure-ra.service"
+
+GBMC_BR_MAC_ADDR ?= ""
+
+# 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"
+
+def mac_to_eui64(mac):
+ if not mac:
+ return ''
+ b = [int(c, 16) for c in mac.split(':')]
+ b[0] ^= 2
+ b.insert(3, 0xfe)
+ b.insert(3, 0xff)
+ idx = range(0, len(b)-1, 2)
+ return ':'.join([format((b[i] << 8) + b[i+1], '04x') for i in idx])
+
+do_install() {
+ netdir=${D}${systemd_unitdir}/network
+ install -d -m0755 $netdir
+
+ if [ ! -z "${GBMC_BR_MAC_ADDR}" ]; then
+ sfx='${@mac_to_eui64(GBMC_BR_MAC_ADDR)}'
+ addr="Address=${GBMC_ULA_PREFIX}:$sfx/64\nAddress=fe80::$sfx/64"
+ sed -i "s,@ADDR@,$addr," ${WORKDIR}/-bmc-gbmcbr.network.in
+ else
+ sed -i '/@ADDR@/d' ${WORKDIR}/-bmc-gbmcbr.network.in
+ fi
+
+ install -m0644 ${WORKDIR}/-bmc-gbmcbr.netdev $netdir/
+ install -m0644 ${WORKDIR}/-bmc-gbmcbr.network.in $netdir/-bmc-gbmcbr.network
+ install -m0644 ${WORKDIR}/-bmc-gbmcbrdummy.netdev $netdir/
+ install -m0644 ${WORKDIR}/-bmc-gbmcbrdummy.network $netdir/
+ install -m0644 ${WORKDIR}/+-bmc-gbmcbrusb.network $netdir/
+
+ nftables_dir=${D}${sysconfdir}/nftables
+ install -d -m0755 "$nftables_dir"
+ install -m0644 ${WORKDIR}/50-gbmc-br.rules $nftables_dir/
+
+ avahi_dir=${D}${sysconfdir}/avahi/services
+ install -d -m 0755 "$avahi_dir"
+ sed -i 's,@MACHINE@,${MACHINE},g' ${WORKDIR}/ipmi.service.in
+ sed -i 's,@EXTRA_ATTRS@,,g' ${WORKDIR}/ipmi.service.in
+ sed 's,@NAME@,bmc,g' ${WORKDIR}/ipmi.service.in >${avahi_dir}/bmc.ipmi.service
+ sed 's,@NAME@,${MACHINE}-bmc,g' ${WORKDIR}/ipmi.service.in >${avahi_dir}/${MACHINE}-bmc.ipmi.service
+
+ mondir=${D}${datadir}/gbmc-ip-monitor
+ install -d -m0755 "$mondir"
+ install -m0644 ${WORKDIR}/gbmc-br-ula.sh "$mondir"/
+ install -m0644 ${WORKDIR}/gbmc-br-from-ra.sh "$mondir"/
+ install -m0644 ${WORKDIR}/gbmc-br-gw-src.sh "$mondir"/
+ install -m0644 ${WORKDIR}/gbmc-br-nft.sh "$mondir"/
+
+ install -d -m0755 ${D}${libexecdir}
+ install -m0755 ${WORKDIR}/gbmc-br-ensure-ra.sh ${D}${libexecdir}/
+ install -d -m0755 ${D}${systemd_system_unitdir}
+ install -m0755 ${WORKDIR}/gbmc-br-ensure-ra.service ${D}${systemd_system_unitdir}/
+}
+
+do_rm_work_prepend() {
+ # HACK: Work around broken do_rm_work not properly calling rm with `--`
+ # It doesn't like filenames that start with `-`
+ rm -rf -- ${WORKDIR}/-*
+}
diff --git a/meta-google/recipes-google/networking/gbmc-bridge/+-bmc-gbmcbrusb.network b/meta-google/recipes-google/networking/gbmc-bridge/+-bmc-gbmcbrusb.network
new file mode 100644
index 000000000..e403334b4
--- /dev/null
+++ b/meta-google/recipes-google/networking/gbmc-bridge/+-bmc-gbmcbrusb.network
@@ -0,0 +1,8 @@
+[Match]
+Name=usb*
+[Network]
+Bridge=gbmcbr
+[Bridge]
+# USB speeds tend to be better than 100mbit (100 cost) but worse
+# than 1gbit (10 cost). Generally around 200mbit.
+Cost=85
diff --git a/meta-google/recipes-google/networking/gbmc-bridge/-bmc-gbmcbr.netdev b/meta-google/recipes-google/networking/gbmc-bridge/-bmc-gbmcbr.netdev
new file mode 100644
index 000000000..d890ef9ff
--- /dev/null
+++ b/meta-google/recipes-google/networking/gbmc-bridge/-bmc-gbmcbr.netdev
@@ -0,0 +1,5 @@
+[NetDev]
+Name=gbmcbr
+Kind=bridge
+[Bridge]
+STP=true
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
new file mode 100644
index 000000000..c6097bbdb
--- /dev/null
+++ b/meta-google/recipes-google/networking/gbmc-bridge/-bmc-gbmcbr.network.in
@@ -0,0 +1,9 @@
+[Match]
+Name=gbmcbr
+[Network]
+@ADDR@
+DHCP=false
+IPv6AcceptRA=true
+LLMNR=true
+MulticastDNS=true
+LinkLocalAddressing=ipv6
diff --git a/meta-google/recipes-google/networking/gbmc-bridge/-bmc-gbmcbrdummy.netdev b/meta-google/recipes-google/networking/gbmc-bridge/-bmc-gbmcbrdummy.netdev
new file mode 100644
index 000000000..97c725812
--- /dev/null
+++ b/meta-google/recipes-google/networking/gbmc-bridge/-bmc-gbmcbrdummy.netdev
@@ -0,0 +1,3 @@
+[NetDev]
+Name=gbmcbrdummy
+Kind=dummy
diff --git a/meta-google/recipes-google/networking/gbmc-bridge/-bmc-gbmcbrdummy.network b/meta-google/recipes-google/networking/gbmc-bridge/-bmc-gbmcbrdummy.network
new file mode 100644
index 000000000..7d3f07197
--- /dev/null
+++ b/meta-google/recipes-google/networking/gbmc-bridge/-bmc-gbmcbrdummy.network
@@ -0,0 +1,4 @@
+[Match]
+Name=gbmcbrdummy
+[Network]
+Bridge=gbmcbr
diff --git a/meta-google/recipes-google/networking/gbmc-bridge/50-gbmc-br.rules b/meta-google/recipes-google/networking/gbmc-bridge/50-gbmc-br.rules
new file mode 100644
index 000000000..1a5e6331d
--- /dev/null
+++ b/meta-google/recipes-google/networking/gbmc-bridge/50-gbmc-br.rules
@@ -0,0 +1,27 @@
+table bridge filter {
+ chain gbmc_br_prerouting {
+ type filter hook prerouting priority 0;
+ iifname != gbmcbr accept
+ # Sometimes our links are over NCSI and we don't want to broadcast
+ # those packets over the entire bridge. They are only relevant P2P.
+ ether type 0x88F8 drop
+ }
+}
+
+table inet filter {
+ chain gbmc_br_input {
+ type filter hook input priority 0; policy drop;
+ iifname != gbmcbr accept
+ jump gbmc_br_int_input
+ jump gbmc_br_pub_input
+ reject
+ }
+ chain gbmc_br_int_input {
+ ip6 daddr ff00::/8 accept
+ ip6 daddr fe80::/64 accept
+ ip6 daddr fdb5:0481:10ce::/64 accept
+ }
+ chain gbmc_br_pub_input {
+ ip6 nexthdr icmpv6 accept
+ }
+}
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..18341fefb
--- /dev/null
+++ b/meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-from-ra.sh
@@ -0,0 +1,96 @@
+# 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="$(ip_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
+ if ! addr="$(ip_pfx_concat "$pfx" "$sfx")"; then
+ unset 'gbmc_br_from_ra_pfxs[$pfx]'
+ continue
+ fi
+ else
+ unset 'gbmc_br_from_ra_pfxs[$pfx]'
+ 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
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
new file mode 100644
index 000000000..cfe993f28
--- /dev/null
+++ b/meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-gw-src.sh
@@ -0,0 +1,74 @@
+# 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_gw_src_lib-}" ] || return
+
+source /usr/share/network/lib.sh || exit
+
+gbmc_br_gw_src_ip=
+declare -A gbmc_br_gw_src_routes=()
+
+gbmc_br_gw_src_update() {
+ [ -n "$gbmc_br_gw_src_ip" ] || 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
+ ip route change $route src "$gbmc_br_gw_src_ip"
+ unset 'gbmc_br_gw_src_routes[$route]'
+ done
+}
+
+gbmc_br_gw_src_hook() {
+ # We only want to match default gateway routes that are dynamic
+ # (have an expiration time). These will be updated with our preferred
+ # source.
+ if [[ "$change" == 'route' && "$route" == 'default '*':'* ]]; then
+ if [[ "$route" =~ ^(.*)( +expires +[^ ]+)(.*)$ ]]; then
+ route="${BASH_REMATCH[1]}${BASH_REMATCH[3]}"
+ fi
+ if [ "$action" = 'add' -a -z "${gbmc_br_gw_src_routes["$route"]}" ]; then
+ gbmc_br_gw_src_routes["$route"]=1
+ gbmc_br_gw_src_update
+ elif [ "$action" = 'del' -a -n "${gbmc_br_gw_src_routes["$route"]}" ]; then
+ unset 'gbmc_br_gw_src_routes[$route]'
+ gbmc_br_gw_src_update
+ 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
+ # matched as the preferred source IP for outoging traffic.
+ elif [ "$change" = 'addr' -a "$intf" = 'gbmcbr' -a "$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
+ if (( ip_bytes[8] != 0xfd || ip_bytes[9] != 0 )); then
+ return 0
+ fi
+ if [ "$action" = 'add' -a "$ip" != "$gbmc_br_gw_src_ip" ]; then
+ gbmc_br_gw_src_ip="$ip"
+ gbmc_br_gw_src_update
+ fi
+ if [ "$action" = 'del' -a "$ip" = "$gbmc_br_gw_src_ip" ]; then
+ gbmc_br_gw_src_ip=
+ fi
+ fi
+}
+
+GBMC_IP_MONITOR_HOOKS+=(gbmc_br_gw_src_hook)
+
+gbmc_br_gw_src_lib=1
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
new file mode 100644
index 000000000..19b8f64a1
--- /dev/null
+++ b/meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-nft.sh
@@ -0,0 +1,76 @@
+# 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_nft_lib-}" ] || return
+
+source /usr/share/network/lib.sh || exit
+
+gbmc_br_nft_init=
+gbmc_br_nft_pfx=
+
+gbmc_br_nft_update() {
+ printf 'gBMC Bridge input firewall for %s\n' \
+ "${gbmc_br_nft_pfx:-(deleted)}" >&2
+
+ local contents=
+ contents+='table inet filter {'$'\n'
+ contents+=' chain gbmc_br_int_input {'$'\n'
+ if [ -n "${gbmc_br_nft_pfx-}" ]; then
+ contents+=" ip6 saddr $gbmc_br_nft_pfx"
+ contents+=" ip6 daddr $gbmc_br_nft_pfx accept"$'\n'
+ fi
+ contents+=' }'$'\n'
+ contents+='}'$'\n'
+
+ local rfile=/run/nftables/40-gbmc-br-int.rules
+ mkdir -p -m 755 "$(dirname "$rfile")"
+ printf '%s' "$contents" >"$rfile"
+
+ echo 'Restarting nftables' >&2
+ systemctl reset-failed nftables
+ systemctl --no-block restart nftables
+}
+
+gbmc_br_nft_hook() {
+ if [ "$change" = 'init' ]; then
+ gbmc_br_nft_init=1
+ gbmc_br_nft_update
+ # Match only global IP addresses on the bridge that match the BMC prefix
+ # (<mpfx>:fdxx:). So 2002:af4:3480:2248:fd02:6345:3069:9186 would become
+ # a 2002:af4:3480:2248:fd00/72 rule.
+ elif [ "$change" = 'addr' -a "$intf" = 'gbmcbr' -a "$scope" = 'global' ] &&
+ [[ "$fam" == 'inet6' && "$flags" != *tentative* ]]; then
+ local ip_bytes=()
+ if ! ip_to_bytes ip_bytes "$ip"; then
+ echo "gBMC Bridge NFT Invalid IP: $ip" >&2
+ return 1
+ fi
+ if (( ip_bytes[8] != 0xfd )); then
+ return 0
+ fi
+ local i
+ for (( i=9; i<16; i++ )); do
+ ip_bytes[$i]=0
+ done
+ pfx="$(ip_bytes_to_str ip_bytes)/72"
+ if [ "$action" = "add" -a "$pfx" != "$gbmc_br_nft_pfx" ]; then
+ gbmc_br_nft_pfx="$pfx"
+ gbmc_br_nft_update
+ fi
+ fi
+}
+
+GBMC_IP_MONITOR_HOOKS+=(gbmc_br_nft_hook)
+
+gbmc_br_nft_lib=1
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
new file mode 100644
index 000000000..8e28d3956
--- /dev/null
+++ b/meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-ula.sh
@@ -0,0 +1,71 @@
+# 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_ula_lib-}" ] || return
+
+source /usr/share/network/lib.sh || exit
+
+gbmc_br_ula_init=
+gbmc_br_ula_mac=
+
+gbmc_br_ula_update() {
+ [ -n "$gbmc_br_ula_init" ] || return
+
+ 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'
+ fi
+ fi
+
+ local netfile
+ for netfile in /run/systemd/network/{00,}-bmc-gbmcbr.network.d/60-ula.conf; do
+ mkdir -p -m 755 "$(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
+
+ if [ "$(systemctl is-active systemd-networkd)" != 'inactive' ]; then
+ networkctl reload
+ networkctl reconfigure gbmcbr
+ fi
+}
+
+gbmc_br_ula_hook() {
+ if [ "$change" = 'init' ]; then
+ gbmc_br_ula_init=1
+ gbmc_br_ula_update
+ elif [ "$change" = 'link' -a "$intf" = 'gbmcbr' ]; then
+ if [ "$action" = 'add' -a "$mac" != "$gbmc_br_ula_mac" ]; then
+ gbmc_br_ula_mac="$mac"
+ gbmc_br_ula_update
+ fi
+ if [ "$action" = 'del' -a "$mac" = "$gbmc_br_ula_mac" ]; then
+ gbmc_br_ula_mac=
+ gbmc_br_ula_update
+ fi
+ fi
+}
+
+GBMC_IP_MONITOR_HOOKS+=(gbmc_br_ula_hook)
+
+gbmc_br_ula_lib=1
diff --git a/meta-google/recipes-google/networking/gbmc-bridge/ipmi.service.in b/meta-google/recipes-google/networking/gbmc-bridge/ipmi.service.in
new file mode 100644
index 000000000..0b940fa2d
--- /dev/null
+++ b/meta-google/recipes-google/networking/gbmc-bridge/ipmi.service.in
@@ -0,0 +1,11 @@
+<?xml version="1.0" ?>
+<!DOCTYPE service-group SYSTEM "avahi-service.dtd">
+<service-group>
+ <name>@NAME@</name>
+ <service>
+ <type>_ipmi._udp</type>
+ <port>623</port>
+ <txt-record>Machine=@MACHINE@</txt-record>
+ @EXTRA_ATTRS@
+ </service>
+</service-group>
diff --git a/meta-google/recipes-google/networking/gbmc-iperf3.bb b/meta-google/recipes-google/networking/gbmc-iperf3.bb
index 5044e418b..27ebdb7e0 100644
--- a/meta-google/recipes-google/networking/gbmc-iperf3.bb
+++ b/meta-google/recipes-google/networking/gbmc-iperf3.bb
@@ -17,13 +17,13 @@ do_install() {
install -m 0644 ${WORKDIR}/iperf3.service ${D}${systemd_system_unitdir}
}
-# Allow IPERF3 to the mgmt node on DEV builds
+# Allow IPERF3 to run on the gbmcbr node on DEV builds
do_install_append_dev() {
nftables_dir=${D}${sysconfdir}/nftables
rules=$nftables_dir/50-gbmc-iperf3-dev.rules
install -d -m0755 $nftables_dir
echo 'table inet filter {' >"$rules"
- echo ' chain mgmt_pub_input {' >>"$rules"
+ echo ' chain gbmc_br_pub_input {' >>"$rules"
echo ' tcp dport 5201 accept' >>"$rules"
echo ' }' >>"$rules"
echo '}' >>"$rules"
diff --git a/meta-google/recipes-google/networking/network-sh/lib.sh b/meta-google/recipes-google/networking/network-sh/lib.sh
index f37f7196d..b5d9382fc 100644
--- a/meta-google/recipes-google/networking/network-sh/lib.sh
+++ b/meta-google/recipes-google/networking/network-sh/lib.sh
@@ -33,11 +33,11 @@ mac_to_bytes() {
}
mac_to_eui48() {
- local mac_bytes=()
+ local mac_bytes=(0 0 0 0 0 0 0 0 0 0)
mac_to_bytes mac_bytes "$1" || return
# Return the EUI-64 bytes in the IPv6 format
- printf '%02x%02x:%02x%02x:%02x%02x\n' "${mac_bytes[@]}"
+ ip_bytes_to_str mac_bytes
}
mac_to_eui64() {
@@ -47,6 +47,7 @@ mac_to_eui64() {
# Using EUI-64 conversion rules, create the suffix bytes from MAC bytes
# Invert bit-0 of the first byte, and insert 0xfffe in the middle.
local suffix_bytes=(
+ 0 0 0 0 0 0 0 0
$((mac_bytes[0] ^ 1))
${mac_bytes[@]:1:2}
$((0xff)) $((0xfe))
@@ -54,52 +55,239 @@ mac_to_eui64() {
)
# Return the EUI-64 bytes in the IPv6 format
- printf '%02x%02x:%02x%02x:%02x%02x:%02x%02x\n' "${suffix_bytes[@]}"
+ ip_bytes_to_str suffix_bytes
+}
+
+ip_to_bytes() {
+ local -n bytes_out="$1"
+ local str="$2"
+
+ local bytes=()
+ local oldifs="$IFS"
+ # Heuristic for V4 / V6, validity will be checked as it is parsed
+ if [[ "$str" == *.* ]]; then
+ # Ensure we don't start or end with IFS
+ [ "${str:0:1}" != '.' ] || return 1
+ [ "${str: -1}" != '.' ] || return 1
+
+ local v
+ # Split IPv4 address into octets
+ IFS=.
+ for v in $str; do
+ # IPv4 digits are always decimal numbers
+ if ! [[ "$v" =~ ^[0-9]+$ ]]; then
+ IFS="$oldifs"
+ return 1
+ fi
+ # Each octet is a single byte, make sure the number isn't larger
+ if (( v > 0xff )); then
+ IFS="$oldifs"
+ return 1
+ fi
+ bytes+=($v)
+ done
+ # IPv4 addresses must have all 4 bytes present
+ if (( "${#bytes[@]}" != 4 )); then
+ IFS="$oldifs"
+ return 1
+ fi
+ else
+ # Ensure we bound the padding in an outer byte for
+ # IFS splitting to work correctly
+ [ "${str:0:2}" = '::' ] && str="0$str"
+ [ "${str: -2}" = '::' ] && str="${str}0"
+
+ # Ensure we don't start or end with IFS
+ [ "${str:0:1}" != ':' ] || return 1
+ [ "${str: -1}" != ':' ] || return 1
+
+ # Stores the bytes that come before ::, if it exists
+ local bytesBeforePad=()
+ local v
+ # Split the Address into hextets
+ IFS=:
+ for v in $str; do
+ # Handle ::, which translates to an empty string
+ if [ -z "$v" ]; then
+ # Only allow a single :: sequence in an address
+ if (( "${#bytesBeforePad[@]}" > 0 )); then
+ IFS="$oldifs"
+ return 1
+ fi
+ # Store the already parsed upper bytes separately
+ # This allows us to calculate and insert padding
+ bytesBeforePad=("${bytes[@]}")
+ bytes=()
+ continue
+ fi
+ # IPv6 digits are always hex
+ if ! [[ "$v" =~ ^[[:xdigit:]]+$ ]]; then
+ IFS="$oldifs"
+ return 1
+ fi
+ # Ensure the number is no larger than a hextet
+ v="0x$v"
+ if (( v > 0xffff )); then
+ IFS="$oldifs"
+ return 1
+ fi
+ # Split the hextet into 2 bytes
+ bytes+=($(( v >> 8 )))
+ bytes+=($(( v & 0xff )))
+ done
+ # If we have ::, add padding
+ if (( "${#bytesBeforePad[@]}" > 0 )); then
+ # Fill the middle bytes with padding and store in `bytes`
+ while (( "${#bytes[@]}" + "${#bytesBeforePad[@]}" < 16 )); do
+ bytesBeforePad+=(0)
+ done
+ bytes=("${bytesBeforePad[@]}" "${bytes[@]}")
+ fi
+ # IPv6 addresses must have all 16 bytes present
+ if (( "${#bytes[@]}" != 16 )); then
+ IFS="$oldifs"
+ return 1
+ fi
+ fi
+
+ IFS="$oldifs"
+ bytes_out=("${bytes[@]}")
}
-ipv6_pfx_concat() {
+ip_bytes_to_str() {
+ local -n bytes="$1"
+
+ if (( "${#bytes[@]}" == 4 )); then
+ printf '%d.%d.%d.%d\n' "${bytes[@]}"
+ elif (( "${#bytes[@]}" == 16 )); then
+ # Track the starting position of the longest run of 0 hextets (2 bytes)
+ local longest_i=0
+ # Track the size of the longest run of 0 hextets
+ local longest_s=0
+ # The index of the first 0 byte in the current run of zeros
+ local first_zero=0
+ local i
+ # Find the location of the longest run of zero hextets, preferring same
+ # size runs later in the address.
+ for (( i=0; i<=16; i+=2 )); do
+ # Terminate the run of zeros if we are at the end of the array or
+ # have a non-zero hextet
+ if (( i == 16 || bytes[$i] != 0 || bytes[$((i+1))] != 0 )); then
+ local s=$((i - first_zero))
+ if (( s >= longest_s )); then
+ longest_i=$first_zero
+ longest_s=$s
+ fi
+ first_zero=$((i+2))
+ fi
+ done
+ # Build the address string by each hextet
+ for (( i=0; i<16; i+=2 )); do
+ # If we encountered a run of zeros, add the necessary :: at the end
+ # of the string. If not at the end, a single : is added since : is
+ # printed to subsequent hextets already.
+ if (( i == longest_i )); then
+ (( i += longest_s-2 ))
+ printf ':'
+ # End of string needs to be ::
+ if (( i == 14 )); then
+ printf ':'
+ fi
+ else
+ # Prepend : to all hextets except the first for separation
+ if (( i != 0 )); then
+ printf ':'
+ fi
+ printf '%x' $(( (bytes[$i]<<8) | bytes[$(($i+1))]))
+ fi
+ done
+ printf '\n'
+ else
+ echo "Invalid IP Bytes: ${bytes[*]}" >&2
+ return 1
+ fi
+}
+
+ip_pfx_concat() {
local pfx="$1"
local sfx="$2"
- # Validate the prefix
- if ! [[ "$pfx" =~ ^(([0-9a-fA-F]{1,4}:)+):/([0-9]+)$ ]]; then
- echo "Invalid IPv6 prefix: $pfx" >&2
+ # Parse the prefix
+ if ! [[ "$pfx" =~ ^([0-9a-fA-F:.]+)/([0-9]+)$ ]]; then
+ echo "Invalid IP prefix: $pfx" >&2
return 1
fi
local addr="${BASH_REMATCH[1]}"
- local cidr="${BASH_REMATCH[3]}"
+ local cidr="${BASH_REMATCH[2]}"
+
# Ensure prefix doesn't have too many bytes
- local nos="${addr//:/}"
- if (( ${#addr} - ${#nos} > (cidr+7)/16 )); then
- echo "Too many prefix bytes: $pfx" >&2
+ local pfx_bytes=()
+ if ! ip_to_bytes pfx_bytes "$addr"; then
+ echo "Invalid IP prefix: $pfx" >&2
+ return 1
+ fi
+ if (( ${#pfx_bytes[@]}*8 < cidr )); then
+ echo "Prefix CIDR too large" >&2
+ return 1
+ fi
+ # CIDR values might partially divide a byte so we need to mask out
+ # only the part of the byte we want to check for emptiness
+ if (( (pfx_bytes[cidr/8] & ~(~0 << (8-cidr%8))) != 0 )); then
+ echo "Invalid byte $((cidr/8)): $pfx" >&2
return 1
fi
+ local i
+ # Check the rest of the whole bytes to make sure they are empty
+ for (( i=cidr/8+1; i<${#pfx_bytes[@]}; i++ )); do
+ if (( pfx_bytes[$i] != 0 )); then
+ echo "Byte $i not 0: $pfx" >&2
+ return 1
+ fi
+ done
# Validate the suffix
- if ! [[ "$sfx" =~ ^[0-9a-fA-F]{1,4}(:[0-9a-fA-F]{1,4})*$ ]]; then
+ local sfx_bytes=()
+ if ! ip_to_bytes sfx_bytes "$sfx"; then
echo "Invalid IPv6 suffix: $sfx" >&2
return 1
fi
- # Ensure suffix doesn't have too many bytes
- local nos="${sfx//:/}"
- if (( ${#sfx} - ${#nos} >= (128-cidr)/16 )); then
- echo "Too many suffix bytes: $sfx" >&2
+ if (( "${#sfx_bytes[@]}" != "${#pfx_bytes[@]}" )); then
+ echo "Suffix not the same family as prefix: $pfx $sfx" >&2
return 1
fi
-
- local comb="$addr:$sfx"
- local nos="${comb//:/}"
- if (( ${#comb} - ${#nos} == 8 )); then
- comb="$addr$sfx"
+ # Check potential partially divided bytes for emptiness in the upper part
+ # based on the division specified in CIDR.
+ if (( (sfx_bytes[cidr/8] & (~0 << (8-cidr%8))) != 0 )); then
+ echo "Invalid byte $((cidr/8)): $sfx" >&2
+ return 1
fi
- echo "$comb/$cidr"
+ local i
+ # Check the bytes before the CIDR for emptiness to ensure they don't overlap
+ for (( i=0; i<cidr/8; i++ )); do
+ if (( sfx_bytes[$i] != 0 )); then
+ echo "Byte $i not 0: $sfx" >&2
+ return 1
+ fi
+ done
+
+ out_bytes=()
+ for (( i=0; i<${#pfx_bytes[@]}; i++ )); do
+ out_bytes+=($(( pfx_bytes[$i] | sfx_bytes[$i] )))
+ done
+ echo "$(ip_bytes_to_str out_bytes)/$cidr"
}
-ipv6_pfx_to_cidr() {
- [[ "$1" =~ ^[0-9a-fA-F:]+/([0-9]+)$ ]] || return
+ip_pfx_to_cidr() {
+ [[ "$1" =~ ^[0-9a-fA-F:.]+/([0-9]+)$ ]] || return
echo "${BASH_REMATCH[1]}"
}
+normalize_ip() {
+ local ip_bytes=()
+ ip_to_bytes ip_bytes "$1" || return
+ ip_bytes_to_str ip_bytes
+}
+
network_init=1
return 0 2>/dev/null
echo "network is a library, not executed directly" >&2
diff --git a/meta-google/recipes-google/networking/network-sh/test.sh b/meta-google/recipes-google/networking/network-sh/test.sh
index 57387c47c..2803c0978 100755
--- a/meta-google/recipes-google/networking/network-sh/test.sh
+++ b/meta-google/recipes-google/networking/network-sh/test.sh
@@ -21,6 +21,21 @@ else
fi
source lib.sh
+expect_array_numeq() {
+ local -n a1="$1"
+ local -n a2="$2"
+
+ if (( "${#a1[@]}" != "${#a2[@]}" )); then
+ echo " Line ${BASH_LINENO[0]} Array Size ${#a1[@]} != ${#a2[@]}" >&2
+ test_err=1
+ else
+ local i
+ for (( i=0; i < ${#a1[@]}; ++i )); do
+ expect_numeq "${a1[$i]}" "${a2[$i]}"
+ done
+ fi
+}
+
test_mac_to_bytes() {
out=()
expect_err 1 mac_to_bytes out ''
@@ -32,52 +47,154 @@ test_mac_to_bytes() {
expect_err 0 mac_to_bytes out 'a2:0:f:de:0:29'
expected=(0xa2 0 0xf 0xde 0 0x29)
- for (( i=0; i < ${#expected[@]}; ++i )); do
- expect_numeq "${out[$i]}" "${expected[$i]}"
- done
+ expect_array_numeq out expected
}
-test_mac_to_eui_48() {
+test_mac_to_eui48() {
str="$(mac_to_eui48 '12:34:56:78:90:af')" || fail
- expect_streq "$str" '1234:5678:90af'
+ expect_streq "$str" '::1234:5678:90af'
}
-test_eui_64() {
+test_mac_to_eui64() {
str="$(mac_to_eui64 '12:34:56:78:90:af')" || fail
- expect_streq "$str" '1334:56ff:fe78:90af'
+ expect_streq "$str" '::1334:56ff:fe78:90af'
+}
+
+test_ip4_to_bytes() {
+ out=()
+ expect_err 1 ip_to_bytes out ''
+ expect_err 1 ip_to_bytes out '10.0.0.'
+ expect_err 1 ip_to_bytes out '.0.1.1'
+ expect_err 1 ip_to_bytes out '10.0.0'
+ expect_err 1 ip_to_bytes out '10.0..0'
+ expect_err 1 ip_to_bytes out '.10.0.0.0'
+ expect_err 1 ip_to_bytes out '10.0.0.0.'
+ expect_err 1 ip_to_bytes out '10.0.0.256'
+ expect_err 1 ip_to_bytes out '10.0.0.0.256'
+ expect_err 1 ip_to_bytes out '10.0.0.0.1'
+
+ expect_err 0 ip_to_bytes out '10.0.0.1'
+ expected=(10 0 0 1)
+ expect_array_numeq out expected
}
-test_ipv6_pfx_concat() {
+test_ip6_to_bytes() {
+ out=()
+ expect_err 1 ip_to_bytes out ''
+ expect_err 1 ip_to_bytes out ':::'
+ expect_err 1 ip_to_bytes out '::z'
+ expect_err 1 ip_to_bytes out '1::1::1'
+ expect_err 1 ip_to_bytes out '1:1:1'
+ expect_err 1 ip_to_bytes out ':1::1'
+ expect_err 1 ip_to_bytes out '1::1:'
+
+ expect_err 0 ip_to_bytes out '::'
+ expected=(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)
+ expect_array_numeq out expected
+ out=()
+
+ expect_err 0 ip_to_bytes out '::1'
+ expected=(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1)
+ expect_array_numeq out expected
+ out=()
+
+ expect_err 0 ip_to_bytes out 'fd00::'
+ expected=(0xfd 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)
+ expect_array_numeq out expected
+ out=()
+
+ expect_err 0 ip_to_bytes out 'fd00:ffee::ddff:22'
+ expected=(0xfd 0 0xff 0xee 0 0 0 0 0 0 0 0 0xdd 0xff 0 0x22)
+ expect_array_numeq out expected
+ out=()
+
+ expect_err 0 ip_to_bytes out '1:2:3:4:5:6:7:8'
+ expected=(0 1 0 2 0 3 0 4 0 5 0 6 0 7 0 8)
+ expect_array_numeq out expected
+ out=()
+}
+
+test_ip4_bytes_str() {
+ in=(10 0 255 1)
+ str="$(ip_bytes_to_str in)" || fail
+ expect_streq "$str" '10.0.255.1'
+}
+
+test_ip6_bytes_str() {
+ in=(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)
+ str="$(ip_bytes_to_str in)" || fail
+ expect_streq "$str" '::'
+ in=(0xfd 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)
+ str="$(ip_bytes_to_str in)" || fail
+ expect_streq "$str" 'fd00::'
+ in=(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0xfd)
+ str="$(ip_bytes_to_str in)" || fail
+ expect_streq "$str" '::fd'
+ in=(0xfd 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1)
+ str="$(ip_bytes_to_str in)" || fail
+ expect_streq "$str" 'fd01::1'
+ in=(0xfd 1 0 0 0 0 0 0 0 1 0 0 0 0 0 1)
+ str="$(ip_bytes_to_str in)" || fail
+ expect_streq "$str" 'fd01::1:0:0:1'
+ in=(0xfd 1 0 0 0 0 0 1 0 1 0 0 0 0 0 1)
+ str="$(ip_bytes_to_str in)" || fail
+ expect_streq "$str" 'fd01:0:0:1:1::1'
+ in=(0 1 0 1 0xdd 0xdd 0 1 0 1 0 1 0 1 0 1)
+ str="$(ip_bytes_to_str in)" || fail
+ expect_streq "$str" '1:1:dddd:1:1:1:1:1'
+}
+
+test_ip_pfx_concat() {
# Invalid inputs
- expect_err 1 ipv6_pfx_concat 'fd/64' '1234:5678:90af'
- expect_err 1 ipv6_pfx_concat 'fd01::' '1234:5678:90af'
- expect_err 1 ipv6_pfx_concat 'fd01:' '1234:5678:90af'
- expect_err 1 ipv6_pfx_concat 'fd01::/a0' '1234:5678:90af'
- expect_err 1 ipv6_pfx_concat 'fd01::/64' ':1234:5678:90af'
- expect_err 1 ipv6_pfx_concat 'fd01::/64' '::'
+ expect_err 1 ip_pfx_concat 'fd/64' '::1234:5678:90af'
+ expect_err 1 ip_pfx_concat 'fd01::' '::1234:5678:90af'
+ expect_err 1 ip_pfx_concat 'fd01:' '::1234:5678:90af'
+ expect_err 1 ip_pfx_concat 'fd01::/a0' '::1234:5678:90af'
+ expect_err 1 ip_pfx_concat 'fd01::/64' ':1234:5678:90af'
+ expect_err 1 ip_pfx_concat 'fd01::/64' ''
+ expect_err 1 ip_pfx_concat 'fd01::/129' '::1'
# Too many address bits
- expect_err 1 ipv6_pfx_concat 'fd01:1:1:1:1::/64' '1234:5678:90af'
- expect_err 1 ipv6_pfx_concat 'fd01::/64' '1:0:1234:5678:90af'
- expect_err 1 ipv6_pfx_concat 'fd01::/65' '1:1234:5678:90af'
- expect_err 1 ipv6_pfx_concat 'fd01::/72' '1:1234:5678:90af'
+ expect_err 1 ip_pfx_concat 'fd01:1:1:1:1::/64' '::1234:5678:90af'
+ expect_err 1 ip_pfx_concat 'fd01::/64' '::1:0:1234:5678:90af'
+ expect_err 1 ip_pfx_concat 'fd01::/79' '::3:1234:5678:90af'
+ expect_err 1 ip_pfx_concat 'fd01::/15' '::3:1234:5678:90af'
+ expect_err 1 ip_pfx_concat '10.0.0.1/31' '0.0.0.0'
- str="$(ipv6_pfx_concat 'fd01::/64' '1')" || fail
+ str="$(ip_pfx_concat '::1/128' '::0')" || fail
+ expect_streq "$str" '::1/128'
+ str="$(ip_pfx_concat 'fd01::/64' '::1')" || fail
expect_streq "$str" 'fd01::1/64'
- str="$(ipv6_pfx_concat 'fd01::/72' '1234:5678:90af')" || fail
+ str="$(ip_pfx_concat 'fd01::/127' '::1')" || fail
+ expect_streq "$str" 'fd01::1/127'
+ str="$(ip_pfx_concat 'fd02::/15' '::1')" || fail
+ expect_streq "$str" 'fd02::1/15'
+ str="$(ip_pfx_concat 'fd01::/72' '::1234:5678:90af')" || fail
expect_streq "$str" 'fd01::1234:5678:90af/72'
- str="$(ipv6_pfx_concat 'fd01:eeee:aaaa:cccc::/64' 'a:1234:5678:90af')" || fail
+ str="$(ip_pfx_concat 'fd01:eeee:aaaa:cccc::/64' '::a:1234:5678:90af')" || fail
expect_streq "$str" 'fd01:eeee:aaaa:cccc:a:1234:5678:90af/64'
+ str="$(ip_pfx_concat 'fd01::fd00:0:0:0/80' '::1')" || fail
+ expect_streq "$str" 'fd01::fd00:0:0:1/80'
+
+ str="$(ip_pfx_concat '10.0.0.0/24' '0.0.0.1')" || fail
+ expect_streq "$str" '10.0.0.1/24'
}
-test_ipv6_pfx_to_cidr() {
- expect_err 1 ipv6_pfx_to_cidr 'z/64'
- expect_err 1 ipv6_pfx_to_cidr '64'
+test_ip_pfx_to_cidr() {
+ expect_err 1 ip_pfx_to_cidr 'z/64'
+ expect_err 1 ip_pfx_to_cidr '64'
- cidr="$(ipv6_pfx_to_cidr 'fd01::/64')" || fail
+ cidr="$(ip_pfx_to_cidr 'fd01::/64')" || fail
expect_numeq "$cidr" 64
- cidr="$(ipv6_pfx_to_cidr 'fd01:eeee:aaaa:cccc:a:1234:5678:90af/128')" || fail
+ cidr="$(ip_pfx_to_cidr 'fd01:eeee:aaaa:cccc:a:1234:5678:90af/128')" || fail
expect_numeq "$cidr" 128
+ cidr="$(ip_pfx_to_cidr '10.0.0.1/24')" || fail
+ expect_numeq "$cidr" 24
+}
+
+test_normalize_ip() {
+ ip="$(normalize_ip 'fd01:1::0:0:1')" || fail
+ expect_streq "$ip" 'fd01:1::1'
}
return 0 2>/dev/null
diff --git a/meta-google/recipes-google/systemd/files/40-gbmc-forward.conf b/meta-google/recipes-google/systemd/files/40-gbmc-forward.conf
new file mode 100644
index 000000000..9f8d1eb50
--- /dev/null
+++ b/meta-google/recipes-google/systemd/files/40-gbmc-forward.conf
@@ -0,0 +1,5 @@
+net.ipv4.ip_forward=1
+net.ipv4.conf.default.forwarding=1
+net.ipv4.conf.all.forwarding=1
+net.ipv6.conf.default.forwarding=1
+net.ipv6.conf.all.forwarding=1
diff --git a/meta-google/recipes-google/systemd/gbmc-systemd-config.bb b/meta-google/recipes-google/systemd/gbmc-systemd-config.bb
index 011b62edc..29d81f46a 100644
--- a/meta-google/recipes-google/systemd/gbmc-systemd-config.bb
+++ b/meta-google/recipes-google/systemd/gbmc-systemd-config.bb
@@ -10,11 +10,13 @@ S = "${WORKDIR}"
SRC_URI_append = " \
file://firmware-updates.target \
file://firmware-updates-pre.target \
+ file://40-gbmc-forward.conf \
"
FILES_${PN}_append = " \
${systemd_unitdir}/coredump.conf.d/40-gbmc-coredump.conf \
${systemd_unitdir}/resolved.conf.d/40-gbmc-nomdns.conf \
+ ${libdir}/sysctl.d/40-gbmc-forward.conf \
"
FILES_${PN}_append_dev = " \
@@ -28,22 +30,23 @@ SYSTEMD_SERVICE_${PN}_append = " \
# Put coredumps in the journal to ensure they stay in ram
do_install() {
- install -d -m 0755 ${D}${systemd_unitdir}/coredump.conf.d
- printf "[Coredump]\nStorage=journal\n" \
- >${D}${systemd_unitdir}/coredump.conf.d/40-gbmc-coredump.conf
+ install -d -m 0755 ${D}${systemd_unitdir}/coredump.conf.d
+ printf "[Coredump]\nStorage=journal\n" \
+ >${D}${systemd_unitdir}/coredump.conf.d/40-gbmc-coredump.conf
- install -d -m 0755 ${D}${systemd_unitdir}/resolved.conf.d
- printf "[Resolve]\nLLMNR=no\nMulticastDNS=resolve\n" \
- >${D}${systemd_unitdir}/resolved.conf.d/40-gbmc-nomdns.conf
+ install -d -m 0755 ${D}${systemd_unitdir}/resolved.conf.d
+ printf "[Resolve]\nLLMNR=no\nMulticastDNS=resolve\n" \
+ >${D}${systemd_unitdir}/resolved.conf.d/40-gbmc-nomdns.conf
- install -d -m 0755 ${D}${systemd_system_unitdir}
- install -m 0644 ${WORKDIR}/firmware-updates.target ${D}${systemd_system_unitdir}/
- install -m 0644 ${WORKDIR}/firmware-updates-pre.target ${D}${systemd_system_unitdir}/
+ install -d -m 0755 ${D}${systemd_system_unitdir}
+ install -m 0644 ${WORKDIR}/firmware-updates.target ${D}${systemd_system_unitdir}/
+ install -m 0644 ${WORKDIR}/firmware-updates-pre.target ${D}${systemd_system_unitdir}/
+
+ install -d -m0755 ${D}${libdir}/sysctl.d
+ install -m 0644 ${WORKDIR}/40-gbmc-forward.conf ${D}${libdir}/sysctl.d/
}
do_install_append_dev() {
- install -d -m 0755 ${D}${libdir}/sysctl.d
- printf "kernel.sysrq = 1\n" \
- >${D}${libdir}/sysctl.d/40-gbmc-debug.conf
-
+ printf "kernel.sysrq = 1\n" \
+ >${D}${libdir}/sysctl.d/40-gbmc-debug.conf
}