Skip to content

Commit

Permalink
Add Route info in output of "antctl get bgproutes"
Browse files Browse the repository at this point in the history
Signed-off-by: Kumar Atish <[email protected]>
  • Loading branch information
Atish-iaf committed Nov 18, 2024
1 parent aef4fb3 commit fbf32fe
Show file tree
Hide file tree
Showing 8 changed files with 441 additions and 229 deletions.
26 changes: 15 additions & 11 deletions docs/antctl.md
Original file line number Diff line number Diff line change
Expand Up @@ -803,25 +803,29 @@ For more information about route advertisement, please refer to [Advertisements]
# Get the list of all advertised bgp routes
$ antctl get bgproutes

ROUTE
10.96.10.10/32
192.168.77.100/32
fec0::10:96:10:10/128
fec0::192:168:77:100/128
ROUTE TYPE K8s-OBJ-REF
10.244.1.0/24 NodeIPAMPodCIDR Pod
10.96.0.1/32 ServiceLoadBalancerIP default/svc1
172.18.0.3/32 EgressIP egress1
fd00:10:244:1::/64 NodeIPAMPodCIDR Pod
fec0::10:96:10:10/128 ServiceLoadBalancerIP default/svc2
fec0::192:168:77:100/128 EgressIP egress2

# Get the list of advertised IPv4 bgp routes
$ antctl get bgproutes --ipv4-only

ROUTE
10.96.10.10/32
192.168.77.100/32
ROUTE TYPE K8s-OBJ-REF
10.244.1.0/24 NodeIPAMPodCIDR Pod
10.96.0.1/32 ServiceLoadBalancerIP default/svc1
172.18.0.3/32 EgressIP egress1

# Get the list of advertised IPv6 bgp routes
$ antctl get bgproutes --ipv6-only

