Integration with Nathan for Tibit packet in (raw)
Change-Id: I0fb9a2b020eae9b45da7db4bc68a6ed98835e5db
diff --git a/cli/main.py b/cli/main.py
index d684f85..3f2dd7a 100755
--- a/cli/main.py
+++ b/cli/main.py
@@ -50,10 +50,10 @@
)
banner = """\
- _ _ _ _ _
-__ _____| | |_| |_ __ _ __| (_)
-\ V / _ \ | _| ' \/ _` | / _| | |
- \_/\___/_|\__|_||_\__,_| \__|_|_|
+ _ _ _ ___ _ ___
+__ _____| | |_| |_ __ _ / __| | |_ _|
+\ V / _ \ | _| ' \/ _` | | (__| |__ | |
+ \_/\___/_|\__|_||_\__,_| \___|____|___|
(to exit type quit or hit Ctrl-D)
"""
diff --git a/tests/utests/common/utils/test_bpf.py b/tests/utests/common/utils/test_bpf.py
new file mode 100644
index 0000000..9bbcb76
--- /dev/null
+++ b/tests/utests/common/utils/test_bpf.py
@@ -0,0 +1,35 @@
+from unittest import TestCase, main
+
+from scapy.layers.l2 import Ether, Dot1Q
+
+from common.frameio.frameio import BpfProgramFilter
+
+
+class TestBpf(TestCase):
+
+ def test_bpf1(self):
+ vid = 4090
+ pcp = 7
+ frame_match = 'ether[14:2] = 0x{:01x}{:03x}'.format(pcp << 1, vid)
+ filter = BpfProgramFilter(frame_match)
+ self.assertTrue(filter(str(Ether()/Dot1Q(prio=pcp, vlan=vid))))
+ self.assertFalse(filter(str(Ether()/Dot1Q(prio=pcp, vlan=4000))))
+
+ def test_bpf2(self):
+ vid1 = 4090
+ pcp1 = 7
+ frame_match_case1 = 'ether[14:2] = 0x{:01x}{:03x}'.format(
+ pcp1 << 1, vid1)
+
+ vid2 = 4000
+ frame_match_case2 = '(ether[14:2] & 0xfff) = 0x{:03x}'.format(vid2)
+
+ filter = BpfProgramFilter('{} or {}'.format(
+ frame_match_case1, frame_match_case2))
+ self.assertTrue(filter(str(Ether()/Dot1Q(prio=pcp1, vlan=vid1))))
+ self.assertTrue(filter(str(Ether()/Dot1Q(vlan=vid2))))
+ self.assertFalse(filter(str(Ether()/Dot1Q(vlan=4001))))
+
+
+if __name__ == '__main__':
+ main()
diff --git a/voltha/adapters/tibit_olt/tibit_olt.py b/voltha/adapters/tibit_olt/tibit_olt.py
index b2b3f5b..0d260c3 100644
--- a/voltha/adapters/tibit_olt/tibit_olt.py
+++ b/voltha/adapters/tibit_olt/tibit_olt.py
@@ -28,13 +28,13 @@
from twisted.internet.defer import DeferredQueue, inlineCallbacks
from zope.interface import implementer
-from common.frameio.frameio import BpfProgramFilter
+from common.frameio.frameio import BpfProgramFilter, hexify
from voltha.adapters.interface import IAdapterInterface
from voltha.extensions.eoam.EOAM import EOAMPayload, DPoEOpcode_SetRequest
from voltha.extensions.eoam.EOAM_TLV import DOLTObject, \
PortIngressRuleClauseMatchLength02, PortIngressRuleResultForward, \
PortIngressRuleResultSet, PortIngressRuleResultInsert, \
- PortIngressRuleTerminator, AddPortIngressRule, CablelabsOUI
+ PortIngressRuleTerminator, AddPortIngressRule, CablelabsOUI, PonPortObject
from voltha.extensions.eoam.EOAM_TLV import PortIngressRuleHeader
from voltha.extensions.eoam.EOAM_TLV import ClauseSubtypeEnum as Clause
from voltha.core.flow_decomposer import *
@@ -53,10 +53,18 @@
log = structlog.get_logger()
# Match on the MGMT VLAN, Priority 7
-TIBIT_MGMT_VLAN=4090
-TIBIT_MGMT_PRIORITY=7
-frame_match = 'ether[14:2] = 0x{:01x}{:03x}'.format(TIBIT_MGMT_PRIORITY << 1, TIBIT_MGMT_VLAN)
-is_tibit_frame = BpfProgramFilter(frame_match)
+TIBIT_MGMT_VLAN = 4090
+TIBIT_MGMT_PRIORITY = 7
+frame_match_case1 = 'ether[14:2] = 0x{:01x}{:03x}'.format(
+ TIBIT_MGMT_PRIORITY << 1, TIBIT_MGMT_VLAN)
+
+TIBIT_PACKET_IN_VLAN = 4000
+frame_match_case2 = '(ether[14:2] & 0xfff) = 0x{:03x}'.format(
+ TIBIT_PACKET_IN_VLAN)
+
+is_tibit_frame = BpfProgramFilter('{} or {}'.format(
+ frame_match_case1, frame_match_case2))
+
#is_tibit_frame = lambda x: True
@@ -95,6 +103,7 @@
self.io_port = None
self.incoming_queues = {} # OLT mac_address -> DeferredQueue()
self.device_ids = {} # OLT mac_address -> device_id
+ self.vlan_to_device_ids = {} # c-vid -> (device_id, logical_device_id)
def start(self):
log.debug('starting', interface=self.interface)
@@ -269,7 +278,7 @@
# Convert from string to colon separated form
tibit_mac = ':'.join(s.encode('hex') for s in tibit_mac.decode('hex'))
- gemport, vlan_id = self._olt_side_onu_activation(int(macid['macid'][-4:-2], 16))
+ vlan_id = self._olt_side_onu_activation(int(macid['macid'][-4:-2], 16))
self.adapter_agent.child_device_detected(
parent_device_id=device.id,
parent_port_no=1,
@@ -282,6 +291,10 @@
vlan=vlan_id
)
+ # also record the vlan_id -> (device_id, logical_device_id) for
+ # later use
+ self.vlan_to_device_ids[vlan_id] = (device.id, device.parent_id)
+
def _olt_side_onu_activation(self, serial):
"""
This is where if this was a real OLT, the OLT-side activation for
@@ -289,40 +302,73 @@
be able to provide tunneled (proxy) communication to the given ONU,
using the returned information.
"""
- gemport = serial
vlan_id = serial + 200
- return gemport, vlan_id
+ return vlan_id
def _rcv_io(self, port, frame):
- log.info('frame-received')
+ log.info('frame-received', frame=hexify(frame))
# make into frame to extract source mac
response = Ether(frame)
if response.haslayer(Dot1Q):
- # All responses from the OLT should have a TIBIT_MGMT_VLAN.
- # Responses from the ONUs should have a TIBIT_MGMT_VLAN followed by a ONU CTAG
- if response.getlayer(Dot1Q).type == 0x8100:
- ## Responses from the ONU
- ## Since the type of the first layer is 0x8100,
- ## then the frame must have an inner tag layer
- olt_mac = response.src
- device_id = self.device_ids[olt_mac]
- channel_id = response[Dot1Q:2].vlan
- log.info('received_channel_id', channel_id=channel_id,
- device_id=device_id)
- proxy_address=Device.ProxyAddress(
- device_id=device_id,
- channel_id=channel_id
- )
- # pop dot1q header(s)
- msg = response.payload.payload
- self.adapter_agent.receive_proxied_message(proxy_address, msg)
+ # All OAM responses from the OLT should have a TIBIT_MGMT_VLAN.
+ # Responses from the ONUs should have a TIBIT_MGMT_VLAN followed by a ONU CTAG
+ # All packet-in frames will have the TIBIT_PACKET_IN_VLAN.
+ if response.getlayer(Dot1Q).type == 0x8100:
+
+ if response.getlayer(Dot1Q).vlan == TIBIT_PACKET_IN_VLAN:
+
+ inner_tag_and_rest = response.payload.payload
+
+ inner_tag_and_rest.show() # TODO remove this soon
+
+ if isinstance(inner_tag_and_rest, Dot1Q):
+
+ cvid = inner_tag_and_rest.vlan
+
+ frame = Ether(src=response.src,
+ dst=response.dst,
+ type=inner_tag_and_rest.type) /\
+ inner_tag_and_rest.payload
+
+ _, logical_device_id = self.vlan_to_device_ids.get(cvid)
+ if logical_device_id is None:
+ log.error('invalid-cvid', cvid=cvid)
+ else:
+ self.adapter_agent.send_packet_in(
+ logical_device_id=logical_device_id,
+ logical_port_no=cvid, # C-VID encodes port no
+ packet=str(frame))
+
+ else:
+ log.error('packet-in-single-tagged',
+ frame=hexify(response))
+
+ else:
+ ## Responses from the ONU
+ ## Since the type of the first layer is 0x8100,
+ ## then the frame must have an inner tag layer
+ olt_mac = response.src
+ device_id = self.device_ids[olt_mac]
+ channel_id = response[Dot1Q:2].vlan
+ log.info('received_channel_id', channel_id=channel_id,
+ device_id=device_id)
+
+ proxy_address=Device.ProxyAddress(
+ device_id=device_id,
+ channel_id=channel_id
+ )
+ # pop dot1q header(s)
+ msg = response.payload.payload
+ self.adapter_agent.receive_proxied_message(proxy_address, msg)
+
else:
## Respones from the OLT
## enqueue incoming parsed frame to right device
+ log.info('received-dot1q-not-8100')
self.incoming_queues[response.src].put(response)
def _make_ping_frame(self, mac_address):
@@ -361,7 +407,7 @@
elif in_port == 1:
# Upstream rule
- req = DOLTObject()
+ req = PonPortObject()
req /= PortIngressRuleHeader(precedence=precedence)
for field in get_ofb_fields(flow):
diff --git a/voltha/extensions/eoam/EOAM_TLV.py b/voltha/extensions/eoam/EOAM_TLV.py
index c0f431c..9598967 100644
--- a/voltha/extensions/eoam/EOAM_TLV.py
+++ b/voltha/extensions/eoam/EOAM_TLV.py
@@ -162,6 +162,15 @@
XByteField("num", 0)
]
+class PonPortObject(Packet):
+ """ Object Context: PON Port Object """
+ name = "Object Context: PON Port Object"
+ fields_desc = [XByteField("branch", 0xD6),
+ XShortField("leaf", 0x0001),
+ XByteField("length", 1),
+ XByteField("num", 1)
+ ]
+
class UnicastLogicalLink(Packet):
""" Object Context: Unicast Logical Link """
name = "Object Context: Unicast Logical Link"
diff --git a/voltha/protos/events.proto b/voltha/protos/events.proto
new file mode 100644
index 0000000..628a3f5
--- /dev/null
+++ b/voltha/protos/events.proto
@@ -0,0 +1,32 @@
+syntax = "proto3";
+
+package voltha;
+
+import "meta.proto";
+import "google/api/annotations.proto";
+
+
+message KpiEventType {
+ enum KpiEventType {
+ slice = 0; // slice: a set of path/metric data for same time-stamp
+ ts = 1; // time-series: array of data for same metric
+ }
+}
+
+/*
+message KpiEvent {
+
+ KpiEventType type = 1;
+
+ // Fields used when for slice:
+
+ float ts = 2; // UTC time-stamp of data in slice mode (seconds since epoc)
+
+ message MetricSamples {
+ map<string, float> metric_samples = 1;
+ }
+
+ map<string, MetricSamples> data = 3;
+
+}
+*/