Cleanup adapter code and address a few issues

Change-Id: I114712d9afc27d504b0aebc71f9c5307084db947
diff --git a/voltha/adapters/dpoe_onu/dpoe_onu.py b/voltha/adapters/dpoe_onu/dpoe_onu.py
index 2bf9397..e53c30f 100644
--- a/voltha/adapters/dpoe_onu/dpoe_onu.py
+++ b/voltha/adapters/dpoe_onu/dpoe_onu.py
@@ -58,10 +58,10 @@
 from voltha.extensions.eoam.EOAM_TLV import DeviceId
 from voltha.extensions.eoam.EOAM_TLV import ClauseSubtypeEnum
 from voltha.extensions.eoam.EOAM_TLV import RuleOperatorEnum
-from voltha.extensions.eoam.EOAM_TLV import FirmwareInfo
+from voltha.extensions.eoam.EOAM_TLV import FirmwareInfo, CablelabsOUI
+from voltha.extensions.eoam.EOAM_TLV import DPoEOpcode_GetRequest, DPoEOpcode_SetRequest
+from voltha.extensions.eoam.EOAM_Layers import EOAMPayload
 
-from voltha.extensions.eoam.EOAM import EOAMPayload, CablelabsOUI
-from voltha.extensions.eoam.EOAM import DPoEOpcode_GetRequest, DPoEOpcode_SetRequest
 
 @implementer(IAdapterInterface)
 class DPoEOnuAdapter(object):
diff --git a/voltha/adapters/dpoe_onu/eoam_config.py b/voltha/adapters/dpoe_onu/eoam_config.py
index b69770b..ab96329 100644
--- a/voltha/adapters/dpoe_onu/eoam_config.py
+++ b/voltha/adapters/dpoe_onu/eoam_config.py
@@ -37,9 +37,8 @@
 
 # TODO should remove import *
 from EOAM_TLV import *
+from EOAM_Layers import EOAM_MULTICAST_ADDRESS, IGMP_MULTICAST_ADDRESS
 
-EOAM_MULTICAST_ADDRESS = '01:80:c2:00:00:02'
-IGMP_MULTICAST_ADDRESS = '01:00:5e:00:00:01'   # for test
 
 class EOAM():
     """ EOAM frame layer """
diff --git a/voltha/adapters/tibit_olt/tibit_olt.py b/voltha/adapters/tibit_olt/tibit_olt.py
index c2067b5..9fb4b28 100644
--- a/voltha/adapters/tibit_olt/tibit_olt.py
+++ b/voltha/adapters/tibit_olt/tibit_olt.py
@@ -17,7 +17,6 @@
 """
 Tibit OLT device adapter
 """
-import json
 import time
 from uuid import uuid4
 import struct
@@ -34,6 +33,8 @@
 from scapy.fields import XLongField, StrFixedLenField, XIntField, \
     FieldLenField, StrLenField, IntField
 
+
+
 from twisted.internet import reactor
 from twisted.internet.defer import DeferredQueue, inlineCallbacks
 from twisted.internet.task import LoopingCall
@@ -42,12 +43,14 @@
 from common.frameio.frameio import BpfProgramFilter, hexify
 from voltha.adapters.interface import IAdapterInterface
 
-from voltha.extensions.eoam.EOAM import EOAMPayload, EOAMEvent, EOAM_VendSpecificMsg
-from voltha.extensions.eoam.EOAM import EOAM_OmciMsg, EOAM_TibitMsg, EOAM_DpoeMsg
-from voltha.extensions.eoam.EOAM import OAM_ETHERTYPE
-from voltha.extensions.eoam.EOAM import CableLabs_OUI, Tibit_OUI, IEEE_OUI
-from voltha.extensions.eoam.EOAM import RxedOamMsgTypeEnum, Dpoe_Opcodes, get_oam_msg_type, \
-    handle_get_value, get_value_from_msg, check_set_resp, check_resp
+from voltha.extensions.eoam.EOAM_Layers import EOAMPayload, EOAM_EventMsg, EOAM_VendSpecificMsg
+from voltha.extensions.eoam.EOAM_Layers import EOAM_OmciMsg, EOAM_TibitMsg
+from voltha.extensions.eoam.EOAM_Layers import OAM_ETHERTYPE
+from voltha.extensions.eoam.EOAM_Layers import CABLELABS_OUI, TIBIT_OUI, ITU_OUI
+from voltha.extensions.eoam.EOAM_Layers import RxedOamMsgTypeEnum, RxedOamMsgTypes
+from voltha.extensions.eoam.EOAM import get_oam_msg_type, get_value_from_msg, check_set_resp, check_resp
+from voltha.extensions.eoam.EOAM import get_unicast_logical_link, get_olt_queue
+from voltha.extensions.eoam.EOAM import ADTRAN_SHORTENED_VSSN, TIBIT_SHORTENED_VSSN
 
 from voltha.extensions.eoam.EOAM_TLV import DOLTObject, \
      NetworkToNetworkPortObject, OLTUnicastLogicalLink, OLTEPONUnicastLogicalLink, \
@@ -58,11 +61,11 @@
      PortIngressRuleResultDelete, PortIngressRuleResultOLTQueue, \
      PortIngressRuleResultOLTBroadcastQueue, PortIngressRuleResultOLTEPONQueue, \
      PortIngressRuleTerminator, AddPortIngressRule, \
-     ItuOUI, PonPortObject
+     ItuOUI, PonPortObject, DPoEOpcodes
 from voltha.extensions.eoam.EOAM_TLV import PortIngressRuleHeader
-from voltha.extensions.eoam.EOAM_TLV import ClauseSubtypeEnum
-from voltha.extensions.eoam.EOAM_TLV import RuleOperatorEnum
-from voltha.extensions.eoam.EOAM_TLV import DPoEVariableResponseCodes, DPoEOpcodeEnum
+from voltha.extensions.eoam.EOAM_TLV import ClauseSubtypeEnum, RuleClauses
+from voltha.extensions.eoam.EOAM_TLV import RuleOperatorEnum, RuleOperators
+from voltha.extensions.eoam.EOAM_TLV import DPoEVariableResponseEnum, DPoEOpcodeEnum
 from voltha.extensions.eoam.EOAM_TLV import VendorName, OltMode, HardwareVersion, ManufacturerInfo
 from voltha.extensions.eoam.EOAM_TLV import TibitLinkMacTable, OltPonAdminStateSet, TibitDeviceReset
 from voltha.extensions.eoam.EOAM_TLV import SlowProtocolsSubtypeEnum
@@ -75,14 +78,6 @@
     TxFrame_65_127, TxFrame_128_255, TxFrame_256_511, \
     TxFrame_512_1023, TxFrame_1024_1518, TxFrame_1519Plus
 
-from voltha.extensions.eoam.EOAM_TLV import RxFramesGreen, TxFramesGreen, \
-    RxFrame_64, RxFrame_65_127, RxFrame_128_255, RxFrame_256_511, \
-    RxFrame_512_1023,RxFrame_1024_1518, RxFrame_1519Plus, \
-    TxFrame_64, TxFrame_65_127, TxFrame_128_255, \
-    TxFrame_256_511, TxFrame_512_1023, TxFrame_1024_1518, \
-    TxFrame_1519Plus
-
-
 
 from voltha.core.flow_decomposer import *
 from voltha.core.logical_device_agent import mac_str_to_tuple
@@ -101,35 +96,29 @@
 from voltha.registry import registry
 log = structlog.get_logger()
 
-TIBIT_ONU_LINK_INDEX = 2
 
 # Match on the MGMT VLAN, Priority 7
-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_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)
+TIBIT_PACKET_IN_VLAN  = 4000
+frame_match_case2     = '(ether[14:2] & 0xfff) = 0x{:03x}'.format(TIBIT_PACKET_IN_VLAN)
 
 TIBIT_PACKET_OUT_VLAN = 4000
 
 TIBIT_MSG_WAIT_TIME = 3
 
-is_tibit_frame = BpfProgramFilter('{} or {}'.format(
-    frame_match_case1, frame_match_case2))
+is_tibit_frame = BpfProgramFilter('{} or {}'.format(frame_match_case1, frame_match_case2))
 
 
 # TODO: This information should be conveyed to the adapter
 # from a higher level.
 MULTICAST_VLAN = 140
 
-TIBIT_COMMUNICATIONS_OUI=u'000CE2'
-SUMITOMO_ELECTRIC_INDUSTRIES_OUI=u'0025DC'
+TIBIT_COMMUNICATIONS_OUI         = u'000CE2'
+SUMITOMO_ELECTRIC_INDUSTRIES_OUI = u'0025DC'
 
-ADTRAN_SHORTENED_VSSN=u'4144'                 # 'AD'
-TIBIT_SHORTENED_VSSN=u'5442'                 # 'TB'
 
 @implementer(IAdapterInterface)
 class TibitOltAdapter(object):
@@ -206,35 +195,20 @@
             self.incoming_queues[device.mac_address] = DeferredQueue(size=100)
 
             # add mac_address to device_ids table
-            olt_mac = device.mac_address
-            self.device_ids[olt_mac] = device.id
+            self.device_ids[device.mac_address] = device.id
 
             # send out ping to OLT device
-            ping_frame = self._make_ping_frame(mac_address=olt_mac)
-            self.io_port.send(ping_frame)
-
-            # Loop until we have a Get Response or timeout
-            ack = False
-            start_time = time.time()
-            while not ack:
-                frame = yield self.incoming_queues[olt_mac].get()
-                #TODO - Need to add proper timeout functionality
-                #if (time.time() - start_time) > TIBIT_MSG_WAIT_TIME or (frame is None):
-                #    break  # don't wait forever
-
-                respType = get_oam_msg_type(log, frame)
-             
-                if (respType == RxedOamMsgTypeEnum["DPoE Get Response"]):
-                    ack = True
-                else:
-                    # Handle unexpected events/OMCI messages
-                    check_resp(log, frame)
+            resp = []
+            action = "Get Device Info"
+            body = VendorName()/OltMode()/HardwareVersion()/ManufacturerInfo()
+            yield self._get_req_rsp(device, action, body, resp)
+            if resp is not []: frame = resp[0]
 
         except Exception as e:
             log.exception('launch device failed', e=e)
 
-        if ack:
-            # Process the Get Request message
+        if frame:
+            # Process the Get Response message
             self._process_ping_frame_response(device, frame)
 
             yield self.change_device_state(device, 1)
@@ -317,36 +291,19 @@
             # before checking for ONUs
             reactor.callLater(0.1, self._detect_onus, device)
 
-        # END if ack
+        # END if frame
+
 
     @inlineCallbacks
     def _detect_onus(self, device):
         # send out get 'links' to the OLT device
-        olt_mac = device.mac_address
-        links_frame = self._make_links_frame(mac_address=olt_mac)
-        self.io_port.send(links_frame)
+        resp = []
+        action = "Get Registered Links"
+        body = TibitLinkMacTable()
+        yield self._get_req_rsp(device, action, body, resp)
+        if resp is not []: frame = resp[0]
 
-
-        # Loop until we have a Get Response or timeout
-        ack = False
-        start_time = time.time()
-        while not ack:
-
-            frame = yield self.incoming_queues[olt_mac].get()
-
-            #TODO - Need to add proper timeout functionality
-            #if (time.time() - start_time) > TIBIT_MSG_WAIT_TIME or (frame is None):
-            #    break  # don't wait forever
-
-            respType = get_oam_msg_type(log, frame)
- 
-            if (respType == RxedOamMsgTypeEnum["DPoE Get Response"]):
-                ack = True
-            else:
-                # Handle unexpected events/OMCI messages
-                check_resp(log, frame)
-
-        if ack:
+        if frame:
             #Process the Get Response
             mac_table = [0xB7, 0x0103]
             links = []
@@ -360,7 +317,7 @@
                 temp_pair.append(value)
                 if rc:
                     overall_rc = True
-                else: 
+                else:
                     log.info('Failed to get valid response for Branch 0x{:X} Leaf 0x{:0>4X} '.format(temp_pair[0], temp_pair[1]))
 
             if overall_rc and mac_table[rc]:
@@ -373,11 +330,11 @@
                     if linkAddr is None:
                         log.info('MAC Addr is NONE')
                     elif linkAddr[:6].upper() == SUMITOMO_ELECTRIC_INDUSTRIES_OUI:
-                        onu_mac_string = linkAddr 
+                        onu_mac_string = linkAddr
                         log.info('SUMITOMO mac address %s' % str(linkAddr))
                         child_device_name = 'dpoe_onu'
                     elif linkAddr[:4].upper() == ADTRAN_SHORTENED_VSSN:
-                        onu_mac_string = linkAddr 
+                        onu_mac_string = linkAddr
                         log.info('ADTRAN mac address %s' % str(linkAddr))
                         child_device_name = 'adtran_onu'
                     else:
@@ -393,51 +350,29 @@
                         vlan_id = self._olt_side_onu_activation(mac_octet_4)
 
                         macLen += 6
-                
+
                         ## Automatically setup default downstream control frames flow (in this case VLAN 4000)
                         ## on the OLT for the new ONU/ONT device
-                        Clause = {v: k for k, v in ClauseSubtypeEnum.iteritems()}
-                        Operator = {v: k for k, v in RuleOperatorEnum.iteritems()}
 
-                        if self.mode.upper()[0] == "G":  # GPON
-                            if child_device_name is 'tibit_onu':
-                                vssn = "TBIT"
-                            elif child_device_name is 'adtran_onu':
-                                vssn = "ADTN"
-                            link = int(onu_mac_string[4:12], 16)
-                            resultOltQueue = "PortIngressRuleResultOLTQueue(unicastvssn=vssn, unicastlink=link)"
-                        else:                       # EPON
-                            vssn = int(onu_mac_string[0:8].rjust(8,"0"), 16)
-                            link = int((onu_mac_string[8:12]).ljust(8,"0"), 16)
-                            resultOltQueue = "PortIngressRuleResultOLTEPONQueue(unicastvssn=vssn, unicastlink=link)"
-
-                        packet_out_rule = (
-                            Ether(dst=device.mac_address) /
-                            Dot1Q(vlan=TIBIT_MGMT_VLAN, prio=TIBIT_MGMT_PRIORITY) /
-                            EOAMPayload() / EOAM_VendSpecificMsg(oui=Tibit_OUI) /
-                            EOAM_TibitMsg(dpoe_opcode=Dpoe_Opcodes["Set Request"],
-                                body=NetworkToNetworkPortObject()/
-                                PortIngressRuleHeader(precedence=13)/
-                                PortIngressRuleClauseMatchLength02(fieldcode=Clause['C-VLAN Tag'], fieldinstance=0,
-                                                                   operator=Operator['=='],
-                                                                   match=TIBIT_PACKET_OUT_VLAN)/
-                                PortIngressRuleClauseMatchLength02(fieldcode=Clause['C-VLAN Tag'], fieldinstance=1,
-                                                                   operator=Operator['=='], match=vlan_id)/
-                                eval(resultOltQueue)/
-                                PortIngressRuleResultForward()/
-                                PortIngressRuleResultDelete(fieldcode=Clause['C-VLAN Tag'])/
-                                PortIngressRuleTerminator()/
-                                AddPortIngressRule())/
-                            EndOfPDU()
-                            )
-
+                        resultOltQueue = get_olt_queue(onu_mac_string, self.mode)
                         action = "Set DS Rule for ONU to strip C Tag"
-                        log.info('OLT-send to {} for OLT: {}'.format(action, olt_mac))
-                        self.io_port.send(str(packet_out_rule))
+
+                        body=NetworkToNetworkPortObject()
+                        body/=PortIngressRuleHeader(precedence=13)
+                        body/=PortIngressRuleClauseMatchLength02(fieldcode=RuleClauses['C-VLAN Tag'], fieldinstance=0,
+                                                           operator=RuleOperators['=='],
+                                                           match=TIBIT_PACKET_OUT_VLAN)
+                        body/=PortIngressRuleClauseMatchLength02(fieldcode=RuleClauses['C-VLAN Tag'], fieldinstance=1,
+                                                           operator=RuleOperators['=='], match=vlan_id)
+                        body/=eval(resultOltQueue)
+                        body/=PortIngressRuleResultForward()
+                        body/=PortIngressRuleResultDelete(fieldcode=RuleClauses['C-VLAN Tag'])
+                        body/=PortIngressRuleTerminator()
+                        body/=AddPortIngressRule()
 
                         # Get and process the Set Response
                         rc = []
-                        yield self._handle_set_resp(olt_mac, action, rc)
+                        yield self._set_req_rsp(device, action, body, rc)
 
                         if rc[0] is True:
                             # also record the vlan_id -> (device_id, logical_device_id, linkid) for
@@ -462,7 +397,7 @@
                     # END linkAddr is not none
             else:
                 log.info('No links were found in the MAC Table')
-				# Poll to get more ONUs
+		        # Poll to get more ONUs
                 reactor.callLater(3, self._detect_onus, device)
 
             # END if mac_table[rc]
@@ -549,29 +484,15 @@
                 log.info('received-dot1q-not-8100')
                 self.incoming_queues[response.src].put(response)
 
-    def _make_ping_frame(self, mac_address):
-        frame = (
-            Ether(dst=mac_address) /
-            Dot1Q(vlan=TIBIT_MGMT_VLAN, prio=TIBIT_MGMT_PRIORITY) /
-            EOAMPayload() / EOAM_VendSpecificMsg(oui=Tibit_OUI) /
-            EOAM_TibitMsg(dpoe_opcode=Dpoe_Opcodes["Get Request"],body=VendorName() /
-                                                OltMode() /
-                                                HardwareVersion() /
-                                                ManufacturerInfo()
-                                                ) /
-            EndOfPDU()
-            )
-
-        return str(frame)
 
     def _process_ping_frame_response(self, device, frame):
 
-        vendor = [0xD7, 0x0011]
-        oltMode = [0xB7, 0x0101]
-        hw_version = [0xD7, 0x0013]
-        manufacturer =  [0xD7, 0x0006]
+        vendor       = [VendorName().branch, VendorName().leaf]
+        oltMode      = [OltMode().branch, OltMode().leaf]
+        hw_version   = [HardwareVersion().branch, HardwareVersion().leaf]
+        manufacturer = [ManufacturerInfo().branch, ManufacturerInfo().leaf]
         branch_leaf_pairs = [vendor, oltMode, hw_version, manufacturer]
-                    
+
         for pair in branch_leaf_pairs:
             temp_pair = pair
             (rc, value) = (get_value_from_msg(log, frame, pair[0], pair[1]))
@@ -579,7 +500,7 @@
             temp_pair.append(value)
             if rc:
                 overall_rc = True
-            else: 
+            else:
                 log.info('Failed to get valid response for Branch 0x{:X} Leaf 0x{:0>4X} '.format(temp_pair[0], temp_pair[1]))
                 ack = True
 
@@ -589,9 +510,9 @@
                 device.vendor = device.vendor[:-1]
         else:
             device.vendor = "UNKNOWN"
-            
+
         # mode: 3 = EPON OLT, 7 = GPON OLT
-        # mode: 2 = EPON ONU, 6 = GPON ONU    
+        # mode: 2 = EPON ONU, 6 = GPON ONU
         if oltMode[rc]:
             value = oltMode.pop()
             mode = "UNKNOWN"
@@ -614,7 +535,7 @@
             self.mode = "UNKNOWN"
 
         log.info("OLT Mode is {}".format(self.mode))
-                
+
         if hw_version[rc]:
             device.hardware_version = hw_version.pop()
             device.hardware_version = device.hardware_version.replace("FA","")
@@ -640,90 +561,12 @@
         device.root = True
         device.connect_status = ConnectStatus.REACHABLE
 
-    def _make_links_frame(self, mac_address):
-        frame = (
-            Ether(dst=mac_address) /
-            Dot1Q(vlan=TIBIT_MGMT_VLAN, prio=TIBIT_MGMT_PRIORITY) /
-            EOAMPayload() / EOAM_VendSpecificMsg(oui=Tibit_OUI) /
-            EOAM_TibitMsg(dpoe_opcode=Dpoe_Opcodes["Get Request"],body=TibitLinkMacTable()
-                            )/
-            EndOfPDU()
-            )
-        return str(frame)
-
-    def _make_link_stats_frame(self, olt_mac_address, onu_mac_address):
-
-        if self.mode.upper()[0] == "G":  # GPON
-            vssn = "TBIT"
-            link = int(onu_mac_address[4:12], 16)
-            logical_link = "OLTUnicastLogicalLink(unicastvssn=vssn, unicastlink=link)"
-        else:                       # EPON
-            vssn = int(onu_mac_address[0:8].rjust(8,"0"), 16)
-            link = int((onu_mac_address[8:12]).ljust(8,"0"), 16)
-            logical_link = "OLTEPONUnicastLogicalLink(unicastvssn=vssn, unicastlink=link)"
-
-        frame = (
-            Ether(dst=olt_mac_address) /
-            Dot1Q(vlan=TIBIT_MGMT_VLAN, prio=TIBIT_MGMT_PRIORITY) /
-            EOAMPayload() / EOAM_VendSpecificMsg(oui=Tibit_OUI) /
-            EOAM_TibitMsg(dpoe_opcode=Dpoe_Opcodes["Get Request"],
-                          body=eval(logical_link)/
-                                #RxFramesGreen()/
-                                #TxFramesGreen()/
-                                RxFrame_64()/
-                                RxFrame_65_127()/
-                                RxFrame_128_255()/
-                                RxFrame_256_511()/
-                                RxFrame_512_1023()/
-                                RxFrame_1024_1518()/
-                                RxFrame_1519Plus()/
-                                TxFrame_64()/
-                                TxFrame_65_127()/
-                                TxFrame_128_255()/
-                                TxFrame_256_511()/
-                                TxFrame_512_1023()/
-                                TxFrame_1024_1518()/
-                                TxFrame_1519Plus()
-                            )/
-            EndOfPDU()
-            )
-
-        return str(frame)
-
-    def _make_nni_stats_frame(self, mac_address):
-        frame = (
-            Ether(dst=mac_address) /
-            Dot1Q(vlan=TIBIT_MGMT_VLAN, prio=TIBIT_MGMT_PRIORITY) /
-            EOAMPayload() / EOAM_VendSpecificMsg(oui=Tibit_OUI) /
-            EOAM_TibitMsg(dpoe_opcode=Dpoe_Opcodes["Get Request"], body=NetworkToNetworkPortObject()/
-                                #RxFramesGreen()/
-                                #TxFramesGreen()/
-                                RxFrame_64()/
-                                RxFrame_65_127()/
-                                RxFrame_128_255()/
-                                RxFrame_256_511()/
-                                RxFrame_512_1023()/
-                                RxFrame_1024_1518()/
-                                RxFrame_1519Plus()/
-                                TxFrame_64()/
-                                TxFrame_65_127()/
-                                TxFrame_128_255()/
-                                TxFrame_256_511()/
-                                TxFrame_512_1023()/
-                                TxFrame_1024_1518()/
-                                TxFrame_1519Plus()
-                            )/
-            EndOfPDU()
-            )
-        return str(frame)
 
     def abandon_device(self, device):
-        raise NotImplementedError(0
-                                  )
+        raise NotImplementedError(0)
+
     @inlineCallbacks
     def disable_device(self, device):
-        log.info('Disabling OLT: {}'.format(device.mac_address))
-        yield self.change_device_state(device, 0)
 
         # Update the operational status to UNKNOWN
         device.oper_status = OperStatus.UNKNOWN
@@ -746,6 +589,10 @@
         self.adapter_agent.disable_all_ports(device.id)
         log.info('disabled', device_id=device.id)
 
+        # Update the device last
+        log.info('Disabling OLT: {}'.format(device.mac_address))
+        yield self.change_device_state(device, 0)
+
 
     @inlineCallbacks
     def reenable_device(self, device):
@@ -833,22 +680,11 @@
         self.adapter_agent.update_child_devices_state(device.id,
                                                       connect_status=ConnectStatus.UNREACHABLE)
 
-        msg = (
-            Ether(dst=device.mac_address) /
-            Dot1Q(vlan=TIBIT_MGMT_VLAN, prio=TIBIT_MGMT_PRIORITY) /
-            EOAMPayload() / EOAM_VendSpecificMsg(oui=Tibit_OUI) /
-            EOAM_TibitMsg(dpoe_opcode = Dpoe_Opcodes["Set Request"], 
-                          body=TibitDeviceReset())/
-            EndOfPDU()
-            )
-        olt_mac = device.mac_address
+        # Send the Device Reset
         action = "Device Reset"
-        log.info('OLT-send to {} for OLT: {}'.format(action, olt_mac))
-        self.io_port.send(str(msg))
-
-        # Get and process the Set Response
         rc = []
-        yield self._handle_set_resp(olt_mac, action, rc)
+        tlvs = TibitDeviceReset()
+        yield self._set_req_rsp(device, action, tlvs, rc)
 
         # Change the operational status back to its previous state.
         device.oper_status = previous_oper_status
@@ -910,9 +746,6 @@
         _inner_vid = None
         olt_mac = device.mac_address
 
-        Clause = {v: k for k, v in ClauseSubtypeEnum.iteritems()}
-        Operator = {v: k for k, v in RuleOperatorEnum.iteritems()}
-
         for flow in flows.items:
 
             try:
