Skip to content

Commit

Permalink
Support BGP in antctl
Browse files Browse the repository at this point in the history
Add `antctl get bgppolicy` agent command to get effective BGP policy applied
on the Node.
Add `antctl get bgpserver` agent command to get configuration of BGP server
running on the Node.

For antrea-io#6209

Signed-off-by: Kumar Atish <[email protected]>
  • Loading branch information
Atish-iaf committed Aug 30, 2024
1 parent a996421 commit 187729c
Show file tree
Hide file tree
Showing 17 changed files with 300 additions and 3 deletions.
4 changes: 3 additions & 1 deletion cmd/antrea-agent/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -746,9 +746,10 @@ func run(o *Options) error {
}
}

var bgpController *bgp.Controller
if features.DefaultFeatureGate.Enabled(features.BGPPolicy) {
bgpPolicyInformer := crdInformerFactory.Crd().V1alpha1().BGPPolicies()
bgpController, err := bgp.NewBGPPolicyController(nodeInformer,
bgpController, err = bgp.NewBGPPolicyController(nodeInformer,
serviceInformer,
egressInformer,
bgpPolicyInformer,
Expand Down Expand Up @@ -926,6 +927,7 @@ func run(o *Options) error {
o.config.NodePortLocal.PortRange,
memberlistCluster,
nodeInformer.Lister(),
bgpController,
)

if features.DefaultFeatureGate.Enabled(features.SupportBundleCollection) {
Expand Down
23 changes: 23 additions & 0 deletions docs/antctl.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ running in three different modes:
- [Multi-cluster commands](#multi-cluster-commands)
- [Multicast commands](#multicast-commands)
- [Showing memberlist state](#showing-memberlist-state)
- [BGP commands](#bgp-commands)
- [Upgrade existing objects of CRDs](#upgrade-existing-objects-of-crds)
<!-- /toc -->

Expand Down Expand Up @@ -747,6 +748,28 @@ worker2 172.18.0.3 Alive
worker3 172.18.0.2 Dead
```

### BGP commands

`antctl` agent command `get bgppolicy` (or `get bp`) prints effective BGP policy applied on the local Node.
It includes the name, local ASN, router ID and listen port of the effective BGP policy.

```bash
$ antctl get bgppolicy

NAME ROUTER-ID LOCAL-ASN LISTEN-PORT
example-bgp-policy 172.18.0.2 64512 179
```

`antctl` agent command `get bgpserver` (or `get bs`) prints configuration of the
BGP server running on the local Node. It includes local ASN, router ID and listen port.

```bash
$ antctl get bgpserver

ROUTER-ID LOCAL-ASN LISTEN-PORT
172.18.0.2 64512 179
```

### Upgrade existing objects of CRDs

antctl supports upgrading existing objects of Antrea CRDs to the storage version.
Expand Down
5 changes: 5 additions & 0 deletions docs/bgp-policy.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
- [Example Usage](#example-usage)
- [Combined Advertisements of Service, Pod, and Egress IPs](#combined-advertisements-of-service-pod-and-egress-ips)
- [Advertise Egress IPs to external BGP peers with more than one hop](#advertise-egress-ips-to-external-bgp-peers-with-more-than-one-hop)
- [Using antctl](#using-antctl)
- [Limitations](#limitations)
<!-- /toc -->

Expand Down Expand Up @@ -214,6 +215,10 @@ spec:
multihopTTL: 2
```

## Using antctl

Please refer to the corresponding [antctl page](antctl.md#bgp-commands).

## Limitations

- The routes received from remote BGP peers will not be installed. Therefore, you must ensure that the path from Nodes
Expand Down
39 changes: 39 additions & 0 deletions pkg/agent/apis/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,3 +190,42 @@ func (r ServiceExternalIPInfo) GetTableRow(_ int) []string {
func (r ServiceExternalIPInfo) SortRows() bool {
return true
}

// BGPPolicyResponse describes the response struct of bgppolicy command.
type BGPPolicyResponse struct {
BGPPolicyName string `json:"name,omitempty"`
RouterID string `json:"routerID,omitempty"`
LocalASN int32 `json:"localASN,omitempty"`
ListenPort int32 `json:"listenPort,omitempty"`
}

func (r BGPPolicyResponse) GetTableHeader() []string {
return []string{"NAME", "ROUTER-ID", "LOCAL-ASN", "LISTEN-PORT"}
}

func (r BGPPolicyResponse) GetTableRow(_ int) []string {
return []string{r.BGPPolicyName, r.RouterID, strconv.Itoa(int(r.LocalASN)), strconv.Itoa(int(r.ListenPort))}
}

func (r BGPPolicyResponse) SortRows() bool {
return true
}

// BGPServerResponse describes the response struct of bgpserver command.
type BGPServerResponse struct {
RouterID string `json:"routerID,omitempty"`
LocalASN int32 `json:"localASN,omitempty"`
ListenPort int32 `json:"listenPort,omitempty"`
}

func (r BGPServerResponse) GetTableHeader() []string {
return []string{"ROUTER-ID", "LOCAL-ASN", "LISTEN-PORT"}
}

func (r BGPServerResponse) GetTableRow(_ int) []string {
return []string{r.RouterID, strconv.Itoa(int(r.LocalASN)), strconv.Itoa(int(r.ListenPort))}
}

func (r BGPServerResponse) SortRows() bool {
return true
}
4 changes: 4 additions & 0 deletions pkg/agent/apiserver/apiserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ import (
"antrea.io/antrea/pkg/agent/apiserver/handlers/addressgroup"
"antrea.io/antrea/pkg/agent/apiserver/handlers/agentinfo"
"antrea.io/antrea/pkg/agent/apiserver/handlers/appliedtogroup"
"antrea.io/antrea/pkg/agent/apiserver/handlers/bgppolicy"
"antrea.io/antrea/pkg/agent/apiserver/handlers/bgpserver"
"antrea.io/antrea/pkg/agent/apiserver/handlers/featuregates"
"antrea.io/antrea/pkg/agent/apiserver/handlers/memberlist"
"antrea.io/antrea/pkg/agent/apiserver/handlers/multicast"
Expand Down Expand Up @@ -97,6 +99,8 @@ func installHandlers(aq agentquerier.AgentQuerier, npq querier.AgentNetworkPolic
s.Handler.NonGoRestfulMux.HandleFunc("/ovstracing", ovstracing.HandleFunc(aq))
s.Handler.NonGoRestfulMux.HandleFunc("/serviceexternalip", serviceexternalip.HandleFunc(seipq))
s.Handler.NonGoRestfulMux.HandleFunc("/memberlist", memberlist.HandleFunc(aq))
s.Handler.NonGoRestfulMux.HandleFunc("/bgppolicy", bgppolicy.HandleFunc(aq))
s.Handler.NonGoRestfulMux.HandleFunc("/bgpserver", bgpserver.HandleFunc(aq))
}

func installAPIGroup(s *genericapiserver.GenericAPIServer, aq agentquerier.AgentQuerier, npq querier.AgentNetworkPolicyInfoQuerier, v4Enabled, v6Enabled bool) error {
Expand Down
52 changes: 52 additions & 0 deletions pkg/agent/apiserver/handlers/bgppolicy/handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Copyright 2024 Antrea Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package bgppolicy

import (
"encoding/json"
"net/http"
"reflect"

"k8s.io/klog/v2"

"antrea.io/antrea/pkg/agent/apis"
"antrea.io/antrea/pkg/agent/querier"
)

// HandleFunc returns the function which can handle queries issued by the bgppolicy command.
func HandleFunc(aq querier.AgentQuerier) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
bgpPolicyInfoQuerier := aq.GetBGPPolicyInfoQuerier()
if reflect.ValueOf(bgpPolicyInfoQuerier).IsNil() {
// The error message must match the "FOO is not enabled" pattern to pass antctl e2e tests.
http.Error(w, "bgp is not enabled", http.StatusServiceUnavailable)
return
}

bgpPolicyName, routerID, localASN, listenPort := bgpPolicyInfoQuerier.GetBGPPolicyInfo()
bgpPolicyResp := apis.BGPPolicyResponse{
BGPPolicyName: bgpPolicyName,
RouterID: routerID,
LocalASN: localASN,
ListenPort: listenPort,
}

err := json.NewEncoder(w).Encode(bgpPolicyResp)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
klog.Errorf("Error when encoding BGPPolicyResp to json: %v", err)
}
}
}
55 changes: 55 additions & 0 deletions pkg/agent/apiserver/handlers/bgpserver/handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// Copyright 2024 Antrea Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package bgpserver

import (
"encoding/json"
"net/http"
"reflect"

"k8s.io/klog/v2"

"antrea.io/antrea/pkg/agent/apis"
"antrea.io/antrea/pkg/agent/querier"
)

// HandleFunc returns the function which can handle queries issued by the bgpserver command.
func HandleFunc(aq querier.AgentQuerier) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
bgpPolicyInfoQuerier := aq.GetBGPPolicyInfoQuerier()
if reflect.ValueOf(bgpPolicyInfoQuerier).IsNil() {
// The error message must match the "FOO is not enabled" pattern to pass antctl e2e tests.
http.Error(w, "bgp is not enabled", http.StatusServiceUnavailable)
return
}

routerID, localASN, listenPort, err := bgpPolicyInfoQuerier.GetBGPServerConfig()
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
bgpServerResp := apis.BGPServerResponse{
RouterID: routerID,
LocalASN: localASN,
ListenPort: listenPort,
}

err = json.NewEncoder(w).Encode(bgpServerResp)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
klog.Errorf("Error when encoding BGPServerResp to json: %v", err)
}
}
}
12 changes: 12 additions & 0 deletions pkg/agent/bgp/gobgp/gobgp.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,18 @@ func (s *Server) GetRoutes(ctx context.Context, routeType bgp.RouteType, peerAdd
return routes, nil
}

func (s *Server) GetGlobalConfig(ctx context.Context) (bgp.GlobalConfig, error) {
gobgpResponse, err := s.server.GetBgp(ctx, &gobgpapi.GetBgpRequest{})
if err != nil {
return bgp.GlobalConfig{}, err
}
return bgp.GlobalConfig{
RouterID: gobgpResponse.Global.RouterId,
ListenPort: gobgpResponse.Global.ListenPort,
ASN: gobgpResponse.Global.Asn,
}, err
}

func convertGoBGPPeerToPeerStatus(peer *gobgpapi.Peer) *bgp.PeerStatus {
if peer == nil {
return nil
Expand Down
3 changes: 3 additions & 0 deletions pkg/agent/bgp/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ type Interface interface {

// GetRoutes retrieves the advertised / received routes to / from the given peer.
GetRoutes(ctx context.Context, routeType RouteType, peerAddress string) ([]Route, error)

// GetGlobalConfig retrieves the global configuration of BGP server.
GetGlobalConfig(ctx context.Context) (GlobalConfig, error)
}

// GlobalConfig contains the global configuration to start a BGP server. More attributes might be added later.
Expand Down
15 changes: 15 additions & 0 deletions pkg/agent/bgp/testing/mock_bgp.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

29 changes: 29 additions & 0 deletions pkg/agent/controller/bgp/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -931,3 +931,32 @@ func (c *Controller) updateBGPPeerPasswords(secret *corev1.Secret) {
}
}
}

// GetBGPPolicyInfo returns Name, RouterID, LocalASN and ListenPort of effective BGP Policy applied on the Node.
func (c *Controller) GetBGPPolicyInfo() (string, string, int32, int32) {
var name, routerID string
var localASN, listenPort int32
bgpPolicy := c.getEffectiveBGPPolicy()
if bgpPolicy != nil {
name = bgpPolicy.Name
}
if c.bgpPolicyState != nil {
routerID = c.bgpPolicyState.routerID
localASN = c.bgpPolicyState.localASN
listenPort = c.bgpPolicyState.listenPort
}
return name, routerID, localASN, listenPort
}

// GetBGPServerConfig returns RouterID, LocalASN and ListenPort of BGP server running on the Node.
func (c *Controller) GetBGPServerConfig() (string, int32, int32, error) {
if c.bgpPolicyState == nil {
return "", 0, 0, nil
}
bgpServer := c.bgpPolicyState.bgpServer
globalConfig, err := bgpServer.GetGlobalConfig(context.TODO())
if err != nil {
return "", 0, 0, fmt.Errorf("failed to get bgp server config: %w", err)
}
return globalConfig.RouterID, int32(globalConfig.ASN), int32(globalConfig.ListenPort), err
}
9 changes: 9 additions & 0 deletions pkg/agent/querier/querier.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ type AgentQuerier interface {
GetNetworkPolicyInfoQuerier() querier.AgentNetworkPolicyInfoQuerier
GetMemberlistCluster() memberlist.Interface
GetNodeLister() corelisters.NodeLister
GetBGPPolicyInfoQuerier() querier.AgentBGPPolicyInfoQuerier
}

type agentQuerier struct {
Expand All @@ -61,6 +62,7 @@ type agentQuerier struct {
nplRange string
memberlistCluster memberlist.Interface
nodeLister corelisters.NodeLister
bgpPolicyInfoQuerier querier.AgentBGPPolicyInfoQuerier
}

func NewAgentQuerier(
Expand All @@ -76,6 +78,7 @@ func NewAgentQuerier(
nplRange string,
memberlistCluster memberlist.Interface,
nodeLister corelisters.NodeLister,
bgpPolicyInfoQuerier querier.AgentBGPPolicyInfoQuerier,
) *agentQuerier {
return &agentQuerier{
nodeConfig: nodeConfig,
Expand All @@ -90,6 +93,7 @@ func NewAgentQuerier(
nplRange: nplRange,
memberlistCluster: memberlistCluster,
nodeLister: nodeLister,
bgpPolicyInfoQuerier: bgpPolicyInfoQuerier,
}
}

Expand Down Expand Up @@ -248,3 +252,8 @@ func (aq agentQuerier) GetAgentInfo(agentInfo *v1beta1.AntreaAgentInfo, partial
agentInfo.NodePortLocalPortRange = aq.nplRange
}
}

// GetBGPPolicyInfoQuerier returns AgentBGPPolicyInfoQuerier.
func (aq agentQuerier) GetBGPPolicyInfoQuerier() querier.AgentBGPPolicyInfoQuerier {
return aq.bgpPolicyInfoQuerier
}
14 changes: 14 additions & 0 deletions pkg/agent/querier/testing/mock_querier.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 187729c

Please sign in to comment.