Finished OLT initialization.
OLT can now initialise even if the DBA algorithm is
already running.
Change-Id: I89218cc5a70f720fb193631ba3065b0c103e7e2f
diff --git a/voltha/adapters/microsemi/OltStateMachine.py b/voltha/adapters/microsemi/OltStateMachine.py
index a2db517..3f389b8 100644
--- a/voltha/adapters/microsemi/OltStateMachine.py
+++ b/voltha/adapters/microsemi/OltStateMachine.py
@@ -17,13 +17,15 @@
from scapy.layers.l2 import sendp
import structlog
from voltha.adapters.microsemi.PAS5211 import PAS5211MsgGetProtocolVersion, PAS5211MsgGetOltVersion, \
- PAS5211MsgGetOltVersionResponse, PAS5211MsgGetProtocolVersionResponse, PAS5211MsgSetOltOptics, BurstTimingCtrl, \
+ PAS5211MsgGetOltVersionResponse, PAS5211MsgGetProtocolVersionResponse, \
SnrBurstDelay, RngBurstDelay, GeneralOpticsParams, ResetValues, ResetTimingCtrl, PreambleParams, \
PAS5211MsgSetOltOpticsResponse, CHANNELS, PON_OPTICS_VOLTAGE_IF_LVPECL, PON_ENABLE, PON_POLARITY_ACTIVE_HIGH, \
PON_SD_SOURCE_LASER_SD, PON_RESET_TYPE_DELAY_BASED, PON_DISABLE, PON_RESET_TYPE_NORMAL_START_BURST_BASED, \
- PAS5211MsgSetOpticsIoControl, PON_POLARITY_ACTIVE_LOW, PAS5211MsgSetOpticsIoControlResponse, \
- PAS5211MsgGetGeneralParam, PON_TX_ENABLE_DEFAULT, PAS5211MsgGetGeneralParamResponse, PAS5211MsgAddOltChannel, \
- PAS5211MsgAddOltChannelResponse, PON_ALARM_LOS, PAS5211MsgSetAlarmConfigResponse
+ PAS5211MsgSetOpticsIoControlResponse, PON_TX_ENABLE_DEFAULT, PAS5211MsgGetGeneralParamResponse, PAS5211MsgAddOltChannel, \
+ PAS5211MsgAddOltChannelResponse, PON_ALARM_LOS, PAS5211MsgSetAlarmConfigResponse, PAS5211MsgGetDbaMode, \
+ PAS5211MsgGetDbaModeResponse, PON_DBA_MODE_LOADED_NOT_RUNNING, PAS5211MsgStartDbaAlgorithm, \
+ PAS5211MsgStartDbaAlgorithmResponse, PON_DBA_MODE_RUNNING, PAS5211MsgSetOltChannelActivationPeriod, \
+ PAS5211MsgSetOltChannelActivationPeriodResponse
from voltha.adapters.microsemi.PAS5211_utils import general_param, olt_optics_pkt, burst_timing, io_ctrl_optics, \
alarm_config
@@ -41,6 +43,7 @@
verbose = None
send_state = []
+ dba_needs_start = False
def parse_args(self, debug=0, store=0, **kwargs):
self.comm = kwargs.pop('comm', None)
@@ -77,6 +80,10 @@
self.send_state = []
return True
+ """
+ States
+ """
+
@ATMT.state(initial=1)
def disconnected(self):
pass
@@ -137,23 +144,49 @@
def got_alarm_set(self):
pass
- @ATMT.state(final=1)
+ @ATMT.state()
+ def wait_dba_mode(self):
+ pass
+
+ @ATMT.state()
+ def got_dba_mode(self):
+ pass
+
+ @ATMT.state()
+ def wait_dba_start(self):
+ pass
+
+ @ATMT.state()
+ def got_dba_start(self):
+ pass
+
+ @ATMT.state()
+ def wait_activation(self):
+ pass
+
+ @ATMT.state()
def initialized(self):
pass
+ @ATMT.state()
+ def wait_keepalive(self):
+ pass
+
@ATMT.state(error=1)
def ERROR(self):
pass
+ """
+ Transitions
+ """
-
- #Transitions from disconnected state
+ # Transitions from disconnected state
@ATMT.condition(disconnected)
def send_proto_request(self):
self.send(self.p(PAS5211MsgGetProtocolVersion()))
raise self.wait_for_proto_version()
- #Transitions from wait_for_proto_version
+ # Transitions from wait_for_proto_version
@ATMT.timeout(wait_for_proto_version, 1)
def timeout_proto(self):
log.info("Timed out waiting for proto version")
@@ -324,7 +357,7 @@
if PAS5211MsgGetGeneralParamResponse in pkt:
self.send_state[pkt.channel_id] = True
if pkt.value == PON_ENABLE:
- # we may want to do something here.
+ # TODO: we may want to do something here.
if self.check_channel_state():
raise self.got_query_response()
else:
@@ -379,9 +412,101 @@
raise self.got_alarm_set()
raise self.wait_alarm_set()
- @ATMT.timeout(got_alarm_set, 1)
+ # Transitions from got_alarm_set
+ @ATMT.condition(got_alarm_set)
+ def send_dba_mode(self):
+ get_dba_mode = PAS5211MsgGetDbaMode()
+ for id in CHANNELS:
+ self.send_state.append(False)
+ self.send(self.p(get_dba_mode, channel_id=id))
+ raise self.wait_dba_mode()
+
+ # Transitions from wait_dba_mode
+ @ATMT.timeout(wait_dba_mode, 3)
+ def dba_timeout(self):
+ log.error("No DBA information returned; disconnecting")
+ raise self.ERROR()
+
+
+ @ATMT.receive_condition(wait_dba_mode)
+ def wait_for_dba_mode(self, pkt):
+
+ if PAS5211MsgGetDbaModeResponse in pkt:
+ # TODO: What do we do in case the DBA is not loaded.
+ if pkt.dba_mode == PON_DBA_MODE_LOADED_NOT_RUNNING:
+ self.send_state[pkt.channel_id] = True
+ self.dba_needs_start = True
+ elif pkt.dba_mode == PON_DBA_MODE_RUNNING:
+ self.send_state[pkt.channel_id] = True
+ if self.check_channel_state():
+ if self.dba_needs_start:
+ raise self.got_dba_mode()
+ else:
+ raise self.got_dba_start()
+ raise self.wait_dba_mode()
+
+ # Transition from got_dba_mode
+ @ATMT.condition(got_dba_mode)
+ def send_start_dba(self):
+ dba_start = PAS5211MsgStartDbaAlgorithm(size=0, initialization_data=None)
+ for id in CHANNELS:
+ self.send_state.append(False)
+ self.send(self.p(dba_start, channel_id=id))
+ raise self.wait_dba_start()
+
+ # Transitions from wait_dba_start
+ @ATMT.timeout(wait_dba_start, 3)
+ def dba_timeout(self):
+ log.error("DBA has not started; disconnecting")
+ raise self.ERROR()
+
+ @ATMT.receive_condition(wait_dba_start)
+ def wait_for_dba_start(self, pkt):
+ if pkt.opcode == PAS5211MsgStartDbaAlgorithmResponse.opcode:
+ self.send_state[pkt.channel_id] = True
+ if self.check_channel_state():
+ raise self.got_dba_start()
+ raise self.wait_dba_start()
+
+ # Transitions from got_dba_start
+ @ATMT.condition(got_dba_start)
+ def send_activation_period(self):
+ activation = PAS5211MsgSetOltChannelActivationPeriod(activation_period=1000)
+ for id in CHANNELS:
+ self.send_state.append(False)
+ self.send(self.p(activation, channel_id=id))
+ raise self.wait_activation()
+
+ # Transitions for wait_for_activation
+ @ATMT.timeout(wait_activation, 3)
+ def timeout_activation(self):
+ log.error("No activation; disconnect")
+ raise self.ERROR()
+
+ @ATMT.receive_condition(wait_activation)
+ def wait_for_activation(self, pkt):
+ if pkt.opcode == PAS5211MsgSetOltChannelActivationPeriodResponse.opcode:
+ self.send_state[pkt.channel_id] = True
+ if self.check_channel_state():
+ raise self.initialized()
+ raise self.wait_activation()
+
+ # Keep alive loop
+ @ATMT.timeout(initialized, 1)
def send_keepalive(self):
self.send(self.p(PAS5211MsgGetOltVersion()))
- raise self.got_alarm_set()
+ raise self.wait_keepalive()
+
+ # Transitions from wait_keepalive
+ @ATMT.timeout(wait_keepalive, 1)
+ def timeout_keepalive(self):
+ log.error("OLT not responsing to keepalive; disconnecting")
+ raise self.ERROR()
+
+ @ATMT.receive_condition(wait_keepalive)
+ def wait_for_keepalive(self, pkt):
+ if PAS5211MsgGetOltVersionResponse in pkt:
+ raise self.initialized()
+
diff --git a/voltha/adapters/microsemi/PAS5211.py b/voltha/adapters/microsemi/PAS5211.py
index f24af17..41f3882 100644
--- a/voltha/adapters/microsemi/PAS5211.py
+++ b/voltha/adapters/microsemi/PAS5211.py
@@ -516,6 +516,21 @@
LEIntField("parameter4", None)
]
+class PAS5211MsgStartDbaAlgorithm(PAS5211Msg):
+ opcode = 55
+ name = "PAS5211MsgStartDbaAlgorithm"
+ fields_desc = [
+ LEShortField("size", 0),
+ ByteField("initialization_data", 0)
+ ]
+
+
+class PAS5211MsgStartDbaAlgorithmResponse(PAS5211Msg):
+ name = "PAS5211MsgStartDbaAlgorithmResponse"
+ opcode = 10295
+ fields_desc = []
+
+
class PAS5211MsgSetOltChannelActivationPeriod(PAS5211Msg):
opcode = 11
@@ -526,6 +541,7 @@
class PAS5211MsgSetOltChannelActivationPeriodResponse(PAS5211Msg):
+ opcode = 10251
name = "PAS5211MsgSetOltChannelActivationPeriodResponse"
fields_desc = []
@@ -535,6 +551,18 @@
name = "PAS5211MsgSetAlarmConfigResponse"
fields_desc = []
+class PAS5211MsgGetDbaMode(PAS5211Msg):
+ opcode = 57
+ name = "PAS5211MsgGetDbaMode"
+ fields_desc = []
+
+
+class PAS5211MsgGetDbaModeResponse(PAS5211Msg):
+ name = "PAS5211MsgGetDbaModeResponse"
+ fields_desc = [
+ LEIntField("dba_mode", None),
+ ]
+
"""
Bindings used for message processing
"""
@@ -546,3 +574,6 @@
bind_layers(PAS5211MsgHeader, PAS5211MsgGetProtocolVersionResponse, opcode=0x2800 | 2)
bind_layers(PAS5211MsgHeader, PAS5211MsgGetGeneralParamResponse, opcode=0x2800 | 165)
bind_layers(PAS5211MsgHeader, PAS5211MsgSetAlarmConfigResponse, opcode=0x2800 | 48)
+bind_layers(PAS5211MsgHeader, PAS5211MsgGetDbaModeResponse, opcode=0x2800 | 57)
+bind_layers(PAS5211MsgHeader, PAS5211MsgStartDbaAlgorithmResponse, opcode=0x2800 | 55)
+bind_layers(PAS5211MsgHeader, PAS5211MsgSetOltChannelActivationPeriodResponse, opcode=0x2800 | 11)
\ No newline at end of file
diff --git a/voltha/adapters/microsemi/PAS5211_comm.py b/voltha/adapters/microsemi/PAS5211_comm.py
index 863cfbb..623b498 100644
--- a/voltha/adapters/microsemi/PAS5211_comm.py
+++ b/voltha/adapters/microsemi/PAS5211_comm.py
@@ -14,9 +14,7 @@
# limitations under the License.
#
import netifaces
-import select
from scapy.layers.l2 import Dot3
-from scapy.sendrecv import srp1
import structlog
from voltha.adapters.microsemi.PAS5211 import PAS5211Msg, PAS5211MsgHeader, PAS5211FrameHeader
diff --git a/voltha/adapters/microsemi/RubyAdapter.py b/voltha/adapters/microsemi/RubyAdapter.py
index 8050cb8..80edb8c 100644
--- a/voltha/adapters/microsemi/RubyAdapter.py
+++ b/voltha/adapters/microsemi/RubyAdapter.py
@@ -19,7 +19,8 @@
"""
import structlog
from twisted.internet import reactor
-from zope.interface import implementer
+
+
from voltha.adapters.interface import IAdapterInterface
from voltha.adapters.microsemi.OltStateMachine import OltStateMachine
@@ -28,11 +29,13 @@
from voltha.protos.device_pb2 import DeviceTypes
from voltha.protos.health_pb2 import HealthStatus
+from zope.interface import implementer
+
log = structlog.get_logger()
_ = third_party
# Move to configuration... eventually
-olt_conf = { 'olts' : { 'id' : 0, 'mac' : '00:0c:d5:00:01:00'}, 'iface' : 'en0'}
+olt_conf = { 'olts' : { 'id' : 0, 'mac' : '00:0c:d5:00:01:00'}, 'iface' : 'eth3'}
@implementer(IAdapterInterface)
class RubyAdapter(object):
@@ -65,11 +68,11 @@
return self.descriptor
def device_types(self):
- pass
return DeviceTypes(
- items=[] # TODO
+ items=[] # TODO
)
+
def health(self):
return HealthStatus(state=HealthStatus.HealthState.HEALTHY)
diff --git a/voltha/adapters/microsemi/sniff.py b/voltha/adapters/microsemi/sniff.py
index 23cb7ee..915efe6 100755
--- a/voltha/adapters/microsemi/sniff.py
+++ b/voltha/adapters/microsemi/sniff.py
@@ -1,11 +1,13 @@
#!/usr/bin/env python
import code
+import sys
+from scapy.config import conf
+from scapy.data import ARPHDR_ETHER
-from time import sleep
from scapy.fields import Field, lhex, MACField, LenField, LEShortField, \
LEIntField, LESignedIntField, FieldLenField, FieldListField, PacketField, \
- ByteField, StrField, ConditionalField, StrFixedLenField
-from scapy.layers.l2 import DestMACField, ETHER_ANY, ETH_P_ALL, sniff, sendp, LLC, SNAP, Dot3
+ ByteField, StrField, ConditionalField, StrFixedLenField, LELongField
+from scapy.layers.l2 import DestMACField, ETHER_ANY, LLC, Dot3
from scapy.layers.ntp import XLEShortField
from scapy.packet import Packet, bind_layers, split_layers
from scapy.utils import rdpcap
@@ -194,25 +196,6 @@
Field.__init__(self, name, default, "<h")
-class PAS5211Dot3(Packet):
- name = "PAS5211Dot3"
- fields_desc = [ DestMACField("dst"),
- MACField("src", ETHER_ANY),
- LenField("len", None, "H") ]
-
- MIN_FRAME_SIZE = 60
-
- def post_build(self, pkt, payload):
- pkt += payload
- size = ord(payload[4]) + (ord(payload[5]) << 8)
- length = size + 6 # this is a idiosyncracy of the PASCOMM protocol
- pkt = pkt[:12] + chr(length >> 8) + chr(length & 0xff) + pkt[14:]
- padding = self.MIN_FRAME_SIZE - len(pkt)
- if padding > 0:
- pkt = pkt + ("\x00" * padding)
- return pkt
-
-
class PAS5211FrameHeader(Packet):
name = "PAS5211FrameHeader"
fields_desc = [
@@ -443,6 +426,22 @@
def extract_padding(self, p):
return "", p
+
+class PAS5211MsgStartDbaAlgorithm(PAS5211Msg):
+ opcode = 55
+ name = "PAS5211MsgStartDbaAlgorithm"
+ fields_desc = [
+ LEShortField("size", 0),
+ ByteField("initialization_data", None)
+ ]
+
+
+class PAS5211MsgStartDbaAlgorithmResponse(PAS5211Msg):
+ name = "PAS5211MsgStartDbaAlgorithmResponse"
+ opcode = 10295
+ fields_desc = []
+
+
class PAS5211MsgSetGeneralParam(PAS5211Msg):
opcode = 164
name = "PAS5211MsgSetGeneralParam"
@@ -482,13 +481,15 @@
fields_desc = []
-class PAS5211MsgGetDbaModeResponse(PAS5211Msg):
+class PAS5211MsgGetDbaModeResponse(PAS5211Msg):
name = "PAS5211MsgGetDbaModeResponse"
fields_desc = [
LEIntField("dba_mode", None),
]
+
+
class PAS5211MsgAddOltChannel(PAS5211Msg):
opcode = 4
name = "PAS5211MsgAddOltChannel"
@@ -603,8 +604,9 @@
# bindings for messages received
+
split_layers(Dot3, LLC)
-bind_layers(Dot3,PAS5211FrameHeader)
+bind_layers(Dot3, PAS5211FrameHeader)
bind_layers(PAS5211FrameHeader, PAS5211MsgHeader)
bind_layers(PAS5211MsgHeader, PAS5211MsgGetProtocolVersion, opcode=0x3000 | 2)
@@ -634,6 +636,9 @@
bind_layers(PAS5211MsgHeader, PAS5211MsgSetOltChannelActivationPeriod, opcode=0x3000 | 11)
bind_layers(PAS5211MsgHeader, PAS5211MsgSetOltChannelActivationPeriodResponse, opcode=0x2800 | 11)
+bind_layers(PAS5211MsgHeader, PAS5211MsgStartDbaAlgorithm, opcode=0x3000 | 55)
+bind_layers(PAS5211MsgHeader, PAS5211MsgStartDbaAlgorithmResponse, opcode=0x2800 | 55)
+
bind_layers(PAS5211MsgHeader, PAS5211MsgGetDbaMode, opcode=0x3000 | 57)
bind_layers(PAS5211MsgHeader, PAS5211MsgGetDbaModeResponse, opcode=0x2800 | 57)
@@ -658,7 +663,7 @@
if __name__ == '__main__':
- packets = rdpcap('pcaps/olt.pcap')
+ packets = rdpcap(sys.argv[1])
p = Display(packets)
code.interact(local=locals())