VOL-2153 remove flow_utils.go from voltha-go

Change-Id: I81bdc9ed78e6a6b00a176f9c8366ff56fb7777b0
diff --git a/rw_core/core/device_agent.go b/rw_core/core/device_agent.go
index 4a5274b..c8e07a9 100755
--- a/rw_core/core/device_agent.go
+++ b/rw_core/core/device_agent.go
@@ -19,8 +19,9 @@
 	"context"
 	"fmt"
 	"github.com/gogo/protobuf/proto"
-	fu "github.com/opencord/voltha-go/rw_core/utils"
+	coreutils "github.com/opencord/voltha-go/rw_core/utils"
 	"github.com/opencord/voltha-lib-go/pkg/db/model"
+	fu "github.com/opencord/voltha-lib-go/pkg/flows"
 	"github.com/opencord/voltha-lib-go/pkg/log"
 	ic "github.com/opencord/voltha-protos/go/inter_container"
 	ofp "github.com/opencord/voltha-protos/go/openflow_13"
@@ -323,7 +324,7 @@
 	device.FlowGroups = &voltha.FlowGroups{Items: updatedGroups}
 	go agent.updateDeviceWithoutLockAsync(device, chdB)
 
-	if res := fu.WaitForNilOrErrorResponses(agent.defaultTimeout, chAdapters, chdB); res != nil {
+	if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, chAdapters, chdB); res != nil {
 		log.Debugw("Failed to get response from adapter[or] DB", log.Fields{"result": res})
 		return status.Errorf(codes.Aborted, "errors-%s", res)
 	}
@@ -414,7 +415,7 @@
 	device.FlowGroups = &voltha.FlowGroups{Items: groupsToKeep}
 	go agent.updateDeviceWithoutLockAsync(device, chdB)
 
-	if res := fu.WaitForNilOrErrorResponses(agent.defaultTimeout, chAdapters, chdB); res != nil {
+	if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, chAdapters, chdB); res != nil {
 		return status.Errorf(codes.Aborted, "errors-%s", res)
 	}
 	return nil
@@ -522,7 +523,7 @@
 	device.FlowGroups = &voltha.FlowGroups{Items: updatedGroups}
 	go agent.updateDeviceWithoutLockAsync(device, chdB)
 
-	if res := fu.WaitForNilOrErrorResponses(agent.defaultTimeout, chAdapters, chdB); res != nil {
+	if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, chAdapters, chdB); res != nil {
 		return status.Errorf(codes.Aborted, "errors-%s", res)
 	}
 	return nil
diff --git a/rw_core/core/logical_device_agent.go b/rw_core/core/logical_device_agent.go
index 21f65fa..c36e1a2 100644
--- a/rw_core/core/logical_device_agent.go
+++ b/rw_core/core/logical_device_agent.go
@@ -22,8 +22,9 @@
 	"github.com/gogo/protobuf/proto"
 	fd "github.com/opencord/voltha-go/rw_core/flow_decomposition"
 	"github.com/opencord/voltha-go/rw_core/graph"
-	fu "github.com/opencord/voltha-go/rw_core/utils"
+	coreutils "github.com/opencord/voltha-go/rw_core/utils"
 	"github.com/opencord/voltha-lib-go/pkg/db/model"
+	fu "github.com/opencord/voltha-lib-go/pkg/flows"
 	"github.com/opencord/voltha-lib-go/pkg/log"
 	ic "github.com/opencord/voltha-protos/go/inter_container"
 	ofp "github.com/opencord/voltha-protos/go/openflow_13"
@@ -406,7 +407,7 @@
 			}(child, ch)
 		}
 		// Wait for completion
-		if res := fu.WaitForNilOrErrorResponses(agent.defaultTimeout, chnlsList...); res != nil {
+		if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, chnlsList...); res != nil {
 			return status.Errorf(codes.Aborted, "errors-%s", res)
 		}
 	}
@@ -1034,7 +1035,7 @@
 		}(deviceId, value.ListFlows(), value.ListGroups())
 	}
 	// Wait for completion
-	if res := fu.WaitForNilOrErrorResponses(agent.defaultTimeout, chnlsList...); res != nil {
+	if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, chnlsList...); res != nil {
 		return status.Errorf(codes.Aborted, "errors-%s", res)
 	}
 	return nil
@@ -1056,7 +1057,7 @@
 		}(deviceId, value.ListFlows(), value.ListGroups())
 	}
 	// Wait for completion
-	if res := fu.WaitForNilOrErrorResponses(agent.defaultTimeout, chnlsList...); res != nil {
+	if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, chnlsList...); res != nil {
 		return status.Errorf(codes.Aborted, "errors-%s", res)
 	}
 	return nil
@@ -1078,7 +1079,7 @@
 		}(deviceId, value.ListFlows(), value.ListGroups())
 	}
 	// Wait for completion
-	if res := fu.WaitForNilOrErrorResponses(agent.defaultTimeout, chnlsList...); res != nil {
+	if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, chnlsList...); res != nil {
 		return status.Errorf(codes.Aborted, "errors-%s", res)
 	}
 	return nil
diff --git a/rw_core/flow_decomposition/flow_decomposer.go b/rw_core/flow_decomposition/flow_decomposer.go
index d28a803..ff9225c 100644
--- a/rw_core/flow_decomposition/flow_decomposer.go
+++ b/rw_core/flow_decomposition/flow_decomposer.go
@@ -20,7 +20,7 @@
 	"github.com/gogo/protobuf/proto"
 	"github.com/opencord/voltha-go/rw_core/coreIf"
 	"github.com/opencord/voltha-go/rw_core/graph"
-	fu "github.com/opencord/voltha-go/rw_core/utils"
+	fu "github.com/opencord/voltha-lib-go/pkg/flows"
 	"github.com/opencord/voltha-lib-go/pkg/log"
 	ofp "github.com/opencord/voltha-protos/go/openflow_13"
 	"github.com/opencord/voltha-protos/go/voltha"