ROUTE
fec0::10:96:10:10/128
fec0::192:168:77:100/128
ROUTE TYPE K8s-OBJ-REF
fd00:10:244:1::/64 NodeIPAMPodCIDR Pod
fec0::10:96:10:10/128 ServiceLoadBalancerIP default/svc2
fec0::192:168:77:100/128 EgressIP egress2
```

### Upgrade existing objects of CRDs
Expand Down
8 changes: 5 additions & 3 deletions pkg/agent/apis/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -232,15 +232,17 @@ func (r BGPPeerResponse) SortRows() bool {

// BGPRouteResponse describes the response struct of bgproutes command.
type BGPRouteResponse struct {
Route string `json:"route,omitempty"`
Route string `json:"route,omitempty"`
Type string `json:"type,omitempty"`
K8sObjRef string `json:"k8sObjRef,omitempty"`
}

func (r BGPRouteResponse) GetTableHeader() []string {
return []string{"ROUTE"}
return []string{"ROUTE", "TYPE", "K8s-OBJ-REF"}
}

func (r BGPRouteResponse) GetTableRow(_ int) []string {
return []string{r.Route}
return []string{r.Route, r.Type, r.K8sObjRef}
}

func (r BGPRouteResponse) SortRows() bool {
Expand Down
32 changes: 28 additions & 4 deletions pkg/agent/apiserver/handlers/bgproute/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"reflect"

"k8s.io/klog/v2"
"k8s.io/utils/net"

"antrea.io/antrea/pkg/agent/apis"
"antrea.io/antrea/pkg/agent/controller/bgp"
Expand Down Expand Up @@ -68,10 +69,33 @@ func HandleFunc(bq querier.AgentBGPPolicyInfoQuerier) http.HandlerFunc {
}

var bgpRoutesResp []apis.BGPRouteResponse
for _, bgpRoute := range bgpRoutes {
bgpRoutesResp = append(bgpRoutesResp, apis.BGPRouteResponse{
Route: bgpRoute,
})
if !ipv4Only && !ipv6Only {
for bgpRoute := range bgpRoutes {
if net.IsIPv4CIDRString(bgpRoute.Prefix) {
bgpRoutesResp = append(bgpRoutesResp, apis.BGPRouteResponse{
Route: bgpRoute.Prefix,
Type: string(bgpRoutes[bgpRoute].Type),
K8sObjRef: bgpRoutes[bgpRoute].K8sObjRef,
})
}
}
for bgpRoute := range bgpRoutes {
if net.IsIPv6CIDRString(bgpRoute.Prefix) {
bgpRoutesResp = append(bgpRoutesResp, apis.BGPRouteResponse{
Route: bgpRoute.Prefix,
Type: string(bgpRoutes[bgpRoute].Type),
K8sObjRef: bgpRoutes[bgpRoute].K8sObjRef,
})
}
}
} else {
for bgpRoute := range bgpRoutes {
bgpRoutesResp = append(bgpRoutesResp, apis.BGPRouteResponse{
Route: bgpRoute.Prefix,
Type: string(bgpRoutes[bgpRoute].Type),
K8sObjRef: bgpRoutes[bgpRoute].K8sObjRef,
})
}
}

if err := json.NewEncoder(w).Encode(bgpRoutesResp); err != nil {
Expand Down
70 changes: 57 additions & 13 deletions pkg/agent/apiserver/handlers/bgproute/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,26 @@ import (
"go.uber.org/mock/gomock"

"antrea.io/antrea/pkg/agent/apis"
"antrea.io/antrea/pkg/agent/controller/bgp"
"antrea.io/antrea/pkg/agent/bgp"
bgpcontroller "antrea.io/antrea/pkg/agent/controller/bgp"
queriertest "antrea.io/antrea/pkg/querier/testing"
)

const (
namespaceDefault = "default"
)

var (
podIPv4CIDR = "10.10.0.0/24"
clusterIPv4 = "10.96.10.10/32"
loadBalancerIPv6 = "fec0::192:168:77:150/128"
egressIPv6 = "fec0::192:168:77:200/128"

ipv4ClusterIPName = "clusterip-4"
ipv6LoadBalancerName = "loadbalancer-6"
ipv6EgressName = "egress-6"
)

func TestBGPRouteQuery(t *testing.T) {
ctx := context.Background()
tests := []struct {
Expand All @@ -42,26 +58,36 @@ func TestBGPRouteQuery(t *testing.T) {
{
name: "bgpPolicyState does not exist",
expectedCalls: func(mockBGPServer *queriertest.MockAgentBGPPolicyInfoQuerier) {
mockBGPServer.EXPECT().GetBGPRoutes(context.Background(), true, true).Return(nil, bgp.ErrBGPPolicyNotFound)
mockBGPServer.EXPECT().GetBGPRoutes(context.Background(), true, true).Return(nil, bgpcontroller.ErrBGPPolicyNotFound)
},
expectedStatus: http.StatusNotFound,
},
{
name: "get all advertised routes",
expectedCalls: func(mockBGPServer *queriertest.MockAgentBGPPolicyInfoQuerier) {
mockBGPServer.EXPECT().GetBGPRoutes(ctx, true, true).Return(
[]string{"192.168.1.0/24", "192.168.2.0/24", "fec0::10:96:10:10/128"}, nil)
map[bgp.Route]bgpcontroller.RouteMetadata{
{Prefix: clusterIPv4}: {Type: bgpcontroller.ServiceClusterIP, K8sObjRef: getServiceName(ipv4ClusterIPName)},
{Prefix: podIPv4CIDR}: {Type: bgpcontroller.NodeIPAMPodCIDR, K8sObjRef: "Pod"},
{Prefix: egressIPv6}: {Type: bgpcontroller.EgressIP, K8sObjRef: ipv6EgressName},
}, nil)
},
expectedStatus: http.StatusOK,
expectedResponse: []apis.BGPRouteResponse{
{
Route: "192.168.1.0/24",
Route: clusterIPv4,
Type: string(bgpcontroller.ServiceClusterIP),
K8sObjRef: getServiceName(ipv4ClusterIPName),
},
{
Route: "192.168.2.0/24",
Route: podIPv4CIDR,
Type: string(bgpcontroller.NodeIPAMPodCIDR),
K8sObjRef: "Pod",
},
{
Route: "fec0::10:96:10:10/128",
Route: egressIPv6,
Type: string(bgpcontroller.EgressIP),
K8sObjRef: ipv6EgressName,
},
},
},
Expand All @@ -70,15 +96,22 @@ func TestBGPRouteQuery(t *testing.T) {
url: "?ipv4-only",
expectedCalls: func(mockBGPServer *queriertest.MockAgentBGPPolicyInfoQuerier) {
mockBGPServer.EXPECT().GetBGPRoutes(ctx, true, false).Return(
[]string{"192.168.1.0/24", "192.168.2.0/24"}, nil)
map[bgp.Route]bgpcontroller.RouteMetadata{
{Prefix: clusterIPv4}: {Type: bgpcontroller.ServiceClusterIP, K8sObjRef: getServiceName(ipv4ClusterIPName)},
{Prefix: podIPv4CIDR}: {Type: bgpcontroller.NodeIPAMPodCIDR, K8sObjRef: "Pod"},
}, nil)
},
expectedStatus: http.StatusOK,
expectedResponse: []apis.BGPRouteResponse{
{
Route: "192.168.1.0/24",
Route: clusterIPv4,
Type: string(bgpcontroller.ServiceClusterIP),
K8sObjRef: getServiceName(ipv4ClusterIPName),
},
{
Route: "192.168.2.0/24",
Route: podIPv4CIDR,
Type: string(bgpcontroller.NodeIPAMPodCIDR),
K8sObjRef: "Pod",
},
},
},
Expand All @@ -87,15 +120,22 @@ func TestBGPRouteQuery(t *testing.T) {
url: "?ipv6-only=",
expectedCalls: func(mockBGPServer *queriertest.MockAgentBGPPolicyInfoQuerier) {
mockBGPServer.EXPECT().GetBGPRoutes(ctx, false, true).Return(
[]string{"fec0::192:168:77:150/128", "fec0::10:10:0:10/128"}, nil)
map[bgp.Route]bgpcontroller.RouteMetadata{
{Prefix: loadBalancerIPv6}: {Type: bgpcontroller.ServiceLoadBalancerIP, K8sObjRef: getServiceName(ipv6LoadBalancerName)},
{Prefix: egressIPv6}: {Type: bgpcontroller.EgressIP, K8sObjRef: ipv6EgressName},
}, nil)
},
expectedStatus: http.StatusOK,
expectedResponse: []apis.BGPRouteResponse{
{
Route: "fec0::192:168:77:150/128",
Route: loadBalancerIPv6,
Type: string(bgpcontroller.ServiceLoadBalancerIP),
K8sObjRef: getServiceName(ipv6LoadBalancerName),
},
{
Route: "fec0::10:10:0:10/128",
Route: egressIPv6,
Type: string(bgpcontroller.EgressIP),
K8sObjRef: ipv6EgressName,
},
},
},
Expand Down Expand Up @@ -131,8 +171,12 @@ func TestBGPRouteQuery(t *testing.T) {
var received []apis.BGPRouteResponse
err = json.Unmarshal(recorder.Body.Bytes(), &received)
require.NoError(t, err)
assert.Equal(t, tt.expectedResponse, received)
assert.ElementsMatch(t, tt.expectedResponse, received)
}
})
}
}

func getServiceName(name string) string {
return namespaceDefault + "/" + name
}
Loading

0 comments on commit fbf32fe

Please sign in to comment.