Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions calico-vpp-agent/cni/cni_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -538,10 +538,17 @@ func (s *Server) createRedirectToHostRules() (uint32, error) {
return types.InvalidID, fmt.Errorf("no main interface found")
}
for _, rule := range config.GetCalicoVppInitialConfig().RedirectToHostRules {
mainInterfaceAddress := mainInterface.GetAddress(vpplink.IPFamilyFromIP(rule.IP))
if mainInterfaceAddress == nil {
return types.InvalidID, fmt.Errorf("error installing rule %v no address found on uplink", rule)
}
err = s.vpp.AddSessionRedirect(&types.SessionRedirect{
FiveTuple: types.NewDst3Tuple(rule.Proto, net.ParseIP(rule.IP), rule.Port),
FiveTuple: types.NewDst3Tuple(rule.Proto, rule.IP, rule.Port),
TableIndex: index,
}, &types.RoutePath{Gw: config.VppHostPuntFakeGatewayAddress, SwIfIndex: mainInterface.TapSwIfIndex})
}, &types.RoutePath{
Gw: mainInterfaceAddress.IP,
SwIfIndex: mainInterface.TapSwIfIndex,
})
if err != nil {
return types.InvalidID, err
}
Expand Down
21 changes: 17 additions & 4 deletions calico-vpp-agent/routing/bgp_watcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -543,10 +543,14 @@ func (s *Server) WatchBGPPath(t *tomb.Tomb) error {
peer := localPeer.Peer
filters := localPeer.BGPFilterNames
// create a neighbor set to apply filter only on specific peer using a global policy
prefixLen := "/32"
if ip := net.ParseIP(peer.Conf.NeighborAddress); ip != nil && ip.To4() == nil {
prefixLen = "/128"
}
neighborSet := &bgpapi.DefinedSet{
Name: peer.Conf.NeighborAddress + "neighbor",
DefinedType: bgpapi.DefinedType_NEIGHBOR,
List: []string{peer.Conf.NeighborAddress + "/32"},
List: []string{peer.Conf.NeighborAddress + prefixLen},
}
err := s.BGPServer.AddDefinedSet(context.Background(), &bgpapi.AddDefinedSetRequest{
DefinedSet: neighborSet,
Expand Down Expand Up @@ -580,9 +584,18 @@ func (s *Server) WatchBGPPath(t *tomb.Tomb) error {
if err != nil {
return errors.Wrapf(err, "error cleaning peer filters up")
}
err = s.BGPServer.DeleteDefinedSet(context.Background(), &bgpapi.DeleteDefinedSetRequest{DefinedSet: s.bgpPeers[addr].NeighborSet, All: true})
if err != nil {
return errors.Wrapf(err, "error deleting prefix set")
if s.bgpPeers[addr] == nil {
s.log.Warnf("Trying to delete unknown BGP peer %s", addr)
} else if s.bgpPeers[addr].NeighborSet == nil {
s.log.Warnf("Trying to delete BGP peer %s with empty NeighborSet", addr)
} else {
err = s.BGPServer.DeleteDefinedSet(context.Background(), &bgpapi.DeleteDefinedSetRequest{
DefinedSet: s.bgpPeers[addr].NeighborSet,
All: true,
})
if err != nil {
return errors.Wrapf(err, "error deleting prefix set")
}
}
err := s.BGPServer.DeletePeer(
context.Background(),
Expand Down
38 changes: 32 additions & 6 deletions calico-vpp-agent/routing/routing_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import (

"github.com/projectcalico/vpp-dataplane/v3/calico-vpp-agent/common"
"github.com/projectcalico/vpp-dataplane/v3/calico-vpp-agent/watchers"
"github.com/projectcalico/vpp-dataplane/v3/config"
"github.com/projectcalico/vpp-dataplane/v3/vpplink"
)

Expand Down Expand Up @@ -114,17 +115,28 @@ func (s *Server) ServeRouting(t *tomb.Tomb) (err error) {
}

for t.Alive() {
globalConfig, err := s.getGoBGPGlobalConfig()
nodeIP4, nodeIP6 := common.GetBGPSpecAddresses(s.nodeBGPSpec)
globalConfig, err := s.getGoBGPGlobalConfig(*config.BGPServerMode)
if err != nil {
return fmt.Errorf("cannot get global configuration: %v", err)
}

err = s.BGPServer.StartBgp(context.Background(), &bgpapi.StartBgpRequest{Global: globalConfig})
if err != nil {
if err != nil && *config.BGPServerMode == config.BGPServerModeDualStack && nodeIP4 != nil {
s.log.Warnf("Failed to start BGP server in dualStack mode: %v. Retrying with IPv4-only listener", err)
globalConfig, err = s.getGoBGPGlobalConfig(config.BGPServerModeV4Only)
if err != nil {
return errors.Wrap(err, "cannot get IPv4-only BGP configuration for fallback")
}
err = s.BGPServer.StartBgp(context.Background(), &bgpapi.StartBgpRequest{Global: globalConfig})
if err != nil {
return errors.Wrap(err, "failed to start BGP server after IPv4-only fallback")
}
s.log.Warn("BGP server started in degraded IPv4-only mode because IPv6 listener failed")
} else if err != nil {
return errors.Wrap(err, "failed to start BGP server")
}

nodeIP4, nodeIP6 := common.GetBGPSpecAddresses(s.nodeBGPSpec)
if nodeIP4 != nil {
err = s.initialPolicySetting(false /* isv6 */)
if err != nil {
Expand Down Expand Up @@ -176,7 +188,7 @@ func (s *Server) getLogSeverityScreen() string {
return s.BGPConf.LogSeverityScreen
}

func (s *Server) getGoBGPGlobalConfig() (*bgpapi.Global, error) {
func (s *Server) getGoBGPGlobalConfig(mode config.BGPServerModeType) (*bgpapi.Global, error) {
var routerID string
listenAddresses := make([]string, 0)
asn := s.nodeBGPSpec.ASNumber
Expand All @@ -185,11 +197,25 @@ func (s *Server) getGoBGPGlobalConfig() (*bgpapi.Global, error) {
}

nodeIP4, nodeIP6 := common.GetBGPSpecAddresses(s.nodeBGPSpec)
if nodeIP6 != nil {
useIP4 := nodeIP4 != nil
useIP6 := nodeIP6 != nil

switch mode {
case config.BGPServerModeDualStack:
case config.BGPServerModeV4Only:
useIP6 = false
if !useIP4 {
return nil, fmt.Errorf("BGP server mode set to v4Only but no IPv4 node address configured")
}
default:
return nil, fmt.Errorf("unsupported BGP server mode %q", mode)
}

if useIP6 {
routerID = nodeIP6.String()
listenAddresses = append(listenAddresses, routerID)
}
if nodeIP4 != nil {
if useIP4 {
routerID = nodeIP4.String() // Override v6 ID if v4 is available
listenAddresses = append(listenAddresses, routerID)
}
Expand Down
41 changes: 33 additions & 8 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,22 @@ const (
BaseVppSideHardwareAddress = "02:ca:11:c0:fd:00"
)

type BGPServerModeType string

const (
BGPServerModeDualStack BGPServerModeType = "dualStack"
BGPServerModeV4Only BGPServerModeType = "v4Only"
)

var (
// fake constants for place where we need a pointer to true or false
True = true
False = false

NodeName = RequiredStringEnvVar("NODENAME")
LogLevel = EnvVar("CALICOVPP_LOG_LEVEL", logrus.InfoLevel, logrus.ParseLevel)
BGPLogLevel = EnvVar("CALICOVPP_BGP_LOG_LEVEL", apipb.SetLogLevelRequest_INFO, BGPLogLevelParse)
NodeName = RequiredStringEnvVar("NODENAME")
LogLevel = EnvVar("CALICOVPP_LOG_LEVEL", logrus.InfoLevel, logrus.ParseLevel)
BGPLogLevel = EnvVar("CALICOVPP_BGP_LOG_LEVEL", apipb.SetLogLevelRequest_INFO, BGPLogLevelParse)
BGPServerMode = EnvVar("CALICOVPP_BGP_SERVER_MODE", BGPServerModeDualStack, BGPServerModeParse)

ServiceCIDRs = PrefixListEnvVar("SERVICE_PREFIX")
IPSecIkev2Psk = StringEnvVar("CALICOVPP_IPSEC_IKEV2_PSK", "")
Expand Down Expand Up @@ -133,11 +141,17 @@ var (
HookScriptVppErrored,
}

Info = &VppManagerInfo{}
Info = &VppManagerInfo{
UplinkStatuses: make(map[string]UplinkStatus),
PhysicalNets: make(map[string]PhysicalNetwork),
}

// VppHostPuntFakeGatewayAddress is the fake gateway we use with a static neighbor
// in the punt table to route punted packets to the host
VppHostPuntFakeGatewayAddress = net.ParseIP("169.254.0.1")
// VppsideTap0Address is the IP address we add to the tap0
// so that it can receive ipv4 packets
VppsideTap0Address = PrefixEnvVar(
"CALICOVPP_TAP0_ADDR",
MustParseCIDR("169.254.0.1/32"),
)
)

func RunHook(hookScript *string, hookName string, params *VppManagerParams, log *logrus.Logger) {
Expand Down Expand Up @@ -271,7 +285,7 @@ func (u *UplinkInterfaceSpec) String() string {

type RedirectToHostRulesConfigType struct {
Port uint16 `json:"port,omitempty"`
IP string `json:"ip,omitempty"`
IP net.IP `json:"ip,omitempty"`
/* "tcp", "udp",... */
Proto types.IPProto `json:"proto,omitempty"`
}
Expand Down Expand Up @@ -567,6 +581,17 @@ type UplinkStatus struct {
// FakeNextHopIP6 is the computed next hop for v6 routes added
// in linux to (ServiceCIDR, podCIDR, etc...) towards this interface
FakeNextHopIP6 net.IP

UplinkAddresses []*net.IPNet
}

func (uplinkStatus *UplinkStatus) GetAddress(ipFamily vpplink.IPFamily) *net.IPNet {
for _, addr := range uplinkStatus.UplinkAddresses {
if vpplink.IPFamilyFromIPNet(addr) == ipFamily {
return addr
}
}
return nil
}

type PhysicalNetwork struct {
Expand Down
24 changes: 23 additions & 1 deletion config/config_parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,18 @@ func prefixParser(value string) (net.IPNet, error) {
func RequiredPrefixEnvVar(varName string) *net.IPNet {
return RequiredEnvVar(varName, net.IPNet{}, prefixParser)
}
func PrefixEnvVar(varName string) *net.IPNet { return EnvVar(varName, net.IPNet{}, prefixParser) }

func PrefixEnvVar(varName string, defaultValue *net.IPNet) *net.IPNet {
return EnvVar(varName, *defaultValue, prefixParser)
}

func MustParseCIDR(str string) *net.IPNet {
_, cidr, err := net.ParseCIDR(str)
if err != nil {
logrus.Fatalf("error parsing %s as cidr %v", str, err)
}
return cidr
}

func prefixListParser(value string) ([]*net.IPNet, error) {
chunks := strings.Split(value, ",")
Expand Down Expand Up @@ -257,3 +268,14 @@ func BGPLogLevelParse(lvl string) (apipb.SetLogLevelRequest_Level, error) {
var l apipb.SetLogLevelRequest_Level
return l, fmt.Errorf("not a valid logrus Level: %q", lvl)
}

func BGPServerModeParse(mode string) (BGPServerModeType, error) {
switch strings.ToLower(mode) {
case strings.ToLower(string(BGPServerModeDualStack)):
return BGPServerModeDualStack, nil
case "v4only":
return BGPServerModeV4Only, nil
}

return BGPServerModeDualStack, fmt.Errorf("not a valid BGP server mode: %q", mode)
}
Loading