[VOL-5458] - Multi NNI support in VGC
Change-Id: I4ed19bf43a5594109a16397da94c56cda87c69f0
Signed-off-by: Sridhar Ravindra <sridhar.ravindra@radisys.com>
diff --git a/internal/pkg/application/application.go b/internal/pkg/application/application.go
index f0fa05e..4f390fd 100644
--- a/internal/pkg/application/application.go
+++ b/internal/pkg/application/application.go
@@ -160,6 +160,7 @@
Type VoltPortType
State PortState
ChannelPerSubAlarmRaised bool
+ NniDhcpTrapFlowAdded bool
}
// NewVoltPort : Constructor for the port.
@@ -209,26 +210,20 @@
MigratingServices *util.ConcurrentMap //<vnetID,<RequestID, MigrateServicesRequest>>
VpvsBySvlan *util.ConcurrentMap // map[svlan]map[vnet_port]*VoltPortVnet
ConfiguredVlanForDeviceFlows *util.ConcurrentMap //map[string]map[string]bool
-
- IgmpDsFlowAppliedForMvlan map[uint16]bool
-
- Ports sync.Map
- VlanPortStatus sync.Map
- ActiveChannelsPerPon sync.Map // [PonPortID]*PonPortCfg
- PonPortList sync.Map // [PonPortID]map[string]string
-
- State controller.DeviceState
- SouthBoundID string
- NniPort string
- Name string
- SerialNum string
-
- ActiveChannelCountLock sync.Mutex // This lock is used to update ActiveIGMPChannels
-
- NniDhcpTrapVid of.VlanType
-
- GlobalDhcpFlowAdded bool
- icmpv6GroupAdded bool
+ IgmpDsFlowAppliedForMvlan map[uint16]bool
+ Ports sync.Map
+ VlanPortStatus sync.Map
+ ActiveChannelsPerPon sync.Map // [PonPortID]*PonPortCfg
+ PonPortList sync.Map // [PonPortID]map[string]string
+ State controller.DeviceState
+ SouthBoundID string
+ Name string
+ SerialNum string
+ NniPort []string
+ ActiveChannelCountLock sync.Mutex // This lock is used to update ActiveIGMPChannels
+ NniDhcpTrapVid of.VlanType
+ GlobalDhcpFlowAdded bool
+ icmpv6GroupAdded bool
}
type VoltDevInterface interface {
@@ -241,7 +236,7 @@
d.Name = name
d.SouthBoundID = southBoundID
d.State = controller.DeviceStateDOWN
- d.NniPort = ""
+ d.NniPort = make([]string, 0)
d.SouthBoundID = southBoundID
d.SerialNum = slno
d.icmpv6GroupAdded = false
@@ -339,12 +334,21 @@
va.AggActiveChannelsCountPerSub(d.Name, port, p)
d.Ports.Store(port, p)
if util.IsNniPort(id) {
- d.NniPort = port
+ d.NniPort = append(d.NniPort, port)
}
addPonPortFromUniPort(p)
return p
}
+func (d *VoltDevice) IsPortNni(port string) bool {
+ for _, nniPort := range d.NniPort {
+ if nniPort == port {
+ return true
+ }
+ }
+ return false
+}
+
// GetPort to get port information from the device.
func (d *VoltDevice) GetPort(port string) *VoltPort {
logger.Debugw(ctx, "Get Port", log.Fields{"Port": port})
@@ -354,7 +358,7 @@
return nil
}
-// GetPortByPortID to get port information from the device.
+// GetPortNameFromPortID to get port information from the device.
func (d *VoltDevice) GetPortNameFromPortID(portID uint32) string {
logger.Debugw(ctx, "Get Port Name from the device", log.Fields{"PortID": portID})
portName := ""
@@ -368,6 +372,20 @@
return portName
}
+// GetPortIDFromPortName to get port information from the device.
+func (d *VoltDevice) GetPortIDFromPortName(portName string) uint32 {
+ logger.Debugw(ctx, "Get Port ID from the device", log.Fields{"PortName": portName})
+ var portID uint32
+ d.Ports.Range(func(key, value interface{}) bool {
+ vp := value.(*VoltPort)
+ if vp.Name == portName {
+ portID = vp.ID
+ }
+ return true
+ })
+ return portID
+}
+
// DelPort to delete port from the device
func (d *VoltDevice) DelPort(port string) {
logger.Debugw(ctx, "Delete Port from the device", log.Fields{"Port": port})
@@ -399,7 +417,7 @@
for _, vpv := range vnets.([]*VoltPortVnet) {
vpv.VpvLock.Lock()
- vpv.PortUpInd(cntx, d, port)
+ vpv.PortUpInd(cntx, d, port, "")
vpv.VpvLock.Unlock()
}
return true
@@ -419,7 +437,7 @@
type VoltAppInterface interface {
AddVnet(cntx context.Context, cfg VnetConfig, oper *VnetOper) error
AddService(cntx context.Context, cfg VoltServiceCfg, oper *VoltServiceOper) error
- AddDeviceConfig(cntx context.Context, serialNum, hardwareIdentifier, nasID, ipAddress, uplinkPort string, nniDhcpTrapID uint16) error
+ AddDeviceConfig(cntx context.Context, serialNum, hardwareIdentifier, nasID, ipAddress, uplinkPort string, nniDhcpTrapID uint16, nniPorts []string) error
GetFlowProvisionStatus(portNo string) FlowProvisionStatus
DelServiceWithPrefix(cntx context.Context, prefix string) error
GetDevice(device string) *VoltDevice
@@ -499,12 +517,13 @@
}
type DeviceConfig struct {
- SerialNumber string `json:"id"`
- HardwareIdentifier string `json:"hardwareIdentifier"`
- IPAddress string `json:"ipAddress"`
- UplinkPort string `json:"uplinkPort"`
- NasID string `json:"nasId"`
- NniDhcpTrapVid uint16 `json:"nniDhcpTrapVid"`
+ SerialNumber string `json:"id"`
+ HardwareIdentifier string `json:"hardwareIdentifier"`
+ IPAddress string `json:"ipAddress"`
+ UplinkPort string `json:"uplinkPort"`
+ NasID string `json:"nasId"`
+ NniPorts []string `json:"nniPorts"`
+ NniDhcpTrapVid uint16 `json:"nniDhcpTrapVid"`
}
// PonPortCfg contains NB port config and activeIGMPChannels count
@@ -602,7 +621,7 @@
continue
}
logger.Debugw(ctx, "Retrieved device config", log.Fields{"Device Config": devConfig})
- if err := va.AddDeviceConfig(cntx, devConfig.SerialNumber, devConfig.HardwareIdentifier, devConfig.NasID, devConfig.IPAddress, devConfig.UplinkPort, devConfig.NniDhcpTrapVid); err != nil {
+ if err := va.AddDeviceConfig(cntx, devConfig.SerialNumber, devConfig.HardwareIdentifier, devConfig.NasID, devConfig.IPAddress, devConfig.UplinkPort, devConfig.NniDhcpTrapVid, devConfig.NniPorts); err != nil {
logger.Warnw(ctx, "Add device config failed", log.Fields{"DeviceConfig": devConfig, "Error": err})
}
}
@@ -621,7 +640,7 @@
return nil
}
-func (va *VoltApplication) AddDeviceConfig(cntx context.Context, serialNum, hardwareIdentifier, nasID, ipAddress, uplinkPort string, nniDhcpTrapID uint16) error {
+func (va *VoltApplication) AddDeviceConfig(cntx context.Context, serialNum, hardwareIdentifier, nasID, ipAddress, uplinkPort string, nniDhcpTrapID uint16, nniPorts []string) error {
logger.Debugw(ctx, "Received Add device config", log.Fields{"SerialNumber": serialNum, "HardwareIdentifier": hardwareIdentifier, "NasID": nasID, "IPAddress": ipAddress, "UplinkPort": uplinkPort, "NniDhcpTrapID": nniDhcpTrapID})
var dc *DeviceConfig
@@ -632,6 +651,7 @@
UplinkPort: uplinkPort,
IPAddress: ipAddress,
NniDhcpTrapVid: nniDhcpTrapID,
+ NniPorts: nniPorts,
}
va.DevicesConfig.Store(serialNum, deviceConfig)
err := dc.WriteDeviceConfigToDb(cntx, serialNum, deviceConfig)
@@ -1139,13 +1159,29 @@
// port which is a result of protection methods applied.
func (va *VoltApplication) GetNniPort(device string) (string, error) {
logger.Debugw(ctx, "NNI Get Ind", log.Fields{"device": device})
- va.portLock.Lock()
- defer va.portLock.Unlock()
d, ok := va.DevicesDisc.Load(device)
if !ok {
return "", errors.New("device doesn't exist")
}
- return d.(*VoltDevice).NniPort, nil
+ devConfig := va.GetDeviceConfig(d.(*VoltDevice).SerialNum)
+ if devConfig == nil {
+ return "", fmt.Errorf("device config not found for serial number %s", d.(*VoltDevice).SerialNum)
+ }
+ if len(d.(*VoltDevice).NniPort) > 0 {
+ for _, nniPort := range d.(*VoltDevice).NniPort {
+ nniPortID, err := GetApplication().GetPortID(nniPort)
+ if err != nil {
+ logger.Errorw(ctx, "Error getting port ID by port Name", log.Fields{"Error": err})
+ continue
+ }
+ if devConfig.UplinkPort == strconv.Itoa(int(nniPortID)) {
+ logger.Debugw(ctx, "NNI port configured from NB", log.Fields{"NB NNI Port": devConfig.UplinkPort, "SB NNI Ports": d.(*VoltDevice).NniPort})
+ return nniPort, nil // Match found
+ }
+ }
+ }
+ // If no matching NNI port is found, return an error
+ return "", errors.New("nni port doesn't exist")
}
// NniDownInd process for Nni down indication.
@@ -1215,7 +1251,11 @@
func (va *VoltApplication) ProcessIgmpDSFlowForMvlan(cntx context.Context, d *VoltDevice, mvp *MvlanProfile, addFlow bool) {
logger.Debugw(ctx, "Process IGMP DS Flows for MVlan", log.Fields{"device": d.Name, "Mvlan": mvp.Mvlan, "addFlow": addFlow})
portState := false
- p := d.GetPort(d.NniPort)
+ nniPort, err := va.GetNniPort(d.Name)
+ if err != nil {
+ logger.Errorw(ctx, "Error gettin NNI port", log.Fields{"Error": err})
+ }
+ p := d.GetPort(nniPort)
if p != nil && p.State == PortStateUp {
portState = true
}
@@ -1438,9 +1478,12 @@
if p.Type == VoltPortTypeNni {
logger.Debugw(ctx, "Received NNI Port Ind: UP", log.Fields{"Device": device, "PortName": port, "PortId": p.ID})
- //va.PushDevFlowForDevice(d)
- //Build Igmp TrapFlowRule
- //va.ProcessIgmpDSFlowForDevice(d, true)
+ if d.NniDhcpTrapVid == 1 {
+ err := va.AddDefaultDhcpTrapFlow(cntx, d, p)
+ if err != nil {
+ logger.Errorw(ctx, "Failed adding DHCP trap flow", log.Fields{"Device": device, "PortName": port, "PortId": p.ID, "error": err})
+ }
+ }
}
vpvs, ok := va.VnetsByPort.Load(port)
if !ok || nil == vpvs || len(vpvs.([]*VoltPortVnet)) == 0 {
@@ -1450,7 +1493,7 @@
}
// If NNI port is not UP, do not push Flows
- if d.NniPort == "" {
+ if len(d.NniPort) == 0 {
logger.Warnw(ctx, "NNI port not UP. Not sending Port UP Ind for VPVs", log.Fields{"NNI": d.NniPort})
return
}
@@ -1458,12 +1501,12 @@
for _, vpv := range vpvs.([]*VoltPortVnet) {
vpv.VpvLock.Lock()
// If no service is activated drop the portUpInd
- if vpv.IsServiceActivated(cntx) {
+ if ok, nniPort := vpv.IsServiceActivated(cntx); ok {
// Do not trigger indication for the vpv which is already removed from vpv list as
// part of service delete (during the lock wait duration)
// In that case, the services associated wil be zero
if vpv.servicesCount.Load() != 0 {
- vpv.PortUpInd(cntx, d, port)
+ vpv.PortUpInd(cntx, d, port, nniPort)
}
} else {
// Service not activated, still attach device to service
@@ -1801,7 +1844,7 @@
if flow.FlowCount >= uint32(controller.GetController().GetMaxFlowRetryAttempt()) {
devConfig := va.GetDeviceConfig(devSerialNum)
if devConfig != nil {
- portNo := util.GetUniPortFromFlow(devConfig.UplinkPort, flow)
+ portNo := util.GetUniPortFromFlow(devConfig.UplinkPort, devConfig.NniPorts, flow)
portName, err := va.GetPortName(portNo)
if err != nil {
logger.Warnw(ctx, "Error getting port name", log.Fields{"Reason": err.Error(), "PortID": portNo})