Adding several updates to the Tibit Adapters
Change-Id: I15c7cf4fc4a1caaa67851fd8bab4fb2e592c20ba
diff --git a/voltha/adapters/tibit_olt/tibit_olt.py b/voltha/adapters/tibit_olt/tibit_olt.py
index 233f048..cdd2d1f 100644
--- a/voltha/adapters/tibit_olt/tibit_olt.py
+++ b/voltha/adapters/tibit_olt/tibit_olt.py
@@ -21,12 +21,21 @@
import time
from uuid import uuid4
import struct
+import re
import arrow
import structlog
-from scapy.fields import StrField
+from scapy.fields import StrField, PacketField, X3BytesField
from scapy.layers.l2 import Ether, Dot1Q
from scapy.packet import Packet, bind_layers
+
+from scapy.fields import ByteEnumField, XShortField, XByteField, MACField, \
+ ByteField, BitEnumField, BitField, ShortField
+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
@@ -34,7 +43,11 @@
from common.frameio.frameio import BpfProgramFilter, hexify
from voltha.adapters.interface import IAdapterInterface
-from voltha.extensions.eoam.EOAM import EOAMPayload, DPoEOpcode_SetRequest
+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_TLV import DOLTObject, \
NetworkToNetworkPortObject, OLTUnicastLogicalLink, \
PortIngressRuleClauseMatchLength01, AddStaticMacAddress, \
@@ -42,15 +55,34 @@
PortIngressRuleResultSet, PortIngressRuleResultInsert, \
PortIngressRuleResultCopy, PortIngressRuleResultReplace, \
PortIngressRuleResultDelete, PortIngressRuleResultOLTQueue, \
- PortIngressRuleResultOLTBroadcastQueue, \
- PortIngressRuleTerminator, AddPortIngressRule, CablelabsOUI, \
+ PortIngressRuleResultOLTBroadcastQueue, PortIngressRuleResultOLTEPONQueue, \
+ PortIngressRuleTerminator, AddPortIngressRule, \
ItuOUI, PonPortObject
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
-from voltha.extensions.eoam.EOAM_TLV import TibitOUI
-from voltha.extensions.eoam.EOAM import EOAMPayload, CablelabsOUI
+from voltha.extensions.eoam.EOAM_TLV import DPoEVariableResponseCodes, DPoEOpcodeEnum
+from voltha.extensions.eoam.EOAM_TLV import VendorName, OltMode, HardwareVersion, ManufacturerInfo
+from voltha.extensions.eoam.EOAM_TLV import TibitLinkMacTable
+from voltha.extensions.eoam.EOAM_TLV import SlowProtocolsSubtypeEnum
+from voltha.extensions.eoam.EOAM_TLV import EndOfPDU
+
+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.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
from voltha.protos.adapter_pb2 import Adapter, AdapterConfig
@@ -106,23 +138,6 @@
# from a higher level.
MULTICAST_VLAN = 140
-
-# Extract OLT MAC address: This is a good
-# example of getting the OLT mac address
-
-#for mac, device in self.device_ids.iteritems():
-# if device == dev_id:
-# olt_mac_address = mac
-# log.info('packet-out', olt_mac_address=olt_mac_address)
-
-# To be removed in favor of OAM
-class TBJSON(Packet):
- """ TBJSON 'packet' layer. """
- name = "TBJSON"
- fields_desc = [StrField("data", default="")]
-
-bind_layers(Ether, TBJSON, type=0xA8C8)
-
TIBIT_COMMUNICATIONS_OUI=u'000CE2'
SUMITOMO_ELECTRIC_INDUSTRIES_OUI=u'0025DC'
@@ -156,6 +171,7 @@
self.incoming_queues = {} # OLT mac_address -> DeferredQueue()
self.device_ids = {} # OLT mac_address -> device_id
self.vlan_to_device_ids = {} # c-vid -> (device_id, logical_device_id, mac_address)
+ self.mode = "GPON"
def start(self):
log.debug('starting', interface=self.interface)
@@ -207,103 +223,103 @@
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
- while True:
- response = yield self.incoming_queues[olt_mac].get()
- # verify response and if not the expected response
- if 1: # TODO check if it is really what we expect, and wait if not
- break
+ # 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 = self._get_oam_msg_type(frame)
+
+ if (respType == RxedOamMsgTypeEnum["DPoE Get Response"]):
+ ack = True
+ else:
+ # Handle unexpected events/OMCI messages
+ self._check_resp(frame)
except Exception as e:
log.exception('launch device failed', e=e)
- # if we got response, we can fill out the device info, mark the device
- # reachable
- jdev = json.loads(response.payload.payload.body.load)
- device.root = True
- device.vendor = 'Tibit Communications, Inc.'
- 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']
+ if ack:
+ # Process the Get Request message
+ self._process_ping_frame_response(device, frame)
- device.connect_status = ConnectStatus.REACHABLE
- self.adapter_agent.update_device(device)
+ # then shortly after we create some ports for the device
+ log.info('create-port')
+ nni_port = Port(
+ port_no=2,
+ label='NNI facing Ethernet port',
+ type=Port.ETHERNET_NNI,
+ admin_state=AdminState.ENABLED,
+ oper_status=OperStatus.ACTIVE
+ )
+ self.adapter_agent.add_port(device.id, nni_port)
+ self.adapter_agent.add_port(device.id, Port(
+ port_no=1,
+ label='PON port',
+ type=Port.PON_OLT,
+ admin_state=AdminState.ENABLED,
+ oper_status=OperStatus.ACTIVE
+ ))
- # then shortly after we create some ports for the device
- log.info('create-port')
- nni_port = Port(
- port_no=2,
- label='NNI facing Ethernet port',
- type=Port.ETHERNET_NNI,
- admin_state=AdminState.ENABLED,
- oper_status=OperStatus.ACTIVE
- )
- self.adapter_agent.add_port(device.id, nni_port)
- self.adapter_agent.add_port(device.id, Port(
- port_no=1,
- label='PON port',
- type=Port.PON_OLT,
- admin_state=AdminState.ENABLED,
- oper_status=OperStatus.ACTIVE
- ))
+ log.info('create-logical-device')
+ # then shortly after we create the logical device with one port
+ # that will correspond to the NNI port
+ ld = LogicalDevice(
+ desc=ofp_desc(
+ mfr_desc=device.vendor,
+ hw_desc=device.hardware_version,
+ sw_desc=device.software_version,
+ serial_num=uuid4().hex,
+ dp_desc='n/a'
+ ),
+ switch_features=ofp_switch_features(
+ n_buffers=256, # TODO fake for now
+ n_tables=2, # TODO ditto
+ capabilities=( # TODO and ditto
+ OFPC_FLOW_STATS
+ | OFPC_TABLE_STATS
+ | OFPC_PORT_STATS
+ | OFPC_GROUP_STATS
+ )
+ ),
+ root_device_id=device.id
+ )
+ ld_initialized = self.adapter_agent.create_logical_device(ld)
+ cap = OFPPF_10GB_FD | OFPPF_FIBER
+ self.adapter_agent.add_logical_port(ld_initialized.id, LogicalPort(
+ id='nni',
+ ofp_port=ofp_port(
+ port_no=0,
+ hw_addr=mac_str_to_tuple(device.mac_address),
+ name='nni',
+ config=0,
+ state=OFPPS_LIVE,
+ curr=cap,
+ advertised=cap,
+ peer=cap,
+ curr_speed=OFPPF_10GB_FD,
+ max_speed=OFPPF_10GB_FD
+ ),
+ device_id=device.id,
+ device_port_no=nni_port.port_no,
+ root_port=True
+ ))
- log.info('create-logical-device')
- # then shortly after we create the logical device with one port
- # that will correspond to the NNI port
- ld = LogicalDevice(
- desc=ofp_desc(
- mfr_desc=device.vendor,
- hw_desc=jdev['results']['device'],
- sw_desc=jdev['results']['firmware'],
- serial_num=uuid4().hex,
- dp_desc='n/a'
- ),
- switch_features=ofp_switch_features(
- n_buffers=256, # TODO fake for now
- n_tables=2, # TODO ditto
- capabilities=( # TODO and ditto
- OFPC_FLOW_STATS
- | OFPC_TABLE_STATS
- | OFPC_PORT_STATS
- | OFPC_GROUP_STATS
- )
- ),
- root_device_id=device.id
- )
- ld_initialized = self.adapter_agent.create_logical_device(ld)
- cap = OFPPF_10GB_FD | OFPPF_FIBER
- self.adapter_agent.add_logical_port(ld_initialized.id, LogicalPort(
- id='nni',
- ofp_port=ofp_port(
- port_no=0,
- hw_addr=mac_str_to_tuple(device.mac_address),
- name='nni',
- config=0,
- state=OFPPS_LIVE,
- curr=cap,
- advertised=cap,
- peer=cap,
- curr_speed=OFPPF_10GB_FD,
- max_speed=OFPPF_10GB_FD
- ),
- device_id=device.id,
- device_port_no=nni_port.port_no,
- root_port=True
- ))
+ # and finally update to active
+ device = self.adapter_agent.get_device(device.id)
+ device.parent_id = ld_initialized.id
+ device.oper_status = OperStatus.ACTIVE
+ self.adapter_agent.update_device(device)
- # and finally update to active
- device = self.adapter_agent.get_device(device.id)
- device.parent_id = ld_initialized.id
- device.oper_status = OperStatus.ACTIVE
- self.adapter_agent.update_device(device)
+ # Just transitioned to ACTIVE, wait a tenth of second
+ # before checking for ONUs
+ reactor.callLater(0.1, self._detect_onus, device)
- # Just transitioned to ACTIVE, wait a tenth of second
- # before checking for ONUs
- reactor.callLater(0.1, self._detect_onus, device)
+ # END if ack
@inlineCallbacks
def _detect_onus(self, device):
@@ -311,111 +327,172 @@
olt_mac = device.mac_address
links_frame = self._make_links_frame(mac_address=olt_mac)
self.io_port.send(links_frame)
- while True:
- response = yield self.incoming_queues[olt_mac].get()
- # verify response and if not the expected response
- if 1: # TODO check if it is really what we expect, and wait if not
- break
- jdev = json.loads(response.payload.payload.body.load)
- onu_mac = ''
- child_device_name = ''
- for macid in jdev['results']:
- if macid['macid'] is None:
- log.info('MAC ID is NONE %s' % str(macid['macid']))
- elif macid['macid'][:6].upper() == SUMITOMO_ELECTRIC_INDUSTRIES_OUI:
- onu_mac_string = macid['macid']
- log.info('SUMITOMO mac address %s' % str(macid['macid']))
- child_device_name = 'dpoe_onu'
- elif macid['macid'][:4].upper() == ADTRAN_SHORTENED_VSSN:
- onu_mac_string = macid['macid']
- log.info('ADTRAN mac address %s' % str(macid['macid']))
- child_device_name = 'adtran_onu'
+ # 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 = self._get_oam_msg_type(frame)
+
+ if (respType == RxedOamMsgTypeEnum["DPoE Get Response"]):
+ ack = True
else:
- onu_mac_string = '000c' + macid.get('macid', 'e2000000')[4:]
- log.info('TIBIT mac address %s' % onu_mac)
- child_device_name = 'tibit_onu'
+ # Handle unexpected events/OMCI messages
+ self._check_resp(frame)
- # Convert from string to colon separated form
- onu_mac = ':'.join(s.encode('hex') for s in onu_mac_string.decode('hex'))
- log.info('activate-olt-for-onu-%s' % onu_mac)
- mac_octet_4 = int(macid['macid'][-4:-2], 16)
- vlan_id = self._olt_side_onu_activation(mac_octet_4)
- self.adapter_agent.child_device_detected(
- parent_device_id=device.id,
- parent_port_no=1,
- child_device_type=child_device_name,
- mac_address = onu_mac,
- proxy_address=Device.ProxyAddress(
- device_id=device.id,
- channel_id=vlan_id
- ),
- vlan=vlan_id
- )
+ if ack:
+ #Process the Get Response
+ mac_table = [0xB7, 0x0103]
+ links = []
+ branch_leaf_pairs = [mac_table]
- ## 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()}
- packet_out_rule = (
- Ether(dst=device.mac_address) /
- Dot1Q(vlan=TIBIT_MGMT_VLAN, prio=TIBIT_MGMT_PRIORITY) /
- EOAMPayload(
- body=TibitOUI() / DPoEOpcode_SetRequest() /
- 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)/
- PortIngressRuleResultOLTQueue(unicastvssn="TBIT", unicastlink=int(onu_mac_string[4:], 16))/
- PortIngressRuleResultForward()/
- PortIngressRuleResultDelete(fieldcode=Clause['C-VLAN Tag'])/
- PortIngressRuleTerminator()/
- AddPortIngressRule()))
-
- self.io_port.send(str(packet_out_rule))
-
- # 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[olt_mac].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 = self._voltha_get_oam_msg_type(frame)
- log.info('Received OAM Message 0x %s' % str(respType))
-
- #Check that the message received is a Set Response
- if (respType == RxedOamMsgTypeEnum["DPoE Set Response"]):
+ for pair in branch_leaf_pairs:
+ temp_pair = pair
+ (rc, value) = (self._get_value_from_msg(frame, pair[0], pair[1]))
+ temp_pair.append(rc)
+ temp_pair.append(value)
+ if rc:
+ overall_rc = True
+ 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
- else:
- # Handle unexpected events/OMCI messages
- self._voltha_check_resp(frame)
- # Verify Set Response
- if ack:
- (rc,branch,leaf,status) = self._voltha_check_set_resp(frame)
- if (rc == True):
- log.info('Set Response had no errors')
- else:
- raise Exception('Set Respose had errors')
- log.info('Branch 0x{:X} Leaf 0x{:0>4X} {}'.format(branch, leaf, DPoEVariableResponseCodes[status]))
+ if mac_table[rc]:
+ value = mac_table.pop()
+ macLen = 0
+ while (macLen < len(value)):
+ macAddr = struct.unpack_from(">6B", value, macLen)
+ linkAddr = "".join([hex(i).lstrip("0x").zfill(2) for i in macAddr])
- # also record the vlan_id -> (device_id, logical_device_id, linkid) for
- # later use. The linkid is the macid returned.
- self.vlan_to_device_ids[vlan_id] = (device.id, device.parent_id, macid.get('macid', 0))
+ if linkAddr is None:
+ log.info('MAC Addr is NONE')
+ elif linkAddr[:6].upper() == SUMITOMO_ELECTRIC_INDUSTRIES_OUI:
+ 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
+ log.info('ADTRAN mac address %s' % str(linkAddr))
+ child_device_name = 'adtran_onu'
+ else:
+ onu_mac_string = '000c' + linkAddr[4:]
+ log.info('TIBIT mac address %s' % onu_mac_string)
+ child_device_name = 'tibit_onu'
+
+ if linkAddr is not None:
+ # Convert from string to colon separated form
+ onu_mac = ':'.join(s.encode('hex') for s in onu_mac_string.decode('hex'))
+ log.info('activate-olt-for-onu-%s' % onu_mac)
+ mac_octet_4 = int(linkAddr[-4:-2], 16)
+ 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
+ vssn = "TBIT"
+ 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:10]+"02").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=0x03,
+ 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()
+ )
+
+ self.io_port.send(str(packet_out_rule))
+
+ # 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[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 = self._get_oam_msg_type(frame)
+
+ #Check that the message received is a Set Response
+ if (respType == RxedOamMsgTypeEnum["DPoE Set Response"]):
+ ack = True
+ else:
+ # Handle unexpected events/OMCI messages
+ self._check_resp(frame)
+
+ # Verify Set Response
+ if ack:
+ (rc,branch,leaf,status) = self._check_set_resp(frame)
+ if (rc == True):
+ log.info('Set Response had no errors')
+
+ # also record the vlan_id -> (device_id, logical_device_id, linkid) for
+ # later use. The linkid is the macid returned.
+
+ self.vlan_to_device_ids[vlan_id] = (device.id, device.parent_id, linkAddr)
+
+
+ self.adapter_agent.child_device_detected(
+ parent_device_id=device.id,
+ parent_port_no=1,
+ child_device_type=child_device_name,
+ mac_address = onu_mac,
+ proxy_address=Device.ProxyAddress(
+ device_id=device.id,
+ channel_id=vlan_id
+ ),
+ vlan=vlan_id
+ )
+
+ else:
+ log.info('Set Response had errors')
+ log.info('Branch 0x{:X} Leaf 0x{:0>4X} {}'.format(branch, leaf, DPoEVariableResponseCodes[status]))
+
+ # END linkAddr is not none
+ else:
+ log.info('No links were found in the MAC Table')
+ # END if mac_table[rc]
+ #END if ack
### KPI Metrics - Work in progress feature - Disabling for now
### Give the ONUs a chance to arrive before starting metric collection
- ### reactor.callLater(5.0, self.start_kpi_collection, device.id)
+
+ # TODO - Disable Stats Reporting for the moment
+ # reactor.callLater(5.0, self.start_kpi_collection, device.id)
+
def _olt_side_onu_activation(self, serial):
"""
@@ -492,21 +569,158 @@
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(dst=mac_address)/Dot1Q(vlan=TIBIT_MGMT_VLAN, prio=TIBIT_MGMT_PRIORITY)/TBJSON(data='json %s' % json_operation_str)
+ frame = (
+ Ether(dst=mac_address) /
+ Dot1Q(vlan=TIBIT_MGMT_VLAN, prio=TIBIT_MGMT_PRIORITY) /
+ EOAMPayload() / EOAM_VendSpecificMsg(oui=Tibit_OUI) /
+ EOAM_TibitMsg(dpoe_opcode=0x01,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]
+ branch_leaf_pairs = [vendor, oltMode, hw_version, manufacturer]
+
+ for pair in branch_leaf_pairs:
+ temp_pair = pair
+ (rc, value) = (self._get_value_from_msg(frame, pair[0], pair[1]))
+ temp_pair.append(rc)
+ temp_pair.append(value)
+ if rc:
+ overall_rc = True
+ 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
+
+ if vendor[rc]:
+ device.vendor = vendor.pop()
+ else:
+ device.vendor = "UNKNOWN"
+
+ # mode: 3 = EPON OLT, 7 = GPON OLT
+ # mode: 2 = EPON ONU, 6 = GPON ONU
+ if oltMode[rc]:
+ value = oltMode.pop()
+ mode = "UNKNOWN"
+ self.mode = "UNKNOWN"
+
+ if value == 7:
+ mode = "10G GPON OLT"
+ self.mode = "GPON"
+ if value == 3:
+ mode = "10G EPON OLT"
+ self.mode = "EPON"
+ if value == 1:
+ mode = "10G Point to Point"
+ self.mode = "Unsupported"
+
+ device.model = mode
+
+ else:
+ device.model = "UNKNOWN"
+ self.mode = "UNKNOWN"
+
+ log.info("OLT Mode is {}".format(self.mode))
+
+ if hw_version[rc]:
+ device.hardware_version = hw_version.pop()
+ else:
+ device.hardware_version = "UNKNOWN"
+
+ if manufacturer[rc]:
+ manu_value = manufacturer.pop()
+ device.firmware_version = re.search('\Firmware: (.+?) ', manu_value).group(1)
+ device.software_version = re.search('\Build: (.+?) ', manu_value).group(1)
+ device.serial_number = re.search('\Serial #: (.+?) ', manu_value).group(1)
+ else:
+ device.firmware_version = "UNKNOWN"
+ device.software_version = "UNKNOWN"
+ device.serial_number = "UNKNOWN"
+ device.root = True
+ device.connect_status = ConnectStatus.REACHABLE
+
def _make_links_frame(self, mac_address):
- # Create a json packet
- json_operation_str = '{\"operation\":\"links\"}'
- frame = Ether(dst=mac_address)/Dot1Q(vlan=TIBIT_MGMT_VLAN, prio=TIBIT_MGMT_PRIORITY)/TBJSON(data='json %s' % json_operation_str)
+ frame = (
+ Ether(dst=mac_address) /
+ Dot1Q(vlan=TIBIT_MGMT_VLAN, prio=TIBIT_MGMT_PRIORITY) /
+ EOAMPayload() / EOAM_VendSpecificMsg(oui=Tibit_OUI) /
+ EOAM_TibitMsg(dpoe_opcode=0x01,body=TibitLinkMacTable()
+ )/
+ EndOfPDU()
+ )
return str(frame)
- def _make_stats_frame(self, mac_address, itype, link):
- # Create a json packet
- json_operation_str = ('{\"operation\":\"stats\",\"parameters\":{\"itype\":\"%s\",\"iinst\",\"0\",\"macid\":\"%s\"}}' % (itype, link))
- frame = Ether(dst=mac_address)/Dot1Q(vlan=TIBIT_MGMT_VLAN, prio=TIBIT_MGMT_PRIORITY)/TBJSON(data='json %s' % json_operation_str)
+ 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)
+ else: # EPON
+ vssn = int(onu_mac_address[0:8].rjust(8,"0"), 16)
+ link = int((onu_mac_address[8:10]+"02").ljust(8,"0"), 16)
+ 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=0x01,
+ body=OLTUnicastLogicalLink(unicastvssn=vssn, unicastlink=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=0x01, 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):
@@ -613,9 +827,19 @@
dn_req /= PortIngressRuleResultOLTBroadcastQueue()
elif _inner_vid is not None:
serial = _inner_vid - 200
- link = (0xe222 << 16) | (serial << 8)
- dn_req /= PortIngressRuleResultOLTQueue(unicastvssn="TBIT",
- unicastlink=link)
+ 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:10]+"02").ljust(8,"0"), 16)
+ resultOltQueue = "PortIngressRuleResultOLTEPONQueue(unicastvssn=vssn, unicastlink=link)"
+
+ dn_req /= eval(resultOltQueue)
+
elif _inner_vid is None:
log.info('#### action.type == OUTPUT INNER VID is NONE ####')
@@ -626,7 +850,7 @@
dn_req /= PortIngressRuleClauseMatchLength02(fieldcode=Clause['C-VLAN Tag'], fieldinstance=0,
operator=Operator['=='], match=_outer_vid)
else:
- dn_req /= PortIngressRuleResultDelete(fieldcode=Clause['S-VLAN Tag'])
+ 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,
@@ -660,8 +884,9 @@
msg = (
Ether(dst=device.mac_address) /
Dot1Q(vlan=TIBIT_MGMT_VLAN, prio=TIBIT_MGMT_PRIORITY) /
- EOAMPayload(
- body=TibitOUI() / DPoEOpcode_SetRequest() / dn_req)
+ EOAMPayload() / EOAM_VendSpecificMsg(oui=Tibit_OUI) /
+ EOAM_TibitMsg(dpoe_opcode = 0x03, body=dn_req)/
+ EndOfPDU()
)
self.io_port.send(str(msg))
@@ -673,27 +898,26 @@
# Loop until we have a set response or timeout
while not ack:
frame = yield self.incoming_queues[olt_mac].get()
- #TODO - Need to add propoer timeout functionality
+ #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 = self._voltha_get_oam_msg_type(frame)
- log.info('Received OAM Message 0x %s' % str(respType))
+ respType = self._get_oam_msg_type(frame)
#Check that the message received is a Set Response
if (respType == RxedOamMsgTypeEnum["DPoE Set Response"]):
ack = True
else:
# Handle unexpected events/OMCI messages
- self._voltha_check_resp(frame)
+ self._check_resp(frame)
# Verify Set Response
if ack:
- (rc,branch,leaf,status) = self._voltha_check_set_resp(frame)
+ (rc,branch,leaf,status) = self._check_set_resp(frame)
if (rc == True):
log.info('Set Response had no errors')
else:
- raise Exception('Set Respose had errors')
+ log.info('Set Response had errors')
log.info('Branch 0x{:X} Leaf 0x{:0>4X} {}'.format(branch, leaf, DPoEVariableResponseCodes[status]))
elif in_port == 1:
@@ -747,9 +971,19 @@
operator=Operator['=='], match=_vlan_vid)
serial = _vlan_vid - 200
- link = (0xe222 << 16) | (serial << 8)
- up_req_link /= OLTUnicastLogicalLink(unicastvssn='TBIT', unicastlink=link)
+ 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:10]+"02").ljust(8,"0"), 16)
+ logical_link = "OLTEPONUnicastLogicalLink(unicastvssn=vssn, unicastlink=link)"
+
+ up_req_link /= eval(logical_link)
+
up_req_link /= PortIngressRuleClauseMatchLength02(
fieldcode=Clause['C-VLAN Tag'], fieldinstance=0,
operator=Operator['=='], match=_vlan_vid)
@@ -831,8 +1065,9 @@
msg = (
Ether(dst=device.mac_address) /
Dot1Q(vlan=TIBIT_MGMT_VLAN, prio=TIBIT_MGMT_PRIORITY) /
- EOAMPayload(
- body=TibitOUI() / DPoEOpcode_SetRequest() / up_req)
+ EOAMPayload() / EOAM_VendSpecificMsg(oui=Tibit_OUI) /
+ EOAM_TibitMsg(dpoe_opcode = 0x03, body=up_req)/
+ EndOfPDU()
)
self.io_port.send(str(msg))
@@ -844,27 +1079,26 @@
# Loop until we have a set response or timeout
while not ack:
frame = yield self.incoming_queues[olt_mac].get()
- #TODO - Need to add propoer timeout functionality
+ #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 = self._voltha_get_oam_msg_type(frame)
- log.info('Received OAM Message 0x %s' % str(respType))
+ respType = self._get_oam_msg_type(frame)
#Check that the message received is a Set Response
if (respType == RxedOamMsgTypeEnum["DPoE Set Response"]):
ack = True
else:
# Handle unexpected events/OMCI messages
- self._voltha_check_resp(frame)
+ self._check_resp(frame)
# Verify Set Response
if ack:
- (rc,branch,leaf,status) = self._voltha_check_set_resp(frame)
+ (rc,branch,leaf,status) = self._check_set_resp(frame)
if (rc == True):
log.info('Set Response had no errors')
else:
- raise Exception('Set Respose had errors')
+ log.info('Set Respose had errors')
log.info('Branch 0x{:X} Leaf 0x{:0>4X} {}'.format(branch, leaf, DPoEVariableResponseCodes[status]))
else:
@@ -882,7 +1116,7 @@
mac_address = self.vlan_to_device_ids[proxy_address.channel_id][2].upper()
- if mac_address.startswith(TIBIT_SHORTENED_VSSN):
+ if mac_address.startswith(TIBIT_SHORTENED_VSSN) or self.mode.upper()[0] == "E":
# Send straight OAM
frame = Ether(dst=device.mac_address) / \
Dot1Q(vlan=TIBIT_MGMT_VLAN, prio=TIBIT_MGMT_PRIORITY) / \
@@ -890,11 +1124,12 @@
msg
else:
# Use the standard to send OMCI over OAM
- encapsulated_omci = EOAMPayload(body=ItuOUI()/msg)
+ encapsulated_omci = EOAM_OmciMsg(body=msg)
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) / \
encapsulated_omci
self.io_port.send(str(frame))
@@ -920,7 +1155,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()
@@ -937,43 +1172,106 @@
@inlineCallbacks
def _collect(device_id, prefix):
- pon_port_metrics = {}
- links = []
+ pon_port_metrics = []
+ pon_metrics_list = {}
+ 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"]]
+
olt_mac = next((mac for mac, device in self.device_ids.iteritems() if device == device_id), None)
- links = [v[TIBIT_ONU_LINK_INDEX] for _,v,_ in self.vlan_to_device_ids.iteritems()]
try:
# Step 1: gather metrics from device
- log.info('link stats frame', links=links)
- for link in links:
- stats_frame = self._make_stats_frame(mac_address=olt_mac, itype='olt', link=link)
- self.io_port.send(stats_frame)
- ## Add timeout mechanism so we can signal if we cannot reach
- ## device
- while True:
- response = yield self.incoming_queues[olt_mac].get()
- jdict = json.loads(response.payload.payload.body.load)
- pon_port_metrics[link] = {k: int(v,16) for k,v in jdict['results'].iteritems()}
- # verify response and if not the expected response
- if 1: # TODO check if it is really what we expect, and wait if not
- break
+ #for each link on this OLT
+ for vlan_id in self.vlan_to_device_ids:
+
+ 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()
+
+ 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)
+
+ # 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 = self._get_oam_msg_type(frame)
+
+ if (respType == RxedOamMsgTypeEnum["DPoE Get Response"]):
+ ack = True
+ else:
+ # Handle unexpected events/OMCI messages
+ self._check_resp(frame)
+
+ if ack:
+ # Process the Get Request message
+ log.info('Received Link Stats Get Response Frame')
+
+ for pair in branch_leaf_pairs:
+ (rc, value) = (self._get_value_from_msg(frame, pair[0], pair[1]))
+
+ if rc:
+ log.info('Response for Branch 0x{:X} Leaf 0x{:0>4X} '.format(pair[0], pair[1]))
+ pon_port_metrics.append((pair[2],value))
+ else:
+ log.info('Failed to get valid response for Branch 0x{:X} Leaf 0x{:0>4X} '.format(pair[0], pair[1]))
+
+ pon_metrics_list[vlan_id] = pon_port_metrics
+
+ #end looping on each vlan_id
log.info('nni stats frame')
- olt_nni_link = ''.join(l for l in olt_mac.split(':'))
- stats_frame = self._make_stats_frame(mac_address=olt_mac, itype='eth', link=olt_nni_link)
- self.io_port.send(stats_frame)
- ## Add timeout mechanism so we can signal if we cannot reach
- ## device
- while True:
- response = yield self.incoming_queues[olt_mac].get()
- jdict = json.loads(response.payload.payload.body.load)
- nni_port_metrics = {k: int(v,16) for k,v in jdict['results'].iteritems()}
- # verify response and if not the expected response
- if 1: # TODO check if it is really what we expect, and wait if not
- break
+ link_stats_frame = self._make_nni_stats_frame(mac_address=olt_mac)
+ self.io_port.send(link_stats_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 = self._get_oam_msg_type(frame)
+
+ if (respType == RxedOamMsgTypeEnum["DPoE Get Response"]):
+ ack = True
+ else:
+ # Handle unexpected events/OMCI messages
+ self._check_resp(frame)
+
+ if ack:
+ # Process the Get Response message
+ log.info('Recieved NNI Stats Get Response Frame')
+
+ for pair in branch_leaf_pairs:
+ (rc, value) = (self._get_value_from_msg(frame, pair[0], pair[1]))
+ if rc:
+ log.info('Response for Branch 0x{:X} Leaf 0x{:0>4X} '.format(pair[0], pair[1]))
+ nni_metrics.append((pair[2],value))
+ else:
+ log.info('Failed to get valid response for Branch 0x{:X} Leaf 0x{:0>4X} '.format(temp_pair[0], temp_pair[1]))
+
+ #Need to replace with actual data
olt_metrics = dict(
cpu_util=20 + 5 * random.random(),
buffer_util=10 + 10 * random.random()
@@ -986,12 +1284,12 @@
# CPU Metrics (example)
prefix: MetricValuePairs(metrics=olt_metrics),
# OLT NNI port
- prefix + '.nni': MetricValuePairs(metrics=nni_port_metrics)
+ prefix + '.nni': MetricValuePairs(metrics=nni_metrics)
}
- for link in links:
+ for link in pon_metrics_list:
# PON link ports
- prefixes[prefix + '.pon.{}'.format(link)] = MetricValuePairs(metrics=pon_port_metrics[link])
+ prefixes[prefix + '.pon.{}'.format(link)] = MetricValuePairs(metrics=pon_metrics_list[link])
kpi_event = KpiEvent(
type=KpiEventType.slice,
@@ -1009,175 +1307,67 @@
lc = LoopingCall(_collect, device_id, prefix)
lc.start(interval=15) # TODO make this configurable
- def _voltha_get_oam_msg_type(self, frame):
+
+ # Methods for Get / Set Response Processing from eoam_messages
+
+
+ def _get_oam_msg_type(self, frame):
+
respType = RxedOamMsgTypeEnum["Unknown"]
recv_frame = frame
- payload = recv_frame.payload
- if hasattr(payload, 'body'):
- loadstr = payload.body.load
- bytesRead = 0;
- if (payload.opcode == 0xFE):
- # Extract the OUI
- (oui_hi, oui_lo) = struct.unpack_from('>BH', loadstr, bytesRead)
- oui = (oui_hi << 16) | oui_lo
- log.debug('oui: 0x %06x' % oui)
- bytesRead += 3
-
- # If this is the ITU OUI, then there is an embedded OMCI message
- if (oui == 0x0019A7):
- respType = RxedOamMsgTypeEnum["OMCI Message"]
-
- # Treat Cablelabs OUI and Tibit OUI as the same
- elif ((oui == 0x001000) or (oui == 0x2AEA15)):
-
- (dpoeOpcode) = struct.unpack_from('>B', loadstr, bytesRead)[0]
-# log.info('DPoE Opcode: {} ({:0>2X})'.format(DPoEOpcodeEnum[dpoeOpcode], dpoeOpcode))
- bytesRead += 1
-
- # Get Response
- if (dpoeOpcode == 0x02):
- respType = RxedOamMsgTypeEnum["DPoE Get Response"]
-
- # Set Response
- elif (dpoeOpcode == 0x04):
- respType = RxedOamMsgTypeEnum["DPoE Set Response"]
-
- # File Transfer ACK
- elif (dpoeOpcode == 0x09):
- respType = RxedOamMsgTypeEnum["DPoE File Transfer"]
-
- else:
- log.info('Unsupported OAM OUI 0x{:0>6X}'.format(oui))
-
- # Handle OAM Event Notification
- elif (payload.opcode == 0x01):
- respType = RxedOamMsgTypeEnum["Event Notification"]
+ if recv_frame.haslayer(EOAMPayload):
+ if recv_frame.haslayer(EOAMEvent):
+ recv_frame = RxedOamMsgTypeEnum["Event Notification"]
+ elif recv_frame.haslayer(EOAM_OmciMsg):
+ respType = RxedOamMsgTypeEnum["OMCI Message"]
else:
- log.info('Unsupported OAM Opcode {}'.format(payload.opcode))
+ dpoeOpcode = 0x00
+ if recv_frame.haslayer(EOAM_TibitMsg):
+ dpoeOpcode = recv_frame.getlayer(EOAM_TibitMsg).dpoe_opcode;
+ elif recv_frame.haslayer(EOAM_DpoeMsg):
+ dpoeOpcode = recv_frame.getlayer(EOAM_DpoeMsg).dpoe_opcode;
+
+ # Get Response
+ if (dpoeOpcode == 0x02):
+ respType = RxedOamMsgTypeEnum["DPoE Get Response"]
+
+ # Set Response
+ elif (dpoeOpcode == 0x04):
+ respType = RxedOamMsgTypeEnum["DPoE Set Response"]
+
+ # File Transfer ACK
+ elif (dpoeOpcode == 0x09):
+ respType = RxedOamMsgTypeEnum["DPoE File Transfer"]
+ else:
+ log.info('Unsupported DPoE Opcode {:0>2X}'.format(dpoeOpcode))
else:
- log.debug('received frame has no payload')
+ log.info('Invalid OAM Header')
+
+ log.info('Received OAM Message 0x %s' % str(respType))
return respType
- def _voltha_check_set_resp(self, frame):
- rc = False
- branch = 0
- leaf = 0
- status = 0
-
+ def _get_value_from_msg(self, frame, branch, leaf):
+ retVal = False
+ value = 0
recv_frame = frame
- payload = recv_frame.payload
- if hasattr(payload, 'body'):
- loadstr = payload.body.load
- bytesRead = 0;
- #if self.report_obj is not None:
- # self.report_obj.log_result(data="OAM Opcode", actual=hex(payload.opcode), expected=hex(0xFE), criteria="==")
- if (payload.opcode == 0xFE):
- # Extract the OUI
- (oui_hi, oui_lo) = struct.unpack_from('>BH', loadstr, bytesRead)
- oui = (oui_hi << 16) | oui_lo
- log.info('oui: 0x %06x' % oui)
- bytesRead += 3
-
- # Treat Cablelabs OUI and Tibit OUI as the same
- if ((oui == 0x001000) or (oui == 0x2AEA15)):
- (dpoeOpcode) = struct.unpack_from('>B', loadstr, bytesRead)[0]
- bytesRead += 1
-
- startOfTlvs = bytesRead
- # Set Response
- if (dpoeOpcode == 0x04):
- test =1
- (rc,branch,leaf,status) = self._voltha_check_set_resp_attrs(loadstr, startOfTlvs)
- if (rc == True):
- log.info('Set Response had no errors')
- else:
- log.debug('Branch 0x{:X} Leaf 0x{:0>4X} {}'.format(branch, leaf, DPoEVariableResponseCodes[status]))
- else:
- log.info('Unsupported DPoE Opcode: {} ({:0>2X})'.format(DPoEOpcodeEnum[dpoeOpcode], dpoeOpcode))
- else:
- log.info('Unsupported OAM OUI 0x{:0>6X}'. format(oui))
+ if recv_frame.haslayer(EOAMPayload):
+ payload = recv_frame.payload
+ if hasattr(payload, 'body'):
+ loadstr = payload.body.load
+ # Get a specific TLV value
+ (retVal,bytesRead,value,retbranch,retleaf) = self._handle_get_value(loadstr, 0, branch, leaf)
else:
- log.info('Unsupported OAM Opcode {}'.format(payload.opcode))
+ log.info('received frame has no payload')
else:
- log.debug('received frame has no payload')
-
- return rc,branch,leaf,status
-
-
- def _voltha_check_resp(self, frame):
- recv_frame = frame
- payload = recv_frame.payload
- if hasattr(payload, 'body'):
- loadstr = payload.body.load
- bytesRead = 0;
- if (payload.opcode == 0xFE):
-
- # Extract the OUI
- (oui_hi, oui_lo) = struct.unpack_from('>BH', loadstr, bytesRead)
- oui = (oui_hi << 16) | oui_lo
- log.info('oui: 0x %06x' % oui)
- bytesRead += 3
-
- # If this is the ITU OUI, then there is an embedded OMCI message
- if (oui == 0x0019A7):
- self._voltha_handle_omci(loadstr,bytesRead)
-
- # Treat Cablelabs OUI and Tibit OUI as the same
- elif ((oui == 0x001000) or (oui == 0x2AEA15)):
- log.debug('Recieved Response OUI 0x{:0>6X}'. format(oui))
- else:
- log.info('Unsupported OAM OUI 0x{:0>6X}'. format(oui))
-
- # Handle OAM Event Notification
- elif (payload.opcode == 0x01):
- self._voltha_handle_oam_event(loadstr, bytesRead)
- else:
- log.info('Unsupported OAM Opcode {}'.format(payload.opcode))
-
- else:
- log.debug('received frame has no payload')
+ log.info('Invalid OAM Header')
+ return retVal,value,
- def _voltha_handle_oam_event(self, loadstr, startOfEvent):
- bytesRead = startOfEvent
- (seq_num, tlv_type, ev_len, oui_hi, oui_lo) = struct.unpack_from('>HBBBH', loadstr, bytesRead)
- oui = (oui_hi << 16) | oui_lo
-
- log.info('seq_num: 0x%04x' % seq_num)
- log.info('tlv_type: 0x%' % tlv_type)
- log.info('ev_len: 0x%x' % ev_len)
- log.info('oui: 0x%06x"'% oui)
-
- if (tlv_type != 0xFE):
- log.debug('unexpected tlv_type 0x%x (expected 0xFE)' % tlv_type)
- elif (oui == 0x001000):
- log.debug('DPoE Event')
- ## TODO - Handle DPoE Event/Alarm
- elif (oui == 0x2AEA15):
- log.debug('Tibit-specific Event')
-
- # TODO - Handle addition/removal of links
-
- bytesRead = 7
-
- # TODO - Check OUI and parse Source and Reference Object Contexts
-
-
- def _voltha_handle_omci(self, loadstr, startOfEvent):
- bytesRead = startOfEvent
-# (seq_num, tlv_type, ev_len, oui_hi, oui_lo) = struct.unpack_from('>BBBBBH', loadstr, bytesRead)
-
- log.debug('OMCI Message')
-
- # TODO - Handle OMCI message
-
-
-
- def _voltha_handle_get_value(self, loadstr, startOfTlvs, queryBranch, queryLeaf):
+ def _handle_get_value(self, loadstr, startOfTlvs, queryBranch, queryLeaf):
retVal = False;
value = 0
branch = 0
@@ -1187,12 +1377,10 @@
while (bytesRead <= loadstrlen):
(branch, leaf) = struct.unpack_from('>BH', loadstr, bytesRead)
-# log.info('Branch/Leaf 0x{:0>2X}/0x{:0>4X}'.format(branch, leaf))
if (branch != 0):
bytesRead += 3
length = struct.unpack_from('>B', loadstr, bytesRead)[0]
-# log.info('Length: 0x{:0>2X} ({})'.format(length,length))
bytesRead += 1
if (length == 1):
@@ -1215,8 +1403,6 @@
valStr = ">{}s".format(length)
value = struct.unpack_from(valStr, loadstr, bytesRead)[0]
-# log.info('Value: {}'.format(value))
-
if (length > 0):
bytesRead += length
@@ -1235,7 +1421,89 @@
return retVal,bytesRead,value,branch,leaf
- def _voltha_check_set_resp_attrs(self, loadstr, startOfTlvs):
+
+ def _check_set_resp(self, frame):
+ rc = False
+ branch = 0
+ leaf = 0
+ status = 0
+ recv_frame = frame
+ if recv_frame.haslayer(EOAMPayload):
+ payload = recv_frame.payload
+ if hasattr(payload, 'body'):
+ loadstr = payload.body.load
+ # Get a specific TLV value
+ (rc,branch,leaf,status) = self._check_set_resp_attrs(loadstr, 0)
+ else:
+ log.info('received frame has no payload')
+ else:
+ log.info('Invalid OAM Header')
+ return rc,branch,leaf,status
+
+
+
+ def _check_resp(self, frame):
+ respType = RxedOamMsgTypeEnum["Unknown"]
+ recv_frame = frame
+ if recv_frame.haslayer(EOAMPayload):
+
+ if recv_frame.haslayer(EOAMEvent):
+ self.handle_oam_event(recv_frame)
+ elif recv_frame.haslayer(EOAM_OmciMsg):
+ self.handle_omci(recv_frame)
+ else:
+ dpoeOpcode = 0x00
+ if recv_frame.haslayer(EOAM_TibitMsg):
+ dpoeOpcode = recv_frame.getlayer(EOAM_TibitMsg).dpoe_opcode;
+ elif recv_frame.haslayer(EOAM_DpoeMsg):
+ dpoeOpcode = recv_frame.getlayer(EOAM_DpoeMsg).dpoe_opcode;
+
+ if hasattr(recv_frame, 'body'):
+ payload = recv_frame.payload
+ loadstr = payload.body.load
+
+ # Get Response
+ if (dpoeOpcode == 0x02):
+ # Get a specific TLV value
+ branch = 0xD7
+ leaf = 0x0006
+ (rc,bytesRead,value,retbranch,retleaf) = self._handle_get_value(loadstr, startOfTlvs, branch, leaf)
+ if (rc == True):
+ log.info('Branch 0x{:X} Leaf 0x{:0>4X} value = {}'.format(branch, leaf, value))
+ else:
+ log.info('Branch 0x{:X} Leaf 0x{:0>4X} no value'.format(branch, leaf))
+
+ # Walk through all TLV values
+ bytesRead = 0
+ rc = True
+ while(rc == True):
+ branch = 0
+ leaf = 0
+ (rc,bytesRead,value,branch,leaf) = self._handle_get_value(loadstr, bytesRead, branch, leaf)
+ if (rc == True):
+ log.info('Branch 0x{:0>2X} Leaf 0x{:0>4X} value = {}'.format(branch, leaf, value))
+ elif (branch != 0):
+ log.info('Branch 0x{:0>2X} Leaf 0x{:0>4X} no value'.format(branch, leaf))
+
+ # Set Response
+ elif (dpoeOpcode == 0x04):
+ (rc,branch,leaf,status) = self._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]))
+
+ # File Transfer ACK
+ elif (dpoeOpcode == 0x09):
+ rc = self._handle_fx_ack(loadstr, bytesRead, block_number)
+ else:
+ log.info('Unsupported DPoE Opcode {:0>2X}'.format(dpoeOpcode))
+ else:
+ log.info('Invalid OAM Header')
+
+ return respType
+
+ def _check_set_resp_attrs(self, loadstr, startOfTlvs):
retVal = True;
branch = 0
leaf = 0
@@ -1245,16 +1513,16 @@
while (bytesRead <= loadstrlen):
(branch, leaf) = struct.unpack_from('>BH', loadstr, bytesRead)
-# log.info('Branch/Leaf 0x{:0>2X}/0x{:0>4X}'.format(branch, leaf))
+# print "Branch/Leaf 0x{:0>2X}/0x{:0>4X}".format(branch, leaf)
if (branch != 0):
bytesRead += 3
length = struct.unpack_from('>B', loadstr, bytesRead)[0]
-# log.info('Length: 0x{:0>2X} ({})'.format(length,length))
+# print "Length: 0x{:0>2X} ({})".format(length,length)
bytesRead += 1
if (length >= 0x80):
- log.debug('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, DPoEVariableResponseCodes[length]))
if (length > 0x80):
retVal = False;
break;
@@ -1266,24 +1534,21 @@
return retVal,branch,leaf,length
-
-
- def _voltha_handle_fx_ack(self, loadstr, startOfXfer, block_number):
+
+ def _handle_fx_ack(self, loadstr, startOfXfer, block_number):
retVal = False
(fx_opcode, acked_block, response_code) = struct.unpack_from('>BHB', loadstr, startOfXfer)
- log.debug('fx_opcode: 0x%x' % fx_opcode)
- log.debug('acked_block: 0x%x' % acked_block)
- log.debug('response_code: 0x%x' % response_code)
-
+ #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.debug('unexpected fx_opcode 0x%x (expected 0x03)' % fx_opcode)
+ log.info('unexpected fx_opcode 0x%x (expected 0x03)' % fx_opcode)
elif (acked_block != block_number):
- log.debug('unexpected acked_block 0x%x (expected 0x%x)' % (acked_block, block_number))
+ log.info('unexpected acked_block 0x%x (expected 0x%x)' % (acked_block, block_number))
elif (response_code != 0):
- log.debug('unexpected response_code 0x%x (expected 0x00)' % response_code)
+ log.info('unexpected response_code 0x%x (expected 0x00)' % response_code)
else:
- retVal = True;
-
+ retVal = True;
\ No newline at end of file
diff --git a/voltha/adapters/tibit_onu/tibit_onu.py b/voltha/adapters/tibit_onu/tibit_onu.py
index 6062007..5801101 100644
--- a/voltha/adapters/tibit_onu/tibit_onu.py
+++ b/voltha/adapters/tibit_onu/tibit_onu.py
@@ -63,9 +63,11 @@
from voltha.extensions.eoam.EOAM_TLV import ClauseSubtypeEnum
from voltha.extensions.eoam.EOAM_TLV import RuleOperatorEnum
from voltha.extensions.eoam.EOAM_TLV import DPoEVariableResponseCodes
-from voltha.extensions.eoam.EOAM_TLV import TibitOUI
+from voltha.extensions.eoam.EOAM_TLV import DPoEOpcode_MulticastRegister, MulticastRegisterSet
-from voltha.extensions.eoam.EOAM import EOAMPayload, CablelabsOUI
+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 import DPoEOpcode_GetRequest, DPoEOpcode_SetRequest
from voltha.extensions.eoam.EOAM import mcastIp2McastMac
@@ -212,16 +214,18 @@
device_port_no=uni_port.port_no
))
-
# simulate a proxied message sending and receving a reply
reply = yield self._message_exchange(device)
+ # TODO - Need to add validation of reply and decide what to do upon failure
+
# and finally update to "ACTIVE"
device = self.adapter_agent.get_device(device.id)
device.oper_status = OperStatus.ACTIVE
self.adapter_agent.update_device(device)
- self.start_kpi_collection(device.id)
+ # TODO - Disable Stats Reporting for the moment
+ #self.start_kpi_collection(device.id)
def abandon_device(self, device):
raise NotImplementedError(0
@@ -259,8 +263,13 @@
if in_port == 2:
log.info('#### Upstream Rule ####')
- dn_req = EOAMPayload(body=TibitOUI() /
- DPoEOpcode_SetRequest())
+
+ up_req = (
+ EOAMPayload() / EOAM_VendSpecificMsg(oui=CableLabs_OUI) /
+ EOAM_DpoeMsg(dpoe_opcode=0x03)
+ )
+
+ #TODO - There is no body to the message above, is there ever an Upstream Rule
for field in get_ofb_fields(flow):
@@ -365,15 +374,14 @@
b = int(hex(_ipv4_dst)[4:6], 16)
c = int(hex(_ipv4_dst)[6:8], 16)
d = int(hex(_ipv4_dst)[8:], 16)
- dn_req = EOAMPayload(body=TibitOUI() /
- DPoEOpcode_SetRequest() /
- AddStaticMacAddress(
- mac=mcastIp2McastMac('%d.%d.%d.%d' % (a,b,c,d)))
- )
-
- # send message
+ dn_req = (
+ EOAMPayload() / EOAM_VendSpecificMsg(oui=CableLabs_OUI) /
+ EOAM_DpoeMsg(dpoe_opcode=0x03, body=AddStaticMacAddress(mac=mcastIp2McastMac('%d.%d.%d.%d' % (a,b,c,d)))
+ ))
- log.info('ONU-send-proxied-message')
+ # send message
+
+ log.info('ONU-send-proxied-message to Set Static IP MCAST address for ONU: {}'.format(device.mac_address))
self.adapter_agent.send_proxied_message(device.proxy_address,
dn_req)
@@ -388,7 +396,7 @@
#if (time.time() - start_time) > TIBIT_MSG_WAIT_TIME or (frame is None):
# break # don't wait forever
- respType = self._voltha_get_oam_msg_type(frame)
+ respType = self._get_oam_msg_type(frame)
log.info('Received OAM Message 0x %s' % str(respType))
#Check that the message received is a Set Response
@@ -396,17 +404,16 @@
ack = True
else:
# Handle unexpected events/OMCI messages
- self._voltha_check_resp(frame)
+ self._check_resp(frame)
# Verify Set Response
if ack:
- (rc,branch,leaf,status) = self._voltha_check_set_resp(frame)
- log.info('REturn from Set resp')
+ log.info('ONU-response received for Set Static IP MCAST address for ONU: {}'.format(device.mac_address))
+ (rc,branch,leaf,status) = self._check_set_resp(frame)
if (rc == True):
log.info('Set Response had no errors')
else:
- log.info('Set Respose had errors')
- log.info('Branch 0x{:X} Leaf 0x{:0>4X} {}'.format(branch, leaf, DPoEVariableResponseCodes[status]))
+ log.info('Set Response had errors - Branch 0x{:X} Leaf 0x{:0>4X} {}'.format(branch, leaf, DPoEVariableResponseCodes[status]))
else:
raise NotImplementedError('field.type={}'.format(
@@ -467,32 +474,36 @@
_ = yield self.incoming_messages.get()
# construct message
- msg = EOAMPayload(body=TibitOUI() /
- DPoEOpcode_GetRequest() /
- DeviceId()
- )
+ msg = (
+ EOAMPayload() / EOAM_VendSpecificMsg(oui=CableLabs_OUI) /
+ EOAM_DpoeMsg(dpoe_opcode=0x01,body=DeviceId())
+ )
# send message
- log.info('ONU-send-proxied-message')
+ log.info('ONU-send-proxied-message to Get Device Id for ONU: {}'.format(device.mac_address))
self.adapter_agent.send_proxied_message(device.proxy_address, msg)
# wait till we detect incoming message
yield self.incoming_messages.get()
+ log.info('ONU-response received for Get Device Id for ONU: {}'.format(device.mac_address))
+
+ #TODO Add a timeout to the above, if we do not recieve a message
+
+ #The above get request/ get response is done to verify the message exchange is
+ #functioning correctly, there is nothing to store from the response
+
# construct install of igmp query address
- msg = EOAMPayload(body=TibitOUI() /
- DPoEOpcode_SetRequest() /
- AddStaticMacAddress(mac='01:00:5e:00:00:01')
- )
+ msg = (
+ EOAMPayload() / EOAM_VendSpecificMsg(oui=CableLabs_OUI) /
+ EOAM_DpoeMsg(dpoe_opcode=0x03,body=AddStaticMacAddress(mac='01:00:5e:00:00:01')
+ ))
# send message
- log.info('ONU-send-proxied-message')
+ log.info('ONU-send-proxied-message to Set Static IGMP MAC address for ONU: {}'.format(device.mac_address))
self.adapter_agent.send_proxied_message(device.proxy_address, msg)
- # wait till we detect incoming message
- #frame = yield self.incoming_messages.get()
-
# Get and process the Set Response
ack = False
start_time = time.time()
@@ -504,7 +515,7 @@
#if (time.time() - start_time) > TIBIT_MSG_WAIT_TIME or (frame is None):
# break # don't wait forever
- respType = self._voltha_get_oam_msg_type(frame)
+ respType = self._get_oam_msg_type(frame)
log.info('Received OAM Message 0x %s' % str(respType))
#Check that the message received is a Set Response
@@ -512,17 +523,31 @@
ack = True
else:
# Handle unexpected events/OMCI messages
- self._voltha_check_resp(frame)
+ self._check_resp(frame)
# Verify Set Response
if ack:
- (rc,branch,leaf,status) = self._voltha_check_set_resp(frame)
- log.info('REturn from Set resp')
+ log.info('ONU-response received for Set Static IGMP MAC address for ONU: {}'.format(device.mac_address))
+ (rc,branch,leaf,status) = self._check_set_resp(frame)
if (rc == True):
log.info('Set Response had no errors')
else:
- log.info('Set Respose had errors')
- log.info('Branch 0x{:X} Leaf 0x{:0>4X} {}'.format(branch, leaf, DPoEVariableResponseCodes[status]))
+ log.info('Set Response had errors - Branch 0x{:X} Leaf 0x{:0>4X} {}'.format(branch, leaf, DPoEVariableResponseCodes[status]))
+
+ # construct multicast LLID set
+ # TODO - This is needed to support multicast traffic for GPON. This should only be done for a
+ # a GPON ONU and the UnicastLink value needs to come from the OLT. This will work only for
+ # a single GPON ONU.
+ msg = (
+ EOAMPayload() / EOAM_VendSpecificMsg(oui=CableLabs_OUI) /
+ EOAM_DpoeMsg(dpoe_opcode=0x06,body=MulticastRegisterSet(MulticastLink=0x10bc, UnicastLink=0x1008)
+ ))
+
+ # send message
+ log.info('ONU-send-proxied-message to Set Static IGMP MAC address for ONU: {}'.format(device.mac_address))
+ self.adapter_agent.send_proxied_message(device.proxy_address, msg)
+
+ # The MulticastRegisterSet does not currently return a response. Just hope it worked.
# by returning we allow the device to be shown as active, which
# indirectly verified that message passing works
@@ -593,170 +618,65 @@
lc = LoopingCall(_collect, device_id, prefix)
lc.start(interval=15) # TODO make this configurable
- def _voltha_get_oam_msg_type(self, frame):
+
+# Methods for Get / Set Response Processing from eoam_messages
+
+
+ def _get_oam_msg_type(self, frame):
+
respType = RxedOamMsgTypeEnum["Unknown"]
recv_frame = frame
- payload = recv_frame.payload
- if hasattr(payload, 'body'):
- loadstr = payload.body.load
- bytesRead = 0;
- if (payload.opcode == 0xFE):
- # Extract the OUI
- (oui_hi, oui_lo) = struct.unpack_from('>BH', loadstr, bytesRead)
- oui = (oui_hi << 16) | oui_lo
- log.debug('oui: 0x %06x' % oui)
- bytesRead += 3
-
- # If this is the ITU OUI, then there is an embedded OMCI message
- if (oui == 0x0019A7):
- respType = RxedOamMsgTypeEnum["OMCI Message"]
-
- # Treat Cablelabs OUI and Tibit OUI as the same
- elif ((oui == 0x001000) or (oui == 0x2AEA15)):
-
- (dpoeOpcode) = struct.unpack_from('>B', loadstr, bytesRead)[0]
- bytesRead += 1
-
- # Get Response
- if (dpoeOpcode == 0x02):
- respType = RxedOamMsgTypeEnum["DPoE Get Response"]
-
- # Set Response
- elif (dpoeOpcode == 0x04):
- respType = RxedOamMsgTypeEnum["DPoE Set Response"]
-
- # File Transfer ACK
- elif (dpoeOpcode == 0x09):
- respType = RxedOamMsgTypeEnum["DPoE File Transfer"]
-
- else:
- log.info('Unsupported OAM OUI 0x{:0>6X}'.format(oui))
-
- # Handle OAM Event Notification
- elif (payload.opcode == 0x01):
- respType = RxedOamMsgTypeEnum["Event Notification"]
+ if recv_frame.haslayer(EOAMPayload):
+ if recv_frame.haslayer(EOAMEvent):
+ recv_frame = RxedOamMsgTypeEnum["Event Notification"]
+ elif recv_frame.haslayer(EOAM_OmciMsg):
+ respType = RxedOamMsgTypeEnum["OMCI Message"]
else:
- log.info('Unsupported OAM Opcode {}'.format(payload.opcode))
+ dpoeOpcode = 0x00
+ if recv_frame.haslayer(EOAM_TibitMsg):
+ dpoeOpcode = recv_frame.getlayer(EOAM_TibitMsg).dpoe_opcode;
+ elif recv_frame.haslayer(EOAM_DpoeMsg):
+ dpoeOpcode = recv_frame.getlayer(EOAM_DpoeMsg).dpoe_opcode;
+
+ # Get Response
+ if (dpoeOpcode == 0x02):
+ respType = RxedOamMsgTypeEnum["DPoE Get Response"]
+
+ # Set Response
+ elif (dpoeOpcode == 0x04):
+ respType = RxedOamMsgTypeEnum["DPoE Set Response"]
+
+ # File Transfer ACK
+ elif (dpoeOpcode == 0x09):
+ respType = RxedOamMsgTypeEnum["DPoE File Transfer"]
+ else:
+ log.info('Unsupported DPoE Opcode {:0>2X}'.format(dpoeOpcode))
else:
- log.debug('received frame has no payload')
+ log.info('Invalid OAM Header')
return respType
- def _voltha_check_set_resp(self, frame):
- rc = False
- branch = 0
- leaf = 0
- status = 0
-
+ def _get_value_from_msg(self, frame, branch, leaf):
+ retVal = False
+ value = 0
recv_frame = frame
- payload = recv_frame.payload
- if hasattr(payload, 'body'):
- loadstr = payload.body.load
- bytesRead = 0;
- if (payload.opcode == 0xFE):
- # Extract the OUI
- (oui_hi, oui_lo) = struct.unpack_from('>BH', loadstr, bytesRead)
- oui = (oui_hi << 16) | oui_lo
- log.info('oui: 0x %06x' % oui)
- bytesRead += 3
-
- # Treat Cablelabs OUI and Tibit OUI as the same
- if ((oui == 0x001000) or (oui == 0x2AEA15)):
- (dpoeOpcode) = struct.unpack_from('>B', loadstr, bytesRead)[0]
- bytesRead += 1
-
- startOfTlvs = bytesRead
- # Set Response
- if (dpoeOpcode == 0x04):
- test =1
- (rc,branch,leaf,status) = self._voltha_check_set_resp_attrs(loadstr, startOfTlvs)
- if (rc == True):
- log.info('Set Response had no errors')
- else:
- log.debug('Branch 0x{:X} Leaf 0x{:0>4X} {}'.format(branch, leaf, DPoEVariableResponseCodes[status]))
- else:
- log.info('Unsupported DPoE Opcode: {} ({:0>2X})'.format(DPoEOpcodeEnum[dpoeOpcode], dpoeOpcode))
- else:
- log.info('Unsupported OAM OUI 0x{:0>6X}'. format(oui))
+ if recv_frame.haslayer(EOAMPayload):
+ payload = recv_frame.payload
+ if hasattr(payload, 'body'):
+ loadstr = payload.body.load
+ # Get a specific TLV value
+ (retVal,bytesRead,value,retbranch,retleaf) = self._handle_get_value(loadstr, 0, branch, leaf)
else:
- log.info('Unsupported OAM Opcode {}'.format(payload.opcode))
+ log.info('received frame has no payload')
else:
- log.debug('received frame has no payload')
-
- return rc,branch,leaf,status
-
-
- def _voltha_check_resp(self, frame):
- recv_frame = frame
- payload = recv_frame.payload
- if hasattr(payload, 'body'):
- loadstr = payload.body.load
- bytesRead = 0;
- if (payload.opcode == 0xFE):
-
- # Extract the OUI
- (oui_hi, oui_lo) = struct.unpack_from('>BH', loadstr, bytesRead)
- oui = (oui_hi << 16) | oui_lo
- log.info('oui: 0x %06x' % oui)
- bytesRead += 3
-
- # If this is the ITU OUI, then there is an embedded OMCI message
- if (oui == 0x0019A7):
- self._voltha_handle_omci(loadstr,bytesRead)
-
- # Treat Cablelabs OUI and Tibit OUI as the same
- elif ((oui == 0x001000) or (oui == 0x2AEA15)):
- log.debug('Recieved Response OUI 0x{:0>6X}'. format(oui))
- else:
- log.info('Unsupported OAM OUI 0x{:0>6X}'. format(oui))
-
- # Handle OAM Event Notification
- elif (payload.opcode == 0x01):
- self._voltha_handle_oam_event(loadstr, bytesRead)
- else:
- log.info('Unsupported OAM Opcode {}'.format(payload.opcode))
-
- else:
- log.debug('received frame has no payload')
+ log.info('Invalid OAM Header')
+ return retVal,value,
- def _voltha_handle_oam_event(self, loadstr, startOfEvent):
- bytesRead = startOfEvent
- (seq_num, tlv_type, ev_len, oui_hi, oui_lo) = struct.unpack_from('>HBBBH', loadstr, bytesRead)
- oui = (oui_hi << 16) | oui_lo
-
- log.info('seq_num: 0x%04x' % seq_num)
- log.info('tlv_type: 0x%' % tlv_type)
- log.info('ev_len: 0x%x' % ev_len)
- log.info('oui: 0x%06x"'% oui)
-
- if (tlv_type != 0xFE):
- log.debug('unexpected tlv_type 0x%x (expected 0xFE)' % tlv_type)
- elif (oui == 0x001000):
- log.debug('DPoE Event')
- ## TODO - Handle DPoE Event/Alarm
- elif (oui == 0x2AEA15):
- log.debug('Tibit-specific Event')
-
- # TODO - Handle addition/removal of links
-
- bytesRead = 7
-
- # TODO - Check OUI and parse Source and Reference Object Contexts
-
-
- def _voltha_handle_omci(self, loadstr, startOfEvent):
- bytesRead = startOfEvent
- log.debug('OMCI Message')
-
- # TODO - Handle OMCI message
-
-
-
- def _voltha_handle_get_value(self, loadstr, startOfTlvs, queryBranch, queryLeaf):
+ def _handle_get_value(self, loadstr, startOfTlvs, queryBranch, queryLeaf):
retVal = False;
value = 0
branch = 0
@@ -810,7 +730,89 @@
return retVal,bytesRead,value,branch,leaf
- def _voltha_check_set_resp_attrs(self, loadstr, startOfTlvs):
+
+ def _check_set_resp(self, frame):
+ rc = False
+ branch = 0
+ leaf = 0
+ status = 0
+ recv_frame = frame
+ if recv_frame.haslayer(EOAMPayload):
+ payload = recv_frame.payload
+ if hasattr(payload, 'body'):
+ loadstr = payload.body.load
+ # Get a specific TLV value
+ (rc,branch,leaf,status) = self._check_set_resp_attrs(loadstr, 0)
+ else:
+ log.info('received frame has no payload')
+ else:
+ log.info('Invalid OAM Header')
+ return rc,branch,leaf,status
+
+
+
+ def _check_resp(self, frame):
+ respType = RxedOamMsgTypeEnum["Unknown"]
+ recv_frame = frame
+ if recv_frame.haslayer(EOAMPayload):
+
+ if recv_frame.haslayer(EOAMEvent):
+ self.handle_oam_event(recv_frame)
+ elif recv_frame.haslayer(EOAM_OmciMsg):
+ self.handle_omci(recv_frame)
+ else:
+ dpoeOpcode = 0x00
+ if recv_frame.haslayer(EOAM_TibitMsg):
+ dpoeOpcode = recv_frame.getlayer(EOAM_TibitMsg).dpoe_opcode;
+ elif recv_frame.haslayer(EOAM_DpoeMsg):
+ dpoeOpcode = recv_frame.getlayer(EOAM_DpoeMsg).dpoe_opcode;
+
+ if hasattr(recv_frame, 'body'):
+ payload = recv_frame.payload
+ loadstr = payload.body.load
+
+ # Get Response
+ if (dpoeOpcode == 0x02):
+ # Get a specific TLV value
+ branch = 0xD7
+ leaf = 0x0006
+ (rc,bytesRead,value,retbranch,retleaf) = self._handle_get_value(loadstr, startOfTlvs, branch, leaf)
+ if (rc == True):
+ log.info('Branch 0x{:X} Leaf 0x{:0>4X} value = {}'.format(branch, leaf, value))
+ else:
+ log.info('Branch 0x{:X} Leaf 0x{:0>4X} no value'.format(branch, leaf))
+
+ # Walk through all TLV values
+ bytesRead = 0
+ rc = True
+ while(rc == True):
+ branch = 0
+ leaf = 0
+ (rc,bytesRead,value,branch,leaf) = self._handle_get_value(loadstr, bytesRead, branch, leaf)
+ if (rc == True):
+ log.info('Branch 0x{:0>2X} Leaf 0x{:0>4X} value = {}'.format(branch, leaf, value))
+ elif (branch != 0):
+ log.info('Branch 0x{:0>2X} Leaf 0x{:0>4X} no value'.format(branch, leaf))
+
+ # Set Response
+ elif (dpoeOpcode == 0x04):
+ (rc,branch,leaf,status) = self._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]))
+
+ # File Transfer ACK
+ elif (dpoeOpcode == 0x09):
+ rc = self._handle_fx_ack(loadstr, bytesRead, block_number)
+ else:
+ log.info('Unsupported DPoE Opcode {:0>2X}'.format(dpoeOpcode))
+ else:
+ log.info('Invalid OAM Header')
+
+ return respType
+
+ def _check_set_resp_attrs(self, loadstr, startOfTlvs):
retVal = True;
branch = 0
leaf = 0
@@ -820,14 +822,16 @@
while (bytesRead <= loadstrlen):
(branch, leaf) = struct.unpack_from('>BH', loadstr, bytesRead)
+# print "Branch/Leaf 0x{:0>2X}/0x{:0>4X}".format(branch, leaf)
if (branch != 0):
bytesRead += 3
length = struct.unpack_from('>B', loadstr, bytesRead)[0]
+# print "Length: 0x{:0>2X} ({})".format(length,length)
bytesRead += 1
if (length >= 0x80):
- log.debug('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, DPoEVariableResponseCodes[length]))
if (length > 0x80):
retVal = False;
break;
@@ -839,26 +843,22 @@
return retVal,branch,leaf,length
-
-
- def _voltha_handle_fx_ack(self, loadstr, startOfXfer, block_number):
+
+ def _handle_fx_ack(self, loadstr, startOfXfer, block_number):
retVal = False
(fx_opcode, acked_block, response_code) = struct.unpack_from('>BHB', loadstr, startOfXfer)
- log.debug('fx_opcode: 0x%x' % fx_opcode)
- log.debug('acked_block: 0x%x' % acked_block)
- log.debug('response_code: 0x%x' % response_code)
-
+ #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.debug('unexpected fx_opcode 0x%x (expected 0x03)' % fx_opcode)
+ log.info('unexpected fx_opcode 0x%x (expected 0x03)' % fx_opcode)
elif (acked_block != block_number):
- log.debug('unexpected acked_block 0x%x (expected 0x%x)' % (acked_block, block_number))
+ log.info('unexpected acked_block 0x%x (expected 0x%x)' % (acked_block, block_number))
elif (response_code != 0):
- log.debug('unexpected response_code 0x%x (expected 0x00)' % response_code)
+ log.info('unexpected response_code 0x%x (expected 0x00)' % response_code)
else:
- retVal = True;
-
-
-
+ retVal = True;
+
\ No newline at end of file
diff --git a/voltha/extensions/eoam/EOAM.py b/voltha/extensions/eoam/EOAM.py
index 9e6b709..56511d1 100644
--- a/voltha/extensions/eoam/EOAM.py
+++ b/voltha/extensions/eoam/EOAM.py
@@ -1,497 +1,551 @@
-#!/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, 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]])
-
-
-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=0xA8C8)
-
-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)
-
-
-class TBJSON(Packet):
- """ TBJSON 'packet' layer. """
- name = "TBJSON"
- fields_desc = [StrField("data", default="")]
-
-bind_layers(Ether, TBJSON, type=0xA8C8)
-
-
-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)
-
+#!/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
+from scapy.fields import StrField, X3BytesField
+from scapy.packet import Packet
+from scapy.fields import ByteEnumField, XShortField, XByteField, MACField, \
+ ByteField, BitEnumField, BitField, ShortField
+from scapy.fields import XLongField, StrFixedLenField, XIntField, \
+ FieldLenField, StrLenField, IntField
+
+import fcntl, socket, struct # for get hw address
+
+# 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
+
+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)
+
+
+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)
+
diff --git a/voltha/extensions/eoam/EOAM_TLV.py b/voltha/extensions/eoam/EOAM_TLV.py
index f0861cd..545490b 100644
--- a/voltha/extensions/eoam/EOAM_TLV.py
+++ b/voltha/extensions/eoam/EOAM_TLV.py
@@ -133,6 +133,11 @@
name = "DPoE Opcode"
fields_desc = [ByteEnumField("opcode", 0x07, DPoEOpcodeEnum)]
+class DPoEOpcode_FileTransfer(Packet):
+ """ DPoE Opcode"""
+ name = "DPoE Opcode"
+ fields_desc = [ByteEnumField("opcode", 0x09, DPoEOpcodeEnum)]
+
class MulticastRegisterSetSumitomo01(Packet):
""" Multicast Register: Multicast Register Set Sumitomo 01 """
name = "Multicast Register: Multicast Register Set Sumitomo 01"
@@ -157,11 +162,6 @@
XShortField("UnicastLink", 0x0000),
]
-class TibitOpcode_OmciMessage(Packet):
- """ DPoE Opcode"""
- name = "Tibit Opcode"
- fields_desc = [ByteEnumField("opcode", 0xA0, DPoEOpcodeEnum)]
-
####
#### PORT OBJECTS
####
@@ -898,6 +898,9 @@
name = "Variable Descriptor: FEC Mode"
fields_desc = [XByteField("branch", 0xD7),
XShortField("leaf", 0x0605),
+ XByteField("length", 2),
+ XByteField("downstream", 0x01),
+ XByteField("upstream", 0x01),
]
class MediaType(Packet):
@@ -1087,10 +1090,28 @@
XByteField("instance", 0),
XByteField("pon", 0),
StrField("unicastvssn", "TBIT"),
- XIntField("unicastlink", 0xe2222900),
+ XIntField("unicastlink", 0x00000000),
XByteField("pad", 0),
]
+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),
+ XShortField("leaf", 0x0501),
+ ByteField("length", 15),
+ XByteField("result", 3),
+ XByteField("oltqueuerule", 0x13),
+ XShortField("objecttype", 0x0001),
+ XByteField("instance", 0),
+ XByteField("pon", 0),
+ XIntField("unicastvssn", 0x00000000),
+ XIntField("unicastlink", 0x00000000),
+ XByteField("pad", 0),
+ ]
+
+
+
# __TIBIT_OLT_OAM__: Defined by Tibit
class PortIngressRuleResultOLTBroadcastQueue(Packet):
""" Variable Descriptor: Port Ingress Rule Result OLT Broadcast Queue """
@@ -1260,6 +1281,15 @@
XShortField("leaf", 0x0101),
]
+class OltModeSet(Packet):
+ """ Variable Descriptor: OLT Mode """
+ name = "Variable Descriptor: "
+ fields_desc = [XByteField("branch", 0xB7),
+ XShortField("leaf", 0x0101),
+ XByteField("length", 1),
+ XByteField("value", 0),
+ ]
+
class OltPonAdminState(Packet):
""" Variable Descriptor: OLT PON Admin State """
name = "Variable Descriptor: "
@@ -1299,6 +1329,66 @@
XShortField("value", 0x1234),
]
+class OnuMode(Packet):
+ """ Variable Descriptor: ONU Mode """
+ name = "Variable Descriptor: "
+ fields_desc = [XByteField("branch", 0xB7),
+ XShortField("leaf", 0x0105),
+ ]
+
+class OnuModeSet(Packet):
+ """ Variable Descriptor: ONU Mode """
+ name = "Variable Descriptor: "
+ fields_desc = [XByteField("branch", 0xB7),
+ XShortField("leaf", 0x0105),
+ XByteField("length", 1),
+ XByteField("value", 0),
+ ]
+
+class TibitGrantSpacing(Packet):
+ """ Variable Descriptor: Grant Spacing """
+ name = "Variable Descriptor: "
+ fields_desc = [XByteField("branch", 0xB7),
+ XShortField("leaf", 0x0106),
+ ]
+
+class TibitGrantSpacingSet(Packet):
+ """ Variable Descriptor: Grant Spacing """
+ name = "Variable Descriptor: "
+ fields_desc = [XByteField("branch", 0xB7),
+ 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),
+ XShortField("leaf", 0x0107),
+ ]
+
+class TibitBurstOverheadProfilesSet(Packet):
+ """ Variable Descriptor: Burst Overhead Profiles """
+ name = "Variable Descriptor: "
+ fields_desc = [XByteField("branch", 0xB7),
+ XShortField("leaf", 0x0107),
+ # Length is one + 5 for each entry
+ XByteField("length", 6),
+ XByteField("num_profiles", 1),
+ ]
+
+class TibitBurstOverheadProfilesEntry(Packet):
+ """ Variable Descriptor: Burst Overhead Profile Entry """
+ name = "Burst Profile Entry:"
+ fields_desc = [XByteField("laser_on_time", 0x28),
+ XByteField("laser_off_time", 0x28),
+ XShortField("sync_time", 0x0040),
+ XByteField("us_fec", 1),
+ ]
+
+
+
UpstreamSlaSubtypeEnum = { 0x00: "Terminator",
0x01: "Header",
0x02: "Max Grant Period",