Adding an OLT state machine.
Initialized the OLT connection and maintaining a keepalive
Need to change implementation to use twisted
Change-Id: I670c2875b8c653a0849c85a2840089742dfa1188
diff --git a/voltha/adapters/microsemi/PAS5211.py b/voltha/adapters/microsemi/PAS5211.py
index 01a3b66..ec9e8b8 100644
--- a/voltha/adapters/microsemi/PAS5211.py
+++ b/voltha/adapters/microsemi/PAS5211.py
@@ -69,6 +69,7 @@
LESignedIntField("onu_session_id", -1)
]
+
class PAS5211MsgGetOltVersion(PAS5211Msg):
opcode = 3
name = "PAS5211MsgGetOltVersion"
@@ -77,6 +78,26 @@
def answers(self, other):
return other.name == "PAS5211MsgGetOltVersionResponse"
+
+class PAS5211MsgGetProtocolVersion(PAS5211Msg):
+ opcode = 2
+ name = "PAS5211MsgGetProtocolVersion"
+ fields_desc = [ ]
+
+
+class PAS5211MsgGetProtocolVersionResponse(PAS5211Msg):
+ name = "PAS5211MsgGetProtocolVersionResponse"
+ fields_desc = [
+ LEShortField("major_hardware_version", 0),
+ LEShortField("minor_hardware_version", 0),
+ LEShortField("major_pfi_version", 0),
+ LEShortField("minor_pfi_version", 0)
+ ]
+
+ def answers(self, other):
+ return other.name == 'PAS5211MsgGetProtocolVersion'
+
+
class PAS5211MsgGetOltVersionResponse(PAS5211Msg):
name = "PAS5211MsgGetOltVersionResponse"
fields_desc = [
@@ -110,4 +131,5 @@
split_layers(Dot3, LLC)
bind_layers(Dot3,PAS5211FrameHeader)
bind_layers(PAS5211FrameHeader, PAS5211MsgHeader)
-bind_layers(PAS5211MsgHeader, PAS5211MsgGetOltVersionResponse, opcode=0x3800 | 3)
\ No newline at end of file
+bind_layers(PAS5211MsgHeader, PAS5211MsgGetOltVersionResponse, opcode=0x3800 | 3)
+bind_layers(PAS5211MsgHeader, PAS5211MsgGetProtocolVersionResponse, opcode=0x2800 | 2)
\ No newline at end of file
diff --git a/voltha/adapters/microsemi/PAS5211_comm.py b/voltha/adapters/microsemi/PAS5211_comm.py
index a9fec63..2167a9d 100644
--- a/voltha/adapters/microsemi/PAS5211_comm.py
+++ b/voltha/adapters/microsemi/PAS5211_comm.py
@@ -63,10 +63,10 @@
self.seqgen = sequence_generator(init)
self.src_mac = determine_src_mac(self.iface)
- def communicate(self, msg, **kwargs):
+ def communicate(self, msg, timeout=1, **kwargs):
if self.src_mac is not None:
frame = constructPAS5211Frames(msg, self.seqgen.next(), self.src_mac,
self.dst_mac, **kwargs)
- return srp1(frame, timeout=2, iface=self.iface)
+ return srp1(frame, timeout=timeout, iface=self.iface)
else:
log.info('Unknown src mac for {}'.format(self.iface))
diff --git a/voltha/adapters/microsemi/RubyAdapter.py b/voltha/adapters/microsemi/RubyAdapter.py
index 93c5b07..cdfec1a 100644
--- a/voltha/adapters/microsemi/RubyAdapter.py
+++ b/voltha/adapters/microsemi/RubyAdapter.py
@@ -19,10 +19,13 @@
"""
import structlog
from voltha.adapters.interface import IAdapterInterface
-from voltha.adapters.microsemi.PAS5211 import PAS5211MsgGetOltVersion
from voltha.adapters.microsemi.PAS5211_comm import PAS5211Communication
-#from voltha.protos.adapter_pb2 import Adapter, AdapterConfig, DeviceTypes
-#from voltha.protos.health_pb2 import HealthStatus
+from voltha.adapters.microsemi.StateMachine import Disconnected
+import signal
+from voltha.protos.adapter_pb2 import Adapter, AdapterConfig, DeviceTypes
+from voltha.protos.health_pb2 import HealthStatus
+
+
from zope.interface import implementer
log = structlog.get_logger()
@@ -33,11 +36,15 @@
class RubyAdapter(object):
def __init__(self, config):
self.config = config
-# self.descriptor = Adapter(
-# id='ruby',
-# config=AdapterConfig()
-# # TODO
-# )
+ self.descriptor = Adapter(
+ id='ruby',
+ config=AdapterConfig()
+ # TODO
+ )
+ self.comm = comm = PAS5211Communication(dst_mac=olt_conf['olts']['mac'],
+ iface=olt_conf['iface'])
+ self.olt = Disconnected(comm)
+ signal.signal(signal.SIGINT, self.stop)
def start(self):
log.debug('starting')
@@ -46,6 +53,7 @@
def stop(self):
log.debug('stopping')
+ self.olt.disconnect()
log.info('stopped')
def adapter_descriptor(self):
@@ -53,13 +61,12 @@
def device_types(self):
pass
-# return DeviceTypes(
-# items=[] # TODO
-# )
+ return DeviceTypes(
+ items=[] # TODO
+ )
def health(self):
- pass
-# return HealthStatus(state=HealthStatus.HealthState.HEALTHY)
+ return HealthStatus(state=HealthStatus.HealthState.HEALTHY)
def change_master_state(self, master):
raise NotImplementedError()
@@ -74,10 +81,15 @@
raise NotImplementedError()
def init_olt(self):
- comm = PAS5211Communication(dst_mac=olt_conf['olts']['mac'], iface=olt_conf['iface'])
- packet = comm.communicate(PAS5211MsgGetOltVersion())
- log.info('{}'.format(packet.show()))
-
+ self.olt.run()
+ self.olt = self.olt.transition()
+ self.olt.run()
+ self.olt = self.olt.transition()
+ self.olt.run()
if __name__ == '__main__':
- RubyAdapter(None).start()
\ No newline at end of file
+ try:
+ ruby = RubyAdapter(None)
+ ruby.start()
+ except KeyboardInterrupt:
+ ruby.stop()
\ No newline at end of file
diff --git a/voltha/adapters/microsemi/StateMachine.py b/voltha/adapters/microsemi/StateMachine.py
new file mode 100644
index 0000000..5ad1622
--- /dev/null
+++ b/voltha/adapters/microsemi/StateMachine.py
@@ -0,0 +1,155 @@
+#
+# Copyright 2016 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.
+#
+
+"""
+Base OLT State machine class
+"""
+import threading
+import time
+from voltha.adapters.microsemi.PAS5211 import PAS5211MsgGetProtocolVersion, PAS5211MsgGetOltVersion
+
+class State(object):
+ def __init__(self):
+ pass
+
+ """
+ Attempt an operation towards the OLT
+ """
+ def run(self):
+ raise NotImplementedError()
+
+ """
+ Distates which state to transtion to.
+ Predicated on the run operation to be successful.
+ """
+ def transition(self):
+ raise NotImplementedError()
+
+ """
+ Returns any useful information for the given State
+ """
+ def value(self):
+ raise NotImplementedError()
+
+ """
+ Sends a message to this olt
+ """
+ def send_msg(self, msg):
+ raise NotImplementedError()
+
+ """
+ Disconnected an OLT.
+ """
+ def disconnect(self):
+ raise NotImplementedError()
+
+"""
+Represents an OLT in disconnected or pre init state.
+"""
+class Disconnected(State):
+
+ def __init__(self, pas_comm):
+ self.comm = pas_comm
+ self.completed = False
+ self.packet = None
+
+ def run(self):
+ self.packet = self.comm.communicate(PAS5211MsgGetProtocolVersion())
+ if self.packet is not None:
+ self.completed = True
+ return self.completed
+
+ def transition(self):
+ if self.completed:
+ return Fetch_Version(self.comm)
+
+ def value(self):
+ # TODO return a nicer value than the packet.
+ return self.packet
+
+ def send_msg(self, msg):
+ raise NotImplementedError()
+
+ def disconnect(self):
+ raise NotImplementedError()
+
+"""
+Fetches the OLT version
+"""
+class Fetch_Version(State):
+ def __init__(self, pas_comm):
+ self.comm = pas_comm
+ self.completed = False
+ self.packet = None
+
+ def run(self):
+ self.packet = self.comm.communicate(PAS5211MsgGetOltVersion())
+ if self.packet is not None:
+ self.completed = True
+ return self.completed
+
+ def transition(self):
+ if self.completed:
+ return Connected(self.comm)
+
+ def value(self):
+ # TODO return a nicer value than the packet.
+ return self.packet
+
+ def send_msg(self, msg):
+ raise NotImplementedError()
+
+ def disconnect(self):
+ raise NotImplementedError()
+
+
+"""
+OLT is in connected State
+"""
+class Connected(State):
+ def __init__(self, pas_comm):
+ self.comm = pas_comm
+ self.completed = False
+ self.packet = None
+ self.t = threading.Thread(target = self.keepalive)
+
+ def run(self):
+ self.t.start()
+
+ def transition(self):
+ if self.completed:
+ return Disconnected(self.comm)
+
+ def value(self):
+ # TODO return a nicer value than the packet.
+ return self.packet
+
+ def send_msg(self, msg):
+ return self.comm.communicate(msg)
+
+ # FIXME replace with twisted
+ def keepalive(self):
+ while not self.completed:
+ self.packet = self.comm.communicate(PAS5211MsgGetOltVersion())
+ if self.packet is not None:
+ time.sleep(1)
+ else:
+ break
+ self.completed = True
+
+ def disconnect(self):
+ print "Stopping"
+ self.completed = True