Adding ability to send OMCI messages from PMCS adapter
Change-Id: Ic6eacc4e74cc2796f93c5787fa57dc230dd11036
diff --git a/voltha/adapters/microsemi_olt/ActivationWatcher.py b/voltha/adapters/microsemi_olt/ActivationWatcher.py
index ee0e309..c59c19c 100644
--- a/voltha/adapters/microsemi_olt/ActivationWatcher.py
+++ b/voltha/adapters/microsemi_olt/ActivationWatcher.py
@@ -153,34 +153,19 @@
Utility Methods
"""
- def create_port(self, vendor):
- port = Port(port_no=self.port_id,
- label="{} ONU".format(vendor),
- type=Port.ETHERNET_UNI,
- admin_state=AdminState.ENABLED,
- oper_status=OperStatus.ACTIVE
- )
- self.device.add_port(port)
-
def px(self, pkt):
return self.p(pkt, channel_id=self.channel_id,
onu_id=self.onu_id, onu_session_id=self.onu_session_id)
- def error(self, msg):
- log.error(msg)
- raise self.error()
-
def detect_onu(self):
log.info("Activated {} ONT".format(self.vendor))
- self.create_port(self.vendor)
- print self.channel_id
- print self.onu_id
try:
self.device.onu_detected(
parent_port_no=self.channel_id,
child_device_type='%s_onu' % self.vendor.lower(),
onu_id=self.onu_id,
- serial_number=hexstring(self.serial_number)
+ serial_number=hexstring(self.serial_number),
+ onu_session_id=self.onu_session_id
)
except Exception as e:
print e
@@ -443,6 +428,7 @@
def wait_for_set_vlan_uplink_config(self, pkt):
if PAS5211SetVlanUplinkConfigurationResponse in pkt:
# YAY we made it.
+ # TODO update OLT with CNI port
self.detect_onu()
raise self.end()
diff --git a/voltha/adapters/microsemi_olt/DeviceManager.py b/voltha/adapters/microsemi_olt/DeviceManager.py
index e468a0d..a9795d4 100644
--- a/voltha/adapters/microsemi_olt/DeviceManager.py
+++ b/voltha/adapters/microsemi_olt/DeviceManager.py
@@ -105,7 +105,8 @@
def onu_detected(self, parent_port_no=None,
child_device_type=None,
onu_id=None,
- serial_number=None):
+ serial_number=None,
+ onu_session_id=None):
self.adapter_agent.child_device_detected(
parent_device_id=self.device.id,
parent_port_no=parent_port_no,
@@ -113,7 +114,9 @@
serial_number=serial_number,
proxy_address=Device.ProxyAddress(
device_id=self.device.id,
- channel_id=onu_id
+ channel_id=parent_port_no, # happens to be the channel id as well
+ onu_id=onu_id,
+ onu_session_id=onu_session_id
),
vlan=0
)
diff --git a/voltha/adapters/microsemi_olt/OMCIProxy.py b/voltha/adapters/microsemi_olt/OMCIProxy.py
new file mode 100644
index 0000000..be81fd4
--- /dev/null
+++ b/voltha/adapters/microsemi_olt/OMCIProxy.py
@@ -0,0 +1,107 @@
+#
+# Copyright 2017 the original author or authors.
+#
+# 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.
+#
+
+"""
+Handles sequence of messages that are used to send OMCI to the ONU
+"""
+import structlog
+from scapy.automaton import ATMT
+
+from voltha.adapters.microsemi_olt.BaseOltAutomaton import BaseOltAutomaton
+from voltha.adapters.microsemi_olt.PAS5211 import PAS5211MsgSendFrame, PAS5211MsgSendFrameResponse, \
+ PAS5211EventFrameReceived
+
+log = structlog.get_logger()
+
+class OMCIProxy(BaseOltAutomaton):
+
+
+ proxy_address = None
+ msg = None
+
+ def parse_args(self, debug=0, store=0, **kwargs):
+ self.adaptor_agent = kwargs.pop('adapter_agent')
+ self.proxy_address = kwargs.pop('proxy_address')
+ self.msg = kwargs.pop('msg')
+
+ BaseOltAutomaton.parse_args(self, debug=debug, store=store, **kwargs)
+
+ """
+ States
+ """
+
+ @ATMT.state(initial=1)
+ def got_omci_msg(self):
+ pass
+
+ @ATMT.state()
+ def wait_send_response(self):
+ pass
+
+ @ATMT.state()
+ def wait_event(self):
+ pass
+
+ @ATMT.state(error=1)
+ def error(self, msg):
+ log.error(msg)
+
+ @ATMT.state(final=1)
+ def end(self):
+ pass
+
+ """
+ Utils
+ """
+
+ def px(self, pkt):
+ return self.p(pkt, channel_id=self.proxy_address.channel_id,
+ onu_id=self.proxy_address.onu_id,
+ onu_session_id=self.proxy_address.onu_session_id)
+
+ """
+ Transitions
+ """
+
+ @ATMT.condition(got_omci_msg)
+ def send_omci_msg(self):
+ pkt = PAS5211MsgSendFrame(frame=self.msg, port_id=self.proxy_address.onu_id)
+ self.send(self.px(pkt))
+ raise self.wait_send_response()
+
+ # Transitions from wait_send_response
+ @ATMT.timeout(wait_send_response, 3)
+ def timeout_wait_send_response(self):
+ raise self.error("No ack for OMCI for {}".format(self.proxy_address))
+
+ @ATMT.receive_condition(wait_send_response)
+ def wait_for_send_response(self, pkt):
+ if PAS5211MsgSendFrameResponse in pkt:
+ raise self.wait_event()
+
+ # Transitions from wait_event
+ @ATMT.timeout(wait_event, 3)
+ def timeout_wait_event(self):
+ raise self.error("No OMCI event for {}".format(self.proxy_address))
+
+ @ATMT.receive_condition(wait_event)
+ def wait_for_event(self, pkt):
+ if PAS5211EventFrameReceived in pkt:
+ # FIXME we may need to verify the transaction id
+ # to make sure we have the right packet
+ self.adaptor_agent.recieve_proxied_message(self.proxy_address,
+ pkt['PAS5211EventFrameReceived'])
+ raise self.end()
\ No newline at end of file
diff --git a/voltha/adapters/microsemi_olt/microsemi_olt.py b/voltha/adapters/microsemi_olt/microsemi_olt.py
index addfd34..532915d 100644
--- a/voltha/adapters/microsemi_olt/microsemi_olt.py
+++ b/voltha/adapters/microsemi_olt/microsemi_olt.py
@@ -27,6 +27,7 @@
from voltha.adapters.interface import IAdapterInterface
from voltha.adapters.microsemi_olt.ActivationWatcher import ActivationWatcher
from voltha.adapters.microsemi_olt.DeviceManager import DeviceManager
+from voltha.adapters.microsemi_olt.OMCIProxy import OMCIProxy
from voltha.adapters.microsemi_olt.OltStateMachine import OltStateMachine
from voltha.adapters.microsemi_olt.PAS5211_comm import PAS5211Communication
from voltha.protos import third_party
@@ -132,6 +133,11 @@
def send_proxied_message(self, proxy_address, msg):
log.info('send-proxied-message', proxy_address=proxy_address, msg=msg)
+ # TODO make this more efficient
+ omci_proxy = OMCIProxy(proxy_address=proxy_address,
+ msg=msg)
+ omci_proxy.run()
+ del omci_proxy
def receive_proxied_message(self, proxy_address, msg):
raise NotImplementedError()
diff --git a/voltha/adapters/pmcs_onu/pmcs_onu.py b/voltha/adapters/pmcs_onu/pmcs_onu.py
index 8b244b6..26b112c 100644
--- a/voltha/adapters/pmcs_onu/pmcs_onu.py
+++ b/voltha/adapters/pmcs_onu/pmcs_onu.py
@@ -20,15 +20,19 @@
import structlog
from twisted.internet import reactor
+from twisted.internet.defer import DeferredQueue, inlineCallbacks
from zope.interface import implementer
from voltha.adapters.interface import IAdapterInterface
+from voltha.adapters.microsemi_olt.DeviceManager import mac_str_to_tuple
from voltha.protos import third_party
from voltha.protos.adapter_pb2 import Adapter
from voltha.protos.adapter_pb2 import AdapterConfig
-from voltha.protos.common_pb2 import LogLevel
-from voltha.protos.device_pb2 import DeviceType, DeviceTypes
+from voltha.protos.common_pb2 import LogLevel, ConnectStatus, AdminState, OperStatus
+from voltha.protos.device_pb2 import DeviceType, DeviceTypes, Port
from voltha.protos.health_pb2 import HealthStatus
+from voltha.protos.logical_device_pb2 import LogicalPort
+from voltha.protos.openflow_13_pb2 import OFPPF_1GB_FD, OFPPF_FIBER, ofp_port, OFPPS_LIVE
_ = third_party
log = structlog.get_logger()
@@ -55,6 +59,7 @@
version='0.1',
config=AdapterConfig(log_level=LogLevel.INFO)
)
+ self.incoming_messages = DeferredQueue()
def start(self):
log.debug('starting')
@@ -77,6 +82,8 @@
raise NotImplementedError()
def adopt_device(self, device):
+ log.info('adopt-device', device=device)
+ reactor.callLater(0.1, self._onu_device_activation, device)
return device
def abandon_device(self, device):
@@ -116,7 +123,89 @@
def receive_proxied_message(self, proxy_address, msg):
log.info('receive-proxied-message', proxy_address=proxy_address,
device_id=proxy_address.device_id, msg=msg)
+ self.incoming_messages.put(msg)
def receive_packet_out(self, logical_device_id, egress_port_no, msg):
log.info('packet-out', logical_device_id=logical_device_id,
egress_port_no=egress_port_no, msg_len=len(msg))
+
+ @inlineCallbacks
+ def _onu_device_activation(self, device):
+ # first we verify that we got parent reference and proxy info
+ assert device.parent_id
+ assert device.proxy_address.device_id
+ assert device.proxy_address.channel_id
+
+ device.model = 'GPON ONU'
+ device.hardware_version = 'tbd'
+ device.firware_version = 'tbd'
+ device.software_version = 'tbd'
+
+ device.connect_status = ConnectStatus.REACHABLE
+
+ self.adapter_agent.update_device(device)
+
+ uni_port = Port(port_no=self.port_id,
+ label="{} ONU".format('PMCS'),
+ type=Port.ETHERNET_UNI,
+ admin_state=AdminState.ENABLED,
+ oper_status=OperStatus.ACTIVE
+ )
+ self.device.add_port(uni_port)
+
+ pon_port = Port(
+ port_no=1,
+ label='PON port',
+ type=Port.PON_ONU,
+ admin_state=AdminState.ENABLED,
+ oper_status=OperStatus.ACTIVE,
+ peers=[
+ Port.PeerPort(
+ device_id=device.parent_id,
+ port_no=device.parent_port_no
+ )
+ ]
+ )
+
+ self.adapter_agent.add_port(device.id, pon_port)
+
+ # obtain logical device id
+ parent_device = self.adapter_agent.get_device(device.parent_id)
+ logical_device_id = parent_device.parent_id
+ assert logical_device_id
+
+ # we are going to use the proxy_address.channel_id as unique number
+ # and name for the virtual ports, as this is guaranteed to be unique
+ # in the context of the OLT port, so it is also unique in the context
+ # of the logical device
+ port_no = device.proxy_address.channel_id
+ cap = OFPPF_1GB_FD | OFPPF_FIBER
+ self.adapter_agent.add_logical_port(logical_device_id, LogicalPort(
+ id=str(port_no),
+ ofp_port=ofp_port(
+ port_no=port_no,
+ hw_addr=mac_str_to_tuple(device.mac_address),
+ name='uni-{}'.format(port_no),
+ config=0,
+ state=OFPPS_LIVE,
+ curr=cap,
+ advertised=cap,
+ peer=cap,
+ curr_speed=OFPPF_1GB_FD,
+ max_speed=OFPPF_1GB_FD
+ ),
+ device_id=device.id,
+ device_port_no=uni_port.port_no
+ ))
+
+ self._initialize_onu(device)
+
+ # and finally update to "ACTIVE"
+ device = self.adapter_agent.get_device(device.id)
+ device.oper_status = OperStatus.ACTIVE
+ self.adapter_agent.update_device(device)
+
+
+ def _initialize_onu(self, device):
+ # DO things to the ONU
+ pass
\ No newline at end of file
diff --git a/voltha/protos/device.proto b/voltha/protos/device.proto
index 47deacd..5a32f28 100644
--- a/voltha/protos/device.proto
+++ b/voltha/protos/device.proto
@@ -129,7 +129,9 @@
message ProxyAddress {
string device_id = 1; // Which device to use as proxy to this device
- uint32 channel_id = 2; // Sub-address within proxy device
+ uint32 channel_id = 2; // Sub-address within proxy
+ uint32 onu_id = 3; // onu identifier; optional
+ uint32 onu_sesssion_id = 4; // session identifier for the ONU; optional
};
oneof address {