Initial working Tibit OLT and ONU.

Change-Id: I693cfc56638304f2b4d5ad05a401e9bc6cd5fa85
diff --git a/voltha/adapters/tibit_olt/EOAM.py b/voltha/adapters/tibit_olt/EOAM.py
index dd6e42b..69c056e 100644
--- a/voltha/adapters/tibit_olt/EOAM.py
+++ b/voltha/adapters/tibit_olt/EOAM.py
@@ -12,17 +12,18 @@
 #--------------------------------------------------------------------------#
 """ EOAM protocol implementation in scapy """
 
-TIBIT_VERSION_NUMBER = '1.1.2'
+TIBIT_VERSION_NUMBER = '1.1.4'
 
 import argparse
 import logging
 import time
-
 from hexdump import hexdump
 
 logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
 from scapy.layers.l2 import Ether, Dot1Q
 from scapy.sendrecv import sendp
+from scapy.fields import PacketField
+from scapy.packet import bind_layers
 
 import fcntl, socket, struct # for get hw address
 
@@ -90,7 +91,7 @@
             PACKET.show()
             print '###[ Frame Length %d (before padding) ]###' % len(PACKET)
         if (self.hexdump == True):
-            print hexdump(PACKET)
+            print hexdump(str(PACKET))
         if (self.dryrun != True):
             sendp(PACKET, iface=self.interface)
             time.sleep(self.sleep)
@@ -118,40 +119,18 @@
         return ':'.join(['%02x' % ord(char) for char in info[18:24]])
 
 
-class EOAMPayload():
-    """ EOAM Payload """
-    def __init__(self, dryrun=False,
-                 verbose=False, etype='8809',
-                 hexdump=False):
-        self.etype = int(etype, 16)
-        self.hexdump = hexdump
-        self.verbose = verbose
-        if (self.verbose == True):
-            print("=== Settings ================")
-            print("dryrun    = %s" % self.dryrun)
-            print("etype     = 0x%04x" % self.etype)
-            print("hexdump   = %s" % self.hexdump)
-            print("verbose   = %s" % self.verbose)
-            print("=== END Settings ============")
+class EOAMPayload(Packet):
+    name = 'EOAM Payload'
+    fields_desc = [
+        ByteEnumField("subtype", 0x03, SlowProtocolsSubtypeEnum),
+        XShortField("flags", 0x0050),
+        XByteField("opcode", 0xfe),
+        PacketField("body", None, Packet),
+        BitEnumField("type", 0x00, 7, TLV_dictionary),
+        BitField("length", 0x00, 9)
+    ]
 
-    def payload(self, frame_body):
-        PACKET = Ether()
-        PACKET.type = self.etype
-        PACKET/=SlowProtocolsSubtype()/FlagsBytes()/OAMPDU()
-        PACKET/=frame_body
-        PACKET/=EndOfPDU()
-        if (self.verbose == True):
-            PACKET.show()
-            print '###[ Frame Length %d (before padding) ]###' % len(PACKET)
-        if (self.hexdump == True):
-            print hexdump(PACKET)
-        return PACKET
-
-    def get_request(self, TLV):
-        return self.payload(CablelabsOUI()/DPoEOpcode_GetRequest()/TLV)
-
-    def set_request(self, TLV):
-        return self.payload(CablelabsOUI()/DPoEOpcode_SetRequest()/TLV)
+bind_layers(Ether, EOAMPayload, type=0x9001)
 
 if __name__ == "__main__":
     parser = argparse.ArgumentParser()
@@ -184,6 +163,8 @@
                         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')
 
     args = parser.parse_args()
 
@@ -206,7 +187,8 @@
         and not args.test
         and not args.test_add
         and not args.test_del
-        and not args.test_clr):
+        and not args.test_clr
+        and not args.test_eapol):
         print 'WARNING: *** No frames sent, please specify \'test\' or \'critical\', etc.  See --help'
 
 
@@ -228,3 +210,23 @@
     elif (args.test_del == True):
         print 'SET Delete Static MAC Address -- User Port Object'
         eoam.set_request(DeleteStaticMacAddress(mac=IGMP_MULTICAST_ADDRESS))
+
+    if (args.test_eapol == True):
+        print 'SET - Port Ingress Rule -- User Port Object -- Precedence 32 Match 0x888e'
+        eoam.set_request(DOLTObject()/
+                         PortIngressRuleHeader(precedence=32)/
+                         PortIngressRuleClauseMatchLength02(fieldcode=3, operator=1, match0=0x88, match1=0x8e)/
+                         PortIngressRuleResultForward()/
+                         PortIngressRuleResultSet(fieldcode=7, value=0x4090)/
+                         PortIngressRuleResultInsert(fieldcode=7)/
+                         PortIngressRuleTerminator()/
+                         AddPortIngressRule())
+
+        eoam.set_request(DOLTObject()/
+                         PortIngressRuleHeader(precedence=32)/
+                         PortIngressRuleClauseMatchLength02(fieldcode=3, operator=1, match0=0x88, match1=0x8e)/
+                         PortIngressRuleResultForward()/
+                         PortIngressRuleResultSet(fieldcode=7, value=0x4090)/
+                         PortIngressRuleResultInsert(fieldcode=7)/
+                         PortIngressRuleTerminator()/
+                         DeletePortIngressRule())
diff --git a/voltha/adapters/tibit_olt/EOAM_TLV.py b/voltha/adapters/tibit_olt/EOAM_TLV.py
index 0f02b7c..00ff2d7 100644
--- a/voltha/adapters/tibit_olt/EOAM_TLV.py
+++ b/voltha/adapters/tibit_olt/EOAM_TLV.py
@@ -21,7 +21,7 @@
 # This library may be used with PON devices for
 # configuration and provisioning.
 
-TIBIT_VERSION_NUMBER = '1.0.1'
+TIBIT_VERSION_NUMBER = '1.1.4'
 
 TLV_dictionary = {
     0x00: "End EOAMPDU",
@@ -144,6 +144,15 @@
                    XByteField("num", 0)
                    ]
 
+class DOLTObject(Packet):
+    """ Object Context: D-OLT Object """
+    name = "Object Context: D-OLT Object"
+    fields_desc = [XByteField("branch", 0xD6),
+                   XShortField("leaf", 0x0000),
+                   XByteField("length", 1),
+                   XByteField("num", 0)
+                   ]
+
 class NetworkPortObject(Packet):
     """ Object Context: Network Port Object """
     name = "Object Context: Network Port Object"
@@ -839,6 +848,35 @@
         XByteField("queuenum", 0),
         ]
 
+class PortIngressRuleResultSet(Packet):
+    """ Variable Descriptor: Port Ingress Rule Result Set """
+    name = "Variable Descriptor: Port Ingress Rule Result Set"
+    fields_desc = [
+        XByteField("branch", 0xD7),
+        XShortField("leaf", 0x0501),
+        ByteField("length", 8),
+        XByteField("result", 3),
+        XByteField("set", 4),
+        XByteField("fieldcode", 0),
+        XByteField("fieldinstance", 0),
+        XByteField("msbmask", 0),
+        XByteField("lsbmask", 0),
+        XShortField("value", 0),
+        ]
+
+class PortIngressRuleResultInsert(Packet):
+    """ Variable Descriptor: Port Ingress Rule Result Insert """
+    name = "Variable Descriptor: Port Ingress Rule Result Insert"
+    fields_desc = [
+        XByteField("branch", 0xD7),
+        XShortField("leaf", 0x0501),
+        ByteField("length", 4),
+        XByteField("result", 3),
+        XByteField("insert", 7),
+        XByteField("fieldcode", 0),
+        XByteField("fieldinstance", 0),
+        ]
+
 class PortIngressRuleTerminator(Packet):
     """ Variable Descriptor: Port Ingress Rule Terminator """
     name = "Variable Descriptor: Port Ingress Rule Terminator"
@@ -914,7 +952,7 @@
     name = "Variable Descriptor: Delete Port Ingress Rule"
     fields_desc = [XByteField("branch", 0xD9),
                    XShortField("leaf", 0x0503),
-                   XByteField("length", 1),
+                   XByteField("length", 0x80),
                    XByteField("value", 0),
                    ]
 
diff --git a/voltha/adapters/tibit_olt/tibit_olt.py b/voltha/adapters/tibit_olt/tibit_olt.py
index a871cc9..6a0ff9e 100644
--- a/voltha/adapters/tibit_olt/tibit_olt.py
+++ b/voltha/adapters/tibit_olt/tibit_olt.py
@@ -41,7 +41,6 @@
 from voltha.protos.device_pb2 import DeviceType, DeviceTypes
 from voltha.protos.health_pb2 import HealthStatus
 from voltha.protos.common_pb2 import LogLevel, ConnectStatus
-
 from voltha.protos.common_pb2 import OperStatus, AdminState
 
 from voltha.protos.logical_device_pb2 import LogicalDevice, LogicalPort
