[VOL-1035] Initial submission of flow decomposition code.
Additional test cases will follow to test the core of the flow
decomposition functionality
Change-Id: Ie685714ce5ab54ac89501a67f9489613de195c15
diff --git a/rw_core/utils/flow_utils.go b/rw_core/utils/flow_utils.go
new file mode 100644
index 0000000..997c466
--- /dev/null
+++ b/rw_core/utils/flow_utils.go
@@ -0,0 +1,164 @@
+/*
+ * Copyright 2018-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 utils
+
+import (
+ "bytes"
+ "github.com/cevaris/ordered_map"
+ "github.com/gogo/protobuf/proto"
+ ofp "github.com/opencord/voltha-go/protos/openflow_13"
+)
+
+type OfpFlowModArgs map[string]uint64
+
+type FlowArgs struct {
+ MatchFields []*ofp.OfpOxmOfbField
+ Actions []*ofp.OfpAction
+ Command *ofp.OfpFlowModCommand
+ Priority uint32
+ KV OfpFlowModArgs
+}
+
+type FlowsAndGroups struct {
+ Flows *ordered_map.OrderedMap
+ Groups *ordered_map.OrderedMap
+}
+
+func NewFlowsAndGroups() *FlowsAndGroups {
+ var fg FlowsAndGroups
+ fg.Flows = ordered_map.NewOrderedMap()
+ fg.Groups = ordered_map.NewOrderedMap()
+ return &fg
+}
+
+func (fg *FlowsAndGroups) Copy() *FlowsAndGroups {
+ copyFG := NewFlowsAndGroups()
+ iter := fg.Flows.IterFunc()
+ for kv, ok := iter(); ok; kv, ok = iter() {
+ if protoMsg, isMsg := kv.Value.(*ofp.OfpFlowStats); isMsg {
+ copyFG.Flows.Set(kv.Key, proto.Clone(protoMsg))
+ }
+ }
+ iter = fg.Groups.IterFunc()
+ for kv, ok := iter(); ok; kv, ok = iter() {
+ if protoMsg, isMsg := kv.Value.(*ofp.OfpGroupEntry); isMsg {
+ copyFG.Groups.Set(kv.Key, proto.Clone(protoMsg))
+ }
+ }
+ return copyFG
+}
+
+func (fg *FlowsAndGroups) GetFlow(index int) *ofp.OfpFlowStats {
+ iter := fg.Flows.IterFunc()
+ pos := 0
+ for kv, ok := iter(); ok; kv, ok = iter() {
+ if pos == index {
+ if protoMsg, isMsg := kv.Value.(*ofp.OfpFlowStats); isMsg {
+ return protoMsg
+ }
+ return nil
+ }
+ pos += 1
+ }
+ return nil
+}
+
+func (fg *FlowsAndGroups) String() string {
+ var buffer bytes.Buffer
+ iter := fg.Flows.IterFunc()
+ for kv, ok := iter(); ok; kv, ok = iter() {
+ if protoMsg, isMsg := kv.Value.(*ofp.OfpFlowStats); isMsg {
+ buffer.WriteString("\nFlow:\n")
+ buffer.WriteString(proto.MarshalTextString(protoMsg))
+ buffer.WriteString("\n")
+ }
+ }
+ iter = fg.Groups.IterFunc()
+ for kv, ok := iter(); ok; kv, ok = iter() {
+ if protoMsg, isMsg := kv.Value.(*ofp.OfpGroupEntry); isMsg {
+ buffer.WriteString("\nGroup:\n")
+ buffer.WriteString(proto.MarshalTextString(protoMsg))
+ buffer.WriteString("\n")
+ }
+ }
+ return buffer.String()
+}
+
+func (fg *FlowsAndGroups) AddFlow(flow *ofp.OfpFlowStats) {
+ if fg.Flows == nil {
+ fg.Flows = ordered_map.NewOrderedMap()
+ }
+ if fg.Groups == nil {
+ fg.Groups = ordered_map.NewOrderedMap()
+ }
+ //Add flow only if absent
+ if _, exist := fg.Flows.Get(flow.Id); !exist {
+ fg.Flows.Set(flow.Id, flow)
+ }
+}
+
+//AddFrom add flows and groups from the argument into this structure only if they do not already exist
+func (fg *FlowsAndGroups) AddFrom(from *FlowsAndGroups) {
+ iter := from.Flows.IterFunc()
+ for kv, ok := iter(); ok; kv, ok = iter() {
+ if protoMsg, isMsg := kv.Value.(*ofp.OfpFlowStats); isMsg {
+ if _, exist := fg.Flows.Get(protoMsg.Id); !exist {
+ fg.Flows.Set(protoMsg.Id, protoMsg)
+ }
+ }
+ }
+ iter = from.Groups.IterFunc()
+ for kv, ok := iter(); ok; kv, ok = iter() {
+ if protoMsg, isMsg := kv.Value.(*ofp.OfpGroupEntry); isMsg {
+ if _, exist := fg.Groups.Get(protoMsg.Stats.GroupId); !exist {
+ fg.Groups.Set(protoMsg.Stats.GroupId, protoMsg)
+ }
+ }
+ }
+}
+
+type DeviceRules struct {
+ Rules map[string]*FlowsAndGroups
+}
+
+func NewDeviceRules() *DeviceRules {
+ var dr DeviceRules
+ dr.Rules = make(map[string]*FlowsAndGroups)
+ return &dr
+}
+
+func (dr *DeviceRules) Copy() *DeviceRules {
+ copyDR := NewDeviceRules()
+ for key, val := range dr.Rules {
+ copyDR.Rules[key] = val.Copy()
+ }
+ return copyDR
+}
+
+func (dr *DeviceRules) String() string {
+ var buffer bytes.Buffer
+ for key, value := range dr.Rules {
+ buffer.WriteString("DeviceId:")
+ buffer.WriteString(key)
+ buffer.WriteString(value.String())
+ buffer.WriteString("\n\n")
+ }
+ return buffer.String()
+}
+
+func (dr *DeviceRules) AddFlowsAndGroup(deviceId string, fg *FlowsAndGroups) {
+ dr.Rules[deviceId] = fg
+}