@@ -932,8 +765,8 @@
                             _type = field.eth_type
                             log.info('#### field.type == ETH_TYPE ####')
                             dn_req /= PortIngressRuleClauseMatchLength02(
-                                fieldcode=Clause['L2 Type/Len'],
-                                operator=Operator['=='],
+                                fieldcode=RuleClauses['L2 Type/Len'],
+                                operator=RuleOperators['=='],
                                 match=_type)
 
                         elif field.type == IP_PROTO:
@@ -974,6 +807,8 @@
                             raise NotImplementedError('field.type={}'.format(
                                 field.type))
 
+                    ruleInnerVidNotSet = False;
+
                     for action in get_actions(flow):
 
                         if action.type == OUTPUT:
@@ -985,39 +820,32 @@
                                 serial = _inner_vid - 200
                                 mac_address = self.vlan_to_device_ids[_inner_vid][2].upper()
 
-                                if self.mode.upper()[0] == "G":  # GPON
-                                    vssn = "TBIT"
-                                    link = int(mac_address[4:12], 16)
-                                    resultOltQueue = "PortIngressRuleResultOLTQueue(unicastvssn=vssn, unicastlink=link)"
-                                else:                       # EPON
-                                    vssn = int(mac_address[0:8].rjust(8,"0"), 16)
-                                    link = int((mac_address[8:12]).ljust(8,"0"), 16)
-                                    resultOltQueue = "PortIngressRuleResultOLTEPONQueue(unicastvssn=vssn, unicastlink=link)"
-
+                                resultOltQueue = get_olt_queue(mac_address, self.mode)
                                 dn_req /= eval(resultOltQueue)
 
                             elif _inner_vid is None:
+                                ruleInnerVidNotSet = True
                                 log.info('#### action.type == OUTPUT INNER VID is NONE ####')
 
                         elif action.type == POP_VLAN:
                             log.info('#### action.type == POP_VLAN ####')
                             if _outer_vid == MULTICAST_VLAN:
-                                dn_req /= PortIngressRuleResultDelete(fieldcode=Clause['C-VLAN Tag'])
-                                dn_req /= PortIngressRuleClauseMatchLength02(fieldcode=Clause['C-VLAN Tag'], fieldinstance=0,
-                                                                             operator=Operator['=='], match=_outer_vid)
+                                dn_req /= PortIngressRuleResultDelete(fieldcode=RuleClauses['C-VLAN Tag'])
+                                dn_req /= PortIngressRuleClauseMatchLength02(fieldcode=RuleClauses['C-VLAN Tag'], fieldinstance=0,
+                                                                             operator=RuleOperators['=='], match=_outer_vid)
                             else:
-                                dn_req /= PortIngressRuleResultDelete(fieldcode=Clause['C-VLAN Tag'])
-                                dn_req /= PortIngressRuleClauseMatchLength02(fieldcode=Clause['C-VLAN Tag'], fieldinstance=0,
-                                                                             operator=Operator['=='], match=_outer_vid)
-                                dn_req /= PortIngressRuleClauseMatchLength02(fieldcode=Clause['C-VLAN Tag'], fieldinstance=1,
-                                                                             operator=Operator['=='], match=_inner_vid)
+                                dn_req /= PortIngressRuleResultDelete(fieldcode=RukeClauses['C-VLAN Tag'])
+                                dn_req /= PortIngressRuleClauseMatchLength02(fieldcode=RuleClauses['C-VLAN Tag'], fieldinstance=0,
+                                                                             operator=RuleOperators['=='], match=_outer_vid)
+                                dn_req /= PortIngressRuleClauseMatchLength02(fieldcode=RuleClauses['C-VLAN Tag'], fieldinstance=1,
+                                                                             operator=RuleOperators['=='], match=_inner_vid)
 
                         elif action.type == PUSH_VLAN:
                             log.info('#### action.type == PUSH_VLAN ####')
                             if action.push.ethertype != 0x8100:
                                 log.error('unhandled-tpid',
                                           ethertype=action.push.ethertype)
-                                dn_req /= PortIngressRuleResultInsert(fieldcode=Clause['C-VLAN Tag'])
+                                dn_req /= PortIngressRuleResultInsert(fieldcode=RuleClauses['C-VLAN Tag'])
 
                         elif action.type == SET_FIELD:
                             log.info('#### action.type == SET_FIELD ####')
@@ -1025,8 +853,11 @@
                                     ofp.OFPXMC_OPENFLOW_BASIC)
                             field = action.set_field.field.ofb_field
                             if field.type == VLAN_VID:
+                                # need to convert value in Set to a variable length value
+                                ctagStr = struct.pack('>H', (field.vlan_vid & 0xfff))
+
                                 dn_req /= PortIngressRuleResultSet(
-                                    fieldcode=Clause['C-VLAN Tag'], value=field.vlan_vid & 0xfff)
+                                    fieldcode=RuleClauses['C-VLAN Tag'], value=ctagStr)
                             else:
                                 log.error('unsupported-action-set-field-type',
                                           field_type=field.type)
@@ -1034,25 +865,18 @@
                             log.error('UNSUPPORTED-ACTION-TYPE',
                                       action_type=action.type)
 
+                    # Don't send the rule if a Queue was not set in the Port Ingress Rule
+                    if ruleInnerVidNotSet == True:
+                        continue
+
                     dn_req /= PortIngressRuleTerminator()
                     dn_req /= AddPortIngressRule()
 
-                    msg = (
-                        Ether(dst=device.mac_address) /
-                        Dot1Q(vlan=TIBIT_MGMT_VLAN, prio=TIBIT_MGMT_PRIORITY) /
-                        EOAMPayload() / EOAM_VendSpecificMsg(oui=Tibit_OUI) /
-                        EOAM_TibitMsg(dpoe_opcode = Dpoe_Opcodes["Set Request"], body=dn_req)/
-                        EndOfPDU()
-                    )
-
-                    # Send OAM Request
-                    action = "Set DS Rule"
-                    log.info('OLT-send to {} for OLT: {}'.format(action, olt_mac))
-                    self.io_port.send(str(msg))
-
                     # Get and process the Set Response
+                    action = "Set DS Rule"
                     rc = []
-                    yield self._handle_set_resp(olt_mac, action, rc)
+                    yield self._set_req_rsp(device, action, dn_req, rc)
+
 
                 elif in_port == 1:
                     # Upstream rule
@@ -1071,13 +895,13 @@
                             log.info('#### field.type == ETH_TYPE ####', in_port=in_port,
                                      match=_type)
                             up_req_pon /= PortIngressRuleClauseMatchLength02(
-                                fieldcode=Clause['L2 Type/Len'],
-                                operator=Operator['=='],
+                                fieldcode=RuleClauses['L2 Type/Len'],
+                                operator=RuleOperators['=='],
                                 match=_type)
 
                             up_req_link /= PortIngressRuleClauseMatchLength02(
-                                fieldcode=Clause['L2 Type/Len'],
-                                operator=Operator['=='],
+                                fieldcode=RuleClauses['L2 Type/Len'],
+                                operator=RuleOperators['=='],
                                 match=_type)
 
                         elif field.type == IP_PROTO:
@@ -1086,12 +910,12 @@
                                      ip_proto=_proto)
 
                             up_req_pon /= PortIngressRuleClauseMatchLength01(
-                                fieldcode=Clause['IPv4/IPv6 Protocol Type'],
-                                operator=Operator['=='], match=_proto)
+                                fieldcode=RuleClauses['IPv4/IPv6 Protocol Type'],
+                                operator=RuleOperators['=='], match=_proto)
 
                             up_req_link /= PortIngressRuleClauseMatchLength01(
-                                fieldcode=Clause['IPv4/IPv6 Protocol Type'],
-                                operator=Operator['=='], match=_proto)
+                                fieldcode=RuleClauses['IPv4/IPv6 Protocol Type'],
+                                operator=RuleOperators['=='], match=_proto)
 
                         elif field.type == IN_PORT:
                             _port = field.port
@@ -1101,26 +925,18 @@
                             _vlan_vid = field.vlan_vid & 0xfff
                             log.info('#### field.type == VLAN_VID ####')
                             up_req_pon /= PortIngressRuleClauseMatchLength02(
-                                fieldcode=Clause['C-VLAN Tag'], fieldinstance=0,
-                                operator=Operator['=='], match=_vlan_vid)
+                                fieldcode=RuleClauses['C-VLAN Tag'], fieldinstance=0,
+                                operator=RuleOperators['=='], match=_vlan_vid)
 
                             serial = _vlan_vid - 200
                             mac_address = self.vlan_to_device_ids[_vlan_vid][2].upper()
 
-                            if self.mode.upper()[0] == "G":  # GPON
-                                vssn = "TBIT"
-                                link = int(mac_address[4:12], 16)
-                                logical_link = "OLTUnicastLogicalLink(unicastvssn=vssn, unicastlink=link)"
-                            else:                       # EPON
-                                vssn = int(mac_address[0:8].rjust(8,"0"), 16)
-                                link = int((mac_address[8:12]).ljust(8,"0"), 16)
-                                logical_link = "OLTEPONUnicastLogicalLink(unicastvssn=vssn, unicastlink=link)"
-
+                            logical_link = get_unicast_logical_link(mac_address, self.mode)
                             up_req_link /= eval(logical_link)
-                            
+
                             up_req_link /= PortIngressRuleClauseMatchLength02(
-                                fieldcode=Clause['C-VLAN Tag'], fieldinstance=0,
-                                operator=Operator['=='], match=_vlan_vid)
+                                fieldcode=RuleClauses['C-VLAN Tag'], fieldinstance=0,
+                                operator=RuleOperators['=='], match=_vlan_vid)
                             field_match_vlan_upstream_with_link = True
 
 
@@ -1131,10 +947,10 @@
                         elif field.type == UDP_DST:
                             _udp_dst = field.udp_dst
                             log.info('#### field.type == UDP_DST ####')
-                            up_req_pon /= (PortIngressRuleClauseMatchLength02(fieldcode=Clause['TCP/UDP source port'],
-                                                                              operator=Operator['=='], match=0x0044)/
-                                           PortIngressRuleClauseMatchLength02(fieldcode=Clause['TCP/UDP destination port'],
-                                                                              operator=Operator['=='], match=0x0043))
+                            up_req_pon /= (PortIngressRuleClauseMatchLength02(fieldcode=RuleClauses['TCP/UDP source port'],
+                                                                              operator=RuleOperators['=='], match=0x0044)/
+                                           PortIngressRuleClauseMatchLength02(fieldcode=RuleClauses['TCP/UDP destination port'],
+                                                                              operator=RuleOperators['=='], match=0x0043))
 
                         elif field.type == UDP_SRC:
                             _udp_src = field.udp_src
@@ -1160,10 +976,10 @@
                                 log.error('unhandled-ether-type',
                                           ethertype=action.push.ethertype)
                             if field_match_vlan_upstream_with_link == True:
-                                up_req_link /= PortIngressRuleResultInsert(fieldcode=Clause['C-VLAN Tag'],
+                                up_req_link /= PortIngressRuleResultInsert(fieldcode=RuleClauses['C-VLAN Tag'],
                                                                       fieldinstance=1)
                             else:
-                                up_req_pon /= PortIngressRuleResultInsert(fieldcode=Clause['C-VLAN Tag'],
+                                up_req_pon /= PortIngressRuleResultInsert(fieldcode=RuleClauses['C-VLAN Tag'],
                                                                       fieldinstance=0)
 
                         elif action.type == SET_FIELD:
@@ -1173,13 +989,16 @@
                             field = action.set_field.field.ofb_field
                             if field.type == VLAN_VID:
                                 if field_match_vlan_upstream_with_link == True:
-                                    up_req_link /=(PortIngressRuleResultCopy(fieldcode=Clause['C-VLAN Tag'])/
-                                                   PortIngressRuleResultReplace(fieldcode=Clause['C-VLAN Tag']))
+                                    up_req_link /=(PortIngressRuleResultCopy(fieldcode=RuleClauses['C-VLAN Tag'])/
+                                                   PortIngressRuleResultReplace(fieldcode=RuleClauses['C-VLAN Tag']))
+
+                                # need to convert value in Set to a variable length value
+                                ctagStr = struct.pack('>H', (field.vlan_vid & 0xfff))
 
                                 up_req_pon /= PortIngressRuleResultSet(
-                                    fieldcode=Clause['C-VLAN Tag'], value=field.vlan_vid & 0xfff)
+                                    fieldcode=RuleClauses['C-VLAN Tag'], value=ctagStr)
                                 up_req_link /= PortIngressRuleResultSet(
-                                    fieldcode=Clause['C-VLAN Tag'], value=field.vlan_vid & 0xfff)
+                                    fieldcode=RuleClauses['C-VLAN Tag'], value=ctagStr)
                             else:
                                 log.error('unsupported-action-set-field-type',
                                           field_type=field.type)
@@ -1196,22 +1015,10 @@
                     up_req /= PortIngressRuleTerminator()
                     up_req /= AddPortIngressRule()
 
-                    msg = (
-                        Ether(dst=device.mac_address) /
-                        Dot1Q(vlan=TIBIT_MGMT_VLAN, prio=TIBIT_MGMT_PRIORITY) /
-                        EOAMPayload() / EOAM_VendSpecificMsg(oui=Tibit_OUI) /
-                        EOAM_TibitMsg(dpoe_opcode = Dpoe_Opcodes["Set Request"], body=up_req)/
-                        EndOfPDU()
-                    )
-
-                    # Send OAM Request
-                    action = "Set US Rule"
-                    log.info('OLT-send to {} for OLT: {}'.format(action, olt_mac))
-                    self.io_port.send(str(msg))
-
                     # Get and process the Set Response
+                    action = "Set US Rule"
                     rc = []
-                    yield self._handle_set_resp(olt_mac, action, rc)
+                    yield self._set_req_rsp(device, action, up_req, rc)
 
                 else:
                     raise Exception('Port should be 1 or 2 by our convention')
@@ -1246,7 +1053,7 @@
             frame = Ether(dst=device.mac_address) / \
               Dot1Q(vlan=TIBIT_MGMT_VLAN, prio=TIBIT_MGMT_PRIORITY) / \
               Dot1Q(vlan=proxy_address.channel_id, prio=TIBIT_MGMT_PRIORITY) / \
-              EOAMPayload() / EOAM_VendSpecificMsg(oui=IEEE_OUI) / \
+              EOAMPayload() / EOAM_VendSpecificMsg(oui=ITU_OUI) / \
               encapsulated_omci /\
               EndOfPDU()
 
@@ -1273,7 +1080,7 @@
         self.io_port.send(str(frame))
 
     def receive_inter_adapter_message(self, msg):
-        raise NotImplementedError()    
+        raise NotImplementedError()
 
     def suppress_alarm(self, filter):
         raise NotImplementedError()
@@ -1295,16 +1102,28 @@
             nni_metrics = []
 
             branch_leaf_pairs = [
-                            #[0xD7, 0x0201,], [0xD7, 0x0202], 
-                            [0xD7, 0x0204, "rx_64"], [0xD7, 0x0205, "rx_65_127"], 
-                            [0xD7, 0x0206, "rx_128_255"], [0xD7, 0x0207, "rx_256_511"],
-                            [0xD7, 0x0208, "rx_512_1023"], [0xD7, 0x0209, "rx_1024_1518"],
-                            [0xD7, 0x020A, "rx_1519_9k"], [0xD7, 0x020B, "tx_64"],
-                            [0xD7, 0x020C, "tx_65_127"], [0xD7, 0x020D, "tx_128_255"],
-                            [0xD7, 0x020E, "tx_256_511"], [0xD7, 0x020F, "tx_512_1023"],
-                            [0xD7, 0x0210, "tx_1024_1518"], [0xD7, 0x0211, "tx_1519_9k"]]
+                            [RxFrame_64().branch,        RxFrame_64().leaf,        "rx_64"],
+                            [RxFrame_65_127().branch,    RxFrame_65_127().leaf,    "rx_65_127"],
+                            [RxFrame_128_255().branch,   RxFrame_128_255().leaf,   "rx_128_255"],
+                            [RxFrame_256_511().branch,   RxFrame_256_511().leaf,   "rx_256_511"],
+                            [RxFrame_512_1023().branch,  RxFrame_512_1023().leaf,  "rx_512_1023"],
+                            [RxFrame_1024_1518().branch, RxFrame_1024_1518().leaf, "rx_1024_1518"],
+                            [RxFrame_1519Plus().branch,  RxFrame_1519Plus().leaf,  "rx_1519_9k"],
 
-            olt_mac = next((mac for mac, device in self.device_ids.iteritems() if device == device_id), None)
+                            [TxFrame_64().branch,        TxFrame_64().leaf,        "tx_64"],
+                            [TxFrame_65_127().branch,    TxFrame_65_127().leaf,    "tx_65_127"],
+                            [TxFrame_128_255().branch,   TxFrame_128_255().leaf,   "tx_128_255"],
+                            [TxFrame_256_511().branch,   TxFrame_256_511().leaf,   "tx_256_511"],
+                            [TxFrame_512_1023().branch,  TxFrame_512_1023().leaf,  "tx_512_1023"],
+                            [TxFrame_1024_1518().branch, TxFrame_1024_1518().leaf, "tx_1024_1518"],
+                            [TxFrame_1519Plus().branch,  TxFrame_1519Plus().leaf,  "tx_1519_9k"]
+                            ]
+
+            stats_tlvs =  RxFrame_64()/RxFrame_65_127()/RxFrame_128_255()/RxFrame_256_511()/RxFrame_512_1023()/RxFrame_1024_1518()/RxFrame_1519Plus()
+            stats_tlvs /= TxFrame_64()/TxFrame_65_127()/TxFrame_128_255()/TxFrame_256_511()/TxFrame_512_1023()/TxFrame_1024_1518()/TxFrame_1519Plus()
+
+            # Get the latest device reference
+            device = self.adapter_agent.get_device(device_id)
 
             try:
                 # Step 1: gather metrics from device
@@ -1315,30 +1134,17 @@
                     log.info('link stats frame', links=self.vlan_to_device_ids[vlan_id])
 
                     # send out link_stats_frame
-                    mac_address = self.vlan_to_device_ids[vlan_id][2].upper()
+                    onu_mac_address = self.vlan_to_device_ids[vlan_id][2].upper()
 
-                    link_stats_frame = self._make_link_stats_frame(olt_mac_address=olt_mac, onu_mac_address=mac_address)
-        
-                    self.io_port.send(link_stats_frame)
+                    logical_link = get_unicast_logical_link(onu_mac_address, self.mode)
 
-                    # Loop until we have a Get Response or timeout
-                    ack = False
-                    start_time = time.time()
-                    while not ack:
-                        frame = yield self.incoming_queues[olt_mac].get()
-                        #TODO - Need to add proper timeout functionality
-                        #if (time.time() - start_time) > TIBIT_MSG_WAIT_TIME or (frame is None):
-                        #    break  # don't wait forever
+                    resp = []
+                    action = "Get Link Stats"
+                    tlvs = eval(logical_link)/stats_tlvs
+                    yield self._get_req_rsp(device, action, tlvs, resp)
+                    if resp is not []: frame = resp[0]
 
-                        respType = get_oam_msg_type(log, frame)
-                 
-                        if (respType == RxedOamMsgTypeEnum["DPoE Get Response"]):
-                            ack = True
-                        else:
-                            # Handle unexpected events/OMCI messages
-                            check_resp(log, frame)
-
-                    if ack:
+                    if frame:
                         # Process the Get Request message
                         log.info('Received Link Stats Get Response Frame')
 
@@ -1357,30 +1163,16 @@
 
                 log.info('nni stats frame')
 
-                link_stats_frame = self._make_nni_stats_frame(mac_address=olt_mac)
-                self.io_port.send(link_stats_frame)
+                resp = []
+                action = "Get NNI Stats"
+                tlvs=NetworkToNetworkPortObject()/stats_tlvs
+                yield self._get_req_rsp(device, action, tlvs, resp)
+                if resp is not []: frame = resp[0]
 
-                # Loop until we have a Get Response or timeout
-                ack = False
-                start_time = time.time()
-                while not ack:
-                    frame = yield self.incoming_queues[olt_mac].get()
-                    #TODO - Need to add proper timeout functionality
-                    #if (time.time() - start_time) > TIBIT_MSG_WAIT_TIME or (frame is None):
-                    #    break  # don't wait forever
-
-                    respType = get_oam_msg_type(log, frame)
-             
-                    if (respType == RxedOamMsgTypeEnum["DPoE Get Response"]):
-                        ack = True
-                    else:
-                        # Handle unexpected events/OMCI messages
-                        check_resp(log, frame)
-
-                if ack:
+                if frame:
                     # Process the Get Response message
                     log.info('Recieved NNI Stats Get Response Frame')
-                                
+
                     for pair in branch_leaf_pairs:
                         (rc, value) = (get_value_from_msg(log, frame, pair[0], pair[1]))
                         if rc:
@@ -1426,26 +1218,79 @@
         lc.start(interval=15)  # TODO make this configurable
 
 
-    # Methods for Get / Set  Response Processing from eoam_messages
+    @inlineCallbacks
+    def change_device_state(self, device, state=0):
+        if state is 0:
+            stateStr = "disabled"
+        else:
+            stateStr = "enabled"
+        action = "Set PON Admin State to " + stateStr
+
+        # Get and process the Set Response
+        rc = []
+        tlvs = PonPortObject()/OltPonAdminStateSet(value=state)
+        yield self._set_req_rsp(device, action, tlvs, rc)
+
+
+    # Generic Request handlers
+
+    def _build_tibit_oam_msg(self, mac_addr, opcode, body):
+        msg = (
+            Ether(dst=mac_addr) /
+            Dot1Q(vlan=TIBIT_MGMT_VLAN, prio=TIBIT_MGMT_PRIORITY) /
+            EOAMPayload() / EOAM_VendSpecificMsg(oui=TIBIT_OUI) /
+            EOAM_TibitMsg(dpoe_opcode = opcode, body=body)/
+            EndOfPDU()
+            )
+        return msg
+
 
     @inlineCallbacks
-    def _handle_set_resp(self, olt_mac, action, retcode):
-        # Get and process the Set Response
+    def _get_req_rsp(self, device, action, body, resp):
+        msg = self._build_tibit_oam_msg(device.mac_address, DPoEOpcodes["Get Request"], body)
+        log.info('Send to {} for {}: {}'.format(action, device.model, device.mac_address))
+
+        self.io_port.send(str(msg))
+
+        # Loop until we have a Get Response or timeout
         ack = False
-
-        # Loop until we have a set response
+        start_time = time.time()
         while not ack:
-            frame = yield self.incoming_queues[olt_mac].get()
-
+            frame = yield self.incoming_queues[device.mac_address].get()
             #TODO - Need to add proper timeout functionality
+            #if (time.time() - start_time) > TIBIT_MSG_WAIT_TIME or (frame is None):
+            #    break  # don't wait forever
 
             respType = get_oam_msg_type(log, frame)
-            log.info('Received OAM Message 0x %s' % str(respType))
+
+            if (respType == RxedOamMsgTypeEnum["DPoE Get Response"]):
+                ack = True
+                resp.append(frame)
+            else:
+                # Handle unexpected events/OMCI messages
+                check_resp(log, frame)
+
+
+    @inlineCallbacks
+    def _handle_set_resp(self, device, action, retcode):
+        # Get and process the Set Response
+        ack = False
+        #start_time = time.time()
+
+        # Loop until we have a set response or timeout
+        while not ack:
+            frame = yield self.incoming_queues[device.mac_address].get()
+            #TODO - Need to add proper timeout functionality
+            #if (time.time() - start_time) > TIBIT_MSG_WAIT_TIME or (frame is None):
+            #    break  # don't wait forever
+
+            respType = get_oam_msg_type(log, frame)
 
             #Check that the message received is a Set Response
             if (respType == RxedOamMsgTypeEnum["DPoE Set Response"]):
                 ack = True
             else:
+                log.info('Received Unexpected OAM Message 0x{:X} while waiting for Set Resp for {}'.format(respType,action))
                 # Handle unexpected events/OMCI messages
                 check_resp(log, frame)
 
@@ -1454,38 +1299,23 @@
         if ack:
             (rc,branch,leaf,status) = check_set_resp(log, frame)
             if (rc is False):
-                log.info('Set Response had errors - Branch 0x{:X} Leaf 0x{:0>4X} {}'.format(branch, leaf, DPoEVariableResponseCodes[status]))
-        
-        if (rc is True):
-            log.info('OLT-response received for {} for OLT: {}'.format(action, olt_mac))
+                log.info('Set Response for {} for {}: {} had errors - Branch 0x{:X} Leaf 0x{:0>4X} {}'.format(action, device.model, device.mac_address,branch, leaf, DPoEVariableResponseEnum[status]))
+            else:
+                log.info('Set Response received for {} for {}: {} had no errors'.format(action, device.model, device.mac_address))
         else:
-            log.info('BAD OLT-response received for {} for OLT: {}'.format(action, olt_mac))
+            log.info('No Set Response received for {} for {}: {}'.format(action, device.model, device.mac_address))
 
         retcode.append(rc)
 
+
     @inlineCallbacks