@@ -52,11 +51,14 @@
 from scapy.packet import Packet, bind_layers
 from scapy.fields import StrField
 
-from EOAM import EOAM_MULTICAST_ADDRESS
-
 log = structlog.get_logger()
 
-is_tibit_frame = BpfProgramFilter('ether[12:2] = 0x9001')
+# Match on the MGMT VLAN, Priority 7
+TIBIT_MGMT_VLAN=4090
+TIBIT_MGMT_PRIORITY=7
+frame_match = 'ether[14:2] = 0x{:01x}{:03x}'.format(TIBIT_MGMT_PRIORITY << 1, TIBIT_MGMT_VLAN)
+is_tibit_frame = BpfProgramFilter(frame_match)
+#is_tibit_frame = lambda x: True
 
 # To be removed in favor of OAM
 class TBJSON(Packet):
@@ -64,6 +66,7 @@
     name = "TBJSON"
     fields_desc = [StrField("data", default="")]
 
+bind_layers(Ether, TBJSON, type=0x9001)
 
 @implementer(IAdapterInterface)
 class TibitOltAdapter(object):
@@ -89,7 +92,8 @@
         )
         self.interface = registry('main').get_args().interface
         self.io_port = None
-        self.incoming_queues = {}  # mac_address -> DeferredQueue()
+        self.incoming_queues = {}  # OLT mac_address -> DeferredQueue()
+        self.device_ids = {}  # OLT mac_address -> device_id
 
     def start(self):
         log.debug('starting', interface=self.interface)
@@ -125,19 +129,22 @@
 
     @inlineCallbacks
     def _launch_device_activation(self, device):
-
         try:
             log.debug('launch_dev_activation')
             # prepare receive queue
             self.incoming_queues[device.mac_address] = DeferredQueue(size=100)
 
-            # send out ping to OLT device
+            # add mac_address to device_ids table
             olt_mac = device.mac_address
+            self.device_ids[olt_mac] = device.id
+
+            # send out ping to OLT device
             ping_frame = self._make_ping_frame(mac_address=olt_mac)
             self.io_port.send(ping_frame)
 
             # wait till we receive a response
-            # TODO add timeout mechanism so we can signal if we cannot reach device
+            ## TODO add timeout mechanism so we can signal if we cannot reach
+            ##device
             while True:
                 response = yield self.incoming_queues[olt_mac].get()
                 # verify response and if not the expected response
@@ -152,11 +159,12 @@
         jdev = json.loads(response.data[5:])
         device.root = True
         device.vendor = 'Tibit Communications, Inc.'
-        device.model = jdev['results']['device']
+        device.model = jdev.get('results', {}).get('device', 'DEVICE_UNKNOWN')
         device.hardware_version = jdev['results']['datecode']
         device.firmware_version = jdev['results']['firmware']
         device.software_version = jdev['results']['modelversion']
         device.serial_number = jdev['results']['manufacturer']
+
         device.connect_status = ConnectStatus.REACHABLE
         self.adapter_agent.update_device(device)
 
@@ -248,17 +256,23 @@
                 break
 
         jdev = json.loads(response.data[5:])
+        tibit_mac = ''
         for macid in jdev['results']:
             if macid['macid'] is None:
                 log.info('MAC ID is NONE %s' % str(macid['macid']))
             else:
-                log.info('activate-olt-for-onu-%s' % macid['macid'])
-            # TODO: report gemport and vlan_id
-            gemport, vlan_id = self._olt_side_onu_activation(int(macid['macid'][-3:]))
+                tibit_mac = '000c' + macid.get('macid', 'e2000000')[4:]
+                log.info('activate-olt-for-onu-%s' % tibit_mac)
+
+            # Convert from string to colon separated form
+            tibit_mac = ':'.join(s.encode('hex') for s in tibit_mac.decode('hex'))
+
+            gemport, vlan_id = self._olt_side_onu_activation(int(macid['macid'][-4:-2], 16))
             self.adapter_agent.child_device_detected(
                 parent_device_id=device.id,
                 parent_port_no=1,
                 child_device_type='tibit_onu',
+                mac_address = tibit_mac,
                 proxy_address=Device.ProxyAddress(
                     device_id=device.id,
                     channel_id=vlan_id
@@ -266,43 +280,59 @@
                 vlan=vlan_id
                 )
 
-    def _olt_side_onu_activation(self, seq):
+    def _olt_side_onu_activation(self, serial):
         """
         This is where if this was a real OLT, the OLT-side activation for
         the new ONU should be performed. By the time we return, the OLT shall
         be able to provide tunneled (proxy) communication to the given ONU,
         using the returned information.
         """
-        gemport = seq + 1
-        vlan_id = seq + 100
+        gemport = serial
+        vlan_id = serial + 200
         return gemport, vlan_id
 
     def _rcv_io(self, port, frame):
 
-        log.info('frame-recieved')
+        log.info('frame-received')
 
         # make into frame to extract source mac
         response = Ether(frame)
 
-        # enqueue incoming parsed frame to right device
-        self.incoming_queues[response.src].put(response)
+        if response.haslayer(Dot1Q):
+            # All responses from the OLT should have a TIBIT_MGMT_VLAN.
+            # Responses from the ONUs should have a TIBIT_MGMT_VLAN followed by a ONU CTAG
+            if response.getlayer(Dot1Q).type == 0x8100:
+                ## Responses from the ONU
+                ## Since the type of the first layer is 0x8100,
+                ## then the frame must have an inner tag layer
+                olt_mac = response.src
+                device_id = self.device_ids[olt_mac]
+                channel_id = response[Dot1Q:2].vlan
+                log.info('received_channel_id', channel_id=channel_id,
+                         device_id=device_id)
+
+                proxy_address=Device.ProxyAddress(
+                    device_id=device_id,
+                    channel_id=channel_id
+                    )
+                # pop dot1q header(s)
+                msg = response.payload.payload
+                self.adapter_agent.receive_proxied_message(proxy_address, msg)
+            else:
+                ## Respones from the OLT
+                ## enqueue incoming parsed frame to right device
+                self.incoming_queues[response.src].put(response)
 
     def _make_ping_frame(self, mac_address):
         # Create a json packet
         json_operation_str = '{\"operation\":\"version\"}'
-        frame = Ether()/TBJSON(data='json %s' % json_operation_str)
-        frame.type = int("9001", 16)
-        frame.dst = mac_address
-        bind_layers(Ether, TBJSON, type=0x9001)
+        frame = Ether(dst=mac_address)/Dot1Q(vlan=TIBIT_MGMT_VLAN, prio=TIBIT_MGMT_PRIORITY)/TBJSON(data='json %s' % json_operation_str)
         return str(frame)
 
     def _make_links_frame(self, mac_address):
         # Create a json packet
         json_operation_str = '{\"operation\":\"links\"}'
-        frame = Ether()/TBJSON(data='json %s' % json_operation_str)
-        frame.type = int("9001", 16)
-        frame.dst = mac_address
-        bind_layers(Ether, TBJSON, type=0x9001)
+        frame = Ether(dst=mac_address)/Dot1Q(vlan=TIBIT_MGMT_VLAN, prio=TIBIT_MGMT_PRIORITY)/TBJSON(data='json %s' % json_operation_str)
         return str(frame)
 
     def abandon_device(self, device):
@@ -319,14 +349,14 @@
         raise NotImplementedError()
 
     def send_proxied_message(self, proxy_address, msg):
-        log.info('send-proxied-message', proxy_address=proxy_address, msg=msg)
+        log.info('send-proxied-message', proxy_address=proxy_address)
         # TODO build device_id -> mac_address cache
         device = self.adapter_agent.get_device(proxy_address.device_id)
-        frame = Ether(dst=device.mac_address) / \
-                Dot1Q(vlan=4090) / \
-                Dot1Q(vlan=proxy_address.channel_id) / \
+        frame = Ether(dst='00:0c:e2:22:29:00') / \
+                Dot1Q(vlan=TIBIT_MGMT_VLAN, prio=TIBIT_MGMT_PRIORITY) / \
+                Dot1Q(vlan=proxy_address.channel_id, prio=TIBIT_MGMT_PRIORITY) / \
                 msg
-        # frame = Ether(dst=EOAM_MULTICAST_ADDRESS) / msg
+
         self.io_port.send(str(frame))
 
     def receive_proxied_message(self, proxy_address, msg):
diff --git a/voltha/adapters/tibit_onu/EOAM.py b/voltha/adapters/tibit_onu/EOAM.py
index 3f7e3c9..69c056e 100644
--- a/voltha/adapters/tibit_onu/EOAM.py
+++ b/voltha/adapters/tibit_onu/EOAM.py
@@ -11,18 +11,21 @@
 #                                                                          #
 #--------------------------------------------------------------------------#
 """ EOAM protocol implementation in scapy """
-from scapy.layers.inet import IP
 
-TIBIT_VERSION_NUMBER = '1.1.2'
+TIBIT_VERSION_NUMBER = '1.1.4'
 
 import argparse
 import logging
+import time
+from hexdump import hexdump
 
 logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
 from scapy.layers.l2 import Ether, Dot1Q
 from scapy.sendrecv import sendp
+from scapy.fields import PacketField
+from scapy.packet import bind_layers
 
-import fcntl  # for get hw address
+import fcntl, socket, struct # for get hw address
 
 # TODO should remove import *
 from EOAM_TLV import *
@@ -88,7 +91,7 @@
             PACKET.show()
             print '###[ Frame Length %d (before padding) ]###' % len(PACKET)
         if (self.hexdump == True):
-            print hexdump(PACKET)
+            print hexdump(str(PACKET))
         if (self.dryrun != True):
             sendp(PACKET, iface=self.interface)
             time.sleep(self.sleep)
@@ -116,7 +119,7 @@
         return ':'.join(['%02x' % ord(char) for char in info[18:24]])
 
 
-class EoamPayload(Packet):
+class EOAMPayload(Packet):
     name = 'EOAM Payload'
     fields_desc = [
         ByteEnumField("subtype", 0x03, SlowProtocolsSubtypeEnum),
@@ -127,15 +130,7 @@
         BitField("length", 0x00, 9)
     ]
 
-#    def get_request(self, TLV):
-#        return self.payload(CablelabsOUI()/DPoEOpcode_GetRequest()/TLV)
-
-#    def set_request(self, TLV):
-#        return self.payload(CablelabsOUI()/DPoEOpcode_SetRequest()/TLV)
-
-bind_layers(Ether, EoamPayload, type=0x8809)
-
-
+bind_layers(Ether, EOAMPayload, type=0x9001)
 
 if __name__ == "__main__":
     parser = argparse.ArgumentParser()
@@ -168,6 +163,8 @@
                         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')
 
     args = parser.parse_args()
 
@@ -190,7 +187,8 @@
         and not args.test
         and not args.test_add
         and not args.test_del
-        and not args.test_clr):
+        and not args.test_clr
+        and not args.test_eapol):
         print 'WARNING: *** No frames sent, please specify \'test\' or \'critical\', etc.  See --help'
 
 
