VOL-649: Support MIB Upload Next with sequence numbers > 255
Corrected parameter range typo in OntDataFrame documentation

Change-Id: Ic578bd2741d16b034298f3a1d685b8966dee685d
diff --git a/tests/utests/voltha/extensions/omci/test_me_frame.py b/tests/utests/voltha/extensions/omci/test_me_frame.py
index bee69f4..e188048 100644
--- a/tests/utests/voltha/extensions/omci/test_me_frame.py
+++ b/tests/utests/voltha/extensions/omci/test_me_frame.py
@@ -14,6 +14,7 @@
 # limitations under the License.
 #
 from unittest import TestCase, main
+from nose.tools import assert_raises
 from voltha.extensions.omci.me_frame import *
 from voltha.extensions.omci.omci_me import *
 from voltha.extensions.omci.omci import *
@@ -269,6 +270,34 @@
     def test_constraint_errors(self):
         self.assertTrue(True)  # TODO Also test some attribute constraint failures
 
+    def test_mib_upload_next(self):
+        # Test for VOL-649 error. SCAPY was only originally coded for a 'get'
+        # action (8-bit MIB Data Sync value) but MIB Upload Next commands have
+        # a 16-bit field.
+        #
+        # 255 and less always worked
+        OntDataFrame(sequence_number=0).mib_upload_next()
+        OntDataFrame(sequence_number=255).mib_upload_next()
+        # But not 256+
+        OntDataFrame(sequence_number=256).mib_upload_next()
+        OntDataFrame(sequence_number=1000).mib_upload_next()
+        OntDataFrame(sequence_number=0xFFFE).mib_upload_next()
+
+        # Also test the optional arguments for the other actions
+        OntDataFrame().get()
+        OntDataFrame(mib_data_sync=4).set()
+        OntDataFrame().mib_reset()
+        OntDataFrame().mib_upload()
+        # OntDataFrame(ignore_arc=True).get_all_alarms()        Not yet coded
+        # OntDataFrame(ignore_arc=False).get_all_alarms()       Not yet coded
+
+        # Range/type checks
+        assert_raises(ValueError, OntDataFrame, mib_data_sync=-1)
+        assert_raises(ValueError, OntDataFrame, mib_data_sync=256)
+        assert_raises(ValueError, OntDataFrame, sequence_number=-1)
+        assert_raises(ValueError, OntDataFrame, sequence_number=0x10000)
+        assert_raises(TypeError, OntDataFrame, ignore_arc=123)
+
 
 if __name__ == '__main__':
     main()
diff --git a/voltha/extensions/omci/omci_cc.py b/voltha/extensions/omci/omci_cc.py
index 8f1bb4d..5a4ad6c 100644
--- a/voltha/extensions/omci/omci_cc.py
+++ b/voltha/extensions/omci/omci_cc.py
@@ -576,7 +576,7 @@
     def send_mib_upload_next(self, seq_no, timeout=DEFAULT_OMCI_TIMEOUT):
         self.log.debug('send-mib-upload-next')
 
-        frame = OntDataFrame(seq_no).mib_upload_next()
+        frame = OntDataFrame(sequence_number=seq_no).mib_upload_next()
         return self.send(frame, timeout)
 
     def send_reboot(self, timeout=DEFAULT_OMCI_TIMEOUT):
diff --git a/voltha/extensions/omci/omci_entities.py b/voltha/extensions/omci/omci_entities.py
index c39335d..505c6b9 100644
--- a/voltha/extensions/omci/omci_entities.py
+++ b/voltha/extensions/omci/omci_entities.py
@@ -213,7 +213,8 @@
     attributes = [
         ECA(ShortField("managed_entity_id", None), {AA.R},
             range_check=lambda x: x == 0),
-        ECA(ByteField("mib_data_sync", 0), {AA.R, AA.W})
+        # Only 1 octet used if GET/SET operation
+        ECA(ShortField("mib_data_sync", 0), {AA.R, AA.W})
     ]
     mandatory_operations = {OP.Get, OP.Set,
                             OP.GetAllAlarms, OP.GetAllAlarmsNext,
@@ -857,6 +858,7 @@
     def to_json(self):
         return json.dumps(self.fields)
 
+
 class DownstreamIgmpMulticastTci(Packet):
     name = "DownstreamIgmpMulticastTci"
     fields_desc = [
diff --git a/voltha/extensions/omci/omci_me.py b/voltha/extensions/omci/omci_me.py
index fdd404a..431ea41 100644
--- a/voltha/extensions/omci/omci_me.py
+++ b/voltha/extensions/omci/omci_me.py
@@ -649,16 +649,41 @@
     """
     This managed entity models the MIB itself
     """
-    def __init__(self, mib_data_sync=None):
+    def __init__(self, mib_data_sync=None, sequence_number=None, ignore_arc=None):
         """
+        For 'get', 'MIB reset', 'MIB upload', pass no value
+        For 'set' actions, pass mib_data_sync value (0..255)
+        For 'MIB upload next',and 'Get all alarms next' pass sequence_number value (0..65535)
+        For 'Get all alarms", set ignore_arc to True to get all alarms regadrless
+                              of ARC status or False to get all alarms not currently
+                              under ARC
+
         :param mib_data_sync: (int) This attribute is used to check the alignment
                                     of the MIB of the ONU with the corresponding MIB
-                                    in the OLT. (0..0xFFFF)
+                                    in the OLT. (0..0xFF)
+        :param sequence_number: (int) This is used for MIB Upload Next (0..0xFFFF)
+        :param ignore_arc: (bool) None for all but 'get_all_alarm' commands
         """
         self.check_type(mib_data_sync, (int, type(None)))
-        if mib_data_sync is not None and not 0 <= mib_data_sync <= 0xFFFF:
-            raise ValueError('mib_data_sync should be 0..0xFFFF')   # TODO: Verify max value
+        if mib_data_sync is not None and not 0 <= mib_data_sync <= 0xFF:
+            raise ValueError('mib_data_sync should be 0..0xFF')
 
-        data = {'mib_data_sync': mib_data_sync} if mib_data_sync is not None else None
+        if sequence_number is not None and not 0 <= sequence_number <= 0xFFFF:
+            raise ValueError('sequence_number should be 0..0xFFFF')
+
+        if ignore_arc is not None and not isinstance(ignore_arc, bool):
+            raise TypeError('ignore_arc should be a boolean')
+
+        if mib_data_sync is not None:
+            data = {'mib_data_sync': mib_data_sync}
+
+        elif sequence_number is not None:
+            data = {'mib_data_sync': sequence_number}
+
+        elif ignore_arc is not None:
+            data = {'mib_data_sync': 0 if ignore_arc else 1}
+
+        else:
+            data = {'mib_data_sync'}    # Make Get's happy
 
         super(OntDataFrame, self).__init__(OntData, 0, data)
diff --git a/voltha/extensions/omci/tasks/get_mds_task.py b/voltha/extensions/omci/tasks/get_mds_task.py
index 0fa0ae7..b042877 100644
--- a/voltha/extensions/omci/tasks/get_mds_task.py
+++ b/voltha/extensions/omci/tasks/get_mds_task.py
@@ -83,7 +83,7 @@
             #########################################
             # Request (MDS supplied value does not matter for a 'get' request)
 
-            results = yield device.omci_cc.send(OntDataFrame(mib_data_sync=123).get())
+            results = yield device.omci_cc.send(OntDataFrame().get())
 
             omci_msg = results.fields['omci_message'].fields
             status = omci_msg['success_code']