From 9b44c0b8fb71fddd36eaab52c27ad6f9356b3693 Mon Sep 17 00:00:00 2001 From: Stefan Majer Date: Fri, 5 Jul 2024 15:57:54 +0200 Subject: [PATCH] IPv6 Support --- cmd/internal/core/reconfigure-switch_test.go | 5 +- .../switcher/templates/template_test.go | 5 +- .../templates/test_data/dev/conf.yaml | 1 + .../templates/test_data/dev/cumulus_frr.conf | 15 +++++ .../test_data/dev/customtpl/frr.conf | 3 + .../templates/test_data/dev/sonic_frr.conf | 15 +++++ .../templates/test_data/lab/cumulus_frr.conf | 12 ++++ .../templates/test_data/lab/sonic_frr.conf | 12 ++++ .../test_data/notenants/cumulus_frr.conf | 5 ++ .../test_data/notenants/sonic_frr.conf | 5 ++ .../switcher/templates/tpl/cumulus_frr.tpl | 16 +++++ .../switcher/templates/tpl/sonic_frr.tpl | 16 +++++ cmd/internal/switcher/types/types.go | 64 +++++++++++++++---- 13 files changed, 160 insertions(+), 14 deletions(-) diff --git a/cmd/internal/core/reconfigure-switch_test.go b/cmd/internal/core/reconfigure-switch_test.go index 8a89030e..3b5f9250 100644 --- a/cmd/internal/core/reconfigure-switch_test.go +++ b/cmd/internal/core/reconfigure-switch_test.go @@ -73,8 +73,9 @@ func TestBuildSwitcherConfig(t *testing.T) { Filter: types.Filter{ IPPrefixLists: []types.IPPrefixList{ { - Name: "vrf104001-in-prefixes", - Spec: "permit 10.240.0.0/12 le 32", + AddressFamily: "ip", + Name: "vrf104001-in-prefixes", + Spec: "permit 10.240.0.0/12 le 32", }, }, RouteMaps: []types.RouteMap{ diff --git a/cmd/internal/switcher/templates/template_test.go b/cmd/internal/switcher/templates/template_test.go index 4bf6b162..f05718ae 100644 --- a/cmd/internal/switcher/templates/template_test.go +++ b/cmd/internal/switcher/templates/template_test.go @@ -8,6 +8,7 @@ import ( "testing" "text/template" + "github.com/google/go-cmp/cmp" "github.com/stretchr/testify/require" "gopkg.in/yaml.v3" @@ -83,7 +84,9 @@ func TestCustomSonicFrrTemplate(t *testing.T) { func verifyTemplate(t *testing.T, tpl *template.Template, c *types.Conf, expectedFilename string) { actual := renderToString(t, tpl, c) expected := readExpected(t, expectedFilename) - require.Equal(t, expected, actual, "Wanted: %s\nGot: %s", expected, actual) + if diff := cmp.Diff(expected, actual); diff != "" { + t.Errorf("%s render differs:%s", expectedFilename, diff) + } } func renderToString(t *testing.T, tpl *template.Template, c *types.Conf) string { diff --git a/cmd/internal/switcher/templates/test_data/dev/conf.yaml b/cmd/internal/switcher/templates/test_data/dev/conf.yaml index bbef9185..8af90b45 100644 --- a/cmd/internal/switcher/templates/test_data/dev/conf.yaml +++ b/cmd/internal/switcher/templates/test_data/dev/conf.yaml @@ -36,6 +36,7 @@ ports: cidrs: - "100.127.131.0/24" - "212.17.234.17/32" + - "2002::1/128" additionalbridgevids: - 201-256 - 301-356 diff --git a/cmd/internal/switcher/templates/test_data/dev/cumulus_frr.conf b/cmd/internal/switcher/templates/test_data/dev/cumulus_frr.conf index 06ef159d..ca27e218 100644 --- a/cmd/internal/switcher/templates/test_data/dev/cumulus_frr.conf +++ b/cmd/internal/switcher/templates/test_data/dev/cumulus_frr.conf @@ -53,6 +53,12 @@ router bgp 4200000010 neighbor swp3 route-map fw-swp3-in in exit-address-family ! + address-family ipv6 unicast + redistribute connected route-map LOOPBACKS + neighbor FIREWALL allowas-in 2 + neighbor swp3 route-map fw-swp3-in in + exit-address-family + ! address-family l2vpn evpn advertise-all-vni neighbor FABRIC activate @@ -93,6 +99,12 @@ router bgp 4200000010 vrf vrf104001 neighbor MACHINE route-map vrf104001-in in exit-address-family ! + address-family ipv6 unicast + redistribute connected + neighbor MACHINE maximum-prefix 24000 + neighbor MACHINE route-map vrf104001-in6 in + exit-address-family + ! address-family l2vpn evpn advertise ipv4 unicast exit-address-family @@ -101,8 +113,11 @@ router bgp 4200000010 vrf vrf104001 ip prefix-list vrf104001-in-prefixes permit 100.127.131.0/24 le 32 ip prefix-list vrf104001-in-prefixes permit 212.17.234.17/32 le 32 ip prefix-list vrf104001-in-prefixes permit 10.240.0.0/12 le 32 +ip prefix-list vrf104001-in6-prefixes permit 2002::1/128 le 128 route-map vrf104001-in permit 10 match ip address prefix-list vrf104001-in-prefixes +route-map vrf104001-in6 permit 10 + match ipv6 address prefix-list vrf104001-in6-prefixes ! line vty ! diff --git a/cmd/internal/switcher/templates/test_data/dev/customtpl/frr.conf b/cmd/internal/switcher/templates/test_data/dev/customtpl/frr.conf index f47d0f09..a4eed3b0 100644 --- a/cmd/internal/switcher/templates/test_data/dev/customtpl/frr.conf +++ b/cmd/internal/switcher/templates/test_data/dev/customtpl/frr.conf @@ -102,8 +102,11 @@ router bgp 4200000010 vrf vrf104001 ip prefix-list vrf104001-in-prefixes permit 100.127.131.0/24 le 32 ip prefix-list vrf104001-in-prefixes permit 212.17.234.17/32 le 32 ip prefix-list vrf104001-in-prefixes permit 10.240.0.0/12 le 32 +ip prefix-list vrf104001-in6-prefixes permit 2002::1/128 le 128 route-map vrf104001-in permit 10 match ip address prefix-list vrf104001-in-prefixes +route-map vrf104001-in6 permit 10 + match ipv6 address prefix-list vrf104001-in6-prefixes ! line vty ! diff --git a/cmd/internal/switcher/templates/test_data/dev/sonic_frr.conf b/cmd/internal/switcher/templates/test_data/dev/sonic_frr.conf index d0c2b11e..acf01bef 100644 --- a/cmd/internal/switcher/templates/test_data/dev/sonic_frr.conf +++ b/cmd/internal/switcher/templates/test_data/dev/sonic_frr.conf @@ -58,6 +58,12 @@ router bgp 4200000010 neighbor swp3 route-map fw-swp3-in in exit-address-family ! + address-family ipv6 unicast + redistribute connected route-map DENY_MGMT + neighbor FIREWALL allowas-in 2 + neighbor swp3 route-map fw-swp3-in in + exit-address-family + ! address-family l2vpn evpn advertise-all-vni neighbor FABRIC activate @@ -99,6 +105,12 @@ router bgp 4200000010 vrf Vrf104001 neighbor MACHINE route-map Vrf104001-in in exit-address-family ! + address-family ipv6 unicast + redistribute connected + neighbor MACHINE maximum-prefix 24000 + neighbor MACHINE route-map Vrf104001-in6 in + exit-address-family + ! address-family l2vpn evpn advertise ipv4 unicast exit-address-family @@ -107,8 +119,11 @@ router bgp 4200000010 vrf Vrf104001 ip prefix-list Vrf104001-in-prefixes permit 100.127.131.0/24 le 32 ip prefix-list Vrf104001-in-prefixes permit 212.17.234.17/32 le 32 ip prefix-list Vrf104001-in-prefixes permit 10.240.0.0/12 le 32 +ip prefix-list Vrf104001-in6-prefixes permit 2002::1/128 le 128 route-map Vrf104001-in permit 10 match ip address prefix-list Vrf104001-in-prefixes +route-map Vrf104001-in6 permit 10 + match ipv6 address prefix-list Vrf104001-in6-prefixes ! line vty ! diff --git a/cmd/internal/switcher/templates/test_data/lab/cumulus_frr.conf b/cmd/internal/switcher/templates/test_data/lab/cumulus_frr.conf index 614d7d77..0979ca76 100644 --- a/cmd/internal/switcher/templates/test_data/lab/cumulus_frr.conf +++ b/cmd/internal/switcher/templates/test_data/lab/cumulus_frr.conf @@ -53,6 +53,12 @@ router bgp 4200000010 neighbor swp3 route-map fw-swp3-in in exit-address-family ! + address-family ipv6 unicast + redistribute connected route-map LOOPBACKS + neighbor FIREWALL allowas-in 2 + neighbor swp3 route-map fw-swp3-in in + exit-address-family + ! address-family l2vpn evpn advertise-all-vni neighbor FABRIC activate @@ -93,6 +99,12 @@ router bgp 4200000010 vrf vrf104001 neighbor MACHINE route-map vrf104001-in in exit-address-family ! + address-family ipv6 unicast + redistribute connected + neighbor MACHINE maximum-prefix 24000 + neighbor MACHINE route-map vrf104001-in6 in + exit-address-family + ! address-family l2vpn evpn advertise ipv4 unicast exit-address-family diff --git a/cmd/internal/switcher/templates/test_data/lab/sonic_frr.conf b/cmd/internal/switcher/templates/test_data/lab/sonic_frr.conf index 2738fe2a..b6682f10 100644 --- a/cmd/internal/switcher/templates/test_data/lab/sonic_frr.conf +++ b/cmd/internal/switcher/templates/test_data/lab/sonic_frr.conf @@ -58,6 +58,12 @@ router bgp 4200000010 neighbor swp3 route-map fw-swp3-in in exit-address-family ! + address-family ipv6 unicast + redistribute connected route-map DENY_MGMT + neighbor FIREWALL allowas-in 2 + neighbor swp3 route-map fw-swp3-in in + exit-address-family + ! address-family l2vpn evpn advertise-all-vni neighbor FABRIC activate @@ -99,6 +105,12 @@ router bgp 4200000010 vrf Vrf104001 neighbor MACHINE route-map Vrf104001-in in exit-address-family ! + address-family ipv6 unicast + redistribute connected + neighbor MACHINE maximum-prefix 24000 + neighbor MACHINE route-map Vrf104001-in6 in + exit-address-family + ! address-family l2vpn evpn advertise ipv4 unicast exit-address-family diff --git a/cmd/internal/switcher/templates/test_data/notenants/cumulus_frr.conf b/cmd/internal/switcher/templates/test_data/notenants/cumulus_frr.conf index 392a3493..296bd578 100644 --- a/cmd/internal/switcher/templates/test_data/notenants/cumulus_frr.conf +++ b/cmd/internal/switcher/templates/test_data/notenants/cumulus_frr.conf @@ -35,6 +35,11 @@ router bgp 4200000010 neighbor FIREWALL allowas-in 2 exit-address-family ! + address-family ipv6 unicast + redistribute connected route-map LOOPBACKS + neighbor FIREWALL allowas-in 2 + exit-address-family + ! address-family l2vpn evpn advertise-all-vni neighbor FABRIC activate diff --git a/cmd/internal/switcher/templates/test_data/notenants/sonic_frr.conf b/cmd/internal/switcher/templates/test_data/notenants/sonic_frr.conf index e784bf59..adbee723 100644 --- a/cmd/internal/switcher/templates/test_data/notenants/sonic_frr.conf +++ b/cmd/internal/switcher/templates/test_data/notenants/sonic_frr.conf @@ -40,6 +40,11 @@ router bgp 4200000010 neighbor FIREWALL allowas-in 2 exit-address-family ! + address-family ipv6 unicast + redistribute connected route-map DENY_MGMT + neighbor FIREWALL allowas-in 2 + exit-address-family + ! address-family l2vpn evpn advertise-all-vni neighbor FABRIC activate diff --git a/cmd/internal/switcher/templates/tpl/cumulus_frr.tpl b/cmd/internal/switcher/templates/tpl/cumulus_frr.tpl index 385fa240..2789fdc3 100644 --- a/cmd/internal/switcher/templates/tpl/cumulus_frr.tpl +++ b/cmd/internal/switcher/templates/tpl/cumulus_frr.tpl @@ -60,6 +60,14 @@ router bgp {{ $ASN }} {{- end }} exit-address-family ! + address-family ipv6 unicast + redistribute connected route-map LOOPBACKS + neighbor FIREWALL allowas-in 2 + {{- range $k, $f := .Ports.Firewalls }} + neighbor {{ $f.Port }} route-map fw-{{ $k }}-in in + {{- end }} + exit-address-family + ! address-family l2vpn evpn advertise-all-vni neighbor FABRIC activate @@ -108,6 +116,14 @@ router bgp {{ $ASN }} vrf {{ $vrf }} {{- end }} exit-address-family ! + address-family ipv6 unicast + redistribute connected + neighbor MACHINE maximum-prefix 24000 + {{- if gt (len $t.IPPrefixLists) 0 }} + neighbor MACHINE route-map {{ $vrf }}-in6 in + {{- end }} + exit-address-family + ! address-family l2vpn evpn advertise ipv4 unicast exit-address-family diff --git a/cmd/internal/switcher/templates/tpl/sonic_frr.tpl b/cmd/internal/switcher/templates/tpl/sonic_frr.tpl index 2d81bdb5..4ba91c31 100644 --- a/cmd/internal/switcher/templates/tpl/sonic_frr.tpl +++ b/cmd/internal/switcher/templates/tpl/sonic_frr.tpl @@ -65,6 +65,14 @@ router bgp {{ $ASN }} {{- end }} exit-address-family ! + address-family ipv6 unicast + redistribute connected route-map DENY_MGMT + neighbor FIREWALL allowas-in 2 + {{- range $k, $f := .Ports.Firewalls }} + neighbor {{ $f.Port }} route-map fw-{{ $k }}-in in + {{- end }} + exit-address-family + ! address-family l2vpn evpn advertise-all-vni neighbor FABRIC activate @@ -116,6 +124,14 @@ router bgp {{ $ASN }} vrf {{ $vrf }} {{- end }} exit-address-family ! + address-family ipv6 unicast + redistribute connected + neighbor MACHINE maximum-prefix 24000 + {{- if gt (len $t.IPPrefixLists) 0 }} + neighbor MACHINE route-map {{ $vrf }}-in6 in + {{- end }} + exit-address-family + ! address-family l2vpn evpn advertise ipv4 unicast exit-address-family diff --git a/cmd/internal/switcher/types/types.go b/cmd/internal/switcher/types/types.go index 21c4fd27..3fac3dcc 100644 --- a/cmd/internal/switcher/types/types.go +++ b/cmd/internal/switcher/types/types.go @@ -2,6 +2,7 @@ package types import ( "fmt" + "net/netip" ) // Conf holds the switch configuration @@ -62,12 +63,14 @@ type RouteMap struct { // IPPrefixList represents 'ip prefix-list' filtering mechanism to be used in combination with route-maps. type IPPrefixList struct { - Name string - Spec string + AddressFamily string + Name string + Spec string } func (s *Filter) Assemble(rmPrefix string, vnis, cidrs []string) { - if len(cidrs) > 0 { + cidrMap := sortCIDRByAddressfamily(cidrs) + if len(cidrMap["ipv4"]) > 0 { prefixRouteMapName := fmt.Sprintf("%s-in", rmPrefix) prefixListName := fmt.Sprintf("%s-in-prefixes", rmPrefix) rm := RouteMap{ @@ -77,15 +80,19 @@ func (s *Filter) Assemble(rmPrefix string, vnis, cidrs []string) { Order: 10, } s.RouteMaps = append(s.RouteMaps, rm) - - for _, cidr := range cidrs { - spec := fmt.Sprintf("permit %s le 32", cidr) - prefixList := IPPrefixList{ - Name: prefixListName, - Spec: spec, - } - s.IPPrefixLists = append(s.IPPrefixLists, prefixList) + s.addPrefixList(prefixListName, cidrMap["ipv4"], "ip") + } + if len(cidrMap["ipv6"]) > 0 { + prefixRouteMapName := fmt.Sprintf("%s-in6", rmPrefix) + prefixListName := fmt.Sprintf("%s-in6-prefixes", rmPrefix) + rm := RouteMap{ + Name: prefixRouteMapName, + Entries: []string{fmt.Sprintf("match ipv6 address prefix-list %s", prefixListName)}, + Policy: "permit", + Order: 10, } + s.RouteMaps = append(s.RouteMaps, rm) + s.addPrefixList(prefixListName, cidrMap["ipv6"], "ipv6") } if len(vnis) > 0 { vniRouteMapName := fmt.Sprintf("%s-vni", rmPrefix) @@ -100,3 +107,38 @@ func (s *Filter) Assemble(rmPrefix string, vnis, cidrs []string) { } } } + +func (s *Filter) addPrefixList(prefixListName string, cidrs []string, af string) { + for _, cidr := range cidrs { + prefix, err := netip.ParsePrefix(cidr) + if err != nil { + continue + } + spec := fmt.Sprintf("permit %s le %d", cidr, prefix.Addr().BitLen()) + prefixList := IPPrefixList{ + AddressFamily: af, + Name: prefixListName, + Spec: spec, + } + s.IPPrefixLists = append(s.IPPrefixLists, prefixList) + } +} + +func sortCIDRByAddressfamily(cidrs []string) map[string][]string { + sortedCIDRs := make(map[string][]string) + sortedCIDRs["ipv4"] = []string{} + sortedCIDRs["ipv6"] = []string{} + for _, cidr := range cidrs { + prefix, err := netip.ParsePrefix(cidr) + if err != nil { + continue + } + if prefix.Addr().Is4() { + sortedCIDRs["ipv4"] = append(sortedCIDRs["ipv4"], cidr) + } + if prefix.Addr().Is6() { + sortedCIDRs["ipv6"] = append(sortedCIDRs["ipv6"], cidr) + } + } + return sortedCIDRs +}