Updates to Tibit Adapters
Change-Id: I8bd15d2a1a7c5d56da0923f50876017a56cee49f
diff --git a/voltha/adapters/tibit_olt/tibit_olt.py b/voltha/adapters/tibit_olt/tibit_olt.py
index 9f1e5d3..57fc1f2 100644
--- a/voltha/adapters/tibit_olt/tibit_olt.py
+++ b/voltha/adapters/tibit_olt/tibit_olt.py
@@ -43,10 +43,13 @@
from common.frameio.frameio import BpfProgramFilter, hexify
from voltha.adapters.interface import IAdapterInterface
+
from voltha.extensions.eoam.EOAM import EOAMPayload, EOAMEvent, EOAM_VendSpecificMsg
from voltha.extensions.eoam.EOAM import EOAM_OmciMsg, EOAM_TibitMsg, EOAM_DpoeMsg
from voltha.extensions.eoam.EOAM import OAM_ETHERTYPE
from voltha.extensions.eoam.EOAM import CableLabs_OUI, Tibit_OUI, IEEE_OUI
+from voltha.extensions.eoam.EOAM import RxedOamMsgTypeEnum, Dpoe_Opcodes, get_oam_msg_type, \
+ handle_get_value, get_value_from_msg, check_set_resp, check_resp
from voltha.extensions.eoam.EOAM_TLV import DOLTObject, \
NetworkToNetworkPortObject, OLTUnicastLogicalLink, \
@@ -119,23 +122,6 @@
is_tibit_frame = BpfProgramFilter('{} or {}'.format(
frame_match_case1, frame_match_case2))
-### Received OAM Message Types
-RxedOamMsgTypeEnum = {
- "Unknown": 0x00,
- # Info PDU - not currently used
- "Info": 0x01,
- # Event Notification - Tibit or DPoE Event
- "Event Notification": 0x02,
- "DPoE Get Response": 0x03,
- "DPoE Set Response": 0x04,
- # Specifically - a File Transfer ACK
- "DPoE File Transfer": 0x05,
- # Contains an embedded OMCI message
- "OMCI Message": 0x06,
- }
-
-Dpoe_Opcodes = {v: k for k, v in DPoEOpcodeEnum.iteritems()}
-
# TODO: This information should be conveyed to the adapter
# from a higher level.
@@ -235,13 +221,13 @@
#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)
+ respType = get_oam_msg_type(log, frame)
if (respType == RxedOamMsgTypeEnum["DPoE Get Response"]):
ack = True
else:
# Handle unexpected events/OMCI messages
- self._check_resp(frame)
+ check_resp(log, frame)
except Exception as e:
log.exception('launch device failed', e=e)
@@ -343,13 +329,13 @@
#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)
+ respType = get_oam_msg_type(log, frame)
if (respType == RxedOamMsgTypeEnum["DPoE Get Response"]):
ack = True
else:
# Handle unexpected events/OMCI messages
- self._check_resp(frame)
+ check_resp(log, frame)
if ack:
#Process the Get Response
@@ -359,7 +345,7 @@
for pair in branch_leaf_pairs:
temp_pair = pair
- (rc, value) = (self._get_value_from_msg(frame, pair[0], pair[1]))
+ (rc, value) = (get_value_from_msg(log, frame, pair[0], pair[1]))
temp_pair.append(rc)
temp_pair.append(value)
if rc:
@@ -573,7 +559,7 @@
for pair in branch_leaf_pairs:
temp_pair = pair
- (rc, value) = (self._get_value_from_msg(frame, pair[0], pair[1]))
+ (rc, value) = (get_value_from_msg(log, frame, pair[0], pair[1]))
temp_pair.append(rc)
temp_pair.append(value)
if rc:
@@ -1206,20 +1192,20 @@
#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)
+ respType = get_oam_msg_type(log, frame)
if (respType == RxedOamMsgTypeEnum["DPoE Get Response"]):
ack = True
else:
# Handle unexpected events/OMCI messages
- self._check_resp(frame)
+ check_resp(log, 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]))
+ (rc, value) = (get_value_from_msg(log, frame, pair[0], pair[1]))
if rc:
log.info('Response for Branch 0x{:X} Leaf 0x{:0>4X} '.format(pair[0], pair[1]))
@@ -1245,20 +1231,20 @@
#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)
+ respType = get_oam_msg_type(log, frame)
if (respType == RxedOamMsgTypeEnum["DPoE Get Response"]):
ack = True
else:
# Handle unexpected events/OMCI messages
- self._check_resp(frame)
+ check_resp(log, 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]))
+ (rc, value) = (get_value_from_msg(log, 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))
@@ -1304,239 +1290,6 @@
# Methods for Get / Set Response Processing from eoam_messages
-
- def _get_oam_msg_type(self, frame):
-
- respType = RxedOamMsgTypeEnum["Unknown"]
- recv_frame = frame
-
- 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:
- 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.info('Invalid OAM Header')
-
- log.info('Received OAM Message 0x %s' % str(respType))
-
- return respType
-
-
- def _get_value_from_msg(self, frame, branch, leaf):
- retVal = False
- value = 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
- (retVal,bytesRead,value,retbranch,retleaf) = self._handle_get_value(loadstr, 0, branch, leaf)
- else:
- log.info('received frame has no payload')
- else:
- log.info('Invalid OAM Header')
- return retVal,value,
-
-
- def _handle_get_value(self, loadstr, startOfTlvs, queryBranch, queryLeaf):
- retVal = False;
- value = 0
- branch = 0
- leaf = 0
- bytesRead = startOfTlvs
- loadstrlen = len(loadstr)
-
- while (bytesRead <= loadstrlen):
- (branch, leaf) = struct.unpack_from('>BH', loadstr, bytesRead)
-
- if (branch != 0):
- bytesRead += 3
- length = struct.unpack_from('>B', loadstr, bytesRead)[0]
- bytesRead += 1
-
- if (length == 1):
- value = struct.unpack_from(">B", loadstr, bytesRead)[0]
- elif (length == 2):
- value = struct.unpack_from(">H", loadstr, bytesRead)[0]
- elif (length == 4):
- value = struct.unpack_from(">I", loadstr, bytesRead)[0]
- elif (length == 8):
- value = struct.unpack_from(">Q", loadstr, bytesRead)[0]
- else:
- if (length >= 0x80):
- log.info('Branch 0x{:0>2X} Leaf 0x{:0>4X} {}'.format(branch, leaf, DPoEVariableResponseCodes[length]))
- # Set length to zero so bytesRead doesn't get mistakenly incremented below
- length = 0
- else:
- # Attributes with a length of zero are actually 128 bytes long
- if (length == 0):
- length = 128;
- valStr = ">{}s".format(length)
- value = struct.unpack_from(valStr, loadstr, bytesRead)[0]
-
- if (length > 0):
- bytesRead += length
-
- if (branch != 0xD6):
- if ( ((queryBranch == 0) and (queryLeaf == 0)) or
- ((queryBranch == branch) and (queryLeaf == leaf)) ):
- # Prevent zero-lengthed values from returning success
- if (length > 0):
- retVal = True;
- break
- else:
- break
-
- if (retVal == False):
- value = 0
-
- return retVal,bytesRead,value,branch,leaf
-
-
- 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):
- 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
- length = 0
- bytesRead = startOfTlvs
- loadstrlen = len(loadstr)
-
- 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.info('Branch 0x{:0>2X} Leaf 0x{:0>4X} {}'.format(branch, leaf, DPoEVariableResponseCodes[length]))
- if (length > 0x80):
- retVal = False;
- break;
- else:
- bytesRead += length
-
- else:
- break
-
- return retVal,branch,leaf,length
-
-
- def _handle_fx_ack(self, loadstr, startOfXfer, block_number):
- retVal = False
- (fx_opcode, acked_block, response_code) = struct.unpack_from('>BHB', loadstr, startOfXfer)
-
- #print "fx_opcode: 0x%x" % fx_opcode
- #print "acked_block: 0x%x" % acked_block
- #print "response_code: 0x%x" % response_code
-
-
- if (fx_opcode != 0x03):
- log.info('unexpected fx_opcode 0x%x (expected 0x03)' % fx_opcode)
- elif (acked_block != block_number):
- log.info('unexpected acked_block 0x%x (expected 0x%x)' % (acked_block, block_number))
- elif (response_code != 0):
- log.info('unexpected response_code 0x%x (expected 0x00)' % response_code)
- else:
- retVal = True;
-
@inlineCallbacks
def _handle_set_resp(self, olt_mac, action, retcode):
# Get and process the Set Response
@@ -1548,7 +1301,7 @@
#TODO - Need to add proper timeout functionality
- respType = self._get_oam_msg_type(frame)
+ respType = get_oam_msg_type(log, frame)
log.info('Received OAM Message 0x %s' % str(respType))
#Check that the message received is a Set Response
@@ -1556,12 +1309,12 @@
ack = True
else:
# Handle unexpected events/OMCI messages
- self._check_resp(frame)
+ check_resp(log, frame)
# Verify Set Response
rc = False
if ack:
- (rc,branch,leaf,status) = self._check_set_resp(frame)
+ (rc,branch,leaf,status) = check_set_resp(log, frame)
if (rc is False):
log.info('Set Response had errors - Branch 0x{:X} Leaf 0x{:0>4X} {}'.format(branch, leaf, DPoEVariableResponseCodes[status]))
diff --git a/voltha/adapters/tibit_onu/tibit_onu.py b/voltha/adapters/tibit_onu/tibit_onu.py
index 7b2dc7e..ee37bd4 100644
--- a/voltha/adapters/tibit_onu/tibit_onu.py
+++ b/voltha/adapters/tibit_onu/tibit_onu.py
@@ -58,6 +58,7 @@
log = structlog.get_logger()
+from voltha.extensions.eoam.EOAM_TLV import UserPortObject
from voltha.extensions.eoam.EOAM_TLV import AddStaticMacAddress, DeleteStaticMacAddress
from voltha.extensions.eoam.EOAM_TLV import ClearStaticMacTable
from voltha.extensions.eoam.EOAM_TLV import DeviceId
@@ -67,6 +68,17 @@
from voltha.extensions.eoam.EOAM_TLV import DPoEOpcode_MulticastRegister, MulticastRegisterSet
from voltha.extensions.eoam.EOAM_TLV import VendorName, OnuMode, HardwareVersion, ManufacturerInfo
from voltha.extensions.eoam.EOAM_TLV import SlowProtocolsSubtypeEnum, DeviceReset
+from voltha.extensions.eoam.EOAM_TLV import DONUObject, \
+ UserPortObject, PonPortObject, \
+ PortIngressRuleClauseMatchLength00, PortIngressRuleClauseMatchLength01, \
+ PortIngressRuleClauseMatchLength02, PortIngressRuleResultForward, \
+ PortIngressRuleResultSet, PortIngressRuleResultInsert, \
+ PortIngressRuleResultCopy, PortIngressRuleResultReplace, \
+ PortIngressRuleResultDelete, PortIngressRuleResultOLTQueue, \
+ PortIngressRuleTerminator, AddPortIngressRule
+from voltha.extensions.eoam.EOAM_TLV import PortIngressRuleHeader
+from voltha.extensions.eoam.EOAM_TLV import ClauseSubtypeEnum
+from voltha.extensions.eoam.EOAM_TLV import RuleOperatorEnum
from voltha.extensions.eoam.EOAM_TLV import EndOfPDU
from voltha.extensions.eoam.EOAM import EOAMPayload, EOAMEvent, EOAM_VendSpecificMsg
@@ -74,26 +86,11 @@
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
+from voltha.extensions.eoam.EOAM import RxedOamMsgTypeEnum, Dpoe_Opcodes, get_oam_msg_type, \
+ handle_get_value, get_value_from_msg, check_set_resp, check_resp
TIBIT_MSG_WAIT_TIME = 3
-### Received OAM Message Types
-RxedOamMsgTypeEnum = {
- "Unknown": 0x00,
- # Info PDU - not currently used
- "Info": 0x01,
- # Event Notification - Tibit or DPoE Event
- "Event Notification": 0x02,
- "DPoE Get Response": 0x03,
- "DPoE Set Response": 0x04,
- # Specifically - a File Transfer ACK
- "DPoE File Transfer": 0x05,
- # Contains an embedded OMCI message
- "OMCI Message": 0x06,
- }
-
-Dpoe_Opcodes = {v: k for k, v in DPoEOpcodeEnum.iteritems()}
-
@implementer(IAdapterInterface)
class TibitOnuAdapter(object):
@@ -308,12 +305,9 @@
if in_port == 2:
log.info('#### Upstream Rule ####')
- up_req = (
- EOAMPayload() / EOAM_VendSpecificMsg(oui=CableLabs_OUI) /
- EOAM_DpoeMsg(dpoe_opcode=Dpoe_Opcodes["Set Request"])
- )
- #TODO - There is no body to the message above, is there ever an Upstream Rule
+ up_req = UserPortObject()
+ up_req /= PortIngressRuleHeader(precedence=precedence)
for field in get_ofb_fields(flow):
@@ -332,6 +326,8 @@
elif field.type == VLAN_VID:
_vlan_vid = field.vlan_vid & 0xfff
log.info('#### field.type == VLAN_VID ####', vlan=_vlan_vid)
+ up_req /= PortIngressRuleClauseMatchLength02(fieldcode=Clause['C-VLAN Tag'], fieldinstance=0,
+ operator=Operator['=='], match=_vlan_vid)
elif field.type == VLAN_PCP:
_vlan_pcp = field.vlan_pcp
@@ -339,11 +335,15 @@
elif field.type == UDP_DST:
_udp_dst = field.udp_dst
- log.info('#### field.type == UDP_DST ####')
+ log.info('#### field.type == UDP_DST ####', udp_dst=_udp_dst)
elif field.type == IPV4_DST:
_ipv4_dst = field.ipv4_dst
- log.info('#### field.type == IPV4_DST ####')
+ log.info('#### field.type == IPV4_DST ####', ipv4_dst=_ipv4_dst)
+
+ elif field.type == METADATA:
+ _metadata = field.table_metadata
+ log.info('#### field.type == METADATA ####', metadata=_metadata)
else:
log.info('#### field.type == NOT IMPLEMENTED!! ####')
@@ -354,15 +354,17 @@
if action.type == OUTPUT:
log.info('#### action.type == OUTPUT ####')
+ up_req /= PortIngressRuleResultInsert(fieldcode=Clause['C-VLAN Tag'])
elif action.type == POP_VLAN:
log.info('#### action.type == POP_VLAN ####')
elif action.type == PUSH_VLAN:
log.info('#### action.type == PUSH_VLAN ####')
- if action.push.ethertype != 0x8100:
- log.error('unhandled-tpid',
- ethertype=action.push.ethertype)
+ up_req /= PortIngressRuleResultInsert(fieldcode=Clause['C-VLAN Tag'])
+# if action.push.ethertype != 0x8100:
+# log.error('unhandled-tpid',
+# ethertype=action.push.ethertype)
elif action.type == SET_FIELD:
log.info('#### action.type == SET_FIELD ####')
@@ -370,7 +372,9 @@
ofp.OFPXMC_OPENFLOW_BASIC)
field = action.set_field.field.ofb_field
if field.type == VLAN_VID:
- pass
+ log.info("#### action.field.vlan {} ####".format(field.vlan_vid & 0xfff))
+ up_req /= PortIngressRuleResultSet(
+ fieldcode=Clause['C-VLAN Tag'], value=field.vlan_vid & 0xfff)
else:
log.error('unsupported-action-set-field-type',
field_type=field.type)
@@ -378,8 +382,31 @@
log.error('UNSUPPORTED-ACTION-TYPE',
action_type=action.type)
+ up_req /= PortIngressRuleTerminator()
+ up_req /= AddPortIngressRule()
+
+ msg = (
+ EOAMPayload() / EOAM_VendSpecificMsg(oui=CableLabs_OUI) /
+ EOAM_DpoeMsg(dpoe_opcode = Dpoe_Opcodes["Set Request"], body=up_req)/
+ EndOfPDU()
+ )
+
+ # send message
+ action = "Set ONU US Rule"
+ log.info('ONU-send-proxied-message to {} for ONU: {}'.format(action, device.mac_address))
+ self.adapter_agent.send_proxied_message(device.proxy_address, msg)
+
+ # Get and process the Set Response
+ rc = []
+ yield self._handle_set_resp(device, action, rc)
+
+
elif in_port == 1:
log.info('#### Downstream Rule ####')
+ Is_MCast = False
+
+ dn_req = PonPortObject()
+ dn_req /= PortIngressRuleHeader(precedence=precedence)
#### Loop through fields again...
@@ -393,7 +420,7 @@
elif field.type == IP_PROTO:
_proto = field.ip_proto
log.info('#### field.type == IP_PROTO ####', in_port=in_port,
- ip_proto=ip_proto)
+ ip_proto=_proto)
elif field.type == IN_PORT:
_port = field.port
@@ -418,20 +445,8 @@
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() / EOAM_VendSpecificMsg(oui=CableLabs_OUI) /
- EOAM_DpoeMsg(dpoe_opcode=Dpoe_Opcodes["Set Request"], body=AddStaticMacAddress(mac=mcastIp2McastMac('%d.%d.%d.%d' % (a,b,c,d)))
- ))
-
- # send message
- action = "Set Static IP MCAST address"
- log.info('ONU-send-proxied-message to {} for ONU: {}'.format(action, device.mac_address))
- self.adapter_agent.send_proxied_message(device.proxy_address,
- dn_req)
-
- # Get and process the Set Response
- rc = []
- yield self._handle_set_resp(device, action, rc)
+ dn_req = AddStaticMacAddress(mac=mcastIp2McastMac('%d.%d.%d.%d' % (a,b,c,d)))
+ Is_MCast = True
else:
raise NotImplementedError('field.type={}'.format(
@@ -444,6 +459,11 @@
elif action.type == POP_VLAN:
log.info('#### action.type == POP_VLAN ####')
+ dn_req /= PortIngressRuleClauseMatchLength02(fieldcode=Clause['C-VLAN Tag'], fieldinstance=0,
+ operator=Operator['=='], match=_vlan_vid)
+ dn_req /= PortIngressRuleResultReplace(fieldcode=Clause['C-VLAN Tag'])
+ dn_req /= PortIngressRuleResultSet(
+ fieldcode=Clause['C-VLAN Tag'], value=field.vlan_vid & 0xfff)
elif action.type == PUSH_VLAN:
log.info('#### action.type == PUSH_VLAN ####')
@@ -457,7 +477,11 @@
ofp.OFPXMC_OPENFLOW_BASIC)
field = action.set_field.field.ofb_field
if field.type == VLAN_VID:
- pass
+ dn_req /= PortIngressRuleClauseMatchLength02(fieldcode=Clause['C-VLAN Tag'], fieldinstance=0,
+ operator=Operator['=='], match=_vlan_vid)
+ dn_req /= PortIngressRuleResultReplace(fieldcode=Clause['C-VLAN Tag'])
+ dn_req /= PortIngressRuleResultSet(
+ fieldcode=Clause['C-VLAN Tag'], value=field.vlan_vid & 0xfff)
else:
log.error('unsupported-action-set-field-type',
field_type=field.type)
@@ -466,6 +490,27 @@
log.error('UNSUPPORTED-ACTION-TYPE',
action_type=action.type)
+ if Is_MCast is True:
+ action = "Set Static IP MCAST address"
+ else:
+ dn_req /= PortIngressRuleTerminator()
+ dn_req /= AddPortIngressRule()
+ action = "Set ONU DS Rule"
+
+ msg = (
+ EOAMPayload() / EOAM_VendSpecificMsg(oui=CableLabs_OUI) /
+ EOAM_DpoeMsg(dpoe_opcode = Dpoe_Opcodes["Set Request"], body=dn_req)/
+ EndOfPDU()
+ )
+
+ # send message
+ log.info('ONU-send-proxied-message to {} for ONU: {}'.format(action, device.mac_address))
+ self.adapter_agent.send_proxied_message(device.proxy_address, msg)
+
+ # Get and process the Set Response
+ rc = []
+ yield self._handle_set_resp(device, action, rc)
+
else:
raise Exception('Port should be 1 or 2 by our convention')
@@ -510,13 +555,13 @@
while not ack:
frame = yield self.incoming_messages.get()
- respType = self._get_oam_msg_type(frame)
+ respType = get_oam_msg_type(log, frame)
if (respType == RxedOamMsgTypeEnum["DPoE Get Response"]):
ack = True
else:
# Handle unexpected events/OMCI messages
- self._check_resp(frame)
+ check_resp(log, frame)
if ack:
log.info('ONU-response received for Get Version Info for ONU: {}'.format(device.mac_address))
@@ -609,235 +654,6 @@
# Methods for Get / Set Response Processing from eoam_messages
- def _get_oam_msg_type(self, frame):
-
- respType = RxedOamMsgTypeEnum["Unknown"]
- recv_frame = frame
-
- 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:
- 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.info('Invalid OAM Header')
-
- return respType
-
-
- def _get_value_from_msg(self, frame, branch, leaf):
- retVal = False
- value = 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
- (retVal,bytesRead,value,retbranch,retleaf) = self._handle_get_value(loadstr, 0, branch, leaf)
- else:
- log.info('received frame has no payload')
- else:
- log.info('Invalid OAM Header')
- return retVal,value,
-
-
- def _handle_get_value(self, loadstr, startOfTlvs, queryBranch, queryLeaf):
- retVal = False;
- value = 0
- branch = 0
- leaf = 0
- bytesRead = startOfTlvs
- loadstrlen = len(loadstr)
-
- while (bytesRead <= loadstrlen):
- (branch, leaf) = struct.unpack_from('>BH', loadstr, bytesRead)
-
- if (branch != 0):
- bytesRead += 3
- length = struct.unpack_from('>B', loadstr, bytesRead)[0]
- bytesRead += 1
-
- if (length == 1):
- value = struct.unpack_from(">B", loadstr, bytesRead)[0]
- elif (length == 2):
- value = struct.unpack_from(">H", loadstr, bytesRead)[0]
- elif (length == 4):
- value = struct.unpack_from(">I", loadstr, bytesRead)[0]
- elif (length == 8):
- value = struct.unpack_from(">Q", loadstr, bytesRead)[0]
- else:
- if (length >= 0x80):
- log.info('Branch 0x{:0>2X} Leaf 0x{:0>4X} {}'.format(branch, leaf, DPoEVariableResponseCodes[length]))
- # Set length to zero so bytesRead doesn't get mistakenly incremented below
- length = 0
- else:
- # Attributes with a length of zero are actually 128 bytes long
- if (length == 0):
- length = 128;
- valStr = ">{}s".format(length)
- value = struct.unpack_from(valStr, loadstr, bytesRead)[0]
-
- if (length > 0):
- bytesRead += length
-
- if (branch != 0xD6):
- if ( ((queryBranch == 0) and (queryLeaf == 0)) or
- ((queryBranch == branch) and (queryLeaf == leaf)) ):
- # Prevent zero-lengthed values from returning success
- if (length > 0):
- retVal = True;
- break
- else:
- break
-
- if (retVal == False):
- value = 0
-
- return retVal,bytesRead,value,branch,leaf
-
-
- 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):
- 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
- length = 0
- bytesRead = startOfTlvs
- loadstrlen = len(loadstr)
-
- 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.info('Branch 0x{:0>2X} Leaf 0x{:0>4X} {}'.format(branch, leaf, DPoEVariableResponseCodes[length]))
- if (length > 0x80):
- retVal = False;
- break;
- else:
- bytesRead += length
-
- else:
- break
-
- return retVal,branch,leaf,length
-
- def _handle_fx_ack(self, loadstr, startOfXfer, block_number):
- retVal = False
- (fx_opcode, acked_block, response_code) = struct.unpack_from('>BHB', loadstr, startOfXfer)
-
- #print "fx_opcode: 0x%x" % fx_opcode
- #print "acked_block: 0x%x" % acked_block
- #print "response_code: 0x%x" % response_code
-
-
- if (fx_opcode != 0x03):
- log.info('unexpected fx_opcode 0x%x (expected 0x03)' % fx_opcode)
- elif (acked_block != block_number):
- log.info('unexpected acked_block 0x%x (expected 0x%x)' % (acked_block, block_number))
- elif (response_code != 0):
- log.info('unexpected response_code 0x%x (expected 0x00)' % response_code)
- else:
- retVal = True;
-
@inlineCallbacks
def _send_igmp_mcast_addr(self, device):
# construct install of igmp query address
@@ -887,7 +703,7 @@
#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)
+ respType = get_oam_msg_type(log, frame)
log.info('Received OAM Message 0x %s' % str(respType))
#Check that the message received is a Set Response
@@ -895,12 +711,12 @@
ack = True
else:
# Handle unexpected events/OMCI messages
- self._check_resp(frame)
+ check_resp(log, frame)
# Verify Set Response
rc = False
if ack:
- (rc,branch,leaf,status) = self._check_set_resp(frame)
+ (rc,branch,leaf,status) = check_set_resp(log, frame)
if (rc is False):
log.info('Set Response had errors - Branch 0x{:X} Leaf 0x{:0>4X} {}'.format(branch, leaf, DPoEVariableResponseCodes[status]))
@@ -921,7 +737,7 @@
for pair in branch_leaf_pairs:
temp_pair = pair
- (rc, value) = (self._get_value_from_msg(frame, pair[0], pair[1]))
+ (rc, value) = (get_value_from_msg(log, frame, pair[0], pair[1]))
temp_pair.append(rc)
temp_pair.append(value)
if rc:
diff --git a/voltha/extensions/eoam/EOAM.py b/voltha/extensions/eoam/EOAM.py
index 56511d1..6dab1a8 100644
--- a/voltha/extensions/eoam/EOAM.py
+++ b/voltha/extensions/eoam/EOAM.py
@@ -44,6 +44,261 @@
EOAM_MULTICAST_ADDRESS = '01:80:c2:00:00:02'
IGMP_MULTICAST_ADDRESS = '01:00:5e:00:00:01' # for test
+
+
+
+### Received OAM Message Types
+RxedOamMsgTypeEnum = {
+ "Unknown": 0x00,
+ # Info PDU - not currently used
+ "Info": 0x01,
+ # Event Notification - Tibit or DPoE Event
+ "Event Notification": 0x02,
+ "DPoE Get Response": 0x03,
+ "DPoE Set Response": 0x04,
+ # Specifically - a File Transfer ACK
+ "DPoE File Transfer": 0x05,
+ # Contains an embedded OMCI message
+ "OMCI Message": 0x06,
+ }
+
+Dpoe_Opcodes = {v: k for k, v in DPoEOpcodeEnum.iteritems()}
+
+def get_oam_msg_type(log, frame):
+
+ respType = RxedOamMsgTypeEnum["Unknown"]
+ recv_frame = frame
+
+ 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:
+ 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.info('Invalid OAM Header')
+
+ log.info('Received OAM Message 0x %s' % str(respType))
+
+ return respType
+
+def handle_get_value(log, loadstr, startOfTlvs, queryBranch, queryLeaf):
+ retVal = False;
+ value = 0
+ branch = 0
+ leaf = 0
+ bytesRead = startOfTlvs
+ loadstrlen = len(loadstr)
+
+ while (bytesRead <= loadstrlen):
+ (branch, leaf) = struct.unpack_from('>BH', loadstr, bytesRead)
+
+ if (branch != 0):
+ bytesRead += 3
+ length = struct.unpack_from('>B', loadstr, bytesRead)[0]
+ bytesRead += 1
+
+ if (length == 1):
+ value = struct.unpack_from(">B", loadstr, bytesRead)[0]
+ elif (length == 2):
+ value = struct.unpack_from(">H", loadstr, bytesRead)[0]
+ elif (length == 4):
+ value = struct.unpack_from(">I", loadstr, bytesRead)[0]
+ elif (length == 8):
+ value = struct.unpack_from(">Q", loadstr, bytesRead)[0]
+ else:
+ if (length >= 0x80):
+ log.info('Branch 0x{:0>2X} Leaf 0x{:0>4X} {}'.format(branch, leaf, DPoEVariableResponseCodes[length]))
+ # Set length to zero so bytesRead doesn't get mistakenly incremented below
+ length = 0
+ else:
+ # Attributes with a length of zero are actually 128 bytes long
+ if (length == 0):
+ length = 128;
+ valStr = ">{}s".format(length)
+ value = struct.unpack_from(valStr, loadstr, bytesRead)[0]
+
+ if (length > 0):
+ bytesRead += length
+
+ if (branch != 0xD6):
+ if ( ((queryBranch == 0) and (queryLeaf == 0)) or
+ ((queryBranch == branch) and (queryLeaf == leaf)) ):
+ # Prevent zero-lengthed values from returning success
+ if (length > 0):
+ retVal = True;
+ break
+ else:
+ break
+
+ if (retVal == False):
+ value = 0
+
+ return retVal,bytesRead,value,branch,leaf
+
+
+def get_value_from_msg(log, frame, branch, leaf):
+ retVal = False
+ value = 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
+ (retVal,bytesRead,value,retbranch,retleaf) = handle_get_value(log, loadstr, 0, branch, leaf)
+ else:
+ log.info('received frame has no payload')
+ else:
+ log.info('Invalid OAM Header')
+ return retVal,value,
+
+def check_set_resp_attrs(log, loadstr, startOfTlvs):
+ retVal = True;
+ branch = 0
+ leaf = 0
+ length = 0
+ bytesRead = startOfTlvs
+ loadstrlen = len(loadstr)
+
+ 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.info('Branch 0x{:0>2X} Leaf 0x{:0>4X} {}'.format(branch, leaf, DPoEVariableResponseCodes[length]))
+ if (length > 0x80):
+ retVal = False;
+ break;
+ else:
+ bytesRead += length
+
+ else:
+ break
+
+ return retVal,branch,leaf,length
+
+def check_set_resp(log, 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) = check_set_resp_attrs(log, loadstr, 0)
+ else:
+ log.info('received frame has no payload')
+ else:
+ log.info('Invalid OAM Header')
+ return rc,branch,leaf,status
+
+
+
+def check_resp(log, frame):
+ respType = RxedOamMsgTypeEnum["Unknown"]
+ recv_frame = frame
+ if recv_frame.haslayer(EOAMPayload):
+
+ if recv_frame.haslayer(EOAMEvent):
+# handle_oam_event(recv_frame)
+ pass
+ elif recv_frame.haslayer(EOAM_OmciMsg):
+# handle_omci(recv_frame)
+ pass
+ 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):
+ bytesRead = 0
+ rc = True
+ while(rc == True):
+ branch = 0
+ leaf = 0
+ (rc,bytesRead,value,branch,leaf) = handle_get_value(log, 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) = 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 = handle_fx_ack(log, loadstr, bytesRead, block_number)
+ else:
+ log.info('Unsupported DPoE Opcode {:0>2X}'.format(dpoeOpcode))
+ else:
+ log.info('Invalid OAM Header')
+
+ return respType
+
+
+
+def handle_fx_ack(log, loadstr, startOfXfer, block_number):
+ retVal = False
+ (fx_opcode, acked_block, response_code) = struct.unpack_from('>BHB', loadstr, startOfXfer)
+
+ #print "fx_opcode: 0x%x" % fx_opcode
+ #print "acked_block: 0x%x" % acked_block
+ #print "response_code: 0x%x" % response_code
+
+ if (fx_opcode != 0x03):
+ log.info('unexpected fx_opcode 0x%x (expected 0x03)' % fx_opcode)
+ elif (acked_block != block_number):
+ log.info('unexpected acked_block 0x%x (expected 0x%x)' % (acked_block, block_number))
+ elif (response_code != 0):
+ log.info('unexpected response_code 0x%x (expected 0x00)' % response_code)
+ else:
+ retVal = True;
+
+
+
+
class EOAM():
""" EOAM frame layer """
def __init__(self, ctag=None, dryrun=False, stag=None,