VOL-1224: The ONU Adapter must support deletion of a Service Flow using the Open OMCI MEs
VOL-1389: Support Transparent C-tag handling in OpenOLT and BRCM OpenOMCI adapters
Change-Id: I7a3c89d68180fd94a744db6082ecdf695635c635
diff --git a/voltha/adapters/brcm_openomci_onu/brcm_openomci_onu.py b/voltha/adapters/brcm_openomci_onu/brcm_openomci_onu.py
index ad89dc8..8df0b09 100644
--- a/voltha/adapters/brcm_openomci_onu/brcm_openomci_onu.py
+++ b/voltha/adapters/brcm_openomci_onu/brcm_openomci_onu.py
@@ -56,7 +56,8 @@
id=name,
vendor_ids=['OPEN', 'ALCL', 'BRCM', 'TWSH', 'ALPH', 'ISKT', 'SFAA', 'BBSM'],
adapter=name,
- accepts_bulk_flow_update=True
+ accepts_bulk_flow_update=True,
+ accepts_add_remove_flow_updates=True
)
]
@@ -208,7 +209,20 @@
return handler.update_flow_table(device, flows.items)
def update_flows_incrementally(self, device, flow_changes, group_changes):
- raise NotImplementedError()
+ log.info('incremental-flow-update', device_id=device.id,
+ flows=flow_changes, groups=group_changes)
+ # For now, there is no support for group changes
+ assert len(group_changes.to_add.items) == 0
+ assert len(group_changes.to_remove.items) == 0
+
+ handler = self.devices_handlers[device.id]
+ # Remove flows
+ if len(flow_changes.to_remove.items) != 0:
+ handler.remove_onu_flows(device, flow_changes.to_remove.items)
+
+ # Add flows
+ if len(flow_changes.to_add.items) != 0:
+ handler.add_onu_flows(device, flow_changes.to_add.items)
def send_proxied_message(self, proxy_address, msg):
log.debug('send-proxied-message', proxy_address=proxy_address, msg=msg)
diff --git a/voltha/adapters/brcm_openomci_onu/brcm_openomci_onu_handler.py b/voltha/adapters/brcm_openomci_onu/brcm_openomci_onu_handler.py
index f2aa656..0f759f3 100644
--- a/voltha/adapters/brcm_openomci_onu/brcm_openomci_onu_handler.py
+++ b/voltha/adapters/brcm_openomci_onu/brcm_openomci_onu_handler.py
@@ -602,31 +602,254 @@
if _type is not None:
self.log.warn('ignoring-flow-with-ethType', ethType=_type)
elif _set_vlan_vid is None or _set_vlan_vid == 0:
- self.log.warn('ignorning-flow-that-does-not-set-vlanid')
+ self.log.warn('ignoring-flow-that-does-not-set-vlanid')
else:
self.log.warn('set-vlanid', uni_id=uni_port.port_number, set_vlan_vid=_set_vlan_vid)
- self._add_vlan_filter_task(device, uni_port, _set_vlan_vid)
+ self._do_vlan_filter_task(device, flow.cookie, add_tag=True,
+ uni_port=uni_port, _set_vlan_vid=_set_vlan_vid)
except Exception as e:
self.log.exception('failed-to-install-flow', e=e, flow=flow)
+ def add_onu_flows(self, device, flows):
+ self.log.debug('function-entry', device=device, flows=flows)
- def _add_vlan_filter_task(self, device, uni_port, _set_vlan_vid):
- assert uni_port is not None
+ #
+ # We need to proxy through the OLT to get to the ONU
+ # Configuration from here should be using OMCI
+ #
+ # self.log.info('bulk-flow-update', device_id=device.id, flows=flows)
+
+ # no point in pushing omci flows if the device isnt reachable
+ if device.connect_status != ConnectStatus.REACHABLE or \
+ device.admin_state != AdminState.ENABLED:
+ self.log.warn("device-disabled-or-offline-skipping-flow-update",
+ admin=device.admin_state, connect=device.connect_status)
+ return
+
+ for flow in flows:
+ # if incoming flow contains cookie, then add to ONU
+ if flow.cookie:
+ _type = None
+ _port = None
+ _vlan_vid = None
+ _udp_dst = None
+ _udp_src = None
+ _ipv4_dst = None
+ _ipv4_src = None
+ _metadata = None
+ _output = None
+ _push_tpid = None
+ _field = None
+ _set_vlan_vid = None
+ self.log.debug("add-flow", device_id=device.id, flow=flow)
+
+ def is_downstream(port):
+ return port == self._pon_port_number
+
+ def is_upstream(port):
+ return not is_downstream(port)
+
+ try:
+ _in_port = fd.get_in_port(flow)
+ assert _in_port is not None
+
+ _out_port = fd.get_out_port(flow) # may be None
+
+ if is_downstream(_in_port):
+ self.log.debug('downstream-flow', in_port=_in_port, out_port=_out_port)
+ uni_port = self.uni_port(_out_port)
+ elif is_upstream(_in_port):
+ self.log.debug('upstream-flow', in_port=_in_port, out_port=_out_port)
+ uni_port = self.uni_port(_in_port)
+ else:
+ raise Exception('port should be 1 or 2 by our convention')
+
+ self.log.debug('flow-ports', in_port=_in_port, out_port=_out_port, uni_port=str(uni_port))
+
+ for field in fd.get_ofb_fields(flow):
+ if field.type == fd.ETH_TYPE:
+ _type = field.eth_type
+ self.log.debug('field-type-eth-type',
+ eth_type=_type)
+
+ elif field.type == fd.IP_PROTO:
+ _proto = field.ip_proto
+ self.log.debug('field-type-ip-proto',
+ ip_proto=_proto)
+
+ elif field.type == fd.IN_PORT:
+ _port = field.port
+ self.log.debug('field-type-in-port',
+ in_port=_port)
+
+ elif field.type == fd.VLAN_VID:
+ _vlan_vid = field.vlan_vid & 0xfff
+ self.log.debug('field-type-vlan-vid',
+ vlan=_vlan_vid)
+
+ elif field.type == fd.VLAN_PCP:
+ _vlan_pcp = field.vlan_pcp
+ self.log.debug('field-type-vlan-pcp',
+ pcp=_vlan_pcp)
+
+ elif field.type == fd.UDP_DST:
+ _udp_dst = field.udp_dst
+ self.log.debug('field-type-udp-dst',
+ udp_dst=_udp_dst)
+
+ elif field.type == fd.UDP_SRC:
+ _udp_src = field.udp_src
+ self.log.debug('field-type-udp-src',
+ udp_src=_udp_src)
+
+ elif field.type == fd.IPV4_DST:
+ _ipv4_dst = field.ipv4_dst
+ self.log.debug('field-type-ipv4-dst',
+ ipv4_dst=_ipv4_dst)
+
+ elif field.type == fd.IPV4_SRC:
+ _ipv4_src = field.ipv4_src
+ self.log.debug('field-type-ipv4-src',
+ ipv4_dst=_ipv4_src)
+
+ elif field.type == fd.METADATA:
+ _metadata = field.table_metadata
+ self.log.debug('field-type-metadata',
+ metadata=_metadata)
+
+ else:
+ raise NotImplementedError('field.type={}'.format(
+ field.type))
+
+ for action in fd.get_actions(flow):
+
+ if action.type == fd.OUTPUT:
+ _output = action.output.port
+ self.log.debug('action-type-output',
+ output=_output, in_port=_in_port)
+
+ elif action.type == fd.POP_VLAN:
+ self.log.debug('action-type-pop-vlan',
+ in_port=_in_port)
+
+ elif action.type == fd.PUSH_VLAN:
+ _push_tpid = action.push.ethertype
+ self.log.debug('action-type-push-vlan',
+ push_tpid=_push_tpid, in_port=_in_port)
+ if action.push.ethertype != 0x8100:
+ self.log.error('unhandled-tpid',
+ ethertype=action.push.ethertype)
+
+ elif action.type == fd.SET_FIELD:
+ _field = action.set_field.field.ofb_field
+ assert (action.set_field.field.oxm_class ==
+ OFPXMC_OPENFLOW_BASIC)
+ self.log.debug('action-type-set-field',
+ field=_field, in_port=_in_port)
+ if _field.type == fd.VLAN_VID:
+ _set_vlan_vid = _field.vlan_vid & 0xfff
+ self.log.debug('set-field-type-vlan-vid',
+ vlan_vid=_set_vlan_vid)
+ else:
+ self.log.error('unsupported-action-set-field-type',
+ field_type=_field.type)
+ else:
+ self.log.error('unsupported-action-type',
+ action_type=action.type, in_port=_in_port)
+
+ # TODO: We only set vlan omci flows. Handle omci matching ethertypes at some point in another task
+ if _type is not None:
+ self.log.warn('ignoring-flow-with-ethType', ethType=_type)
+ elif _set_vlan_vid is None or _set_vlan_vid == 0:
+ self.log.warn('ignoring-flow-that-does-not-set-vlanid')
+ else:
+ self.log.warn('set-vlanid', uni_id=uni_port.port_number, set_vlan_vid=_set_vlan_vid)
+ self._do_vlan_filter_task(device, flow.cookie, add_tag=True,
+ uni_port=uni_port, _set_vlan_vid=_set_vlan_vid)
+
+ except Exception as e:
+ self.log.exception('failed-to-install-flow', e=e, flow=flow)
+
+ def remove_onu_flows(self, device, flows):
+ self.log.debug('function-entry', device=device, flows=flows)
+
+ # no point in removing omci flows if the device isnt reachable
+ if device.connect_status != ConnectStatus.REACHABLE or \
+ device.admin_state != AdminState.ENABLED:
+ self.log.warn("device-disabled-or-offline-skipping-remove-flow",
+ admin=device.admin_state, connect=device.connect_status)
+ return
+
+ for flow in flows:
+ # if incoming flow contains cookie, then remove from ONU
+ if flow.cookie:
+ self.log.debug("remove-flow", device_id=device.id, flow=flow)
+
+ def is_downstream(port):
+ return port == self._pon_port_number
+
+ def is_upstream(port):
+ return not is_downstream(port)
+
+ try:
+ _in_port = fd.get_in_port(flow)
+ assert _in_port is not None
+
+ _out_port = fd.get_out_port(flow) # may be None
+
+ if is_downstream(_in_port):
+ self.log.debug('downstream-flow', in_port=_in_port, out_port=_out_port)
+ uni_port = self.uni_port(_out_port)
+ elif is_upstream(_in_port):
+ self.log.debug('upstream-flow', in_port=_in_port, out_port=_out_port)
+ uni_port = self.uni_port(_in_port)
+ else:
+ raise Exception('port should be 1 or 2 by our convention')
+
+ self.log.debug('flow-ports', in_port=_in_port, out_port=_out_port, uni_port=str(uni_port))
+
+ # Deleting flow from ONU.
+ self._do_vlan_filter_task(device, flow.cookie, add_tag=False, uni_port=uni_port)
+ except Exception as e:
+ self.log.exception('failed-to-remove-flow', e=e)
+
+ def _do_vlan_filter_task(self, device, flow_cookie, add_tag=True, uni_port=None, _set_vlan_vid=None):
+ task_name = 'removing-vlan-tag'
+ if add_tag:
+ assert uni_port is not None
+ task_name = 'setting-vlan-tag'
def success(_results):
- self.log.info('vlan-tagging-success', uni_port=uni_port, vlan=_set_vlan_vid)
- device.reason = 'omci-flows-pushed'
+ if add_tag:
+ self.log.info('vlan-tagging-success', _results=_results)
+ device.reason = 'omci-flows-pushed'
+ self.log.debug('Flow-addition-success', cookie=flow_cookie)
+ else:
+ self.log.info('vlan-untagging-success', _results=_results)
+ device.reason = 'omci-flows-deleted'
+ self.log.debug('Flow-removal-success', cookie=flow_cookie)
+
self._vlan_filter_task = None
def failure(_reason):
- self.log.warn('vlan-tagging-failure', uni_port=uni_port, vlan=_set_vlan_vid)
- device.reason = 'omci-flows-failed-retrying'
- self._vlan_filter_task = reactor.callLater(_STARTUP_RETRY_WAIT,
- self._add_vlan_filter_task, device, uni_port, _set_vlan_vid)
+ if add_tag:
+ self.log.warn('vlan-tagging-failure', _reason=_reason)
+ device.reason = 'omci-flows-addition-failed-retrying'
+ self._vlan_filter_task = reactor.callLater(_STARTUP_RETRY_WAIT,
+ self._do_vlan_filter_task, device, flow_cookie,
+ add_tag=True, uni_port=uni_port,
+ _set_vlan_vid=_set_vlan_vid)
+ else:
+ self.log.warn('vlan-untagging-failure', _reason=_reason)
+ device.reason = 'omci-flows-deletion-failed-retrying'
+ self._vlan_filter_task = reactor.callLater(_STARTUP_RETRY_WAIT,
+ self._do_vlan_filter_task, device, flow_cookie,
+ add_tag=False)
- self.log.info('setting-vlan-tag')
- self._vlan_filter_task = BrcmVlanFilterTask(self.omci_agent, self.device_id, uni_port, _set_vlan_vid)
+ self.log.info(task_name)
+ self._vlan_filter_task = BrcmVlanFilterTask(self.omci_agent, self.device_id, uni_port, _set_vlan_vid,
+ add_tag=add_tag)
self._deferred = self._onu_omci_device.task_runner.queue_task(self._vlan_filter_task)
self._deferred.addCallbacks(success, failure)
diff --git a/voltha/adapters/brcm_openomci_onu/omci/brcm_vlan_filter_task.py b/voltha/adapters/brcm_openomci_onu/omci/brcm_vlan_filter_task.py
index 6c665c7..2ed8f33 100644
--- a/voltha/adapters/brcm_openomci_onu/omci/brcm_vlan_filter_task.py
+++ b/voltha/adapters/brcm_openomci_onu/omci/brcm_vlan_filter_task.py
@@ -18,9 +18,12 @@
from twisted.internet.defer import inlineCallbacks, failure, returnValue
from voltha.extensions.omci.omci_defs import ReasonCodes, EntityOperations
from voltha.extensions.omci.omci_me import *
+from voltha.adapters.brcm_openomci_onu.uni_port import UniType
+from voltha.adapters.brcm_openomci_onu.pon_port import BRDCM_DEFAULT_VLAN, DEFAULT_TPID
RC = ReasonCodes
OP = EntityOperations
+RESERVED_VLAN = 4095
class BrcmVlanFilterException(Exception):
@@ -34,13 +37,16 @@
task_priority = 200
name = "Broadcom VLAN Filter Task"
- def __init__(self, omci_agent, device_id, uni_port, set_vlan_id, priority=task_priority):
+ def __init__(self, omci_agent, device_id, uni_port, set_vlan_id, add_tag=True,
+ priority=task_priority):
"""
Class initialization
:param omci_agent: (OmciAdapterAgent) OMCI Adapter agent
:param device_id: (str) ONU Device ID
+ :param uni_port: (UniPort) UNI port
:param set_vlan_id: (int) VLAN to filter for and set
+ :param add_tag: (bool) Flag to identify VLAN Tagging or Untagging
:param priority: (int) OpenOMCI Task priority (0..255) 255 is the highest
"""
@@ -57,6 +63,12 @@
self._results = None
self._local_deferred = None
self._config = self._device.configuration
+ self._add_tag = add_tag
+
+ # Port numbers
+ self._input_tpid = DEFAULT_TPID
+ self._output_tpid = DEFAULT_TPID
+ self._cvid = BRDCM_DEFAULT_VLAN
def cancel_deferred(self):
super(BrcmVlanFilterTask, self).cancel_deferred()
@@ -73,117 +85,197 @@
Start Vlan Tagging Task
"""
super(BrcmVlanFilterTask, self).start()
- self._local_deferred = reactor.callLater(0, self.perform_vlan_tagging)
+ self._local_deferred = reactor.callLater(0, self.perform_vlan_tagging, add_tag=self._add_tag)
@inlineCallbacks
- def perform_vlan_tagging(self):
+ def perform_vlan_tagging(self, add_tag=True):
"""
Perform the vlan tagging
"""
- self.log.info('setting-vlan-tagging')
+ if add_tag:
+ self.log.info('setting-vlan-tagging')
+ else:
+ self.log.info('removing-vlan-tagging')
try:
# TODO: parameterize these from the handler, or objects in the handler
# TODO: make this a member of the onu gem port or the uni port
_mac_bridge_service_profile_entity_id = 0x201
_mac_bridge_port_ani_entity_id = 0x2102 # TODO: can we just use the entity id from the anis list?
+
+ vlan_tagging_entity_id = _mac_bridge_port_ani_entity_id + self._uni_port.mac_bridge_port_num
+ extended_vlan_tagging_entity_id = _mac_bridge_service_profile_entity_id + \
+ self._uni_port.mac_bridge_port_num
+
# Delete bridge ani side vlan filter
- msg = VlanTaggingFilterDataFrame(_mac_bridge_port_ani_entity_id + self._uni_port.mac_bridge_port_num)
- frame = msg.delete()
- self.log.debug('openomci-msg', omci_msg=msg)
- self.strobe_watchdog()
- results = yield self._device.omci_cc.send(frame)
- self.check_status_and_state(results, 'flow-delete-vlan-tagging-filter-data')
+ yield self._send_msg(VlanTaggingFilterDataFrame(vlan_tagging_entity_id), 'delete',
+ 'flow-delete-vlan-tagging-filter-data')
- # Re-Create bridge ani side vlan filter
- msg = VlanTaggingFilterDataFrame(
- _mac_bridge_port_ani_entity_id + self._uni_port.mac_bridge_port_num, # Entity ID
- vlan_tcis=[self._set_vlan_id], # VLAN IDs
- forward_operation=0x10
- )
- frame = msg.create()
- self.log.debug('openomci-msg', omci_msg=msg)
- self.strobe_watchdog()
- results = yield self._device.omci_cc.send(frame)
- self.check_status_and_state(results, 'flow-create-vlan-tagging-filter-data')
+ forward_operation = 0x10 # VID investigation
+ # When the PUSH VLAN is RESERVED_VLAN (4095), let ONU be transparent
+ if self._set_vlan_id == RESERVED_VLAN:
+ forward_operation = 0x00 # no investigation, ONU transparent
- # Re-Create bridge ani side vlan filter
-
- # Update uni side extended vlan filter
- # filter for untagged
- # probably for eapol
- # TODO: Create constants for the operation values. See omci spec
- attributes = dict(
- received_frame_vlan_tagging_operation_table=
- VlanTaggingOperation(
- filter_outer_priority=15,
- filter_outer_vid=4096,
- filter_outer_tpid_de=0,
-
- filter_inner_priority=15,
- filter_inner_vid=4096,
- filter_inner_tpid_de=0,
- filter_ether_type=0,
-
- treatment_tags_to_remove=0,
- treatment_outer_priority=15,
- treatment_outer_vid=0,
- treatment_outer_tpid_de=0,
-
- treatment_inner_priority=0,
- treatment_inner_vid=self._set_vlan_id,
- treatment_inner_tpid_de=4
+ if add_tag:
+ # Re-Create bridge ani side vlan filter
+ msg = VlanTaggingFilterDataFrame(
+ vlan_tagging_entity_id, # Entity ID
+ vlan_tcis=[self._set_vlan_id], # VLAN IDs
+ forward_operation=forward_operation
)
- )
- msg = ExtendedVlanTaggingOperationConfigurationDataFrame(
- _mac_bridge_service_profile_entity_id + self._uni_port.mac_bridge_port_num, # Bridge Entity ID
- attributes=attributes # See above
- )
- frame = msg.set()
- self.log.debug('openomci-msg', omci_msg=msg)
- self.strobe_watchdog()
- results = yield self._device.omci_cc.send(frame)
- self.check_status_and_state(results,
- 'flow-set-ext-vlan-tagging-op-config-data-untagged')
+ yield self._send_msg(msg, 'create', 'flow-create-vlan-tagging-filter-data')
+ else:
+ # Delete bridge ani side vlan filter
+ msg = VlanTaggingFilterDataFrame(
+ vlan_tagging_entity_id # Entity ID
+ )
+ yield self._send_msg(msg, 'delete', 'flow-delete-vlan-tagging-filter-data')
- # Update uni side extended vlan filter
- # filter for vlan 0
- # TODO: Create constants for the operation values. See omci spec
- attributes = dict(
- received_frame_vlan_tagging_operation_table=
- VlanTaggingOperation(
+ # Delete uni side extended vlan filter
+ msg = ExtendedVlanTaggingOperationConfigurationDataFrame(
+ extended_vlan_tagging_entity_id # Bridge Entity ID
+ )
+ yield self._send_msg(msg, 'delete', 'flow-delete-ext-vlan-tagging-op-config-data')
+
+ # Create uni side extended vlan filter
+ if add_tag:
+ # When flow is removed and immediately re-added tech_profile specific task is not re-played, hence
+ # Extended VLAN Tagging Operation configuration which is part of tech_profile specific task is not
+ # getting created. To create it, we do Extended VLAN Tagging Operation configuration here.
+ # TODO: do this for all uni/ports...
+ # TODO: magic. static variable for assoc_type
+
+ omci_cc = self._device.omci_cc
+ # default to PPTP
+ if self._uni_port.type is UniType.VEIP:
+ association_type = 10
+ elif self._uni_port.type is UniType.PPTP:
+ association_type = 2
+ else:
+ association_type = 2
+
+ attributes = dict(
+ association_type=association_type, # Assoc Type, PPTP/VEIP Ethernet UNI
+ associated_me_pointer=self._uni_port.entity_id, # Assoc ME, PPTP/VEIP Entity Id
+
+ # See VOL-1311 - Need to set table during create to avoid exception
+ # trying to read back table during post-create-read-missing-attributes
+ # But, because this is a R/W attribute. Some ONU may not accept the
+ # value during create. It is repeated again in a set below.
+ input_tpid=self._input_tpid, # input TPID
+ output_tpid=self._output_tpid, # output TPID
+ )
+
+ msg = ExtendedVlanTaggingOperationConfigurationDataFrame(
+ extended_vlan_tagging_entity_id, # Bridge Entity ID
+ attributes=attributes
+ )
+ yield self._send_msg(msg, 'create', 'create-extended-vlan-tagging-operation-configuration-data')
+
+ attributes = dict(
+ # Specifies the TPIDs in use and that operations in the downstream direction are
+ # inverse to the operations in the upstream direction
+ input_tpid=self._input_tpid, # input TPID
+ output_tpid=self._output_tpid, # output TPID
+ downstream_mode=0, # inverse of upstream
+ )
+
+ msg = ExtendedVlanTaggingOperationConfigurationDataFrame(
+ extended_vlan_tagging_entity_id, # Bridge Entity ID
+ attributes=attributes
+ )
+ yield self._send_msg(msg, 'set', 'set-extended-vlan-tagging-operation-configuration-data')
+
+ # parameters: Entity Id ( 0x900), Filter Inner Vlan Id(0x1000-4096,do not filter on Inner vid,
+ # Treatment Inner Vlan Id : 2
+
+ # Update uni side extended vlan filter
+ # filter for untagged
+ # probably for eapol
+ # TODO: lots of magic
+ # TODO: magic 0x1000 / 4096?
+ attributes = self._generate_attributes(
filter_outer_priority=15, # This entry is not a double-tag rule
filter_outer_vid=4096, # Do not filter on the outer VID value
filter_outer_tpid_de=0, # Do not filter on the outer TPID field
- filter_inner_priority=8, # Filter on inner vlan
- filter_inner_vid=0x0, # Look for vlan 0
- filter_inner_tpid_de=0, # Do not filter on inner TPID field
- filter_ether_type=0, # Do not filter on EtherType
+ filter_inner_priority=15, filter_inner_vid=4096, filter_inner_tpid_de=0, filter_ether_type=0,
+ treatment_tags_to_remove=0, treatment_outer_priority=15, treatment_outer_vid=0,
+ treatment_outer_tpid_de=0, treatment_inner_priority=0, treatment_inner_vid=self._cvid,
+ treatment_inner_tpid_de=4)
- treatment_tags_to_remove=1,
- treatment_outer_priority=15,
- treatment_outer_vid=0,
- treatment_outer_tpid_de=0,
-
- treatment_inner_priority=8, # Add an inner tag and insert this value as the priority
- treatment_inner_vid=self._set_vlan_id, # use this value as the VID in the inner VLAN tag
- treatment_inner_tpid_de=4, # set TPID
+ msg = ExtendedVlanTaggingOperationConfigurationDataFrame(
+ extended_vlan_tagging_entity_id, # Bridge Entity ID
+ attributes=attributes
)
- )
- msg = ExtendedVlanTaggingOperationConfigurationDataFrame(
- _mac_bridge_service_profile_entity_id + self._uni_port.mac_bridge_port_num, # Bridge Entity ID
- attributes=attributes # See above
- )
- frame = msg.set()
- self.log.debug('openomci-msg', omci_msg=msg)
- self.strobe_watchdog()
- results = yield self._device.omci_cc.send(frame)
- self.check_status_and_state(results,
- 'flow-set-ext-vlan-tagging-op-config-data-zero-tagged')
+ yield self._send_msg(msg, 'set', 'set-extended-vlan-tagging-operation-configuration-data-table')
+
+ if self._set_vlan_id == RESERVED_VLAN:
+ # Transparently send any single tagged packet.
+ # Any other specific rules will take priority over this
+ attributes = self._generate_attributes(
+ filter_outer_priority=15, filter_outer_vid=4096, filter_outer_tpid_de=0,
+ filter_inner_priority=14, filter_inner_vid=4096, filter_inner_tpid_de=0, filter_ether_type=0,
+ treatment_tags_to_remove=0, treatment_outer_priority=15, treatment_outer_vid=0,
+ treatment_outer_tpid_de=0, treatment_inner_priority=15, treatment_inner_vid=0,
+ treatment_inner_tpid_de=4)
+
+ msg = ExtendedVlanTaggingOperationConfigurationDataFrame(
+ extended_vlan_tagging_entity_id, # Bridge Entity ID
+ attributes=attributes # See above
+ )
+ yield self._send_msg(msg, 'set',
+ 'flow-set-ext-vlan-tagging-op-config-data-single-tag-fwd-transparent')
+ else:
+ # Update uni side extended vlan filter
+ # filter for untagged
+ # probably for eapol
+ # TODO: Create constants for the operation values. See omci spec
+ attributes = self._generate_attributes(
+ filter_outer_priority=15, filter_outer_vid=4096, filter_outer_tpid_de=0,
+ filter_inner_priority=15, filter_inner_vid=4096, filter_inner_tpid_de=0, filter_ether_type=0,
+ treatment_tags_to_remove=0, treatment_outer_priority=15, treatment_outer_vid=0,
+ treatment_outer_tpid_de=0, treatment_inner_priority=0, treatment_inner_vid=self._set_vlan_id,
+ treatment_inner_tpid_de=4)
+
+ msg = ExtendedVlanTaggingOperationConfigurationDataFrame(
+ extended_vlan_tagging_entity_id, # Bridge Entity ID
+ attributes=attributes # See above
+ )
+ yield self._send_msg(msg, 'set', 'flow-set-ext-vlan-tagging-op-config-data-untagged')
+
+ # Update uni side extended vlan filter
+ # filter for vlan 0
+ # TODO: Create constants for the operation values. See omci spec
+ attributes = self._generate_attributes(
+ filter_outer_priority=15, # This entry is not a double-tag rule
+ filter_outer_vid=4096, # Do not filter on the outer VID value
+ filter_outer_tpid_de=0, # Do not filter on the outer TPID field
+
+ filter_inner_priority=8, # Filter on inner vlan
+ filter_inner_vid=0x0, # Look for vlan 0
+ filter_inner_tpid_de=0, # Do not filter on inner TPID field
+ filter_ether_type=0, # Do not filter on EtherType
+
+ treatment_tags_to_remove=1, treatment_outer_priority=15, treatment_outer_vid=0,
+ treatment_outer_tpid_de=0,
+
+ treatment_inner_priority=8, # Add an inner tag and insert this value as the priority
+ treatment_inner_vid=self._set_vlan_id, # use this value as the VID in the inner VLAN tag
+ treatment_inner_tpid_de=4) # set TPID
+
+ msg = ExtendedVlanTaggingOperationConfigurationDataFrame(
+ extended_vlan_tagging_entity_id, # Bridge Entity ID
+ attributes=attributes # See above
+ )
+ yield self._send_msg(msg, 'set', 'flow-set-ext-vlan-tagging-op-config-data-zero-tagged')
+ else:
+ msg = ExtendedVlanTaggingOperationConfigurationDataFrame(
+ extended_vlan_tagging_entity_id # Bridge Entity ID
+ )
+ yield self._send_msg(msg, 'delete', 'flow-delete-ext-vlan-tagging-op-config-data')
self.deferred.callback(self)
-
except Exception as e:
self.log.exception('setting-vlan-tagging', e=e)
self.deferred.errback(failure.Failure(e))
@@ -214,3 +306,53 @@
elif status == RC.InstanceExists:
return False
+
+ @inlineCallbacks
+ def _send_msg(self, msg, operation, vlan_tagging_operation_msg):
+ """
+ Send frame to ONU.
+
+ :param msg: (VlanTaggingFilterDataFrame/ExtendedVlanTaggingOperationConfigurationDataFrame) message used
+ to generate OMCI frame
+ :param operation: (str) type of CUD(Create/Update/Delete) operation
+ :param vlan_tagging_operation_msg: (str) what operation was being performed
+ """
+ if operation == 'create':
+ frame = msg.create()
+ elif operation == 'set':
+ frame = msg.set()
+ else:
+ frame = msg.delete()
+ self.log.debug('openomci-msg', omci_msg=msg)
+ self.strobe_watchdog()
+ results = yield self._device.omci_cc.send(frame)
+ self.check_status_and_state(results, vlan_tagging_operation_msg)
+
+ def _generate_attributes(self, **kwargs):
+ """
+ Generate ExtendedVlanTaggingOperation attributes
+
+ :return: (dict) ExtendedVlanTaggingOperation attributes dictinary
+ """
+ return dict(
+ received_frame_vlan_tagging_operation_table=
+ VlanTaggingOperation(
+ filter_outer_priority=kwargs['filter_outer_priority'],
+ filter_outer_vid=kwargs['filter_outer_vid'],
+ filter_outer_tpid_de=kwargs['filter_outer_tpid_de'],
+
+ filter_inner_priority=kwargs['filter_inner_priority'],
+ filter_inner_vid=kwargs['filter_inner_vid'],
+ filter_inner_tpid_de=kwargs['filter_inner_tpid_de'],
+ filter_ether_type=kwargs['filter_ether_type'],
+
+ treatment_tags_to_remove=kwargs['treatment_tags_to_remove'],
+ treatment_outer_priority=kwargs['treatment_outer_priority'],
+ treatment_outer_vid=kwargs['treatment_outer_vid'],
+ treatment_outer_tpid_de=kwargs['treatment_outer_tpid_de'],
+
+ treatment_inner_priority=kwargs['treatment_inner_priority'],
+ treatment_inner_vid=kwargs['treatment_inner_vid'],
+ treatment_inner_tpid_de=kwargs['treatment_inner_tpid_de'],
+ )
+ )
diff --git a/voltha/adapters/openolt/openolt_flow_mgr.py b/voltha/adapters/openolt/openolt_flow_mgr.py
index acfcbfd..99d387c 100644
--- a/voltha/adapters/openolt/openolt_flow_mgr.py
+++ b/voltha/adapters/openolt/openolt_flow_mgr.py
@@ -40,6 +40,7 @@
# FIXME - see also BRDCM_DEFAULT_VLAN in broadcom_onu.py
DEFAULT_MGMT_VLAN = 4091
+RESERVED_VLAN = 4095
# Openolt Flow
UPSTREAM = "upstream"
@@ -803,10 +804,12 @@
classifier.eth_type = classifier_info[ETH_TYPE]
if IP_PROTO in classifier_info:
classifier.ip_proto = classifier_info[IP_PROTO]
- if VLAN_VID in classifier_info:
- classifier.o_vid = classifier_info[VLAN_VID]
- if METADATA in classifier_info:
- classifier.i_vid = classifier_info[METADATA]
+ if VLAN_VID in classifier_info and \
+ classifier_info[VLAN_VID] != RESERVED_VLAN:
+ classifier.o_vid = classifier_info[VLAN_VID]
+ if METADATA in classifier_info and \
+ classifier_info[METADATA] != RESERVED_VLAN:
+ classifier.i_vid = classifier_info[METADATA]
if VLAN_PCP in classifier_info:
classifier.o_pbits = classifier_info[VLAN_PCP]
if UDP_SRC in classifier_info:
diff --git a/voltha/extensions/omci/omci_me.py b/voltha/extensions/omci/omci_me.py
index a8a2d05..990cf8f 100644
--- a/voltha/extensions/omci/omci_me.py
+++ b/voltha/extensions/omci/omci_me.py
@@ -75,7 +75,7 @@
of its point of attachment, the specified tagging operations refer to the
upstream direction.
"""
- def __init__(self, entity_id, attributes):
+ def __init__(self, entity_id, attributes=None):
"""
:param entity_id: (int) This attribute uniquely identifies each instance of
this managed entity. Its value is the same as that