VOL-3212: Fix uni-trap flow match and actions

Change-Id: Iba217562a7631a9ab7dc49a4636d8f5f1a3e3a80
diff --git a/rw_core/flowdecomposition/flow_decomposer.go b/rw_core/flowdecomposition/flow_decomposer.go
index 2b4f194..986d911 100644
--- a/rw_core/flowdecomposition/flow_decomposer.go
+++ b/rw_core/flowdecomposition/flow_decomposer.go
@@ -144,7 +144,8 @@
 	} else {
 		// Trap flow for UNI port
 		logger.Debug(ctx, "trap-uni")
-
+		var setVid, setPcp uint32
+		var setVidOk, setPcpOk bool
 		//inPortNo is 0 for wildcard input case, do not include upstream port for controller bound flow in input
 		var inPorts = map[uint32]struct{}{inPortNo: {}}
 		if inPortNo == 0 {
@@ -162,8 +163,17 @@
 					fu.Output(egressHop.Egress),
 				},
 			}
-			// Augment the matchfields with the ofpfields from the flow
-			faParent.MatchFields = append(faParent.MatchFields, fu.GetOfbFields(flow, fu.IN_PORT)...)
+			// Augment the parent device flow matchfields with the ofpfields from the flow
+			faParent.MatchFields = append(faParent.MatchFields, fu.GetOfbFields(flow, fu.IN_PORT, fu.VLAN_VID, fu.VLAN_PCP)...)
+			// Augment the parent device flow matchfields with vlan vid and vlan pcp from action field.
+			// The child device is going to set the vlan and pcp and parent device has to match on them
+			if setVid, setVidOk = fu.GetSetActionField(ctx, flow, fu.VLAN_VID); setVidOk {
+				faParent.MatchFields = append(faParent.MatchFields, fu.VlanVid(setVid))
+				if setPcp, setPcpOk = fu.GetSetActionField(ctx, flow, fu.VLAN_PCP); setPcpOk {
+					faParent.MatchFields = append(faParent.MatchFields, fu.VlanPcp(setPcp))
+				}
+			}
+
 			fgParent := fu.NewFlowsAndGroups()
 			fs, err := fu.MkFlowStat(faParent)
 			if err != nil {
@@ -175,14 +185,16 @@
 
 			// Upstream flow on child (onu) device
 			var actions []*ofp.OfpAction
-			setvid := fu.GetVlanVid(flow)
-			if setvid != nil {
+			if setVidOk {
 				// have this child push the vlan the parent is matching/trapping on above
 				actions = []*ofp.OfpAction{
 					fu.PushVlan(0x8100),
-					fu.SetField(fu.VlanVid(*setvid)),
+					fu.SetField(fu.VlanVid(setVid)),
 					fu.Output(ingressHop.Egress),
 				}
+				if setPcpOk {
+					actions = append(actions, fu.SetField(fu.VlanPcp(setPcp)))
+				}
 			} else {
 				// otherwise just set the egress port
 				actions = []*ofp.OfpAction{
@@ -200,11 +212,7 @@
 			// Augment the matchfields with the ofpfields from the flow.
 			// If the parent has a match vid and the child is setting that match vid exclude the the match vlan
 			// for the child given it will be setting that vlan and the parent will be matching on it
-			if setvid != nil {
-				faChild.MatchFields = append(faChild.MatchFields, fu.GetOfbFields(flow, fu.IN_PORT, fu.VLAN_VID)...)
-			} else {
-				faChild.MatchFields = append(faChild.MatchFields, fu.GetOfbFields(flow, fu.IN_PORT)...)
-			}
+			faChild.MatchFields = append(faChild.MatchFields, fu.GetOfbFields(flow, fu.IN_PORT)...)
 			fgChild := fu.NewFlowsAndGroups()
 			fs, err = fu.MkFlowStat(faChild)
 			if err != nil {
diff --git a/rw_core/flowdecomposition/flow_decomposer_test.go b/rw_core/flowdecomposition/flow_decomposer_test.go
index 6f8c80c..8f0149e 100644
--- a/rw_core/flowdecomposition/flow_decomposer_test.go
+++ b/rw_core/flowdecomposition/flow_decomposer_test.go
@@ -468,7 +468,7 @@
 		KV: fu.OfpFlowModArgs{"priority": 1000},
 		MatchFields: []*ofp.OfpOxmOfbField{
 			fu.InPort(1),
-			fu.VlanVid(50),
+			fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 50),
 			fu.EthType(0x888e),
 		},
 		Actions: []*ofp.OfpAction{
@@ -495,7 +495,7 @@
 		MatchFields: []*ofp.OfpOxmOfbField{
 			fu.InPort(1),
 			fu.TunnelId(uint64(1)),
-			fu.VlanVid(50),
+			fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
 			fu.EthType(0x888e),
 		},
 		Actions: []*ofp.OfpAction{
@@ -513,10 +513,11 @@
 			fu.InPort(2),
 			fu.TunnelId(uint64(1)),
 			fu.EthType(0x888e),
+			fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 50),
 		},
 		Actions: []*ofp.OfpAction{
 			fu.PushVlan(0x8100),
-			fu.SetField(fu.VlanVid(50)),
+			fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
 			fu.Output(1),
 		},
 	}
@@ -532,7 +533,7 @@
 		KV: fu.OfpFlowModArgs{"priority": 1000},
 		MatchFields: []*ofp.OfpOxmOfbField{
 			fu.InPort(1),
-			fu.VlanVid(0),
+			fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
 			fu.EthType(0x888e),
 		},
 		Actions: []*ofp.OfpAction{
@@ -559,7 +560,7 @@
 		MatchFields: []*ofp.OfpOxmOfbField{
 			fu.InPort(1),
 			fu.TunnelId(uint64(1)),
-			fu.VlanVid(0),
+			fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
 			fu.EthType(0x888e),
 		},
 		Actions: []*ofp.OfpAction{
@@ -577,10 +578,11 @@
 			fu.InPort(2),
 			fu.TunnelId(uint64(1)),
 			fu.EthType(0x888e),
+			fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
 		},
 		Actions: []*ofp.OfpAction{
 			fu.PushVlan(0x8100),
-			fu.SetField(fu.VlanVid(0)),
+			fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
 			fu.Output(1),
 		},
 	}
@@ -623,6 +625,7 @@
 			fu.InPort(1),
 			fu.TunnelId(uint64(1)),
 			fu.EthType(0x888e),
+			fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
 		},
 		Actions: []*ofp.OfpAction{
 			fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
@@ -641,6 +644,8 @@
 			fu.EthType(0x888e),
 		},
 		Actions: []*ofp.OfpAction{
+			fu.PushVlan(0x8100),
+			fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
 			fu.Output(1),
 		},
 	}