[VOL-5402]-VGC all fixes till date from jan 2024
Change-Id: I2857e0ef9b1829a28c6e3ad04da96b826cb900b6
Signed-off-by: Akash Soni <akash.soni@radisys.com>
diff --git a/internal/pkg/application/application.go b/internal/pkg/application/application.go
index c87e419..7c61725 100644
--- a/internal/pkg/application/application.go
+++ b/internal/pkg/application/application.go
@@ -203,6 +203,7 @@
// NniPort: The identity of the NNI port
// Ports: List of all ports added to the device
type VoltDevice struct {
+ VoltDeviceIntr VoltDevInterface
FlowAddEventMap *util.ConcurrentMap //map[string]*FlowEvent
FlowDelEventMap *util.ConcurrentMap //map[string]*FlowEvent
MigratingServices *util.ConcurrentMap //<vnetID,<RequestID, MigrateServicesRequest>>
@@ -222,7 +223,6 @@
NniDhcpTrapVid of.VlanType
GlobalDhcpFlowAdded bool
icmpv6GroupAdded bool
- VoltDeviceIntr VoltDevInterface
}
type VoltDevInterface interface {
@@ -459,8 +459,8 @@
IgmpPendingPool map[string]map[*IgmpGroup]bool //[grpkey, map[groupObj]bool] //mvlan_grpName/IP
macPortMap map[string]string
VnetsToDelete map[string]bool
- ServicesToDelete map[string]bool
- ServicesToDeactivate map[string]bool
+ ServicesToDelete sync.Map
+ ServicesToDeactivate sync.Map
PortAlarmProfileCache map[string]map[string]int // [portAlarmID][ThresholdLevelString]ThresholdLevel
vendorID string
ServiceByName sync.Map // [serName]*VoltService
@@ -700,8 +700,6 @@
va.IgmpPendingPool = make(map[string]map[*IgmpGroup]bool)
va.VnetsBySvlan = util.NewConcurrentMap()
va.VnetsToDelete = make(map[string]bool)
- va.ServicesToDelete = make(map[string]bool)
- va.ServicesToDeactivate = make(map[string]bool)
va.VoltPortVnetsToDelete = make(map[*VoltPortVnet]bool)
go va.Start(context.Background(), TimerCfg{tick: 100 * time.Millisecond}, tickTimer)
go va.Start(context.Background(), TimerCfg{tick: time.Duration(GroupExpiryTime) * time.Minute}, pendingPoolTimer)
@@ -926,6 +924,21 @@
}
}
+// CheckServiceExists to check if service exists for the given uniport and tech profile ID.
+func (va *VoltApplication) CheckServiceExists(port string, techProfID uint16) bool {
+ var serviceExists bool
+ va.ServiceByName.Range(func(key, existingServiceIntf interface{}) bool {
+ existingService := existingServiceIntf.(*VoltService)
+ if existingService.Port == port && existingService.TechProfileID == techProfID {
+ logger.Warnw(ctx, "Service already exists for same Port and TP. Ignoring add service request", log.Fields{"ExistingService": existingService.Name})
+ serviceExists = true
+ return false
+ }
+ return true
+ })
+ return serviceExists
+}
+
// GetDeviceBySerialNo to get a device by serial number.
// TODO - Transform this into a MAP instead
func (va *VoltApplication) GetDeviceBySerialNo(slno string) (*VoltDevice, string) {
@@ -1772,35 +1785,60 @@
}
}
-// IsFlowDelThresholdReached - check if the attempts for flow delete has reached threshold or not
-func (va *VoltApplication) IsFlowDelThresholdReached(cntx context.Context, cookie string, device string) bool {
- logger.Debugw(ctx, "Check flow delete threshold", log.Fields{"Cookie": cookie, "Device": device})
- d := va.GetDevice(device)
- if d == nil {
- logger.Warnw(ctx, "Failed to get device during flow delete threshold check", log.Fields{"Cookie": cookie, "Device": device})
- return false
+// CheckAndDeactivateService - check if the attempts for flow delete has reached threshold or not
+func (va *VoltApplication) CheckAndDeactivateService(ctx context.Context, flow *of.VoltSubFlow, devSerialNum string, devID string) {
+ logger.Debugw(ctx, "Check and Deactivate service", log.Fields{"Cookie": flow.Cookie, "FlowCount": flow.FlowCount, "DeviceSerial": devSerialNum})
+ if flow.FlowCount >= controller.GetController().GetMaxFlowRetryAttempt() {
+ devConfig := va.GetDeviceConfig(devSerialNum)
+ if devConfig != nil {
+ portNo := util.GetUniPortFromFlow(devConfig.UplinkPort, flow)
+ portName, err := va.GetPortName(portNo)
+ if err != nil {
+ logger.Warnw(ctx, "Error getting port name", log.Fields{"Reason": err.Error(), "PortID": portNo})
+ return
+ } else if portName == "" {
+ logger.Warnw(ctx, "Port does not exist", log.Fields{"PortID": portNo})
+ return
+ }
+ svc := va.GetServiceNameFromCookie(flow.Cookie, portName, uint8(of.PbitMatchNone), devID, flow.Match.TableMetadata)
+ if svc != nil {
+ va.DeactivateServiceForPort(ctx, svc, devID, portName)
+ }
+ }
}
+}
- flowEventMap, err := d.GetFlowEventRegister(of.CommandDel)
- if err != nil {
- logger.Warnw(ctx, "Flow event map does not exists", log.Fields{"flowMod": of.CommandDel, "Error": err})
- return false
+// DeactivateServiceForPort - deactivate service for given UNI and remove flows from DB, after max flow install threshold has reached
+func (va *VoltApplication) DeactivateServiceForPort(cntx context.Context, vs *VoltService, devID string, portName string) {
+ logger.Debugw(ctx, "Flow install threshold reached. Deactivating service", log.Fields{"Service": vs.Name, "Port": portName})
+
+ if devID == vs.Device && portName == vs.Port && vs.IsActivated {
+ vs.SetSvcDeactivationFlags(SvcDeacRsn_Controller)
+ va.ServiceByName.Store(vs.Name, vs)
+ vs.WriteToDb(cntx)
+ device, err := va.GetDeviceFromPort(portName)
+ if err != nil {
+ // Even if the port/device does not exists at this point in time, the deactivate request is succss.
+ // So no error is returned
+ logger.Warnw(ctx, "Error Getting Device", log.Fields{"Reason": err.Error(), "Port": portName})
+ }
+ p := device.GetPort(vs.Port)
+ if p != nil && (p.State == PortStateUp || !va.OltFlowServiceConfig.RemoveFlowsOnDisable) {
+ if vpv := va.GetVnetByPort(vs.Port, vs.SVlan, vs.CVlan, vs.UniVlan); vpv != nil {
+ // Port down call internally deletes all the flows
+ vpv.PortDownInd(cntx, device.Name, portName, true, true)
+ if vpv.IgmpEnabled {
+ va.ReceiverDownInd(cntx, device.Name, portName)
+ }
+ } else {
+ logger.Warnw(ctx, "VPV does not exists!!!", log.Fields{"Device": device.Name, "port": portName, "SvcName": vs.Name})
+ }
+ logger.Infow(ctx, "Service deactivated after flow install threshold", log.Fields{"Device": device.Name, "Service": vs.Name, "Port": portName})
+ }
+ vs.DeactivateInProgress = false
+ va.ServiceByName.Store(vs.Name, vs)
+ vs.WriteToDb(cntx)
}
- flowEventMap.MapLock.Lock()
- var event interface{}
- if event, _ = flowEventMap.Get(cookie); event == nil {
- logger.Warnw(ctx, "Event does not exist during flow delete threshold check", log.Fields{"Cookie": cookie})
- flowEventMap.MapLock.Unlock()
- return false
- }
- flowEventMap.MapLock.Unlock()
- flowEvent := event.(*FlowEvent)
- if vs, ok := flowEvent.eventData.(*VoltService); ok {
- vs.ServiceLock.RLock()
- defer vs.ServiceLock.RUnlock()
- return vs.FlowPushCount[cookie] == controller.GetController().GetMaxFlowRetryAttempt()
- }
- return false
}
func pushFlowFailureNotif(flowStatus intf.FlowStatus) {
@@ -2131,46 +2169,51 @@
// TriggerPendingServiceDeactivateReq - trigger pending service deactivate request
func (va *VoltApplication) TriggerPendingServiceDeactivateReq(cntx context.Context, device string) {
- logger.Infow(ctx, "Pending Services to be deactivated", log.Fields{"Count": len(va.ServicesToDeactivate)})
- for serviceName := range va.ServicesToDeactivate {
- logger.Debugw(ctx, "Trigger Service Deactivate", log.Fields{"Service": serviceName})
+ va.ServicesToDeactivate.Range(func(key, value interface{}) bool {
+ serviceName := key.(string)
if vs := va.GetService(serviceName); vs != nil {
if vs.Device == device {
logger.Infow(ctx, "Triggering Pending Service Deactivate", log.Fields{"Service": vs.Name})
vpv := va.GetVnetByPort(vs.Port, vs.SVlan, vs.CVlan, vs.UniVlan)
if vpv == nil {
logger.Warnw(ctx, "Vpv Not found for Service", log.Fields{"vs": vs.Name, "port": vs.Port, "Vnet": vs.VnetID})
- continue
+ return true
}
-
vpv.DelTrapFlows(cntx)
vs.DelHsiaFlows(cntx)
+ // Set the flag to false and clear the SevicesToDeactivate map entry so that when core restarts, VGC will not
+ // try to deactivate the service again
+ vs.DeactivateInProgress = false
+ va.ServicesToDeactivate.Delete(serviceName)
vs.WriteToDb(cntx)
vpv.ClearServiceCounters(cntx)
}
} else {
- logger.Warnw(ctx, "Pending Service Not found", log.Fields{"Service": serviceName})
+ logger.Warnw(ctx, "Pending Service Not found during Deactivate", log.Fields{"Service": serviceName})
}
- }
+ return true
+ })
}
// TriggerPendingServiceDeleteReq - trigger pending service delete request
func (va *VoltApplication) TriggerPendingServiceDeleteReq(cntx context.Context, device string) {
- logger.Infow(ctx, "Pending Services to be deleted", log.Fields{"Count": len(va.ServicesToDelete)})
- for serviceName := range va.ServicesToDelete {
- logger.Debugw(ctx, "Trigger Service Delete", log.Fields{"Service": serviceName})
+ va.ServicesToDelete.Range(func(key, value interface{}) bool {
+ serviceName := key.(string)
if vs := va.GetService(serviceName); vs != nil {
if vs.Device == device {
logger.Infow(ctx, "Triggering Pending Service delete", log.Fields{"Service": vs.Name})
vs.DelHsiaFlows(cntx)
+ // Clear the SevicesToDelete map so that when core restarts, VGC will not try to deactivate the service again
+ va.ServicesToDelete.Delete(serviceName)
if vs.ForceDelete {
vs.DelFromDb(cntx)
}
}
} else {
- logger.Warnw(ctx, "Pending Service Not found", log.Fields{"Service": serviceName})
+ logger.Warnw(ctx, "Pending Service Not found during Delete", log.Fields{"Service": serviceName})
}
- }
+ return true
+ })
}
// TriggerPendingVpvDeleteReq - trigger pending VPV delete request
diff --git a/internal/pkg/application/application_test.go b/internal/pkg/application/application_test.go
index 3bb9c72..4c2fe4c 100644
--- a/internal/pkg/application/application_test.go
+++ b/internal/pkg/application/application_test.go
@@ -332,9 +332,6 @@
},
}
- servicesToDel := map[string]bool{}
- servicesToDel["SCOM00001c75-1_SCOM00001c75-1-4096-2310-4096-65"] = true
-
tests := []struct {
name string
args args
@@ -350,12 +347,13 @@
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
va := &VoltApplication{
- ServicesToDelete: servicesToDel,
+ ServicesToDelete: sync.Map{},
ServiceByName: sync.Map{},
DevicesDisc: sync.Map{},
}
va.ServiceByName.Store("SCOM00001c75-1_SCOM00001c75-1-4096-2310-4096-65", voltServ)
+ va.ServicesToDelete.Store("SCOM00001c75-1_SCOM00001c75-1-4096-2310-4096-65", true)
dbintf := mocks.NewMockDBIntf(gomock.NewController(t))
db = dbintf
@@ -2767,8 +2765,7 @@
cntx context.Context
device string
}
- ServicesDeactivate := map[string]bool{}
- ServicesDeactivate["SDX6320031-1_SDX6320031-1-4096-2310-4096-65"] = true
+
voltServ := &VoltService{
VoltServiceOper: VoltServiceOper{
Device: "SDX6320031",
@@ -2813,12 +2810,13 @@
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
va := &VoltApplication{
- ServicesToDeactivate: ServicesDeactivate,
+ ServicesToDeactivate: sync.Map{},
ServiceByName: sync.Map{},
VnetsByPort: sync.Map{},
}
va.ServiceByName.Store("SDX6320031-1_SDX6320031-1-4096-2310-4096-65", voltServ)
va.VnetsByPort.Store("16777472", voltPortVnets)
+ va.ServicesToDeactivate.Store("SDX6320031-1_SDX6320031-1-4096-2310-4096-65", true)
dbintf := mocks.NewMockDBIntf(gomock.NewController(t))
db = dbintf
dbintf.EXPECT().PutService(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
diff --git a/internal/pkg/application/flowevent.go b/internal/pkg/application/flowevent.go
index 63123da..b7b838b 100644
--- a/internal/pkg/application/flowevent.go
+++ b/internal/pkg/application/flowevent.go
@@ -19,7 +19,6 @@
"context"
infraerrorcode "voltha-go-controller/internal/pkg/errorcodes/service"
- "voltha-go-controller/internal/pkg/util"
"voltha-go-controller/internal/pkg/intf"
"voltha-go-controller/log"
@@ -32,7 +31,7 @@
type FlowEventType string
// FlowEventHandler - Func prototype for flow event handling funcs
-type FlowEventHandler func(context.Context, *FlowEvent, intf.FlowStatus, *util.ConcurrentMap)
+type FlowEventHandler func(context.Context, *FlowEvent, intf.FlowStatus)
var eventMapper map[FlowEventType]FlowEventHandler
@@ -93,20 +92,16 @@
flowEventMap.MapLock.Unlock()
return false
}
+ flowEventMap.Remove(cookie)
flowEventMap.MapLock.Unlock()
flowEvent := event.(*FlowEvent)
- if flowEvent.eType != EventTypeServiceFlowAdded && flowEvent.eType != EventTypeServiceFlowRemoved {
- flowEventMap.MapLock.Lock()
- flowEventMap.Remove(cookie)
- flowEventMap.MapLock.Unlock()
- }
- eventMapper[flowEvent.eType](cntx, flowEvent, flowStatus, flowEventMap)
+ eventMapper[flowEvent.eType](cntx, flowEvent, flowStatus)
return true
}
// ProcessUsIgmpFlowAddEvent - Process Us Igmp Flow event trigger
-func ProcessUsIgmpFlowAddEvent(cntx context.Context, event *FlowEvent, flowStatus intf.FlowStatus, flowEventMap *util.ConcurrentMap) {
- logger.Infow(ctx, "Processing Post Flow Add Event for US Igmp", log.Fields{"Cookie": event.cookie, "event": event})
+func ProcessUsIgmpFlowAddEvent(cntx context.Context, event *FlowEvent, flowStatus intf.FlowStatus) {
+ logger.Debugw(ctx, "Processing Post Flow Add Event for US Igmp", log.Fields{"Cookie": event.cookie, "event": event})
vpv := event.eventData.(*VoltPortVnet)
if isFlowStatusSuccess(flowStatus.Status, true) {
vpv.services.Range(ReceiverUpInd)
@@ -116,19 +111,19 @@
}
// ProcessServiceFlowAddEvent - Process Service Flow event trigger
-func ProcessServiceFlowAddEvent(cntx context.Context, event *FlowEvent, flowStatus intf.FlowStatus, flowEventMap *util.ConcurrentMap) {
- logger.Infow(ctx, "Processing Post Flow Add Event for Service", log.Fields{"Cookie": event.cookie, "event": event})
+func ProcessServiceFlowAddEvent(cntx context.Context, event *FlowEvent, flowStatus intf.FlowStatus) {
+ logger.Debugw(ctx, "Processing Post Flow Add Event for Service", log.Fields{"Cookie": event.cookie, "event": event})
vs := event.eventData.(*VoltService)
if isFlowStatusSuccess(flowStatus.Status, true) {
- vs.FlowInstallSuccess(cntx, event.cookie, flowStatus.AdditionalData, flowEventMap)
+ vs.FlowInstallSuccess(cntx, event.cookie, flowStatus.AdditionalData)
} else {
- vs.FlowInstallFailure(cntx, event.cookie, flowStatus.Status, flowStatus.Reason, flowEventMap)
+ vs.FlowInstallFailure(cntx, event.cookie, flowStatus.Status, flowStatus.Reason)
}
}
// ProcessControlFlowAddEvent - Process Control Flow event trigger
-func ProcessControlFlowAddEvent(cntx context.Context, event *FlowEvent, flowStatus intf.FlowStatus, flowEventMap *util.ConcurrentMap) {
- logger.Infow(ctx, "Processing Post Flow Add Event for VPV", log.Fields{"Cookie": event.cookie, "event": event})
+func ProcessControlFlowAddEvent(cntx context.Context, event *FlowEvent, flowStatus intf.FlowStatus) {
+ logger.Debugw(ctx, "Processing Post Flow Add Event for VPV", log.Fields{"Cookie": event.cookie, "event": event})
vpv := event.eventData.(*VoltPortVnet)
if !isFlowStatusSuccess(flowStatus.Status, true) {
vpv.FlowInstallFailure(event.cookie, flowStatus.Status, flowStatus.Reason)
@@ -136,19 +131,19 @@
}
// ProcessServiceFlowDelEvent - Process Service Flow event trigger
-func ProcessServiceFlowDelEvent(cntx context.Context, event *FlowEvent, flowStatus intf.FlowStatus, flowEventMap *util.ConcurrentMap) {
- logger.Infow(ctx, "Processing Post Flow Remove Event for Service", log.Fields{"Cookie": event.cookie, "event": event})
+func ProcessServiceFlowDelEvent(cntx context.Context, event *FlowEvent, flowStatus intf.FlowStatus) {
+ logger.Debugw(ctx, "Processing Post Flow Remove Event for Service", log.Fields{"Cookie": event.cookie, "event": event})
vs := event.eventData.(*VoltService)
if isFlowStatusSuccess(flowStatus.Status, false) {
- vs.FlowRemoveSuccess(cntx, event.cookie, flowEventMap)
+ vs.FlowRemoveSuccess(cntx, event.cookie)
} else {
- vs.FlowRemoveFailure(cntx, event.cookie, flowStatus.Status, flowStatus.Reason, flowEventMap)
+ vs.FlowRemoveFailure(cntx, event.cookie, flowStatus.Status, flowStatus.Reason)
}
}
// ProcessControlFlowDelEvent - Process Control Flow event trigger
-func ProcessControlFlowDelEvent(cntx context.Context, event *FlowEvent, flowStatus intf.FlowStatus, flowEventMap *util.ConcurrentMap) {
- logger.Infow(ctx, "Processing Post Flow Remove Event for VPV", log.Fields{"Cookie": event.cookie, "event": event})
+func ProcessControlFlowDelEvent(cntx context.Context, event *FlowEvent, flowStatus intf.FlowStatus) {
+ logger.Debugw(ctx, "Processing Post Flow Remove Event for VPV", log.Fields{"Cookie": event.cookie, "event": event})
vpv := event.eventData.(*VoltPortVnet)
if isFlowStatusSuccess(flowStatus.Status, false) {
vpv.FlowRemoveSuccess(cntx, event.cookie, event.device)
@@ -158,8 +153,8 @@
}
// ProcessMcastFlowDelEvent - Process Control Flow event trigger
-func ProcessMcastFlowDelEvent(cntx context.Context, event *FlowEvent, flowStatus intf.FlowStatus, flowEventMap *util.ConcurrentMap) {
- logger.Infow(ctx, "Processing Post Flow Remove Event for Mcast/Igmp", log.Fields{"Cookie": event.cookie, "event": event})
+func ProcessMcastFlowDelEvent(cntx context.Context, event *FlowEvent, flowStatus intf.FlowStatus) {
+ logger.Debugw(ctx, "Processing Post Flow Remove Event for Mcast/Igmp", log.Fields{"Cookie": event.cookie, "event": event})
mvp := event.eventData.(*MvlanProfile)
if isFlowStatusSuccess(flowStatus.Status, false) {
mvp.FlowRemoveSuccess(cntx, event.cookie, event.device)
@@ -169,7 +164,7 @@
}
// ProcessDeviceFlowDelEvent - Process Control Flow event trigger
-func ProcessDeviceFlowDelEvent(cntx context.Context, event *FlowEvent, flowStatus intf.FlowStatus, flowEventMap *util.ConcurrentMap) {
+func ProcessDeviceFlowDelEvent(cntx context.Context, event *FlowEvent, flowStatus intf.FlowStatus) {
logger.Debugw(ctx, "Processing Post Flow Remove Event for VNET", log.Fields{"Cookie": event.cookie, "event": event})
vnet := event.eventData.(*VoltVnet)
if isFlowStatusSuccess(flowStatus.Status, false) {
@@ -181,7 +176,7 @@
// TODO: Update the func or flowStatus struct once all flow status are based on NB error code
func isFlowStatusSuccess(status uint32, flowAdd bool) bool {
- logger.Infow(ctx, "Processing isFlowStatusSuccess", log.Fields{"Status": status, "FlowAdd": flowAdd})
+ logger.Debugw(ctx, "Processing isFlowStatusSuccess", log.Fields{"Status": status, "FlowAdd": flowAdd})
result := false
errorCode := infraerrorcode.ErrorCode(status)
diff --git a/internal/pkg/application/flowevent_test.go b/internal/pkg/application/flowevent_test.go
index 6bd5da2..8621521 100644
--- a/internal/pkg/application/flowevent_test.go
+++ b/internal/pkg/application/flowevent_test.go
@@ -150,7 +150,7 @@
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
- ProcessUsIgmpFlowAddEvent(tt.args.cntx, tt.args.event, tt.args.flowStatus, nil)
+ ProcessUsIgmpFlowAddEvent(tt.args.cntx, tt.args.event, tt.args.flowStatus)
})
}
}
@@ -162,12 +162,8 @@
flowStatus intf.FlowStatus
flowEventMap *util.ConcurrentMap
}
-
- flowPushCountMap := make(map[string]uint32)
vs := &VoltService{
- VoltServiceCfg: VoltServiceCfg{
- FlowPushCount: flowPushCountMap,
- },
+ VoltServiceCfg: VoltServiceCfg{},
}
tests := []struct {
@@ -202,7 +198,7 @@
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
- ProcessServiceFlowAddEvent(tt.args.cntx, tt.args.event, tt.args.flowStatus, tt.args.flowEventMap)
+ ProcessServiceFlowAddEvent(tt.args.cntx, tt.args.event, tt.args.flowStatus)
})
}
}
@@ -241,7 +237,7 @@
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
- ProcessControlFlowAddEvent(tt.args.cntx, tt.args.event, tt.args.flowStatus, nil)
+ ProcessControlFlowAddEvent(tt.args.cntx, tt.args.event, tt.args.flowStatus)
})
}
}
@@ -253,12 +249,8 @@
flowStatus intf.FlowStatus
flowEventMap *util.ConcurrentMap
}
-
- flowPushCountMap := make(map[string]uint32)
vs := &VoltService{
- VoltServiceCfg: VoltServiceCfg{
- FlowPushCount: flowPushCountMap,
- },
+ VoltServiceCfg: VoltServiceCfg{},
}
tests := []struct {
@@ -294,7 +286,7 @@
dbintf := mocks.NewMockDBIntf(gomock.NewController(t))
db = dbintf
dbintf.EXPECT().PutService(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).Times(1)
- ProcessServiceFlowDelEvent(tt.args.cntx, tt.args.event, tt.args.flowStatus, tt.args.flowEventMap)
+ ProcessServiceFlowDelEvent(tt.args.cntx, tt.args.event, tt.args.flowStatus)
})
}
}
@@ -336,7 +328,7 @@
dbintf := mocks.NewMockDBIntf(gomock.NewController(t))
db = dbintf
dbintf.EXPECT().PutVpv(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).Times(1)
- ProcessControlFlowDelEvent(tt.args.cntx, tt.args.event, tt.args.flowStatus, nil)
+ ProcessControlFlowDelEvent(tt.args.cntx, tt.args.event, tt.args.flowStatus)
})
}
}
@@ -381,7 +373,7 @@
dbintf := mocks.NewMockDBIntf(gomock.NewController(t))
db = dbintf
dbintf.EXPECT().PutMvlan(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).Times(1)
- ProcessMcastFlowDelEvent(tt.args.cntx, tt.args.event, tt.args.flowStatus, nil)
+ ProcessMcastFlowDelEvent(tt.args.cntx, tt.args.event, tt.args.flowStatus)
})
}
}
@@ -431,9 +423,9 @@
dbintf := mocks.NewMockDBIntf(gomock.NewController(t))
db = dbintf
dbintf.EXPECT().PutVnet(gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes().Return(nil).AnyTimes()
- ProcessDeviceFlowDelEvent(tt.args.cntx, tt.args.event, tt.args.flowStatus, nil)
+ ProcessDeviceFlowDelEvent(tt.args.cntx, tt.args.event, tt.args.flowStatus)
case "ProcessDeviceFlowDelEvent_else_condition":
- ProcessDeviceFlowDelEvent(tt.args.cntx, tt.args.event, tt.args.flowStatus, nil)
+ ProcessDeviceFlowDelEvent(tt.args.cntx, tt.args.event, tt.args.flowStatus)
}
})
}
diff --git a/internal/pkg/application/service.go b/internal/pkg/application/service.go
index 5f7178b..e060548 100644
--- a/internal/pkg/application/service.go
+++ b/internal/pkg/application/service.go
@@ -82,7 +82,7 @@
// MacAddress - The MAC hardware address learnt on the UNI interface
// MacAddresses - Not yet implemented. To be used to learn more MAC addresses
type VoltServiceCfg struct {
- Pbits []of.PbitType
+ DsRemarkPbitsMap map[int]int // Ex: Remark case {0:0,1:0} and No-remark case {1:1}
Name string
CircuitID string
Port string
@@ -94,20 +94,20 @@
RemoteIDType string
DataRateAttr string
ServiceType string
- DsRemarkPbitsMap map[int]int // Ex: Remark case {0:0,1:0} and No-remark case {1:1}
- RemoteID []byte
MacAddr net.HardwareAddr
- ONTEtherTypeClassification int
- SchedID int
+ RemoteID []byte
+ Pbits []of.PbitType
Trigger ServiceTrigger
MacLearning MacLearningType
+ ONTEtherTypeClassification int
+ SchedID int
PonPort uint32
MinDataRateUs uint32
MinDataRateDs uint32
MaxDataRateUs uint32
MaxDataRateDs uint32
- TechProfileID uint16
SVlanTpid layers.EthernetType
+ TechProfileID uint16
UniVlan of.VlanType
CVlan of.VlanType
SVlan of.VlanType
@@ -115,6 +115,7 @@
UsPonSTagPriority of.PbitType
DsPonSTagPriority of.PbitType
DsPonCTagPriority of.PbitType
+ ServiceDeactivateReason SvcDeactivateReason // Mentions why the service was deactivated
VlanControl VlanControl
IsOption82Enabled bool
IgmpEnabled bool
@@ -122,8 +123,6 @@
AllowTransparent bool
EnableMulticastKPI bool
IsActivated bool
- FlowPushCount map[string]uint32 // Tracks the number of flow install/delete failure attempts per cookie in order to throttle flow auditing
- ServiceDeactivateReason SvcDeactivateReason // Mentions why the service was deactivated
}
// VoltServiceOper structure
@@ -215,7 +214,6 @@
vs.Ipv6Addr = net.ParseIP("::")
vs.PendingFlows = make(map[string]bool)
vs.AssociatedFlows = make(map[string]bool)
- vs.FlowPushCount = make(map[string]uint32)
return &vs
}
@@ -302,10 +300,12 @@
func (vs *VoltService) AddHsiaFlows(cntx context.Context) {
logger.Debugw(ctx, "Add US & DS HSIA Flows for the service", log.Fields{"ServiceName": vs.Name})
if err := vs.AddUsHsiaFlows(cntx); err != nil {
+ logger.Errorw(ctx, "Error adding US HSIA Flows", log.Fields{"Service": vs.Name, "Port": vs.Port, "Reason": err.Error()})
statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
vs.triggerServiceFailureInd(statusCode, statusMessage)
}
if err := vs.AddDsHsiaFlows(cntx); err != nil {
+ logger.Errorw(ctx, "Error adding DS HSIA Flows", log.Fields{"Service": vs.Name, "Port": vs.Port, "Reason": err.Error()})
statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
vs.triggerServiceFailureInd(statusCode, statusMessage)
}
@@ -315,11 +315,13 @@
func (vs *VoltService) DelHsiaFlows(cntx context.Context) {
logger.Debugw(ctx, "Delete US & DS HSIA Flows for the service", log.Fields{"ServiceName": vs.Name})
if err := vs.DelUsHsiaFlows(cntx, false); err != nil {
+ logger.Errorw(ctx, "Error deleting US HSIA Flows", log.Fields{"Service": vs.Name, "Port": vs.Port, "Reason": err.Error()})
statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
vs.triggerServiceFailureInd(statusCode, statusMessage)
}
if err := vs.DelDsHsiaFlows(cntx, false); err != nil {
+ logger.Errorw(ctx, "Error deleting DS HSIA Flows", log.Fields{"Service": vs.Name, "Port": vs.Port, "Reason": err.Error()})
statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
vs.triggerServiceFailureInd(statusCode, statusMessage)
}
@@ -346,7 +348,7 @@
// AddUsHsiaFlows - Add US HSIA Flows for the service
func (vs *VoltService) AddUsHsiaFlows(cntx context.Context) error {
- logger.Infow(ctx, "Configuring US HSIA Service Flows", log.Fields{"Device": vs.Device, "ServiceName": vs.Name})
+ logger.Infow(ctx, "Configuring US HSIA Service Flows", log.Fields{"Device": vs.Device, "ServiceName": vs.Name, "Port": vs.Port})
if vs.DeleteInProgress || vs.UpdateInProgress {
logger.Warnw(ctx, "Ignoring US HSIA Flow Push, Service deleteion In-Progress", log.Fields{"Device": vs.Device, "Service": vs.Name})
return nil
@@ -356,6 +358,7 @@
if !vs.UsHSIAFlowsApplied || vgcRebooted {
device, err := va.GetDeviceFromPort(vs.Port)
if err != nil {
+ logger.Errorw(ctx, "Error Getting Device for Service and Port", log.Fields{"Service": vs.Name, "Port": vs.Port, "Error": err})
return fmt.Errorf("Error Getting Device for Service %s and Port %s : %w", vs.Name, vs.Port, err)
} else if device.State != controller.DeviceStateUP {
logger.Warnw(ctx, "Device state Down. Ignoring US HSIA Flow Push", log.Fields{"Service": vs.Name, "Port": vs.Port})
@@ -398,7 +401,7 @@
// AddDsHsiaFlows - Add DS HSIA Flows for the service
func (vs *VoltService) AddDsHsiaFlows(cntx context.Context) error {
- logger.Infow(ctx, "Configuring DS HSIA Service Flows", log.Fields{"Device": vs.Device, "ServiceName": vs.Name})
+ logger.Infow(ctx, "Configuring DS HSIA Service Flows", log.Fields{"Device": vs.Device, "ServiceName": vs.Name, "Port": vs.Port})
if vs.DeleteInProgress {
logger.Warnw(ctx, "Ignoring DS HSIA Flow Push, Service deleteion In-Progress", log.Fields{"Device": vs.Device, "Service": vs.Name})
return nil
@@ -408,6 +411,7 @@
if !vs.DsHSIAFlowsApplied || vgcRebooted {
device, err := va.GetDeviceFromPort(vs.Port)
if err != nil {
+ logger.Errorw(ctx, "Error Getting Device for Service and Port", log.Fields{"Service": vs.Name, "Port": vs.Port, "Error": err})
return fmt.Errorf("Error Getting Device for Service %s and Port %s : %w", vs.Name, vs.Port, err)
} else if device.State != controller.DeviceStateUP {
logger.Warnw(ctx, "Device state Down. Ignoring DS HSIA Flow Push", log.Fields{"Service": vs.Name, "Port": vs.Port})
@@ -473,6 +477,7 @@
if vs.UsHSIAFlowsApplied || vgcRebooted {
device, err := GetApplication().GetDeviceFromPort(vs.Port)
if err != nil {
+ logger.Errorw(ctx, "Error Getting Device for Servic and Port", log.Fields{"Device": vs.Device, "ServiceName": vs.Name, "Reason": err})
return fmt.Errorf("Error Getting Device for Service %s and Port %s : %w", vs.Name, vs.Port, err)
}
pBits := vs.Pbits
@@ -746,7 +751,7 @@
// BuildUsHsiaFlows build the US HSIA flows
// Called for add/delete HSIA flows
func (vs *VoltService) BuildUsHsiaFlows(pbits of.PbitType) (*of.VoltFlow, error) {
- logger.Debugw(ctx, "Building US HSIA Service Flows", log.Fields{"Device": vs.Device, "ServiceName": vs.Name})
+ logger.Debugw(ctx, "Building US HSIA Service Flows", log.Fields{"Device": vs.Device, "ServiceName": vs.Name, "Port": vs.Port})
flow := &of.VoltFlow{}
flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
@@ -1059,17 +1064,13 @@
vs.DeactivateInProgress = oper.DeactivateInProgress
vs.BwAvailInfo = oper.BwAvailInfo
vs.Device = oper.Device
- // FlowPushCount is newly introduced map and it can be nil when VGC is upgraded. Hence adding a nil check to handle backward compatibility
- if cfg.FlowPushCount != nil {
- vs.FlowPushCount = cfg.FlowPushCount
- }
vs.ServiceDeactivateReason = cfg.ServiceDeactivateReason
} else {
// Sorting Pbit from highest
sort.Slice(vs.Pbits, func(i, j int) bool {
return vs.Pbits[i] > vs.Pbits[j]
})
- logger.Infow(ctx, "Sorted Pbits", log.Fields{"Pbits": vs.Pbits})
+ logger.Debugw(ctx, "Sorted Pbits", log.Fields{"Pbits": vs.Pbits})
}
logger.Infow(ctx, "VolthService...", log.Fields{"vs": vs.Name})
@@ -1151,7 +1152,7 @@
// DelServiceWithPrefix - Deletes service with the provided prefix.
// Added for DT/TT usecase with sadis replica interface
func (va *VoltApplication) DelServiceWithPrefix(cntx context.Context, prefix string) error {
- logger.Infow(ctx, "Delete Service With provided Prefix", log.Fields{"Prefix": prefix})
+ logger.Debugw(ctx, "Delete Service With provided Prefix", log.Fields{"Prefix": prefix})
var isServiceExist bool
va.ServiceByName.Range(func(key, value interface{}) bool {
srvName := key.(string)
@@ -1202,9 +1203,12 @@
vs.ForceDelete = forceDelete
vs.ForceWriteToDb(cntx)
+ vs.ServiceLock.RLock()
if len(vs.AssociatedFlows) == 0 {
noFlowsPresent = true
}
+ vs.ServiceLock.RUnlock()
+
vpv.VpvLock.Lock()
defer vpv.VpvLock.Unlock()
@@ -1301,12 +1305,8 @@
// FlowInstallSuccess - Called when corresponding service flow installation is success
// If no more pending flows, HSIA indication wil be triggered
-func (vs *VoltService) FlowInstallSuccess(cntx context.Context, cookie string, bwAvailInfo of.BwAvailDetails, flowEventMap *util.ConcurrentMap) {
+func (vs *VoltService) FlowInstallSuccess(cntx context.Context, cookie string, bwAvailInfo of.BwAvailDetails) {
logger.Debugw(ctx, "Flow Add Success Notification", log.Fields{"Cookie": cookie, "bwAvailInfo": bwAvailInfo, "Service": vs.Name})
- flowEventMap.MapLock.Lock()
- flowEventMap.Remove(cookie)
- flowEventMap.MapLock.Unlock()
-
if vs.DeleteInProgress {
logger.Warnw(ctx, "Skipping Flow Add Success Notification. Service deletion in-progress", log.Fields{"Cookie": cookie, "Service": vs.Name})
return
@@ -1321,7 +1321,6 @@
delete(vs.PendingFlows, cookie)
vs.AssociatedFlows[cookie] = true
- vs.FlowPushCount[cookie] = 0
vs.ServiceLock.Unlock()
var prevBwAvail, presentBwAvail string
if bwAvailInfo.PrevBw != "" && bwAvailInfo.PresentBw != "" {
@@ -1332,7 +1331,9 @@
}
vs.WriteToDb(cntx)
+ vs.ServiceLock.RLock()
if len(vs.PendingFlows) == 0 && vs.DsHSIAFlowsApplied {
+ vs.ServiceLock.RUnlock()
device, err := GetApplication().GetDeviceFromPort(vs.Port)
if err != nil {
logger.Errorw(ctx, "Error Getting Device. Dropping HSIA Success indication to NB", log.Fields{"Reason": err.Error(), "Service": vs.Name, "Port": vs.Port})
@@ -1349,24 +1350,16 @@
logger.Infow(ctx, "All Flows installed for Service", log.Fields{"Service": vs.Name})
return
}
- logger.Infow(ctx, "Processed Service Flow Add Success Indication", log.Fields{"Cookie": cookie, "Service": vs.Name, "DsFlowsApplied": vs.DsHSIAFlowsApplied})
+ vs.ServiceLock.RUnlock()
+ logger.Debugw(ctx, "Processed Service Flow Add Success Indication", log.Fields{"Cookie": cookie, "Service": vs.Name, "DsFlowsApplied": vs.DsHSIAFlowsApplied})
}
// FlowInstallFailure - Called when corresponding service flow installation is failed
// Trigger service failure indication to NB
-func (vs *VoltService) FlowInstallFailure(cntx context.Context, cookie string, errorCode uint32, errReason string, flowEventMap *util.ConcurrentMap) {
+func (vs *VoltService) FlowInstallFailure(cntx context.Context, cookie string, errorCode uint32, errReason string) {
logger.Debugw(ctx, "Service flow installation failure", log.Fields{"Service": vs.Name, "Cookie": cookie, "errorCode": errorCode, "errReason": errReason})
-
- isServiceDeactivated := vs.CheckAndDeactivateService(cntx, cookie)
- if isServiceDeactivated {
- flowEventMap.MapLock.Lock()
- for ck := range vs.PendingFlows {
- flowEventMap.Remove(ck)
- }
- flowEventMap.MapLock.Unlock()
- }
-
vs.ServiceLock.RLock()
+
if _, ok := vs.PendingFlows[cookie]; !ok {
logger.Errorw(ctx, "Flow Add Failure for unknown Cookie", log.Fields{"Service": vs.Name, "Cookie": cookie})
vs.ServiceLock.RUnlock()
@@ -1380,7 +1373,7 @@
// DelFlows - Deletes the flow from the service
// Triggers flow deletion after registering for flow indication event
func (vs *VoltService) DelFlows(cntx context.Context, device *VoltDevice, flow *of.VoltFlow, delFlowsInDevice bool) error {
- logger.Debugw(ctx, "Delete the flow from the service", log.Fields{"Port": vs.Port, "Device": device.Name})
+ logger.Infow(ctx, "Delete the flow from the service", log.Fields{"Port": vs.Port, "Device": device.Name, "cookie": flow.MigrateCookie})
if !vs.ForceDelete {
// Using locks instead of concurrent map for AssociatedFlows to avoid
// race condition during flow response indication processing
@@ -1410,56 +1403,16 @@
}
}
-// CheckAndDeactivateService - deactivate service and remove flows from DB, if the max flows retry attempt has reached
-func (vs *VoltService) CheckAndDeactivateService(cntx context.Context, cookie string) bool {
- vs.ServiceLock.Lock()
- logger.Debugw(ctx, "Check and Deactivate service if flow install threshold is reached and remove flows from DB/Device", log.Fields{"serviceName": vs.Name, "FlowPushCount": vs.FlowPushCount[cookie]})
- vs.FlowPushCount[cookie]++
- if vs.FlowPushCount[cookie] == controller.GetController().GetMaxFlowRetryAttempt() {
- if vs.IsActivated {
- vs.ServiceLock.Unlock()
- device, err := GetApplication().GetDeviceFromPort(vs.Port)
- if err != nil {
- // Even if the port/device does not exists at this point in time, the deactivate request is succss.
- // So no error is returned
- logger.Warnw(ctx, "Error Getting Device", log.Fields{"Reason": err.Error(), "Port": vs.Port})
- return false
- }
- vs.SetSvcDeactivationFlags(SvcDeacRsn_Controller)
- GetApplication().ServiceByName.Store(vs.Name, vs)
- p := device.GetPort(vs.Port)
- if p != nil && (p.State == PortStateUp) {
- if vpv := GetApplication().GetVnetByPort(vs.Port, vs.SVlan, vs.CVlan, vs.UniVlan); vpv != nil {
- // Port down call internally deletes all the flows
- vpv.PortDownInd(cntx, vs.Device, vs.Port, true, true)
- } else {
- logger.Warnw(ctx, "VPV does not exists!!!", log.Fields{"Device": vs.Device, "port": vs.Port, "SvcName": vs.Name})
- }
- }
- vs.DeactivateInProgress = false
- GetApplication().ServiceByName.Store(vs.Name, vs)
- vs.WriteToDb(cntx)
- logger.Infow(ctx, "Service deactivated after max flow install attempts", log.Fields{"SvcName": vs.Name, "Cookie": cookie})
- return true
- }
- }
- vs.ServiceLock.Unlock()
- return false
-}
-
// FlowRemoveSuccess - Called when corresponding service flow removal is success
// If no more associated flows, DelHSIA indication wil be triggered
-func (vs *VoltService) FlowRemoveSuccess(cntx context.Context, cookie string, flowEventMap *util.ConcurrentMap) {
+func (vs *VoltService) FlowRemoveSuccess(cntx context.Context, cookie string) {
// if vs.DeleteInProgress {
// logger.Warnw(ctx, "Skipping Flow Remove Success Notification. Service deletion in-progress", log.Fields{"Cookie": cookie, "Service": vs.Name})
// return
// }
- flowEventMap.MapLock.Lock()
- flowEventMap.Remove(cookie)
- flowEventMap.MapLock.Unlock()
vs.ServiceLock.Lock()
- logger.Infow(ctx, "Processing Service Flow Remove Success Indication", log.Fields{"Cookie": cookie, "Service": vs.Name, "Associated Flows": vs.AssociatedFlows, "DsFlowsApplied": vs.DsHSIAFlowsApplied})
+ logger.Debugw(ctx, "Processing Service Flow Remove Success Indication", log.Fields{"Cookie": cookie, "Service": vs.Name, "Associated Flows": vs.AssociatedFlows, "DsFlowsApplied": vs.DsHSIAFlowsApplied})
if _, ok := vs.AssociatedFlows[cookie]; ok {
delete(vs.AssociatedFlows, cookie)
@@ -1468,13 +1421,12 @@
} else {
logger.Debugw(ctx, "Service Flow Remove Success for unknown Cookie", log.Fields{"Service": vs.Name, "Cookie": cookie, "AssociatedFlows": vs.AssociatedFlows, "PendingFlows": vs.PendingFlows})
}
-
- vs.FlowPushCount[cookie] = 0
vs.ServiceLock.Unlock()
-
vs.WriteToDb(cntx)
+ vs.ServiceLock.RLock()
if len(vs.AssociatedFlows) == 0 && !vs.DsHSIAFlowsApplied {
+ vs.ServiceLock.RUnlock()
device := GetApplication().GetDevice(vs.Device)
if device == nil {
logger.Errorw(ctx, "Error Getting Device. Dropping DEL_HSIA Success indication to NB", log.Fields{"Service": vs.Name, "Port": vs.Port})
@@ -1490,20 +1442,25 @@
return
}
logger.Infow(ctx, "All Flows removed for Service. Triggering Service De-activation Success indication to NB", log.Fields{"Service": vs.Name, "DeleteFlag": vs.DeleteInProgress})
- vs.CheckAndDeleteService(cntx)
+ // Get the service from application before proceeding to delete, as the service might have been activated
+ // by the time the flow removal response is received from SB
+ svc := GetApplication().GetService(vs.Name)
+ if svc != nil {
+ svc.CheckAndDeleteService(cntx)
+ }
return
}
- logger.Infow(ctx, "Processed Service Flow Remove Success Indication", log.Fields{"Cookie": cookie, "Service": vs.Name, "Associated Flows": vs.AssociatedFlows, "DsFlowsApplied": vs.DsHSIAFlowsApplied})
+ vs.ServiceLock.RUnlock()
+ logger.Debugw(ctx, "Processed Service Flow Remove Success Indication", log.Fields{"Cookie": cookie, "Service": vs.Name, "Associated Flows": vs.AssociatedFlows, "DsFlowsApplied": vs.DsHSIAFlowsApplied})
}
// FlowRemoveFailure - Called when corresponding service flow installation is failed
// Trigger service failure indication to NB
-func (vs *VoltService) FlowRemoveFailure(cntx context.Context, cookie string, errorCode uint32, errReason string, flowEventMap *util.ConcurrentMap) {
+func (vs *VoltService) FlowRemoveFailure(cntx context.Context, cookie string, errorCode uint32, errReason string) {
vs.ServiceLock.Lock()
- logger.Debugw(ctx, "Processing Service Flow Remove Failure Indication", log.Fields{"Cookie": cookie, "Service": vs.Name, "Associated Flows": vs.AssociatedFlows, "DsFlowsApplied": vs.DsHSIAFlowsApplied, "FlowPushCount": vs.FlowPushCount[cookie]})
+ logger.Debugw(ctx, "Processing Service Flow Remove Failure Indication", log.Fields{"Cookie": cookie, "Service": vs.Name, "Associated Flows": vs.AssociatedFlows, "DsFlowsApplied": vs.DsHSIAFlowsApplied})
- vs.FlowPushCount[cookie]++
if _, ok := vs.AssociatedFlows[cookie]; !ok {
logger.Warnw(ctx, "Flow Failure for unknown Cookie", log.Fields{"Service": vs.Name, "Cookie": cookie})
vs.ServiceLock.Unlock()
@@ -1516,7 +1473,12 @@
logger.Debugw(ctx, "Service Flow Remove Failure Notification", log.Fields{"uniPort": vs.Port, "Cookie": cookie, "Service": vs.Name, "ErrorCode": errorCode, "ErrorReason": errReason})
vs.triggerServiceFailureInd(errorCode, errReason)
- vs.CheckAndDeleteService(cntx)
+ // Get the service from application before proceeding to delete, as the service might have been activated
+ // by the time the flow removal response is received from SB
+ svc := GetApplication().GetService(vs.Name)
+ if svc != nil {
+ svc.CheckAndDeleteService(cntx)
+ }
}
func (vs *VoltService) triggerServiceFailureInd(errorCode uint32, errReason string) {
@@ -1554,12 +1516,12 @@
}
if vvs.VoltServiceOper.DeactivateInProgress {
- va.ServicesToDeactivate[vvs.VoltServiceCfg.Name] = true
+ va.ServicesToDeactivate.Store(vvs.VoltServiceCfg.Name, true)
logger.Warnw(ctx, "Service (restored) to be deactivated", log.Fields{"Service": vvs.Name})
}
if vvs.VoltServiceOper.DeleteInProgress {
- va.ServicesToDelete[vvs.VoltServiceCfg.Name] = true
+ va.ServicesToDelete.Store(vvs.VoltServiceCfg.Name, true)
logger.Warnw(ctx, "Service (restored) to be deleted", log.Fields{"Service": vvs.Name})
}
}
@@ -2248,12 +2210,11 @@
// DeactivateService to activate pre-provisioned service
func (va *VoltApplication) DeactivateService(cntx context.Context, deviceID, portNo string, sVlan, cVlan of.VlanType, tpID uint16) error {
- logger.Infow(ctx, "Service Deactivate Request ", log.Fields{"Device": deviceID, "Port": portNo, "Svaln": sVlan, "Cvlan": cVlan, "TpID": tpID})
+ logger.Debugw(ctx, "Service Deactivate Request ", log.Fields{"Device": deviceID, "Port": portNo, "Svaln": sVlan, "Cvlan": cVlan, "TpID": tpID})
va.ServiceByName.Range(func(key, value interface{}) bool {
vs := value.(*VoltService)
// If svlan if provided, then the tags and tpID of service has to be matching
- logger.Debugw(ctx, "Service Deactivate Request ", log.Fields{"Device": deviceID, "Port": portNo})
if sVlan != of.VlanNone && (sVlan != vs.SVlan || cVlan != vs.CVlan || tpID != vs.TechProfileID) {
logger.Warnw(ctx, "condition not matched", log.Fields{"Device": deviceID, "Port": portNo, "sVlan": sVlan, "cVlan": cVlan, "tpID": tpID})
return true
@@ -2277,11 +2238,13 @@
if vpv.IgmpEnabled {
va.ReceiverDownInd(cntx, deviceID, portNo)
}
- vs.DeactivateInProgress = false
} else {
logger.Warnw(ctx, "VPV does not exists!!!", log.Fields{"Device": deviceID, "port": portNo, "SvcName": vs.Name})
}
}
+ vs.DeactivateInProgress = false
+ va.ServiceByName.Store(vs.Name, vs)
+ vs.WriteToDb(cntx)
}
return true
})
diff --git a/internal/pkg/application/service_test.go b/internal/pkg/application/service_test.go
index 13201ff..746666a 100644
--- a/internal/pkg/application/service_test.go
+++ b/internal/pkg/application/service_test.go
@@ -140,11 +140,11 @@
Name: "test_service_name",
},
}
- serviceToDelete := map[string]bool{}
- serviceToDelete[voltService4.VoltServiceCfg.Name] = true
+
va := &VoltApplication{
- ServicesToDelete: serviceToDelete,
+ ServicesToDelete: sync.Map{},
}
+ va.ServicesToDelete.Store(voltService4.VoltServiceCfg.Name, true)
dbintf := mocks.NewMockDBIntf(gomock.NewController(t))
db = dbintf
switch tt.name {
@@ -224,30 +224,24 @@
switch tt.name {
case "VoltService_FlowRemoveFailure":
associatedFlows := map[string]bool{}
- flowPushCountMap := map[string]uint32{}
associatedFlows["test_cookie"] = true
vs := &VoltService{
VoltServiceOper: VoltServiceOper{
AssociatedFlows: associatedFlows,
},
- VoltServiceCfg: VoltServiceCfg{
- FlowPushCount: flowPushCountMap,
- },
+ VoltServiceCfg: VoltServiceCfg{},
}
- vs.FlowRemoveFailure(tt.args.cntx, tt.args.cookie, tt.args.errorCode, tt.args.errReason, nil)
+ vs.FlowRemoveFailure(tt.args.cntx, tt.args.cookie, tt.args.errorCode, tt.args.errReason)
case "cookie_not_found":
associatedFlows := map[string]bool{}
- flowPushCountMap := map[string]uint32{}
associatedFlows["cookie"] = true
vs := &VoltService{
VoltServiceOper: VoltServiceOper{
AssociatedFlows: associatedFlows,
},
- VoltServiceCfg: VoltServiceCfg{
- FlowPushCount: flowPushCountMap,
- },
+ VoltServiceCfg: VoltServiceCfg{},
}
- vs.FlowRemoveFailure(tt.args.cntx, tt.args.cookie, tt.args.errorCode, tt.args.errReason, nil)
+ vs.FlowRemoveFailure(tt.args.cntx, tt.args.cookie, tt.args.errorCode, tt.args.errReason)
}
})
}
@@ -560,7 +554,6 @@
pendingFlows := map[string]bool{}
pendingFlows["test_cookie"] = true
associatedFlows := map[string]bool{}
- flowPushCountMap := map[string]uint32{}
associatedFlows["test_cookie"] = true
vs := &VoltService{
VoltServiceOper: VoltServiceOper{
@@ -569,14 +562,13 @@
DsHSIAFlowsApplied: true,
},
VoltServiceCfg: VoltServiceCfg{
- Port: "test_port",
- FlowPushCount: flowPushCountMap,
+ Port: "test_port",
},
}
ga := GetApplication()
ga.PortsDisc.Store("test_port", voltPort)
ga.DevicesDisc.Store(test_device, voltDevice)
- vs.FlowInstallSuccess(tt.args.cntx, tt.args.cookie, tt.args.bwAvailInfo, tt.args.flowEventMap)
+ vs.FlowInstallSuccess(tt.args.cntx, tt.args.cookie, tt.args.bwAvailInfo)
})
}
}
@@ -2357,19 +2349,16 @@
pendingFlows["test_cookie"] = true
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
- flowPushCountMap := map[string]uint32{}
vs := &VoltService{
VoltServiceOper: VoltServiceOper{},
- VoltServiceCfg: VoltServiceCfg{
- FlowPushCount: flowPushCountMap,
- },
+ VoltServiceCfg: VoltServiceCfg{},
}
switch tt.name {
case "VoltService_FlowInstallFailure":
vs.PendingFlows = pendingFlows
- vs.FlowInstallFailure(tt.args.cntx, tt.args.cookie, tt.args.errorCode, tt.args.errReason, nil)
+ vs.FlowInstallFailure(tt.args.cntx, tt.args.cookie, tt.args.errorCode, tt.args.errReason)
case "PendingFlows[cookie]_false":
- vs.FlowInstallFailure(tt.args.cntx, tt.args.cookie, tt.args.errorCode, tt.args.errReason, nil)
+ vs.FlowInstallFailure(tt.args.cntx, tt.args.cookie, tt.args.errorCode, tt.args.errReason)
}
})
}
@@ -2396,14 +2385,11 @@
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
- flowPushCountMap := map[string]uint32{}
vs := &VoltService{
VoltServiceOper: VoltServiceOper{
Device: test_device,
},
- VoltServiceCfg: VoltServiceCfg{
- FlowPushCount: flowPushCountMap,
- },
+ VoltServiceCfg: VoltServiceCfg{},
}
ga := GetApplication()
ga.DevicesDisc.Store(test_device, voltDevice2)
@@ -2411,7 +2397,7 @@
dbintf := mocks.NewMockDBIntf(gomock.NewController(t))
db = dbintf
dbintf.EXPECT().PutService(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
- vs.FlowRemoveSuccess(tt.args.cntx, tt.args.cookie, tt.args.flowEventMap)
+ vs.FlowRemoveSuccess(tt.args.cntx, tt.args.cookie)
})
}
}
diff --git a/internal/pkg/application/timer.go b/internal/pkg/application/timer.go
index 42b16d8..7ad35c3 100644
--- a/internal/pkg/application/timer.go
+++ b/internal/pkg/application/timer.go
@@ -17,6 +17,7 @@
import (
"context"
+ "sync"
"time"
"voltha-go-controller/log"
)
@@ -34,7 +35,7 @@
pendingPoolTimer: false,
}
-var timerChannels = make(map[TimerType](chan bool))
+var timerChannels = sync.Map{}
// TimerCfg structure
type TimerCfg struct {
@@ -49,7 +50,8 @@
return
}
timerMap[timerType] = true
- timerChannels[timerType] = make(chan bool)
+ ch := make(chan bool)
+ timerChannels.Store(timerType, ch)
for {
select {
case <-time.After(cfg.tick):
@@ -59,7 +61,7 @@
case pendingPoolTimer:
va.removeExpiredGroups(cntx)
}
- case <-timerChannels[timerType]:
+ case <-ch:
return
}
}
@@ -67,7 +69,11 @@
// StopTimer to stop timers
func StopTimer() {
- for _, ch := range timerChannels {
+ timerChannels.Range(func(key, value interface{}) bool {
+ ch := value.(chan bool)
ch <- true
- }
+ /* Range calls function sequentially for each key and value present in the map.
+ If function returns false, range stops the iteration. */
+ return true
+ })
}
diff --git a/internal/pkg/application/vnets.go b/internal/pkg/application/vnets.go
index 72c43fd..80e8212 100644
--- a/internal/pkg/application/vnets.go
+++ b/internal/pkg/application/vnets.go
@@ -314,7 +314,7 @@
devicesToHandle = append(devicesToHandle, serialNum)
}
if len(devicesToHandle) == 0 {
- logger.Debugw(ctx, "Ignoring Duplicate VNET by name ", log.Fields{"Vnet": cfg.Name})
+ logger.Warnw(ctx, "Ignoring Duplicate VNET by name ", log.Fields{"Vnet": cfg.Name})
AppMutex.VnetMutex.Unlock()
return nil
}
@@ -761,7 +761,7 @@
func (vpv *VoltPortVnet) PortUpInd(cntx context.Context, device *VoltDevice, port string) {
logger.Infow(ctx, "Port UP Ind, pushing flows for the port", log.Fields{"Device": device, "Port": port, "VnetDhcp": vpv.DhcpRelay, "McastService": vpv.McastService})
if vpv.DeleteInProgress {
- logger.Warnw(ctx, "Ignoring VPV Port UP Ind, VPV deleteion In-Progress", log.Fields{"Device": device, "Port": port, "Vnet": vpv.VnetName})
+ logger.Warnw(ctx, "Ignoring VPV Port UP Ind, VPV deletion In-Progress", log.Fields{"Device": device, "Port": port, "Vnet": vpv.VnetName})
return
}
vpv.setDevice(device.Name)
@@ -856,7 +856,7 @@
return
}
logger.Infow(ctx, "VPV Port DOWN Ind, deleting all flows for services",
- log.Fields{"service count": vpv.servicesCount.Load()})
+ log.Fields{"service count": vpv.servicesCount.Load(), "Port": port})
//vpv.RangeOnServices(cntx, DelAllFlows)
vpv.DelTrapFlows(cntx)
@@ -977,6 +977,16 @@
return service
}
+func (vpv *VoltPortVnet) GetSvcFromVPV() *VoltService {
+ var service *VoltService
+ vpv.services.Range(func(key, value interface{}) bool {
+ service = value.(*VoltService)
+ logger.Debugw(ctx, "Get Service from VPV", log.Fields{"Service": value})
+ return false
+ })
+ return service
+}
+
// GetRemarkedPriority : If the VNET matches priority of the incoming packet with any service, return true. Else, return false
func (vpv *VoltPortVnet) GetRemarkedPriority(priority uint8) uint8 {
logger.Debugw(ctx, "Get Remarked Priority", log.Fields{"Priority": priority})
@@ -1064,7 +1074,7 @@
voltDevice, err := GetApplication().GetDeviceFromPort(vpv.Port)
if err != nil {
- logger.Warnw(ctx, "Not pushing Service Flows: Error Getting Device", log.Fields{"Reason": err.Error()})
+ logger.Errorw(ctx, "Not pushing Service Flows: Error Getting Device", log.Fields{"Reason": err.Error()})
// statusCode, statusMessage := errorCodes.GetErrorInfo(err)
// TODO-COMM: vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
return
@@ -1078,7 +1088,7 @@
devConfig := GetApplication().GetDeviceConfig(voltDevice.SerialNum)
if devConfig.UplinkPort != voltDevice.NniPort {
- logger.Warnw(ctx, "NNI port mismatch", log.Fields{"NB NNI Port": devConfig.UplinkPort, "SB NNI port": voltDevice.NniPort})
+ logger.Errorw(ctx, "NNI port mismatch", log.Fields{"NB NNI Port": devConfig.UplinkPort, "SB NNI port": voltDevice.NniPort})
return
}
// Push Service Flows if DHCP relay is not configured
@@ -1308,7 +1318,7 @@
// DelHsiaFlows deletes the service flows
func (vpv *VoltPortVnet) DelHsiaFlows(cntx context.Context, delFlowsInDevice bool) {
- logger.Infow(ctx, "Received Delete Hsia Flows", log.Fields{"McastService": vpv.McastService})
+ logger.Debugw(ctx, "Received Delete Hsia Flows", log.Fields{"McastService": vpv.McastService})
// no HSIA flows for multicast service
if !vpv.McastService {
vpv.RangeOnServices(cntx, DelUsHsiaFlows, delFlowsInDevice)
@@ -1597,7 +1607,7 @@
// Write the status of the VPV to the DB once the delete is scheduled
// for dispatch
func (vpv *VoltPortVnet) DelDsPppoeFlows(cntx context.Context) error {
- logger.Debugw(ctx, "Deleting DS PPPoE flows", log.Fields{"STAG": vpv.SVlan, "CTAG": vpv.CVlan, "Device": vpv.Device})
+ logger.Infow(ctx, "Deleting DS PPPoE flows", log.Fields{"STAG": vpv.SVlan, "CTAG": vpv.CVlan, "Device": vpv.Device})
device, err := GetApplication().GetDeviceFromPort(vpv.Port)
if err != nil {
return fmt.Errorf("DS PPPoE Flow Delete Failed : DeviceName %s : %w", device.Name, err)
@@ -2401,17 +2411,22 @@
case ONUCVlan,
None:
service = vnet.MatchesPriority(priority)
- // In case of DHCP Flow - cvlan == VlanNone
// In case of HSIA Flow - cvlan == Svlan
- if len(vlans) == 1 && (vlans[0] == vnet.SVlan || vlans[0] == of.VlanNone) && service != nil {
+ // In case of DHCP flow, match for cvlan as we are setting cvlan for DHCP flows
+ if len(vlans) == 1 && (vlans[0] == vnet.CVlan || vlans[0] == of.VlanNone) && (service != nil && service.IsActivated) {
return service
}
- case OLTCVlanOLTSVlan,
- OLTSVlan:
+ case OLTCVlanOLTSVlan:
service = vnet.MatchesPriority(priority)
if len(vlans) == 1 && vlans[0] == vnet.UniVlan && service != nil {
return service
}
+ case OLTSVlan:
+ // For OLTSVlan, return only the active service attached to the VPV.
+ service = vnet.GetSvcFromVPV()
+ if service != nil && service.IsActivated {
+ return service
+ }
default:
logger.Warnw(ctx, "Invalid Vlan Control Option", log.Fields{"Value": vnet.VlanControl})
}
@@ -2696,7 +2711,7 @@
// DeleteDevFlowForVlanFromDevice to delete icmpv6 flow for vlan from device
func (va *VoltApplication) DeleteDevFlowForVlanFromDevice(cntx context.Context, vnet *VoltVnet, deviceSerialNum string) {
- logger.Debugw(ctx, "DeleteDevFlowForVlanFromDevice", log.Fields{"Device-serialNum": deviceSerialNum, "SVlan": vnet.SVlan, "CVlan": vnet.CVlan})
+ logger.Infow(ctx, "DeleteDevFlowForVlanFromDevice", log.Fields{"Device-serialNum": deviceSerialNum, "SVlan": vnet.SVlan, "CVlan": vnet.CVlan})
delflows := func(key interface{}, value interface{}) bool {
device := value.(*VoltDevice)
if device.SerialNum != deviceSerialNum {