def update_flow_table(self, flows, device): """ Update the flow table on the OLT. If an existing flow is not in the list, it needs to be removed from the device. :param flows: List of flows that should be installed upon completion of this function :param device: A voltha.Device object, with possible device-type specific extensions. """ self.log.debug('bulk-flow-update', num_flows=len(flows), device_id=device.id, flows=flows) valid_flows = [] for flow in flows: try: # Try to create an EVC. # # The first result is the flow entry that was created. This could be a match to an # existing flow since it is a bulk update. None is returned only if no match to # an existing entry is found and decode failed (unsupported field) # # The second result is the EVC this flow should be added to. This could be an # existing flow (so your adding another EVC-MAP) or a brand new EVC (no existing # EVC-MAPs). None is returned if there are not a valid EVC that can be created YET. valid_flow, evc = FlowEntry.create(flow, self) if valid_flow is not None: valid_flows.append(valid_flow.flow_id) if evc is not None: try: evc.schedule_install() self.add_evc(evc) except Exception as e: evc.status = 'EVC Install Exception: {}'.format( e.message) self.log.exception('EVC-install', e=e) except Exception as e: self.log.exception('bulk-flow-update-add', e=e) # Now drop all flows from this device that were not in this bulk update try: FlowEntry.drop_missing_flows(device.id, valid_flows) except Exception as e: self.log.exception('bulk-flow-update-remove', e=e)
def update_flow_table(self, flows, device): """ Update the flow table on the OLT. If an existing flow is not in the list, it needs to be removed from the device. :param flows: List of flows that should be installed upon completion of this function :param device: A voltha.Device object, with possible device-type specific extensions. """ self.log.debug('bulk-flow-update', num_flows=len(flows), device_id=device.id, flows=flows) valid_flows = [] for flow in flows: try: # Try to create an EVC. # # The first result is the flow entry that was created. This could be a match to an # existing flow since it is a bulk update. None is returned only if no match to # an existing entry is found and decode failed (unsupported field) # # The second result is the EVC this flow should be added to. This could be an # existing flow (so your adding another EVC-MAP) or a brand new EVC (no existing # EVC-MAPs). None is returned if there are not a valid EVC that can be created YET. valid_flow, evc = FlowEntry.create(flow, self) if valid_flow is not None: valid_flows.append(valid_flow.flow_id) if evc is not None: try: evc.schedule_install() self.add_evc(evc) except Exception as e: evc.status = 'EVC Install Exception: {}'.format(e.message) self.log.exception('EVC-install', e=e) except Exception as e: self.log.exception('bulk-flow-update-add', e=e) # Now drop all flows from this device that were not in this bulk update try: yield FlowEntry.drop_missing_flows(device.id, valid_flows) except Exception as e: self.log.exception('bulk-flow-update-remove', e=e)
def add_gem_port(self, gem_port, add_always=False): """ Add a GEM Port to this ONU :param gem_port: (GemPort) GEM Port to add :param add_always: (boolean) If true, force add (used during h/w resync) :return: (deferred) """ if not self._valid: returnValue(succeed('Deleting')) if not add_always and gem_port.gem_id in self._gem_ports: returnValue(succeed('already created')) try: results = yield gem_port.add_to_hardware(self.olt.rest_client, self._pon_id, self.onu_id) self._gem_ports[gem_port.gem_id] = gem_port # May need to update flow tables/evc-maps if gem_port.alloc_id in self._tconts: # GEM-IDs are a sorted list (ascending). First gemport handles downstream traffic from flow.flow_entry import FlowEntry evc_maps = FlowEntry.find_evc_map_flows( self._device_id, self._pon_id, self._onu_id) pass except Exception as e: self.log.exception('gem-port', e=e) raise returnValue(results)
def remove_gem_id(self, gem_id): gem_port = self._gem_ports.get(gem_id) if gem_port is None: returnValue(succeed('nop')) del self._gem_ports[gem_id] # self._resync_flows = True try: from flow.flow_entry import FlowEntry if gem_port.alloc_id in self._tconts: # May need to update flow tables/evc-maps # GEM-IDs are a sorted list (ascending). First gemport handles downstream traffic pass results = yield gem_port.remove_from_hardware( self.olt.rest_client, self._pon_id, self.onu_id) evc_maps = FlowEntry.find_evc_map_flows(self) for evc_map in evc_maps: evc_map.remove_gem_port(gem_port) except Exception as e: self.log.exception('delete', e=e) raise returnValue(succeed(results))
def remove_gem_id(self, gem_id): from flow.flow_entry import FlowEntry gem_port = self._gem_ports.get(gem_id) if gem_port is None: returnValue('nop') del self._gem_ports[gem_id] try: if gem_port.alloc_id in self._tconts: # May need to update flow tables/evc-maps # GEM-IDs are a sorted list (ascending). First gemport handles downstream traffic evc_maps = FlowEntry.find_evc_map_flows(self) for evc_map in evc_maps: evc_map.remove_gem_port(gem_port) results = yield gem_port.remove_from_hardware( self.olt.rest_client, self._pon_id, self.onu_id) except RestInvalidResponseCode as e: if e.code != 404: self.log.exception('onu-delete', e=e) except Exception as ex: self.log.exception('gem-port-delete', e=ex) raise for evc_map in FlowEntry.find_evc_map_flows(self): try: evc_map.remove_gem_port(gem_port) except Exception as ex: self.log.exception('evc-map-gem-remove', e=ex) returnValue('done')
def add_gem_port(self, gem_port, reflow=False): """ Add a GEM Port to this ONU :param gem_port: (GemPort) GEM Port to add :param reflow: (boolean) If true, force add (used during h/w resync) :return: (deferred) """ if not self._valid: returnValue('Deleting') if not reflow and gem_port.gem_id in self._gem_ports: returnValue('nop') gem_port.pon_id = self.pon_id gem_port.onu_id = self.onu_id if self.onu_id is not None else -1 gem_port.intf_id = self.intf_id # TODO: Currently only support a single UNI. Need to support multiple and track their GEM Ports # Probably best done by having a UNI-Port class (keep it simple) self.log.info('add', gem_port=gem_port, reflow=reflow) self._gem_ports[gem_port.gem_id] = gem_port try: results = yield gem_port.add_to_hardware(self.olt.rest_client) # May need to update flow tables/evc-maps if gem_port.alloc_id in self._tconts: from flow.flow_entry import FlowEntry # GEM-IDs are a sorted list (ascending). First gemport handles downstream traffic # from flow.flow_entry import FlowEntry evc_maps = FlowEntry.find_evc_map_flows(self) for evc_map in evc_maps: evc_map.add_gem_port(gem_port, reflow=reflow) except Exception as e: self.log.exception('gem-port', gem_port=gem_port, reflow=reflow, e=e) # This can happen with xPON if the ONU has been provisioned, but the PON Discovery # has not occurred for the ONU. Rely on hw sync to recover results = 'resync needed' returnValue(results)
def add_gem_port(self, gem_port, reflow=False): """ Add a GEM Port to this ONU :param gem_port: (GemPort) GEM Port to add :param reflow: (boolean) If true, force add (used during h/w resync) :return: (deferred) """ if not self._valid: returnValue(succeed('Deleting')) if not reflow and gem_port.gem_id in self._gem_ports: returnValue(succeed) self._gem_ports[gem_port.gem_id] = gem_port try: results = yield gem_port.add_to_hardware(self.olt.rest_client, self._pon_id, self.onu_id) # self._resync_flows = True # May need to update flow tables/evc-maps if gem_port.alloc_id in self._tconts: from flow.flow_entry import FlowEntry # GEM-IDs are a sorted list (ascending). First gemport handles downstream traffic # from flow.flow_entry import FlowEntry evc_maps = FlowEntry.find_evc_map_flows(self) for evc_map in evc_maps: evc_map.add_gem_port(gem_port, reflow=reflow) except Exception as e: self.log.exception('gem-port', gem_port=gem_port, reflow=reflow, e=e) # This can happen with xPON if the ONU has been provisioned, but the PON Discovery # has not occurred for the ONU. Rely on hw sync to recover results = 'resync needed' returnValue(results)
def sync_flows(): from flow.flow_entry import FlowEntry reflow, self._resync_flows = self._resync_flows, False return FlowEntry.sync_flows_by_onu(self, reflow=reflow)