diff --git a/rw_core/flow_decomposition/flow_decomposer_test.go b/rw_core/flow_decomposition/flow_decomposer_test.go
index 3264c12..37faa25 100644
--- a/rw_core/flow_decomposition/flow_decomposer_test.go
+++ b/rw_core/flow_decomposition/flow_decomposer_test.go
@@ -18,7 +18,7 @@
 import (
 	"errors"
 	"github.com/opencord/voltha-go/rw_core/graph"
-	fu "github.com/opencord/voltha-go/rw_core/utils"
+	fu "github.com/opencord/voltha-lib-go/pkg/flows"
 	"github.com/opencord/voltha-lib-go/pkg/log"
 	ofp "github.com/opencord/voltha-protos/go/openflow_13"
 	"github.com/opencord/voltha-protos/go/voltha"
diff --git a/rw_core/utils/flow_utils.go b/rw_core/utils/flow_utils.go
deleted file mode 100644
index 7cb718e..0000000
--- a/rw_core/utils/flow_utils.go
+++ /dev/null
@@ -1,1332 +0,0 @@
-/*
- * 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"
-	"crypto/md5"
-	"fmt"
-	"github.com/cevaris/ordered_map"
-	"github.com/gogo/protobuf/proto"
-	"github.com/opencord/voltha-lib-go/pkg/log"
-	ofp "github.com/opencord/voltha-protos/go/openflow_13"
-	"math/big"
-	"strings"
-)
-
-var (
-	// Instructions shortcut
-	APPLY_ACTIONS  = ofp.OfpInstructionType_OFPIT_APPLY_ACTIONS
-	WRITE_METADATA = ofp.OfpInstructionType_OFPIT_WRITE_METADATA
-	METER_ACTION   = ofp.OfpInstructionType_OFPIT_METER
-
-	//OFPAT_* shortcuts
-	OUTPUT       = ofp.OfpActionType_OFPAT_OUTPUT
-	COPY_TTL_OUT = ofp.OfpActionType_OFPAT_COPY_TTL_OUT
-	COPY_TTL_IN  = ofp.OfpActionType_OFPAT_COPY_TTL_IN
-	SET_MPLS_TTL = ofp.OfpActionType_OFPAT_SET_MPLS_TTL
-	DEC_MPLS_TTL = ofp.OfpActionType_OFPAT_DEC_MPLS_TTL
-	PUSH_VLAN    = ofp.OfpActionType_OFPAT_PUSH_VLAN
-	POP_VLAN     = ofp.OfpActionType_OFPAT_POP_VLAN
-	PUSH_MPLS    = ofp.OfpActionType_OFPAT_PUSH_MPLS
-	POP_MPLS     = ofp.OfpActionType_OFPAT_POP_MPLS
-	SET_QUEUE    = ofp.OfpActionType_OFPAT_SET_QUEUE
-	GROUP        = ofp.OfpActionType_OFPAT_GROUP
-	SET_NW_TTL   = ofp.OfpActionType_OFPAT_SET_NW_TTL
-	NW_TTL       = ofp.OfpActionType_OFPAT_DEC_NW_TTL
-	SET_FIELD    = ofp.OfpActionType_OFPAT_SET_FIELD
-	PUSH_PBB     = ofp.OfpActionType_OFPAT_PUSH_PBB
-	POP_PBB      = ofp.OfpActionType_OFPAT_POP_PBB
-	EXPERIMENTER = ofp.OfpActionType_OFPAT_EXPERIMENTER
-
-	//OFPXMT_OFB_* shortcuts (incomplete)
-	IN_PORT         = ofp.OxmOfbFieldTypes_OFPXMT_OFB_IN_PORT
-	IN_PHY_PORT     = ofp.OxmOfbFieldTypes_OFPXMT_OFB_IN_PHY_PORT
-	METADATA        = ofp.OxmOfbFieldTypes_OFPXMT_OFB_METADATA
-	ETH_DST         = ofp.OxmOfbFieldTypes_OFPXMT_OFB_ETH_DST
-	ETH_SRC         = ofp.OxmOfbFieldTypes_OFPXMT_OFB_ETH_SRC
-	ETH_TYPE        = ofp.OxmOfbFieldTypes_OFPXMT_OFB_ETH_TYPE
-	VLAN_VID        = ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID
-	VLAN_PCP        = ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP
-	IP_DSCP         = ofp.OxmOfbFieldTypes_OFPXMT_OFB_IP_DSCP
-	IP_ECN          = ofp.OxmOfbFieldTypes_OFPXMT_OFB_IP_ECN
-	IP_PROTO        = ofp.OxmOfbFieldTypes_OFPXMT_OFB_IP_PROTO
-	IPV4_SRC        = ofp.OxmOfbFieldTypes_OFPXMT_OFB_IPV4_SRC
-	IPV4_DST        = ofp.OxmOfbFieldTypes_OFPXMT_OFB_IPV4_DST
-	TCP_SRC         = ofp.OxmOfbFieldTypes_OFPXMT_OFB_TCP_SRC
-	TCP_DST         = ofp.OxmOfbFieldTypes_OFPXMT_OFB_TCP_DST
-	UDP_SRC         = ofp.OxmOfbFieldTypes_OFPXMT_OFB_UDP_SRC
-	UDP_DST         = ofp.OxmOfbFieldTypes_OFPXMT_OFB_UDP_DST
-	SCTP_SRC        = ofp.OxmOfbFieldTypes_OFPXMT_OFB_SCTP_SRC
-	SCTP_DST        = ofp.OxmOfbFieldTypes_OFPXMT_OFB_SCTP_DST
-	ICMPV4_TYPE     = ofp.OxmOfbFieldTypes_OFPXMT_OFB_ICMPV4_TYPE
-	ICMPV4_CODE     = ofp.OxmOfbFieldTypes_OFPXMT_OFB_ICMPV4_CODE
-	ARP_OP          = ofp.OxmOfbFieldTypes_OFPXMT_OFB_ARP_OP
-	ARP_SPA         = ofp.OxmOfbFieldTypes_OFPXMT_OFB_ARP_SPA
-	ARP_TPA         = ofp.OxmOfbFieldTypes_OFPXMT_OFB_ARP_TPA
-	ARP_SHA         = ofp.OxmOfbFieldTypes_OFPXMT_OFB_ARP_SHA
-	ARP_THA         = ofp.OxmOfbFieldTypes_OFPXMT_OFB_ARP_THA
-	IPV6_SRC        = ofp.OxmOfbFieldTypes_OFPXMT_OFB_IPV6_SRC
-	IPV6_DST        = ofp.OxmOfbFieldTypes_OFPXMT_OFB_IPV6_DST
-	IPV6_FLABEL     = ofp.OxmOfbFieldTypes_OFPXMT_OFB_IPV6_FLABEL
-	ICMPV6_TYPE     = ofp.OxmOfbFieldTypes_OFPXMT_OFB_ICMPV6_TYPE
-	ICMPV6_CODE     = ofp.OxmOfbFieldTypes_OFPXMT_OFB_ICMPV6_CODE
-	IPV6_ND_TARGET  = ofp.OxmOfbFieldTypes_OFPXMT_OFB_IPV6_ND_TARGET
-	OFB_IPV6_ND_SLL = ofp.OxmOfbFieldTypes_OFPXMT_OFB_IPV6_ND_SLL
-	IPV6_ND_TLL     = ofp.OxmOfbFieldTypes_OFPXMT_OFB_IPV6_ND_TLL
-	MPLS_LABEL      = ofp.OxmOfbFieldTypes_OFPXMT_OFB_MPLS_LABEL
-	MPLS_TC         = ofp.OxmOfbFieldTypes_OFPXMT_OFB_MPLS_TC
-	MPLS_BOS        = ofp.OxmOfbFieldTypes_OFPXMT_OFB_MPLS_BOS
-	PBB_ISID        = ofp.OxmOfbFieldTypes_OFPXMT_OFB_PBB_ISID
-	TUNNEL_ID       = ofp.OxmOfbFieldTypes_OFPXMT_OFB_TUNNEL_ID
-	IPV6_EXTHDR     = ofp.OxmOfbFieldTypes_OFPXMT_OFB_IPV6_EXTHDR
-)
-
-//ofp_action_* shortcuts
-
-func Output(port uint32, maxLen ...ofp.OfpControllerMaxLen) *ofp.OfpAction {
-	maxLength := ofp.OfpControllerMaxLen_OFPCML_MAX
-	if len(maxLen) > 0 {
-		maxLength = maxLen[0]
-	}
-	return &ofp.OfpAction{Type: OUTPUT, Action: &ofp.OfpAction_Output{Output: &ofp.OfpActionOutput{Port: port, MaxLen: uint32(maxLength)}}}
-}
-
-func MplsTtl(ttl uint32) *ofp.OfpAction {
-	return &ofp.OfpAction{Type: SET_MPLS_TTL, Action: &ofp.OfpAction_MplsTtl{MplsTtl: &ofp.OfpActionMplsTtl{MplsTtl: ttl}}}
-}
-
-func PushVlan(ethType uint32) *ofp.OfpAction {
-	return &ofp.OfpAction{Type: PUSH_VLAN, Action: &ofp.OfpAction_Push{Push: &ofp.OfpActionPush{Ethertype: ethType}}}
-}
-
-func PopVlan() *ofp.OfpAction {
-	return &ofp.OfpAction{Type: POP_VLAN}
-}
-
-func PopMpls(ethType uint32) *ofp.OfpAction {
-	return &ofp.OfpAction{Type: POP_MPLS, Action: &ofp.OfpAction_PopMpls{PopMpls: &ofp.OfpActionPopMpls{Ethertype: ethType}}}
-}
-
-func Group(groupId uint32) *ofp.OfpAction {
-	return &ofp.OfpAction{Type: GROUP, Action: &ofp.OfpAction_Group{Group: &ofp.OfpActionGroup{GroupId: groupId}}}
-}
-
-func NwTtl(nwTtl uint32) *ofp.OfpAction {
-	return &ofp.OfpAction{Type: NW_TTL, Action: &ofp.OfpAction_NwTtl{NwTtl: &ofp.OfpActionNwTtl{NwTtl: nwTtl}}}
-}
-
-func SetField(field *ofp.OfpOxmOfbField) *ofp.OfpAction {
-	actionSetField := &ofp.OfpOxmField{OxmClass: ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC, Field: &ofp.OfpOxmField_OfbField{OfbField: field}}
-	return &ofp.OfpAction{Type: SET_FIELD, Action: &ofp.OfpAction_SetField{SetField: &ofp.OfpActionSetField{Field: actionSetField}}}
-}
-
-func Experimenter(experimenter uint32, data []byte) *ofp.OfpAction {
-	return &ofp.OfpAction{Type: EXPERIMENTER, Action: &ofp.OfpAction_Experimenter{Experimenter: &ofp.OfpActionExperimenter{Experimenter: experimenter, Data: data}}}
-}
-
-//ofb_field generators (incomplete set)
-
-func InPort(inPort uint32) *ofp.OfpOxmOfbField {
-	return &ofp.OfpOxmOfbField{Type: IN_PORT, Value: &ofp.OfpOxmOfbField_Port{Port: inPort}}
-}
-
-func InPhyPort(inPhyPort uint32) *ofp.OfpOxmOfbField {
-	return &ofp.OfpOxmOfbField{Type: IN_PHY_PORT, Value: &ofp.OfpOxmOfbField_Port{Port: inPhyPort}}
-}
-
-func Metadata_ofp(tableMetadata uint64) *ofp.OfpOxmOfbField {
-	return &ofp.OfpOxmOfbField{Type: METADATA, Value: &ofp.OfpOxmOfbField_TableMetadata{TableMetadata: tableMetadata}}
-}
-
-// should Metadata_ofp used here ?????
-func EthDst(ethDst uint64) *ofp.OfpOxmOfbField {
-	return &ofp.OfpOxmOfbField{Type: ETH_DST, Value: &ofp.OfpOxmOfbField_TableMetadata{TableMetadata: ethDst}}
-}
-
-// should Metadata_ofp used here ?????
-func EthSrc(ethSrc uint64) *ofp.OfpOxmOfbField {
-	return &ofp.OfpOxmOfbField{Type: ETH_SRC, Value: &ofp.OfpOxmOfbField_TableMetadata{TableMetadata: ethSrc}}
-}
-
-func EthType(ethType uint32) *ofp.OfpOxmOfbField {
-	return &ofp.OfpOxmOfbField{Type: ETH_TYPE, Value: &ofp.OfpOxmOfbField_EthType{EthType: ethType}}
-}
-
-func VlanVid(vlanVid uint32) *ofp.OfpOxmOfbField {
-	return &ofp.OfpOxmOfbField{Type: VLAN_VID, Value: &ofp.OfpOxmOfbField_VlanVid{VlanVid: vlanVid}}
-}
-
-func VlanPcp(vlanPcp uint32) *ofp.OfpOxmOfbField {
-	return &ofp.OfpOxmOfbField{Type: VLAN_PCP, Value: &ofp.OfpOxmOfbField_VlanPcp{VlanPcp: vlanPcp}}
-}
-
-func IpDscp(ipDscp uint32) *ofp.OfpOxmOfbField {
-	return &ofp.OfpOxmOfbField{Type: IP_DSCP, Value: &ofp.OfpOxmOfbField_IpDscp{IpDscp: ipDscp}}
-}
-
-func IpEcn(ipEcn uint32) *ofp.OfpOxmOfbField {
-	return &ofp.OfpOxmOfbField{Type: IP_ECN, Value: &ofp.OfpOxmOfbField_IpEcn{IpEcn: ipEcn}}
-}
-
-func IpProto(ipProto uint32) *ofp.OfpOxmOfbField {
-	return &ofp.OfpOxmOfbField{Type: IP_PROTO, Value: &ofp.OfpOxmOfbField_IpProto{IpProto: ipProto}}
-}
-
-func Ipv4Src(ipv4Src uint32) *ofp.OfpOxmOfbField {
-	return &ofp.OfpOxmOfbField{Type: IPV4_SRC, Value: &ofp.OfpOxmOfbField_Ipv4Src{Ipv4Src: ipv4Src}}
-}
-
-func Ipv4Dst(ipv4Dst uint32) *ofp.OfpOxmOfbField {
-	return &ofp.OfpOxmOfbField{Type: IPV4_DST, Value: &ofp.OfpOxmOfbField_Ipv4Dst{Ipv4Dst: ipv4Dst}}
-}
-
-func TcpSrc(tcpSrc uint32) *ofp.OfpOxmOfbField {
-	return &ofp.OfpOxmOfbField{Type: TCP_SRC, Value: &ofp.OfpOxmOfbField_TcpSrc{TcpSrc: tcpSrc}}
-}
-
-func TcpDst(tcpDst uint32) *ofp.OfpOxmOfbField {
-	return &ofp.OfpOxmOfbField{Type: TCP_DST, Value: &ofp.OfpOxmOfbField_TcpDst{TcpDst: tcpDst}}
-}
-
-func UdpSrc(udpSrc uint32) *ofp.OfpOxmOfbField {
-	return &ofp.OfpOxmOfbField{Type: UDP_SRC, Value: &ofp.OfpOxmOfbField_UdpSrc{UdpSrc: udpSrc}}
-}
-
-func UdpDst(udpDst uint32) *ofp.OfpOxmOfbField {
-	return &ofp.OfpOxmOfbField{Type: UDP_DST, Value: &ofp.OfpOxmOfbField_UdpDst{UdpDst: udpDst}}
-}
-
-func SctpSrc(sctpSrc uint32) *ofp.OfpOxmOfbField {
-	return &ofp.OfpOxmOfbField{Type: SCTP_SRC, Value: &ofp.OfpOxmOfbField_SctpSrc{SctpSrc: sctpSrc}}
-}
-
-func SctpDst(sctpDst uint32) *ofp.OfpOxmOfbField {
-	return &ofp.OfpOxmOfbField{Type: SCTP_DST, Value: &ofp.OfpOxmOfbField_SctpDst{SctpDst: sctpDst}}
-}
-
-func Icmpv4Type(icmpv4Type uint32) *ofp.OfpOxmOfbField {
-	return &ofp.OfpOxmOfbField{Type: ICMPV4_TYPE, Value: &ofp.OfpOxmOfbField_Icmpv4Type{Icmpv4Type: icmpv4Type}}
-}
-
-func Icmpv4Code(icmpv4Code uint32) *ofp.OfpOxmOfbField {
-	return &ofp.OfpOxmOfbField{Type: ICMPV4_CODE, Value: &ofp.OfpOxmOfbField_Icmpv4Code{Icmpv4Code: icmpv4Code}}
-}
-
-func ArpOp(arpOp uint32) *ofp.OfpOxmOfbField {
-	return &ofp.OfpOxmOfbField{Type: ARP_OP, Value: &ofp.OfpOxmOfbField_ArpOp{ArpOp: arpOp}}
-}
-
-func ArpSpa(arpSpa uint32) *ofp.OfpOxmOfbField {
-	return &ofp.OfpOxmOfbField{Type: ARP_SPA, Value: &ofp.OfpOxmOfbField_ArpSpa{ArpSpa: arpSpa}}
-}
-
-func ArpTpa(arpTpa uint32) *ofp.OfpOxmOfbField {
-	return &ofp.OfpOxmOfbField{Type: ARP_TPA, Value: &ofp.OfpOxmOfbField_ArpTpa{ArpTpa: arpTpa}}
-}
-
-func ArpSha(arpSha []byte) *ofp.OfpOxmOfbField {
-	return &ofp.OfpOxmOfbField{Type: ARP_SHA, Value: &ofp.OfpOxmOfbField_ArpSha{ArpSha: arpSha}}
-}
-
-func ArpTha(arpTha []byte) *ofp.OfpOxmOfbField {
-	return &ofp.OfpOxmOfbField{Type: ARP_THA, Value: &ofp.OfpOxmOfbField_ArpTha{ArpTha: arpTha}}
-}
-
-func Ipv6Src(ipv6Src []byte) *ofp.OfpOxmOfbField {
-	return &ofp.OfpOxmOfbField{Type: IPV6_SRC, Value: &ofp.OfpOxmOfbField_Ipv6Src{Ipv6Src: ipv6Src}}
-}
-
-func Ipv6Dst(ipv6Dst []byte) *ofp.OfpOxmOfbField {
-	return &ofp.OfpOxmOfbField{Type: IPV6_DST, Value: &ofp.OfpOxmOfbField_Ipv6Dst{Ipv6Dst: ipv6Dst}}
-}
-
-func Ipv6Flabel(ipv6Flabel uint32) *ofp.OfpOxmOfbField {
-	return &ofp.OfpOxmOfbField{Type: IPV6_FLABEL, Value: &ofp.OfpOxmOfbField_Ipv6Flabel{Ipv6Flabel: ipv6Flabel}}
-}
-
-func Icmpv6Type(icmpv6Type uint32) *ofp.OfpOxmOfbField {
-	return &ofp.OfpOxmOfbField{Type: ICMPV6_TYPE, Value: &ofp.OfpOxmOfbField_Icmpv6Type{Icmpv6Type: icmpv6Type}}
-}
-
-func Icmpv6Code(icmpv6Code uint32) *ofp.OfpOxmOfbField {
-	return &ofp.OfpOxmOfbField{Type: ICMPV6_CODE, Value: &ofp.OfpOxmOfbField_Icmpv6Code{Icmpv6Code: icmpv6Code}}
-}
-
-func Ipv6NdTarget(ipv6NdTarget []byte) *ofp.OfpOxmOfbField {
-	return &ofp.OfpOxmOfbField{Type: IPV6_ND_TARGET, Value: &ofp.OfpOxmOfbField_Ipv6NdTarget{Ipv6NdTarget: ipv6NdTarget}}
-}
-
-func OfbIpv6NdSll(ofbIpv6NdSll []byte) *ofp.OfpOxmOfbField {
-	return &ofp.OfpOxmOfbField{Type: OFB_IPV6_ND_SLL, Value: &ofp.OfpOxmOfbField_Ipv6NdSsl{Ipv6NdSsl: ofbIpv6NdSll}}
-}
-
-func Ipv6NdTll(ipv6NdTll []byte) *ofp.OfpOxmOfbField {
-	return &ofp.OfpOxmOfbField{Type: IPV6_ND_TLL, Value: &ofp.OfpOxmOfbField_Ipv6NdTll{Ipv6NdTll: ipv6NdTll}}
-}
-
-func MplsLabel(mplsLabel uint32) *ofp.OfpOxmOfbField {
-	return &ofp.OfpOxmOfbField{Type: MPLS_LABEL, Value: &ofp.OfpOxmOfbField_MplsLabel{MplsLabel: mplsLabel}}
-}
-
-func MplsTc(mplsTc uint32) *ofp.OfpOxmOfbField {
-	return &ofp.OfpOxmOfbField{Type: MPLS_TC, Value: &ofp.OfpOxmOfbField_MplsTc{MplsTc: mplsTc}}
-}
-
-func MplsBos(mplsBos uint32) *ofp.OfpOxmOfbField {
-	return &ofp.OfpOxmOfbField{Type: MPLS_BOS, Value: &ofp.OfpOxmOfbField_MplsBos{MplsBos: mplsBos}}
-}
-
-func PbbIsid(pbbIsid uint32) *ofp.OfpOxmOfbField {
-	return &ofp.OfpOxmOfbField{Type: PBB_ISID, Value: &ofp.OfpOxmOfbField_PbbIsid{PbbIsid: pbbIsid}}
-}
-
-func TunnelId(tunnelId uint64) *ofp.OfpOxmOfbField {
-	return &ofp.OfpOxmOfbField{Type: TUNNEL_ID, Value: &ofp.OfpOxmOfbField_TunnelId{TunnelId: tunnelId}}
-}
-
-func Ipv6Exthdr(ipv6Exthdr uint32) *ofp.OfpOxmOfbField {
-	return &ofp.OfpOxmOfbField{Type: IPV6_EXTHDR, Value: &ofp.OfpOxmOfbField_Ipv6Exthdr{Ipv6Exthdr: ipv6Exthdr}}
-}
-
-//frequently used extractors
-
-func excludeAction(action *ofp.OfpAction, exclude ...ofp.OfpActionType) bool {
-	for _, actionToExclude := range exclude {
-		if action.Type == actionToExclude {
-			return true
-		}
-	}
-	return false
-}
-
-func GetActions(flow *ofp.OfpFlowStats, exclude ...ofp.OfpActionType) []*ofp.OfpAction {
-	if flow == nil {
-		return nil
-	}
-	for _, instruction := range flow.Instructions {
-		if instruction.Type == uint32(ofp.OfpInstructionType_OFPIT_APPLY_ACTIONS) {
-			instActions := instruction.GetActions()
-			if instActions == nil {
-				return nil
-			}
-			if len(exclude) == 0 {
-				return instActions.Actions
-			} else {
-				filteredAction := make([]*ofp.OfpAction, 0)
-				for _, action := range instActions.Actions {
-					if !excludeAction(action, exclude...) {
-						filteredAction = append(filteredAction, action)
-					}
-				}
-				return filteredAction
-			}
-		}
-	}
-	return nil
-}
-
-func UpdateOutputPortByActionType(flow *ofp.OfpFlowStats, actionType uint32, toPort uint32) *ofp.OfpFlowStats {
-	if flow == nil {
-		return nil
-	}
-	nFlow := (proto.Clone(flow)).(*ofp.OfpFlowStats)
-	nFlow.Instructions = nil
-	nInsts := make([]*ofp.OfpInstruction, 0)
-	for _, instruction := range flow.Instructions {
-		if instruction.Type == actionType {
-			instActions := instruction.GetActions()
-			if instActions == nil {
-				return nil
-			}
-			nActions := make([]*ofp.OfpAction, 0)
-			for _, action := range instActions.Actions {
-				if action.GetOutput() != nil {
-					nActions = append(nActions, Output(toPort))
-				} else {
-					nActions = append(nActions, action)
-				}
-			}
-			instructionAction := ofp.OfpInstruction_Actions{Actions: &ofp.OfpInstructionActions{Actions: nActions}}
-			nInsts = append(nInsts, &ofp.OfpInstruction{Type: uint32(APPLY_ACTIONS), Data: &instructionAction})
-		} else {
-			nInsts = append(nInsts, instruction)
-		}
-	}
-	nFlow.Instructions = nInsts
-	return nFlow
-}
-
-func excludeOxmOfbField(field *ofp.OfpOxmOfbField, exclude ...ofp.OxmOfbFieldTypes) bool {
-	for _, fieldToExclude := range exclude {
-		if field.Type == fieldToExclude {
-			return true
-		}
-	}
-	return false
-}
-
-func GetOfbFields(flow *ofp.OfpFlowStats, exclude ...ofp.OxmOfbFieldTypes) []*ofp.OfpOxmOfbField {
-	if flow == nil || flow.Match == nil || flow.Match.Type != ofp.OfpMatchType_OFPMT_OXM {
-		return nil
-	}
-	ofbFields := make([]*ofp.OfpOxmOfbField, 0)
-	for _, field := range flow.Match.OxmFields {
-		if field.OxmClass == ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
-			ofbFields = append(ofbFields, field.GetOfbField())
-		}
-	}
-	if len(exclude) == 0 {
-		return ofbFields
-	} else {
-		filteredFields := make([]*ofp.OfpOxmOfbField, 0)
-		for _, ofbField := range ofbFields {
-			if !excludeOxmOfbField(ofbField, exclude...) {
-				filteredFields = append(filteredFields, ofbField)
-			}
-		}
-		return filteredFields
-	}
-}
-
-func GetPacketOutPort(packet *ofp.OfpPacketOut) uint32 {
-	if packet == nil {
-		return 0
-	}
-	for _, action := range packet.GetActions() {
-		if action.Type == OUTPUT {
-			return action.GetOutput().Port
-		}
-	}
-	return 0
-}
-
-func GetOutPort(flow *ofp.OfpFlowStats) uint32 {
-	if flow == nil {
-		return 0
-	}
-	for _, action := range GetActions(flow) {
-		if action.Type == OUTPUT {
-			out := action.GetOutput()
-			if out == nil {
-				return 0
-			}
-			return out.GetPort()
-		}
-	}
-	return 0
-}
-
-func GetInPort(flow *ofp.OfpFlowStats) uint32 {
-	if flow == nil {
-		return 0
-	}
-	for _, field := range GetOfbFields(flow) {
-		if field.Type == IN_PORT {
-			return field.GetPort()
-		}
-	}
-	return 0
-}
-
-func GetGotoTableId(flow *ofp.OfpFlowStats) uint32 {
-	if flow == nil {
-		return 0
-	}
-	for _, instruction := range flow.Instructions {
-		if instruction.Type == uint32(ofp.OfpInstructionType_OFPIT_GOTO_TABLE) {
-			gotoTable := instruction.GetGotoTable()
-			if gotoTable == nil {
-				return 0
-			}
-			return gotoTable.GetTableId()
-		}
-	}
-	return 0
-}
-
-func GetMeterId(flow *ofp.OfpFlowStats) uint32 {
-	if flow == nil {
-		return 0
-	}
-	for _, instruction := range flow.Instructions {
-		if instruction.Type == uint32(ofp.OfpInstructionType_OFPIT_METER) {
-			MeterInstruction := instruction.GetMeter()
-			if MeterInstruction == nil {
-				return 0
-			}
-			return MeterInstruction.GetMeterId()
-		}
-	}
-	return 0
-}
-
-func GetVlanVid(flow *ofp.OfpFlowStats) *uint32 {
-	if flow == nil {
-		return nil
-	}
-	for _, field := range GetOfbFields(flow) {
-		if field.Type == VLAN_VID {
-			ret := field.GetVlanVid()
-			return &ret
-		}
-	}
-	// Dont return 0 if the field is missing as vlan id value 0 has meaning and cannot be overloaded as "not found"
-	return nil
-}
-
-func GetTunnelId(flow *ofp.OfpFlowStats) uint64 {
-	if flow == nil {
-		return 0
-	}
-	for _, field := range GetOfbFields(flow) {
-		if field.Type == TUNNEL_ID {
-			return field.GetTunnelId()
-		}
-	}
-	return 0
-}
-
-//GetMetaData - legacy get method (only want lower 32 bits)
-func GetMetaData(flow *ofp.OfpFlowStats) uint32 {
-	if flow == nil {
-		return 0
-	}
-	for _, field := range GetOfbFields(flow) {
-		if field.Type == METADATA {
-			return uint32(field.GetTableMetadata() & 0xFFFFFFFF)
-		}
-	}
-	log.Debug("No-metadata-present")
-	return 0
-}
-
-func GetMetaData64Bit(flow *ofp.OfpFlowStats) uint64 {
-	if flow == nil {
-		return 0
-	}
-	for _, field := range GetOfbFields(flow) {
-		if field.Type == METADATA {
-			return field.GetTableMetadata()
-		}
-	}
-	log.Debug("No-metadata-present")
-	return 0
-}
-
-// function returns write metadata value from write_metadata action field
-func GetMetadataFromWriteMetadataAction(flow *ofp.OfpFlowStats) uint64 {
-	if flow != nil {
-		for _, instruction := range flow.Instructions {
-			if instruction.Type == uint32(WRITE_METADATA) {
-				if writeMetadata := instruction.GetWriteMetadata(); writeMetadata != nil {
-					return writeMetadata.GetMetadata()
-				}
-			}
-		}
-	}
-	log.Debugw("No-write-metadata-present", log.Fields{"flow": flow})
-	return 0
-}
-
-func GetTechProfileIDFromWriteMetaData(metadata uint64) uint16 {
-	/*
-	   Write metadata instruction value (metadata) is 8 bytes:
-	   MS 2 bytes: C Tag
-	   Next 2 bytes: Technology Profile Id
-	   Next 4 bytes: Port number (uni or nni)
-
-	   This is set in the ONOS OltPipeline as a write metadata instruction
-	*/
-	var tpId uint16 = 0
-	log.Debugw("Write metadata value for Techprofile ID", log.Fields{"metadata": metadata})
-	if metadata != 0 {
-		tpId = uint16((metadata >> 32) & 0xFFFF)
-		log.Debugw("Found techprofile ID from write metadata action", log.Fields{"tpid": tpId})
-	}
-	return tpId
-}
-
-func GetEgressPortNumberFromWriteMetadata(flow *ofp.OfpFlowStats) uint32 {
-	/*
-			  Write metadata instruction value (metadata) is 8 bytes:
-		    	MS 2 bytes: C Tag
-		    	Next 2 bytes: Technology Profile Id
-		    	Next 4 bytes: Port number (uni or nni)
-		    	This is set in the ONOS OltPipeline as a write metadata instruction
-	*/
-	var uniPort uint32 = 0
-	md := GetMetadataFromWriteMetadataAction(flow)
-	log.Debugw("Metadata found for egress/uni port ", log.Fields{"metadata": md})
-	if md != 0 {
-		uniPort = uint32(md & 0xFFFFFFFF)
-		log.Debugw("Found EgressPort from write metadata action", log.Fields{"egress_port": uniPort})
-	}
-	return uniPort
-
-}
-
-func GetInnerTagFromMetaData(flow *ofp.OfpFlowStats) uint16 {
-	/*
-			  Write metadata instruction value (metadata) is 8 bytes:
-		    	MS 2 bytes: C Tag
-		    	Next 2 bytes: Technology Profile Id
-		    	Next 4 bytes: Port number (uni or nni)
-		    	This is set in the ONOS OltPipeline as a write metadata instruction
-	*/
-	var innerTag uint16 = 0
-	md := GetMetadataFromWriteMetadataAction(flow)
-	if md != 0 {
-		innerTag = uint16((md >> 48) & 0xFFFF)
-		log.Debugw("Found  CVLAN from write metadate action", log.Fields{"c_vlan": innerTag})
-	}
-	return innerTag
-}
-
-//GetInnerTagFromMetaData retrieves the inner tag from the Metadata_ofp. The port number (UNI on ONU) is in the
-// lower 32-bits of Metadata_ofp and the inner_tag is in the upper 32-bits. This is set in the ONOS OltPipeline as
-//// a Metadata_ofp field
-/*func GetInnerTagFromMetaData(flow *ofp.OfpFlowStats) uint64 {
-	md := GetMetaData64Bit(flow)
-	if md == 0 {
-		return 0
-	}
-	if md <= 0xffffffff {
-		log.Debugw("onos-upgrade-suggested", log.Fields{"Metadata_ofp": md, "message": "Legacy MetaData detected form OltPipeline"})
-		return md
-	}
-	return (md >> 32) & 0xffffffff
-}*/
-
-// Extract the child device port from a flow that contains the parent device peer port.  Typically the UNI port of an
-// ONU child device.  Per TST agreement this will be the lower 32 bits of tunnel id reserving upper 32 bits for later
-// use
-func GetChildPortFromTunnelId(flow *ofp.OfpFlowStats) uint32 {
-	tid := GetTunnelId(flow)
-	if tid == 0 {
-		return 0
-	}
-	// Per TST agreement we are keeping any child port id (uni port id) in the lower 32 bits
-	return uint32(tid & 0xffffffff)
-}
-
-func HasNextTable(flow *ofp.OfpFlowStats) bool {
-	if flow == nil {
-		return false
-	}
-	return GetGotoTableId(flow) != 0
-}
-
-func GetGroup(flow *ofp.OfpFlowStats) uint32 {
-	if flow == nil {
-		return 0
-	}
-	for _, action := range GetActions(flow) {
-		if action.Type == GROUP {
-			grp := action.GetGroup()
-			if grp == nil {
-				return 0
-			}
-			return grp.GetGroupId()
-		}
-	}
-	return 0
-}
-
-func HasGroup(flow *ofp.OfpFlowStats) bool {
-	return GetGroup(flow) != 0
-}
-
-// GetNextTableId returns the next table ID if the "table_id" is present in the map, otherwise return nil
-func GetNextTableId(kw OfpFlowModArgs) *uint32 {
-	if val, exist := kw["table_id"]; exist {
-		ret := uint32(val)
-		return &ret
-	}
-	return nil
-}
-
-// GetMeterIdFlowModArgs returns the meterId if the "meter_id" is present in the map, otherwise return 0
-func GetMeterIdFlowModArgs(kw OfpFlowModArgs) uint32 {
-	if val, exist := kw["meter_id"]; exist {
-		return uint32(val)
-	}
-	return 0
-}
-
-// Function returns the metadata if the "write_metadata" is present in the map, otherwise return nil
-func GetMetadataFlowModArgs(kw OfpFlowModArgs) uint64 {
-	if val, exist := kw["write_metadata"]; exist {
-		ret := uint64(val)
-		return ret
-	}
-	return 0
-}
-
-// Return unique 64-bit integer hash for flow covering the following attributes:
-// 'table_id', 'priority', 'flags', 'cookie', 'match', '_instruction_string'
-func HashFlowStats(flow *ofp.OfpFlowStats) uint64 {
-	if flow == nil { // Should never happen
-		return 0
-	}
-	// Create string with the instructions field first
-	var instructionString bytes.Buffer
-	for _, instruction := range flow.Instructions {
-		instructionString.WriteString(instruction.String())
-	}
-	var flowString = fmt.Sprintf("%d%d%d%d%s%s", flow.TableId, flow.Priority, flow.Flags, flow.Cookie, flow.Match.String(), instructionString.String())
-	h := md5.New()
-	h.Write([]byte(flowString))
-	hash := big.NewInt(0)
-	hash.SetBytes(h.Sum(nil))
-	return hash.Uint64()
-}
-
-// flowStatsEntryFromFlowModMessage maps an ofp_flow_mod message to an ofp_flow_stats message
-func FlowStatsEntryFromFlowModMessage(mod *ofp.OfpFlowMod) *ofp.OfpFlowStats {
-	flow := &ofp.OfpFlowStats{}
-	if mod == nil {
-		return flow
-	}
-	flow.TableId = mod.TableId
-	flow.Priority = mod.Priority
-	flow.IdleTimeout = mod.IdleTimeout
-	flow.HardTimeout = mod.HardTimeout
-	flow.Flags = mod.Flags
-	flow.Cookie = mod.Cookie
-	flow.Match = mod.Match
-	flow.Instructions = mod.Instructions
-	flow.Id = HashFlowStats(flow)
-	return flow
-}
-
-func GroupEntryFromGroupMod(mod *ofp.OfpGroupMod) *ofp.OfpGroupEntry {
-	group := &ofp.OfpGroupEntry{}
-	if mod == nil {
-		return group
-	}
-	group.Desc = &ofp.OfpGroupDesc{Type: mod.Type, GroupId: mod.GroupId, Buckets: mod.Buckets}
-	group.Stats = &ofp.OfpGroupStats{GroupId: mod.GroupId}
-	//TODO do we need to instantiate bucket bins?
-	return group
-}
-
-// flowStatsEntryFromFlowModMessage maps an ofp_flow_mod message to an ofp_flow_stats message
-func MeterEntryFromMeterMod(meterMod *ofp.OfpMeterMod) *ofp.OfpMeterEntry {
-	bandStats := make([]*ofp.OfpMeterBandStats, 0)
-	meter := &ofp.OfpMeterEntry{Config: &ofp.OfpMeterConfig{},
-		Stats: &ofp.OfpMeterStats{BandStats: bandStats}}
-	if meterMod == nil {
-		log.Error("Invalid meter mod command")
-		return meter
-	}
-	// config init
-	meter.Config.MeterId = meterMod.MeterId
-	meter.Config.Flags = meterMod.Flags
-	meter.Config.Bands = meterMod.Bands
-	// meter stats init
-	meter.Stats.MeterId = meterMod.MeterId
-	meter.Stats.FlowCount = 0
-	meter.Stats.PacketInCount = 0
-	meter.Stats.ByteInCount = 0
-	meter.Stats.DurationSec = 0
-	meter.Stats.DurationNsec = 0
-	// band stats init
-	for _, _ = range meterMod.Bands {
-		band := &ofp.OfpMeterBandStats{}
-		band.PacketBandCount = 0
-		band.ByteBandCount = 0
-		bandStats = append(bandStats, band)
-	}
-	meter.Stats.BandStats = bandStats
-	log.Debugw("Allocated meter entry", log.Fields{"meter": *meter})
-	return meter
-
-}
-
-func GetMeterIdFromFlow(flow *ofp.OfpFlowStats) uint32 {
-	if flow != nil {
-		for _, instruction := range flow.Instructions {
-			if instruction.Type == uint32(METER_ACTION) {
-				if meterInst := instruction.GetMeter(); meterInst != nil {
-					return meterInst.GetMeterId()
-				}
-			}
-		}
-	}
-
-	return uint32(0)
-}
-
-func MkOxmFields(matchFields []ofp.OfpOxmField) []*ofp.OfpOxmField {
-	oxmFields := make([]*ofp.OfpOxmField, 0)
-	for _, matchField := range matchFields {
-		oxmField := ofp.OfpOxmField{OxmClass: ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC, Field: matchField.Field}
-		oxmFields = append(oxmFields, &oxmField)
-	}
-	return oxmFields
-}
-
-func MkInstructionsFromActions(actions []*ofp.OfpAction) []*ofp.OfpInstruction {
-	instructions := make([]*ofp.OfpInstruction, 0)
-	instructionAction := ofp.OfpInstruction_Actions{Actions: &ofp.OfpInstructionActions{Actions: actions}}
-	instruction := ofp.OfpInstruction{Type: uint32(APPLY_ACTIONS), Data: &instructionAction}
-	instructions = append(instructions, &instruction)
-	return instructions
-}
-
-// Convenience function to generare ofp_flow_mod message with OXM BASIC match composed from the match_fields, and
-// single APPLY_ACTIONS instruction with a list if ofp_action objects.
-func MkSimpleFlowMod(matchFields []*ofp.OfpOxmField, actions []*ofp.OfpAction, command *ofp.OfpFlowModCommand, kw OfpFlowModArgs) *ofp.OfpFlowMod {
-
-	// Process actions instructions
-	instructions := make([]*ofp.OfpInstruction, 0)
-	instructionAction := ofp.OfpInstruction_Actions{Actions: &ofp.OfpInstructionActions{Actions: actions}}
-	instruction := ofp.OfpInstruction{Type: uint32(APPLY_ACTIONS), Data: &instructionAction}
-	instructions = append(instructions, &instruction)
-
-	// Process next table
-	if tableId := GetNextTableId(kw); tableId != nil {
-		var instGotoTable ofp.OfpInstruction_GotoTable
-		instGotoTable.GotoTable = &ofp.OfpInstructionGotoTable{TableId: *tableId}
-		inst := ofp.OfpInstruction{Type: uint32(ofp.OfpInstructionType_OFPIT_GOTO_TABLE), Data: &instGotoTable}
-		instructions = append(instructions, &inst)
-	}
-	// Process meter action
-	if meterId := GetMeterIdFlowModArgs(kw); meterId != 0 {
-		var instMeter ofp.OfpInstruction_Meter
-		instMeter.Meter = &ofp.OfpInstructionMeter{MeterId: meterId}
-		inst := ofp.OfpInstruction{Type: uint32(METER_ACTION), Data: &instMeter}
-		instructions = append(instructions, &inst)
-	}
-	//process write_metadata action
-	if metadata := GetMetadataFlowModArgs(kw); metadata != 0 {
-		var instWriteMetadata ofp.OfpInstruction_WriteMetadata
-		instWriteMetadata.WriteMetadata = &ofp.OfpInstructionWriteMetadata{Metadata: metadata}
-		inst := ofp.OfpInstruction{Type: uint32(WRITE_METADATA), Data: &instWriteMetadata}
-		instructions = append(instructions, &inst)
-	}
-
-	// Process match fields
-	oxmFields := make([]*ofp.OfpOxmField, 0)
-	for _, matchField := range matchFields {
-		oxmField := ofp.OfpOxmField{OxmClass: ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC, Field: matchField.Field}
-		oxmFields = append(oxmFields, &oxmField)
-	}
-	var match ofp.OfpMatch
-	match.Type = ofp.OfpMatchType_OFPMT_OXM
-	match.OxmFields = oxmFields
-
-	// Create ofp_flow_message
-	msg := &ofp.OfpFlowMod{}
-	if command == nil {
-		msg.Command = ofp.OfpFlowModCommand_OFPFC_ADD
-	} else {
-		msg.Command = *command
-	}
-	msg.Instructions = instructions
-	msg.Match = &match
-
-	// Set the variadic argument values
-	msg = setVariadicModAttributes(msg, kw)
-
-	return msg
-}
-
-func MkMulticastGroupMod(groupId uint32, buckets []*ofp.OfpBucket, command *ofp.OfpGroupModCommand) *ofp.OfpGroupMod {
-	group := &ofp.OfpGroupMod{}
-	if command == nil {
-		group.Command = ofp.OfpGroupModCommand_OFPGC_ADD
-	} else {
-		group.Command = *command
-	}
-	group.Type = ofp.OfpGroupType_OFPGT_ALL
-	group.GroupId = groupId
-	group.Buckets = buckets
-	return group
-}
-
-//SetVariadicModAttributes sets only uint64 or uint32 fields of the ofp_flow_mod message
-func setVariadicModAttributes(mod *ofp.OfpFlowMod, args OfpFlowModArgs) *ofp.OfpFlowMod {
-	if args == nil {
-		return mod
-	}
-	for key, val := range args {
-		switch key {
-		case "cookie":
-			mod.Cookie = val
-		case "cookie_mask":
-			mod.CookieMask = val
-		case "table_id":
-			mod.TableId = uint32(val)
-		case "idle_timeout":
-			mod.IdleTimeout = uint32(val)
-		case "hard_timeout":
-			mod.HardTimeout = uint32(val)
-		case "priority":
-			mod.Priority = uint32(val)
-		case "buffer_id":
-			mod.BufferId = uint32(val)
-		case "out_port":
-			mod.OutPort = uint32(val)
-		case "out_group":
-			mod.OutGroup = uint32(val)
-		case "flags":
-			mod.Flags = uint32(val)
-		}
-	}
-	return mod
-}
-
-func MkPacketIn(port uint32, packet []byte) *ofp.OfpPacketIn {
-	packetIn := &ofp.OfpPacketIn{
-		Reason: ofp.OfpPacketInReason_OFPR_ACTION,
-		Match: &ofp.OfpMatch{
-			Type: ofp.OfpMatchType_OFPMT_OXM,
-			OxmFields: []*ofp.OfpOxmField{
-				{
-					OxmClass: ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC,
-					Field: &ofp.OfpOxmField_OfbField{
-						OfbField: InPort(port)},
-				},
-			},
-		},
-		Data: packet,
-	}
-	return packetIn
-}
-
-// MkFlowStat is a helper method to build flows
-func MkFlowStat(fa *FlowArgs) *ofp.OfpFlowStats {
-	//Build the match-fields
-	matchFields := make([]*ofp.OfpOxmField, 0)
-	for _, val := range fa.MatchFields {
-		matchFields = append(matchFields, &ofp.OfpOxmField{Field: &ofp.OfpOxmField_OfbField{OfbField: val}})
-	}
-	return FlowStatsEntryFromFlowModMessage(MkSimpleFlowMod(matchFields, fa.Actions, fa.Command, fa.KV))
-}
-
-func MkGroupStat(ga *GroupArgs) *ofp.OfpGroupEntry {
-	return GroupEntryFromGroupMod(MkMulticastGroupMod(ga.GroupId, ga.Buckets, ga.Command))
-}
-
-type OfpFlowModArgs map[string]uint64
-
-type FlowArgs struct {
-	MatchFields []*ofp.OfpOxmOfbField
-	Actions     []*ofp.OfpAction
-	Command     *ofp.OfpFlowModCommand
-	Priority    uint32
-	KV          OfpFlowModArgs
-}
-
-type GroupArgs struct {
-	GroupId uint32
-	Buckets []*ofp.OfpBucket
-	Command *ofp.OfpGroupModCommand
-}
-
-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) ListFlows() []*ofp.OfpFlowStats {
-	flows := make([]*ofp.OfpFlowStats, 0)
-	iter := fg.Flows.IterFunc()
-	for kv, ok := iter(); ok; kv, ok = iter() {
-		if protoMsg, isMsg := kv.Value.(*ofp.OfpFlowStats); isMsg {
-			flows = append(flows, protoMsg)
-		}
-	}
-	return flows
-}
-
-func (fg *FlowsAndGroups) ListGroups() []*ofp.OfpGroupEntry {
-	groups := make([]*ofp.OfpGroupEntry, 0)
-	iter := fg.Groups.IterFunc()
-	for kv, ok := iter(); ok; kv, ok = iter() {
-		if protoMsg, isMsg := kv.Value.(*ofp.OfpGroupEntry); isMsg {
-			groups = append(groups, protoMsg)
-		}
-	}
-	return groups
-}
-
-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 flow == nil {
-		return
-	}
-
-	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)
-	}
-}
-
-func (fg *FlowsAndGroups) AddGroup(group *ofp.OfpGroupEntry) {
-	if group == nil {
-		return
-	}
-
-	if fg.Flows == nil {
-		fg.Flows = ordered_map.NewOrderedMap()
-	}
-	if fg.Groups == nil {
-		fg.Groups = ordered_map.NewOrderedMap()
-	}
-	//Add group only if absent
-	if _, exist := fg.Groups.Get(group.Desc.GroupId); !exist {
-		fg.Groups.Set(group.Desc.GroupId, group)
-	}
-}
-
-//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()
-	if dr != nil {
-		for key, val := range dr.Rules {
-			if val != nil {
-				copyDR.Rules[key] = val.Copy()
-			}
-		}
-	}
-	return copyDR
-}
-
-func (dr *DeviceRules) ClearFlows(deviceId string) {
-	if _, exist := dr.Rules[deviceId]; exist {
-		dr.Rules[deviceId].Flows = ordered_map.NewOrderedMap()
-	}
-}
-
-func (dr *DeviceRules) FilterRules(deviceIds map[string]string) *DeviceRules {
-	filteredDR := NewDeviceRules()
-	for key, val := range dr.Rules {
-		if _, exist := deviceIds[key]; exist {
-			filteredDR.Rules[key] = val.Copy()
-		}
-	}
-	return filteredDR
-}
-
-func (dr *DeviceRules) AddFlow(deviceId string, flow *ofp.OfpFlowStats) {
-	if _, exist := dr.Rules[deviceId]; !exist {
-		dr.Rules[deviceId] = NewFlowsAndGroups()
-	}
-	dr.Rules[deviceId].AddFlow(flow)
-}
-
-func (dr *DeviceRules) GetRules() map[string]*FlowsAndGroups {
-	return dr.Rules
-}
-
-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) {
-	if _, ok := dr.Rules[deviceId]; !ok {
-		dr.Rules[deviceId] = NewFlowsAndGroups()
-	}
-	dr.Rules[deviceId] = fg
-}
-
-// CreateEntryIfNotExist creates a new deviceId in the Map if it does not exist and assigns an
-// empty FlowsAndGroups to it.  Otherwise, it does nothing.
-func (dr *DeviceRules) CreateEntryIfNotExist(deviceId string) {
-	if _, ok := dr.Rules[deviceId]; !ok {
-		dr.Rules[deviceId] = NewFlowsAndGroups()
-	}
-}
-
-/*
- *  Common flow routines
- */
-
-//FindOverlappingFlows return a list of overlapping flow(s) where mod is the flow request
-func FindOverlappingFlows(flows []*ofp.OfpFlowStats, mod *ofp.OfpFlowMod) []*ofp.OfpFlowStats {
-	return nil //TODO - complete implementation
-}
-
-// FindFlowById returns the index of the flow in the flows array if present. Otherwise, it returns -1
-func FindFlowById(flows []*ofp.OfpFlowStats, flow *ofp.OfpFlowStats) int {
-	for idx, f := range flows {
-		if flow.Id == f.Id {
-			return idx
-		}
-	}
-	return -1
-}
-
-// FindFlows returns the index in flows where flow if present.  Otherwise, it returns -1
-func FindFlows(flows []*ofp.OfpFlowStats, flow *ofp.OfpFlowStats) int {
-	for idx, f := range flows {
-		if FlowMatch(f, flow) {
-			return idx
-		}
-	}
-	return -1
-}
-
-//FlowMatch returns true if two flows matches on the following flow attributes:
-//TableId, Priority, Flags, Cookie, Match
-func FlowMatch(f1 *ofp.OfpFlowStats, f2 *ofp.OfpFlowStats) bool {
-	if f1 == nil || f2 == nil {
-		return false
-	}
-	keysMatter := []string{"TableId", "Priority", "Flags", "Cookie", "Match"}
-	for _, key := range keysMatter {
-		switch key {
-		case "TableId":
-			if f1.TableId != f2.TableId {
-				return false
-			}
-		case "Priority":
-			if f1.Priority != f2.Priority {
-				return false
-			}
-		case "Flags":
-			if f1.Flags != f2.Flags {
-				return false
-			}
-		case "Cookie":
-			if f1.Cookie != f2.Cookie {
-				return false
-			}
-		case "Match":
-			if strings.Compare(f1.Match.String(), f2.Match.String()) != 0 {
-				return false
-			}
-		}
-	}
-	return true
-}
-
-//FlowMatchesMod returns True if given flow is "covered" by the wildcard flow_mod, taking into consideration of
-//both exact matches as well as masks-based match fields if any. Otherwise return False
-func FlowMatchesMod(flow *ofp.OfpFlowStats, mod *ofp.OfpFlowMod) bool {
-	if flow == nil || mod == nil {
-		return false
-	}
-	//Check if flow.cookie is covered by mod.cookie and mod.cookie_mask
-	if (flow.Cookie & mod.CookieMask) != (mod.Cookie & mod.CookieMask) {
-		return false
-	}
-
-	//Check if flow.table_id is covered by flow_mod.table_id
-	if mod.TableId != uint32(ofp.OfpTable_OFPTT_ALL) && flow.TableId != mod.TableId {
-		return false
-	}
-
-	//Check out_port
-	if (mod.OutPort&0x7fffffff) != uint32(ofp.OfpPortNo_OFPP_ANY) && !FlowHasOutPort(flow, mod.OutPort) {
-		return false
-	}
-
-	//	Check out_group
-	if (mod.OutGroup&0x7fffffff) != uint32(ofp.OfpGroup_OFPG_ANY) && !FlowHasOutGroup(flow, mod.OutGroup) {
-		return false
-	}
-
-	//Priority is ignored
-
-	//Check match condition
-	//If the flow_mod match field is empty, that is a special case and indicates the flow entry matches
-	if (mod.Match == nil) || (mod.Match.OxmFields == nil) || (len(mod.Match.OxmFields) == 0) {
-		//If we got this far and the match is empty in the flow spec, than the flow matches
-		return true
-	} // TODO : implement the flow match analysis
-	return false
-
-}
-
-//FlowHasOutPort returns True if flow has a output command with the given out_port
-func FlowHasOutPort(flow *ofp.OfpFlowStats, outPort uint32) bool {
-	if flow == nil {
-		return false
-	}
-	for _, instruction := range flow.Instructions {
-		if instruction.Type == uint32(ofp.OfpInstructionType_OFPIT_APPLY_ACTIONS) {
-			if instruction.GetActions() == nil {
-				return false
-			}
-			for _, action := range instruction.GetActions().Actions {
-				if action.Type == ofp.OfpActionType_OFPAT_OUTPUT {
-					if (action.GetOutput() != nil) && (action.GetOutput().Port == outPort) {
-						return true
-					}
-				}
-
-			}
-		}
-	}
-	return false
-}
-
-//FlowHasOutGroup return True if flow has a output command with the given out_group
-func FlowHasOutGroup(flow *ofp.OfpFlowStats, groupID uint32) bool {
-	if flow == nil {
-		return false
-	}
-	for _, instruction := range flow.Instructions {
-		if instruction.Type == uint32(ofp.OfpInstructionType_OFPIT_APPLY_ACTIONS) {
-			if instruction.GetActions() == nil {
-				return false
-			}
-			for _, action := range instruction.GetActions().Actions {
-				if action.Type == ofp.OfpActionType_OFPAT_GROUP {
-					if (action.GetGroup() != nil) && (action.GetGroup().GroupId == groupID) {
-						return true
-					}
-				}
-
-			}
-		}
-	}
-	return false
-}
-
-//FindGroup returns index of group if found, else returns -1
-func FindGroup(groups []*ofp.OfpGroupEntry, groupId uint32) int {
-	for idx, group := range groups {
-		if group.Desc.GroupId == groupId {
-			return idx
-		}
-	}
-	return -1
-}
-
-func FlowsDeleteByGroupId(flows []*ofp.OfpFlowStats, groupId uint32) (bool, []*ofp.OfpFlowStats) {
-	toKeep := make([]*ofp.OfpFlowStats, 0)
-
-	for _, f := range flows {
-		if !FlowHasOutGroup(f, groupId) {
-			toKeep = append(toKeep, f)
-		}
-	}
-	return len(toKeep) < len(flows), toKeep
-}
-
-func ToOfpOxmField(from []*ofp.OfpOxmOfbField) []*ofp.OfpOxmField {
-	matchFields := make([]*ofp.OfpOxmField, 0)
-	for _, val := range from {
-		matchFields = append(matchFields, &ofp.OfpOxmField{Field: &ofp.OfpOxmField_OfbField{OfbField: val}})
-	}
-	return matchFields
-}
diff --git a/rw_core/utils/flow_utils_test.go b/rw_core/utils/flow_utils_test.go
deleted file mode 100644
index c51a778..0000000
--- a/rw_core/utils/flow_utils_test.go
+++ /dev/null
@@ -1,689 +0,0 @@
-/*
- * Copyright 2019-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 (
-	"github.com/opencord/voltha-lib-go/pkg/log"
-	ofp "github.com/opencord/voltha-protos/go/openflow_13"
-	"github.com/stretchr/testify/assert"
-	"google.golang.org/grpc/codes"
-	"google.golang.org/grpc/status"
-	"strings"
-	"testing"
-)
-
-func init() {
-	log.AddPackage(log.JSON, log.WarnLevel, nil)
-	timeoutError = status.Errorf(codes.Aborted, "timeout")
-	taskFailureError = status.Error(codes.Internal, "test failure task")
-}
-
-func TestFlowsAndGroups_AddFlow(t *testing.T) {
-	fg := NewFlowsAndGroups()
-	allFlows := fg.ListFlows()
-	assert.Equal(t, 0, len(allFlows))
-	fg.AddFlow(nil)
-	allFlows = fg.ListFlows()
-	assert.Equal(t, 0, len(allFlows))
-
-	var fa *FlowArgs
-	fa = &FlowArgs{
-		KV: OfpFlowModArgs{"priority": 500},
-		MatchFields: []*ofp.OfpOxmOfbField{
-			InPort(1),
-			VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 1),
-			TunnelId(uint64(1)),
-			EthType(0x0800),
-			Ipv4Dst(0xffffffff),
-			IpProto(17),
-			UdpSrc(68),
-			UdpDst(67),
-		},
-		Actions: []*ofp.OfpAction{
-			PushVlan(0x8100),
-			SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000)),
-			Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
-		},
-	}
-	flow := MkFlowStat(fa)
-	fg.AddFlow(flow)
-
-	allFlows = fg.ListFlows()
-	assert.Equal(t, 1, len(allFlows))
-	assert.True(t, FlowMatch(flow, allFlows[0]))
-}
-
-func TestFlowsAndGroups_AddGroup(t *testing.T) {
-	var ga *GroupArgs
-
-	fg := NewFlowsAndGroups()
-	allGroups := fg.ListGroups()
-	assert.Equal(t, 0, len(allGroups))
-	fg.AddGroup(nil)
-	allGroups = fg.ListGroups()
-	assert.Equal(t, 0, len(allGroups))
-
-	ga = &GroupArgs{
-		GroupId: 10,
-		Buckets: []*ofp.OfpBucket{
-			{Actions: []*ofp.OfpAction{
-				PopVlan(),
-				Output(1),
-			},
-			},
-		},
-	}
-	group := MkGroupStat(ga)
-	fg.AddGroup(group)
-
-	allGroups = fg.ListGroups()
-	assert.Equal(t, 1, len(allGroups))
-	assert.Equal(t, ga.GroupId, allGroups[0].Desc.GroupId)
-}
-
-func TestFlowsAndGroups_Copy(t *testing.T) {
-	fg := NewFlowsAndGroups()
-	var fa *FlowArgs
-	var ga *GroupArgs
-
-	fa = &FlowArgs{
-		KV: OfpFlowModArgs{"priority": 500},
-		MatchFields: []*ofp.OfpOxmOfbField{
-			InPort(2),
-			VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
-		},
-		Actions: []*ofp.OfpAction{
-			SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 10)),
-			Output(1),
-		},
-	}
-	flow := MkFlowStat(fa)
-	fg.AddFlow(flow)
-
-	ga = &GroupArgs{
-		GroupId: 10,
-		Buckets: []*ofp.OfpBucket{
-			{Actions: []*ofp.OfpAction{
-				PopVlan(),
-				Output(1),
-			},
-			},
-		},
-	}
-	group := MkGroupStat(ga)
-	fg.AddGroup(group)
-
-	fgCopy := fg.Copy()
-
-	allFlows := fgCopy.ListFlows()
-	assert.Equal(t, 1, len(allFlows))
-	assert.True(t, FlowMatch(flow, allFlows[0]))
-
-	allGroups := fgCopy.ListGroups()
-	assert.Equal(t, 1, len(allGroups))
-	assert.Equal(t, ga.GroupId, allGroups[0].Desc.GroupId)
-
-	fg = NewFlowsAndGroups()
-	fgCopy = fg.Copy()
-	allFlows = fgCopy.ListFlows()
-	allGroups = fgCopy.ListGroups()
-	assert.Equal(t, 0, len(allFlows))
-	assert.Equal(t, 0, len(allGroups))
-}
-
-func TestFlowsAndGroups_GetFlow(t *testing.T) {
-	fg := NewFlowsAndGroups()
-	var fa1 *FlowArgs
-	var fa2 *FlowArgs
-	var ga *GroupArgs
-
-	fa1 = &FlowArgs{
-		KV: OfpFlowModArgs{"priority": 500},
-		MatchFields: []*ofp.OfpOxmOfbField{
-			InPort(2),
-			Metadata_ofp((1000 << 32) | 1),
-			VlanPcp(0),
-		},
-		Actions: []*ofp.OfpAction{
-			PopVlan(),
-		},
-	}
-	flow1 := MkFlowStat(fa1)
-
-	fa2 = &FlowArgs{
-		KV: OfpFlowModArgs{"priority": 1500},
-		MatchFields: []*ofp.OfpOxmOfbField{
-			InPort(5),
-			VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
-		},
-		Actions: []*ofp.OfpAction{
-			PushVlan(0x8100),
-			SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 1000)),
-			SetField(VlanPcp(0)),
-			Output(2),
-		},
-	}
-	flow2 := MkFlowStat(fa2)
-
-	fg.AddFlow(flow1)
-	fg.AddFlow(flow2)
-
-	ga = &GroupArgs{
-		GroupId: 10,
-		Buckets: []*ofp.OfpBucket{
-			{Actions: []*ofp.OfpAction{
-				PopVlan(),
-				Output(1),
-			},
-			},
-		},
-	}
-	group := MkGroupStat(ga)
-	fg.AddGroup(group)
-
-	gf1 := fg.GetFlow(0)
-	assert.True(t, FlowMatch(flow1, gf1))
-
-	gf2 := fg.GetFlow(1)
-	assert.True(t, FlowMatch(flow2, gf2))
-
-	gf3 := fg.GetFlow(2)
-	assert.Nil(t, gf3)
-
-	allFlows := fg.ListFlows()
-	assert.True(t, FlowMatch(flow1, allFlows[0]))
-	assert.True(t, FlowMatch(flow2, allFlows[1]))
-}
-
-func TestFlowsAndGroups_String(t *testing.T) {
-	fg := NewFlowsAndGroups()
-	var fa *FlowArgs
-	var ga *GroupArgs
-
-	str := fg.String()
-	assert.True(t, str == "")
-
-	fa = &FlowArgs{
-		KV: OfpFlowModArgs{"priority": 500},
-		MatchFields: []*ofp.OfpOxmOfbField{
-			InPort(2),
-			VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
-			VlanPcp(0),
-			EthType(0x800),
-			Ipv4Dst(0xe00a0a0a),
-		},
-		Actions: []*ofp.OfpAction{
-			Group(10),
-		},
-	}
-	flow := MkFlowStat(fa)
-	fg.AddFlow(flow)
-
-	ga = &GroupArgs{
-		GroupId: 10,
-		Buckets: []*ofp.OfpBucket{
-			{Actions: []*ofp.OfpAction{
-				PopVlan(),
-				Output(1),
-			},
-			},
-		},
-	}
-	group := MkGroupStat(ga)
-	fg.AddGroup(group)
-
-	str = fg.String()
-	assert.True(t, strings.Contains(str, "id: 1143307409938767207"))
-	assert.True(t, strings.Contains(str, "group_id: 10"))
-	assert.True(t, strings.Contains(str, "oxm_class: OFPXMC_OPENFLOW_BASICOFPXMC_OPENFLOW_BASIC"))
-	assert.True(t, strings.Contains(str, "type: OFPXMT_OFB_VLAN_VIDOFPXMT_OFB_VLAN_VID"))
-	assert.True(t, strings.Contains(str, "vlan_vid: 4096"))
-	assert.True(t, strings.Contains(str, "buckets:"))
-}
-
-func TestFlowsAndGroups_AddFrom(t *testing.T) {
-	fg := NewFlowsAndGroups()
-	var fa *FlowArgs
-	var ga *GroupArgs
-
-	str := fg.String()
-	assert.True(t, str == "")
-
-	fa = &FlowArgs{
-		KV: OfpFlowModArgs{"priority": 500},
-		MatchFields: []*ofp.OfpOxmOfbField{
-			InPort(2),
-			VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
-			Metadata_ofp(1000),
-			TunnelId(uint64(1)),
-			VlanPcp(0),
-		},
-		Actions: []*ofp.OfpAction{
-			PopVlan(),
-			Output(1),
-		},
-	}
-	flow := MkFlowStat(fa)
-	fg.AddFlow(flow)
-
-	ga = &GroupArgs{
-		GroupId: 10,
-		Buckets: []*ofp.OfpBucket{
-			{Actions: []*ofp.OfpAction{
-				PopVlan(),
-				Output(1),
-			},
-			},
-		},
-	}
-	group := MkGroupStat(ga)
-	fg.AddGroup(group)
-
-	fg1 := NewFlowsAndGroups()
-	fg1.AddFrom(fg)
-
-	allFlows := fg1.ListFlows()
-	allGroups := fg1.ListGroups()
-	assert.Equal(t, 1, len(allFlows))
-	assert.Equal(t, 1, len(allGroups))
-	assert.True(t, FlowMatch(flow, allFlows[0]))
-	assert.Equal(t, group.Desc.GroupId, allGroups[0].Desc.GroupId)
-}
-
-func TestDeviceRules_AddFlow(t *testing.T) {
-	dr := NewDeviceRules()
-	rules := dr.GetRules()
-	assert.True(t, len(rules) == 0)
-
-	dr.AddFlow("123456", nil)
-	rules = dr.GetRules()
-	assert.True(t, len(rules) == 1)
-	val, ok := rules["123456"]
-	assert.True(t, ok)
-	assert.Equal(t, 0, len(val.ListFlows()))
-	assert.Equal(t, 0, len(val.ListGroups()))
-
-	var fa *FlowArgs
-	fa = &FlowArgs{
-		KV: OfpFlowModArgs{"priority": 500},
-		MatchFields: []*ofp.OfpOxmOfbField{
-			InPort(2),
-			VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
-			Metadata_ofp(1000),
-			TunnelId(uint64(1)),
-			VlanPcp(0),
-		},
-		Actions: []*ofp.OfpAction{
-			PopVlan(),
-			Output(1),
-		},
-	}
-	flow := MkFlowStat(fa)
-	dr.AddFlow("123456", flow)
-	rules = dr.GetRules()
-	assert.True(t, len(rules) == 1)
-	val, ok = rules["123456"]
-	assert.True(t, ok)
-	assert.Equal(t, 1, len(val.ListFlows()))
-	assert.True(t, FlowMatch(flow, val.ListFlows()[0]))
-	assert.Equal(t, 0, len(val.ListGroups()))
-}
-
-func TestDeviceRules_AddFlowsAndGroup(t *testing.T) {
-	fg := NewFlowsAndGroups()
-	var fa *FlowArgs
-	var ga *GroupArgs
-
-	str := fg.String()
-	assert.True(t, str == "")
-
-	fa = &FlowArgs{
-		KV: OfpFlowModArgs{"priority": 2000},
-		MatchFields: []*ofp.OfpOxmOfbField{
-			InPort(2),
-			VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
-			Metadata_ofp(1000),
-			TunnelId(uint64(1)),
-			VlanPcp(0),
-		},
-		Actions: []*ofp.OfpAction{
-			PopVlan(),
-			Output(1),
-		},
-	}
-	flow := MkFlowStat(fa)
-	fg.AddFlow(flow)
-
-	ga = &GroupArgs{
-		GroupId: 10,
-		Buckets: []*ofp.OfpBucket{
-			{Actions: []*ofp.OfpAction{
-				PopVlan(),
-				Output(1),
-			},
-			},
-		},
-	}
-	group := MkGroupStat(ga)
-	fg.AddGroup(group)
-
-	dr := NewDeviceRules()
-	dr.AddFlowsAndGroup("123456", fg)
-	rules := dr.GetRules()
-	assert.True(t, len(rules) == 1)
-	val, ok := rules["123456"]
-	assert.True(t, ok)
-	assert.Equal(t, 1, len(val.ListFlows()))
-	assert.Equal(t, 1, len(val.ListGroups()))
-	assert.True(t, FlowMatch(flow, val.ListFlows()[0]))
-	assert.Equal(t, 10, int(val.ListGroups()[0].Desc.GroupId))
-}
-
-func TestFlowHasOutPort(t *testing.T) {
-	var flow *ofp.OfpFlowStats
-	assert.False(t, FlowHasOutPort(flow, 1))
-
-	fa := &FlowArgs{
-		KV: OfpFlowModArgs{"priority": 2000},
-		MatchFields: []*ofp.OfpOxmOfbField{
-			InPort(2),
-			VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
-			Metadata_ofp(1000),
-			TunnelId(uint64(1)),
-			VlanPcp(0),
-		},
-		Actions: []*ofp.OfpAction{
-			PopVlan(),
-			Output(1),
-		},
-	}
-	flow = MkFlowStat(fa)
-	assert.True(t, FlowHasOutPort(flow, 1))
-	assert.False(t, FlowHasOutPort(flow, 2))
-
-	fa = &FlowArgs{
-		KV: OfpFlowModArgs{"priority": 2000},
-		MatchFields: []*ofp.OfpOxmOfbField{
-			InPort(2),
-			VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
-		},
-	}
-	flow = MkFlowStat(fa)
-	assert.False(t, FlowHasOutPort(flow, 1))
-}
-
-func TestFlowHasOutGroup(t *testing.T) {
-	var flow *ofp.OfpFlowStats
-	assert.False(t, FlowHasOutGroup(flow, 10))
-
-	fa := &FlowArgs{
-		KV: OfpFlowModArgs{"priority": 500},
-		MatchFields: []*ofp.OfpOxmOfbField{
-			InPort(2),
-			VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
-			VlanPcp(0),
-			EthType(0x800),
-			Ipv4Dst(0xe00a0a0a),
-		},
-		Actions: []*ofp.OfpAction{
-			Group(10),
-		},
-	}
-	flow = MkFlowStat(fa)
-	assert.True(t, FlowHasOutGroup(flow, 10))
-	assert.False(t, FlowHasOutGroup(flow, 11))
-
-	fa = &FlowArgs{
-		KV: OfpFlowModArgs{"priority": 500},
-		MatchFields: []*ofp.OfpOxmOfbField{
-			InPort(2),
-			VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
-			VlanPcp(0),
-			EthType(0x800),
-			Ipv4Dst(0xe00a0a0a),
-		},
-		Actions: []*ofp.OfpAction{
-			Output(1),
-		},
-	}
-	flow = MkFlowStat(fa)
-	assert.False(t, FlowHasOutGroup(flow, 1))
-}
-
-func TestMatchFlow(t *testing.T) {
-	assert.False(t, FlowMatch(nil, nil))
-	fa := &FlowArgs{
-		KV: OfpFlowModArgs{"priority": 500, "table_id": 1, "cookie": 38268468, "flags": 12},
-		MatchFields: []*ofp.OfpOxmOfbField{
-			InPort(2),
-			VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
-			VlanPcp(0),
-			EthType(0x800),
-			Ipv4Dst(0xe00a0a0a),
-		},
-		Actions: []*ofp.OfpAction{
-			Group(10),
-		},
-	}
-	flow1 := MkFlowStat(fa)
-	assert.False(t, FlowMatch(flow1, nil))
-
-	fa = &FlowArgs{
-		KV: OfpFlowModArgs{"priority": 500},
-		MatchFields: []*ofp.OfpOxmOfbField{
-			InPort(2),
-			VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
-			VlanPcp(0),
-			EthType(0x800),
-			Ipv4Dst(0xe00a0a0a),
-		},
-		Actions: []*ofp.OfpAction{
-			Group(10),
-		},
-	}
-	flow2 := MkFlowStat(fa)
-	assert.False(t, FlowMatch(flow1, flow2))
-	assert.False(t, FlowMatch(nil, flow2))
-
-	fa = &FlowArgs{
-		KV: OfpFlowModArgs{"priority": 500, "table_id": 1, "cookie": 38268468, "flags": 12},
-		MatchFields: []*ofp.OfpOxmOfbField{
-			InPort(2),
-			VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
-			VlanPcp(0),
-			EthType(0x800),
-			Ipv4Dst(0xe00a0a0a),
-		},
-	}
-	flow2 = MkFlowStat(fa)
-	assert.True(t, FlowMatch(flow1, flow2))
-
-	fa = &FlowArgs{
-		KV: OfpFlowModArgs{"priority": 501, "table_id": 1, "cookie": 38268468, "flags": 12},
-		MatchFields: []*ofp.OfpOxmOfbField{
-			InPort(2),
-			VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
-			VlanPcp(0),
-			EthType(0x800),
-			Ipv4Dst(0xe00a0a0a),
-		},
-		Actions: []*ofp.OfpAction{
-			Group(10),
-		},
-	}
-	flow2 = MkFlowStat(fa)
-	assert.False(t, FlowMatch(flow1, flow2))
-
-	fa = &FlowArgs{
-		KV: OfpFlowModArgs{"priority": 500, "table_id": 2, "cookie": 38268468, "flags": 12},
-		MatchFields: []*ofp.OfpOxmOfbField{
-			InPort(2),
-			VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
-			VlanPcp(0),
-			EthType(0x800),
-			Ipv4Dst(0xe00a0a0a),
-		},
-	}
-	flow2 = MkFlowStat(fa)
-	assert.False(t, FlowMatch(flow1, flow2))
-
-	fa = &FlowArgs{
-		KV: OfpFlowModArgs{"priority": 500, "table_id": 1, "cookie": 38268467, "flags": 12},
-		MatchFields: []*ofp.OfpOxmOfbField{
-			InPort(2),
-			VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
-			VlanPcp(0),
-			EthType(0x800),
-			Ipv4Dst(0xe00a0a0a),
-		},
-	}
-	flow2 = MkFlowStat(fa)
-	assert.False(t, FlowMatch(flow1, flow2))
-
-	fa = &FlowArgs{
-		KV: OfpFlowModArgs{"priority": 500, "table_id": 1, "cookie": 38268468, "flags": 14},
-		MatchFields: []*ofp.OfpOxmOfbField{
-			InPort(2),
-			VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
-			VlanPcp(0),
-			EthType(0x800),
-			Ipv4Dst(0xe00a0a0a),
-		},
-	}
-	flow2 = MkFlowStat(fa)
-	assert.False(t, FlowMatch(flow1, flow2))
-
-	fa = &FlowArgs{
-		KV: OfpFlowModArgs{"priority": 500, "table_id": 1, "cookie": 38268468, "flags": 12},
-		MatchFields: []*ofp.OfpOxmOfbField{
-			InPort(4),
-			VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
-			VlanPcp(0),
-			EthType(0x800),
-			Ipv4Dst(0xe00a0a0a),
-		},
-	}
-	flow2 = MkFlowStat(fa)
-	assert.False(t, FlowMatch(flow1, flow2))
-
-	fa = &FlowArgs{
-		KV: OfpFlowModArgs{"priority": 500, "table_id": 1, "cookie": 38268468, "flags": 12},
-		MatchFields: []*ofp.OfpOxmOfbField{
-			InPort(2),
-			VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
-			VlanPcp(0),
-			EthType(0x800),
-		},
-	}
-	flow2 = MkFlowStat(fa)
-	assert.False(t, FlowMatch(flow1, flow2))
-
-	fa = &FlowArgs{
-		KV: OfpFlowModArgs{"priority": 500, "table_id": 1, "cookie": 38268468, "flags": 12},
-		MatchFields: []*ofp.OfpOxmOfbField{
-			InPort(2),
-			VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
-			VlanPcp(0),
-			EthType(0x800),
-			Ipv4Dst(0xe00a0a0a),
-		},
-		Actions: []*ofp.OfpAction{
-			PopVlan(),
-			Output(1),
-		},
-	}
-	flow2 = MkFlowStat(fa)
-	assert.True(t, FlowMatch(flow1, flow2))
-}
-
-func TestFlowMatchesMod(t *testing.T) {
-	assert.False(t, FlowMatchesMod(nil, nil))
-	fa := &FlowArgs{
-		KV: OfpFlowModArgs{"priority": 500, "table_id": 1},
-		MatchFields: []*ofp.OfpOxmOfbField{
-			InPort(2),
-			VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
-			VlanPcp(0),
-			EthType(0x800),
-			Ipv4Dst(0xe00a0a0a),
-		},
-		Actions: []*ofp.OfpAction{
-			Output(1),
-			Group(10),
-		},
-	}
-	flow := MkFlowStat(fa)
-	assert.False(t, FlowMatchesMod(flow, nil))
-
-	fa = &FlowArgs{
-		KV: OfpFlowModArgs{"priority": 500, "table_id": 1},
-		MatchFields: []*ofp.OfpOxmOfbField{
-			InPort(2),
-			VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
-			VlanPcp(0),
-			EthType(0x800),
-			Ipv4Dst(0xe00a0a0a),
-		},
-		Actions: []*ofp.OfpAction{
-			PopVlan(),
-			Output(1),
-		},
-	}
-	flowMod := MkSimpleFlowMod(ToOfpOxmField(fa.MatchFields), fa.Actions, fa.Command, fa.KV)
-	assert.False(t, FlowMatchesMod(nil, flowMod))
-	assert.False(t, FlowMatchesMod(flow, flowMod))
-	assert.True(t, FlowMatch(flow, FlowStatsEntryFromFlowModMessage(flowMod)))
-
-	fa = &FlowArgs{
-		KV: OfpFlowModArgs{"table_id": uint64(ofp.OfpTable_OFPTT_ALL),
-			"cookie_mask": 0,
-			"out_port":    uint64(ofp.OfpPortNo_OFPP_ANY),
-			"out_group":   uint64(ofp.OfpGroup_OFPG_ANY),
-		},
-	}
-	flowMod = MkSimpleFlowMod(ToOfpOxmField(fa.MatchFields), fa.Actions, fa.Command, fa.KV)
-	assert.True(t, FlowMatchesMod(flow, flowMod))
-
-	fa = &FlowArgs{
-		KV: OfpFlowModArgs{"table_id": 1,
-			"cookie_mask": 0,
-			"out_port":    uint64(ofp.OfpPortNo_OFPP_ANY),
-			"out_group":   uint64(ofp.OfpGroup_OFPG_ANY),
-		},
-	}
-	flowMod = MkSimpleFlowMod(ToOfpOxmField(fa.MatchFields), fa.Actions, fa.Command, fa.KV)
-	assert.True(t, FlowMatchesMod(flow, flowMod))
-
-	fa = &FlowArgs{
-		KV: OfpFlowModArgs{"table_id": 1,
-			"cookie_mask": 0,
-			"out_port":    1,
-			"out_group":   uint64(ofp.OfpGroup_OFPG_ANY),
-		},
-	}
-	flowMod = MkSimpleFlowMod(ToOfpOxmField(fa.MatchFields), fa.Actions, fa.Command, fa.KV)
-	assert.True(t, FlowMatchesMod(flow, flowMod))
-
-	fa = &FlowArgs{
-		KV: OfpFlowModArgs{"table_id": 1,
-			"cookie_mask": 0,
-			"out_port":    1,
-			"out_group":   10,
-		},
-	}
-	flowMod = MkSimpleFlowMod(ToOfpOxmField(fa.MatchFields), fa.Actions, fa.Command, fa.KV)
-	assert.True(t, FlowMatchesMod(flow, flowMod))
-}