Skip to content

Commit

Permalink
Initial support for collapsed core
Browse files Browse the repository at this point in the history
  • Loading branch information
Frostman committed Dec 13, 2023
1 parent 7b04d12 commit aad6b4d
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 42 deletions.
11 changes: 8 additions & 3 deletions api/wiring/v1alpha2/switch_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ func (sw *Switch) Default() {
}
}

func (sw *Switch) Validate(ctx context.Context, client validation.Client) (admission.Warnings, error) {
func (sw *Switch) Validate(ctx context.Context, client validation.Client, spineLeaf bool) (admission.Warnings, error) {
// TODO validate port group speeds against switch profile

if len(sw.Spec.VLANNamespaces) == 0 {
Expand All @@ -166,8 +166,13 @@ func (sw *Switch) Validate(ctx context.Context, client validation.Client) (admis
if sw.Spec.ProtocolIP == "" {
return nil, errors.Errorf("protocol IP is required")
}
if sw.Spec.Role.IsLeaf() && sw.Spec.VTEPIP == "" {
return nil, errors.Errorf("VTEP IP is required for leaf switches")
if sw.Spec.Role.IsLeaf() {
if spineLeaf && sw.Spec.VTEPIP == "" {
return nil, errors.Errorf("VTEP IP is required for leaf switches in spine-leaf mode")
}
if !spineLeaf && sw.Spec.VTEPIP != "" {
return nil, errors.Errorf("VTEP IP is not allowed for leaf switches in non spine-leaf mode")
}
}
if sw.Spec.Role.IsSpine() && sw.Spec.VTEPIP != "" {
return nil, errors.Errorf("VTEP IP is not allowed for spine switches")
Expand Down
2 changes: 1 addition & 1 deletion cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ func main() {
setupLog.Error(err, "unable to create webhook", "webhook", "Server")
os.Exit(1)
}
if err = switchWebhook.SetupWithManager(cfgBasedir, mgr); err != nil {
if err = switchWebhook.SetupWithManager(cfgBasedir, mgr, cfg); err != nil {
setupLog.Error(err, "unable to create webhook", "webhook", "Switch")
os.Exit(1)
}
Expand Down
70 changes: 43 additions & 27 deletions pkg/agent/dozer/bcm/plan.go
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,10 @@ func planLLDP(agent *agentapi.Agent, spec *dozer.Spec) error {
SystemDescription: stringPtr(fmt.Sprintf("Hedgehog: [control_vip=%s]", agent.Spec.Config.ControlVIP)),
}

if !agent.IsSpineLeaf() {
return nil
}

for _, conn := range agent.Spec.Connections {
if conn.Fabric != nil {
for _, link := range conn.Fabric.Links {
Expand Down Expand Up @@ -319,7 +323,7 @@ func planLoopbacks(agent *agentapi.Agent, spec *dozer.Spec) error {
},
}

if agent.Spec.Switch.Role.IsLeaf() {
if agent.IsSpineLeaf() && agent.Spec.Switch.Role.IsLeaf() {
ip, ipNet, err = net.ParseCIDR(agent.Spec.Switch.VTEPIP)
if err != nil {
return errors.Wrapf(err, "failed to parse vtep ip %s", agent.Spec.Switch.VTEPIP)
Expand All @@ -345,6 +349,10 @@ func planLoopbacks(agent *agentapi.Agent, spec *dozer.Spec) error {
}

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

spec.RouteMaps[ROUTE_MAP_BLOCK_EVPN_DEFAULT_REMOTE] = &dozer.SpecRouteMap{
Statements: map[string]*dozer.SpecRouteMapStatement{
fmt.Sprintf("%d", ROUTE_MAP_MAX_STATEMENT): {
Expand Down Expand Up @@ -532,7 +540,7 @@ func planExternals(agent *agentapi.Agent, spec *dozer.Spec) error {
ImportVRFs: map[string]*dozer.SpecVRFBGPImportVRF{},
},
L2VPNEVPN: dozer.SpecVRFBGPL2VPNEVPN{
Enabled: true,
Enabled: agent.IsSpineLeaf(),
AdvertiseDefaultGw: boolPtr(true),
},
Neighbors: map[string]*dozer.SpecVRFBGPNeighbor{},
Expand Down Expand Up @@ -731,7 +739,7 @@ func planDefaultVRFWithBGP(agent *agentapi.Agent, spec *dozer.Spec) error {
MaxPaths: uint32Ptr(getMaxPaths(agent)),
},
L2VPNEVPN: dozer.SpecVRFBGPL2VPNEVPN{
Enabled: true,
Enabled: agent.IsSpineLeaf(),
AdvertiseAllVNI: boolPtr(true),
},
}
Expand All @@ -744,6 +752,10 @@ func planDefaultVRFWithBGP(agent *agentapi.Agent, spec *dozer.Spec) error {
}

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

ip, _, err := net.ParseCIDR(agent.Spec.Switch.VTEPIP)
if err != nil {
return errors.Wrapf(err, "failed to parse vtep ip %s", agent.Spec.Switch.VTEPIP)
Expand Down Expand Up @@ -913,8 +925,6 @@ func planVPCs(agent *agentapi.Agent, spec *dozer.Spec) error {
Description: stringPtr(fmt.Sprintf("VPC %s IRB", vpcName)),
}

spec.SuppressVLANNeighs[irbIface] = &dozer.SpecSuppressVLANNeigh{}

if spec.VRFs[vrfName] == nil {
spec.VRFs[vrfName] = &dozer.SpecVRF{}
}
Expand Down Expand Up @@ -942,7 +952,7 @@ func planVPCs(agent *agentapi.Agent, spec *dozer.Spec) error {
ImportVRFs: map[string]*dozer.SpecVRFBGPImportVRF{},
},
L2VPNEVPN: dozer.SpecVRFBGPL2VPNEVPN{
Enabled: true,
Enabled: agent.IsSpineLeaf(),
AdvertiseIPv4Unicast: boolPtr(true),
},
}
Expand All @@ -952,17 +962,21 @@ func planVPCs(agent *agentapi.Agent, spec *dozer.Spec) error {
}
spec.VRFs[vrfName].Interfaces[irbIface] = &dozer.SpecVRFInterface{}

vpcVNI := agent.Spec.VNIs[vpcName]
if vpcVNI == 0 {
return errors.Errorf("VNI for VPC %s not found", vpcName)
}
spec.VRFVNIMap[vrfName] = &dozer.SpecVRFVNIEntry{
VNI: uint32Ptr(vpcVNI),
}
spec.VXLANTunnelMap[fmt.Sprintf("map_%d_%s", vpcVNI, irbIface)] = &dozer.SpecVXLANTunnelMap{
VTEP: stringPtr(VTEP_FABRIC),
VNI: uint32Ptr(vpcVNI),
VLAN: uint16Ptr(irbVLAN),
if agent.IsSpineLeaf() {
spec.SuppressVLANNeighs[irbIface] = &dozer.SpecSuppressVLANNeigh{}

vpcVNI := agent.Spec.VNIs[vpcName]
if vpcVNI == 0 {
return errors.Errorf("VNI for VPC %s not found", vpcName)
}
spec.VRFVNIMap[vrfName] = &dozer.SpecVRFVNIEntry{
VNI: uint32Ptr(vpcVNI),
}
spec.VXLANTunnelMap[fmt.Sprintf("map_%d_%s", vpcVNI, irbIface)] = &dozer.SpecVXLANTunnelMap{
VTEP: stringPtr(VTEP_FABRIC),
VNI: uint32Ptr(vpcVNI),
VLAN: uint16Ptr(irbVLAN),
}
}
}

Expand Down Expand Up @@ -1197,17 +1211,19 @@ func planVPCSubnet(agent *agentapi.Agent, spec *dozer.Spec, vpcName, subnetName

spec.VRFs[vrfName].Interfaces[subnetIface] = &dozer.SpecVRFInterface{}

subnetVNI := agent.Spec.VNIs[fmt.Sprintf("%s/%s", vpcName, subnetName)]
if subnetVNI == 0 {
return errors.Errorf("VNI for VPC %s subnet %s not found", vpcName, subnetName)
}
spec.VXLANTunnelMap[fmt.Sprintf("map_%d_%s", subnetVNI, subnetIface)] = &dozer.SpecVXLANTunnelMap{
VTEP: stringPtr(VTEP_FABRIC),
VNI: uint32Ptr(subnetVNI),
VLAN: uint16Ptr(subnetVLAN),
}
if agent.IsSpineLeaf() {
spec.SuppressVLANNeighs[subnetIface] = &dozer.SpecSuppressVLANNeigh{}

spec.SuppressVLANNeighs[subnetIface] = &dozer.SpecSuppressVLANNeigh{}
subnetVNI := agent.Spec.VNIs[fmt.Sprintf("%s/%s", vpcName, subnetName)]
if subnetVNI == 0 {
return errors.Errorf("VNI for VPC %s subnet %s not found", vpcName, subnetName)
}
spec.VXLANTunnelMap[fmt.Sprintf("map_%d_%s", subnetVNI, subnetIface)] = &dozer.SpecVXLANTunnelMap{
VTEP: stringPtr(VTEP_FABRIC),
VNI: uint32Ptr(subnetVNI),
VLAN: uint16Ptr(subnetVLAN),
}
}

if subnet.DHCP.Enable {
dhcpRelayIP, _, err := net.ParseCIDR(agent.Spec.Config.ControlVIP)
Expand Down
17 changes: 10 additions & 7 deletions pkg/ctrl/agent/agent_ctrl.go
Original file line number Diff line number Diff line change
Expand Up @@ -397,15 +397,18 @@ func (r *AgentReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl
}

vnis := map[string]uint32{}
for _, vpc := range vpcList.Items {
if _, exists := vpcs[vpc.Name]; !exists {
continue
}

vnis[vpc.Name] = vpc.Status.VNI
if r.Cfg.FabricMode == config.FabricModeCollapsedCore {
for _, vpc := range vpcList.Items {
if _, exists := vpcs[vpc.Name]; !exists {
continue
}

vnis[vpc.Name] = vpc.Status.VNI

for subnetName := range vpc.Spec.Subnets {
vnis[fmt.Sprintf("%s/%s", vpc.Name, subnetName)] = vpc.Status.SubnetVNIs[subnetName]
for subnetName := range vpc.Spec.Subnets {
vnis[fmt.Sprintf("%s/%s", vpc.Name, subnetName)] = vpc.Status.SubnetVNIs[subnetName]
}
}
}

Expand Down
9 changes: 6 additions & 3 deletions pkg/webhook/switchh/switch_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (

"github.com/pkg/errors"
wiringapi "go.githedgehog.com/fabric/api/wiring/v1alpha2"
"go.githedgehog.com/fabric/pkg/manager/config"
"go.githedgehog.com/fabric/pkg/manager/validation"
"k8s.io/apimachinery/pkg/api/equality"
"k8s.io/apimachinery/pkg/runtime"
Expand All @@ -17,13 +18,15 @@ type SwitchWebhook struct {
client.Client
Scheme *runtime.Scheme
Validation validation.Client
Cfg *config.Fabric
}

func SetupWithManager(cfgBasedir string, mgr ctrl.Manager) error {
func SetupWithManager(cfgBasedir string, mgr ctrl.Manager, cfg *config.Fabric) error {
w := &SwitchWebhook{
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
Validation: validation.WithCtrlRuntime(mgr.GetClient()),
Cfg: cfg,
}

return ctrl.NewWebhookManagedBy(mgr).
Expand Down Expand Up @@ -54,7 +57,7 @@ func (w *SwitchWebhook) Default(ctx context.Context, obj runtime.Object) error {
func (w *SwitchWebhook) ValidateCreate(ctx context.Context, obj runtime.Object) (warnings admission.Warnings, err error) {
sw := obj.(*wiringapi.Switch)

warns, err := sw.Validate(ctx, w.Validation)
warns, err := sw.Validate(ctx, w.Validation, w.Cfg.FabricMode == config.FabricModeSpineLeaf)
if err != nil {
return warns, err
}
Expand All @@ -70,7 +73,7 @@ func (w *SwitchWebhook) ValidateUpdate(ctx context.Context, oldObj runtime.Objec
return nil, errors.Errorf("switch location is immutable")
}

warns, err := newSw.Validate(ctx, w.Validation)
warns, err := newSw.Validate(ctx, w.Validation, w.Cfg.FabricMode == config.FabricModeSpineLeaf)
if err != nil {
return warns, err
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/webhook/webhook_suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ var _ = BeforeSuite(func() {
err = server.SetupWithManager("", mgr) // TODO cfgBasedir
Expect(err).NotTo(HaveOccurred())

err = switchh.SetupWithManager("", mgr) // TODO cfgBasedir
err = switchh.SetupWithManager("", mgr, nil) // TODO cfgBasedir
Expect(err).NotTo(HaveOccurred())

err = vpc.SetupWithManager("", mgr, nil) // TODO cfgBasedir
Expand Down

0 comments on commit aad6b4d

Please sign in to comment.