Skip to content

Commit

Permalink
Add 'antctl get bgppolicy' command
Browse files Browse the repository at this point in the history
Signed-off-by: Kumar Atish <kumar.atish@broadcom.com>
  • Loading branch information
Atish-iaf committed Sep 13, 2024
1 parent 6210c2d commit 9fb88b7
Show file tree
Hide file tree
Showing 15 changed files with 319 additions and 55 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
13 changes: 13 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,18 @@ worker2 172.18.0.3 Alive
worker3 172.18.0.2 Dead
```

### BGP commands

`antctl` agent command `get bgppolicy` 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
```

### 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
20 changes: 20 additions & 0 deletions pkg/agent/apis/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,3 +190,23 @@ 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
}
2 changes: 2 additions & 0 deletions pkg/agent/apiserver/apiserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ 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/featuregates"
"antrea.io/antrea/pkg/agent/apiserver/handlers/memberlist"
"antrea.io/antrea/pkg/agent/apiserver/handlers/multicast"
Expand Down Expand Up @@ -97,6 +98,7 @@ 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))
}

func installAPIGroup(s *genericapiserver.GenericAPIServer, aq agentquerier.AgentQuerier, npq querier.AgentNetworkPolicyInfoQuerier, v4Enabled, v6Enabled bool) error {
Expand Down
51 changes: 51 additions & 0 deletions pkg/agent/apiserver/handlers/bgppolicy/handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// 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 bgpPolicyInfoQuerier == nil || 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,
}

if err := json.NewEncoder(w).Encode(bgpPolicyResp); err != nil {
w.WriteHeader(http.StatusInternalServerError)
klog.ErrorS(err, "Error when encoding BGPPolicyResp to json")
}
}
}
48 changes: 38 additions & 10 deletions pkg/agent/controller/bgp/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ const dummyKey = "dummyKey"
type bgpPolicyState struct {
// The local BGP server.
bgpServer bgp.Interface
// name of the BGP policy.
bgpPolicyName string
// The port on which the local BGP server listens.
listenPort int32
// The AS number used by the local BGP server.
Expand Down Expand Up @@ -112,7 +114,8 @@ type Controller struct {

secretInformer cache.SharedIndexInformer

bgpPolicyState *bgpPolicyState
bgpPolicyState *bgpPolicyState
bgpPolicyStateMutex sync.RWMutex

k8sClient kubernetes.Interface
bgpPeerPasswords map[string]string
Expand Down Expand Up @@ -306,6 +309,9 @@ func (c *Controller) syncBGPPolicy(ctx context.Context) error {
// Get the oldest BGPPolicy applied to the current Node as the effective BGPPolicy.
effectivePolicy := c.getEffectiveBGPPolicy()

c.bgpPolicyStateMutex.Lock()
defer c.bgpPolicyStateMutex.Unlock()

// When the effective BGPPolicy is nil, it means that there is no available BGPPolicy.
if effectivePolicy == nil {
// If the BGPPolicy state is nil, just return.
Expand All @@ -322,17 +328,18 @@ func (c *Controller) syncBGPPolicy(ctx context.Context) error {
}

klog.V(2).InfoS("Syncing BGPPolicy", "BGPPolicy", klog.KObj(effectivePolicy))
// Retrieve the listen port, local AS number and router ID from the effective BGPPolicy, and update them to the
// Retrieve the BGP policy name, listen port, local AS number and router ID from the effective BGPPolicy, and update them to the
// current state.
routerID, err := c.getRouterID()
if err != nil {
return err
}
bgpPolicyName := effectivePolicy.Name
listenPort := *effectivePolicy.Spec.ListenPort
localASN := effectivePolicy.Spec.LocalASN

// If the BGPPolicy state is nil, a new BGP server should be started, initialize the BGPPolicy state to store the
// new BGP server, listen port, local ASN, and router ID.
// new BGP server, BGP policy name, listen port, local ASN, and router ID.
// If the BGPPolicy is not nil, any of the listen port, local AS number, or router ID have changed, stop the current
// BGP server first and reset the BGPPolicy state to nil; then start a new BGP server and initialize the BGPPolicy
// state to store the new BGP server, listen port, local ASN, and router ID.
Expand Down Expand Up @@ -363,15 +370,19 @@ func (c *Controller) syncBGPPolicy(ctx context.Context) error {
return fmt.Errorf("failed to start BGP server: %w", err)
}

// Initialize the BGPPolicy state to store the new BGP server, listen port, local ASN, and router ID.
// Initialize the BGPPolicy state to store the new BGP server, BGP policy name, listen port, local ASN, and router ID.
c.bgpPolicyState = &bgpPolicyState{
bgpServer: bgpServer,
routerID: routerID,
listenPort: listenPort,
localASN: localASN,
routes: make(sets.Set[bgp.Route]),
peerConfigs: make(map[string]bgp.PeerConfig),
bgpServer: bgpServer,
bgpPolicyName: bgpPolicyName,
routerID: routerID,
listenPort: listenPort,
localASN: localASN,
routes: make(sets.Set[bgp.Route]),
peerConfigs: make(map[string]bgp.PeerConfig),
}
} else if c.bgpPolicyState.bgpPolicyName != bgpPolicyName {
// It may happen that only BGP policy name has changed in effective BGP policy.
c.bgpPolicyState.bgpPolicyName = bgpPolicyName
}

// Reconcile BGP peers.
Expand Down Expand Up @@ -931,3 +942,20 @@ 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

c.bgpPolicyStateMutex.RLock()
defer c.bgpPolicyStateMutex.RUnlock()

if c.bgpPolicyState != nil {
name = c.bgpPolicyState.bgpPolicyName
routerID = c.bgpPolicyState.routerID
localASN = c.bgpPolicyState.localASN
listenPort = c.bgpPolicyState.listenPort
}
return name, routerID, localASN, listenPort
}
Loading

0 comments on commit 9fb88b7

Please sign in to comment.