VOL-1237: Fix for OLT Pipeline not providing inner Q-in-Q tag to OLT
Change-Id: Ib1f61f0388a4ae253c140fca3e3170f65b188778
diff --git a/tests/utests/voltha/core/test_flow_decomposer.py b/tests/utests/voltha/core/test_flow_decomposer.py
index 598f1f0..5e77621 100644
--- a/tests/utests/voltha/core/test_flow_decomposer.py
+++ b/tests/utests/voltha/core/test_flow_decomposer.py
@@ -650,7 +650,7 @@
flow1 = mk_flow_stat(
match_fields=[
in_port(0),
- vlan_vid(ofp.OFPVID_PRESENT | 1000),
+ metadata((1000 << 32) | 1),
vlan_pcp(0)
],
actions=[
@@ -682,7 +682,7 @@
priority=500,
match_fields=[
in_port(2),
- vlan_vid(ofp.OFPVID_PRESENT | 1000),
+ metadata(1000),
vlan_pcp(0)
],
actions=[
diff --git a/tests/utests/voltha/core/test_multipon_lda.py b/tests/utests/voltha/core/test_multipon_lda.py
index 74fd11f..cb99cf2 100644
--- a/tests/utests/voltha/core/test_multipon_lda.py
+++ b/tests/utests/voltha/core/test_multipon_lda.py
@@ -443,7 +443,7 @@
match_fields=[
in_port(0),
vlan_vid(4096 + 1000),
- metadata(c_vid)
+ metadata((c_vid << 32) | port)
],
actions=[pop_vlan()],
next_table_id=1
@@ -581,7 +581,7 @@
))
self.assertFlowsEqual(self.device_flows['olt'].items[14], mk_flow_stat(
priority=500,
- match_fields=[in_port(0), vlan_vid(4096 + 1000), metadata(101)],
+ match_fields=[in_port(0), metadata(101), vlan_vid(4096 + 1000)],
actions=[pop_vlan(), output(1)]
))
self.assertFlowsEqual(self.device_flows['olt'].items[15], mk_flow_stat(
@@ -592,7 +592,7 @@
))
self.assertFlowsEqual(self.device_flows['olt'].items[16], mk_flow_stat(
priority=500,
- match_fields=[in_port(0), vlan_vid(4096 + 1000), metadata(201)],
+ match_fields=[in_port(0), metadata(201), vlan_vid(4096 + 1000)],
actions=[pop_vlan(), output(2)]
))
self.assertFlowsEqual(self.device_flows['olt'].items[17], mk_flow_stat(
diff --git a/voltha/adapters/openolt/openolt_flow_mgr.py b/voltha/adapters/openolt/openolt_flow_mgr.py
index d098065..edda513 100644
--- a/voltha/adapters/openolt/openolt_flow_mgr.py
+++ b/voltha/adapters/openolt/openolt_flow_mgr.py
@@ -644,9 +644,14 @@
def find_next_flow(self, flow):
table_id = fd.get_goto_table_id(flow)
metadata = 0
+ # Prior to ONOS 1.13.5, Metadata contained the UNI output port number. In
+ # 1.13.5 and later, the lower 32-bits is the output port number and the
+ # upper 32-bits is the inner-vid we are looking for. Use just the lower 32
+ # bits. Allows this code to work with pre- and post-1.13.5 ONOS OltPipeline
+
for field in fd.get_ofb_fields(flow):
if field.type == fd.METADATA:
- metadata = field.table_metadata
+ metadata = field.table_metadata & 0xFFFFFFFF
if table_id is None:
return None
flows = self.logical_flows_proxy.get('/').items
diff --git a/voltha/core/flow_decomposer.py b/voltha/core/flow_decomposer.py
index 35f3f1d..fad56dc 100644
--- a/voltha/core/flow_decomposer.py
+++ b/voltha/core/flow_decomposer.py
@@ -316,13 +316,62 @@
return None
def get_metadata(flow):
+ ''' legacy get method (only want lower 32 bits '''
+ for field in get_ofb_fields(flow):
+ if field.type == METADATA:
+ return field.table_metadata & 0xffffffff
+ return None
+
+def get_metadata_64_bit(flow):
for field in get_ofb_fields(flow):
if field.type == METADATA:
return field.table_metadata
return None
-# test and extract next table and group information
+def get_port_number_from_metadata(flow):
+ """
+ The port number (UNI on ONU) is in the lower 32-bits of metadata and
+ the inner_tag is in the upper 32-bits
+
+ This is set in the ONOS OltPipeline as a metadata field
+ """
+ md = get_metadata_64_bit(flow)
+
+ if md is None:
+ return None
+
+ if md <= 0xffffffff:
+ log.warn('onos-upgrade-suggested',
+ netadata=md,
+ message='Legacy MetaData detected form OltPipeline')
+ return md
+
+ return md & 0xffffffff
+
+
+def get_inner_tag_from_metadata(flow):
+ """
+ The port number (UNI on ONU) is in the lower 32-bits of metadata and
+ the inner_tag is in the upper 32-bits
+
+ This is set in the ONOS OltPipeline as a metadata field
+ """
+ md = get_metadata_64_bit(flow)
+
+ if md is None:
+ return None
+
+ if md <= 0xffffffff:
+ log.warn('onos-upgrade-suggested',
+ netadata=md,
+ message='Legacy MetaData detected form OltPipeline')
+ return md
+
+ return (md >> 32) & 0xffffffff
+
+
+# test and extract next table and group information
def has_next_table(flow):
return get_goto_table_id(flow) is not None
@@ -670,30 +719,40 @@
if has_next_table(flow):
assert out_port_no is None
- # For downstream flows with dual-tags, recalculate route with
- # inner-tag as logical output port. Otherwise PON-0 is always
- # selected.
- inner_tag = get_metadata(flow)
- if inner_tag is not None:
- route = self.get_route(in_port_no, inner_tag)
+ # For downstream flows with dual-tags, recalculate route.
+ port_number = get_port_number_from_metadata(flow)
+
+ if port_number is not None:
+ route = self.get_route(in_port_no, port_number)
if route is None:
log.error('no-route-double-tag', in_port_no=in_port_no,
- out_port_no=inner_tag, comment='deleting flow')
+ out_port_no=port_number, comment='deleting flow',
+ metadata=get_metadata_64_bit(flow))
self.flow_delete(flow)
return device_rules
assert len(route) == 2
ingress_hop, egress_hop = route
+ inner_tag = get_inner_tag_from_metadata(flow)
+
+ if inner_tag is None:
+ log.error('no-inner-tag-double-tag', in_port_no=in_port_no,
+ out_port_no=port_number, comment='deleting flow',
+ metadata=get_metadata_64_bit(flow))
+ self.flow_delete(flow)
+ return device_rules
+
fl_lst, _ = device_rules.setdefault(
ingress_hop.device.id, ([], []))
fl_lst.append(mk_flow_stat(
priority=flow.priority,
cookie=flow.cookie,
match_fields=[
- in_port(ingress_hop.ingress_port.port_no)
+ in_port(ingress_hop.ingress_port.port_no),
+ metadata(inner_tag)
] + [
field for field in get_ofb_fields(flow)
- if field.type not in (IN_PORT,)
+ if field.type not in (IN_PORT, METADATA)
],
actions=[
action for action in get_actions(flow)