diff --git a/pkg/evpn/bridge.go b/pkg/evpn/bridge.go index 211ae6f6..9d7efcbc 100644 --- a/pkg/evpn/bridge.go +++ b/pkg/evpn/bridge.go @@ -12,6 +12,7 @@ import ( "sort" "github.com/google/uuid" + "github.com/opiproject/opi-evpn-bridge/pkg/models" pb "github.com/opiproject/opi-api/network/evpn-gw/v1alpha1/gen/go" @@ -51,6 +52,8 @@ func (s *Server) CreateLogicalBridge(ctx context.Context, in *pb.CreateLogicalBr if err := s.netlinkCreateLogicalBridge(ctx, in); err != nil { return nil, err } + // translate object + log.Printf("new object %v", models.NewBridge(in.LogicalBridge)) // save object to the database response := protoClone(in.LogicalBridge) response.Status = &pb.LogicalBridgeStatus{OperStatus: pb.LBOperStatus_LB_OPER_STATUS_UP} diff --git a/pkg/evpn/port.go b/pkg/evpn/port.go index 35e846f5..dfde4956 100644 --- a/pkg/evpn/port.go +++ b/pkg/evpn/port.go @@ -13,7 +13,7 @@ import ( "sort" "github.com/google/uuid" - // "github.com/vishvananda/netlink" + "github.com/opiproject/opi-evpn-bridge/pkg/models" pb "github.com/opiproject/opi-api/network/evpn-gw/v1alpha1/gen/go" @@ -108,6 +108,8 @@ func (s *Server) CreateBridgePort(ctx context.Context, in *pb.CreateBridgePortRe fmt.Printf("Failed to up iface link: %v", err) return nil, err } + // translate object + log.Printf("new object %v", models.NewPort(in.BridgePort)) // save object to the database response := protoClone(in.BridgePort) response.Status = &pb.BridgePortStatus{OperStatus: pb.BPOperStatus_BP_OPER_STATUS_UP} diff --git a/pkg/evpn/svi.go b/pkg/evpn/svi.go index ded33ab2..ab4c0834 100644 --- a/pkg/evpn/svi.go +++ b/pkg/evpn/svi.go @@ -13,6 +13,7 @@ import ( "sort" "github.com/google/uuid" + "github.com/opiproject/opi-evpn-bridge/pkg/models" pb "github.com/opiproject/opi-api/network/evpn-gw/v1alpha1/gen/go" @@ -71,6 +72,8 @@ func (s *Server) CreateSvi(ctx context.Context, in *pb.CreateSviRequest) (*pb.Sv if err := s.frrCreateSviRequest(ctx, in, vrfName, vlanName); err != nil { return nil, err } + // translate object + log.Printf("new object %v", models.NewSvi(in.Svi)) // save object to the database response := protoClone(in.Svi) response.Status = &pb.SviStatus{OperStatus: pb.SVIOperStatus_SVI_OPER_STATUS_UP} diff --git a/pkg/evpn/vrf.go b/pkg/evpn/vrf.go index 8b2b00ca..3883a59f 100644 --- a/pkg/evpn/vrf.go +++ b/pkg/evpn/vrf.go @@ -14,6 +14,7 @@ import ( "sort" "github.com/google/uuid" + "github.com/opiproject/opi-evpn-bridge/pkg/models" pb "github.com/opiproject/opi-api/network/evpn-gw/v1alpha1/gen/go" @@ -68,6 +69,8 @@ func (s *Server) CreateVrf(ctx context.Context, in *pb.CreateVrfRequest) (*pb.Vr if err := s.frrCreateVrfRequest(ctx, in); err != nil { return nil, err } + // translate object + log.Printf("new object %v", models.NewVrf(in.Vrf)) // save object to the database response := protoClone(in.Vrf) response.Status = &pb.VrfStatus{LocalAs: 4, RoutingTable: tableID, Rmac: mac} diff --git a/pkg/models/bridge.go b/pkg/models/bridge.go new file mode 100644 index 00000000..b6aee2e9 --- /dev/null +++ b/pkg/models/bridge.go @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (c) 2022-2023 Dell Inc, or its subsidiaries. + +// Package models translates frontend protobuf messages to backend messages +package models + +import ( + // "encoding/binary" + "net" + + pb "github.com/opiproject/opi-api/network/evpn-gw/v1alpha1/gen/go" +) + +// Bridge object, separate from protobuf for decoupling +type Bridge struct { + Vni uint32 + VlanId uint32 + VtepIp net.IPNet +} + +// NewBridge creates new SVI object from protobuf message +func NewBridge(in *pb.LogicalBridge) *Bridge { + // vtepip := make(net.IP, 4) + // binary.BigEndian.PutUint32(vtepip, in.Spec.VtepIpPrefix.Addr.GetV4Addr()) + // vip := net.IPNet{IP: vtepip, Mask: net.CIDRMask(int(in.Spec.VtepIpPrefix.Len), 32)} + // TODO: Vni: *in.Spec.Vni + return &Bridge{VlanId: in.Spec.VlanId} +} + +// ToPb transforms SVI object to protobuf message +func (in *Bridge) ToPb() (*pb.LogicalBridge, error) { + bridge := &pb.LogicalBridge{ + Spec: &pb.LogicalBridgeSpec{ + Vni: &in.Vni, + VlanId: in.VlanId, + }, + Status: &pb.LogicalBridgeStatus{ + OperStatus: pb.LBOperStatus_LB_OPER_STATUS_UP, + }, + } + // TODO: add VtepIpPrefix + return bridge, nil +} diff --git a/pkg/models/port.go b/pkg/models/port.go new file mode 100644 index 00000000..f726d59b --- /dev/null +++ b/pkg/models/port.go @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (c) 2022-2023 Dell Inc, or its subsidiaries. + +// Package models translates frontend protobuf messages to backend messages +package models + +import ( + "net" + + pb "github.com/opiproject/opi-api/network/evpn-gw/v1alpha1/gen/go" +) + +type BridgePortType int32 + +const ( + UNKNOWN BridgePortType = iota + ACCESS + TRUNK +) + +// Port object, separate from protobuf for decoupling +type Port struct { + Ptype BridgePortType + MacAddress net.HardwareAddr + LogicalBridgeRefKeys []string +} + +// NewPort creates new SVI object from protobuf message +func NewPort(in *pb.BridgePort) *Port { + mac := net.HardwareAddr(in.Spec.MacAddress) + return &Port{Ptype: BridgePortType(in.Spec.Ptype), MacAddress: mac, LogicalBridgeRefKeys: in.Spec.LogicalBridges} +} + +// ToPb transforms SVI object to protobuf message +func (in *Port) ToPb() (*pb.BridgePort, error) { + port := &pb.BridgePort{ + Spec: &pb.BridgePortSpec{ + Ptype: pb.BridgePortType(in.Ptype), + MacAddress: in.MacAddress, + LogicalBridges: in.LogicalBridgeRefKeys, + }, + Status: &pb.BridgePortStatus{ + OperStatus: pb.BPOperStatus_BP_OPER_STATUS_UP, + }, + } + // TODO: add VtepIpPrefix + return port, nil +} diff --git a/pkg/models/svi.go b/pkg/models/svi.go new file mode 100644 index 00000000..896756ca --- /dev/null +++ b/pkg/models/svi.go @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (c) 2022-2023 Dell Inc, or its subsidiaries. + +// Package models translates frontend protobuf messages to backend messages +package models + +import ( + "encoding/binary" + "net" + + pb "github.com/opiproject/opi-api/network/evpn-gw/v1alpha1/gen/go" +) + +// Svi object, separate from protobuf for decoupling +type Svi struct { + VrfRefKey string + LogicalBridgeRefKey string + MacAddress net.HardwareAddr + GwIP []net.IPNet + EnableBgp bool + RemoteAs uint32 +} + +// NewSvi creates new SVI object from protobuf message +func NewSvi(in *pb.Svi) *Svi { + mac := net.HardwareAddr(in.Spec.MacAddress) + gwIPList := []net.IPNet{} + for _, item := range in.Spec.GwIpPrefix { + myip := make(net.IP, 4) + binary.BigEndian.PutUint32(myip, item.Addr.GetV4Addr()) + gip := net.IPNet{IP: myip, Mask: net.CIDRMask(int(item.Len), 32)} + gwIPList = append(gwIPList, gip) + } + svi := &Svi{ + VrfRefKey: in.Spec.Vrf, + LogicalBridgeRefKey: in.Spec.LogicalBridge, + MacAddress: mac, + GwIP: gwIPList, + EnableBgp: in.Spec.EnableBgp, + RemoteAs: in.Spec.RemoteAs, + } + return svi +} + +// ToPb transforms SVI object to protobuf message +func (in *Svi) ToPb() (*pb.Svi, error) { + svi := &pb.Svi{ + Spec: &pb.SviSpec{ + Vrf: in.VrfRefKey, + LogicalBridge: in.LogicalBridgeRefKey, + MacAddress: in.MacAddress, + EnableBgp: in.EnableBgp, + RemoteAs: in.RemoteAs, + }, + Status: &pb.SviStatus{ + OperStatus: pb.SVIOperStatus_SVI_OPER_STATUS_UP, + }, + } + // TODO: add GwIpPrefix + return svi, nil +} diff --git a/pkg/models/vrf.go b/pkg/models/vrf.go new file mode 100644 index 00000000..3117011d --- /dev/null +++ b/pkg/models/vrf.go @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (c) 2022-2023 Dell Inc, or its subsidiaries. + +// Package models translates frontend protobuf messages to backend messages +package models + +import ( + "encoding/binary" + "net" + + pb "github.com/opiproject/opi-api/network/evpn-gw/v1alpha1/gen/go" +) + +// Vrf object, separate from protobuf for decoupling +type Vrf struct { + Vni uint32 + LoopbackIP net.IPNet + VtepIP net.IPNet +} + +// NewVrf creates new VRF object from protobuf message +func NewVrf(in *pb.Vrf) *Vrf { + loopip := make(net.IP, 4) + binary.BigEndian.PutUint32(loopip, in.Spec.LoopbackIpPrefix.Addr.GetV4Addr()) + lip := net.IPNet{IP: loopip, Mask: net.CIDRMask(int(in.Spec.LoopbackIpPrefix.Len), 32)} + // vtepip := make(net.IP, 4) + // binary.BigEndian.PutUint32(vtepip, in.Spec.VtepIpPrefix.Addr.GetV4Addr()) + // vip := net.IPNet{IP: vtepip, Mask: net.CIDRMask(int(in.Spec.VtepIpPrefix.Len), 32)} + return &Vrf{LoopbackIP: lip} +} + +// ToPb transforms VRF object to protobuf message +func (in *Vrf) ToPb() (*pb.Vrf, error) { + vrf := &pb.Vrf{ + Spec: &pb.VrfSpec{ + Vni: &in.Vni, + }, + Status: &pb.VrfStatus{ + LocalAs: 4, + }, + } + // TODO: add LocalAs, LoopbackIP, VtepIP + return vrf, nil +}