Skip to content

Commit

Permalink
Handle gw conn in the agent
Browse files Browse the repository at this point in the history
Signed-off-by: Sergei Lukianov <[email protected]>
  • Loading branch information
Frostman committed Feb 11, 2025
1 parent 17c0fed commit 6f5133a
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 0 deletions.
1 change: 1 addition & 0 deletions api/agent/v1beta1/agent_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ type AgentSpecConfig struct {
ESLAGESIPrefix string `json:"eslagESIPrefix,omitempty"`
DefaultMaxPathsEBGP uint32 `json:"defaultMaxPathsEBGP,omitempty"`
MCLAGSessionSubnet string `json:"mclagSessionSubnet,omitempty"`
GatewayASN uint32 `json:"gatewayASN,omitempty"`
}

type AgentSpecConfigCollapsedCore struct{}
Expand Down
5 changes: 5 additions & 0 deletions api/meta/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ type FabricConfig struct {
DefaultMaxPathsEBGP uint32 `json:"defaultMaxPathsEBGP,omitempty"`
AllowExtraSwitchProfiles bool `json:"allowExtraSwitchProfiles,omitempty"`
MCLAGSessionSubnet string `json:"mclagSessionSubnet,omitempty"`
GatewayASN uint32 `json:"gatewayASN,omitempty"` // Temporarily assuming that all GWs are in the same AS

reservedSubnets []*net.IPNet
}
Expand Down Expand Up @@ -253,6 +254,10 @@ func (cfg *FabricConfig) Init() (*FabricConfig, error) {
return nil, errors.Errorf("config: defaultMaxPathsEBGP is required")
}

if cfg.GatewayASN == 0 {
return nil, errors.Errorf("config: gatewayASN is required")
}

// TODO validate format of all fields

// slog.Debug("Loaded Fabric config", "data", spew.Sdump(cfg))
Expand Down
3 changes: 3 additions & 0 deletions config/crd/bases/agent.githedgehog.com_agents.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,9 @@ spec:
type: string
fabricMTU:
type: integer
gatewayASN:
format: int32
type: integer
mclagSessionSubnet:
type: string
serverFacingMTUOffset:
Expand Down
79 changes: 79 additions & 0 deletions pkg/agent/dozer/bcm/plan.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,11 @@ func (p *BroadcomProcessor) PlanDesiredState(_ context.Context, agent *agentapi.
return nil, errors.Wrap(err, "failed to plan fabric connections")
}

err = planGatewayConnections(agent, spec)
if err != nil {
return nil, errors.Wrap(err, "failed to plan gateway connections")
}

err = planVPCLoopbacks(agent, spec)
if err != nil {
return nil, errors.Wrap(err, "failed to plan VPC loopbacks")
Expand Down Expand Up @@ -429,6 +434,80 @@ func planFabricConnections(agent *agentapi.Agent, spec *dozer.Spec) error {
return nil
}

func planGatewayConnections(agent *agentapi.Agent, spec *dozer.Spec) error {
if !agent.IsSpineLeaf() {
return nil
}

for connName, conn := range agent.Spec.Connections {
if conn.Gateway == nil {
continue
}

if agent.Spec.Config.GatewayASN == 0 {
return errors.Errorf("gateway ASN not set")
}

for _, link := range conn.Gateway.Links {
port := ""
ipStr := ""
remote := ""
// peer := ""
peerIP := ""
if link.Spine.DeviceName() == agent.Name {
port = link.Spine.LocalPortName()
ipStr = link.Spine.IP
remote = link.Gateway.Port
// peer = link.Gateway.DeviceName()
peerIP = link.Gateway.IP
} else {
continue
}

if ipStr == "" {
return errors.Errorf("no IP found for gateway conn %s", connName)
}

ip, ipNet, err := net.ParseCIDR(ipStr)
if err != nil {
return errors.Wrapf(err, "failed to parse gateway conn ip %s", ipStr)
}
ipPrefixLen, _ := ipNet.Mask.Size()

spec.Interfaces[port] = &dozer.SpecInterface{
Enabled: pointer.To(true),
Description: pointer.To(fmt.Sprintf("Gateway %s %s", remote, connName)),
Speed: getPortSpeed(agent, port),
Subinterfaces: map[uint32]*dozer.SpecSubinterface{
0: {
IPs: map[string]*dozer.SpecInterfaceIP{
ip.String(): {
PrefixLen: pointer.To(uint8(ipPrefixLen)), //nolint:gosec
},
},
},
},
}

ip, _, err = net.ParseCIDR(peerIP)
if err != nil {
return errors.Wrapf(err, "failed to parse gateway conn peer ip %s", peerIP)
}

spec.VRFs[VRFDefault].BGP.Neighbors[ip.String()] = &dozer.SpecVRFBGPNeighbor{
Enabled: pointer.To(true),
Description: pointer.To(fmt.Sprintf("Gateway %s %s", remote, connName)),
RemoteAS: pointer.To(agent.Spec.Config.GatewayASN), // TODO load peer GW and get ASN from it
IPv4Unicast: pointer.To(true),
L2VPNEVPN: pointer.To(true),
L2VPNEVPNAllowOwnAS: pointer.To(true),
}
}
}

return nil
}

func planVPCLoopbacks(agent *agentapi.Agent, spec *dozer.Spec) error { //nolint:unparam
for connName, conn := range agent.Spec.Connections {
if conn.VPCLoopback == nil {
Expand Down
1 change: 1 addition & 0 deletions pkg/ctrl/agent/agent_ctrl.go
Original file line number Diff line number Diff line change
Expand Up @@ -684,6 +684,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
ESLAGESIPrefix: r.Cfg.ESLAGESIPrefix,
DefaultMaxPathsEBGP: r.Cfg.DefaultMaxPathsEBGP,
MCLAGSessionSubnet: r.Cfg.MCLAGSessionSubnet,
GatewayASN: r.Cfg.GatewayASN,
}
if r.Cfg.FabricMode == meta.FabricModeCollapsedCore {
agent.Spec.Config.CollapsedCore = &agentapi.AgentSpecConfigCollapsedCore{}
Expand Down

0 comments on commit 6f5133a

Please sign in to comment.