-    def change_device_state(self, device, state=0):
-        # construct PON Admin State attribute
-        msg = (
-            Ether(dst=device.mac_address) /
-            Dot1Q(vlan=TIBIT_MGMT_VLAN, prio=TIBIT_MGMT_PRIORITY) /
-            EOAMPayload() / EOAM_VendSpecificMsg(oui=Tibit_OUI) /
-            EOAM_TibitMsg(dpoe_opcode = Dpoe_Opcodes["Set Request"], 
-                          body=PonPortObject()/OltPonAdminStateSet(value=state))/
-            EndOfPDU()
-            )
-        olt_mac = device.mac_address
-        if state is 0:
-            stateStr = "disabled"
-        else:
-            stateStr = "enabled"
-        action = "Set PON Admin State to " + stateStr
-        log.info('OLT-send to {} for OLT: {}'.format(action, olt_mac))
+    def _set_req_rsp(self, device, action, body, rc):
+        msg = self._build_tibit_oam_msg(device.mac_address, DPoEOpcodes["Set Request"], body)
+        log.info('Send to {} for {}: {}'.format(action, device.model, device.mac_address))
         self.io_port.send(str(msg))
 
         # Get and process the Set Response
-        rc = []
-        yield self._handle_set_resp(olt_mac, action, rc)
+        yield self._handle_set_resp(device, action, rc)
 
     def create_interface(self, device, data):
         raise NotImplementedError()
