Skip to content

Commit

Permalink
Prevent vpc loopback subnet leakage
Browse files Browse the repository at this point in the history
  • Loading branch information
Frostman committed Dec 15, 2023
1 parent 8240dfc commit a241f66
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 8 deletions.
1 change: 1 addition & 0 deletions api/agent/v1alpha2/agent_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ type AgentSpecConfig struct {
CollapsedCore *AgentSpecConfigCollapsedCore `json:"collapsedCore,omitempty"`
SpineLeaf *AgentSpecConfigSpineLeaf `json:"spineLeaf,omitempty"`
BaseVPCCommunity string `json:"baseVPCCommunity,omitempty"`
VPCLoopbackSubnet string `json:"vpcLoopbackSubnet,omitempty"`
}

type AgentSpecConfigCollapsedCore struct{}
Expand Down
2 changes: 2 additions & 0 deletions config/crd/bases/agent.githedgehog.com_agents.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ spec:
type: string
spineLeaf:
type: object
vpcLoopbackSubnet:
type: string
vpcPeeringDisabled:
type: boolean
type: object
Expand Down
1 change: 1 addition & 0 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ _Appears in:_
| `collapsedCore` _[AgentSpecConfigCollapsedCore](#agentspecconfigcollapsedcore)_ | |
| `spineLeaf` _[AgentSpecConfigSpineLeaf](#agentspecconfigspineleaf)_ | |
| `baseVPCCommunity` _string_ | |
| `vpcLoopbackSubnet` _string_ | |


#### AgentSpecConfigCollapsedCore
Expand Down
39 changes: 33 additions & 6 deletions pkg/agent/dozer/bcm/plan.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ const (
ROUTE_MAP_BLOCK_EVPN_DEFAULT_REMOTE = "evpn-default-remote-block"
ROUTE_MAP_MAX_STATEMENT = 65535
PREFIX_LIST_ANY = "any-prefix"
PREFIX_LIST_VPC_LO = "vpc-lo-prefix"
)

func (p *broadcomProcessor) PlanDesiredState(ctx context.Context, agent *agentapi.Agent) (*dozer.Spec, error) {
Expand Down Expand Up @@ -938,6 +939,18 @@ func ipnsVrfName(ipnsName string) string {
}

func planVPCs(agent *agentapi.Agent, spec *dozer.Spec) error {
spec.PrefixLists[PREFIX_LIST_VPC_LO] = &dozer.SpecPrefixList{
Prefixes: map[uint32]*dozer.SpecPrefixListEntry{
10: {
Prefix: dozer.SpecPrefixListPrefix{
Prefix: agent.Spec.Config.VPCLoopbackSubnet,
Le: 32,
},
Action: dozer.SpecPrefixListActionPermit,
},
},
}

for vpcName := range agent.Spec.VPCs {
vrfName := vpcVrfName(vpcName)

Expand Down Expand Up @@ -992,6 +1005,12 @@ func planVPCs(agent *agentapi.Agent, spec *dozer.Spec) error {
stampVPCRouteMap := stampVPCRouteMapName(vpcName)
spec.RouteMaps[stampVPCRouteMap] = &dozer.SpecRouteMap{
Statements: map[string]*dozer.SpecRouteMapStatement{
"1": {
Conditions: dozer.SpecRouteMapConditions{
MatchPrefixList: stringPtr(PREFIX_LIST_VPC_LO),
},
Result: dozer.SpecRouteMapResultReject,
},
"10": {
SetCommunities: []string{vpcComm},
Result: dozer.SpecRouteMapResultAccept,
Expand Down Expand Up @@ -1025,7 +1044,9 @@ func planVPCs(agent *agentapi.Agent, spec *dozer.Spec) error {
dozer.SpecVRFBGPTableConnectionConnected: {
ImportPolicies: []string{stampVPCRouteMap},
},
dozer.SpecVRFBGPTableConnectionStatic: {},
dozer.SpecVRFBGPTableConnectionStatic: {
ImportPolicies: []string{stampVPCRouteMap},
},
}
spec.VRFs[vrfName].Interfaces[irbIface] = &dozer.SpecVRFInterface{}

Expand Down Expand Up @@ -1466,7 +1487,7 @@ func planLoopbackWorkaround(agent *agentapi.Agent, spec *dozer.Spec, peeringName
return "", "", "", "", errors.Errorf("workaround link port %s for peering %s not found", ports[1], peeringName)
}

ip1, ip2, err := vpcWorkaroundIPs("172.30.224.0/19", vlan) // TODO move to config
ip1, ip2, err := vpcWorkaroundIPs(agent, vlan)
if err != nil {
return "", "", "", "", errors.Wrapf(err, "failed to get workaround IPs for peering")
}
Expand Down Expand Up @@ -1512,21 +1533,27 @@ func getMaxPaths(agent *agentapi.Agent) uint32 {
}

// TODO test
func vpcWorkaroundIPs(subnet string, vlan uint16) (string, string, error) {
_, ipNet, err := net.ParseCIDR(subnet)
func vpcWorkaroundIPs(agent *agentapi.Agent, vlan uint16) (string, string, error) {
_, ipNet, err := net.ParseCIDR(agent.Spec.Config.VPCLoopbackSubnet)
if err != nil {
return "", "", err
}
prefixLen, _ := ipNet.Mask.Size()
if prefixLen < 19 {
return "", "", errors.Errorf("subnet should be at least /19")
if prefixLen > 20 {
return "", "", errors.Errorf("subnet should be at least /20")
}
ip := ipNet.IP.To4()
ip[2] += byte(vlan / 128)
ip[3] += byte(vlan % 128 * 2)

res1 := ip.String()

ip[3] += 1

if !ipNet.Contains(ip) {
return "", "", errors.Errorf("subnet %s is too small for VLAN %d", agent.Spec.Config.VPCLoopbackSubnet, vlan)
}

res2 := ip.String()

return res1, res2, nil
Expand Down
5 changes: 3 additions & 2 deletions pkg/ctrl/agent/agent_ctrl.go
Original file line number Diff line number Diff line change
Expand Up @@ -449,8 +449,9 @@ func (r *AgentReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl
agent.Spec.StatusUpdates = statusUpdates

agent.Spec.Config = agentapi.AgentSpecConfig{
ControlVIP: r.Cfg.ControlVIP,
BaseVPCCommunity: r.Cfg.BaseVPCCommunity,
ControlVIP: r.Cfg.ControlVIP,
BaseVPCCommunity: r.Cfg.BaseVPCCommunity,
VPCLoopbackSubnet: r.Cfg.VPCLoopbackSubnet,
}
if r.Cfg.FabricMode == config.FabricModeCollapsedCore {
agent.Spec.Config.CollapsedCore = &agentapi.AgentSpecConfigCollapsedCore{}
Expand Down
4 changes: 4 additions & 0 deletions pkg/manager/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ type Fabric struct {
DHCPDConfigKey string `json:"dhcpdConfigKey,omitempty"`
FabricMode FabricMode `json:"fabricMode,omitempty"`
BaseVPCCommunity string `json:"baseVPCCommunity,omitempty"`
VPCLoopbackSubnet string `json:"vpcLoopbackSubnet,omitempty"`

reservedSubnets []*net.IPNet
}
Expand Down Expand Up @@ -134,6 +135,9 @@ func Load(basedir string) (*Fabric, error) {
if cfg.BaseVPCCommunity == "" {
return nil, errors.Errorf("config: baseVPCCommunity is required")
}
if cfg.VPCLoopbackSubnet == "" {
return nil, errors.Errorf("config: vpcLoopbackSubnet is required")
}

// TODO validate format of all fields

Expand Down

0 comments on commit a241f66

Please sign in to comment.