VOL-1489: Add uni port id as tunnel id needed for olt flows

When the olt is asked to setup pon resources on the
onu/uni's behalf it needs to know what onu and uni port it
is dealing with for a particular flow.
Typically with flow decomposer the ports on the child
device (uni) are not visible on the parent. But in the case
of olt based flows (at least with BAL?) the parent device
needs to know the uni ports so it can create
gems, alloc id, and queues needed.

This patch adds new openflow tunnel id containing the uni port
to the decomposed flows for use by the adapter.

Change-Id: I0ea701b457ab5cb5877b953f58364d6a7806a58f
diff --git a/python/cli/utils.py b/python/cli/utils.py
index 38e5ee2..1f72be3 100644
--- a/python/cli/utils.py
+++ b/python/cli/utils.py
@@ -90,6 +90,7 @@
     'TCP_SRC': lambda f: (108, 'tcp_src', str(f['tcp_src'])),
     'TCP_DST': lambda f: (109, 'tcp_dst', str(f['tcp_dst'])),
     'METADATA': lambda f: (110, 'metadata', str(f['table_metadata'])),
+    'TUNNEL_ID': lambda f: (111, 'tunnel_id', str(f['tunnel_id'])),
 }
 
 
diff --git a/rw_core/flow_decomposition/flow_decomposer.go b/rw_core/flow_decomposition/flow_decomposer.go
index 980420a..41fdc4a 100644
--- a/rw_core/flow_decomposition/flow_decomposer.go
+++ b/rw_core/flow_decomposition/flow_decomposer.go
@@ -463,6 +463,18 @@
 	return 0
 }
 
+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 {
@@ -518,6 +530,18 @@
 	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
@@ -848,6 +872,7 @@
 				MatchFields: []*ofp.OfpOxmOfbField{
 					InPort(egressHop.Ingress),
 					VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | inputPort),
+					TunnelId(uint64(inputPort)),
 				},
 				Actions: []*ofp.OfpAction{
 					PushVlan(0x8100),
@@ -867,6 +892,7 @@
 					VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000),
 					VlanPcp(0),
 					Metadata_ofp(uint64(inputPort)),
+					TunnelId(uint64(inputPort)),
 				},
 				Actions: []*ofp.OfpAction{
 					PopVlan(),
@@ -904,6 +930,7 @@
 			KV: fu.OfpFlowModArgs{"priority": uint64(flow.Priority), "cookie": flow.Cookie},
 			MatchFields: []*ofp.OfpOxmOfbField{
 				InPort(ingressHop.Ingress),
+				TunnelId(uint64(inPortNo)),
 			},
 			Actions: GetActions(flow),
 		}
@@ -948,6 +975,7 @@
 				KV: fu.OfpFlowModArgs{"priority": uint64(flow.Priority), "cookie": flow.Cookie},
 				MatchFields: []*ofp.OfpOxmOfbField{
 					InPort(egressHop.Ingress), //egress_hop.ingress_port.port_no
+					TunnelId(uint64(inPortNo)),
 				},
 				Actions: []*ofp.OfpAction{
 					Output(egressHop.Egress),
@@ -967,6 +995,7 @@
 				KV: fu.OfpFlowModArgs{"priority": uint64(flow.Priority), "cookie": flow.Cookie},
 				MatchFields: []*ofp.OfpOxmOfbField{
 					InPort(egressHop.Ingress),
+					TunnelId(uint64(inPortNo)),
 				},
 			}
 			// Augment the matchfields with the ofpfields from the flow
@@ -1029,6 +1058,7 @@
 			MatchFields: []*ofp.OfpOxmOfbField{
 				InPort(ingressHop.Ingress),
 				Metadata_ofp(innerTag),
+				TunnelId(uint64(portNumber)),
 			},
 			Actions: GetActions(flow),
 		}
@@ -1048,6 +1078,7 @@
 			KV: fu.OfpFlowModArgs{"priority": uint64(flow.Priority), "cookie": flow.Cookie},
 			MatchFields: []*ofp.OfpOxmOfbField{
 				InPort(ingressHop.Ingress),
+				TunnelId(uint64(inPortNo)),
 			},
 			Actions: GetActions(flow),
 		}
@@ -1090,6 +1121,7 @@
 			KV: fu.OfpFlowModArgs{"priority": uint64(flow.Priority), "cookie": flow.Cookie},
 			MatchFields: []*ofp.OfpOxmOfbField{
 				InPort(ingressHop.Ingress),
+				TunnelId(uint64(inPortNo)),
 			},
 			Actions: []*ofp.OfpAction{
 				Output(ingressHop.Egress),
diff --git a/rw_core/flow_decomposition/flow_decomposer_test.go b/rw_core/flow_decomposition/flow_decomposer_test.go
index e5c4bbd..fdc2b86 100644
--- a/rw_core/flow_decomposition/flow_decomposer_test.go
+++ b/rw_core/flow_decomposition/flow_decomposer_test.go
@@ -473,6 +473,7 @@
 		MatchFields: []*ofp.OfpOxmOfbField{
 			InPort(1),
 			VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 1),
+			TunnelId(uint64(1)),
 			EthType(0x888e),
 		},
 		Actions: []*ofp.OfpAction{
@@ -492,6 +493,7 @@
 			VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000),
 			VlanPcp(0),
 			Metadata_ofp(1),
+			TunnelId(uint64(1)),
 		},
 		Actions: []*ofp.OfpAction{
 			PopVlan(),
@@ -553,6 +555,7 @@
 		MatchFields: []*ofp.OfpOxmOfbField{
 			InPort(1),
 			VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 1),
+			TunnelId(uint64(1)),
 			EthType(0x0800),
 			Ipv4Dst(0xffffffff),
 			IpProto(17),
@@ -576,6 +579,7 @@
 			VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000),
 			VlanPcp(0),
 			Metadata_ofp(1),
+			TunnelId(uint64(1)),
 		},
 		Actions: []*ofp.OfpAction{
 			PopVlan(),
@@ -634,6 +638,7 @@
 		KV: fu.OfpFlowModArgs{"priority": 500},
 		MatchFields: []*ofp.OfpOxmOfbField{
 			InPort(2),
+			TunnelId(uint64(1)),
 			VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
 			VlanPcp(0),
 		},
@@ -650,6 +655,7 @@
 		KV: fu.OfpFlowModArgs{"priority": 500},
 		MatchFields: []*ofp.OfpOxmOfbField{
 			InPort(1),
+			TunnelId(uint64(1)),
 			VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
 			VlanPcp(0),
 		},
@@ -710,6 +716,7 @@
 		MatchFields: []*ofp.OfpOxmOfbField{
 			InPort(2),
 			Metadata_ofp(1000),
+			TunnelId(uint64(1)),
 			VlanPcp(0),
 		},
 		Actions: []*ofp.OfpAction{