diff --git a/voltha/adapters/tibit_onu/tibit_onu.py b/voltha/adapters/tibit_onu/tibit_onu.py
index 5c52f18..e3706af 100644
--- a/voltha/adapters/tibit_onu/tibit_onu.py
+++ b/voltha/adapters/tibit_onu/tibit_onu.py
@@ -18,7 +18,6 @@
 Tibit ONU device adapter
 """
 
-import json
 import time
 import struct
 import re
@@ -62,9 +61,9 @@
 from voltha.extensions.eoam.EOAM_TLV import AddStaticMacAddress, DeleteStaticMacAddress
 from voltha.extensions.eoam.EOAM_TLV import ClearStaticMacTable
 from voltha.extensions.eoam.EOAM_TLV import DeviceId
-from voltha.extensions.eoam.EOAM_TLV import ClauseSubtypeEnum
-from voltha.extensions.eoam.EOAM_TLV import RuleOperatorEnum
-from voltha.extensions.eoam.EOAM_TLV import DPoEOpcodeEnum, DPoEVariableResponseCodes
+from voltha.extensions.eoam.EOAM_TLV import ClauseSubtypeEnum, RuleClauses
+from voltha.extensions.eoam.EOAM_TLV import RuleOperatorEnum, RuleOperators
+from voltha.extensions.eoam.EOAM_TLV import DPoEOpcodeEnum, DPoEVariableResponseEnum
 from voltha.extensions.eoam.EOAM_TLV import DPoEOpcode_MulticastRegister, MulticastRegisterSet
 from voltha.extensions.eoam.EOAM_TLV import VendorName, OnuMode, HardwareVersion, ManufacturerInfo
 from voltha.extensions.eoam.EOAM_TLV import SlowProtocolsSubtypeEnum, DeviceReset
@@ -75,19 +74,18 @@
      PortIngressRuleResultSet, PortIngressRuleResultInsert, \
      PortIngressRuleResultCopy, PortIngressRuleResultReplace, \
      PortIngressRuleResultDelete, PortIngressRuleResultOLTQueue, \
-     PortIngressRuleTerminator, AddPortIngressRule
+     PortIngressRuleTerminator, AddPortIngressRule, DPoEOpcodes
 from voltha.extensions.eoam.EOAM_TLV import PortIngressRuleHeader
-from voltha.extensions.eoam.EOAM_TLV import ClauseSubtypeEnum
-from voltha.extensions.eoam.EOAM_TLV import RuleOperatorEnum
 from voltha.extensions.eoam.EOAM_TLV import EndOfPDU
 
-from voltha.extensions.eoam.EOAM import EOAMPayload, EOAMEvent, EOAM_VendSpecificMsg
-from voltha.extensions.eoam.EOAM import EOAM_OmciMsg, EOAM_TibitMsg, EOAM_DpoeMsg
-from voltha.extensions.eoam.EOAM import EOAMPayload, CableLabs_OUI, Tibit_OUI
+from voltha.extensions.eoam.EOAM_Layers import EOAMPayload, EOAM_EventMsg, EOAM_VendSpecificMsg
+from voltha.extensions.eoam.EOAM_Layers import EOAM_TibitMsg, EOAM_DpoeMsg
+from voltha.extensions.eoam.EOAM_Layers import OAM_ETHERTYPE
+from voltha.extensions.eoam.EOAM_Layers import CABLELABS_OUI, TIBIT_OUI
+from voltha.extensions.eoam.EOAM_Layers import RxedOamMsgTypeEnum, RxedOamMsgTypes
 from voltha.extensions.eoam.EOAM import DPoEOpcode_GetRequest, DPoEOpcode_SetRequest
-from voltha.extensions.eoam.EOAM import mcastIp2McastMac
-from voltha.extensions.eoam.EOAM import RxedOamMsgTypeEnum, Dpoe_Opcodes, get_oam_msg_type, \
-    handle_get_value, get_value_from_msg, check_set_resp, check_resp
+from voltha.extensions.eoam.EOAM import mcastIp2McastMac, get_oam_msg_type, get_value_from_msg, check_set_resp, check_resp
+
 
 TIBIT_MSG_WAIT_TIME = 3
 
@@ -346,21 +344,11 @@
         device.connect_status = ConnectStatus.UNREACHABLE
         self.adapter_agent.update_device(device)
 
-        msg = (
-            EOAMPayload() / EOAM_VendSpecificMsg(oui=CableLabs_OUI) /
-            EOAM_DpoeMsg(dpoe_opcode = Dpoe_Opcodes["Set Request"],
-                         body=DeviceReset())/
-            EndOfPDU()
-            )
-
-        action = "Device Reset"
-
         # send message
-        log.info('ONU-send-proxied-message to {} for ONU: {}'.format(action, device.mac_address))
-        self.adapter_agent.send_proxied_message(device.proxy_address, msg)
-
+        action = "Device Reset"
         rc = []
-        yield self._handle_set_resp(device, action, rc)
+        tlvs = DeviceReset()
+        yield self._set_req_rsp(device, action, tlvs, rc)
 
         # Change the operational status back to its previous state.
         device.oper_status = previous_oper_status
@@ -422,9 +410,6 @@
             # Re-add the IGMP Multicast Address
             yield self._send_igmp_mcast_addr(device)
 
-        Clause = {v: k for k, v in ClauseSubtypeEnum.iteritems()}
-        Operator = {v: k for k, v in RuleOperatorEnum.iteritems()}
-
         for flow in flows.items:
             in_port = get_in_port(flow)
             assert in_port is not None
@@ -434,7 +419,6 @@
             if in_port == 2:
                 log.info('#### Upstream Rule ####')
 
-
                 up_req = UserPortObject()
                 up_req /= PortIngressRuleHeader(precedence=precedence)
 
@@ -455,8 +439,8 @@
                     elif field.type == VLAN_VID:
                         _vlan_vid = field.vlan_vid & 0xfff
                         log.info('#### field.type == VLAN_VID ####', vlan=_vlan_vid)
-                        up_req /= PortIngressRuleClauseMatchLength02(fieldcode=Clause['C-VLAN Tag'], fieldinstance=0,
-                                                                     operator=Operator['=='], match=_vlan_vid)
+                        up_req /= PortIngressRuleClauseMatchLength02(fieldcode=RuleClauses['C-VLAN Tag'], fieldinstance=0,
+                                                                     operator=RuleOperators['=='], match=_vlan_vid)
 
                     elif field.type == VLAN_PCP:
                         _vlan_pcp = field.vlan_pcp
@@ -483,14 +467,14 @@
 
                     if action.type == OUTPUT:
                         log.info('#### action.type == OUTPUT ####')
-                        up_req /= PortIngressRuleResultInsert(fieldcode=Clause['C-VLAN Tag'])
+                        up_req /= PortIngressRuleResultInsert(fieldcode=RuleClauses['C-VLAN Tag'])
 
                     elif action.type == POP_VLAN:
                         log.info('#### action.type == POP_VLAN ####')
 
                     elif action.type == PUSH_VLAN:
                         log.info('#### action.type == PUSH_VLAN ####')
-                        up_req /= PortIngressRuleResultInsert(fieldcode=Clause['C-VLAN Tag'])
+                        up_req /= PortIngressRuleResultInsert(fieldcode=RuleClauses['C-VLAN Tag'])
 #                        if action.push.ethertype != 0x8100:
 #                            log.error('unhandled-tpid',
 #                                      ethertype=action.push.ethertype)
@@ -502,32 +486,23 @@
                         field = action.set_field.field.ofb_field
                         if field.type == VLAN_VID:
                             log.info("#### action.field.vlan {} ####".format(field.vlan_vid & 0xfff))
+                            # need to convert value in Set to a variable length value
+                            ctagStr = struct.pack('>H', (field.vlan_vid & 0xfff))
+
                             up_req /= PortIngressRuleResultSet(
-                                    fieldcode=Clause['C-VLAN Tag'], value=field.vlan_vid & 0xfff)
+                                    fieldcode=RuleClauses['C-VLAN Tag'], value=ctagStr)
                         else:
-                            log.error('unsupported-action-set-field-type',
-                                      field_type=field.type)
+                            raise NotImplementedError('unsupported-action-set-field-type={}'.format(field.type))
                     else:
-                        log.error('UNSUPPORTED-ACTION-TYPE',
-                                  action_type=action.type)
+                        raise NotImplementedError('unsupported-action-type={}'.format(action.type))
 
                 up_req /= PortIngressRuleTerminator()
                 up_req /= AddPortIngressRule()
 
-                msg = (
-                    EOAMPayload() / EOAM_VendSpecificMsg(oui=CableLabs_OUI) /
-                    EOAM_DpoeMsg(dpoe_opcode = Dpoe_Opcodes["Set Request"], body=up_req)/
-                    EndOfPDU()
-                )
-
                 # send message
                 action = "Set ONU US Rule"
-                log.info('ONU-send-proxied-message to {} for ONU: {}'.format(action, device.mac_address))
-                self.adapter_agent.send_proxied_message(device.proxy_address, msg)
-
-                # Get and process the Set Response
                 rc = []
-                yield self._handle_set_resp(device, action, rc)
+                yield self._set_req_rsp(device, action, up_req, rc)
 
 
             elif in_port == 1:
@@ -558,6 +533,8 @@
                     elif field.type == VLAN_VID:
                         _vlan_vid = field.vlan_vid & 0xfff
                         log.info('#### field.type == VLAN_VID ####')
+                        dn_req /= PortIngressRuleClauseMatchLength02(fieldcode=RuleClauses['C-VLAN Tag'], fieldinstance=0,
+                                                                     operator=RuleOperators['=='], match=_vlan_vid)
 
                     elif field.type == VLAN_PCP:
                         _vlan_pcp = field.vlan_pcp
@@ -588,17 +565,19 @@
 
                     elif action.type == POP_VLAN:
                         log.info('#### action.type == POP_VLAN ####')
-                        dn_req /= PortIngressRuleClauseMatchLength02(fieldcode=Clause['C-VLAN Tag'], fieldinstance=0,
-                                                                     operator=Operator['=='], match=_vlan_vid)
-                        dn_req /= PortIngressRuleResultReplace(fieldcode=Clause['C-VLAN Tag'])
+
+                        # TODO - This is not the correct operation for a POP operation.
+                        #        This should be a Delete result
+                        dn_req /= PortIngressRuleResultReplace(fieldcode=RuleClauses['C-VLAN Tag'])
+                        # need to convert value in Set to a variable length value
+                        ctagStr = struct.pack('>H', (field.vlan_vid & 0xfff))
                         dn_req /= PortIngressRuleResultSet(
-                                fieldcode=Clause['C-VLAN Tag'], value=field.vlan_vid & 0xfff)
+                                fieldcode=RuleClauses['C-VLAN Tag'], value=ctagStr)
 
                     elif action.type == PUSH_VLAN:
                         log.info('#### action.type == PUSH_VLAN ####')
                         if action.push.ethertype != 0x8100:
-                            log.error('unhandled-ether-type',
-                                      ethertype=action.push.ethertype)
+                            raise NotImplementedError('unhandled-ether-type={}'.format(action.push.ethertype))
 
                     elif action.type == SET_FIELD:
                         log.info('#### action.type == SET_FIELD ####')
@@ -606,18 +585,21 @@
                                 ofp.OFPXMC_OPENFLOW_BASIC)
                         field = action.set_field.field.ofb_field
                         if field.type == VLAN_VID:
-                            dn_req /= PortIngressRuleClauseMatchLength02(fieldcode=Clause['C-VLAN Tag'], fieldinstance=0,
-                                                                         operator=Operator['=='], match=_vlan_vid)
-                            dn_req /= PortIngressRuleResultReplace(fieldcode=Clause['C-VLAN Tag'])
-                            dn_req /= PortIngressRuleResultSet(
-                                    fieldcode=Clause['C-VLAN Tag'], value=field.vlan_vid & 0xfff)
-                        else:
-                            log.error('unsupported-action-set-field-type',
-                                      field_type=field.type)
+                            log.info("#### action.field.vlan {} ####".format(field.vlan_vid & 0xfff))
 
+                            # TODO - Currently only support setting the VID in the DS to zero (clearing the VID)
+                            if ((field.vlan_vid & 0xfff) == 0):
+                                dn_req /= PortIngressRuleResultReplace(fieldcode=RuleClauses['C-VLAN Tag'])
+                                # need to convert value in Set to a variable length value
+                                ctagStr = struct.pack('>H', (field.vlan_vid & 0xfff))
+                                dn_req /= PortIngressRuleResultSet(
+                                        fieldcode=RuleClauses['C-VLAN Tag'], value=ctagStr)
+                            else:
+                                raise NotImplementedError('unsupported-set-vlan-id={}'.format(field.vlan_vid & 0xfff))
+                        else:
+                            raise NotImplementedError('unsupported-action-set-field-type={}'.format(field.type))
                     else:
-                        log.error('UNSUPPORTED-ACTION-TYPE',
-                                  action_type=action.type)
+                        raise NotImplementedError('unsupported-action-type={}'.format(action.type))
 
                 if Is_MCast is True:
                     action = "Set Static IP MCAST address"
@@ -626,19 +608,9 @@
                     dn_req /= AddPortIngressRule()
                     action = "Set ONU DS Rule"
 
-                msg = (
-                    EOAMPayload() / EOAM_VendSpecificMsg(oui=CableLabs_OUI) /
-                    EOAM_DpoeMsg(dpoe_opcode = Dpoe_Opcodes["Set Request"], body=dn_req)/
-                    EndOfPDU()
-                )
-
                 # send message
-                log.info('ONU-send-proxied-message to {} for ONU: {}'.format(action, device.mac_address))
-                self.adapter_agent.send_proxied_message(device.proxy_address, msg)
-
-                # Get and process the Set Response
                 rc = []
-                yield self._handle_set_resp(device, action, rc)
+                yield self._set_req_rsp(device, action, dn_req, rc)
 
             else:
                 raise Exception('Port should be 1 or 2 by our convention')
@@ -716,37 +688,14 @@
         while self.incoming_messages.pending:
             _ = yield self.incoming_messages.get()
 
-        # send out ping frame to ONU device get device information
-        ping_frame = (
-            EOAMPayload() / EOAM_VendSpecificMsg(oui=CableLabs_OUI) /
-            EOAM_DpoeMsg(dpoe_opcode=Dpoe_Opcodes["Get Request"],
-                         body=VendorName() /
-                              OnuMode() /
-                              HardwareVersion() /
-                              ManufacturerInfo()
-                              ) /
-            EndOfPDU()
-            )
+        resp = []
+        action = "Get Device Info"
+        body = VendorName()/OnuMode()/HardwareVersion()/ManufacturerInfo()
+        yield self._get_req_rsp(device, action, body, resp)
+        if resp is not []: frame = resp[0]
 
-        log.info('ONU-send-proxied-message to Get Version Info for ONU: {}'.format(device.mac_address))
-        self.adapter_agent.send_proxied_message(device.proxy_address, ping_frame)
-
-        # Loop until we have a Get Response
-        ack = False
-        while not ack:
-            frame = yield self.incoming_messages.get()
-
-            respType = get_oam_msg_type(log, frame)
-
-            if (respType == RxedOamMsgTypeEnum["DPoE Get Response"]):
-                ack = True
-            else:
-                # Handle unexpected events/OMCI messages
-                check_resp(log, frame)
-
-        if ack:
+        if frame:
             log.info('ONU-response received for Get Version Info for ONU: {}'.format(device.mac_address))
-
             self._process_ping_frame_response(device, frame)
 
 
@@ -763,12 +712,8 @@
 
             log.info("Using Multicast LIDX {:04X}".format(mcastLidx))
 
-            # construct multicast LLID set
-            msg = (
-                EOAMPayload() / EOAM_VendSpecificMsg(oui=CableLabs_OUI) /
-                EOAM_DpoeMsg(dpoe_opcode=Dpoe_Opcodes["Multicast Register"],body=MulticastRegisterSet(MulticastLink=mcastLidx, UnicastLink=0)
-                ))
-
+            tlvs = MulticastRegisterSet(MulticastLink=mcastLidx, UnicastLink=0)
+            msg = self._build_dpoe_oam_msg(DPoEOpcodes["Multicast Register"], tlvs)
             # send message
             log.info('ONU-send-proxied-message to Multicast Register Set for ONU: {}'.format(device.mac_address))
             self.adapter_agent.send_proxied_message(device.proxy_address, msg)
@@ -850,82 +795,26 @@
     @inlineCallbacks
     def _send_igmp_mcast_addr(self, device):
         # construct install of igmp query address
-        msg = (
-            EOAMPayload() / EOAM_VendSpecificMsg(oui=CableLabs_OUI) /
-            EOAM_DpoeMsg(dpoe_opcode=Dpoe_Opcodes["Set Request"],body=AddStaticMacAddress(mac='01:00:5e:00:00:01')
-            ))
-
         action = "Set Static IGMP MAC address"
-
-        # send message
-        log.info('ONU-send-proxied-message to {} for ONU: {}'.format(action, device.mac_address))
-        self.adapter_agent.send_proxied_message(device.proxy_address, msg)
-
         rc = []
-        yield self._handle_set_resp(device, action, rc)
+        tlvs = AddStaticMacAddress(mac='01:00:5e:00:00:01')
+        yield self._set_req_rsp(device, action, tlvs, rc)
 
 
     @inlineCallbacks
     def _send_clear_static_mac_table(self, device):
-        # construct install of igmp query address
-        msg = (
-            EOAMPayload() / EOAM_VendSpecificMsg(oui=CableLabs_OUI) /
-            EOAM_DpoeMsg(dpoe_opcode=Dpoe_Opcodes["Set Request"],body=ClearStaticMacTable()
-            ))
-
         action = "Clear Static MAC Table"
-
-        # send message
-        log.info('ONU-send-proxied-message to {} for ONU: {}'.format(action, device.mac_address))
-        self.adapter_agent.send_proxied_message(device.proxy_address, msg)
-
         rc = []
-        yield self._handle_set_resp(device, action, rc)
+        tlvs = ClearStaticMacTable()
+        yield self._set_req_rsp(device, action, tlvs, rc)
 
 
-    @inlineCallbacks
-    def _handle_set_resp(self, device, action, retcode):
-        # Get and process the Set Response
-        ack = False
-        start_time = time.time()
-
-        # Loop until we have a set response or timeout
-        while not ack:
-            frame = yield self.incoming_messages.get()
-            #TODO - Need to add propoer timeout functionality
-            #if (time.time() - start_time) > TIBIT_MSG_WAIT_TIME or (frame is None):
-            #    break  # don't wait forever
-
-            respType = get_oam_msg_type(log, frame)
-
-            #Check that the message received is a Set Response
-            if (respType == RxedOamMsgTypeEnum["DPoE Set Response"]):
-                ack = True
-            else:
-                log.info('Received Unexpected OAM Message 0x{:X} while waiting for Set Resp for {}'.format(respType,action))
-                # Handle unexpected events/OMCI messages
-                check_resp(log, frame)
-
-        # Verify Set Response
-        rc = False
-        if ack:
-            (rc,branch,leaf,status) = check_set_resp(log, frame)
-            if (rc is False):
-                log.info('Set Response had errors - Branch 0x{:X} Leaf 0x{:0>4X} {}'.format(branch, leaf, DPoEVariableResponseCodes[status]))
-
-        if (rc is True):
-            log.info('ONU-response received for {} for ONU: {}'.format(action, device.mac_address))
-        else:
-            log.info('BAD ONU-response received for {} for ONU: {}'.format(action, device.mac_address))
-
-        retcode.append(rc)
-
     def _process_ping_frame_response(self, device, frame):
+        vendor       = [VendorName().branch, VendorName().leaf]
+        ponMode      = [OnuMode().branch, OnuMode().leaf]
+        hw_version   = [HardwareVersion().branch, HardwareVersion().leaf]
+        manufacturer = [ManufacturerInfo().branch, ManufacturerInfo().leaf]
 
-        vendor = [0xD7, 0x0011]
-        ponMode = [0xB7, 0x0105]
-        hw_version = [0xD7, 0x0013]
-        manufacturer =  [0xD7, 0x0006]
         branch_leaf_pairs = [vendor, ponMode, hw_version, manufacturer]
 
         for pair in branch_leaf_pairs:
@@ -993,3 +882,84 @@
             device.serial_number = "UNKNOWN"
 
         device.connect_status = ConnectStatus.REACHABLE
+
+
+    # Generic Request handlers
+
+    def _build_dpoe_oam_msg(self, opcode, body):
+        msg = (
+            EOAMPayload() / EOAM_VendSpecificMsg(oui=CABLELABS_OUI) /
+            EOAM_DpoeMsg(dpoe_opcode = opcode, body=body)/
+            EndOfPDU()
+            )
+        return msg
+
+    @inlineCallbacks
+    def _get_req_rsp(self, device, action, body, resp):
+        msg = self._build_dpoe_oam_msg(DPoEOpcodes["Get Request"], body)
+        log.info('Send to {} for {}: {}'.format(action, device.model, device.mac_address))
+
+        self.adapter_agent.send_proxied_message(device.proxy_address, msg)
+
+        # Loop until we have a Get Response or timeout
+        ack = False
+        start_time = time.time()
+        while not ack:
+            frame = yield self.incoming_messages.get()
+            #TODO - Need to add proper timeout functionality
+            #if (time.time() - start_time) > TIBIT_MSG_WAIT_TIME or (frame is None):
+            #    break  # don't wait forever
+
+            respType = get_oam_msg_type(log, frame)
+
+            if (respType == RxedOamMsgTypeEnum["DPoE Get Response"]):
+                ack = True
+                resp.append(frame)
+            else:
+                # Handle unexpected events/OMCI messages
+                check_resp(log, frame)
+
+    @inlineCallbacks
+    def _handle_set_resp(self, device, action, retcode):
+        # Get and process the Set Response
+        ack = False
+        #start_time = time.time()
+
+        # Loop until we have a set response or timeout
+        while not ack:
+            frame = yield self.incoming_messages.get()
+            #TODO - Need to add proper timeout functionality
+            #if (time.time() - start_time) > TIBIT_MSG_WAIT_TIME or (frame is None):
+            #    break  # don't wait forever
+
+            respType = get_oam_msg_type(log, frame)
+
+            #Check that the message received is a Set Response
+            if (respType == RxedOamMsgTypeEnum["DPoE Set Response"]):
+                ack = True
+            else:
+                log.info('Received Unexpected OAM Message 0x{:X} while waiting for Set Resp for {}'.format(respType,action))
+                # Handle unexpected events/OMCI messages
+                check_resp(log, frame)
+
+        # Verify Set Response
+        rc = False
+        if ack:
+            (rc,branch,leaf,status) = check_set_resp(log, frame)
+            if (rc is False):
+                log.info('Set Response for {} for {}: {} had errors - Branch 0x{:X} Leaf 0x{:0>4X} {}'.format(action, device.model, device.mac_address,branch, leaf, DPoEVariableResponseEnum[status]))
+            else:
+                log.info('Set Response received for {} for {}: {} had no errors'.format(action, device.model, device.mac_address))
+        else:
+            log.info('No Set Response received for {} for {}: {}'.format(action, device.model, device.mac_address))
+
+        retcode.append(rc)
+
+    @inlineCallbacks
+    def _set_req_rsp(self, device, action, body, rc):
+        msg = self._build_dpoe_oam_msg(DPoEOpcodes["Set Request"], body)
+        log.info('Send to {} for {}: {}'.format(action, device.model, device.mac_address))
+        self.adapter_agent.send_proxied_message(device.proxy_address, msg)
+
+        # Get and process the Set Response
+        yield self._handle_set_resp(device, action, rc)
diff --git a/voltha/extensions/eoam/EOAM.py b/voltha/extensions/eoam/EOAM.py
index 6dab1a8..7096ffe 100644
--- a/voltha/extensions/eoam/EOAM.py
+++ b/voltha/extensions/eoam/EOAM.py
@@ -18,6 +18,8 @@
 import logging

 import time

 from hexdump import hexdump

+from datetime import datetime

+

 

 logging.getLogger("scapy.runtime").setLevel(logging.ERROR)

 from scapy.layers.l2 import Ether, Dot1Q

@@ -33,36 +35,16 @@
 

 import fcntl, socket, struct # for get hw address

 

+from EOAM_Layers import EOAM_MULTICAST_ADDRESS, IGMP_MULTICAST_ADDRESS, OAM_ETHERTYPE

+from EOAM_Layers import VENDOR_SPECIFIC_OPCODE, CABLELABS_OUI, TIBIT_OUI

+from EOAM_Layers import RxedOamMsgTypeEnum, RxedOamMsgTypes

+from EOAM_Layers import EOAMPayload, EOAM_EventMsg, EOAM_VendSpecificMsg, EOAM_TibitMsg, EOAM_DpoeMsg, EOAM_OmciMsg

+

 # TODO should remove import *

 from EOAM_TLV import *

 

-OAM_ETHERTYPE = 0xA8C8

-CableLabs_OUI = 0x001000

-Tibit_OUI = 0x2AEA15

-IEEE_OUI = 0x0019A7

-

-EOAM_MULTICAST_ADDRESS = '01:80:c2:00:00:02'

-IGMP_MULTICAST_ADDRESS = '01:00:5e:00:00:01'   # for test

-

-

-

-

-### Received OAM Message Types

-RxedOamMsgTypeEnum = {

-    "Unknown": 0x00,

-    # Info PDU - not currently used

-    "Info": 0x01,

-    # Event Notification - Tibit or DPoE Event

-    "Event Notification": 0x02,

-    "DPoE Get Response": 0x03,

-    "DPoE Set Response": 0x04,

-    # Specifically - a File Transfer ACK

-    "DPoE File Transfer": 0x05,

-    # Contains an embedded OMCI message

-    "OMCI Message": 0x06,

-    }

-

-Dpoe_Opcodes = {v: k for k, v in DPoEOpcodeEnum.iteritems()}

+ADTRAN_SHORTENED_VSSN = u'4144'  # 'AD'

+TIBIT_SHORTENED_VSSN  = u'5442'  # 'TB'

 

 def get_oam_msg_type(log, frame):

 

@@ -70,8 +52,8 @@
     recv_frame = frame

 

     if recv_frame.haslayer(EOAMPayload):

-        if recv_frame.haslayer(EOAMEvent):

-            recv_frame = RxedOamMsgTypeEnum["Event Notification"]

+        if recv_frame.haslayer(EOAM_EventMsg):

+            respType = RxedOamMsgTypeEnum["Event Notification"]

         elif recv_frame.haslayer(EOAM_OmciMsg):

             respType = RxedOamMsgTypeEnum["OMCI Message"]

         else:

@@ -82,25 +64,26 @@
                 dpoeOpcode = recv_frame.getlayer(EOAM_DpoeMsg).dpoe_opcode;

 

             # Get Response

-            if (dpoeOpcode == 0x02):

+            if (dpoeOpcode == DPoEOpcodes["Get Response"]):

                 respType = RxedOamMsgTypeEnum["DPoE Get Response"]

 

             # Set Response

-            elif (dpoeOpcode == 0x04):

+            elif (dpoeOpcode == DPoEOpcodes["Set Response"]):

                 respType = RxedOamMsgTypeEnum["DPoE Set Response"]

 

             # File Transfer ACK

-            elif (dpoeOpcode == 0x09):

+            elif (dpoeOpcode == DPoEOpcodes["File Transfer"]):

                 respType = RxedOamMsgTypeEnum["DPoE File Transfer"]

             else:

-                log.info('Unsupported DPoE Opcode {:0>2X}'.format(dpoeOpcode))

+                log.info("Unsupported DPoE Opcode {:0>2X}".format(dpoeOpcode))

     else:

-        log.info('Invalid OAM Header')

+        log.info("Invalid OAM Header")

 

-    log.info('Received OAM Message 0x %s' % str(respType))

+    log.info('Received OAM Message - %s' % RxedOamMsgTypes[respType])

 

     return respType

 

+

 def handle_get_value(log, loadstr, startOfTlvs, queryBranch, queryLeaf):

     retVal = False;

     value = 0

@@ -127,7 +110,7 @@
                 value = struct.unpack_from(">Q", loadstr, bytesRead)[0]

             else:

                 if (length >= 0x80):

-                    log.info('Branch 0x{:0>2X} Leaf 0x{:0>4X} {}'.format(branch, leaf, DPoEVariableResponseCodes[length]))

+                    log.info('Branch 0x{:0>2X} Leaf 0x{:0>4X} {}'.format(branch, leaf, DPoEVariableResponseEnum[length]))

                     # Set length to zero so bytesRead doesn't get mistakenly incremented below

                     length = 0

                 else:

@@ -140,7 +123,7 @@
             if (length > 0):

                 bytesRead += length

 

-            if (branch != 0xD6):

+            if (branch != OamBranches["DPoE Object"]):

                 if ( ((queryBranch == 0) and (queryLeaf == 0)) or

                      ((queryBranch == branch) and (queryLeaf == leaf)) ):

                     # Prevent zero-lengthed values from returning success

@@ -192,7 +175,7 @@
             bytesRead += 1

 

             if (length >= 0x80):

-                log.info('Branch 0x{:0>2X} Leaf 0x{:0>4X} {}'.format(branch, leaf, DPoEVariableResponseCodes[length]))

+                log.info('Branch 0x{:0>2X} Leaf 0x{:0>4X} {}'.format(branch, leaf, DPoEVariableResponseEnum[length]))

                 if (length > 0x80):

                     retVal = False;

                     break;

@@ -210,6 +193,7 @@
     leaf = 0

     status = 0

     recv_frame = frame

+

     if recv_frame.haslayer(EOAMPayload):

         payload = recv_frame.payload

         if hasattr(payload, 'body'):

@@ -223,18 +207,202 @@
     return rc,branch,leaf,status

 

 

+def handle_get_event_context(log, loadstr, startOfTlvs, queryType):

+    retVal = False;

+    value = 0

+    objType = 0

+    bytesRead = startOfTlvs

+    loadstrlen    = len(loadstr)

+

+    while (bytesRead <= loadstrlen):

+        objType = struct.unpack_from('>H', loadstr, bytesRead)[0]

+#            print "Branch/Leaf        0x{:0>2X}/0x{:0>4X}".format(branch, leaf)

+

+        if (objType != 0):

+            bytesRead += 2

+            length = struct.unpack_from('>B', loadstr, bytesRead)[0]

+#                print "Length:            0x{:0>2X} ({})".format(length,length)

+            bytesRead += 1

+

+            if (length == 1):

+                value = struct.unpack_from(">B", loadstr, bytesRead)[0]

+            elif (length == 2):

+                value = struct.unpack_from(">H", loadstr, bytesRead)[0]

+            elif (length == 4):

+                value = struct.unpack_from(">I", loadstr, bytesRead)[0]

+            elif (length == 8):

+                value = struct.unpack_from(">Q", loadstr, bytesRead)[0]

+            else:

+                valStr = ">{}s".format(length)

+                value = struct.unpack_from(valStr, loadstr, bytesRead)[0]

+

+#                print "Value:             {}".format(value)

+

+            if (length > 0):

+                bytesRead += length

+

+            if ( (queryType == 0) or (queryType == objType) ):

+                # Prevent zero-lengthed values from returning success

+                if (length > 0):

+                    retVal = True;

+                break

+        else:

+            break

+

+    if (retVal == False):

+        value = 0

+

+    return retVal,bytesRead,value,objType

+

+

+def handle_tibit_oam_event(log, loadstr):

+    bytesRead = 0

+    loadstrlen = len(loadstr)

+    if loadstrlen > 0:

+        rc = True

+        num_iters = 0

+        bytesRead = 0

+        link_mac = ""

+        msg = ""

+        # Theare are two contexts in a Tibit-specific event - Source & Reference Contexts

+        while(rc == True and num_iters < 2):

+            objType = 0

+            (rc,bytesRead,value,objType) = handle_get_event_context(log, loadstr, bytesRead, objType)

+            if (rc == True):

+                if objType == 0x0001:

+#                        print "PON Object 0x{:0>4X}  Value = {}".format(objType, value)

+                    pass

+                elif objType == 0x000A:

+                    # This is a Unicast Logical Link context. Determine if this a GPON or EPON link

+                    if value[1:5] == "TBIT":

+                        #

+                        link_mac = ''.join(s.encode('hex') for s in value[1:3])

+                        link_mac += ''.join(s.encode('hex') for s in value[5:9])

+                    else:

+                        link_mac = ''.join(s.encode('hex') for s in value[1:7])

+

+#                        print "Unicast Logical Link Object 0x{:0>4X}  Value = {}".format(objType, link_mac)

+                else:

+                    log.info("Object Type 0x{:0>4X}  value = {}".format(objType, value))

+            elif (branch != 0):

+                log.error("Object Type 0x{:0>4X}  no value".format(objType))

+            num_iters += 1

+

+        # Pull the Event Code and Event Length out of the event

+        (evtCode, evtLen) = struct.unpack_from('>HB', loadstr, bytesRead)

+        bytesRead += 3

+

+#            print "Event Code  : 0x{:0>4X}".format(evtCode)

+#            print "Event Len   : 0x{:0>4X}".format(evtLen)

+

+        # Tibit Registration Event

+        if (evtCode == 0x0001):

+            # Handle Registration Status attribute

+            regStatus = struct.unpack_from('>B', loadstr, bytesRead)[0]

+            if regStatus == 1:

+                msg = "Link {} Registered".format(link_mac)

+            else:

+                msg = "Link {} Deregistered".format(link_mac)

+

+    return objType,evtCode,msg

+

+

+def handle_dpoe_oam_event(log, loadstr):

+    bytesRead = 0

+    loadstrlen = len(loadstr)

+    if loadstrlen > 0:

+

+        (evtCode, raised, objType) = struct.unpack_from('>BBH', loadstr, bytesRead)

+        bytesRead += 4

+

+#            print "Event Code  : 0x{:0>4X}".format(evtCode)

+#            print "Event Len   : 0x{:0>4X}".format(evtLen)

+

+        if ((loadstrlen - bytesRead) == 2):

+            objInst = struct.unpack_from(">H", loadstr, bytesRead)[0]

+        elif ((loadstrlen - bytesRead) == 4):

+            objInst = struct.unpack_from(">I", loadstr, bytesRead)[0]

+

+        objTypeStr = ObjectContextEnum[objType]

+        evtCodeStr = DPoEEventCodeEnum[evtCode]

+

+        raisedStr = "Raised"

+        if (raised):

+            rasiedStr = "Cleared"

+

+        #print "{} : {} - {} {}".format(objTypeStr, objInst, evtCodeStr, raisedStr)

+        return objType,evtCode,objTypeStr+":"+evtCodeStr

+

+

+def handle_oam_event(log, frame):

+    recv_frame = frame

+    if recv_frame.haslayer(EOAM_EventMsg):

+        now = datetime.now().strftime('%Y-%m-%f %H:%M:%S.%f')

+        event = recv_frame.getlayer(EOAM_EventMsg)

+        if hasattr(event, 'body'):

+            loadstr = event.body.load

+

+            if (event.tlv_type != VENDOR_SPECIFIC_OPCODE):

+                log.error("unexpected tlv_type 0x%x (expected 0xFE)" % event.tlv_type)

+            elif (event.oui == CABLELABS_OUI):

+                log.info("DPoE Event")

+                objType,eventCode,msg = handle_dpoe_oam_event(log, loadstr)

+            elif (event.oui == TIBIT_OUI):

+                log.info("Tibit-specific Event")

+                objType,eventCode,msg = handle_tibit_oam_event(log, loadstr)

+

+            log.info("Description:    %s" % msg)

+            log.info("sequence:       0x%04x" % event.sequence)

+            log.info("tlv_type:       0x%x" % event.tlv_type)

+            log.info("length:         0x%x" % event.length)

+            log.info("oui:            0x%06x" % event.oui)

+            log.info("time_stamp:     %s" % now)

+            log.info("obj_type:       "+hex(objType))

+            log.info("event_code:     "+hex(eventCode))

+

+    # TODO - Store the event for future use or generate alarm

+    #event_data = [msg, event.sequence, objType, eventCode, now]

+

+def handle_omci(log, frame):

+    recv_frame = frame

+    if recv_frame.haslayer(EOAM_OmciMsg):

+        omci = recv_frame.getlayer(EOAM_OmciMsg)

+        if hasattr(omci, 'body'):

+            loadstr = omci.body.load

+

+            #log.info("trans_id:  0x%04x" % omci.trans_id)

+            #log.info("msg_type:  0x%x" % omci.msg_type)

+            #log.info("dev_id:    0x%x" % omci.dev_id)

+            #log.info("me_class:  0x%04x" % omci.me_class)

+            #log.info("me_inst:   0x%04x" % omci.me_inst)

+

+            bytesRead = 0

+

+    # TODO - Handle OMCI message

+

+def handle_fx_ack(log, loadstr):

+    response_code = Dpoe_FileAckRspOpcodes["OK"]

+

+    (fx_opcode, acked_block, response_code) = struct.unpack('>BHB', loadstr[0:4])

+

+    if (fx_opcode == Dpoe_FileXferOpcodes["File Transfer Ack"]):

+        pass

+        #log.info("   Acked_block: {} Code: {}".format(acked_block, DPoEFileAckRespCodeEnum[response_code]))

+    else:

+        log.error("Unexpected File Transfer Opcode {} when expecting ACK".format(DPoEFileXferOpcodeEnum[fx_opcode]))

+

+    return response_code,acked_block

+

 

 def check_resp(log, frame):

     respType = RxedOamMsgTypeEnum["Unknown"]

     recv_frame = frame

     if recv_frame.haslayer(EOAMPayload):

 

-        if recv_frame.haslayer(EOAMEvent):

-#            handle_oam_event(recv_frame)

-            pass

+        if recv_frame.haslayer(EOAM_EventMsg):

+            handle_oam_event(log, recv_frame)

         elif recv_frame.haslayer(EOAM_OmciMsg):

-#            handle_omci(recv_frame)

-            pass

+            handle_omci(log, recv_frame)

         else:

             dpoeOpcode = 0x00

             if recv_frame.haslayer(EOAM_TibitMsg):

@@ -247,7 +415,7 @@
                 loadstr = payload.body.load

 

             # Get Response

-            if (dpoeOpcode == 0x02):

+            if (dpoeOpcode == DPoEOpcodes["Get Response"]):

                 bytesRead = 0

                 rc = True

                 while(rc == True):

@@ -260,547 +428,67 @@
                         log.info('Branch 0x{:0>2X} Leaf 0x{:0>4X}  no value'.format(branch, leaf))

 

             # Set Response

-            elif (dpoeOpcode == 0x04):

+            elif (dpoeOpcode == DPoEOpcodes["Set Response"]):

                 (rc,branch,leaf,status) = check_set_resp_attrs(loadstr, 0)

                 if (rc == True):

                     log.info('Set Response had no errors')

                 else:

-                    log.info('Branch 0x{:X} Leaf 0x{:0>4X} {}'.format(branch, leaf, DPoEVariableResponseCodes[status]))

+                    log.info('Branch 0x{:X} Leaf 0x{:0>4X} {}'.format(branch, leaf, DPoEVariableResponseEnum[status]))

 

             # File Transfer ACK

-            elif (dpoeOpcode == 0x09):

-                rc = handle_fx_ack(log, loadstr, bytesRead, block_number)

+            elif (dpoeOpcode == DPoEOpcodes["File Transfer"]):

+                (rc,block) = handle_fx_ack(log, loadstr)

             else:

                 log.info('Unsupported DPoE Opcode {:0>2X}'.format(dpoeOpcode))

     else:

         log.info('Invalid OAM Header')

 

-    return respType    

+    return respType

 

 

-    

-def handle_fx_ack(log, loadstr, startOfXfer, block_number):

-    retVal = False

-    (fx_opcode, acked_block, response_code) = struct.unpack_from('>BHB', loadstr, startOfXfer)

-

-    #print "fx_opcode:      0x%x" % fx_opcode

-    #print "acked_block:    0x%x" % acked_block

-    #print "response_code:  0x%x" % response_code

-

-    if (fx_opcode != 0x03):

-        log.info('unexpected fx_opcode 0x%x (expected 0x03)' % fx_opcode)

-    elif (acked_block != block_number):

-        log.info('unexpected acked_block 0x%x (expected 0x%x)' % (acked_block, block_number))

-    elif (response_code != 0):

-        log.info('unexpected response_code 0x%x (expected 0x00)' % response_code)

-    else:

-        retVal = True;

-

-

-

-

-class EOAM():

-    """ EOAM frame layer """

-    def __init__(self, ctag=None, dryrun=False, stag=None,

-                 verbose=False, etype='8809',

-                 dst=EOAM_MULTICAST_ADDRESS,

-                 hexdump=False, interface='eth0',

-                 sleep=2.0):

-        self.verbose = verbose

-        self.dst = dst

-        self.dryrun = dryrun

-        self.hexdump = hexdump

-        self.interface = interface

-        self.etype = int(etype, 16)

-        self.stag = stag

-        self.ctag = ctag

-        self.sleep = sleep

-        if (self.verbose == True):

-            print("=== Settings ================")

-            print("ctag      = %s" % self.ctag)

-            print("stag      = %s" % self.stag)

-            print("dst       = %s" % self.dst)

-            print("dryrun    = %s" % self.dryrun)

-            print("hexdump   = %s" % self.hexdump)

-            print("interface = %s" % self.interface)

-            print("etype     = 0x%04x" % self.etype)

-            print("verbose   = %s" % self.verbose)

-            print("sleep     = %d" % self.sleep)

-            print("=== END Settings ============")

-

-    def send_frame(self, frame_body, slow_protocol=True):

-        PACKET = Ether()

-        PACKET.dst = self.dst

-        PACKET.src = self.getHwAddr(self.interface)

-        if self.stag:

-            # WARNING: September/2016: This should be 0x88a8, but the Intel 10G

-            # hardware I am currently using does not support receiving a TPID of

-            # 0x88a8. So, I send double CTAGs, and I usually set this to 0x8100.

-            # (NOTE: The Intel hardware can send a TPID of 0x88a8)

-            PACKET.type = 0x8100

-            if self.ctag:

-                PACKET/=Dot1Q(type=0x8100,vlan=int(self.stag))

-                PACKET/=Dot1Q(type=self.etype,vlan=int(self.ctag))

-            else:

-                PACKET/=Dot1Q(prio=7,type=self.etype,vlan=int(self.stag))

-        else:

-            if self.ctag:

-                PACKET.type = 0x8100

-                PACKET/=Dot1Q(type=self.etype,vlan=int(self.ctag))

-            else:

-                PACKET.type = self.etype

-#            PACKET/=Dot1Q(type=self.etype, vlan=int(self.ctag))

-        if slow_protocol:

-            PACKET /= SlowProtocolsSubtype()/FlagsBytes()/OAMPDU()

-            PACKET /= frame_body

-            PACKET /= EndOfPDU()

-        else:

-            PACKET.lastlayer().type = 0xA8C8

-            PACKET /= frame_body

-

-        if (self.verbose == True):

-            PACKET.show()

-            print '###[ Frame Length %d (before padding) ]###' % len(PACKET)

-        if (self.hexdump == True):

-            print hexdump(str(PACKET))

-        if (self.dryrun != True):

-            sendp(PACKET, iface=self.interface)

-            time.sleep(self.sleep)

-        return PACKET

-

-    def get_request(self, TLV):

-        return self.send_frame(CablelabsOUI()/DPoEOpcode_GetRequest()/TLV)

-

-    def set_request(self, TLV):

-        return self.send_frame(CablelabsOUI()/DPoEOpcode_SetRequest()/TLV)

-

-    def send_multicast_register(self, TLV):

-        '''

-        Note, for mulicast, the standard specifies a register message

-        with ActionFlags of either Register or Deregister

-        '''

-        return self.send_frame(CablelabsOUI()/DPoEOpcode_MulticastRegister()/TLV)

-

-    def set_request_broadcom(self, TLV):

-        return self.send_frame(BroadcomOUI()/DPoEOpcode_SetRequest()/TLV)

-

-    def getHwAddr(self, ifname):

-        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

-        info = fcntl.ioctl(s.fileno(), 0x8927,  struct.pack('256s', ifname[:15]))

-        return ':'.join(['%02x' % ord(char) for char in info[18:24]])

-

-

-#TODO - This is duplicated from eoam_messages.py and renamed to EOAMRespPayload

-class EOAMPayload(Packet):

-    name = 'EOAM Payload'

-    fields_desc = [

-        ByteEnumField("subtype", 0x03, SlowProtocolsSubtypeEnum),

-        XShortField("flags", 0x0050),

-        XByteField("opcode", 0xfe),

-#        PacketField("body", None, Packet),

-    ]

-

-bind_layers(Ether, EOAMPayload, type=OAM_ETHERTYPE)

-

-

-#TODO - This is duplicated from eoam_messages.py

-class EOAMEvent(Packet):

-    name = 'EOAM Event'

-    fields_desc = [

-        XShortField("sequence", 0x0001),

-        XByteField("tlv_type", 0xfe),

-        XByteField("length", 0x01),

-        X3BytesField("oui", 0x001000),

-        PacketField("body", None, Packet),

-    ]

-

-bind_layers(EOAMPayload, EOAMEvent, opcode=0x01)

-

-#TODO - This is duplicated from eoam_messages.py

-class EOAM_VendSpecificMsg(Packet):

-    name = "Vendor-Specific OAM"

-    fields_desc  = [

-        X3BytesField("oui", 0x001000),

-    ]

-

-bind_layers(EOAMPayload, EOAM_VendSpecificMsg, opcode=0xFE)

-

-#TODO - This is duplicated from eoam_messages.py

-class EOAM_OmciMsg(Packet):

-    name = "OAM-encapsulated OMCI Message"

-    fields_desc  = [

-        PacketField("body", None, Packet),

-    ]

-

-bind_layers(EOAM_VendSpecificMsg, EOAM_OmciMsg, oui=0x0019A7)

-

-#TODO - This is duplicated from eoam_messages.py

-class EOAM_TibitMsg(Packet):

-    name = "Tibit OAM Message"

-    fields_desc  = [

-        ByteEnumField("dpoe_opcode", 0x01, DPoEOpcodeEnum),

-        PacketField("body", None, Packet),

-    ]

-

-bind_layers(EOAM_VendSpecificMsg, EOAM_TibitMsg, oui=0x2AEA15)

-

-#TODO - This is duplicated from eoam_messages.py

-class EOAM_DpoeMsg(Packet):

-    name = "DPoE OAM Message"

-    fields_desc  = [

-        ByteEnumField("dpoe_opcode", 0x01, DPoEOpcodeEnum),

-        PacketField("body", None, Packet),

-    ]

-

-bind_layers(EOAM_VendSpecificMsg, EOAM_DpoeMsg, oui=0x001000)

-

 def mcastIp2McastMac(ip):

     """ Convert a dot-notated IPv4 multicast address string into an multicast MAC address"""

     digits = [int(d) for d in ip.split('.')]

     return '01:00:5e:%02x:%02x:%02x' % (digits[1] & 0x7f, digits[2] & 0xff, digits[3] & 0xff)

 

+def get_olt_queue(mac, mode = None):

+    resultOltQueue = ""

+    if mode:

+        # If the MAC is the Multicast LLID, then use EPON encoding regardless of the actual

+        # mode we are in.

+        if (mac == "FFFFFFFFFFFF"):

+            mode = "EPON"

+

+        if mode.upper()[0] == "G":  #GPON

+            if mac[:4].upper() == ADTRAN_SHORTENED_VSSN:

+                vssn = "ADTN"

+            else:

+                vssn = "TBIT"

+            link = int(mac[4:12], 16)

+            resultOltQueue = "PortIngressRuleResultOLTQueue(unicastvssn=\"" + vssn + "\", unicastlink=" + str(link) + ")"

+        else:                       #EPON

+            vssn = int(mac[0:8].rjust(8,"0"), 16)

+            link = int((mac[8:12]).ljust(8,"0"), 16)

+            resultOltQueue = "PortIngressRuleResultOLTEPONQueue(unicastvssn=" + str(vssn) + ", unicastlink=" + str(link) + ")"

+    return resultOltQueue

+

+

+def get_unicast_logical_link(mac, mode = None):

+    unicastLogicalLink = ""

+    if mode:

+        if mode.upper()[0] == "G":  #GPON

+            if mac[:4].upper() == ADTRAN_SHORTENED_VSSN:

+                vssn = "ADTN"

+            else:

+                vssn = "TBIT"

+            link = int(mac[4:12], 16)

+            unicastLogicalLink = "OLTUnicastLogicalLink(unicastvssn=\"" + vssn + "\", unicastlink=" + str(link) + ")"

+        else:                       #EPON

+            vssn = int(mac[0:8].rjust(8,"0"), 16)

+            link = int((mac[8:12]).ljust(8,"0"), 16)

+            unicastLogicalLink = "OLTEPONUnicastLogicalLink(unicastvssn=" + str(vssn) + ", unicastlink=" + str(link) +")"

+    return unicastLogicalLink

+

 

 if __name__ == "__main__":

-    parser = argparse.ArgumentParser()

-    parser.add_argument('-d', '--dst', dest='dst', action='store', default=EOAM_MULTICAST_ADDRESS,

-                        help='MAC destination (default: %s)' % EOAM_MULTICAST_ADDRESS)

-    parser.add_argument('-e', '--etype', dest='etype', action='store', default='8809',

-                        help='EtherType value (default: 0x8809)')

-    parser.add_argument('-i', '--interface', dest='interface', action='store', default='eth0',

-                        help='ETH interface to send (default: eth0)')

-    parser.add_argument('-s', '--stag', dest='stag', action='store', default=None,

-                        help='STAG value (default: None)')

-    parser.add_argument('-c', '--ctag', dest='ctag', action='store', default=None,

-                        help='CTAG value (default: None)')

-    parser.add_argument('-p', '--sleep', dest='sleep', action='store', default='1.0', type=float,

-                        help='SLEEP time after frame (default: 1.0 secs)')

-    parser.add_argument('-v', '--verbose', dest='verbose', action='store_true', default=False,

-                        help='verbose frame print out')

-    parser.add_argument('-x', '--hexdump', dest='hexdump', action='store_true', default=False,

-                        help='Hexdump the frame')

-    parser.add_argument('-y', '--dryrun', dest='dryrun', action='store_true', default=False,

-                        help='Dry run test, dont send - just print')

-

-    parser.add_argument('-t', '--test', dest='test', action='store_true', default=False,

-                        help='Run commands under test')

-    parser.add_argument('-r', '--critical', dest='critical', action='store_true', default=False,

-                        help='Send the critical OAM set of set_request()')

-    parser.add_argument('-ta', '--test_add', dest='test_add', action='store_true', default=False,

-                        help='Run commands under test')

-    parser.add_argument('-tc', '--test_clr', dest='test_clr', action='store_true', default=False,

-                        help='Run commands under test')

-    parser.add_argument('-te', '--test_eapol', dest='test_eapol', action='store_true', default=False,

-                        help='Run commands under test')

-    parser.add_argument('-ti', '--test_igmp', dest='test_igmp', action='store_true', default=False,

-                        help='Run commands under test')

-    parser.add_argument('-th', '--test_dhcp', dest='test_dhcp', action='store_true', default=False,

-                        help='Run commands under test')

-    parser.add_argument('-tu', '--test_upstream', dest='test_upstream', action='store_true', default=False,

-                        help='Run commands under test')

-    parser.add_argument('-td', '--test_downstream', dest='test_downstream', action='store_true', default=False,

-                        help='Run commands under test')

-    parser.add_argument('-tm', '--test_multicast', dest='test_multicast', action='store_true', default=False,

-                        help='Run commands under test')

-    parser.add_argument('-tp', '--test_ping', dest='test_ping', action='store_true', default=False,

-                        help='Issue a test ping to get JSON data on device version')

-

-    args = parser.parse_args()

-

-    if (args.dryrun == True):

-        args.sleep = 0.0

-

-    eoam = EOAM(

-        dryrun=args.dryrun,

-        dst=args.dst,

-        etype=args.etype,

-        hexdump=args.hexdump,

-        interface=args.interface,

-        stag=args.stag,

-        ctag=args.ctag,

-        verbose=args.verbose,

-        sleep=args.sleep

-        )

-

-    if (not args.critical

-        and not args.test

-        and not args.test_add

-        and not args.test_clr

-        and not args.test_eapol

-        and not args.test_igmp

-        and not args.test_dhcp

-        and not args.test_upstream

-        and not args.test_downstream

-        and not args.test_multicast

-        and not args.test_ping):

-        print 'WARNING: *** No frames sent, please specify \'test\' or \'critical\', etc.  See --help'

-

-

-    if (args.test == True):

-        print 'SET - Multicast Register Message 01'

-        eoam.send_multicast_register(MulticastRegisterSet(MulticastLink=0x3fe0, UnicastLink=0x1008))

-

-        print 'SET - Multicast Deregister Message 02'

-        eoam.send_multicast_register(MulticastRegisterSet(ActionFlags="Deregister",MulticastLink=0x3fe0, UnicastLink=0x1008))

-

-    if (args.test_clr == True):

-        print 'Set - Clear Static MAC Table -- User Port Object'

-        eoam.set_request(ClearStaticMacTable())

-

-    if (args.test_add == True):

-        print 'SET Add Static MAC Address -- User Port Object'

-        eoam.set_request(AddStaticMacAddress(mac=mcastIp2McastMac('230.10.10.10')))

-        time.sleep(1)

-        eoam.set_request(AddStaticMacAddress(mac=mcastIp2McastMac('231.11.11.11')))

-

-#        print 'SET Delete Static MAC Address -- User Port Object'

-#        eoam.set_request(DeleteStaticMacAddress(mac=IGMP_MULTICAST_ADDRESS))

-

-    if (args.test_eapol == True):

-        #################################################################################

-        ## EAPOL

-        #################################################################################

-        Clause = {v: k for k, v in ClauseSubtypeEnum.iteritems()}

-        Operator = {v: k for k, v in RuleOperatorEnum.iteritems()}

-

-        print 'SET - Port Ingress Rule -- PON Port Object -- EAPOL'

-        eoam.set_request(PonPortObject()/

-                         PortIngressRuleHeader(precedence=32)/

-                         PortIngressRuleClauseMatchLength02(fieldcode=Clause['L2 Type/Len'],

-                                                            operator=Operator['=='], match=0x888e)/

-                         PortIngressRuleResultForward()/

-                         PortIngressRuleResultSet(fieldcode=Clause['C-VLAN Tag'], value=4090)/

-                         PortIngressRuleResultInsert(fieldcode=Clause['C-VLAN Tag'])/

-                         PortIngressRuleTerminator()/

-                         AddPortIngressRule())

-

-        time.sleep(3)

-

-        print 'Delete - Port Ingress Rule -- PON Port Object -- EAPOL'

-        eoam.set_request(PonPortObject()/

-                         PortIngressRuleHeader(precedence=32)/

-                         PortIngressRuleClauseMatchLength02(fieldcode=Clause['L2 Type/Len'],

-                                                            operator=Operator['=='], match=0x888e)/

-                         PortIngressRuleResultForward()/

-                         PortIngressRuleResultSet(fieldcode=Clause['C-VLAN Tag'], value=4090)/

-                         PortIngressRuleResultInsert(fieldcode=Clause['C-VLAN Tag'])/

-                         PortIngressRuleTerminator()/

-                         DeletePortIngressRule())

-

-    if (args.test_igmp == True):

-        #################################################################################

-        ## IGMP

-        #################################################################################

-        Clause = {v: k for k, v in ClauseSubtypeEnum.iteritems()}

-        Operator = {v: k for k, v in RuleOperatorEnum.iteritems()}

-

-        print 'SET - Port Ingress Rule -- PON Port Object -- IGMP'

-        eoam.set_request(PonPortObject()/

-                         PortIngressRuleHeader(precedence=13)/

-                         PortIngressRuleClauseMatchLength02(fieldcode=Clause['L2 Type/Len'],

-                                                            operator=Operator['=='], match=0x0800)/

-                         PortIngressRuleClauseMatchLength01(fieldcode=Clause['IPv4/IPv6 Protocol Type'],

-                                                            operator=Operator['=='], match=0x02)/

-                         PortIngressRuleResultForward()/

-                         PortIngressRuleResultSet(fieldcode=Clause['C-VLAN Tag'], value=4000)/

-                         PortIngressRuleResultInsert(fieldcode=Clause['C-VLAN Tag'])/

-                         PortIngressRuleTerminator()/

-                         AddPortIngressRule())

-

-        time.sleep(3)

-

-        print 'Delete - Port Ingress Rule -- PON Port Object -- IGMP'

-        eoam.set_request(PonPortObject()/

-                         PortIngressRuleHeader(precedence=13)/

-                         PortIngressRuleClauseMatchLength02(fieldcode=Clause['L2 Type/Len'],

-                                                            operator=Operator['=='], match=0x0800)/

-                         PortIngressRuleClauseMatchLength01(fieldcode=Clause['IPv4/IPv6 Protocol Type'],

-                                                            operator=Operator['=='], match=0x02)/

-                         PortIngressRuleResultForward()/

-                         PortIngressRuleResultSet(fieldcode=Clause['C-VLAN Tag'], value=4000)/

-                         PortIngressRuleResultInsert(fieldcode=Clause['C-VLAN Tag'])/

-                         PortIngressRuleTerminator()/

-                         DeletePortIngressRule())

-

-    if (args.test_dhcp == True):

-        #################################################################################

-        ## DHCP

-        #################################################################################

-        Clause = {v: k for k, v in ClauseSubtypeEnum.iteritems()}

-        Operator = {v: k for k, v in RuleOperatorEnum.iteritems()}

-

-        print 'SET - Port Ingress Rule -- PON Port Object -- DHCP'

-        eoam.set_request(PonPortObject()/

-                         PortIngressRuleHeader(precedence=13)/

-                         PortIngressRuleClauseMatchLength02(fieldcode=Clause['L2 Type/Len'],

-                                                            operator=Operator['=='], match=0x0800)/

-                         PortIngressRuleClauseMatchLength01(fieldcode=Clause['IPv4/IPv6 Protocol Type'],

-                                                            operator=Operator['=='], match=0x11)/

-                         PortIngressRuleClauseMatchLength02(fieldcode=Clause['TCP/UDP source port'],

-                                                            operator=Operator['=='], match=0x0044)/

-                         PortIngressRuleClauseMatchLength02(fieldcode=Clause['TCP/UDP destination port'],

-                                                            operator=Operator['=='], match=0x0043)/

-                         PortIngressRuleResultForward()/

-                         PortIngressRuleResultSet(fieldcode=Clause['C-VLAN Tag'], value=4000)/

-                         PortIngressRuleResultInsert(fieldcode=Clause['C-VLAN Tag'])/

-                         PortIngressRuleTerminator()/

-                         AddPortIngressRule())

-

-        time.sleep(3)

-

-        print 'Delete - Port Ingress Rule -- PON Port Object -- DHCP'

-        eoam.set_request(PonPortObject()/

-                         PortIngressRuleHeader(precedence=13)/

-                         PortIngressRuleClauseMatchLength02(fieldcode=Clause['L2 Type/Len'],

-                                                            operator=Operator['=='], match=0x0800)/

-                         PortIngressRuleClauseMatchLength01(fieldcode=Clause['IPv4/IPv6 Protocol Type'],

-                                                            operator=Operator['=='], match=0x11)/

-                         PortIngressRuleClauseMatchLength02(fieldcode=Clause['TCP/UDP source port'],

-                                                            operator=Operator['=='], match=0x0044)/

-                         PortIngressRuleClauseMatchLength02(fieldcode=Clause['TCP/UDP destination port'],

-                                                            operator=Operator['=='], match=0x0043)/

-                         PortIngressRuleResultForward()/

-                         PortIngressRuleResultSet(fieldcode=Clause['C-VLAN Tag'], value=4000)/

-                         PortIngressRuleResultInsert(fieldcode=Clause['C-VLAN Tag'])/

-                         PortIngressRuleTerminator()/

-                         DeletePortIngressRule())

-

-    if (args.test_upstream == True):

-        #################################################################################

-        ## UPSTREAM

-        #################################################################################

-        Clause = {v: k for k, v in ClauseSubtypeEnum.iteritems()}

-        Operator = {v: k for k, v in RuleOperatorEnum.iteritems()}

-

-        print 'SET - Port Ingress Rule -- OLT Unicast Logical Link -- Upstream Traffic'

-        eoam.set_request(PortIngressRuleHeader(precedence=13)/

-                         PortIngressRuleClauseMatchLength02(fieldcode=Clause['C-VLAN Tag'], fieldinstance=0,

-                                                            operator=Operator['=='], match=0x00f1)/

-                         PortIngressRuleResultForward()/

-                         PortIngressRuleResultCopy(fieldcode=Clause['C-VLAN Tag'])/

-                         PortIngressRuleResultInsert(fieldcode=Clause['C-VLAN Tag'], fieldinstance=1)/

-                         PortIngressRuleResultSet(fieldcode=Clause['C-VLAN Tag'], value=1000)/

-                         PortIngressRuleResultReplace(fieldcode=Clause['C-VLAN Tag'])/

-                         OLTUnicastLogicalLink(unicastvssn="TBIT", unicastlink=0xe2222900)/

-                         PortIngressRuleTerminator()/

-                         AddPortIngressRule())

-

-

-        time.sleep(3)

-

-        print 'DELETE - Port Ingress Rule -- OLT Unicast Logical Link -- Upstream Traffic'

-        eoam.set_request(OLTUnicastLogicalLink(unicastvssn="TBIT", unicastlink=0xe2222900)/

-                         PortIngressRuleHeader(precedence=13)/

-                         PortIngressRuleClauseMatchLength02(fieldcode=Clause['C-VLAN Tag'], fieldinstance=0,

-                                                            operator=Operator['=='], match=0x00f1)/

-                         PortIngressRuleResultForward()/

-                         PortIngressRuleResultCopy(fieldcode=Clause['C-VLAN Tag'])/

-                         PortIngressRuleResultInsert(fieldcode=Clause['C-VLAN Tag'], fieldinstance=1)/

-                         PortIngressRuleResultSet(fieldcode=Clause['C-VLAN Tag'], value=1000)/

-                         PortIngressRuleResultReplace(fieldcode=Clause['C-VLAN Tag'])/

-                         PortIngressRuleTerminator()/

-                         DeletePortIngressRule())

-

-    if (args.test_downstream == True):

-        #################################################################################

-        ## DOWNSTREAM

-        #################################################################################

-        Clause = {v: k for k, v in ClauseSubtypeEnum.iteritems()}

-        Operator = {v: k for k, v in RuleOperatorEnum.iteritems()}

-

-        print 'SET - Port Ingress Rule -- NNI Port Object -- Downstream Traffic -- 4000/241'

-        eoam.set_request(NetworkToNetworkPortObject()/

-                         PortIngressRuleHeader(precedence=13)/

-                         PortIngressRuleClauseMatchLength02(fieldcode=Clause['C-VLAN Tag'], fieldinstance=0,

-                                                            operator=Operator['=='], match=0x0fa0)/

-                         PortIngressRuleClauseMatchLength02(fieldcode=Clause['C-VLAN Tag'], fieldinstance=1,

-                                                            operator=Operator['=='], match=0x00f1)/

-                         PortIngressRuleResultOLTQueue(unicastvssn="TBIT", unicastlink=0xe2222900)/

-                         PortIngressRuleResultForward()/

-                         PortIngressRuleResultDelete(fieldcode=Clause['C-VLAN Tag'])/

-                         PortIngressRuleTerminator()/

-                         AddPortIngressRule())

-

-        time.sleep(1)

-

-        print 'SET - Port Ingress Rule -- NNI Port Object -- Downstream Traffic -- 1000/241'

-        eoam.set_request(NetworkToNetworkPortObject()/

-                         PortIngressRuleHeader(precedence=13)/

-                         PortIngressRuleClauseMatchLength02(fieldcode=Clause['C-VLAN Tag'], fieldinstance=0,

-                                                            operator=Operator['=='], match=0x03e8)/

-                         PortIngressRuleClauseMatchLength02(fieldcode=Clause['C-VLAN Tag'], fieldinstance=1,

-                                                            operator=Operator['=='], match=0x00f1)/

-                         PortIngressRuleResultOLTQueue(unicastvssn="TBIT", unicastlink=0xe2222900)/

-                         PortIngressRuleResultForward()/

-                         PortIngressRuleResultDelete(fieldcode=Clause['C-VLAN Tag'])/

-                         PortIngressRuleTerminator()/

-                         AddPortIngressRule())

-

-

-        time.sleep(1)

-

-        print 'SET - Port Ingress Rule -- NNI Port Object -- Downstream Traffic -- 4000/203'

-        eoam.set_request(NetworkToNetworkPortObject()/

-                         PortIngressRuleHeader(precedence=13)/

-                         PortIngressRuleClauseMatchLength02(fieldcode=Clause['C-VLAN Tag'], fieldinstance=0,

-                                                            operator=Operator['=='], match=0x0fa0)/

-                         PortIngressRuleClauseMatchLength02(fieldcode=Clause['C-VLAN Tag'], fieldinstance=1,

-                                                            operator=Operator['=='], match=0x00CB)/

-                         PortIngressRuleResultOLTQueue(unicastvssn="TBIT", unicastlink=0xe2220300)/

-                         PortIngressRuleResultForward()/

-                         PortIngressRuleResultDelete(fieldcode=Clause['C-VLAN Tag'])/

-                         PortIngressRuleTerminator()/

-                         AddPortIngressRule())

-

-        time.sleep(1)

-

-        print 'SET - Port Ingress Rule -- NNI Port Object -- Downstream Traffic -- 1000/203'

-        eoam.set_request(NetworkToNetworkPortObject()/

-                         PortIngressRuleHeader(precedence=13)/

-                         PortIngressRuleClauseMatchLength02(fieldcode=Clause['C-VLAN Tag'], fieldinstance=0,

-                                                            operator=Operator['=='], match=0x03e8)/

-                         PortIngressRuleClauseMatchLength02(fieldcode=Clause['C-VLAN Tag'], fieldinstance=1,

-                                                            operator=Operator['=='], match=0x00cb)/

-                         PortIngressRuleResultOLTQueue(unicastvssn="TBIT", unicastlink=0xe2220300)/

-                         PortIngressRuleResultForward()/

-                         PortIngressRuleResultDelete(fieldcode=Clause['C-VLAN Tag'])/

-                         PortIngressRuleTerminator()/

-                         AddPortIngressRule())

-

-    if (args.test_multicast == True):

-        #################################################################################

-        ## MULTICAST

-        #################################################################################

-        Clause = {v: k for k, v in ClauseSubtypeEnum.iteritems()}

-        Operator = {v: k for k, v in RuleOperatorEnum.iteritems()}

-

-        print 'SET - Port Ingress Rule -- NNI Port Object -- Downstream Multicast Traffic'

-        eoam.set_request(NetworkToNetworkPortObject()/

-                         PortIngressRuleHeader(precedence=13)/

-                         PortIngressRuleClauseMatchLength02(fieldcode=Clause['C-VLAN Tag'], fieldinstance=0,

-                                                            operator=Operator['=='], match=0x008c)/

-                         PortIngressRuleResultOLTBroadcastQueue()/

-                         PortIngressRuleResultForward()/

-                         PortIngressRuleResultDelete(fieldcode=Clause['C-VLAN Tag'])/

-                         PortIngressRuleTerminator()/

-                         AddPortIngressRule())

-

-

-        time.sleep(3)

-

-        print 'DELETE - Port Ingress Rule -- NNI Port Object -- Downstream Multicast Traffic'

-        eoam.set_request(NetworkToNetworkPortObject()/

-                         PortIngressRuleHeader(precedence=13)/

-                         PortIngressRuleClauseMatchLength02(fieldcode=Clause['C-VLAN Tag'], fieldinstance=0,

-                                                            operator=Operator['=='], match=0x008c)/

-                         PortIngressRuleResultOLTBroadcastQueue()/

-                         PortIngressRuleResultForward()/

-                         PortIngressRuleResultDelete(fieldcode=Clause['C-VLAN Tag'])/

-                         PortIngressRuleTerminator()/

-                         DeletePortIngressRule())

-

-

-    if (args.test_ping == True):

-        json_operation_str = '{\"operation\":\"version\"}'

-        for i in range(10000):

-            eoam.send_frame(TBJSON(data='json %s' % json_operation_str), False)

-

+    pass

diff --git a/voltha/extensions/eoam/EOAM_Layers.py b/voltha/extensions/eoam/EOAM_Layers.py
new file mode 100755
index 0000000..d48ddef
--- /dev/null
+++ b/voltha/extensions/eoam/EOAM_Layers.py
@@ -0,0 +1,141 @@
+#!/usr/bin/env python
+#--------------------------------------------------------------------------#
+# Copyright (C) 2015 - 2016 by Tibit Communications, Inc.                  #
+# All rights reserved.                                                     #
+#                                                                          #
+#    _______ ____  _ ______                                                #
+#   /_  __(_) __ )(_)_  __/                                                #
+#    / / / / __  / / / /                                                   #
+#   / / / / /_/ / / / /                                                    #
+#  /_/ /_/_____/_/ /_/                                                     #
+#                                                                          #
+#--------------------------------------------------------------------------#
+
+import sys
+import inspect
+
+# SCAPY-specific imports
+from scapy.all import Dot1Q
+from scapy.all import sniff, hexdump
+from scapy.packet import Packet, bind_layers
+from scapy.fields import StrField, PacketField, X3BytesField
+from scapy.layers.l2 import Ether
+
+from EOAM_TLV import *
+
+# Layer 2 definitions
+EOAM_MULTICAST_ADDRESS = '01:80:c2:00:00:02'   # Well-known OAM Multicast address
+UNUSED_SOURCE_ADDRESS  = '12:34:56:78:9a:bc'   # for OAM frames sent over the CLI
+IGMP_MULTICAST_ADDRESS = '01:00:5e:00:00:01'   # IGMP Multicast address
+OAM_ETHERTYPE          = 0xA8C8                # Ethertype value used to identify a 1904.2 message
+
+VENDOR_SPECIFIC_OPCODE = 0xFE
+CABLELABS_OUI          = 0x001000              # CableLabs OUI (used for DPoE OAM messages)
+TIBIT_OUI              = 0x2AEA15              # Tibit OUI
+ITU_OUI                = 0x0019A7              # ITU OUI - used to encapsulate OMCI messages
+
+# Message Types which can be received from the Tibit OLT, Tibit ONU, DPoE ONU, or GPON ONT
+# ove the 1904.2 transport
+RxedOamMsgTypeEnum = {
+    "Unknown"            : 0x00,
+    "Info"               : 0x01,    # Info PDU
+    "Event Notification" : 0x02,    # Event Notification - Tibit or DPoE Event
+    "DPoE Get Response"  : 0x03,    # DPoE Get Response
+    "DPoE Set Response"  : 0x04,    # DPoE Set Rewponse
+    "DPoE File Transfer" : 0x05,    # Specifically - a File Transfer ACK
+    "OMCI Message"       : 0x06,    # Contains an embedded OMCI message
+    }
+
+RxedOamMsgTypes = {v: k for k, v in RxedOamMsgTypeEnum.iteritems()}
+
+
+###############################################################
+# SCAPY Layer definitions used to parse 1904.2 messages
+###############################################################
+
+# OAM fields after the L2 addressing/VLAN tags
+# when the Ethertype is set to 0xA8C8
+class EOAMPayload(Packet):
+    name = 'EOAM Payload'
+    fields_desc = [
+        ByteEnumField("subtype", 0x03, SlowProtocolsSubtypeEnum),
+        XShortField("flags", 0x0050),
+        XByteField("opcode", VENDOR_SPECIFIC_OPCODE),
+    ]
+
+bind_layers(Ether, EOAMPayload, type=OAM_ETHERTYPE)
+
+
+# 1904.1 OAM Event
+class EOAM_EventMsg(Packet):
+    name = 'EOAM Event'
+    fields_desc = [
+        XShortField("sequence", 0x0001),
+        XByteField("tlv_type", VENDOR_SPECIFIC_OPCODE),
+        XByteField("length", 0x01),
+        X3BytesField("oui", CABLELABS_OUI),
+        PacketField("body", None, Packet),
+    ]
+
+bind_layers(EOAMPayload, EOAM_EventMsg, opcode=0x01)
+
+# Vendor-specific OAM message
+# indicated by an Opcode field set to 0xFE
+class EOAM_VendSpecificMsg(Packet):
+    name = "Vendor-Specific OAM"
+    fields_desc  = [
+        X3BytesField("oui", CABLELABS_OUI),
+    ]
+
+bind_layers(EOAMPayload, EOAM_VendSpecificMsg, opcode=VENDOR_SPECIFIC_OPCODE)
+
+# Tibit-specific OAM message
+# indicated by an OUI set to 0x2AEA15
+class EOAM_TibitMsg(Packet):
+    name = "Tibit OAM Message"
+    fields_desc  = [
+        ByteEnumField("dpoe_opcode", 0x01, DPoEOpcodeEnum),
+        PacketField("body", None, Packet),
+    ]
+
+bind_layers(EOAM_VendSpecificMsg, EOAM_TibitMsg, oui=TIBIT_OUI)
+
+# DPoE-specific OAM message
+# indicated by an OUI set to 0x001000
+class EOAM_DpoeMsg(Packet):
+    name = "DPoE OAM Message"
+    fields_desc  = [
+        ByteEnumField("dpoe_opcode", 0x01, DPoEOpcodeEnum),
+        PacketField("body", None, Packet),
+    ]
+
+bind_layers(EOAM_VendSpecificMsg, EOAM_DpoeMsg, oui=CABLELABS_OUI)
+
+# Embedded OMCI message
+# indicated by an OUI set to ITU OUI (0x0019A7)
+
+#class EOAM_OmciMsg(Packet):
+#    name = "OAM-encapsulated OMCI Message"
+#    fields_desc  = [
+#        XShortField("trans_id", 1),
+#        XByteField("msg_type", 0x49),
+#        XByteField("dev_id", 0x0A),
+#        XShortField("me_class", 0x0000),
+#        XShortField("me_inst", 0x0000),
+#        PacketField("body", None, Packet),
+#    ]
+
+class EOAM_OmciMsg(Packet):
+    name = "OAM-encapsulated OMCI Message"
+    fields_desc  = [
+        PacketField("body", None, Packet),
+    ]
+
+bind_layers(EOAM_VendSpecificMsg, EOAM_OmciMsg, oui=ITU_OUI)
+
+###############################################################
+# End of SCAPY Layers
+###############################################################
+
+
+
diff --git a/voltha/extensions/eoam/EOAM_TLV.py b/voltha/extensions/eoam/EOAM_TLV.py
index 545490b..2596499 100644
--- a/voltha/extensions/eoam/EOAM_TLV.py
+++ b/voltha/extensions/eoam/EOAM_TLV.py
@@ -1,4 +1,4 @@
-#--------------------------------------------------------------------------#
+##--------------------------------------------------------------------------#
 # Copyright (C) 2015 - 2016 by Tibit Communications, Inc.                  #
 # All rights reserved.                                                     #
 #                                                                          #
@@ -14,7 +14,7 @@
 from scapy.fields import ByteEnumField, XShortField, XByteField, MACField, \
     ByteField, BitEnumField, BitField, ShortField
 from scapy.fields import XLongField, StrField, StrFixedLenField, XIntField, \
-    FieldLenField, StrLenField, IntField
+    FieldLenField, StrLenField, IntField, ShortEnumField
 
 # This library strives to be an implementation of the following standard:
 
@@ -38,6 +38,24 @@
 
 SlowProtocolsSubtypeEnum = {0x03: "OAM"}
 
+### OAM Branch Enumerations
+OamBranchEnum = {
+    0x00: "End",
+    0x06: "Clause 30 Object",
+    0x07: "Clause 30 Attr",
+    0x09: "Clause 30 Action",
+    0xB7: "Tibit Attr",
+    0xB9: "Tibit Action",
+    0xC7: "DPoG Attr",
+    0xC9: "DPoG Action",
+    0xD6: "DPoE Object",
+    0xD7: "DPoE Attr",
+    0xD9: "DPoE Action",
+    }
+
+OamBranches = {v: k for k, v in OamBranchEnum.iteritems()}
+
+
 ### Multicast Action Flags
 MulticastActionFlagsEnum = {
     0x02: "Deregister",
@@ -56,8 +74,11 @@
     0x09: "File Transfer",
     }
 
+DPoEOpcodes = {v: k for k, v in DPoEOpcodeEnum.iteritems()}
+
+
 ### Table 20 - DPoE Variable Response Codes
-DPoEVariableResponseCodes = {
+DPoEVariableResponseEnum = {
     0x80: "No Error",
     0x81: "Too Long",
     0x86: "Bad Parameters",
@@ -70,6 +91,24 @@
     0xa4: "Overflow",
     }
 
+DPoEVariableResponseCodes = {v: k for k, v in DPoEVariableResponseEnum.iteritems()}
+
+
+### Table 14 - DPoE Event Codes
+DPoEEventCodeEnum = {
+    0x11: "Loss of Signal",
+    0x12: "Key Exchange Failure",
+    0x21: "Port Disabled",
+    0x41: "Power Failure",
+    0x81: "Statistics Alarm",
+    0x82: "D-ONU Busy",
+    0x83: "MAC Table Overflow",
+    0x84: "PON Interface Switch",
+    }
+
+DPoEEventCodes = {v: k for k, v in DPoEEventCodeEnum.iteritems()}
+
+
 class SlowProtocolsSubtype(Packet):
     """ Slow Protocols subtype"""
     name = "Slow Protocols subtype"
@@ -163,13 +202,33 @@
                    ]
 
 ####
-#### PORT OBJECTS
+#### OAM Context OBJECTS
 ####
+
+### Object Context Enumerations
+ObjectContextEnum = {
+    0x0000: "Device",
+    0x0001: "PON Port",
+    0x0002: "Unicast Logical Link",
+    0x0003: "Enet Port",
+    0x0004: "Queue",
+    0x0005: "SOAM MEP",
+    0x0006: "Multicast Link",
+    0x0007: "T-CONT",
+# __TIBIT_OLT_OAM__: Defined by Tibit
+    0x0009: "ONU",
+    0x000A: "OLT Unicast Link",
+    0x000B: "GPIO",
+    }
+
+ObjectContexts = {v: k for k, v in ObjectContextEnum.iteritems()}
+
+
 class DONUObject(Packet):
     """ Object Context: D-ONU Object """
     name = "Object Context: D-ONU Object"
-    fields_desc = [XByteField("branch", 0xD6),
-                   XShortField("leaf", 0x0000),
+    fields_desc = [ByteEnumField("branch", 0xD6, OamBranchEnum),
+                   ShortEnumField("leaf", 0x0000, ObjectContextEnum),
                    XByteField("length", 1),
                    XByteField("number", 0)
                    ]
@@ -178,8 +237,8 @@
 class DOLTObject(Packet):
     """ Object Context: D-OLT Object """
     name = "Object Context: D-OLT Object"
-    fields_desc = [XByteField("branch", 0xD6),
-                   XShortField("leaf", 0x0000),
+    fields_desc = [ByteEnumField("branch", 0xD6, OamBranchEnum),
+                   ShortEnumField("leaf", 0x0000, ObjectContextEnum),
                    XByteField("length", 1),
                    XByteField("number", 0)
                    ]
@@ -187,8 +246,8 @@
 class NetworkPortObject(Packet):
     """ Object Context: Network Port Object """
     name = "Object Context: Network Port Object"
-    fields_desc = [XByteField("branch", 0xD6),
-                   XShortField("leaf", 0x0001),
+    fields_desc = [ByteEnumField("branch", 0xD6, OamBranchEnum),
+                   ShortEnumField("leaf", 0x0001, ObjectContextEnum),
                    XByteField("length", 1),
                    XByteField("number", 0)
                    ]
@@ -197,8 +256,8 @@
 class PonPortObject(Packet):
     """ Object Context: PON Port Object """
     name = "Object Context: PON Port Object"
-    fields_desc = [XByteField("branch", 0xD6),
-                   XShortField("leaf", 0x0001),
+    fields_desc = [ByteEnumField("branch", 0xD6, OamBranchEnum),
+                   ShortEnumField("leaf", 0x0001, ObjectContextEnum),
                    XByteField("length", 1),
                    XByteField("number", 0)
                    ]
@@ -206,8 +265,8 @@
 class UnicastLogicalLink(Packet):
     """ Object Context: Unicast Logical Link """
     name = "Object Context: Unicast Logical Link"
-    fields_desc = [XByteField("branch", 0xD6),
-                   XShortField("leaf", 0x0002),
+    fields_desc = [ByteEnumField("branch", 0xD6, OamBranchEnum),
+                   ShortEnumField("leaf", 0x0002, ObjectContextEnum),
                    XByteField("length", 1),
                    XByteField("number", 0)
                    ]
@@ -216,8 +275,8 @@
 class OLTUnicastLogicalLink(Packet):
     """ Object Context: OLT Unicast Logical Link """
     name = "Object Context: OLT Unicast Logical Link"
-    fields_desc = [XByteField("branch", 0xD6),
-                   XShortField("leaf", 0x000a),
+    fields_desc = [ByteEnumField("branch", 0xD6, OamBranchEnum),
+                   ShortEnumField("leaf", 0x000A, ObjectContextEnum),
                    XByteField("length", 10),
                    XByteField("pon", 0),
                    StrField("unicastvssn", "TBIT"),
@@ -228,8 +287,8 @@
 class OLTEPONUnicastLogicalLink(Packet):
     """ Object Context: OLT Unicast Logical Link """
     name = "Object Context: OLT Unicast Logical Link"
-    fields_desc = [XByteField("branch", 0xD6),
-                   XShortField("leaf", 0x000a),
+    fields_desc = [ByteEnumField("branch", 0xD6, OamBranchEnum),
+                   ShortEnumField("leaf", 0x000A, ObjectContextEnum),
                    XByteField("length", 10),
                    XByteField("pon", 0),
                    XIntField("unicastvssn", 0x00000000),
@@ -242,8 +301,8 @@
 class NetworkToNetworkPortObject(Packet):
     """ Object Context: Network-to-Network (NNI) Port Object """
     name = "Object Context: Network-to-Network (NNI) Port Object"
-    fields_desc = [XByteField("branch", 0xD6),
-                   XShortField("leaf", 0x0003),
+    fields_desc = [ByteEnumField("branch", 0xD6, OamBranchEnum),
+                   ShortEnumField("leaf", 0x0003, ObjectContextEnum),
                    XByteField("length", 1),
                    XByteField("number", 0)
                    ]
@@ -251,8 +310,8 @@
 class UserPortObject(Packet):
     """ Object Context: User Port Object """
     name = "Object Context: User Port Object"
-    fields_desc = [XByteField("branch", 0xD6),
-                   XShortField("leaf", 0x0003),
+    fields_desc = [ByteEnumField("branch", 0xD6, OamBranchEnum),
+                   ShortEnumField("leaf", 0x0003, ObjectContextEnum),
                    XByteField("length", 1),
                    XByteField("number", 0)
                    ]
@@ -260,8 +319,8 @@
 class QueueObject(Packet):
     """ Object Context: Queue Object """
     name = "Object Context: Queue Object"
-    fields_desc = [XByteField("branch", 0xD6),
-                   XShortField("leaf", 0x0004),
+    fields_desc = [ByteEnumField("branch", 0xD6, OamBranchEnum),
+                   ShortEnumField("leaf", 0x0004, ObjectContextEnum),
                    XByteField("length", 2),
                    XByteField("instance", 0),
                    XByteField("number", 0)
@@ -270,26 +329,35 @@
 class ONUObject(Packet):
     """ Object Context: ONU Object """
     name = "Object Context: ONU Object"
-    fields_desc = [XByteField("branch", 0xD6),
-                   XShortField("leaf", 0x0009),
+    fields_desc = [ByteEnumField("branch", 0xD6, OamBranchEnum),
+                   ShortEnumField("leaf", 0x0009, ObjectContextEnum),
                    XByteField("length", 6),
                    MACField("mac", "54:42:e2:22:11:00")
                    ]
 
+class GpioObject(Packet):
+    """ Object Context: GPIO Object """
+    name = "Object Context: GPIO Object"
+    fields_desc = [ByteEnumField("branch", 0xD6, OamBranchEnum),
+                   ShortEnumField("leaf", 0x000B, ObjectContextEnum),
+                   XByteField("length", 1),
+                   XByteField("condition", 1)
+                   ]
+
 ####
 #### 0x09 - BRANCH ATTRIBUTES
 ####
 class PhyAdminControl(Packet):
     """ Variable Descriptor: Phy Admin Control """
-    name = "Variable Descriptor: Phy Admin Control"
-    fields_desc = [XByteField("branch", 0x09),
+    name = "Phy Admin Control"
+    fields_desc = [ByteEnumField("branch", 0x09, OamBranchEnum),
                    XShortField("leaf", 0x0005),
                    ]
 
 class PhyAdminControlEnableSet(Packet):
     """ Variable Descriptor: Phy Admin Control Enable """
-    name = "Variable Descriptor: Phy Admin Control Enable"
-    fields_desc = [XByteField("branch", 0x09),
+    name = "Phy Admin Control Enable"
+    fields_desc = [ByteEnumField("branch", 0x09, OamBranchEnum),
                    XShortField("leaf", 0x0005),
                    XByteField("length", 1),
                    XByteField("value", 2)
@@ -297,8 +365,8 @@
 
 class PhyAdminControlDisableSet(Packet):
     """ Variable Descriptor: Phy Admin Control Disable """
-    name = "Variable Descriptor: Phy Admin Control Disable"
-    fields_desc = [XByteField("branch", 0x09),
+    name = "Phy Admin Control Disable"
+    fields_desc = [ByteEnumField("branch", 0x09, OamBranchEnum),
                    XShortField("leaf", 0x0005),
                    XByteField("length", 1),
                    XByteField("value", 1)
@@ -309,69 +377,72 @@
 ####
 class DeviceId(Packet):
     """ Variable Descriptor: Device ID """
-    name = "Variable Descriptor: Device ID"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "Device ID"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0002)]
 
 class FirmwareInfo(Packet):
     """ Variable Descriptor: Firmware Info """
-    name = "Variable Descriptor: Firmware Info"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "Firmware Info"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0003)]
 
 class ChipsetInfo(Packet):
     """ Variable Descriptor: Chipset Info """
-    name = "Variable Descriptor: Chipset Info"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "Chipset Info"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0004)]
 
 class DateOfManufacture(Packet):
     """ Variable Descriptor: Date of Manufacture """
-    name = "Variable Descriptor: Date of Manufacture"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "Date of Manufacture"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0005)]
 
 class ManufacturerInfo(Packet):
     """ Variable Descriptor: ManufacturerInfo """
-    name = "Variable Descriptor: ManufacturerInfo"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "ManufacturerInfo"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0006)]
 
 class MaxLogicalLinks(Packet):
     """ Variable Descriptor: Max Logical Links """
-    name = "Variable Descriptor: Max Logical Links"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "Max Logical Links"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0007)]
 
 class NumberOfNetworkPorts(Packet):
     """ Variable Descriptor: Number of Network Ports """
-    name = "Variable Descriptor: Number of Network Ports"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "Number of Network Ports"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0008)]
 
 class NumberOfS1Interfaces(Packet):
     """ Variable Descriptor: Number of S1 Interfaces """
-    name = "Variable Descriptor: Number of S1 Interfaces"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "Number of S1 Interfaces"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0009)]
 
 class DONUPacketBuffer(Packet):
     """ Variable Descriptor: D-ONU Packet Buffer """
-    name = "Variable Descriptor: D-ONU Packet Buffer"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "D-ONU Packet Buffer"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x000a)]
 
 class ReportThresholds(Packet):
     """ Variable Descriptor: Report Thresholds """
-    name = "Variable Descriptor: Report Thresholds"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "Report Thresholds"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x000b),
                    ]
 
+DFLT_NUM_QUEUE_SETS  = 4
+DFLT_NUM_REPORT_VALS = 1
+
 class ReportThresholdsSet(Packet):
     """ Variable Descriptor: Report Thresholds Set """
-    name = "Variable Descriptor: Report Thresholds Set"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "Report Thresholds Set"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x000b),
                    XByteField("length", 0x0a),
                    XByteField("num_queue_sets", 4),
@@ -384,8 +455,8 @@
 
 class UnicastLogicalLinkReportThresholdsSet(Packet):
     """ Variable Descriptor: Report Thresholds Unicast Logical Link Set"""
-    name = "Variable Descriptor: Report Thresholds Unicast Logical Link Set"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "Report Thresholds Unicast Logical Link Set"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x000b),
                    XByteField("length", 0x0a),
                    XByteField("num_queue_sets", 4),
@@ -398,22 +469,22 @@
 
 class LogicalLinkForwarding(Packet):
     """ Variable Descriptor: Logical Link Forwarding """
-    name = "Variable Descriptor: Logical Link Forwarding"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "Logical Link Forwarding"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x000c),
                    ]
 
 class OamFrameRate(Packet):
     """ Variable Descriptor: OAM Frame Rate """
-    name = "Variable Descriptor: OAM Frame Rate"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "OAM Frame Rate"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x000d),
                    ]
 
 class OamFrameRateSet(Packet):
     """ Variable Descriptor: OAM Frame Rate """
-    name = "Variable Descriptor: OAM Frame Rate"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "OAM Frame Rate"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x000d),
                    XByteField("length", 2),
                    XByteField("max", 12),
@@ -422,57 +493,57 @@
 
 class OnuManufacturerOrganizationName(Packet):
     """ Variable Descriptor: ONU Manufacturer Organization Name """
-    name = "Variable Descriptor: ONU Manufacturer Organization Name"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "ONU Manufacturer Organization Name"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x000e),
                    ]
 
 class FirmwareMfgTimeVaryingControls(Packet):
     """ Variable Descriptor: Firmware Mfg Time Varying Controls """
-    name = "Variable Descriptor: Firmware Mfg Time Varying Controls"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "Firmware Mfg Time Varying Controls"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x000f),
                    ]
 
 class VendorName(Packet):
     """ Variable Descriptor: Vendor Name """
-    name = "Variable Descriptor: Vendor Name"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "Vendor Name"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0011),
                    ]
 
 class ModelNumber(Packet):
     """ Variable Descriptor: Model Number """
-    name = "Variable Descriptor: Model Number"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "Model Number"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0012),
                    ]
 
 class HardwareVersion(Packet):
     """ Variable Descriptor: Hardware Version """
-    name = "Variable Descriptor: Hardware Version"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "Hardware Version"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0013),
                    ]
 
 class EponMode(Packet):
     """ Variable Descriptor: EPON Mode """
-    name = "Variable Descriptor: EPON Mode"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "EPON Mode"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0014),
                    ]
 
 class DynamicAddressAgeLimit(Packet):
     """ Variable Descriptor: Dynamic Address Age Limit """
-    name = "Variable Descriptor: Dynamic Address Age Limit"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "Dynamic Address Age Limit"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0102),
                    ]
 
 class DynamicAddressAgeLimitSet(Packet):
     """ Variable Descriptor: Dynamic Address Age Limit Set """
-    name = "Variable Descriptor: Dynamic Address Age Limit Set"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "Dynamic Address Age Limit Set"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0102),
                    XByteField("length", 2),
                    XShortField("value", 0x0000),
@@ -480,29 +551,29 @@
 
 class DynamicMacTable(Packet):
     """ Variable Descriptor: Dynamic MAC Table """
-    name = "Variable Descriptor: Dynamic MAC Table"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "Dynamic MAC Table"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0103),
                    ]
 
 class StaticMacTable(Packet):
     """ Variable Descriptor: Static MAC Table """
-    name = "Variable Descriptor: Static MAC Table"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "Static MAC Table"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0104),
                    ]
 
 class SourceAddressAdmissionControl(Packet):
     """ Variable Descriptor: Source Address Admission Control """
-    name = "Variable Descriptor: Source Address Admission Control"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "Source Address Admission Control"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0106),
                    ]
 
 class SourceAddressAdmissionControlSet(Packet):
     """ Variable Descriptor: Source Address Admission Control Set """
-    name = "Variable Descriptor: Source Address Admission Control Set"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "Source Address Admission Control Set"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0106),
                    XByteField("length", 1),
                    XByteField("value", 1),
@@ -510,15 +581,15 @@
 
 class MacLearningMinGuarantee(Packet):
     """ Variable Descriptor: MAC Learning MIN Guarantee """
-    name = "Variable Descriptor: MAC Learning MIN Guarantee"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "MAC Learning MIN Guarantee"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0107),
                    ]
 
 class MacLearningMinGuaranteeSet(Packet):
     """ Variable Descriptor: MAC Learning MIN Guarantee Set """
-    name = "Variable Descriptor: MAC Learning MIN Guarantee Set"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "MAC Learning MIN Guarantee Set"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0107),
                    XByteField("length", 2),
                    XShortField("value", 0),
@@ -526,15 +597,15 @@
 
 class MacLearningMaxAllowed(Packet):
     """ Variable Descriptor: MAC Learning MAX Allowed """
-    name = "Variable Descriptor: MAC Learning MAX Allowed"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "MAC Learning MAX Allowed"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0108),
                    ]
 
 class MacLearningMaxAllowedSet(Packet):
     """ Variable Descriptor: MAC Learning MAX Allowed Set """
-    name = "Variable Descriptor: MAC Learning MAX Allowed Set"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "MAC Learning MAX Allowed Set"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0108),
                    XByteField("length", 2),
                    XShortField("value", 0x0010),
@@ -542,15 +613,15 @@
 
 class MacLearningAggregateLimit(Packet):
     """ Variable Descriptor: MAC Learning Aggregate Limit """
-    name = "Variable Descriptor: MAC Learning Aggregate Limit"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "MAC Learning Aggregate Limit"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0109),
                    ]
 
 class MacLearningAggregateLimitSet(Packet):
     """ Variable Descriptor: MAC Learning Aggregate Limit Set """
-    name = "Variable Descriptor: MAC Learning Aggregate Limit Set"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "MAC Learning Aggregate Limit Set"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0109),
                    XByteField("length", 2),
                    XShortField("value", 0x0040),
@@ -558,15 +629,15 @@
 
 class FloodUnknown(Packet):
     """ Variable Descriptor: Flood Unknown """
-    name = "Variable Descriptor: Flood Unknown"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "Flood Unknown"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x010b),
                    ]
 
 class FloodUnknownSet(Packet):
     """ Variable Descriptor: Flood Unknown Set """
-    name = "Variable Descriptor: Flood Unknown Set"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "Flood Unknown Set"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x010b),
                    XByteField("length", 1),
                    XByteField("value", 1),
@@ -574,15 +645,15 @@
 
 class LocalSwitching(Packet):
     """ Variable Descriptor: Local Switching """
-    name = "Variable Descriptor: Local Switching"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "Local Switching"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x010c),
                    ]
 
 class LocalSwitchingSet(Packet):
     """ Variable Descriptor: Local Switching Set """
-    name = "Variable Descriptor: Local Switching Set"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "Local Switching Set"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x010c),
                    XByteField("length", 1),
                    XByteField("value", 0),
@@ -590,29 +661,95 @@
 
 class LLIDQueueConfiguration(Packet):
     """ Variable Descriptor: LLID Queue Configuration """
-    name = "Variable Descriptor: LLID Queue Configuration"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "LLID Queue Configuration"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x010d),
                    ]
 
+DFLT_NUM_ONU_LLIDS   = 1
+DFLT_NUM_LLID_QUEUES = 1
+DFLT_NUM_UNI_PORTS   = 1
+DFLT_NUM_PORT_QUEUES = 1
+DFLT_LLID_QUEUE_SIZE = 0xA0
+
 class LLIDQueueConfigurationSet(Packet):
     """ Variable Descriptor: LLID Queue Configuration """
-    name = "Variable Descriptor: LLID Queue Configuration"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "LLID Queue Configuration"
+
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x010d),
                    XByteField("length", 6),
-                   XByteField("numLLID", 1),
-                   XByteField("LLID0-numq", 1),
-                   XByteField("l0Q0-size",0xa0),
-                   XByteField("numPort", 1),
-                   XByteField("Port0-numq", 1),
-                   XByteField("p0Q0-size",0xa0),
+                   XByteField("numLLID",    DFLT_NUM_ONU_LLIDS),
+                   XByteField("LLID0-numq", DFLT_NUM_LLID_QUEUES),
+                   XByteField("l0Q0-size",  DFLT_LLID_QUEUE_SIZE),
+                   XByteField("numPort",    DFLT_NUM_UNI_PORTS),
+                   XByteField("Port0-numq", DFLT_NUM_PORT_QUEUES),
+                   XByteField("p0Q0-size",  DFLT_LLID_QUEUE_SIZE),
                    ]
 
+
+
+class LLIDQueueConfiguration16Set(Packet):
+    """ Variable Descriptor: LLID Queue Configuration """
+    name = "LLID Queue Configuration"
+
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
+                   XShortField("leaf", 0x010d),
+                   XByteField("length", 36),
+                   XByteField("numLLID",    16),
+                   XByteField("LLID0-numq", 1),
+                   XByteField("l0Q0-size",  32),
+                   XByteField("LLID1-numq", 1),
+                   XByteField("l1Q0-size",  32),
+                   XByteField("LLID2-numq", 1),
+                   XByteField("l2Q0-size",  32),
+                   XByteField("LLID3-numq", 1),
+                   XByteField("l3Q0-size",  32),
+                   XByteField("LLID4-numq", 1),
+                   XByteField("l4Q0-size",  32),
+                   XByteField("LLID5-numq", 1),
+                   XByteField("l5Q0-size",  32),
+                   XByteField("LLID6-numq", 1),
+                   XByteField("l6Q0-size",  32),
+                   XByteField("LLID7-numq", 1),
+                   XByteField("l7Q0-size",  32),
+                   XByteField("LLID8-numq", 1),
+                   XByteField("l8Q0-size",  32),
+                   XByteField("LLID9-numq", 1),
+                   XByteField("l9Q0-size",  32),
+                   XByteField("LLID10-numq", 1),
+                   XByteField("l10Q0-size",  32),
+                   XByteField("LLID11-numq", 1),
+                   XByteField("l11Q0-size",  32),
+                   XByteField("LLID12-numq", 1),
+                   XByteField("l12Q0-size",  32),
+                   XByteField("LLID13-numq", 1),
+                   XByteField("l13Q0-size",  32),
+                   XByteField("LLID14-numq", 1),
+                   XByteField("l14Q0-size",  32),
+                   XByteField("LLID15-numq", 1),
+                   XByteField("l15Q0-size",  16),
+                   XByteField("numPort",    DFLT_NUM_UNI_PORTS),
+                   XByteField("Port0-numq", DFLT_NUM_PORT_QUEUES),
+                   XByteField("p0Q0-size",  DFLT_LLID_QUEUE_SIZE),
+                   ]
+
+
+
+class LLIDQueueConfigurationSetData(Packet):
+    """ Variable Descriptor: LLID Queue Configuration """
+    name = "LLID Queue Configuration"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
+                   XShortField("leaf", 0x010d),
+                   FieldLenField("length", None, length_of="data", fmt="B"),
+                   StrLenField("data", "", length_from=lambda x:x.length),
+                  ]
+
+
 class FirmwareFilename(Packet):
     """ Variable Descriptor: Firmware Filename """
-    name = "Variable Descriptor: Firmware Filename"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "Firmware Filename"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x010e),
                    ]
 
@@ -623,36 +760,36 @@
 
 class ClearDynamicMacTable(Packet):
     """ Variable Descriptor: Clear Dynamic MAC Table """
-    name = "Variable Descriptor: Clear Dynamic MAC Table"
-    fields_desc = [XByteField("branch", 0xD9),
+    name = "Clear Dynamic MAC Table"
+    fields_desc = [ByteEnumField("branch", 0xD9, OamBranchEnum),
                    XShortField("leaf", 0x0101),
                    ]
 
 class AddDynamicMacAddress(Packet):
     """ Variable Descriptor: Add Dynamic MAC Address """
-    name = "Variable Descriptor: Add Dynamic MAC Address"
-    fields_desc = [XByteField("branch", 0xD9),
+    name = "Add Dynamic MAC Address"
+    fields_desc = [ByteEnumField("branch", 0xD9, OamBranchEnum),
                    XShortField("leaf", 0x0102),
                    ]
 
 class DeleteDynamicMacAddress(Packet):
     """ Variable Descriptor: Delete Dynamic MAC Address """
-    name = "Variable Descriptor: Delete Dynamic MAC Address"
-    fields_desc = [XByteField("branch", 0xD9),
+    name = "Delete Dynamic MAC Address"
+    fields_desc = [ByteEnumField("branch", 0xD9, OamBranchEnum),
                    XShortField("leaf", 0x0103),
                    ]
 
 class ClearStaticMacTable(Packet):
     """ Variable Descriptor: Clear Static MAC Table """
-    name = "Variable Descriptor: Clear Static MAC Table"
-    fields_desc = [XByteField("branch", 0xD9),
+    name = "Clear Static MAC Table"
+    fields_desc = [ByteEnumField("branch", 0xD9, OamBranchEnum),
                    XShortField("leaf", 0x0104),
                    ]
 
 class AddStaticMacAddress(Packet):
     """ Variable Descriptor: Add Static MAC Address """
-    name = "Variable Descriptor: Add Static MAC Address"
-    fields_desc = [XByteField("branch", 0xD9),
+    name = "Add Static MAC Address"
+    fields_desc = [ByteEnumField("branch", 0xD9, OamBranchEnum),
                    XShortField("leaf", 0x0105),
                    ByteField("length", 6),
                    MACField("mac", "01:00:5e:00:00:00"),
@@ -660,8 +797,8 @@
 
 class DeleteStaticMacAddress(Packet):
     """ Variable Descriptor: Delete Static MAC Address """
-    name = "Variable Descriptor: Delete Static MAC Address"
-    fields_desc = [XByteField("branch", 0xD9),
+    name = "Delete Static MAC Address"
+    fields_desc = [ByteEnumField("branch", 0xD9, OamBranchEnum),
                    XShortField("leaf", 0x0106),
                    ByteField("length", 6),
                    MACField("mac", "01:00:5e:00:00:00"),
@@ -673,148 +810,148 @@
 
 class RxFramesGreen(Packet):
     """ Variable Descriptor: RxFramesGreen """
-    name = "Variable Descriptor: RxFramesGreen"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "RxFramesGreen"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0201),
                    ]
 
 class TxFramesGreen(Packet):
     """ Variable Descriptor: TxFramesGreen """
-    name = "Variable Descriptor: TxFramesGreen"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "TxFramesGreen"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0202),
                    ]
 
 class RxFrame_64(Packet):
     """ Variable Descriptor: RxFrame_64 """
-    name = "Variable Descriptor: RxFrame_64"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "RxFrame_64"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0204),
                    ]
 
 class RxFrame_65_127(Packet):
     """ Variable Descriptor: RxFrame_65_127 """
-    name = "Variable Descriptor: RxFrame_65_127"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "RxFrame_65_127"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0205),
                    ]
 
 class RxFrame_128_255(Packet):
     """ Variable Descriptor: RxFrame_128_255 """
-    name = "Variable Descriptor: RxFrame_128_255"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "RxFrame_128_255"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0206),
                    ]
 
 class RxFrame_256_511(Packet):
     """ Variable Descriptor: RxFrame_256_511 """
-    name = "Variable Descriptor: RxFrame_256_511"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "RxFrame_256_511"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0207),
                    ]
 
 class RxFrame_512_1023(Packet):
     """ Variable Descriptor: RxFrame_512_1023 """
-    name = "Variable Descriptor: RxFrame_512_1023"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "RxFrame_512_1023"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0208),
                    ]
 
 class RxFrame_1024_1518(Packet):
     """ Variable Descriptor: RxFrame_1024_1518 """
-    name = "Variable Descriptor: RxFrame_1024_1518"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "RxFrame_1024_1518"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0209),
                    ]
 
 class RxFrame_1519Plus(Packet):
     """ Variable Descriptor: RxFrame_1024_1518 """
-    name = "Variable Descriptor: RxFrame_1024_1518"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "RxFrame_1519_Plus"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x020A),
                    ]
 
 class TxFrame_64(Packet):
     """ Variable Descriptor: TxFrame_64 """
-    name = "Variable Descriptor: TxFrame_64"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "TxFrame_64"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x020B),
                    ]
 
 class TxFrame_65_127(Packet):
     """ Variable Descriptor: TxFrame_65_127 """
-    name = "Variable Descriptor: TxFrame_65_127"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "TxFrame_65_127"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x020C),
                    ]
 
 class TxFrame_128_255(Packet):
     """ Variable Descriptor: TxFrame_128_255 """
-    name = "Variable Descriptor: TxFrame_128_255"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "TxFrame_128_255"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x020D),
                    ]
 
 class TxFrame_256_511(Packet):
     """ Variable Descriptor: TxFrame_256_511 """
-    name = "Variable Descriptor: TxFrame_256_511"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "TxFrame_256_511"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x020E),
                    ]
 
 class TxFrame_512_1023(Packet):
     """ Variable Descriptor: TxFrame_512_1023 """
-    name = "Variable Descriptor: TxFrame_512_1023"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "TxFrame_512_1023"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x020F),
                    ]
 
 class TxFrame_1024_1518(Packet):
     """ Variable Descriptor: TxFrame_1024_1518 """
-    name = "Variable Descriptor: TxFrame_1024_1518"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "TxFrame_1024_1518"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0210),
                    ]
 
 class TxFrame_1519Plus(Packet):
     """ Variable Descriptor: TxFrame_1024_1518 """
-    name = "Variable Descriptor: TxFrame_1024_1518"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "TxFrame_1519_Plus"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0211),
                    ]
 
 class FramesDropped(Packet):
     """ Variable Descriptor: Frames Dropped """
-    name = "Variable Descriptor: Frames Dropped"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "Frames Dropped"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0214),
                    ]
 
 class BytesDropped(Packet):
     """ Variable Descriptor: Bytes Dropped """
-    name = "Variable Descriptor: Bytes Dropped"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "Bytes Dropped"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0215),
                    ]
 
 class TxBytesUnused(Packet):
     """ Variable Descriptor: Tx Bytes Unused """
-    name = "Variable Descriptor: Tx Bytes Unused"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "Tx Bytes Unused"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0217),
                    ]
 
 class TxL2Errors(Packet):
     """ Variable Descriptor: TxL2Errors """
-    name = "Variable Descriptor: TxL2Errors"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "TxL2Errors"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0235),
                    ]
 
 class RxL2Errors(Packet):
     """ Variable Descriptor: RxL2Errors """
-    name = "Variable Descriptor: RxL2Errors"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "RxL2Errors"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0236),
                    ]
 
@@ -824,15 +961,15 @@
 
 class AlarmReporting(Packet):
     """ Variable Descriptor: Alarm Reporting """
-    name = "Variable Descriptor: Alarm Reporting"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "Alarm Reporting"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0303),
                    ]
 
 class AlarmReportingSet(Packet):
     """ Variable Descriptor: Alarm Reporting Set """
-    name = "Variable Descriptor: Alarm Reporting Set"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "Alarm Reporting Set"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0303),
                    XByteField("length", 6),
                    XShortField("LOS", 0x1101),
@@ -845,15 +982,15 @@
 ####
 class EncryptionMode(Packet):
     """ Variable Descriptor: Encryption Mode """
-    name = "Variable Descriptor: Encryption Mode"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "Encryption Mode"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0402),
                    ]
 
 class EncryptionModeSet(Packet):
     """ Variable Descriptor: Encryption Mode Set """
-    name = "Variable Descriptor: Encryption Mode Set"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "Encryption Mode Set"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0402),
                    XByteField("length", 1),
                    XByteField("value", 0),
@@ -861,8 +998,8 @@
 
 class IpmcForwardingRuleConfiguration(Packet):
     """ Variable Descriptor: IPMC Forwarding Rule Configuration """
-    name = "Variable Descriptor: IPMC Forwarding Rule Configuration"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "IPMC Forwarding Rule Configuration"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0505),
                    XByteField("length", 2),
                    XShortField("value", 0x0000),
@@ -870,15 +1007,15 @@
 
 class QueueCommittedInformationRate(Packet):
     """ Variable Descriptor: Queue Committed Information Rate """
-    name = "Variable Descriptor: Queue Committed Information Rate"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "Queue Committed Information Rate"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0604),
                    ]
 
 class QueueCommittedInformationRateSet(Packet):
     """ Variable Descriptor: Queue Committed Information Rate Set """
-    name = "Variable Descriptor: Queue Committed Information Rate Set"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "Queue Committed Information Rate Set"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0604),
                    XByteField("length", 6),
                    XShortField("burst", 0x0fff),
@@ -888,15 +1025,15 @@
 
 class FECMode(Packet):
     """ Variable Descriptor: FEC Mode """
-    name = "Variable Descriptor: FEC Mode"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "FEC Mode"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0605),
                    ]
 
 class FECModeSet(Packet):
     """ Variable Descriptor: FEC Mode """
-    name = "Variable Descriptor: FEC Mode"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "FEC Mode"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0605),
                    XByteField("length", 2),
                    XByteField("downstream", 0x01),
@@ -905,8 +1042,8 @@
 
 class MediaType(Packet):
     """ Variable Descriptor: Media Type """
-    name = "Variable Descriptor: Media Type"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "Media Type"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0822),
                    ]
 
@@ -914,6 +1051,12 @@
 ####
 #### 0xD7 - Port Ingress Rules
 ####
+RuleSubtypeEnum = {  0x00: "Terminator",
+                     0x01: "Header",
+                     0x02: "Clause",
+                     0x03: "Result",
+                     }
+
 ClauseSubtypeEnum = {0x00: "LLID Index",
                      0x01: "L2 Destination MAC address",
                      0x02: "L2 Source MAC address",
@@ -958,27 +1101,74 @@
                      0x07: "T",           #True
                      }
 
+RuleResultsEnum =  { 0x00: "NOP",
+                     0x01: "Discard",
+                     0x02: "Forward",
+                     0x03: "Queue",
+                     0x04: "Set",
+                     0x05: "Copy",
+                     0x06: "Delete",
+                     0x07: "Insert",
+                     0x08: "Replace",
+                     0x09: "Clear Delete",
+                     0x0a: "Clear Insert",
+                     0x0b: "Increment Counter",
+                     # Tibit-specific values
+                     0x13: "OLT Queue",
+                     0x14: "Learning Group"
+                     }
+
+RuleClauses = {v: k for k, v in ClauseSubtypeEnum.iteritems()}
+RuleOperators = {v: k for k, v in RuleOperatorEnum.iteritems()}
+RuleResults = {v: k for k, v in RuleResultsEnum.iteritems()}
+
 class PortIngressRule(Packet):
     """ Variable Descriptor: Port Ingress Rule """
-    name = "Variable Descriptor: Port Ingress Rule"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "Port Ingress Rule"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0501),
                    ]
 
 class PortIngressRuleHeader(Packet):
     """ Variable Descriptor: Port Ingress Rule Header """
-    name = "Variable Descriptor: Port Ingress Rule Header"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "Port Ingress Rule Header"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0501),
                    ByteField("length", 2),
-                   XByteField("header", 1),
-                   XByteField("precedence", 00),
+                   XByteField("subtype", 0x01), # Header
+                   ByteField("precedence", 12),
+                   ]
+
+class PortIngressRuleClause(Packet):
+    """ Variable Descriptor: Port Ingress Rule Clause """
+    name = "Port Ingress Rule Clause"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
+                   XShortField("leaf", 0x0501),
+                   FieldLenField("length", None, length_of="match", fmt="B", adjust=lambda pkt,x: x+7),
+                   XByteField("subtype", 0x02), #Clause
+                   XByteField("fieldcode", 0),
+                   XByteField("fieldinstance", 0),
+                   XByteField("msbmask", 0),
+                   XByteField("lsbmask", 0),
+                   XByteField("operator", 0x7), # T
+                   XByteField("matchlength", 0),
+                   StrLenField("match", "", length_from=lambda x:x.matchlength),
+                   ]
+
+class PortIngressRuleResultNoData(Packet):
+    """ Variable Descriptor: Port Ingress Rule Result NOP """
+    name = "Rule Result NOP"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
+                   XShortField("leaf", 0x0501),
+                   ByteField("length", 2),
+                   XByteField("subtype", 0x03), # Result
+                   ByteField("resulttype", 0x00),
                    ]
 
 class PortIngressRuleClauseMatchLength00(Packet):
     """ Variable Descriptor: Port Ingress Rule Clause """
-    name = "Variable Descriptor: Port Ingress Rule Clause"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "Port Ingress Rule Clause"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0501),
                    ByteField("length", 7),
                    XByteField("clause", 2),
@@ -990,10 +1180,25 @@
                    XByteField("matchlength", 0),
                    ]
 
+class PortIngressRuleClauseAlwaysMatch(Packet):
+    """ Variable Descriptor: Port Ingress Rule Clause """
+    name = "Port Ingress Rule Clause"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
+                   XShortField("leaf", 0x0501),
+                   ByteField("length", 7),
+                   XByteField("clause", 2),
+                   XByteField("fieldcode", 0),
+                   XByteField("fieldinstance", 0),
+                   XByteField("msbmask", 0),
+                   XByteField("lsbmask", 0),
+                   XByteField("operator", 7),
+                   XByteField("matchlength", 0),
+                   ]
+
 class PortIngressRuleClauseMatchLength01(Packet):
     """ Variable Descriptor: Port Ingress Rule Clause """
-    name = "Variable Descriptor: Port Ingress Rule Clause"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "Port Ingress Rule Clause"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0501),
                    ByteField("length", 8),
                    XByteField("clause", 2),
@@ -1008,8 +1213,8 @@
 
 class PortIngressRuleClauseMatchLength02(Packet):
     """ Variable Descriptor: Port Ingress Rule Clause """
-    name = "Variable Descriptor: Port Ingress Rule Clause"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "Port Ingress Rule Clause"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0501),
                    ByteField("length", 9),
                    XByteField("clause", 2),
@@ -1019,14 +1224,14 @@
                    XByteField("lsbmask", 0),
                    XByteField("operator", 0),
                    XByteField("matchlength", 2),
-                   XShortField("match", 0),
+                   XShortField("match", 0)
                    ]
 
 
 class PortIngressRuleClauseMatchLength06(Packet):
     """ Variable Descriptor: Port Ingress Rule Clause """
-    name = "Variable Descriptor: Port Ingress Rule Clause"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "Port Ingress Rule Clause"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0501),
                    ByteField("length", 13),
                    XByteField("clause", 2),
@@ -1046,8 +1251,8 @@
 
 class PortIngressRuleResultForward(Packet):
     """ Variable Descriptor: Port Ingress Rule Result Forward """
-    name = "Variable Descriptor: Port Ingress Rule Result Forward"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "Port Ingress Rule Result Forward"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0501),
                    ByteField("length", 2),
                    XByteField("result", 3),
@@ -1056,8 +1261,8 @@
 
 class PortIngressRuleResultDiscard(Packet):
     """ Variable Descriptor: Port Ingress Rule Result Discard """
-    name = "Variable Descriptor: Port Ingress Rule Result Discard"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "Port Ingress Rule Result Discard"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0501),
                    ByteField("length", 2),
                    XByteField("result", 3),
@@ -1066,8 +1271,8 @@
 
 class PortIngressRuleResultQueue(Packet):
     """ Variable Descriptor: Port Ingress Rule Result Queue """
-    name = "Variable Descriptor: Port Ingress Rule Result Queue"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "Port Ingress Rule Result Queue"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0501),
                    ByteField("length", 6),
                    XByteField("result", 3),
@@ -1080,8 +1285,8 @@
 # __TIBIT_OLT_OAM__: Defined by Tibit
 class PortIngressRuleResultOLTQueue(Packet):
     """ Variable Descriptor: Port Ingress Rule Result OLT Queue """
-    name = "Variable Descriptor: Port Ingress Rule Result OLT Queue"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "Port Ingress Rule Result OLT Queue"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0501),
                    ByteField("length", 15),
                    XByteField("result", 3),
@@ -1096,8 +1301,8 @@
 
 class PortIngressRuleResultOLTEPONQueue(Packet):
     """ Variable Descriptor: Port Ingress Rule Result OLT Queue """
-    name = "Variable Descriptor: Port Ingress Rule Result OLT Queue"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "Port Ingress Rule Result OLT Queue"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0501),
                    ByteField("length", 15),
                    XByteField("result", 3),
@@ -1115,8 +1320,8 @@
 # __TIBIT_OLT_OAM__: Defined by Tibit
 class PortIngressRuleResultOLTBroadcastQueue(Packet):
     """ Variable Descriptor: Port Ingress Rule Result OLT Broadcast Queue """
-    name = "Variable Descriptor: Port Ingress Rule Result OLT Broadcast Queue"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "Port Ingress Rule Result OLT Broadcast Queue"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0501),
                    ByteField("length", 15),
                    XByteField("result", 3),
@@ -1128,25 +1333,38 @@
                    XByteField("pad", 0),
                    ]
 
+class PortIngressRuleResultLearningGroup(Packet):
+    """ Variable Descriptor: Port Ingress Rule Result Learning Group """
+    name = "Port Ingress Rule Result Learning Group "
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
+                   XShortField("leaf", 0x0501),
+                   ByteField("length", 6),
+                   XByteField("result", 3),
+                   XByteField("grouprule", 0x14),
+                   XShortField("objecttype", 0x0000),
+                   XByteField("instance", 0),
+                   XByteField("num", 0),
+                   ]
+
 class PortIngressRuleResultSet(Packet):
     """ Variable Descriptor: Port Ingress Rule Result Set """
-    name = "Variable Descriptor: Port Ingress Rule Result Set"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "Port Ingress Rule Result Set"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0501),
-                   ByteField("length", 8),
+                   FieldLenField("length", None, length_of="value", fmt="B", adjust=lambda pkt,x: x+6),
                    XByteField("result", 3),
                    XByteField("set", 4),
                    XByteField("fieldcode", 0),
                    XByteField("fieldinstance", 0),
                    XByteField("msbmask", 0),
                    XByteField("lsbmask", 0),
-                   XShortField("value", 0),
+                   StrLenField("value", "", length_from=lambda x:x.length-6),
                    ]
 
 class PortIngressRuleResultCopy(Packet):
     """ Variable Descriptor: Port Ingress Rule Result Copy """
-    name = "Variable Descriptor: Port Ingress Rule Result Copy"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "Port Ingress Rule Result Copy"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0501),
                    ByteField("length", 6),
                    XByteField("result", 3),
@@ -1159,20 +1377,20 @@
 
 class PortIngressRuleResultDelete(Packet):
     """ Variable Descriptor: Port Ingress Rule Result Delete """
-    name = "Variable Descriptor: Port Ingress Rule Result Delete"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "Port Ingress Rule Result Delete"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0501),
                    ByteField("length", 4),
                    XByteField("result", 3),
                    XByteField("delete", 6),
                    XByteField("fieldcode", 0),
-                   XByteField("instance", 0),
+                   XByteField("fieldinstance", 0),
                    ]
 
 class PortIngressRuleResultInsert(Packet):
     """ Variable Descriptor: Port Ingress Rule Result Insert """
-    name = "Variable Descriptor: Port Ingress Rule Result Insert"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "Port Ingress Rule Result Insert"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0501),
                    ByteField("length", 4),
                    XByteField("result", 3),
@@ -1183,8 +1401,8 @@
 
 class PortIngressRuleResultReplace(Packet):
     """ Variable Descriptor: Port Ingress Rule Result Replace """
-    name = "Variable Descriptor: Port Ingress Rule Result Replace"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "Port Ingress Rule Result Replace"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0501),
                    ByteField("length", 4),
                    XByteField("result", 3),
@@ -1195,8 +1413,8 @@
 
 class PortIngressRuleTerminator(Packet):
     """ Variable Descriptor: Port Ingress Rule Terminator """
-    name = "Variable Descriptor: Port Ingress Rule Terminator"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "Port Ingress Rule Terminator"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0501),
                    ByteField("length", 1),
                    XByteField("terminator", 0),
@@ -1204,8 +1422,8 @@
 
 class CustomField(Packet):
     """ Variable Descriptor: Custom Field """
-    name = "Variable Descriptor: Custom Field"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "Custom Field"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0502),
                    XByteField("length", 1),
                    XByteField("value", 0),
@@ -1213,8 +1431,8 @@
 
 class CustomFieldEtherType(Packet):
     """ Variable Descriptor: Custom Field EtherType """
-    name = "Variable Descriptor: Custom Field EtherType"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "Custom Field EtherType"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0502),
                    XByteField("length", 6),
                    XByteField("fieldcode", 0x19),
@@ -1227,8 +1445,8 @@
 
 class CustomFieldGenericL3(Packet):
     """ Variable Descriptor: Custom Field Generic L3 """
-    name = "Variable Descriptor: Custom Field Generic L3"
-    fields_desc = [XByteField("branch", 0xD7),
+    name = "Custom Field Generic L3"
+    fields_desc = [ByteEnumField("branch", 0xD7, OamBranchEnum),
                    XShortField("leaf", 0x0502),
                    XByteField("length", 6),
                    XByteField("fieldcode", 0x1a),
@@ -1245,30 +1463,24 @@
 
 class ClearPortIngressRules(Packet):
     """ Variable Descriptor: Clear Port Ingress Rule """
-    name = "Variable Descriptor: Clear Port Ingress Rule"
-    fields_desc = [XByteField("branch", 0xD9),
+    name = "Clear Port Ingress Rule"
+    fields_desc = [ByteEnumField("branch", 0xD9, OamBranchEnum),
                    XShortField("leaf", 0x0501),
-                   XByteField("length", 1),
-                   XByteField("value", 0),
                    ]
 
 class AddPortIngressRule(Packet):
     """ Variable Descriptor: Add Port Ingress Rule """
-    name = "Variable Descriptor: Add Port Ingress Rule"
-    fields_desc = [XByteField("branch", 0xD9),
+    name = "Add Port Ingress Rule"
+    fields_desc = [ByteEnumField("branch", 0xD9, OamBranchEnum),
                    XShortField("leaf", 0x0502),
-                   XByteField("length", 0x80),
-                   XByteField("value", 0),
                    ]
 
 
 class DeletePortIngressRule(Packet):
     """ Variable Descriptor: Delete Port Ingress Rule """
-    name = "Variable Descriptor: Delete Port Ingress Rule"
-    fields_desc = [XByteField("branch", 0xD9),
+    name = "Delete Port Ingress Rule"
+    fields_desc = [ByteEnumField("branch", 0xD9, OamBranchEnum),
                    XShortField("leaf", 0x0503),
-                   XByteField("length", 0x80),
-                   XByteField("value", 0),
                    ]
 
 ####
@@ -1276,15 +1488,15 @@
 ####
 class OltMode(Packet):
     """ Variable Descriptor: OLT Mode """
-    name = "Variable Descriptor: "
-    fields_desc = [XByteField("branch", 0xB7),
+    name = "OLT Mode"
+    fields_desc = [ByteEnumField("branch", 0xB7, OamBranchEnum),
                    XShortField("leaf", 0x0101),
                    ]
 
 class OltModeSet(Packet):
     """ Variable Descriptor: OLT Mode """
-    name = "Variable Descriptor: "
-    fields_desc = [XByteField("branch", 0xB7),
+    name = "OLT Mode"
+    fields_desc = [ByteEnumField("branch", 0xB7, OamBranchEnum),
                    XShortField("leaf", 0x0101),
                    XByteField("length", 1),
                    XByteField("value", 0),
@@ -1292,15 +1504,15 @@
 
 class OltPonAdminState(Packet):
     """ Variable Descriptor: OLT PON Admin State """
-    name = "Variable Descriptor: "
-    fields_desc = [XByteField("branch", 0xB7),
+    name = "PON Admin State"
+    fields_desc = [ByteEnumField("branch", 0xB7, OamBranchEnum),
                    XShortField("leaf", 0x0102),
                    ]
 
 class OltPonAdminStateSet(Packet):
     """ Variable Container: OLT PON Admin State """
-    name = "Variable Container: "
-    fields_desc = [XByteField("branch", 0xB7),
+    name = "PON Admin State"
+    fields_desc = [ByteEnumField("branch", 0xB7, OamBranchEnum),
                    XShortField("leaf", 0x0102),
                    XByteField("length", 1),
                    XByteField("value", 0),
@@ -1308,22 +1520,22 @@
 
 class TibitLinkMacTable(Packet):
     """ Variable Descriptor: Link MAC Table """
-    name = "Variable Descriptor: "
-    fields_desc = [XByteField("branch", 0xB7),
+    name = "Link MAC Table"
+    fields_desc = [ByteEnumField("branch", 0xB7, OamBranchEnum),
                    XShortField("leaf", 0x0103),
                    ]
 
 class TibitKeyExchange(Packet):
     """ Variable Descriptor: Key Exchange """
-    name = "Variable Descriptor: "
-    fields_desc = [XByteField("branch", 0xB7),
+    name = "Key Exchange Period"
+    fields_desc = [ByteEnumField("branch", 0xB7, OamBranchEnum),
                    XShortField("leaf", 0x0104),
                    ]
 
 class TibitKeyExchangeSet(Packet):
     """ Variable Descriptor: Key Exchange Set"""
-    name = "Variable Container: "
-    fields_desc = [XByteField("branch", 0xB7),
+    name = "Key Exchange Period"
+    fields_desc = [ByteEnumField("branch", 0xB7, OamBranchEnum),
                    XShortField("leaf", 0x0104),
                    XByteField("length", 2),
                    XShortField("value", 0x1234),
@@ -1331,15 +1543,15 @@
 
 class OnuMode(Packet):
     """ Variable Descriptor: ONU Mode """
-    name = "Variable Descriptor: "
-    fields_desc = [XByteField("branch", 0xB7),
+    name = "ONU Mode"
+    fields_desc = [ByteEnumField("branch", 0xB7, OamBranchEnum),
                    XShortField("leaf", 0x0105),
                    ]
 
 class OnuModeSet(Packet):
     """ Variable Descriptor: ONU Mode """
-    name = "Variable Descriptor: "
-    fields_desc = [XByteField("branch", 0xB7),
+    name = "ONU Mode"
+    fields_desc = [ByteEnumField("branch", 0xB7, OamBranchEnum),
                    XShortField("leaf", 0x0105),
                    XByteField("length", 1),
                    XByteField("value", 0),
@@ -1347,31 +1559,31 @@
 
 class TibitGrantSpacing(Packet):
     """ Variable Descriptor: Grant Spacing """
-    name = "Variable Descriptor: "
-    fields_desc = [XByteField("branch", 0xB7),
+    name = "Grant Spacing"
+    fields_desc = [ByteEnumField("branch", 0xB7, OamBranchEnum),
                    XShortField("leaf", 0x0106),
                    ]
 
 class TibitGrantSpacingSet(Packet):
     """ Variable Descriptor: Grant Spacing """
-    name = "Variable Descriptor: "
-    fields_desc = [XByteField("branch", 0xB7),
+    name = "Grant Spacing"
+    fields_desc = [ByteEnumField("branch", 0xB7, OamBranchEnum),
                    XShortField("leaf", 0x0106),
                    XByteField("length", 1),
                    XByteField("value", 0),
-                   ]                   
+                   ]
 
 class TibitBurstOverheadProfiles(Packet):
     """ Variable Descriptor: Burst Overhead Profiles """
-    name = "Variable Descriptor: "
-    fields_desc = [XByteField("branch", 0xB7),
+    name = "Burst Overhead Profiles"
+    fields_desc = [ByteEnumField("branch", 0xB7, OamBranchEnum),
                    XShortField("leaf", 0x0107),
                    ]
 
 class TibitBurstOverheadProfilesSet(Packet):
     """ Variable Descriptor: Burst Overhead Profiles """
-    name = "Variable Descriptor: "
-    fields_desc = [XByteField("branch", 0xB7),
+    name = "Burst Overhead Profiles"
+    fields_desc = [ByteEnumField("branch", 0xB7, OamBranchEnum),
                    XShortField("leaf", 0x0107),
                    # Length is one + 5 for each entry
                    XByteField("length", 6),
@@ -1387,6 +1599,158 @@
                    XByteField("us_fec", 1),
                    ]
 
+class TibitGpioConditionSet(Packet):
+    """ Variable Descriptor: GPIO condition Set """
+    name = "GPIO Condition"
+    fields_desc = [ByteEnumField("branch", 0xB7, OamBranchEnum),
+                   XShortField("leaf", 0x0108),
+                   XByteField("length", 1),
+                   XByteField("state", 0),
+                   ]
+
+class TibitDiscoveryPeriod(Packet):
+    """ Variable Descriptor: Discovery Period """
+    name = "Discovery Period"
+    fields_desc = [ByteEnumField("branch", 0xB7, OamBranchEnum),
+                   XShortField("leaf", 0x0109),
+                   ]
+
+class TibitDiscoveryPeriodSet(Packet):
+    """ Variable Descriptor: Discovery Period Set """
+    name = "Discovery Period"
+    fields_desc = [ByteEnumField("branch", 0xB7, OamBranchEnum),
+                   XShortField("leaf", 0x0109),
+                   XByteField("length", 2),
+                   XShortField("period", 3000),
+                   ]
+class TibitLldpPeriod(Packet):
+    """ Variable Descriptor: LLDP Period """
+    name = "LLDP Period"
+    fields_desc = [ByteEnumField("branch", 0xB7, OamBranchEnum),
+                   XShortField("leaf", 0x010A),
+                   ]
+
+class TibitLldpPeriodSet(Packet):
+    """ Variable Descriptor: LLDP Period Set """
+    name = "LLDP Period"
+    fields_desc = [ByteEnumField("branch", 0xB7, OamBranchEnum),
+                   XShortField("leaf", 0x010A),
+                   XByteField("length", 2),
+                   XShortField("period", 60),
+                   ]
+
+class TibitLldpDestAddress(Packet):
+    """ Variable Descriptor: LLDP Destination MAC Address """
+    name = "LLDP Dest Address"
+    fields_desc = [ByteEnumField("branch", 0xB7, OamBranchEnum),
+                   XShortField("leaf", 0x010B),
+                   ]
+
+class TibitLldpDestAddressSet(Packet):
+    """ Variable Descriptor: LLDP Destination MAC Address Set """
+    name = "LLDP Dest Address"
+    fields_desc = [ByteEnumField("branch", 0xB7, OamBranchEnum),
+                   XShortField("leaf", 0x010B),
+                   XByteField("length", 6),
+                   MACField("addr", "01:80:c2:00:00:0e"),
+                   ]
+
+class TibitLldpTpid(Packet):
+    """ Variable Descriptor: LLDP TPID """
+    name = "LLDP TPID"
+    fields_desc = [ByteEnumField("branch", 0xB7, OamBranchEnum),
+                   XShortField("leaf", 0x010C),
+                   ]
+
+class TibitLldpTpidSet(Packet):
+    """ Variable Descriptor: LLDP TPID Set """
+    name = "LLDP TPID"
+    fields_desc = [ByteEnumField("branch", 0xB7, OamBranchEnum),
+                   XShortField("leaf", 0x010C),
+                   XByteField("length", 2),
+                   XShortField("tpid", 0),
+                   ]
+
+class TibitLldpVid(Packet):
+    """ Variable Descriptor: LLDP TPID """
+    name = "LLDP VID"
+    fields_desc = [ByteEnumField("branch", 0xB7, OamBranchEnum),
+                   XShortField("leaf", 0x010D),
+                   ]
+
+class TibitLldpVidSet(Packet):
+    """ Variable Descriptor: LLDP TPID Set """
+    name = "LLDP VID"
+    fields_desc = [ByteEnumField("branch", 0xB7, OamBranchEnum),
+                   XShortField("leaf", 0x010D),
+                   XByteField("length", 2),
+                   XShortField("vid", 0),
+                   ]
+
+class TibitFailsafeTimer(Packet):
+    """ Variable Descriptor: Failsafe Timer """
+    name = "Failsafe Timer"
+    fields_desc = [ByteEnumField("branch", 0xB7, OamBranchEnum),
+                   XShortField("leaf", 0x010E),
+                   ]
+
+class TibitFailsafeTimerSet(Packet):
+    """ Variable Descriptor: Failsafe Timer Set """
+    name = "Failsafe Timer"
+    fields_desc = [ByteEnumField("branch", 0xB7, OamBranchEnum),
+                   XShortField("leaf", 0x010E),
+                   XByteField("length", 1),
+                   XByteField("timer", 0),
+                   ]
+
+class TibitMtu(Packet):
+    """ Variable Descriptor: MTU """
+    name = "MTU"
+    fields_desc = [ByteEnumField("branch", 0xB7, OamBranchEnum),
+                   XShortField("leaf", 0x010F),
+                   ]
+
+class TibitMtuSet(Packet):
+    """ Variable Descriptor: MTU Set """
+    name = "MTU"
+    fields_desc = [ByteEnumField("branch", 0xB7, OamBranchEnum),
+                   XShortField("leaf", 0x010F),
+                   XByteField("length", 4),
+                   XIntField("mtu", 0),
+                   ]
+
+class TibitCtagCtagMode(Packet):
+    """ Variable Descriptor: CTAG CTAG Mode """
+    name = "CTAG-CTAG Mode"
+    fields_desc = [ByteEnumField("branch", 0xB7, OamBranchEnum),
+                   XShortField("leaf", 0x0110),
+                   ]
+
+class TibitCtagCtagModeSet(Packet):
+    """ Variable Descriptor: CTAG CTAG Mode Set """
+    name = "CTAG-CTAG Mode"
+    fields_desc = [ByteEnumField("branch", 0xB7, OamBranchEnum),
+                   XShortField("leaf", 0x0110),
+                   XByteField("length", 1),
+                   XByteField("enable", 0),
+                   ]
+
+class TibitStatsOptions(Packet):
+    """ Variable Descriptor: Tibit Stats Options """
+    name = "Tibit Stats Options"
+    fields_desc = [ByteEnumField("branch", 0xB7, OamBranchEnum),
+                   XShortField("leaf", 0x0111),
+                   ]
+
+class TibitStatsOptionsSet(Packet):
+    """ Variable Descriptor: Tibit Stats Options Set"""
+    name = "Tibit Stats Options Set"
+    fields_desc = [ByteEnumField("branch", 0xB7, OamBranchEnum),
+                   XShortField("leaf", 0x0111),
+                   ByteField("length", 5),
+                   ByteField("enable", 0),
+                   IntField("period", 0),
+                   ]
 
 
 UpstreamSlaSubtypeEnum = { 0x00: "Terminator",
@@ -1403,15 +1767,15 @@
 
 class UpstreamSla(Packet):
     """ Variable Descriptor: Upstream SLA """
-    name = "Variable Descriptor: Upstream SLA"
-    fields_desc = [XByteField("branch", 0xB7),
+    name = "Upstream SLA"
+    fields_desc = [ByteEnumField("branch", 0xB7, OamBranchEnum),
                    XShortField("leaf", 0x0621),
                    ]
 
 class UpstreamSlaHeader(Packet):
     """ Variable Descriptor: Upstream SLA Header """
-    name = "Variable Descriptor: Upstream SLA Header"
-    fields_desc = [XByteField("branch", 0xB7),
+    name = "Upstream SLA Header"
+    fields_desc = [ByteEnumField("branch", 0xB7, OamBranchEnum),
                    XShortField("leaf", 0x0621),
                    ByteField("length", 1),
                    XByteField("subtype", 1),
@@ -1419,8 +1783,8 @@
 
 class UpstreamSlaTerminator(Packet):
     """ Variable Descriptor: Upstream SLA Terminator """
-    name = "Variable Descriptor: Upstream SLA Terminator"
-    fields_desc = [XByteField("branch", 0xB7),
+    name = "Upstream SLA Terminator"
+    fields_desc = [ByteEnumField("branch", 0xB7, OamBranchEnum),
                    XShortField("leaf", 0x0621),
                    ByteField("length", 1),
                    XByteField("subtype", 0),
@@ -1428,8 +1792,8 @@
 
 class UpstreamSlaSettingLength01(Packet):
     """ Variable Descriptor: Upstream SLA Setting """
-    name = "Variable Descriptor: Upstream SLA Setting"
-    fields_desc = [XByteField("branch", 0xB7),
+    name = "Upstream SLA Setting"
+    fields_desc = [ByteEnumField("branch", 0xB7, OamBranchEnum),
                    XShortField("leaf", 0x0621),
                    ByteField("length", 3),
                    XByteField("subtype", 0),
@@ -1439,8 +1803,8 @@
 
 class UpstreamSlaSettingLength02(Packet):
     """ Variable Descriptor: Upstream SLA Setting """
-    name = "Variable Descriptor: Upstream SLA Setting"
-    fields_desc = [XByteField("branch", 0xB7),
+    name = "Upstream SLA Setting"
+    fields_desc = [ByteEnumField("branch", 0xB7, OamBranchEnum),
                    XShortField("leaf", 0x0621),
                    ByteField("length", 4),
                    XByteField("subtype", 0),
@@ -1450,8 +1814,8 @@
 
 class UpstreamSlaSettingLength04(Packet):
     """ Variable Descriptor: Upstream SLA Setting """
-    name = "Variable Descriptor: Upstream SLA Setting"
-    fields_desc = [XByteField("branch", 0xB7),
+    name = "Upstream SLA Setting"
+    fields_desc = [ByteEnumField("branch", 0xB7, OamBranchEnum),
                    XShortField("leaf", 0x0621),
                    ByteField("length", 6),
                    XByteField("subtype", 0),
@@ -1461,20 +1825,52 @@
 
 class SlaPriorityType(Packet):
     """ Variable Descriptor: SLA Priority Type """
-    name = "Variable Descriptor: "
-    fields_desc = [XByteField("branch", 0xB7),
+    name = "SLA Priority Type"
+    fields_desc = [ByteEnumField("branch", 0xB7, OamBranchEnum),
                    XShortField("leaf", 0x0622),
                    ]
 
 class SlaPriorityTypeSet(Packet):
     """ Variable Container: SLA Priority Type """
-    name = "Variable Container: "
-    fields_desc = [XByteField("branch", 0xB7),
+    name = "SLA Priority Type"
+    fields_desc = [ByteEnumField("branch", 0xB7, OamBranchEnum),
                    XShortField("leaf", 0x0622),
                    XByteField("length", 1),
                    XByteField("value", 1),
                    ]
 
+class DsGuarRate(Packet):
+    """ Variable Descriptor: Downstream Guaranteed Rate """
+    name = "Downstream Guaranteed Rate"
+    fields_desc = [ByteEnumField("branch", 0xB7, OamBranchEnum),
+                   XShortField("leaf", 0x0623),
+                   ]
+
+class DsGuarRateSet(Packet):
+    """ Variable Descriptor: Downstream Guaranteed Rate Set"""
+    name = "Downstream Guaranteed Rate Set"
+    fields_desc = [ByteEnumField("branch", 0xB7, OamBranchEnum),
+                   XShortField("leaf", 0x0623),
+                   ByteField("length", 6),
+                   ShortField("mbs", 0),
+                   IntField("rate", 0),                  ]
+
+
+class DsBestEffortRate(Packet):
+    """ Variable Descriptor: Downstream Best Effort Rate """
+    name = "Downstream Best Effort Rate"
+    fields_desc = [ByteEnumField("branch", 0xB7, OamBranchEnum),
+                   XShortField("leaf", 0x0624),
+                   ]
+
+class DsBestEffortRateSet(Packet):
+    """ Variable Descriptor: Downstream Best Effort Rate Set"""
+    name = "Downstream Best Effort Rate Set"
+    fields_desc = [ByteEnumField("branch", 0xB7, OamBranchEnum),
+                   XShortField("leaf", 0x0624),
+                   ByteField("length", 6),
+                   ShortField("mbs", 0),
+                   IntField("rate", 0),                  ]
 
 
 ####
@@ -1483,23 +1879,22 @@
 
 class EnableUserTraffic(Packet):
     """ Variable Descriptor: Enable User Traffic """
-    name = "Variable Descriptor: Enable User Traffic"
-    fields_desc = [XByteField("branch", 0xD9),
+    name = "Enable User Traffic"
+    fields_desc = [ByteEnumField("branch", 0xD9, OamBranchEnum),
                    XShortField("leaf", 0x0601),
-                   XByteField("length", 1),
-                   XByteField("value", 0),
                    ]
 
 class DisableUserTraffic(Packet):
     """ Variable Descriptor: Disable User Traffic """
-    name = "Variable Descriptor: Disable User Traffic"
-    fields_desc = [XByteField("branch", 0xD9),
-                   XShortField("leaf", 0x0602)]
+    name = "Disable User Traffic"
+    fields_desc = [ByteEnumField("branch", 0xD9, OamBranchEnum),
+                   XShortField("leaf", 0x0602),
+                   ]
 
 class LoopbackEnable(Packet):
     """ Variable Descriptor: Loopback Enable """
-    name = "Variable Descriptor: Loopback Enable"
-    fields_desc = [XByteField("branch", 0xD9),
+    name = "Loopback Enable"
+    fields_desc = [ByteEnumField("branch", 0xD9, OamBranchEnum),
                    XShortField("leaf", 0x0603),
                    XByteField("length", 1),
                    XByteField("location", 0),
@@ -1507,8 +1902,8 @@
 
 class LoopbackDisable(Packet):
     """ Variable Descriptor: Loopback Disable """
-    name = "Variable Descriptor: Loopback Disable"
-    fields_desc = [XByteField("branch", 0xD9),
+    name = "Loopback Disable"
+    fields_desc = [ByteEnumField("branch", 0xD9, OamBranchEnum),
                    XShortField("leaf", 0x0604),
                    XByteField("length", 1),
                    XByteField("location", 0),
@@ -1516,43 +1911,101 @@
 
 class CurrentAlarmSummary(Packet):
     """ Variable Descriptor: Current Alarm Summary """
-    name = "Variable Descriptor: Current Alarm Summary"
-    fields_desc = [XByteField("branch", 0xD9),
+    name = "Current Alarm Summary"
+    fields_desc = [ByteEnumField("branch", 0xD9, OamBranchEnum),
                    XShortField("leaf", 0x0301)]
 
 class DeviceReset(Packet):
     """ Variable Descriptor: Device Reset """
-    name = "Variable Descriptor: Device Reset"
-    fields_desc = [XByteField("branch", 0xD9),
+    name = "Device Reset"
+    fields_desc = [ByteEnumField("branch", 0xD9, OamBranchEnum),
                    XShortField("leaf", 0x0001),
-                   XByteField("length", 0x80),
                    ]
 
 class TibitDeviceReset(Packet):
     """ Variable Descriptor: Tibit Device Reset """
-    name = "Variable Descriptor: Tibit Device Reset"
+    name = "Tibit Device Reset"
     fields_desc = [XByteField("branch", 0xB9),
                    XShortField("leaf", 0x0001),
-                   XByteField("length", 0x80),
+                   ]
+
+class TibitPreprovisionLink(Packet):
+    """ Variable Descriptor: Tibit Preprovision Link """
+    name = "Tibit Preprovision Link"
+    fields_desc = [XByteField("branch", 0xB9),
+                   XShortField("leaf", 0x0002),
                    ]
 
 class TibitApplySla(Packet):
     """ Variable Descriptor: Apply SLA """
-    name = "Variable Descriptor: Apply Sla"
+    name = "Apply Sla"
     fields_desc = [XByteField("branch", 0xB9),
                    XShortField("leaf", 0x0601),
-                   XByteField("length", 0x80),
-                   XByteField("value", 0),
                    ]
 
 
 ##
+## DPoE File Transfer
+##
+
+### Table 156 - DPoE File Transfer Opcodes
+DPoEFileXferOpcodeEnum = {
+    0x00: "Reserved",
+    0x01: "Write Request",
+    0x02: "File Transfer Data",
+    0x03: "File Transfer Ack",
+    }
+
+Dpoe_FileXferOpcodes = {v: k for k, v in DPoEFileXferOpcodeEnum.iteritems()}
+
+
+### Table 160 - DPoE File Acknowledgement Response Codes
+DPoEFileAckRespCodeEnum = {
+    0x00: "OK",
+    0x01: "Undefined",
+    0x02: "Not Found",
+    0x03: "No Access",
+    0x04: "Full",
+    0x05: "Illegal Operation",
+    0x06: "Unknown ID",
+    0x07: "Bad Block",
+    0x08: "Timeout",
+    0x09: "Busy",
+    0x0A: "Incompatible File",
+    0x0B: "Corrupted File",
+    }
+
+Dpoe_FileAckRspOpcodes = {v: k for k, v in DPoEFileAckRespCodeEnum.iteritems()}
+
+class DpoeFileTransferWrite(Packet):
+    name = "DPoE File Transfer Write "
+    fields_desc = [ByteEnumField("opcode", 0x01, DPoEFileXferOpcodeEnum),
+                   StrField("filename", ""),
+                  ]
+
+class DpoeFileTransferData(Packet):
+    name = "DPoE File Transfer Data "
+    fields_desc = [ByteEnumField("opcode", 0x02, DPoEFileXferOpcodeEnum),
+                   ShortField("block_num", 0),
+                   FieldLenField("block_width", None, length_of="block", fmt="H"),
+                   StrLenField("block", "", length_from=lambda x:x.length),
+                  ]
+
+class DpoeFileTransferAck(Packet):
+    name = "DPoE File Transfer Data "
+    fields_desc = [ByteEnumField("opcode", 0x03, DPoEFileXferOpcodeEnum),
+                   ShortField("block_num", 0),
+                   ByteEnumField("response_code", 0x00, DPoEFileAckRespCodeEnum),
+                  ]
+
+
+##
 ## Broadcom TLVs
 ##
 class Broadcom07_7F_F1_Set01(Packet):
     """ Variable Descriptor: Broadcom 0x07/0x7ff1 """
-    name = "Variable Descriptor: Broadcom 0x07/0x7ff1"
-    fields_desc = [XByteField("branch", 0x07),
+    name = "Broadcom 0x07/0x7ff1"
+    fields_desc = [ByteEnumField("branch", 0x07, OamBranchEnum),
                    XShortField("leaf", 0x7ff1),
                    XByteField("length", 2),
                    XShortField("value0", 0x0101),
@@ -1560,8 +2013,8 @@
 
 class Broadcom07_7F_F1_Set02(Packet):
     """ Variable Descriptor: Broadcom 0x07/0x7ff1 """
-    name = "Variable Descriptor: Broadcom 0x07/0x7ff1"
-    fields_desc = [XByteField("branch", 0x07),
+    name = "Broadcom 0x07/0x7ff1"
+    fields_desc = [ByteEnumField("branch", 0x07, OamBranchEnum),
                    XShortField("leaf", 0x7ff1),
                    XByteField("length", 7),
                    XShortField("value0", 0x0201),
@@ -1572,8 +2025,8 @@
 
 class Broadcom07_7F_F1_Set03(Packet):
     """ Variable Descriptor: Broadcom 0x07/0x7ff1 """
-    name = "Variable Descriptor: Broadcom 0x07/0x7ff1"
-    fields_desc = [XByteField("branch", 0x07),
+    name = "Broadcom 0x07/0x7ff1"
+    fields_desc = [ByteEnumField("branch", 0x07, OamBranchEnum),
                    XShortField("leaf", 0x7ff1),
                    XByteField("length", 7),
                    XShortField("value0", 0x0301),
@@ -1584,8 +2037,8 @@
 
 class Broadcom07_7F_F1_Set04(Packet):
     """ Variable Descriptor: Broadcom 0x07/0x7ff1 """
-    name = "Variable Descriptor: Broadcom 0x07/0x7ff1"
-    fields_desc = [XByteField("branch", 0x07),
+    name = "Broadcom 0x07/0x7ff1"
+    fields_desc = [ByteEnumField("branch", 0x07, OamBranchEnum),
                    XShortField("leaf", 0x7ff1),
                    XByteField("length", 1),
                    XByteField("value0", 0x00),
@@ -1593,8 +2046,8 @@
 
 class Broadcom07_7F_F6_Set(Packet):
     """ Variable Descriptor: Broadcom 0x07/0x7ff6 """
-    name = "Variable Descriptor: Broadcom 0x07/0x7ff6"
-    fields_desc = [XByteField("branch", 0x07),
+    name = "Broadcom 0x07/0x7ff6"
+    fields_desc = [ByteEnumField("branch", 0x07, OamBranchEnum),
                    XShortField("leaf", 0x7ff6),
                    XByteField("length", 2),
                    XShortField("value0", 0x07d0),
@@ -1605,8 +2058,8 @@
 ###
 class Clause30AttributesMacEnable(Packet):
     """ Variable Descriptor: Clause 30 Attributes MAC Enable """
-    name = "Variable Descriptor: Clause 30 Attributes MAC Enable"
-    fields_desc = [XByteField("branch", 0x07),
+    name = "Clause 30 Attributes MAC Enable"
+    fields_desc = [ByteEnumField("branch", 0x07, OamBranchEnum),
                    XShortField("leaf", 0x001a),
                    XByteField("length", 1),
                    XByteField("value", 1),
@@ -1614,8 +2067,8 @@
 
 class GenericTLV(Packet):
     """ Variable Descriptor: Generic TLV """
-    name = "Variable Descriptor: Generic TLV"
-    fields_desc = [XByteField("branch", 0x00),
+    name = "Generic TLV"
+    fields_desc = [ByteEnumField("branch", 0x00, OamBranchEnum),
                    XShortField("leaf", 0x0000),
                    FieldLenField("length", None, length_of="value", fmt="B"),
                    StrLenField("value", "", length_from=lambda x:x.length),