meta-google: gbmc-bridge: Add package

This adds a machine local ethernet network which allows BMCs to
communicate with one another.

Change-Id: I5e0ace231af02d84f7678b8241b5ec71823e86af
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/meta-google/recipes-connectivity/avahi/files/avahi-daemon.conf b/meta-google/recipes-connectivity/avahi/files/avahi-daemon.conf
index 9688ffb..57520df 100644
--- a/meta-google/recipes-connectivity/avahi/files/avahi-daemon.conf
+++ b/meta-google/recipes-connectivity/avahi/files/avahi-daemon.conf
@@ -1,5 +1,5 @@
 [server]
-allow-interfaces=mgmt
+allow-interfaces=mgmt,gbmcbr
 
 [publish]
 disable-user-service-publishing=yes
diff --git a/meta-google/recipes-core/dropbear/dropbear_%.bbappend b/meta-google/recipes-core/dropbear/dropbear_%.bbappend
index e93eba8..0b4349e 100644
--- a/meta-google/recipes-core/dropbear/dropbear_%.bbappend
+++ b/meta-google/recipes-core/dropbear/dropbear_%.bbappend
@@ -5,13 +5,13 @@
 FILESEXTRAPATHS_remove_gbmc_bandaid := "${THISDIR}/${PN}:"
 SYSTEMD_AUTO_ENABLE_${PN}_bandaid_prod = "enable"
 
-# Allow SSH to the mgmt node on DEV builds
+# Allow SSH to the gbmc-bridge node on DEV builds
 do_install_append_gbmc_dev() {
   nftables_dir=${D}${sysconfdir}/nftables
   rules=$nftables_dir/50-dropbear-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 22 accept' >>"$rules"
   echo '    }' >>"$rules"
   echo '}' >>"$rules"
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 0000000..1358ac5
--- /dev/null
+++ b/meta-google/recipes-google/networking/gbmc-bridge.bb
@@ -0,0 +1,75 @@
+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.in \
+  file://-bmc-gbmcbr.network \
+  file://-bmc-gbmcbrdummy.netdev \
+  file://-bmc-gbmcbrdummy.network \
+  file://+-bmc-gbmcbrusb.network \
+  file://ipmi.service.in \
+  file://50-gbmc-br.rules \
+  "
+
+FILES_${PN}_append = " \
+  ${systemd_unitdir}/network \
+  ${sysconfdir}/nftables \
+  ${sysconfdir}/avahi/services \
+  "
+
+RDEPENDS_${PN}_append = " \
+  mstpd-mstpd \
+  "
+
+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
+    sed -i 's,@MAC@,MACAddress=${GBMC_BR_MAC_ADDR},' ${WORKDIR}/-bmc-gbmcbr.netdev.in
+	addr=${GBMC_ULA_PREFIX}:${@mac_to_eui64(GBMC_BR_MAC_ADDR)}/64
+    sed -i "s,@ADDR@,Address=$addr," ${WORKDIR}/-bmc-gbmcbr.netdev.in
+  else
+    sed -i '/@MAC@/d' ${WORKDIR}/-bmc-gbmcbr.netdev.in
+    sed -i '/@ADDR@/d' ${WORKDIR}/-bmc-gbmcbr.netdev.in
+  fi
+
+  install -m0644 ${WORKDIR}/-bmc-gbmcbr.netdev.in $netdir/-bmc-gbmcbr.netdev
+  install -m0644 ${WORKDIR}/-bmc-gbmcbr.network $netdir/
+  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
+}
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 0000000..e403334
--- /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.in b/meta-google/recipes-google/networking/gbmc-bridge/-bmc-gbmcbr.netdev.in
new file mode 100644
index 0000000..a7e9133
--- /dev/null
+++ b/meta-google/recipes-google/networking/gbmc-bridge/-bmc-gbmcbr.netdev.in
@@ -0,0 +1,7 @@
+[NetDev]
+Name=gbmcbr
+Kind=bridge
+@MAC@
+@ADDR@
+[Bridge]
+STP=true
diff --git a/meta-google/recipes-google/networking/gbmc-bridge/-bmc-gbmcbr.network b/meta-google/recipes-google/networking/gbmc-bridge/-bmc-gbmcbr.network
new file mode 100644
index 0000000..18d208a
--- /dev/null
+++ b/meta-google/recipes-google/networking/gbmc-bridge/-bmc-gbmcbr.network
@@ -0,0 +1,8 @@
+[Match]
+Name=gbmcbr
+[Network]
+DHCP=false
+IPv6AcceptRA=false
+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 0000000..97c7258
--- /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 0000000..7d3f071
--- /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 0000000..1a5e633
--- /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/ipmi.service.in b/meta-google/recipes-google/networking/gbmc-bridge/ipmi.service.in
new file mode 100644
index 0000000..0b940fa
--- /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 5044e41..27ebdb7 100644
--- a/meta-google/recipes-google/networking/gbmc-iperf3.bb
+++ b/meta-google/recipes-google/networking/gbmc-iperf3.bb
@@ -17,13 +17,13 @@
   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"