package main import ( "fmt" "log" "net/netip" "os" "git.redxen.eu/nnd/s6-netdev" ) func main() { var ( err error l = log.New(os.Stderr, "s6-netdev: ", log.Ltime|log.Lshortfile|log.Lmsgprefix) ifs = make(s6netdev.IfMap) ) t := s6netdev.S6NewTree() // Loopback ifs.AddIf(&s6netdev.Iface{ Name: "lo", Type: &s6netdev.NetdevIfTypes.Loopback, }) // VRFs ifs.AddIf(&s6netdev.Iface{ Name: "vrf-phys", Type: &s6netdev.NetdevIfTypes.Vrf, Table: 10, }) ifs.AddIf(&s6netdev.Iface{ Name: "vrf-b00b", Type: &s6netdev.NetdevIfTypes.Vrf, Table: 20, }) // Bonds ifs.AddIf(&s6netdev.Iface{ Name: "bond10", Type: &s6netdev.NetdevIfTypes.Bond, }) // Physical interfaces for _, v := range []string{"p129s0f0", "p129s0f1", "p131s0f0", "p131s0f1", "p131s0f2", "p131s0f3"} { ifs.AddIf(&s6netdev.Iface{ Name: fmt.Sprintf("en%s", v), Type: &s6netdev.NetdevIfTypes.Phys, }) } // VLAN Interfaces ifs.AddIf(&s6netdev.Iface{ Name: fmt.Sprintf("phys.%d", 66), Type: &s6netdev.NetdevIfTypes.Vlan, VlanId: s6netdev.VLAN(66), Addresses: []netip.Prefix{ netip.MustParsePrefix("2a04:5b81:2060:b00b:921b:eff:fe53:8b67/64"), }, Routes: []s6netdev.Route{ { Net: netip.MustParsePrefix("2a04:5b81:2060:b00b::/64"), Via: netip.MustParseAddr("fe80::ff:fe00:b00b"), Metric: 128, }, }, // Disable autoconf, we statically assign it to have it early Sysctls: s6netdev.Sysctl_IP{ V6: []s6netdev.Property{ {Key: "autoconf", Value: "0", Default: "1"}, }, }, }) // Wireguard interfaces ifs.AddIf(&s6netdev.Iface{ Name: "wg-tunnel", Type: &s6netdev.NetdevIfTypes.Wireguard, Addresses: []netip.Prefix{ netip.MustParsePrefix("172.22.12.7/32"), netip.MustParsePrefix("fd42:42:42::2:7/128"), }, Routes: []s6netdev.Route{ {Net: netip.MustParsePrefix("172.22.12.0/24")}, {Net: netip.MustParsePrefix("fd42:42:42::2:0/120")}, }, }) // Bridge interfaces ifs.AddIf(&s6netdev.Iface{ Name: "phys", Type: &s6netdev.NetdevIfTypes.Bridge, Properties: []s6netdev.Property{ {Key: "priority", Value: "16384", Default: "32768"}, {Key: "stp_state", Value: "1", Default: "0"}, {Key: "mcast_snooping", Value: "0", Default: "1"}, }, Sysctls: s6netdev.Sysctl_IP{ V6: []s6netdev.Property{ {Key: "forwarding", Value: "0", Default: "0"}, {Key: "accept_ra", Value: "0", Default: "1"}, }, }, }) // Currently there exists no mechanism to depend routes on the addresses, these are manual deps phys_addr_v4 := t.NetdevIfaceAddr(*ifs["phys"], netip.MustParsePrefix("10.24.0.11/24")) phys_defrt_v4_vrf := t.NetdevRoute(*ifs["phys"], s6netdev.Route{ Default: true, IPver: 4, Vrf: ifs["vrf-phys"], Via: netip.MustParseAddr("10.24.0.1"), Metric: 1024, }, ) phys_defrt_v4_vrf.Children = append(phys_defrt_v4_vrf.Children, phys_addr_v4) phys_defrt_v4_main := t.NetdevRoute(*ifs["phys"], s6netdev.Route{ Default: true, IPver: 4, Via: netip.MustParseAddr("10.24.0.1"), Metric: 1024, }, ) phys_defrt_v4_main.Children = append(phys_defrt_v4_main.Children, phys_addr_v4) phys_addr_v6 := t.NetdevIfaceAddr(*ifs["phys"], netip.MustParsePrefix("2a02:810d:95bf:f999:921b:eff:fe55:75ab/64")) phys_defrt_v6_vrf := t.NetdevRoute(*ifs["phys"], s6netdev.Route{ Default: true, IPver: 6, Vrf: ifs["vrf-phys"], Via: netip.MustParseAddr("fe80::2e91:abff:fe90:9bb5"), Metric: 1024, }, ) phys_defrt_v6_vrf.Children = append(phys_defrt_v6_vrf.Children, phys_addr_v6) phys_defrt_v6_main := t.NetdevRoute(*ifs["phys"], s6netdev.Route{ Default: true, IPver: 6, Via: netip.MustParseAddr("fe80::2e91:abff:fe90:9bb5"), Metric: 1024, }, ) phys_defrt_v6_main.Children = append(phys_defrt_v6_main.Children, phys_addr_v6) // Private Bridges for _, name := range []string{ "b00b", "d00d", "f33d", "dn42", } { ifs.AddIf(&s6netdev.Iface{ Name: fmt.Sprintf("virbr-%s", name), Type: &s6netdev.NetdevIfTypes.Bridge, Properties: []s6netdev.Property{ {Key: "stp_state", Value: "1", Default: "0"}, {Key: "mcast_snooping", Value: "0", Default: "1"}, }, Sysctls: s6netdev.Sysctl_IP{ V6: []s6netdev.Property{ {Key: "forwarding", Value: "0", Default: "0"}, {Key: "accept_ra", Value: "0", Default: "1"}, }, }, }) } for _, m := range []struct { Master string Slaves []string }{ { Master: "vrf-b00b", Slaves: []string{ "phys.66", }, }, { Master: "vrf-phys", Slaves: []string{ "phys", }, }, { Master: "bond10", Slaves: []string{ "enp129s0f0", "enp129s0f1", }, }, { Master: "phys", Slaves: []string{ "bond10", "enp131s0f0", "enp131s0f1", "enp131s0f2", "enp131s0f3", }, }, } { master := ifs[m.Master] for _, slave := range m.Slaves { master.Slaves = append(master.Slaves, ifs[slave]) } ifs[m.Master] = master } // Parent of VLANs ifs[fmt.Sprintf("phys.%d", 66)].Parent = ifs["phys"] // Unreachable routes for _, vrf := range []string{"vrf-phys", "vrf-b00b"} { // TODO: iproute2 inconsistency for ipv4? for _, ver := range []int{6} { ifs["lo"].Routes = append(ifs["lo"].Routes, s6netdev.Route{ Type: "unreachable", Default: true, IPver: ver, Vrf: ifs[vrf], Metric: 4278198272, }, ) } } for _, v := range ifs { t.Services(*v) } for _, v := range t.S6Services() { if s6netdev.NetdevIsDummy(v.Name) { continue } l.Printf("Commiting %s\n", v.Name) if err = t.S6CommitService(v); err != nil { l.Fatalf("Failed to commit %s, %s\n", v.Name, err) } } }