First Commit of Voltha-Go-Controller from Radisys
Change-Id: I8e2e908e7ab09a4fe3d86849da18b6d69dcf4ab0
diff --git a/internal/pkg/application/flowevent.go b/internal/pkg/application/flowevent.go
new file mode 100644
index 0000000..4fe1a0a
--- /dev/null
+++ b/internal/pkg/application/flowevent.go
@@ -0,0 +1,192 @@
+/*
+* Copyright 2022-present Open Networking Foundation
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+ */
+
+package application
+
+import (
+ infraerrorcode "voltha-go-controller/internal/pkg/errorcodes/service"
+
+ "voltha-go-controller/internal/pkg/intf"
+ "github.com/opencord/voltha-lib-go/v7/pkg/log"
+)
+
+//Generic Framework to enabling all flow based event trigger and handling.
+//The eventMapper can be updated for dynamic func caller for future events
+
+//FlowEventType - Type of event enumeration
+type FlowEventType string
+
+//FlowEventHandler - Func prototype for flow event handling funcs
+type FlowEventHandler func(*FlowEvent, intf.FlowStatus)
+
+var eventMapper map[FlowEventType]FlowEventHandler
+
+const (
+ //EventTypeUsIgmpFlowAdded - Event type for IGMP US flow add
+ EventTypeUsIgmpFlowAdded FlowEventType = "USIgmpFlowAdded"
+ //EventTypeServiceFlowAdded - Event type for Service flow add
+ EventTypeServiceFlowAdded FlowEventType = "ServiceFlowAdded"
+ //EventTypeControlFlowAdded - Event type for Control flow add
+ EventTypeControlFlowAdded FlowEventType = "ControlFlowAdded"
+
+ //EventTypeDeviceFlowRemoved - Event type for Device flow del
+ EventTypeDeviceFlowRemoved FlowEventType = "DeviceFlowRemoved"
+ //EventTypeMcastFlowRemoved - Event type for Mcast flow del
+ EventTypeMcastFlowRemoved FlowEventType = "McastFlowRemoved"
+
+ //EventTypeServiceFlowRemoved - Event type for Service flow del
+ EventTypeServiceFlowRemoved FlowEventType = "ServiceFlowRemoved"
+ //EventTypeControlFlowRemoved - Event type for Control flow del
+ EventTypeControlFlowRemoved FlowEventType = "ControlFlowRemoved"
+)
+
+//FlowEvent - Event info for Flow event processing
+type FlowEvent struct {
+ eType FlowEventType
+ device string
+ cookie string
+ eventData interface{}
+}
+
+//InitEventFuncMapper - Initialization of flow event mapper
+func InitEventFuncMapper() {
+ eventMapper = map[FlowEventType]FlowEventHandler{
+ EventTypeUsIgmpFlowAdded: ProcessUsIgmpFlowAddEvent,
+ EventTypeControlFlowAdded: ProcessControlFlowAddEvent,
+ EventTypeServiceFlowAdded: ProcessServiceFlowAddEvent,
+ EventTypeControlFlowRemoved: ProcessControlFlowDelEvent,
+ EventTypeServiceFlowRemoved: ProcessServiceFlowDelEvent,
+ EventTypeDeviceFlowRemoved: ProcessDeviceFlowDelEvent,
+ EventTypeMcastFlowRemoved: ProcessMcastFlowDelEvent,
+ }
+}
+
+//ExecuteFlowEvent - Process flow based event triggers
+func ExecuteFlowEvent(vd *VoltDevice, cookie string, flowStatus intf.FlowStatus) bool {
+ var event interface{}
+
+ flowEventMap, err := vd.GetFlowEventRegister(flowStatus.FlowModType)
+ if err != nil {
+ logger.Debugw(ctx, "Flow event map does not exists", log.Fields{"flowMod": flowStatus.FlowModType, "Error": err})
+ return false
+ }
+ flowEventMap.MapLock.Lock()
+
+ if event, _ = flowEventMap.Get(cookie); event == nil {
+ logger.Debugw(ctx, "Event already processed or event not registered for the cookie", log.Fields{"Cookie": cookie})
+ flowEventMap.MapLock.Unlock()
+ return false
+ }
+ flowEventMap.Remove(cookie)
+ flowEventMap.MapLock.Unlock()
+ flowEvent := event.(*FlowEvent)
+ eventMapper[flowEvent.eType](flowEvent, flowStatus)
+ return true
+}
+
+//ProcessUsIgmpFlowAddEvent - Process Us Igmp Flow event trigger
+func ProcessUsIgmpFlowAddEvent(event *FlowEvent, flowStatus intf.FlowStatus) {
+
+ logger.Infow(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)
+ } else {
+ vpv.IgmpFlowInstallFailure(event.cookie, flowStatus.Status, flowStatus.Reason)
+ }
+}
+
+//ProcessServiceFlowAddEvent - Process Service Flow event trigger
+func ProcessServiceFlowAddEvent(event *FlowEvent, flowStatus intf.FlowStatus) {
+
+ logger.Infow(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(event.cookie, flowStatus.AdditionalData)
+ } else {
+ vs.FlowInstallFailure(event.cookie, flowStatus.Status, flowStatus.Reason)
+ }
+}
+
+//ProcessControlFlowAddEvent - Process Control Flow event trigger
+func ProcessControlFlowAddEvent(event *FlowEvent, flowStatus intf.FlowStatus) {
+
+ logger.Infow(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)
+ }
+}
+
+//ProcessServiceFlowDelEvent - Process Service Flow event trigger
+func ProcessServiceFlowDelEvent(event *FlowEvent, flowStatus intf.FlowStatus) {
+
+ logger.Infow(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(event.cookie)
+ } else {
+ vs.FlowRemoveFailure(event.cookie, flowStatus.Status, flowStatus.Reason)
+ }
+}
+
+//ProcessControlFlowDelEvent - Process Control Flow event trigger
+func ProcessControlFlowDelEvent(event *FlowEvent, flowStatus intf.FlowStatus) {
+
+ logger.Infow(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(event.cookie, event.device)
+ } else {
+ vpv.FlowRemoveFailure(event.cookie, event.device, flowStatus.Status, flowStatus.Reason)
+ }
+}
+
+//ProcessMcastFlowDelEvent - Process Control Flow event trigger
+func ProcessMcastFlowDelEvent(event *FlowEvent, flowStatus intf.FlowStatus) {
+
+ logger.Infow(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(event.cookie, event.device)
+ } else {
+ mvp.FlowRemoveFailure(event.cookie, event.device, flowStatus.Status, flowStatus.Reason)
+ }
+}
+
+//ProcessDeviceFlowDelEvent - Process Control Flow event trigger
+func ProcessDeviceFlowDelEvent(event *FlowEvent, flowStatus intf.FlowStatus) {
+
+ logger.Infow(ctx, "Processing Post Flow Remove Event for VNET", log.Fields{"Cookie": event.cookie, "event": event})
+ vnet := event.eventData.(*VoltVnet)
+ if isFlowStatusSuccess(flowStatus.Status, false) {
+ vnet.FlowRemoveSuccess(event.cookie, event.device)
+ } else {
+ vnet.FlowRemoveFailure(event.cookie, event.device, flowStatus.Status, flowStatus.Reason)
+ }
+}
+
+//TODO: Update the func or flowStatus struct once all flow status are based on NB error code
+func isFlowStatusSuccess(status uint32, flowAdd bool) bool {
+ result := false
+ errorCode := infraerrorcode.ErrorCode(status)
+
+ if errorCode == infraerrorcode.ErrOk {
+ result = true
+ } else if !flowAdd && errorCode == infraerrorcode.ErrNotExists {
+ result = true
+ }
+ return result
+}