@@ -212,3 +210,23 @@
     elif (args.test_del == True):
         print 'SET Delete Static MAC Address -- User Port Object'
         eoam.set_request(DeleteStaticMacAddress(mac=IGMP_MULTICAST_ADDRESS))
+
+    if (args.test_eapol == True):
+        print 'SET - Port Ingress Rule -- User Port Object -- Precedence 32 Match 0x888e'
+        eoam.set_request(DOLTObject()/
+                         PortIngressRuleHeader(precedence=32)/
+                         PortIngressRuleClauseMatchLength02(fieldcode=3, operator=1, match0=0x88, match1=0x8e)/
+                         PortIngressRuleResultForward()/
+                         PortIngressRuleResultSet(fieldcode=7, value=0x4090)/
+                         PortIngressRuleResultInsert(fieldcode=7)/
+                         PortIngressRuleTerminator()/
+                         AddPortIngressRule())
+
+        eoam.set_request(DOLTObject()/
+                         PortIngressRuleHeader(precedence=32)/
+                         PortIngressRuleClauseMatchLength02(fieldcode=3, operator=1, match0=0x88, match1=0x8e)/
+                         PortIngressRuleResultForward()/
+                         PortIngressRuleResultSet(fieldcode=7, value=0x4090)/
+                         PortIngressRuleResultInsert(fieldcode=7)/
+                         PortIngressRuleTerminator()/
+                         DeletePortIngressRule())
diff --git a/voltha/adapters/tibit_onu/EOAM_TLV.py b/voltha/adapters/tibit_onu/EOAM_TLV.py
index 0928189..00ff2d7 100644
--- a/voltha/adapters/tibit_onu/EOAM_TLV.py
+++ b/voltha/adapters/tibit_onu/EOAM_TLV.py
@@ -10,8 +10,9 @@
 #                                                                          #
 #--------------------------------------------------------------------------#
 
-from scapy.packet import *
-from scapy.fields import *
+from scapy.packet import Packet
+from scapy.fields import ByteEnumField, XShortField, XByteField, MACField, \
+    ByteField, BitEnumField, BitField
 
 # This library strives to be an implementation of the following standard:
 
@@ -20,7 +21,7 @@
 # This library may be used with PON devices for
 # configuration and provisioning.
 
-TIBIT_VERSION_NUMBER = '1.0.1'
+TIBIT_VERSION_NUMBER = '1.1.4'
 
 TLV_dictionary = {
     0x00: "End EOAMPDU",
@@ -143,6 +144,15 @@
                    XByteField("num", 0)
                    ]
 
+class DOLTObject(Packet):
+    """ Object Context: D-OLT Object """
+    name = "Object Context: D-OLT Object"
+    fields_desc = [XByteField("branch", 0xD6),
+                   XShortField("leaf", 0x0000),
+                   XByteField("length", 1),
+                   XByteField("num", 0)
+                   ]
+
 class NetworkPortObject(Packet):
     """ Object Context: Network Port Object """
     name = "Object Context: Network Port Object"
@@ -838,6 +848,35 @@
         XByteField("queuenum", 0),
         ]
 
+class PortIngressRuleResultSet(Packet):
+    """ Variable Descriptor: Port Ingress Rule Result Set """
+    name = "Variable Descriptor: Port Ingress Rule Result Set"
+    fields_desc = [
+        XByteField("branch", 0xD7),
+        XShortField("leaf", 0x0501),
+        ByteField("length", 8),
+        XByteField("result", 3),
+        XByteField("set", 4),
+        XByteField("fieldcode", 0),
+        XByteField("fieldinstance", 0),
+        XByteField("msbmask", 0),
+        XByteField("lsbmask", 0),
+        XShortField("value", 0),
+        ]
+
+class PortIngressRuleResultInsert(Packet):
+    """ Variable Descriptor: Port Ingress Rule Result Insert """
+    name = "Variable Descriptor: Port Ingress Rule Result Insert"
+    fields_desc = [
+        XByteField("branch", 0xD7),
+        XShortField("leaf", 0x0501),
+        ByteField("length", 4),
+        XByteField("result", 3),
+        XByteField("insert", 7),
+        XByteField("fieldcode", 0),
+        XByteField("fieldinstance", 0),
+        ]
+
 class PortIngressRuleTerminator(Packet):
     """ Variable Descriptor: Port Ingress Rule Terminator """
     name = "Variable Descriptor: Port Ingress Rule Terminator"
@@ -913,7 +952,7 @@
     name = "Variable Descriptor: Delete Port Ingress Rule"
     fields_desc = [XByteField("branch", 0xD9),
                    XShortField("leaf", 0x0503),
-                   XByteField("length", 1),
+                   XByteField("length", 0x80),
                    XByteField("value", 0),
                    ]
 
diff --git a/voltha/adapters/tibit_onu/tibit_onu.py b/voltha/adapters/tibit_onu/tibit_onu.py
index 4af7be3..1d7f279 100644
--- a/voltha/adapters/tibit_onu/tibit_onu.py
+++ b/voltha/adapters/tibit_onu/tibit_onu.py
@@ -38,7 +38,6 @@
 from voltha.protos.device_pb2 import DeviceType, DeviceTypes
 from voltha.protos.health_pb2 import HealthStatus
 from voltha.protos.common_pb2 import LogLevel, ConnectStatus
-
 from voltha.protos.common_pb2 import OperStatus, AdminState
 
 from voltha.protos.logical_device_pb2 import LogicalDevice, LogicalPort
@@ -53,15 +52,9 @@
 
 from EOAM_TLV import AddStaticMacAddress, DeleteStaticMacAddress
 from EOAM_TLV import ClearStaticMacTable
-from EOAM import EoamPayload, CablelabsOUI, DPoEOpcode_GetRequest
-
-
-# To be removed in favor of OAM
-class TBJSON(Packet):
-    """ TBJSON 'packet' layer. """
-    name = "TBJSON"
-    fields_desc = [StrField("data", default="")]
-
+from EOAM_TLV import DeviceId
+from EOAM import EOAMPayload, CablelabsOUI
+from EOAM import DPoEOpcode_GetRequest, DPoEOpcode_SetRequest
 
 @implementer(IAdapterInterface)
 class TibitOnuAdapter(object):
@@ -126,7 +119,6 @@
         device.hardware_version = 'fa161020'
         device.firmware_version = '16.10.01'
         device.software_version = '1.0'
-        device.mac_address = '00:01:02:03:04:05'
         device.serial_number = uuid4().hex
         device.connect_status = ConnectStatus.REACHABLE
         self.adapter_agent.update_device(device)
@@ -227,14 +219,13 @@
             _ = yield self.incoming_messages.get()
 
         # construct message
