VOL-484: delete and addition of flows are not working on ASFvOLT16
Change-Id: I70c8ad6b2402cc3d468ac76cba6cb47f1ea2de13
diff --git a/voltha/adapters/asfvolt16_olt/asfvolt16_device_handler.py b/voltha/adapters/asfvolt16_olt/asfvolt16_device_handler.py
index 653d978..043ce4c 100644
--- a/voltha/adapters/asfvolt16_olt/asfvolt16_device_handler.py
+++ b/voltha/adapters/asfvolt16_olt/asfvolt16_device_handler.py
@@ -1860,7 +1860,9 @@
ASFVOLT_DOWNLINK_EAPOL_ID,
ASFVOLT16_DEFAULT_VLAN)
elif 'push_vlan' in action:
- #self.del_flow(v_enet, ASFVOLT_EAPOL_ID, ASFVOLT_DOWNLINK_EAPOL_ID)
+ yield self.del_eapol_flow(v_enet, ASFVOLT_EAPOL_ID,
+ ASFVOLT_DOWNLINK_EAPOL_ID,
+ ASFVOLT16_DEFAULT_VLAN)
yield self.prepare_and_add_eapol_flow(classifier, action, v_enet,
ASFVOLT_EAPOL_ID_DATA_VLAN,
ASFVOLT_DOWNLINK_EAPOL_ID_DATA_VLAN)
@@ -2231,12 +2233,112 @@
@inlineCallbacks
def del_all_flow(self, v_enet):
+ # Currently this got called whenever we delete a gemport, but
+ # del_flow will not work properly as suffcient parameters are not
+ # present for deleting a flow.
+ # Deleting a flow is of two steps process.
+ # 1. Deactivate the flow, making ADMIN_STATE Down
+ # 2. Deleting the flow, making BalCfgClear
+ # Need to implement deactivate flow, before deleting a flow
+ # for HSIA, DHCP and other flow types.
+ # For EAPOL it's implemented, check del_eapol_flow method
yield self.del_flow(v_enet, ASFVOLT_HSIA_ID, ASFVOLT_HSIA_ID)
yield self.del_flow(v_enet, ASFVOLT_DHCP_TAGGED_ID,
ASFVOLT_DOWNLINK_DHCP_TAGGED_ID)
yield self.del_flow(v_enet, ASFVOLT_EAPOL_ID_DATA_VLAN,
ASFVOLT_DOWNLINK_EAPOL_ID_DATA_VLAN)
- yield self.del_flow(v_enet, ASFVOLT_EAPOL_ID, ASFVOLT_DOWNLINK_EAPOL_ID)
+
+ @inlineCallbacks
+ def del_eapol_flow(self, v_enet, uplink_id, downlink_id, vlan_id):
+ # To-Do For a time being hard code the traffic class value.
+ # Need to know how to get the traffic class info from flows.
+ v_ont_ani = self.get_v_ont_ani(name=v_enet.v_enet.data.v_ontani_ref)
+ if v_ont_ani is None:
+ self.log.info('Failed-to-get-v_ont_ani',
+ v_ont_ani=v_enet.v_enet.data.v_ontani_ref)
+ return
+ gem_port = self.get_gem_port_info(v_enet, traffic_class=2)
+ if gem_port is None:
+ self.log.info('Failed-to-get-gemport',)
+ # To-Do: If Gemport not found, then flow failure indication
+ # should be sent to controller. For now, not sure how to
+ # send that to controller. so store the flows in v_enet
+ # and add it when gem port is created
+ #self.store_flows(uplink_classifier, uplink_action,
+ # v_enet, traffic_class=2)
+ return
+ pon_port = self._get_pon_port_from_pref_chanpair_ref(
+ v_ont_ani.v_ont_ani.data.preferred_chanpair)
+ onu_device = self.adapter_agent.get_child_device(
+ self.device_id, onu_id=v_ont_ani.v_ont_ani.data.onu_id,
+ parent_port_no=pon_port)
+ if onu_device is None:
+ self.log.info('Failed-to-get-onu-device',
+ onu_id=v_ont_ani.v_ont_ani.data.onu_id)
+ return
+ downlink_flow_id = self.get_flow_id(onu_device.proxy_address.onu_id,
+ onu_device.proxy_address.channel_id,
+ downlink_id)
+ is_down_stream = True
+ try:
+ self.log.info('Deleting-Downstream-flow',
+ flow_id=downlink_flow_id)
+
+ yield self.bal.deactivate_eapol_flow(downlink_flow_id, is_down_stream,
+ onu_id=onu_device.proxy_address.onu_id,
+ intf_id=onu_device.proxy_address.channel_id,
+ network_int_id=self.nni_intf_id,
+ gemport_id=gem_port.gemport_id,
+ stag=vlan_id)
+ # While deletion of one flow is in progress,
+ # we cannot delete an another flow. Right now use sleep
+ # of 0.1 sec, assuming that deletion of flow is successful.
+ yield asleep(0.1)
+
+ self.log.info('deleting-Downstream-eapol-flow',
+ flow_id=downlink_flow_id)
+ yield self.bal.delete_flow(downlink_flow_id, is_down_stream)
+ yield asleep(0.1)
+ except Exception as e:
+ self.log.exception('failed-to-delete-downstream-flow', e=e,
+ flow_id=downlink_flow_id,
+ onu_id=onu_device.proxy_address.onu_id,
+ intf_id=onu_device.proxy_address.channel_id)
+
+ uplink_flow_id = self.get_flow_id(onu_device.proxy_address.onu_id,
+ onu_device.proxy_address.channel_id,
+ uplink_id)
+
+ tcont = self.get_tcont_info(v_ont_ani, name=gem_port.tcont_ref)
+ if tcont is None:
+ self.log.info('Failed-to-get-tcont-info',
+ tcont=gem_port.tcont_ref)
+ return
+ try:
+ is_down_stream = False
+ self.log.info('deactivating-Upstream-flow',
+ flow_id=uplink_flow_id)
+ yield self.bal.deactivate_eapol_flow(uplink_flow_id, is_down_stream,
+ onu_id=onu_device.proxy_address.onu_id,
+ intf_id=onu_device.proxy_address.channel_id,
+ network_int_id=self.nni_intf_id,
+ gemport_id=gem_port.gemport_id,
+ stag=vlan_id,
+ sched_id=tcont.alloc_id)
+ # While deletion of one flow is in progress,
+ # we cannot delete an another flow. Right now use sleep
+ # of 0.1 sec, assuming that deletion of flow is successful.
+ yield asleep(0.1)
+
+ self.log.info('deleting-Upstream-eapol-flow',
+ flow_id=uplink_flow_id)
+ yield self.bal.delete_flow(uplink_flow_id, is_down_stream)
+ yield asleep(0.1)
+ except Exception as e:
+ self.log.exception('failed-to-delete-Upstream-flow', e=e,
+ flow_id=uplink_flow_id,
+ onu_id=onu_device.proxy_address.onu_id,
+ intf_id=onu_device.proxy_address.channel_id)
@inlineCallbacks
def del_flow(self, v_enet, uplink_id, downlink_id):
@@ -2264,10 +2366,9 @@
try:
self.log.info('Deleting-Downstream-flow',
flow_id=downlink_flow_id)
-
- yield self.bal.delete_flow(onu_device.proxy_address.onu_id,
- onu_device.proxy_address.channel_id,
- downlink_flow_id, is_down_stream)
+ # Need to implement deactivate HSIA flow ,currently only
+ # Delete is called, so hsia flow deletion will not work properly
+ yield self.bal.delete_flow(downlink_flow_id, is_down_stream)
# While deletion of one flow is in progress,
# we cannot delete an another flow. Right now use sleep
# of 0.1 sec, assuming that deletion of flow is successful.
@@ -2285,9 +2386,10 @@
is_down_stream = False
self.log.info('deleting-Upstream-flow',
flow_id=uplink_flow_id)
- yield self.bal.delete_flow(onu_device.proxy_address.onu_id,
- onu_device.proxy_address.channel_id,
- uplink_flow_id, is_down_stream)
+ # Need to implement deactivate HSIA flow ,currently only
+ # Delete is called, so hsia flow deletion will not work properly
+
+ yield self.bal.delete_flow(uplink_flow_id, is_down_stream)
# While deletion of one flow is in progress,
# we cannot delete an another flow. Right now use sleep
# of 0.1 sec, assuming that deletion of flow is successful.
diff --git a/voltha/adapters/asfvolt16_olt/bal.py b/voltha/adapters/asfvolt16_olt/bal.py
index 43cdef1..ae8dcf0 100644
--- a/voltha/adapters/asfvolt16_olt/bal.py
+++ b/voltha/adapters/asfvolt16_olt/bal.py
@@ -348,7 +348,7 @@
obj.flow.data.action.presence_mask |= \
bal_model_types_pb2.BAL_ACTION_ID_CMDS_BITMASK
else:
- self.log.info('invalid-action',action_info=action_info)
+ self.log.info('invalid-action', action_info=action_info)
return
self.log.info('adding-flow-to-OLT-Device',
@@ -359,8 +359,16 @@
flow_id, onu_id, exc=str(e))
return
+ # Note: Bal_2.4 version expects expects all the classifier and action
+ # in deactivate flow that was used during flow activation.
@inlineCallbacks
- def delete_flow(self, onu_id, intf_id, flow_id, is_downstream):
+ def deactivate_eapol_flow(self, flow_id, is_downstream,
+ onu_id=None,
+ intf_id=None,
+ network_int_id=None,
+ gemport_id=None,
+ stag=None,
+ sched_id=None):
try:
obj = bal_pb2.BalCfg()
# Fill Header details
@@ -369,23 +377,65 @@
# Fill Access Terminal Details
# To-DO flow ID need to be retrieved from flow details
obj.flow.key.flow_id = flow_id
- if is_downstream is False:
- obj.flow.key.flow_type = \
- bal_model_types_pb2.BAL_FLOW_TYPE_UPSTREAM
- else:
+ obj.flow.data.admin_state = bal_model_types_pb2.BAL_STATE_DOWN
+ if intf_id is not None:
+ obj.flow.data.access_int_id = intf_id
+ if network_int_id is not None:
+ obj.flow.data.network_int_id = network_int_id
+ if onu_id is not None:
+ obj.flow.data.sub_term_id = onu_id
+ if gemport_id is not None:
+ obj.flow.data.svc_port_id = gemport_id
+
+ if is_downstream is True:
obj.flow.key.flow_type = \
bal_model_types_pb2.BAL_FLOW_TYPE_DOWNSTREAM
+ else:
+ obj.flow.key.flow_type = \
+ bal_model_types_pb2.BAL_FLOW_TYPE_UPSTREAM
- obj.flow.data.admin_state = bal_model_types_pb2.BAL_STATE_DOWN
- obj.flow.data.access_int_id = intf_id
- # obj.flow.data.network_int_id = intf_id
- obj.flow.data.sub_term_id = onu_id
- self.log.info('deleting-flows-from-OLT-Device',
+ obj.flow.data.classifier.pkt_tag_type = \
+ bal_model_types_pb2.BAL_PKT_TAG_TYPE_SINGLE_TAG
+ obj.flow.data.classifier.presence_mask |= \
+ bal_model_types_pb2.BAL_CLASSIFIER_ID_PKT_TAG_TYPE
+ obj.flow.data.classifier.o_vid = stag
+ obj.flow.data.classifier.presence_mask |= \
+ bal_model_types_pb2.BAL_CLASSIFIER_ID_O_VID
+ obj.flow.data.action.cmds_bitmask |= \
+ bal_model_types_pb2.BAL_ACTION_CMD_ID_TRAP_TO_HOST
+ obj.flow.data.action.presence_mask |= \
+ bal_model_types_pb2.BAL_ACTION_ID_CMDS_BITMASK
+ if sched_id is not None:
+ obj.flow.data.dba_tm_sched_id = sched_id
+
+ self.log.info('deactivating-eapol-flows-from-OLT-Device',
flow_details=obj)
yield self.stub.BalCfgSet(obj, timeout=GRPC_TIMEOUT)
except Exception as e:
- self.log.info('delete_flow-exception',
- flow_id, onu_id, exc=str(e))
+ self.log.exception('deactivate-eapol-flow-exception',
+ flow_id, onu_id, exc=str(e))
+ return
+
+ @inlineCallbacks
+ def delete_flow(self, flow_id, is_downstream):
+ try:
+ obj = bal_pb2.BalKey()
+ # Fill Header details
+ obj.hdr.obj_type = bal_model_ids_pb2.BAL_OBJ_ID_FLOW
+ obj.flow_key.flow_id = flow_id
+ if is_downstream is False:
+ obj.flow_key.flow_type = \
+ bal_model_types_pb2.BAL_FLOW_TYPE_UPSTREAM
+ else:
+ obj.flow_key.flow_type = \
+ bal_model_types_pb2.BAL_FLOW_TYPE_DOWNSTREAM
+
+ self.log.info('deleting-flows-from-OLT-Device',
+ flow_details=obj)
+ resp = yield self.stub.BalCfgClear(obj, timeout=GRPC_TIMEOUT)
+ except Exception as e:
+ self.log.exception('delete_flow-exception',
+ flow_id, e=e)
return
@inlineCallbacks