github.com/cilium/cilium@v1.16.2/pkg/bgpv1/manager/manager_test.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright Authors of Cilium 3 4 package manager 5 6 import ( 7 "context" 8 "fmt" 9 "net/netip" 10 "testing" 11 12 "github.com/stretchr/testify/require" 13 "k8s.io/utils/ptr" 14 15 restapi "github.com/cilium/cilium/api/v1/server/restapi/bgp" 16 "github.com/cilium/cilium/pkg/bgpv1/agent/mode" 17 "github.com/cilium/cilium/pkg/bgpv1/manager/instance" 18 "github.com/cilium/cilium/pkg/bgpv1/types" 19 v2alpha1api "github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2alpha1" 20 ) 21 22 var ( 23 testSingleIPv4Prefix = []netip.Prefix{ 24 netip.MustParsePrefix("192.168.0.0/24"), 25 } 26 testSingleIPv6Prefix = []netip.Prefix{ 27 netip.MustParsePrefix("2001:DB8::/32"), 28 } 29 30 testRouterASN = 64125 31 testInvalidRouterASN = 4126 32 testNeighborIP = "5.6.7.8" 33 testInvalidNeighborIP = "1.2.3.4" 34 35 tableTypeLocRib = "loc-rib" 36 tableTypeLocAdjRibOut = "adj-rib-out" 37 afiIPv4 = "ipv4" 38 afiIPv6 = "ipv6" 39 safiUnicast = "unicast" 40 ) 41 42 // TestGetRoutes tests GetRoutes API of the Manager. 43 func TestGetRoutes(t *testing.T) { 44 45 var table = []struct { 46 // name of the test case 47 name string 48 49 // advertised prefixes 50 advertisedPrefixes []netip.Prefix 51 // expected prefixes 52 expectedPrefixes []netip.Prefix 53 54 // GetRoutes params 55 routerASN *int64 56 tableType string 57 afi string 58 safi string 59 neighbor *string 60 61 // non-nil if error is expected, nil if not 62 expectedErr error 63 }{ 64 { 65 name: "single IPv4 prefix - retrieve IPv4", 66 advertisedPrefixes: testSingleIPv4Prefix, 67 expectedPrefixes: testSingleIPv4Prefix, 68 routerASN: ptr.To[int64](int64(testRouterASN)), 69 tableType: tableTypeLocRib, 70 afi: afiIPv4, 71 safi: safiUnicast, 72 neighbor: nil, 73 expectedErr: nil, 74 }, 75 { 76 name: "single IPv4 prefix - retrieve IPv6", 77 advertisedPrefixes: testSingleIPv4Prefix, 78 expectedPrefixes: nil, 79 routerASN: ptr.To[int64](int64(testRouterASN)), 80 tableType: tableTypeLocRib, 81 afi: afiIPv6, 82 safi: safiUnicast, 83 neighbor: nil, 84 expectedErr: nil, 85 }, 86 { 87 name: "single IPv6 prefix - retrieve IPv6", 88 advertisedPrefixes: testSingleIPv6Prefix, 89 expectedPrefixes: testSingleIPv6Prefix, 90 routerASN: nil, 91 tableType: tableTypeLocRib, 92 afi: afiIPv6, 93 safi: safiUnicast, 94 neighbor: nil, 95 expectedErr: nil, 96 }, 97 { 98 name: "mixed IPv4 & IPv6 prefixes - retrieve IPv6", 99 advertisedPrefixes: []netip.Prefix{testSingleIPv4Prefix[0], testSingleIPv6Prefix[0]}, 100 routerASN: nil, 101 expectedPrefixes: testSingleIPv6Prefix, 102 tableType: tableTypeLocRib, 103 afi: afiIPv6, 104 safi: safiUnicast, 105 neighbor: nil, 106 expectedErr: nil, 107 }, 108 { 109 name: "incorrect ASN", 110 advertisedPrefixes: testSingleIPv4Prefix, 111 expectedPrefixes: nil, 112 routerASN: ptr.To[int64](int64(testInvalidRouterASN)), 113 tableType: tableTypeLocRib, 114 afi: afiIPv4, 115 safi: safiUnicast, 116 neighbor: nil, 117 expectedErr: fmt.Errorf(""), 118 }, 119 { 120 name: "unspecified neighbor for adj-rib-out", 121 advertisedPrefixes: testSingleIPv4Prefix, 122 expectedPrefixes: nil, // nil as the neighbor never goes UP 123 routerASN: nil, 124 tableType: tableTypeLocAdjRibOut, 125 afi: afiIPv4, 126 safi: safiUnicast, 127 neighbor: nil, 128 expectedErr: nil, 129 }, 130 { 131 name: "valid neighbor", 132 advertisedPrefixes: testSingleIPv4Prefix, 133 expectedPrefixes: nil, // nil as the neighbor never goes UP 134 routerASN: nil, 135 tableType: tableTypeLocAdjRibOut, 136 afi: afiIPv4, 137 safi: safiUnicast, 138 neighbor: ptr.To[string](testNeighborIP), 139 expectedErr: nil, 140 }, 141 { 142 name: "non-existing neighbor", 143 advertisedPrefixes: testSingleIPv4Prefix, 144 expectedPrefixes: nil, 145 routerASN: nil, 146 tableType: tableTypeLocAdjRibOut, 147 afi: afiIPv4, 148 safi: safiUnicast, 149 neighbor: ptr.To[string](testInvalidNeighborIP), 150 expectedErr: fmt.Errorf(""), 151 }, 152 } 153 154 for _, tt := range table { 155 t.Run(tt.name, func(t *testing.T) { 156 // set up BGPRouterManager with one BGP server 157 srvParams := types.ServerParameters{ 158 Global: types.BGPGlobal{ 159 ASN: uint32(testRouterASN), 160 RouterID: "127.0.0.1", 161 ListenPort: -1, 162 }, 163 } 164 testSC, err := instance.NewServerWithConfig(context.Background(), log, srvParams) 165 require.NoError(t, err) 166 167 testSC.Config = &v2alpha1api.CiliumBGPVirtualRouter{ 168 LocalASN: int64(testRouterASN), 169 Neighbors: []v2alpha1api.CiliumBGPNeighbor{}, 170 } 171 cm := mode.NewConfigMode() 172 cm.Set(mode.BGPv1) 173 174 brm := &BGPRouterManager{ 175 ConfigMode: cm, 176 Servers: map[int64]*instance.ServerWithConfig{ 177 int64(testRouterASN): testSC, 178 }, 179 running: true, 180 } 181 182 // add a neighbor 183 n := &v2alpha1api.CiliumBGPNeighbor{ 184 PeerAddress: testNeighborIP + "/32", 185 PeerASN: 64100, 186 } 187 n.SetDefaults() 188 err = testSC.Server.AddNeighbor(context.Background(), types.NeighborRequest{ 189 Neighbor: n, 190 }) 191 require.NoError(t, err) 192 193 // advertise test-provided prefixes 194 for _, cidr := range tt.advertisedPrefixes { 195 _, err := testSC.Server.AdvertisePath(context.Background(), types.PathRequest{ 196 Path: types.NewPathForPrefix(cidr), 197 }) 198 require.NoError(t, err) 199 } 200 201 // retrieve routes from server's local RIB and 202 routes, err := brm.GetRoutes(context.Background(), restapi.GetBgpRoutesParams{ 203 RouterAsn: tt.routerASN, 204 TableType: tt.tableType, 205 Afi: tt.afi, 206 Safi: tt.safi, 207 Neighbor: tt.neighbor, 208 }) 209 if tt.expectedErr == nil { 210 require.NoError(t, err) 211 } else { 212 require.Error(t, err) 213 } 214 215 // ensure retrieved routes match expected prefixes 216 var retrievedPrefixes []netip.Prefix 217 for _, r := range routes { 218 retrievedPrefixes = append(retrievedPrefixes, netip.MustParsePrefix(r.Prefix)) 219 } 220 require.EqualValues(t, tt.expectedPrefixes, retrievedPrefixes) 221 }) 222 } 223 }