-        msg = EoamPayload(body=CablelabsOUI() /
-                               DPoEOpcode_GetRequest() /
-                               # MAC address for 230.10.10.10
-                               AddStaticMacAddress(mac='01:00:5e:0a:0a:0a') # device.mac_address)
+        msg = EOAMPayload(body=CablelabsOUI() /
+                          DPoEOpcode_GetRequest() /
+                          DeviceId()
                           )
 
         # send message
-        log.info('ONU-send-proxied-message-%s' % msg)
+        log.info('ONU-send-proxied-message')
         self.adapter_agent.send_proxied_message(device.proxy_address, msg)
 
         log.info('ONU-log incoming messages BEFORE')
diff --git a/voltha/extensions/eoam/EOAM.py b/voltha/extensions/eoam/EOAM.py
new file mode 100644
index 0000000..69c056e
--- /dev/null
+++ b/voltha/extensions/eoam/EOAM.py
@@ -0,0 +1,232 @@
+#!/usr/bin/env python
+#--------------------------------------------------------------------------#
+# Copyright (C) 2015 - 2016 by Tibit Communications, Inc.                  #
+# All rights reserved.                                                     #
+#                                                                          #
+#    _______ ____  _ ______                                                #
+#   /_  __(_) __ )(_)_  __/                                                #
+#    / / / / __  / / / /                                                   #
+#   / / / / /_/ / / / /                                                    #
+#  /_/ /_/_____/_/ /_/                                                     #
+#                                                                          #
+#--------------------------------------------------------------------------#
+""" EOAM protocol implementation in scapy """
+
+TIBIT_VERSION_NUMBER = '1.1.4'
+
+import argparse
+import logging
+import time
+from hexdump import hexdump
+
+logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
+from scapy.layers.l2 import Ether, Dot1Q
+from scapy.sendrecv import sendp
+from scapy.fields import PacketField
+from scapy.packet import bind_layers
+
+import fcntl, socket, struct # for get hw address
+
+# TODO should remove import *
+from EOAM_TLV import *
+
+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 """
+    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):
+        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(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))
+        PACKET/=SlowProtocolsSubtype()/FlagsBytes()/OAMPDU()
+        PACKET/=frame_body
+        PACKET/=EndOfPDU()
+        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]])
+
+
+class EOAMPayload(Packet):
+    name = 'EOAM Payload'
+    fields_desc = [
+        ByteEnumField("subtype", 0x03, SlowProtocolsSubtypeEnum),
+        XShortField("flags", 0x0050),
+        XByteField("opcode", 0xfe),
+        PacketField("body", None, Packet),
+        BitEnumField("type", 0x00, 7, TLV_dictionary),
+        BitField("length", 0x00, 9)
+    ]
+
+bind_layers(Ether, EOAMPayload, type=0x9001)
+
+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('-td', '--test_del', dest='test_del', 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')
+
+    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_del
+        and not args.test_clr
+        and not args.test_eapol):
+        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())
+
+    elif (args.test_add == True):
+        print 'SET Add Static MAC Address -- User Port Object'
+        eoam.set_request(AddStaticMacAddress(mac=IGMP_MULTICAST_ADDRESS))
+
+    elif (args.test_del == True):
+        print 'SET Delete Static MAC Address -- User Port Object'
+        eoam.set_request(DeleteStaticMacAddress(mac=IGMP_MULTICAST_ADDRESS))
+
+    if (args.test_eapol == True):
+        print 'SET - Port Ingress Rule -- User Port Object -- Precedence 32 Match 0x888e'
+        eoam.set_request(DOLTObject()/
+                         PortIngressRuleHeader(precedence=32)/
+                         PortIngressRuleClauseMatchLength02(fieldcode=3, operator=1, match0=0x88, match1=0x8e)/
+                         PortIngressRuleResultForward()/
+                         PortIngressRuleResultSet(fieldcode=7, value=0x4090)/
+                         PortIngressRuleResultInsert(fieldcode=7)/
+                         PortIngressRuleTerminator()/
+                         AddPortIngressRule())
+
+        eoam.set_request(DOLTObject()/
+                         PortIngressRuleHeader(precedence=32)/
+                         PortIngressRuleClauseMatchLength02(fieldcode=3, operator=1, match0=0x88, match1=0x8e)/
+                         PortIngressRuleResultForward()/
+                         PortIngressRuleResultSet(fieldcode=7, value=0x4090)/
+                         PortIngressRuleResultInsert(fieldcode=7)/
+                         PortIngressRuleTerminator()/
+                         DeletePortIngressRule())
diff --git a/voltha/extensions/eoam/EOAM_TLV.py b/voltha/extensions/eoam/EOAM_TLV.py
new file mode 100644
index 0000000..00ff2d7
--- /dev/null
+++ b/voltha/extensions/eoam/EOAM_TLV.py
@@ -0,0 +1,1072 @@
+#--------------------------------------------------------------------------#
+# Copyright (C) 2015 - 2016 by Tibit Communications, Inc.                  #
+# All rights reserved.                                                     #
+#                                                                          #
+#    _______ ____  _ ______                                                #
+#   /_  __(_) __ )(_)_  __/                                                #
+#    / / / / __  / / / /                                                   #
+#   / / / / /_/ / / / /                                                    #
+#  /_/ /_/_____/_/ /_/                                                     #
+#                                                                          #
+#--------------------------------------------------------------------------#
+
+from scapy.packet import Packet
+from scapy.fields import ByteEnumField, XShortField, XByteField, MACField, \
+    ByteField, BitEnumField, BitField
+
+# This library strives to be an implementation of the following standard:
+
+# DPoE-SP-OAMv1.0-IO8-140807 - DPoE OAM Extensions Specifications
+
+# This library may be used with PON devices for
+# configuration and provisioning.
+
+TIBIT_VERSION_NUMBER = '1.1.4'
+
+TLV_dictionary = {
+    0x00: "End EOAMPDU",
+    }
+
+SlowProtocolsSubtypeEnum = {0x03: "OAM"}
+
+### Multicast Action Flags
+MulticastActionFlagsEnum = {
+    0x02: "Deregister",
+    0x03: "Register"
+    }
+
+### Table 17 - DPoE Opcodes
+DPoEOpcodeEnum = {
+    0x01: "Get Request",
+    0x02: "Get Response",
+    0x03: "Set Request",
+    0x04: "Set Response",
+    0x05: "Dynamic IP Multicast Control",
+    0x06: "Multicast Register",
+    0x07: "Multicast Register Response",
+    }
+
+### Table 20 - DPoE Variable Response Codes
+DPoEVariableResponseCodes = {
+    0x80, "No Error",
+    0x81, "Too Long",
+    0x86, "Bad Parameters",
+    0x87, "No Resources",
+    0x88, "System Busy",
+    0xa0, "Undetermined Error",
+    0xa1, "Unsupported",
+    0xa2, "May Be Corrupted",
+    0xa3, "Hardware Failure",
+    0xa4, "Overflow",
+    }
+
+class SlowProtocolsSubtype(Packet):
+    """ Slow Protocols subtype"""
+    name = "Slow Protocols subtype"
+    fields_desc  = [ByteEnumField("subtype", 0x03, SlowProtocolsSubtypeEnum)]
+
+class FlagsBytes(Packet):
+    """ Two Bytes Reserved for 802.3 Flags"""
+    name = "FlagsBytes"
+    fields_desc  = [XShortField("flags", 0x0050)]
+
+class OAMPDU(Packet):
+    """ OAMPDU code: Organization Specific"""
+    name = "OAMPDU code: Organization Specific"
+    fields_desc  = [XByteField("opcode", 0xfe)]
+
+class CablelabsOUI(Packet):
+    """ Organizationally Unique Identifier (Cablelabs)"""
+    name = "Organizationally Unique Identifier (Cablelabs)"
+    fields_desc  = [XByteField("oui0", 0x00),
+                    XByteField("oui1", 0x10),
+                    XByteField("oui2", 0x00)]
+
+class BroadcomOUI(Packet):
+    """ Organizationally Unique Identifier (Broadcom)"""
+    name = "Organizationally Unique Identifier (Broadcom)"
+    fields_desc  = [XByteField("oui0", 0x00),
+                    XByteField("oui1", 0x0D),
+                    XByteField("oui2", 0xB6)]
+
+class DPoEOpcode_GetRequest(Packet):
+    """ DPoE Opcode"""
+    name = "DPoE Opcode"
+    fields_desc  = [ByteEnumField("opcode", 0x01, DPoEOpcodeEnum)]
+
+class DPoEOpcode_SetRequest(Packet):
+    """ DPoE Opcode"""
+    name = "DPoE Opcode"
+    fields_desc  = [ByteEnumField("opcode", 0x03, DPoEOpcodeEnum)]
+
+class DPoEOpcode_MulticastRegister(Packet):
+    """ DPoE Opcode"""
+    name = "DPoE Opcode"
+    fields_desc  = [ByteEnumField("opcode", 0x06, DPoEOpcodeEnum)]
+
+class DPoEOpcode_MulticastRegisterResponse(Packet):
+    """ DPoE Opcode"""
+    name = "DPoE Opcode"
+    fields_desc  = [ByteEnumField("opcode", 0x07, DPoEOpcodeEnum)]
+
+class MulticastRegisterSetSumitomo01(Packet):
+    """ Multicast Register: Multicast Register Set Sumitomo 01 """
+    name = "Multicast Register: Multicast Register Set Sumitomo 01"
+    fields_desc = [ByteEnumField("ActionFlags", 0x02, MulticastActionFlagsEnum),
+                   XShortField("MulticastLink", 0xfffe),
+                   XShortField("UnicastLink", 0x43dc),
+                   ]
+
+class MulticastRegisterSetSumitomo02(Packet):
+    """ Multicast Register: Multicast Register Set Sumitomo 02 """
+    name = "Multicast Register: Multicast Register Set Sumitomo 02"
+    fields_desc = [ByteEnumField("ActionFlags", 0x03, MulticastActionFlagsEnum),
+                   XShortField("MulticastLink", 0x43dd),
+                   XShortField("UnicastLink", 0x43dc),
+                   ]
+
+class MulticastRegisterSet(Packet):
+    """ Multicast Register: Multicast Register Set """
+    name = "Multicast Register: Multicast Register Set"
+    fields_desc = [ByteEnumField("ActionFlags", 0x03, MulticastActionFlagsEnum),
+                   XShortField("MulticastLink", 0x0000),
+                   XShortField("UnicastLink", 0x0000),
+                   ]
+####
+#### PORT OBJECTS
+####
+class DONUObject(Packet):
+    """ Object Context: D-ONU Object """
+    name = "Object Context: D-ONU Object"
+    fields_desc = [XByteField("branch", 0xD6),
+                   XShortField("leaf", 0x0000),
+                   XByteField("length", 1),
+                   XByteField("num", 0)
+                   ]
+
+class DOLTObject(Packet):
+    """ Object Context: D-OLT Object """
+    name = "Object Context: D-OLT Object"
+    fields_desc = [XByteField("branch", 0xD6),
+                   XShortField("leaf", 0x0000),
+                   XByteField("length", 1),
+                   XByteField("num", 0)
+                   ]
+
+class NetworkPortObject(Packet):
+    """ Object Context: Network Port Object """
+    name = "Object Context: Network Port Object"
+    fields_desc = [XByteField("branch", 0xD6),
+                   XShortField("leaf", 0x0001),
+                   XByteField("length", 1),
+                   XByteField("num", 0)
+                   ]
+
+class UnicastLogicalLink(Packet):
+    """ Object Context: Unicast Logical Link """
+    name = "Object Context: Unicast Logical Link"
+    fields_desc = [XByteField("branch", 0xD6),
+                   XShortField("leaf", 0x0002),
+                   XByteField("length", 1),
+                   XByteField("number", 0)
+                   ]
+
+class UserPortObject(Packet):
+    """ Object Context: User Port Object """
+    name = "Object Context: User Port Object"
+    fields_desc = [XByteField("branch", 0xD6),
+                   XShortField("leaf", 0x0003),
+                   XByteField("length", 1),
+                   XByteField("number", 0)
+                   ]
+
+class QueueObject(Packet):
+    """ Object Context: Queue Object """
+    name = "Object Context: Queue Object"
+    fields_desc = [XByteField("branch", 0xD6),
+                   XShortField("leaf", 0x0004),
+                   XByteField("length", 2),
+                   XByteField("instance", 0),
+                   XByteField("number", 0)
+                   ]
+
+
+####
+#### 0x09 - BRANCH ATTRIBUTES
+####
+class PhyAdminControl(Packet):
+    """ Variable Descriptor: Phy Admin Control """
+    name = "Variable Descriptor: Phy Admin Control"
+    fields_desc = [XByteField("branch", 0x09),
+                   XShortField("leaf", 0x0005),
+                   ]
+
+class PhyAdminControlEnableSet(Packet):
+    """ Variable Descriptor: Phy Admin Control Enable """
+    name = "Variable Descriptor: Phy Admin Control Enable"
+    fields_desc = [XByteField("branch", 0x09),
+                   XShortField("leaf", 0x0005),
+                   XByteField("length", 1),
+                   XByteField("value", 2)
+                   ]
+
+class PhyAdminControlDisableSet(Packet):
+    """ Variable Descriptor: Phy Admin Control Disable """
+    name = "Variable Descriptor: Phy Admin Control Disable"
+    fields_desc = [XByteField("branch", 0x09),
+                   XShortField("leaf", 0x0005),
+                   XByteField("length", 1),
+                   XByteField("value", 1)
+                   ]
+
+####
+#### 0xd7 - BRANCH ATTRIBUTES
+####
+class DeviceId(Packet):
+    """ Variable Descriptor: Device ID """
+    name = "Variable Descriptor: Device ID"
+    fields_desc = [XByteField("branch", 0xD7),
+                   XShortField("leaf", 0x0002)]
+
+class FirmwareInfo(Packet):
+    """ Variable Descriptor: Firmware Info """
+    name = "Variable Descriptor: Firmware Info"
+    fields_desc = [XByteField("branch", 0xD7),
+                   XShortField("leaf", 0x0003)]
+
+class ChipsetInfo(Packet):
+    """ Variable Descriptor: Chipset Info """
+    name = "Variable Descriptor: Chipset Info"
+    fields_desc = [XByteField("branch", 0xD7),
+                   XShortField("leaf", 0x0004)]
+
+class DateOfManufacture(Packet):
+    """ Variable Descriptor: Date of Manufacture """
+    name = "Variable Descriptor: Date of Manufacture"
+    fields_desc = [XByteField("branch", 0xD7),
+                   XShortField("leaf", 0x0005)]
+
+class MaxLogicalLinks(Packet):
+    """ Variable Descriptor: Max Logical Links """
+    name = "Variable Descriptor: Max Logical Links"
+    fields_desc = [XByteField("branch", 0xD7),
+                   XShortField("leaf", 0x0007)]
+
+class NumberOfNetworkPorts(Packet):
+    """ Variable Descriptor: Number of Network Ports """
+    name = "Variable Descriptor: Number of Network Ports"
+    fields_desc = [XByteField("branch", 0xD7),
+                   XShortField("leaf", 0x0008)]
+
+class NumberOfS1Interfaces(Packet):
+    """ Variable Descriptor: Number of S1 Interfaces """
+    name = "Variable Descriptor: Number of S1 Interfaces"
+    fields_desc = [XByteField("branch", 0xD7),
+                   XShortField("leaf", 0x0009)]
+
+class DONUPacketBuffer(Packet):
+    """ Variable Descriptor: D-ONU Packet Buffer """
+    name = "Variable Descriptor: D-ONU Packet Buffer"
+    fields_desc = [XByteField("branch", 0xD7),
+                   XShortField("leaf", 0x000a)]
+
+class ReportThresholds(Packet):
+    """ Variable Descriptor: Report Thresholds """
+    name = "Variable Descriptor: Report Thresholds"
+    fields_desc = [XByteField("branch", 0xD7),
+                   XShortField("leaf", 0x000b),
+                   ]
+
+class ReportThresholdsSet(Packet):
+    """ Variable Descriptor: Report Thresholds Set """
+    name = "Variable Descriptor: Report Thresholds Set"
+    fields_desc = [XByteField("branch", 0xD7),
+                   XShortField("leaf", 0x000b),
+                   XByteField("length", 0x0a),
+                   XByteField("num_queue_sets", 4),
+                   XByteField("values", 1),
+                   XShortField("threshold0", 0x800),
+                   XShortField("threshold1", 0x1000),
+                   XShortField("threshold2", 0x1800),
+                   XShortField("threshold3", 0x2000),
+                   ]
+
+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),
+                   XShortField("leaf", 0x000b),
+                   XByteField("length", 0x0a),
+                   XByteField("num_queue_sets", 4),
+                   XByteField("values", 1),
+                   XShortField("threshold0", 0x2800),
+                   XShortField("threshold1", 0x5000),
+                   XShortField("threshold2", 0x7800),
+                   XShortField("threshold3", 0xa000),
+                   ]
+
+class LogicalLinkForwarding(Packet):
+    """ Variable Descriptor: Logical Link Forwarding """
+    name = "Variable Descriptor: Logical Link Forwarding"
+    fields_desc = [XByteField("branch", 0xD7),
+                   XShortField("leaf", 0x000c),
+                   ]
+
+class OamFrameRate(Packet):
+    """ Variable Descriptor: OAM Frame Rate """
+    name = "Variable Descriptor: OAM Frame Rate"
+    fields_desc = [XByteField("branch", 0xD7),
+                   XShortField("leaf", 0x000d),
+                   ]
+
+class OamFrameRateSet(Packet):
+    """ Variable Descriptor: OAM Frame Rate """
+    name = "Variable Descriptor: OAM Frame Rate"
+    fields_desc = [XByteField("branch", 0xD7),
+                   XShortField("leaf", 0x000d),
+                   XByteField("length", 2),
+                   XByteField("max", 12),
+                   XByteField("min", 10),
+                   ]
+
+class OnuManufacturerOrganizationName(Packet):
+    """ Variable Descriptor: ONU Manufacturer Organization Name """
+    name = "Variable Descriptor: ONU Manufacturer Organization Name"
+    fields_desc = [XByteField("branch", 0xD7),
+                   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),
+                   XShortField("leaf", 0x000f),
+                   ]
+
+class VendorName(Packet):
+    """ Variable Descriptor: Vendor Name """
+    name = "Variable Descriptor: Vendor Name"
+    fields_desc = [XByteField("branch", 0xD7),
+                   XShortField("leaf", 0x0011),
+                   ]
+
+class ModelNumber(Packet):
+    """ Variable Descriptor: Model Number """
+    name = "Variable Descriptor: Model Number"
+    fields_desc = [XByteField("branch", 0xD7),
+                   XShortField("leaf", 0x0012),
+                   ]
+
+class HardwareVersion(Packet):
+    """ Variable Descriptor: Hardware Version """
+    name = "Variable Descriptor: Hardware Version"
+    fields_desc = [XByteField("branch", 0xD7),
+                   XShortField("leaf", 0x0013),
+                   ]
+
+class EponMode(Packet):
+    """ Variable Descriptor: EPON Mode """
+    name = "Variable Descriptor: EPON Mode"
+    fields_desc = [XByteField("branch", 0xD7),
+                   XShortField("leaf", 0x0014),
+                   ]
+
+class DynamicAddressAgeLimit(Packet):
+    """ Variable Descriptor: Dynamic Address Age Limit """
+    name = "Variable Descriptor: Dynamic Address Age Limit"
+    fields_desc = [XByteField("branch", 0xD7),
+                   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),
+                   XShortField("leaf", 0x0102),
+                   XByteField("length", 2),
+                   XShortField("value", 0x0000),
+                   ]
+
+class DynamicMacTable(Packet):
+    """ Variable Descriptor: Dynamic MAC Table """
+    name = "Variable Descriptor: Dynamic MAC Table"
+    fields_desc = [XByteField("branch", 0xD7),
+                   XShortField("leaf", 0x0103),
+                   ]
+
+class StaticMacTable(Packet):
+    """ Variable Descriptor: Static MAC Table """
+    name = "Variable Descriptor: Static MAC Table"
+    fields_desc = [XByteField("branch", 0xD7),
+                   XShortField("leaf", 0x0104),
+                   ]
+
+class SourceAddressAdmissionControl(Packet):
+    """ Variable Descriptor: Source Address Admission Control """
+    name = "Variable Descriptor: Source Address Admission Control"
+    fields_desc = [XByteField("branch", 0xD7),
+                   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),
+                   XShortField("leaf", 0x0106),
+                   XByteField("length", 1),
+                   XByteField("value", 1),
+                   ]
+
+class MacLearningMinGuarantee(Packet):
+    """ Variable Descriptor: MAC Learning MIN Guarantee """
+    name = "Variable Descriptor: MAC Learning MIN Guarantee"
+    fields_desc = [XByteField("branch", 0xD7),
+                   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),
+                   XShortField("leaf", 0x0107),
+                   XByteField("length", 2),
+                   XShortField("value", 0),
+                   ]
+
+class MacLearningMaxAllowed(Packet):
+    """ Variable Descriptor: MAC Learning MAX Allowed """
+    name = "Variable Descriptor: MAC Learning MAX Allowed"
+    fields_desc = [XByteField("branch", 0xD7),
+                   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),
+                   XShortField("leaf", 0x0108),
+                   XByteField("length", 2),
+                   XShortField("value", 0x0010),
+                   ]
+
+class MacLearningAggregateLimit(Packet):
+    """ Variable Descriptor: MAC Learning Aggregate Limit """
+    name = "Variable Descriptor: MAC Learning Aggregate Limit"
+    fields_desc = [XByteField("branch", 0xD7),
+                   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),
+                   XShortField("leaf", 0x0109),
+                   XByteField("length", 2),
+                   XShortField("value", 0x0040),
+                   ]
+
+class FloodUnknown(Packet):
+    """ Variable Descriptor: Flood Unknown """
+    name = "Variable Descriptor: Flood Unknown"
+    fields_desc = [XByteField("branch", 0xD7),
+                   XShortField("leaf", 0x010b),
+                   ]
+
+class FloodUnknownSet(Packet):
+    """ Variable Descriptor: Flood Unknown Set """
+    name = "Variable Descriptor: Flood Unknown Set"
+    fields_desc = [XByteField("branch", 0xD7),
+                   XShortField("leaf", 0x010b),
+                   XByteField("length", 1),
+                   XByteField("value", 1),
+                   ]
+
+class LocalSwitching(Packet):
+    """ Variable Descriptor: Local Switching """
+    name = "Variable Descriptor: Local Switching"
+    fields_desc = [XByteField("branch", 0xD7),
+                   XShortField("leaf", 0x010c),
+                   ]
+
+class LocalSwitchingSet(Packet):
+    """ Variable Descriptor: Local Switching Set """
+    name = "Variable Descriptor: Local Switching Set"
+    fields_desc = [XByteField("branch", 0xD7),
+                   XShortField("leaf", 0x010c),
+                   XByteField("length", 1),
+                   XByteField("value", 0),
+                   ]
+
+class LLIDQueueConfiguration(Packet):
+    """ Variable Descriptor: LLID Queue Configuration """
+    name = "Variable Descriptor: LLID Queue Configuration"
+    fields_desc = [XByteField("branch", 0xD7),
+                   XShortField("leaf", 0x010d),
+                   ]
+
+class LLIDQueueConfigurationSet(Packet):
+    """ Variable Descriptor: LLID Queue Configuration """
+    name = "Variable Descriptor: LLID Queue Configuration"
+    fields_desc = [XByteField("branch", 0xD7),
+                   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),
+                   ]
+
+class FirmwareFilename(Packet):
+    """ Variable Descriptor: Firmware Filename """
+    name = "Variable Descriptor: Firmware Filename"
+    fields_desc = [XByteField("branch", 0xD7),
+                   XShortField("leaf", 0x010e),
+                   ]
+####
+#### 0xD9 - MAC Table Operations - Dynamic and Static
+####
+
+class ClearDynamicMacTable(Packet):
+    """ Variable Descriptor: Clear Dynamic MAC Table """
+    name = "Variable Descriptor: Clear Dynamic MAC Table"
+    fields_desc = [XByteField("branch", 0xD9),
+                   XShortField("leaf", 0x0101),
+                   ]
+
+class AddDynamicMacAddress(Packet):
+    """ Variable Descriptor: Add Dynamic MAC Address """
+    name = "Variable Descriptor: Add Dynamic MAC Address"
+    fields_desc = [XByteField("branch", 0xD9),
+                   XShortField("leaf", 0x0102),
+                   ]
+
+class DeleteDynamicMacAddress(Packet):
+    """ Variable Descriptor: Delete Dynamic MAC Address """
+    name = "Variable Descriptor: Delete Dynamic MAC Address"
+    fields_desc = [XByteField("branch", 0xD9),
+                   XShortField("leaf", 0x0103),
+                   ]
+
+class ClearStaticMacTable(Packet):
+    """ Variable Descriptor: Clear Static MAC Table """
+    name = "Variable Descriptor: Clear Static MAC Table"
+    fields_desc = [XByteField("branch", 0xD9),
+                   XShortField("leaf", 0x0104),
+                   ]
+
+class AddStaticMacAddress(Packet):
+    """ Variable Descriptor: Add Static MAC Address """
+    name = "Variable Descriptor: Add Static MAC Address"
+    fields_desc = [XByteField("branch", 0xD9),
+                   XShortField("leaf", 0x0105),
+                   ByteField("length", 6),
+                   MACField("mac", "01:00:5e:00:00:00"),
+                   ]
+
+class DeleteStaticMacAddress(Packet):
+    """ Variable Descriptor: Delete Static MAC Address """
+    name = "Variable Descriptor: Delete Static MAC Address"
+    fields_desc = [XByteField("branch", 0xD9),
+                   XShortField("leaf", 0x0106),
+                   ByteField("length", 6),
+                   MACField("mac", "01:00:5e:00:00:00"),
+                   ]
+
+####
+#### 0xd7 - STATISTICS
+####
+
+class RxFrame_512_1023(Packet):
+    """ Variable Descriptor: RxFrame_512_1023 """
+    name = "Variable Descriptor: RxFrame_512_1023"
+    fields_desc = [XByteField("branch", 0xD7),
+                   XShortField("leaf", 0x0208),
+                   ]
+
+class TxFrame_512_1023(Packet):
+    """ Variable Descriptor: TxFrame_512_1023 """
+    name = "Variable Descriptor: TxFrame_512_1023"
+    fields_desc = [XByteField("branch", 0xD7),
+                   XShortField("leaf", 0x020f),
+                   ]
+
+class FramesDropped(Packet):
+    """ Variable Descriptor: Frames Dropped """
+    name = "Variable Descriptor: Frames Dropped"
+    fields_desc = [XByteField("branch", 0xD7),
+                   XShortField("leaf", 0x0214),
+                   ]
+
+class BytesDropped(Packet):
+    """ Variable Descriptor: Bytes Dropped """
+    name = "Variable Descriptor: Bytes Dropped"
+    fields_desc = [XByteField("branch", 0xD7),
+                   XShortField("leaf", 0x0215),
+                   ]
+
+class TxBytesUnused(Packet):
+    """ Variable Descriptor: Tx Bytes Unused """
+    name = "Variable Descriptor: Tx Bytes Unused"
+    fields_desc = [XByteField("branch", 0xD7),
+                   XShortField("leaf", 0x0217),
+                   ]
+
+class TxL2Errors(Packet):
+    """ Variable Descriptor: TxL2Errors """
+    name = "Variable Descriptor: TxL2Errors"
+    fields_desc = [XByteField("branch", 0xD7),
+                   XShortField("leaf", 0x0235),
+                   ]
+
+class RxL2Errors(Packet):
+    """ Variable Descriptor: RxL2Errors """
+    name = "Variable Descriptor: RxL2Errors"
+    fields_desc = [XByteField("branch", 0xD7),
+                   XShortField("leaf", 0x0236),
+                   ]
+
+####
+#### 0xD7 - Alarm Reporting
+####
+
+class AlarmReporting(Packet):
+    """ Variable Descriptor: Alarm Reporting """
+    name = "Variable Descriptor: Alarm Reporting"
+    fields_desc = [XByteField("branch", 0xD7),
+                   XShortField("leaf", 0x0303),
+                   ]
+
+class AlarmReportingSet(Packet):
+    """ Variable Descriptor: Alarm Reporting Set """
+    name = "Variable Descriptor: Alarm Reporting Set"
+    fields_desc = [XByteField("branch", 0xD7),
+                   XShortField("leaf", 0x0303),
+                   XByteField("length", 6),
+                   XShortField("LOS", 0x1101),
+                   XShortField("KeyExchange", 0x1201),
+                   XShortField("PortDisbled", 0x2101),
+                   ]
+
+####
+#### 0xD7 - Encryption/ FEC/ and Queue CIR/EIR
+####
+class EncryptionMode(Packet):
+    """ Variable Descriptor: Encryption Mode """
+    name = "Variable Descriptor: Encryption Mode"
+    fields_desc = [XByteField("branch", 0xD7),
+                   XShortField("leaf", 0x0402),
+                   ]
+
+class EncryptionModeSet(Packet):
+    """ Variable Descriptor: Encryption Mode Set """
+    name = "Variable Descriptor: Encryption Mode Set"
+    fields_desc = [XByteField("branch", 0xD7),
+                   XShortField("leaf", 0x0402),
+                   XByteField("length", 1),
+                   XByteField("value", 0),
+                   ]
+
+class IpmcForwardingRuleConfiguration(Packet):
+    """ Variable Descriptor: IPMC Forwarding Rule Configuration """
+    name = "Variable Descriptor: IPMC Forwarding Rule Configuration"
+    fields_desc = [XByteField("branch", 0xD7),
+                   XShortField("leaf", 0x0505),
+                   XByteField("length", 2),
+                   XShortField("value", 0x0000),
+                   ]
+
+class QueueCommittedInformationRate(Packet):
+    """ Variable Descriptor: Queue Committed Information Rate """
+    name = "Variable Descriptor: Queue Committed Information Rate"
+    fields_desc = [XByteField("branch", 0xD7),
+                   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),
+                   XShortField("leaf", 0x0604),
+                   XByteField("length", 6),
+                   XShortField("burst", 0x0fff),
+                   XShortField("CIR_UPPER", 0x0000),
+                   XShortField("CIR_LOWER", 0xffff),
+                   ]
+
+class FECMode(Packet):
+    """ Variable Descriptor: FEC Mode """
+    name = "Variable Descriptor: FEC Mode"
+    fields_desc = [XByteField("branch", 0xD7),
+                   XShortField("leaf", 0x0605),
+                   ]
+
+class FECModeSet(Packet):
+    """ Variable Descriptor: FEC Mode """
+    name = "Variable Descriptor: FEC Mode"
+    fields_desc = [XByteField("branch", 0xD7),
+                   XShortField("leaf", 0x0605),
+                   ]
+
+class MediaType(Packet):
+    """ Variable Descriptor: Media Type """
+    name = "Variable Descriptor: Media Type"
+    fields_desc = [XByteField("branch", 0xD7),
+                   XShortField("leaf", 0x0822),
+                   ]
+
+
+####
+#### 0xD7 - Port Ingress Rules
+####
+class PortIngressRule(Packet):
+    """ Variable Descriptor: Port Ingress Rule """
+    name = "Variable Descriptor: Port Ingress Rule"
+    fields_desc = [XByteField("branch", 0xD7),
+                   XShortField("leaf", 0x0501),
+                   ]
+
+class PortIngressRuleHeader(Packet):
+    """ Variable Descriptor: Port Ingress Rule Header """
+    name = "Variable Descriptor: Port Ingress Rule Header"
+    fields_desc = [
+        XByteField("branch", 0xD7),
+        XShortField("leaf", 0x0501),
+        ByteField("length", 2),
+        XByteField("header", 1),
+        XByteField("precedence", 00),
+        ]
+
+class PortIngressRuleClauseMatchLength00(Packet):
+    """ Variable Descriptor: Port Ingress Rule Clause """
+    name = "Variable Descriptor: Port Ingress Rule Clause"
+    fields_desc = [
+        XByteField("branch", 0xD7),
+        XShortField("leaf", 0x0501),
+        ByteField("length", 7),
+        XByteField("clause", 2),
+        XByteField("fieldcode", 0),
+        XByteField("fieldinstance", 0),
+        XByteField("msbmask", 0),
+        XByteField("lsbmask", 0),
+        XByteField("operator", 0),
+        XByteField("matchlength", 0),
+        ]
+
+class PortIngressRuleClauseMatchLength01(Packet):
+    """ Variable Descriptor: Port Ingress Rule Clause """
+    name = "Variable Descriptor: Port Ingress Rule Clause"
+    fields_desc = [
+        XByteField("branch", 0xD7),
+        XShortField("leaf", 0x0501),
+        ByteField("length", 8),
+        XByteField("clause", 2),
+        XByteField("fieldcode", 0),
+        XByteField("fieldinstance", 0),
+        XByteField("msbmask", 0),
+        XByteField("lsbmask", 0),
+        XByteField("operator", 0),
+        XByteField("matchlength", 1),
+        XByteField("match0", 0),
+        ]
+
+class PortIngressRuleClauseMatchLength02(Packet):
+    """ Variable Descriptor: Port Ingress Rule Clause """
+    name = "Variable Descriptor: Port Ingress Rule Clause"
+    fields_desc = [
+        XByteField("branch", 0xD7),
+        XShortField("leaf", 0x0501),
+        ByteField("length", 9),
+        XByteField("clause", 2),
+        XByteField("fieldcode", 0),
+        XByteField("fieldinstance", 0),
+        XByteField("msbmask", 0),
+        XByteField("lsbmask", 0),
+        XByteField("operator", 0),
+        XByteField("matchlength", 2),
+        XByteField("match0", 0),
+        XByteField("match1", 0),
+        ]
+
+
+class PortIngressRuleClauseMatchLength06(Packet):
+    """ Variable Descriptor: Port Ingress Rule Clause """
+    name = "Variable Descriptor: Port Ingress Rule Clause"
+    fields_desc = [
+        XByteField("branch", 0xD7),
+        XShortField("leaf", 0x0501),
+        ByteField("length", 13),
+        XByteField("clause", 2),
+        XByteField("fieldcode", 0),
+        XByteField("fieldinstance", 0),
+        XByteField("msbmask", 0),
+        XByteField("lsbmask", 0),
+        XByteField("operator", 0),
+        XByteField("matchlength", 6),
+        XByteField("match0", 0x01),
+        XByteField("match1", 0x80),
+        XByteField("match2", 0xc2),
+        XByteField("match3", 0x00),
+        XByteField("match4", 0x00),
+        XByteField("match5", 0x00),
+        ]
+
+class PortIngressRuleResultForward(Packet):
+    """ Variable Descriptor: Port Ingress Rule Result Forward """
+    name = "Variable Descriptor: Port Ingress Rule Result Forward"
+    fields_desc = [
+        XByteField("branch", 0xD7),
+        XShortField("leaf", 0x0501),
+        ByteField("length", 2),
+        XByteField("result", 3),
+        XByteField("forward", 2),
+        ]
+
+class PortIngressRuleResultDiscard(Packet):
+    """ Variable Descriptor: Port Ingress Rule Result Discard """
+    name = "Variable Descriptor: Port Ingress Rule Result Discard"
+    fields_desc = [
+        XByteField("branch", 0xD7),
+        XShortField("leaf", 0x0501),
+        ByteField("length", 2),
+        XByteField("result", 3),
+        XByteField("discard", 1),
+        ]
+
+class PortIngressRuleResultQueue(Packet):
+    """ Variable Descriptor: Port Ingress Rule Result Queue """
+    name = "Variable Descriptor: Port Ingress Rule Result Queue"
+    fields_desc = [
+        XByteField("branch", 0xD7),
+        XShortField("leaf", 0x0501),
+        ByteField("length", 6),
+        XByteField("result", 3),
+        XByteField("queuerule", 3),
+        XShortField("objecttype", 0x0000),
+        XByteField("instance", 0),
+        XByteField("queuenum", 0),
+        ]
+
+class PortIngressRuleResultSet(Packet):
+    """ Variable Descriptor: Port Ingress Rule Result Set """
+    name = "Variable Descriptor: Port Ingress Rule Result Set"
+    fields_desc = [
+        XByteField("branch", 0xD7),
+        XShortField("leaf", 0x0501),
+        ByteField("length", 8),
+        XByteField("result", 3),
+        XByteField("set", 4),
+        XByteField("fieldcode", 0),
+        XByteField("fieldinstance", 0),
+        XByteField("msbmask", 0),
+        XByteField("lsbmask", 0),
+        XShortField("value", 0),
+        ]
+
+class PortIngressRuleResultInsert(Packet):
+    """ Variable Descriptor: Port Ingress Rule Result Insert """
+    name = "Variable Descriptor: Port Ingress Rule Result Insert"
+    fields_desc = [
+        XByteField("branch", 0xD7),
+        XShortField("leaf", 0x0501),
+        ByteField("length", 4),
+        XByteField("result", 3),
+        XByteField("insert", 7),
+        XByteField("fieldcode", 0),
+        XByteField("fieldinstance", 0),
+        ]
+
+class PortIngressRuleTerminator(Packet):
+    """ Variable Descriptor: Port Ingress Rule Terminator """
+    name = "Variable Descriptor: Port Ingress Rule Terminator"
+    fields_desc = [
+        XByteField("branch", 0xD7),
+        XShortField("leaf", 0x0501),
+        ByteField("length", 1),
+        XByteField("terminator", 0),
+        ]
+
+class CustomField(Packet):
+    """ Variable Descriptor: Custom Field """
+    name = "Variable Descriptor: Custom Field"
+    fields_desc = [XByteField("branch", 0xD7),
+                   XShortField("leaf", 0x0502),
+                   XByteField("length", 1),
+                   XByteField("value", 0),
+                   ]
+
+class CustomFieldEtherType(Packet):
+    """ Variable Descriptor: Custom Field EtherType """
+    name = "Variable Descriptor: Custom Field EtherType"
+    fields_desc = [XByteField("branch", 0xD7),
+                   XShortField("leaf", 0x0502),
+                   XByteField("length", 6),
+                   XByteField("fieldcode", 0x19),
+                   XByteField("layerselect", 2),
+                   XByteField("dwordoffset", 0),
+                   XByteField("lsb", 0),
+                   XByteField("width", 0x10),
+                   XByteField("numclauses", 0),
+                   ]
+
+class CustomFieldGenericL3(Packet):
+    """ Variable Descriptor: Custom Field Generic L3 """
+    name = "Variable Descriptor: Custom Field Generic L3"
+    fields_desc = [XByteField("branch", 0xD7),
+                   XShortField("leaf", 0x0502),
+                   XByteField("length", 6),
+                   XByteField("fieldcode", 0x1a),
+                   XByteField("layerselect", 8),
+                   XByteField("dwordoffset", 0),
+                   XByteField("lsb", 0x18),
+                   XByteField("width", 0x8),
+                   XByteField("numclauses", 0),
+                   ]
+
+####
+#### 0xD9 - Port Ingress Rules
+####
+
+class ClearPortIngressRules(Packet):
+    """ Variable Descriptor: Clear Port Ingress Rule """
+    name = "Variable Descriptor: Clear Port Ingress Rule"
+    fields_desc = [XByteField("branch", 0xD9),
+                   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),
+                   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),
+                   XShortField("leaf", 0x0503),
+                   XByteField("length", 0x80),
+                   XByteField("value", 0),
+                   ]
+
+####
+#### 0xd9 - BRANCH ATTRIBUTES
+####
+
+class EnableUserTraffic(Packet):
+    """ Variable Descriptor: Enable User Traffic """
+    name = "Variable Descriptor: Enable User Traffic"
+    fields_desc = [XByteField("branch", 0xD9),
+                   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)]
+
+class LoopbackEnable(Packet):
+    """ Variable Descriptor: Loopback Enable """
+    name = "Variable Descriptor: Loopback Enable"
+    fields_desc = [XByteField("branch", 0xD9),
+                   XShortField("leaf", 0x0603),
+                   XByteField("length", 1),
+                   XByteField("location", 0),
+                   ]
+
+class LoopbackDisable(Packet):
+    """ Variable Descriptor: Loopback Disable """
+    name = "Variable Descriptor: Loopback Disable"
+    fields_desc = [XByteField("branch", 0xD9),
+                   XShortField("leaf", 0x0604),
+                   XByteField("length", 1),
+                   XByteField("location", 0),
+                   ]
+
+class CurrentAlarmSummary(Packet):
+    """ Variable Descriptor: Current Alarm Summary """
+    name = "Variable Descriptor: Current Alarm Summary"
+    fields_desc = [XByteField("branch", 0xD9),
+                   XShortField("leaf", 0x0301)]
+
+
+##
+## Broadcom TLVs
+##
+class Broadcom07_7F_F1_Set01(Packet):
+    """ Variable Descriptor: Broadcom 0x07/0x7ff1 """
+    name = "Variable Descriptor: Broadcom 0x07/0x7ff1"
+    fields_desc = [XByteField("branch", 0x07),
+                   XShortField("leaf", 0x7ff1),
+                   XByteField("length", 2),
+                   XShortField("value0", 0x0101),
+                   ]
+
+class Broadcom07_7F_F1_Set02(Packet):
+    """ Variable Descriptor: Broadcom 0x07/0x7ff1 """
+    name = "Variable Descriptor: Broadcom 0x07/0x7ff1"
+    fields_desc = [XByteField("branch", 0x07),
+                   XShortField("leaf", 0x7ff1),
+                   XByteField("length", 7),
+                   XShortField("value0", 0x0201),
+                   XShortField("value1", 0x0000),
+                   XShortField("value2", 0x0107),
+                   XByteField("value3", 0xd0),
+                   ]
+
+class Broadcom07_7F_F1_Set03(Packet):
+    """ Variable Descriptor: Broadcom 0x07/0x7ff1 """
+    name = "Variable Descriptor: Broadcom 0x07/0x7ff1"
+    fields_desc = [XByteField("branch", 0x07),
+                   XShortField("leaf", 0x7ff1),
+                   XByteField("length", 7),
+                   XShortField("value0", 0x0301),
+                   XShortField("value1", 0x0000),
+                   XShortField("value2", 0x0100),
+                   XByteField("value3", 0xb8),
+                   ]
+
+class Broadcom07_7F_F1_Set04(Packet):
+    """ Variable Descriptor: Broadcom 0x07/0x7ff1 """
+    name = "Variable Descriptor: Broadcom 0x07/0x7ff1"
+    fields_desc = [XByteField("branch", 0x07),
+                   XShortField("leaf", 0x7ff1),
+                   XByteField("length", 1),
+                   XByteField("value0", 0x00),
+                   ]
+
+class Broadcom07_7F_F6_Set(Packet):
+    """ Variable Descriptor: Broadcom 0x07/0x7ff6 """
+    name = "Variable Descriptor: Broadcom 0x07/0x7ff6"
+    fields_desc = [XByteField("branch", 0x07),
+                   XShortField("leaf", 0x7ff6),
+                   XByteField("length", 2),
+                   XShortField("value0", 0x07d0),
+                   ]
+
+###
+### Clause 30 Attributes (0x07)
+###
+class Clause30AttributesMacEnable(Packet):
+    """ Variable Descriptor: Clause 30 Attributes MAC Enable """
+    name = "Variable Descriptor: Clause 30 Attributes MAC Enable"
+    fields_desc = [XByteField("branch", 0x07),
+                   XShortField("leaf", 0x001a),
+                   XByteField("length", 1),
+                   XByteField("value", 1),
+                   ]
+
+class EndOfPDU(Packet):
+    name = "End of EOAM PDU"
+    fields_desc = [BitEnumField("type", 0x00, 7, TLV_dictionary),
+                   BitField("length", 0x00, 9)]