def find_next_flow(self, flow): table_id = fd.get_goto_table_id(flow) metadata = 0 for field in fd.get_ofb_fields(flow): if field.type == fd.METADATA: metadata = field.table_metadata if table_id is None: return None flows = self.logical_flows_proxy.get('/').items next_flows = [] for f in flows: if f.table_id == table_id: #FIXME: if fd.get_in_port(f) == fd.get_in_port(flow) and \ fd.get_out_port(f) == metadata: next_flows.append(f) if len(next_flows) == 0: self.log.warning('no next flow found, it may be a timing issue', flow=flow, number_of_flows=len(flows)) reactor.callLater(5, self.add_flow, flow) return None next_flows.sort(key=lambda f: f.priority, reverse=True) return next_flows[0]
def find_next_flow(self, flow): table_id = fd.get_goto_table_id(flow) metadata = 0 # Prior to ONOS 1.13.5, Metadata contained the UNI output port number. In # 1.13.5 and later, the lower 32-bits is the output port number and the # upper 32-bits is the inner-vid we are looking for. Use just the lower 32 # bits. Allows this code to work with pre- and post-1.13.5 ONOS OltPipeline for field in fd.get_ofb_fields(flow): if field.type == fd.METADATA: metadata = field.table_metadata & 0xFFFFFFFF if table_id is None: return None flows = self.logical_flows_proxy.get('/').items next_flows = [] for f in flows: if f.table_id == table_id: # FIXME if fd.get_in_port(f) == fd.get_in_port(flow) and \ fd.get_out_port(f) == metadata: next_flows.append(f) if len(next_flows) == 0: self.log.warning('no next flow found, it may be a timing issue', flow=flow, number_of_flows=len(flows)) reactor.callLater(5, self.add_flow, flow) return None next_flows.sort(key=lambda f: f.priority, reverse=True) return next_flows[0]
def update_flow_table(self, flows): device = self.adapter_agent.get_device(self.device_id) self.log.debug('update flow table') in_port = None for flow in flows: is_down_stream = None in_port = fd.get_in_port(flow) assert in_port is not None # Right now there is only one NNI port. Get the NNI PORT and compare # with IN_PUT port number. Need to find better way. ports = self.adapter_agent.get_ports(device.id, Port.ETHERNET_NNI) for port in ports: if (port.port_no == in_port): self.log.info('downstream-flow') is_down_stream = True break if is_down_stream is None: is_down_stream = False self.log.info('upstream-flow') for flow in flows: try: self.flow_mgr.add_flow(flow, is_down_stream) except Exception as e: self.log.exception('failed-to-install-flow', e=e, flow=flow)
def _decode_traffic_selector(self): """ Extract EVC related traffic selection settings """ self.in_port = fd.get_in_port(self._flow) if self.in_port > OFPP_MAX: log.warn('logical-input-ports-not-supported') return False for field in fd.get_ofb_fields(self._flow): if field.type == IN_PORT: assert self.in_port == field.port, 'Multiple Input Ports found in flow rule' if self._handler.is_nni_port(self.in_port): self._logical_port = self.in_port # TODO: This should be a lookup elif field.type == VLAN_VID: # log.info('*** field.type == VLAN_VID', value=field.vlan_vid & 0xfff) self.vlan_id = field.vlan_vid & 0xfff self._is_multicast = self.vlan_id in self._handler.multicast_vlans elif field.type == VLAN_PCP: # log.info('*** field.type == VLAN_PCP', value=field.vlan_pcp) self.pcp = field.vlan_pcp elif field.type == ETH_TYPE: # log.info('*** field.type == ETH_TYPE', value=field.eth_type) self.eth_type = field.eth_type elif field.type == IP_PROTO: # log.info('*** field.type == IP_PROTO', value=field.ip_proto) self.ip_protocol = field.ip_proto if self.ip_protocol not in _supported_ip_protocols: # log.error('Unsupported IP Protocol') return False elif field.type == IPV4_DST: # log.info('*** field.type == IPV4_DST', value=field.ipv4_dst) self.ipv4_dst = field.ipv4_dst elif field.type == UDP_DST: # log.info('*** field.type == UDP_DST', value=field.udp_dst) self.udp_dst = field.udp_dst elif field.type == UDP_SRC: # log.info('*** field.type == UDP_SRC', value=field.udp_src) self.udp_src = field.udp_src elif field.type == METADATA: # log.info('*** field.type == METADATA', value=field.table_metadata) self.inner_vid = field.table_metadata else: log.warn('unsupported-selection-field', type=field.type) self._status_message = 'Unsupported field.type={}'.format(field.type) return False return True
def _decode_traffic_selector(self): """ Extract EVC related traffic selection settings """ self.in_port = fd.get_in_port(self._flow) if self.in_port > OFPP_MAX: log.warn('Logical-input-ports-not-supported') return False for field in fd.get_ofb_fields(self._flow): if field.type == IN_PORT: pass # Handled earlier elif field.type == VLAN_VID: # log.info('*** field.type == VLAN_VID', value=field.vlan_vid & 0xfff) self.vlan_id = field.vlan_vid & 0xfff elif field.type == VLAN_PCP: # log.info('*** field.type == VLAN_PCP', value=field.vlan_pcp) self.pcp = field.vlan_pcp elif field.type == ETH_TYPE: # log.info('*** field.type == ETH_TYPE', value=field.eth_type) self.eth_type = field.eth_type elif field.type == IP_PROTO: # log.info('*** field.type == IP_PROTO', value=field.ip_proto) self.ip_protocol = field.ip_proto if self.ip_protocol not in _supported_ip_protocols: # log.error('Unsupported IP Protocol') return False elif field.type == IPV4_DST: # log.info('*** field.type == IPV4_DST', value=field.ipv4_dst) self.ipv4_dst = field.ipv4_dst elif field.type == UDP_DST: # log.info('*** field.type == UDP_DST', value=field.udp_dst) self.udp_dst = field.udp_dst elif field.type == UDP_SRC: # log.info('*** field.type == UDP_SRC', value=field.udp_src) self.udp_src = field.udp_src elif field.type == METADATA: # log.info('*** field.type == METADATA', value=field.table_metadata) self.inner_vid = field.table_metadata else: log.warn('unsupported-selection-field', type=field.type) self._status_message = 'Unsupported field.type={}'.format( field.type) return False return True
def get_port_list(self, flows): port_list = [] for flow in flows: _in_port = fd.get_in_port(flow) if _in_port not in (0, PMC_UPSTREAM_PORT): if _in_port not in port_list: port_list.append(_in_port) log.debug('field-type-in-port', in_port=_in_port, port_list=port_list) return port_list
def get_svlan(self, port, flows): svlan_id = None for flow in flows: _in_port = fd.get_in_port(flow) if _in_port == PMC_UPSTREAM_PORT: log.debug('svlan-port-match') metadata = fd.get_metadata(flow) if metadata: if metadata == port: svlan_id = self.get_vlan(flow) & 0xfff log.debug('SVLAN found:{}'.format(svlan_id)) return svlan_id
def get_cvlan(self, svlan_id, port, flows): cvlan_id = None # Look for cvlan ... for flow in flows: _in_port = fd.get_in_port(flow) if _in_port == port: log.debug('cvlan-port-match') for action in fd.get_actions(flow): if action.type == fd.SET_FIELD: vlan = action.set_field.field.ofb_field.vlan_vid & 0xfff if vlan == svlan_id: cvlan_id = self.get_vlan(flow) & 0xfff log.debug('CVLAN found:{}'.format(cvlan_id)) return cvlan_id
def get_downlink_bandwidth(self, cvlan_id, svlan_id, port, flows): bandwidth = None for flow in flows: _in_port = fd.get_in_port(flow) if _in_port == PMC_UPSTREAM_PORT: log.debug('downlink-bandwidth-port-match') if flow.table_id == 1: metadata = fd.get_metadata(flow) if metadata: if metadata == port: vlan = self.get_vlan(flow) & 0xfff if vlan == cvlan_id: bandwidth = fd.get_metadata(flow) log.debug( 'Bandwidth found:{}'.format(bandwidth)) return bandwidth
def get_uplink_bandwidth(self, cvlan_id, svlan_id, port, flows): bandwidth = None # Look for cvlan ... for flow in flows: _in_port = fd.get_in_port(flow) if _in_port == port: log.debug('uplink-bandwidth-port-match') for action in fd.get_actions(flow): if action.type == fd.SET_FIELD: vlan = action.set_field.field.ofb_field.vlan_vid & 0xfff if vlan == svlan_id: bandwidth = fd.get_metadata(flow) if bandwidth: log.debug( 'Bandwidth found:{}'.format(bandwidth)) return bandwidth
def _decode_traffic_selector(self): """ Extract EVC related traffic selection settings """ in_port = fd.get_in_port(self._flow) assert in_port is not None log.debug('InPort: {}', in_port) for field in fd.get_ofb_fields(self._flow): log.debug('Found-OFB-field', field=field) for action in fd.get_actions(self._flow): log.debug('Found-Action', action=action) return True
def _decode_traffic_selector(self): """ Extract EVC related traffic selection settings """ in_port = fd.get_in_port(self._flow) assert in_port is not None log.debug('InPort: {}', in_port) for field in fd.get_ofb_fields(self._flow): log.debug('Found-OFB-field', field=field) for action in fd.get_actions(self._flow): log.debug('Found-Action', action=action) return True
def divide_and_add_flow(self, intf_id, onu_id, classifier, action, flow): self.log.debug('sorting flow', intf_id=intf_id, onu_id=onu_id, classifier=classifier, action=action) if 'ip_proto' in classifier: if classifier['ip_proto'] == 17: self.log.debug('dhcp flow add') self.add_dhcp_trap(intf_id, onu_id, classifier, action, flow) elif classifier['ip_proto'] == 2: self.log.warn('igmp flow add ignored, not implemented yet') else: self.log.warn("Invalid-Classifier-to-handle", classifier=classifier, action=action) elif 'eth_type' in classifier: if classifier['eth_type'] == EAP_ETH_TYPE: self.log.debug('eapol flow add') self.add_eapol_flow(intf_id, onu_id, flow) vlan_id = self.get_subscriber_vlan(fd.get_in_port(flow)) if vlan_id is not None: self.add_eapol_flow( intf_id, onu_id, flow, uplink_eapol_id=EAPOL_UPLINK_SECONDARY_FLOW_INDEX, downlink_eapol_id=EAPOL_DOWNLINK_SECONDARY_FLOW_INDEX, vlan_id=vlan_id) if classifier['eth_type'] == LLDP_ETH_TYPE: self.log.debug('lldp flow add') self.add_lldp_flow(intf_id, onu_id, flow, classifier, action) elif 'push_vlan' in action: self.add_upstream_data_flow(intf_id, onu_id, classifier, action, flow) elif 'pop_vlan' in action: self.add_downstream_data_flow(intf_id, onu_id, classifier, action, flow) else: self.log.debug('Invalid-flow-type-to-handle', classifier=classifier, action=action, flow=flow)
def get_subscriber_vlan(self, port): self.log.debug('looking from subscriber flow for port', port=port) flows = self.logical_flows_proxy.get('/').items for flow in flows: in_port = fd.get_in_port(flow) out_port = fd.get_out_port(flow) if in_port == port and \ self.platform.intf_id_to_port_type_name(out_port) \ == Port.ETHERNET_NNI: fields = fd.get_ofb_fields(flow) self.log.debug('subscriber flow found', fields=fields) for field in fields: if field.type == OFPXMT_OFB_VLAN_VID: self.log.debug('subscriber vlan found', vlan_id=field.vlan_vid) return field.vlan_vid & 0x0fff self.log.debug('No subscriber flow found', port=port) return None
def divide_and_add_flow(self, intf_id, onu_id, classifier, action, flow): self.log.debug('sorting flow', intf_id=intf_id, onu_id=onu_id, classifier=classifier, action=action) if IP_PROTO in classifier: if classifier[IP_PROTO] == 17: self.log.debug('dhcp flow add') self.add_dhcp_trap(intf_id, onu_id, classifier, action, flow) elif classifier[IP_PROTO] == 2: self.log.warn('igmp flow add ignored, not implemented yet') else: self.log.warn("Invalid-Classifier-to-handle", classifier=classifier, action=action) elif ETH_TYPE in classifier: if classifier[ETH_TYPE] == EAP_ETH_TYPE: self.log.debug('eapol flow add') self.add_eapol_flow(intf_id, onu_id, flow) vlan_id = self.get_subscriber_vlan(fd.get_in_port(flow)) if vlan_id is not None: self.add_eapol_flow( intf_id, onu_id, flow, eapol_id=EAPOL_SECONDARY_FLOW_INDEX, vlan_id=vlan_id) if classifier[ETH_TYPE] == LLDP_ETH_TYPE: self.log.debug('lldp flow add') self.add_lldp_flow(flow) elif PUSH_VLAN in action: self.add_upstream_data_flow(intf_id, onu_id, classifier, action, flow) elif POP_VLAN in action: self.add_downstream_data_flow(intf_id, onu_id, classifier, action, flow) else: self.log.debug('Invalid-flow-type-to-handle', classifier=classifier, action=action, flow=flow)
def update_flow_table(self, flows): if not self.is_state_up() and not self.is_state_connected(): self.log.info('OLT is down, ignore update flow table') return device = self.adapter_agent.get_device(self.device_id) self.log.debug('update flow table', number_of_flows=len(flows)) for flow in flows: is_down_stream = None in_port = fd.get_in_port(flow) assert in_port is not None # Right now there is only one NNI port. Get the NNI PORT and # compare with IN_PUT port number. Need to find better way. ports = self.adapter_agent.get_ports(device.id, Port.ETHERNET_NNI) for port in ports: if (port.port_no == in_port): self.log.debug('downstream-flow', in_port=in_port) is_down_stream = True break if is_down_stream is None: is_down_stream = False self.log.debug('upstream-flow', in_port=in_port) for flow in flows: try: self.flow_mgr.add_flow(flow, is_down_stream) except grpc.RpcError as grpc_e: if grpc_e.code() == grpc.StatusCode.ALREADY_EXISTS: self.log.warn('flow already exists', e=grpc_e, flow=flow) else: self.log.error('failed to add flow', flow=flow, e=grpc_e) except Exception as e: self.log.error('failed to add flow', flow=flow, e=e)
def update_flow_table(self, device, flows): import voltha.core.flow_decomposer as fd from voltha.protos.openflow_13_pb2 import OFPP_IN_PORT, OFPP_TABLE, OFPP_NORMAL, OFPP_FLOOD, OFPP_ALL from voltha.protos.openflow_13_pb2 import OFPP_CONTROLLER, OFPP_LOCAL, OFPP_ANY, OFPP_MAX # # We need to proxy through the OLT to get to the ONU # Configuration from here should be using OMCI # log.info('update_flow_table', device_id=device.id, flows=flows) for flow in flows: # TODO: Do we get duplicates here (ie all flows re-pushed on each individual flow add?) in_port = fd.get_in_port(flow) out_port = fd.get_out_port(flow) self.log.debug('InPort: {}, OutPort: {}'.format(in_port, out_port)) for field in fd.get_ofb_fields(flow): self.log.debug('Found OFB field', field=field) for action in fd.get_actions(flow): log.debug('Found Action', action=action) raise NotImplementedError()
def update_flow_table(self, device, flows): self.log.debug('function-entry', device=device, flows=flows) # # 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) def is_downstream(port): return port == self._pon_port_number def is_upstream(port): return not is_downstream(port) for flow in flows: _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('bulk-flow-update', device_id=device.id, flow=flow) try: _in_port = fd.get_in_port(flow) assert _in_port is not None if is_downstream(_in_port): self.log.debug('downstream-flow') elif is_upstream(_in_port): self.log.debug('upstream-flow') else: raise Exception('port should be 1 or 2 by our convention') _out_port = fd.get_out_port(flow) # may be None self.log.debug('out-port', out_port=_out_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-valn-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) # # All flows created from ONU adapter should be OMCI based # if _vlan_vid == 0 and _set_vlan_vid != None and _set_vlan_vid != 0: # TODO: find a better place for all of this # 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? # Delete bridge ani side vlan filter msg = VlanTaggingFilterDataFrame(_mac_bridge_port_ani_entity_id) frame = msg.delete() self.log.debug('openomci-msg', msg=msg) results = yield self.omci_cc.send(frame) self.check_status_and_state(results, 'flow-delete-vlan-tagging-filter-data') # Re-Create bridge ani side vlan filter msg = VlanTaggingFilterDataFrame( _mac_bridge_port_ani_entity_id, # Entity ID vlan_tcis=[_set_vlan_vid], # VLAN IDs forward_operation=0x10 ) frame = msg.create() self.log.debug('openomci-msg', msg=msg) results = yield self.omci_cc.send(frame) self.check_status_and_state(results, 'flow-create-vlan-tagging-filter-data') # Update uni side extended vlan filter # filter for untagged # probably for eapol # TODO: magic 0x1000 / 4096? # TODO: lots of magic 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=_set_vlan_vid, treatment_inner_tpid_de=4 ) ) msg = ExtendedVlanTaggingOperationConfigurationDataFrame( _mac_bridge_service_profile_entity_id, # Bridge Entity ID attributes=attributes # See above ) frame = msg.set() self.log.debug('openomci-msg', msg=msg) results = yield self.omci_cc.send(frame) self.check_status_and_state(results, 'flow-set-ext-vlan-tagging-op-config-data-untagged') # Update uni side extended vlan filter # filter for vlan 0 # TODO: lots of magic attributes = dict( received_frame_vlan_tagging_operation_table= VlanTaggingOperation( 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=_set_vlan_vid, # use this value as the VID in the inner VLAN tag treatment_inner_tpid_de=4, # set TPID ) ) msg = ExtendedVlanTaggingOperationConfigurationDataFrame( _mac_bridge_service_profile_entity_id, # Bridge Entity ID attributes=attributes # See above ) frame = msg.set() self.log.debug('openomci-msg', msg=msg) results = yield self.omci_cc.send(frame) self.check_status_and_state(results, 'flow-set-ext-vlan-tagging-op-config-data-zero-tagged') except Exception as e: self.log.exception('failed-to-install-flow', e=e, flow=flow)
def divide_and_add_flow(self, intf_id, onu_id, uni_id, port_no, classifier, action, flow): self.log.debug('sorting flow', intf_id=intf_id, onu_id=onu_id, uni_id=uni_id, port_no=port_no, classifier=classifier, action=action) alloc_id, gem_ports = self.create_tcont_gemport(intf_id, onu_id, uni_id, flow.table_id) if alloc_id is None or gem_ports is None: self.log.error("alloc-id-gem-ports-unavailable", alloc_id=alloc_id, gem_ports=gem_ports) return self.log.debug('Generated required alloc and gemport ids', alloc_id=alloc_id, gemports=gem_ports) # Flows can't be added specific to gemport unless p-bits are received. # Hence adding flows for all gemports for gemport_id in gem_ports: if IP_PROTO in classifier: if classifier[IP_PROTO] == 17: self.log.debug('dhcp flow add') self.add_dhcp_trap(intf_id, onu_id, uni_id, port_no, classifier, action, flow, alloc_id, gemport_id) elif classifier[IP_PROTO] == 2: self.log.warn('igmp flow add ignored, not implemented yet') else: self.log.warn("Invalid-Classifier-to-handle", classifier=classifier, action=action) elif ETH_TYPE in classifier: if classifier[ETH_TYPE] == EAP_ETH_TYPE: self.log.debug('eapol flow add') self.add_eapol_flow(intf_id, onu_id, uni_id, port_no, flow, alloc_id, gemport_id) vlan_id = self.get_subscriber_vlan(fd.get_in_port(flow)) if vlan_id is not None: self.add_eapol_flow(intf_id, onu_id, uni_id, port_no, flow, alloc_id, gemport_id, vlan_id=vlan_id) ofp_port_name = self.data_model.serial_number(intf_id, onu_id) tp_id = self.resource_mgr.get_tech_profile_id_for_onu( intf_id, onu_id, uni_id) tp_path = self.get_tp_path(intf_id, ofp_port_name, tp_id) self.log.debug('Load-tech-profile-request-to-brcm-handler', tp_path=tp_path) self.data_model.onu_download_tech_profile( intf_id, onu_id, uni_id, tp_path) if classifier[ETH_TYPE] == LLDP_ETH_TYPE: self.log.debug('lldp flow add') nni_intf_id = self.data_model.olt_nni_intf_id() self.add_lldp_flow(flow, port_no, nni_intf_id) elif PUSH_VLAN in action: self.add_upstream_data_flow(intf_id, onu_id, uni_id, port_no, classifier, action, flow, alloc_id, gemport_id) elif POP_VLAN in action: self.add_downstream_data_flow(intf_id, onu_id, uni_id, port_no, classifier, action, flow, alloc_id, gemport_id) else: self.log.debug('Invalid-flow-type-to-handle', classifier=classifier, action=action, flow=flow)
def divide_and_add_flow(self, intf_id, onu_id, classifier, action, flow): self.log.debug('sorting flow', intf_id=intf_id, onu_id=onu_id, classifier=classifier, action=action) alloc_id, gem_ports = self.create_tcont_gemport( intf_id, onu_id, flow.table_id) if alloc_id is None or gem_ports is None: self.log.error("alloc-id-gem-ports-unavailable", alloc_id=alloc_id, gem_ports=gem_ports) return self.log.debug('Generated required alloc and gemport ids', alloc_id=alloc_id, gemports=gem_ports) # Flows can't be added specific to gemport unless p-bits are received. # Hence adding flows for all gemports for gemport_id in gem_ports: if IP_PROTO in classifier: if classifier[IP_PROTO] == 17: self.log.debug('dhcp flow add') self.add_dhcp_trap(intf_id, onu_id, classifier, action, flow, alloc_id, gemport_id) elif classifier[IP_PROTO] == 2: self.log.warn('igmp flow add ignored, not implemented yet') else: self.log.warn("Invalid-Classifier-to-handle", classifier=classifier, action=action) elif ETH_TYPE in classifier: if classifier[ETH_TYPE] == EAP_ETH_TYPE: self.log.debug('eapol flow add') self.add_eapol_flow(intf_id, onu_id, flow, alloc_id, gemport_id) vlan_id = self.get_subscriber_vlan(fd.get_in_port(flow)) if vlan_id is not None: self.add_eapol_flow( intf_id, onu_id, flow, alloc_id, gemport_id, eapol_flow_category=EAPOL_SECONDARY_FLOW, vlan_id=vlan_id) parent_port_no = self.platform.intf_id_to_port_no( intf_id, Port.PON_OLT) onu_device = self.adapter_agent.get_child_device( self.device_id, onu_id=onu_id, parent_port_no=parent_port_no) ofp_port_name = self._get_ofp_port_name(intf_id, onu_id) if ofp_port_name is None: self.log.error("port-name-not-found") return # FIXME Should get Table id form the flow, as of now hardcoded to # DEFAULT_TECH_PROFILE_TABLE_ID (64) # 'tp_path' contains the suffix part of the tech_profile_instance path. # The prefix to the 'tp_path' should be set to \ # TechProfile.KV_STORE_TECH_PROFILE_PATH_PREFIX by the ONU adapter. tp_path = self.tech_profile[intf_id]. \ get_tp_path(DEFAULT_TECH_PROFILE_TABLE_ID, ofp_port_name) self.log.debug('Load-tech-profile-request-to-brcm-handler', tp_path=tp_path) msg = { 'proxy_address': onu_device.proxy_address, 'event': 'download_tech_profile', 'event_data': tp_path } # Send the event message to the ONU adapter self.adapter_agent.publish_inter_adapter_message( onu_device.id, msg) if classifier[ETH_TYPE] == LLDP_ETH_TYPE: self.log.debug('lldp flow add') self.add_lldp_flow(flow) elif PUSH_VLAN in action: self.add_upstream_data_flow(intf_id, onu_id, classifier, action, flow, alloc_id, gemport_id) elif POP_VLAN in action: self.add_downstream_data_flow(intf_id, onu_id, classifier, action, flow, alloc_id, gemport_id) else: self.log.debug('Invalid-flow-type-to-handle', classifier=classifier, action=action, flow=flow)
def update_flow_table(self, device, flows): # # 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) import voltha.core.flow_decomposer as fd from voltha.protos.openflow_13_pb2 import OFPXMC_OPENFLOW_BASIC, ofp_port def is_downstream(port): return port == 100 # Need a better way def is_upstream(port): return not is_downstream(port) omci = self._omci for flow in flows: _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.info('bulk-flow-update', device_id=device.id, flow=flow) try: _in_port = fd.get_in_port(flow) assert _in_port is not None if is_downstream(_in_port): self.log.info('downstream-flow') elif is_upstream(_in_port): self.log.info('upstream-flow') else: raise Exception('port should be 1 or 2 by our convention') _out_port = fd.get_out_port(flow) # may be None self.log.info('out-port', out_port=_out_port) for field in fd.get_ofb_fields(flow): if field.type == fd.ETH_TYPE: _type = field.eth_type self.log.info('field-type-eth-type', eth_type=_type) elif field.type == fd.IP_PROTO: _proto = field.ip_proto self.log.info('field-type-ip-proto', ip_proto=_proto) elif field.type == fd.IN_PORT: _port = field.port self.log.info('field-type-in-port', in_port=_port) elif field.type == fd.VLAN_VID: _vlan_vid = field.vlan_vid & 0xfff self.log.info('field-type-vlan-vid', vlan=_vlan_vid) elif field.type == fd.VLAN_PCP: _vlan_pcp = field.vlan_pcp self.log.info('field-type-vlan-pcp', pcp=_vlan_pcp) elif field.type == fd.UDP_DST: _udp_dst = field.udp_dst self.log.info('field-type-udp-dst', udp_dst=_udp_dst) elif field.type == fd.UDP_SRC: _udp_src = field.udp_src self.log.info('field-type-udp-src', udp_src=_udp_src) elif field.type == fd.IPV4_DST: _ipv4_dst = field.ipv4_dst self.log.info('field-type-ipv4-dst', ipv4_dst=_ipv4_dst) elif field.type == fd.IPV4_SRC: _ipv4_src = field.ipv4_src self.log.info('field-type-ipv4-src', ipv4_dst=_ipv4_src) elif field.type == fd.METADATA: _metadata = field.table_metadata self.log.info('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.info('action-type-output', output=_output, in_port=_in_port) elif action.type == fd.POP_VLAN: self.log.info('action-type-pop-vlan', in_port=_in_port) elif action.type == fd.PUSH_VLAN: _push_tpid = action.push.ethertype log.info('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.info('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.info('set-field-type-valn-vid', _set_vlan_vid) else: self.log.error('unsupported-action-set-field-type', field_type=_field.type) else: log.error('unsupported-action-type', action_type=action.type, in_port=_in_port) # # All flows created from ONU adapter should be OMCI based # if _vlan_vid == 0 and _set_vlan_vid != None and _set_vlan_vid != 0: # allow priority tagged packets # Set AR - ExtendedVlanTaggingOperationConfigData # 514 - RxVlanTaggingOperationTable - add VLAN <cvid> to priority tagged pkts - c-vid results = yield omci.send_delete_vlan_tagging_filter_data( 0x2102) # self.send_set_vlan_tagging_filter_data(0x2102, _set_vlan_vid) results = yield omci.send_create_vlan_tagging_filter_data( 0x2102, _set_vlan_vid) results = yield omci.send_set_extended_vlan_tagging_operation_vlan_configuration_data_untagged( 0x202, 0x1000, _set_vlan_vid) results = yield omci.send_set_extended_vlan_tagging_operation_vlan_configuration_data_single_tag( 0x202, 8, 0, 0, 1, 8, _set_vlan_vid) # Set AR - ExtendedVlanTaggingOperationConfigData # 514 - RxVlanTaggingOperationTable - add VLAN <cvid> to priority tagged pkts - c-vid ''' results = yield omci.send_set_extended_vlan_tagging_operation_vlan_configuration_data_single_tag(0x205, 8, 0, 0, ''' except Exception as e: log.exception('failed-to-install-flow', e=e, flow=flow)
def add_flow(self, flow, is_down_stream): self.log.debug('add flow', flow=flow, is_down_stream=is_down_stream) classifier_info = dict() action_info = dict() in_port = fd.get_in_port(flow) assert in_port is not None for field in fd.get_ofb_fields(flow): if field.type == fd.ETH_TYPE: classifier_info['eth_type'] = field.eth_type self.log.debug('field-type-eth-type', eth_type=classifier_info['eth_type']) elif field.type == fd.IP_PROTO: classifier_info['ip_proto'] = field.ip_proto self.log.debug('field-type-ip-proto', ip_proto=classifier_info['ip_proto']) elif field.type == fd.IN_PORT: classifier_info['in_port'] = field.port self.log.debug('field-type-in-port', in_port=classifier_info['in_port']) elif field.type == fd.VLAN_VID: classifier_info['vlan_vid'] = field.vlan_vid & 0xfff self.log.debug('field-type-vlan-vid', vlan=classifier_info['vlan_vid']) elif field.type == fd.VLAN_PCP: classifier_info['vlan_pcp'] = field.vlan_pcp self.log.debug('field-type-vlan-pcp', pcp=classifier_info['vlan_pcp']) elif field.type == fd.UDP_DST: classifier_info['udp_dst'] = field.udp_dst self.log.debug('field-type-udp-dst', udp_dst=classifier_info['udp_dst']) elif field.type == fd.UDP_SRC: classifier_info['udp_src'] = field.udp_src self.log.debug('field-type-udp-src', udp_src=classifier_info['udp_src']) elif field.type == fd.IPV4_DST: classifier_info['ipv4_dst'] = field.ipv4_dst self.log.debug('field-type-ipv4-dst', ipv4_dst=classifier_info['ipv4_dst']) elif field.type == fd.IPV4_SRC: classifier_info['ipv4_src'] = field.ipv4_src self.log.debug('field-type-ipv4-src', ipv4_dst=classifier_info['ipv4_src']) elif field.type == fd.METADATA: classifier_info['metadata'] = field.table_metadata self.log.debug('field-type-metadata', metadata=classifier_info['metadata']) else: raise NotImplementedError('field.type={}'.format(field.type)) for action in fd.get_actions(flow): if action.type == fd.OUTPUT: action_info['output'] = action.output.port self.log.debug('action-type-output', output=action_info['output'], in_port=classifier_info['in_port']) elif action.type == fd.POP_VLAN: action_info['pop_vlan'] = True self.log.debug('action-type-pop-vlan', in_port=in_port) elif action.type == fd.PUSH_VLAN: action_info['push_vlan'] = True action_info['tpid'] = action.push.ethertype self.log.debug('action-type-push-vlan', push_tpid=action_info['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: # action_info['action_type'] = '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: self.log.debug('set-field-type-vlan-vid', vlan_vid=_field.vlan_vid & 0xfff) action_info['vlan_vid'] = (_field.vlan_vid & 0xfff) 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) # FIXME - Why ignore downstream flows? if is_down_stream is False: intf_id = platform.intf_id_from_uni_port_num( classifier_info['in_port']) onu_id = platform.onu_id_from_port_num(classifier_info['in_port']) self.divide_and_add_flow(intf_id, onu_id, classifier_info, action_info)
def update_flow_table(self, device, flows): # # 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) def is_downstream(port): return port == 2 # Need a better way def is_upstream(port): return not is_downstream(port) for flow in flows: try: _in_port = fd.get_in_port(flow) assert _in_port is not None if is_downstream(_in_port): self.log.info('downstream-flow') elif is_upstream(_in_port): self.log.info('upstream-flow') else: raise Exception('port should be 1 or 2 by our convention') _out_port = fd.get_out_port(flow) # may be None self.log.info('out-port', out_port=_out_port) for field in fd.get_ofb_fields(flow): if field.type == fd.ETH_TYPE: _type = field.eth_type self.log.info('field-type-eth-type', eth_type=_type) elif field.type == fd.IP_PROTO: _proto = field.ip_proto self.log.info('field-type-ip-proto', ip_proto=_proto) elif field.type == fd.IN_PORT: _port = field.port self.log.info('field-type-in-port', in_port=_port) elif field.type == fd.VLAN_VID: _vlan_vid = field.vlan_vid & 0xfff self.log.info('field-type-vlan-vid', vlan=_vlan_vid) elif field.type == fd.VLAN_PCP: _vlan_pcp = field.vlan_pcp self.log.info('field-type-vlan-pcp', pcp=_vlan_pcp) elif field.type == fd.UDP_DST: _udp_dst = field.udp_dst self.log.info('field-type-udp-dst', udp_dst=_udp_dst) elif field.type == fd.UDP_SRC: _udp_src = field.udp_src self.log.info('field-type-udp-src', udp_src=_udp_src) elif field.type == fd.IPV4_DST: _ipv4_dst = field.ipv4_dst self.log.info('field-type-ipv4-dst', ipv4_dst=_ipv4_dst) elif field.type == fd.IPV4_SRC: _ipv4_src = field.ipv4_src self.log.info('field-type-ipv4-src', ipv4_dst=_ipv4_src) elif field.type == fd.METADATA: _metadata = field.metadata self.log.info('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.info('action-type-output', output=_output, in_port=_in_port) elif action.type == fd.POP_VLAN: self.log.info('action-type-pop-vlan', in_port=_in_port) elif action.type == fd.PUSH_VLAN: _push_tpid = action.push.ethertype log.info('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.info('action-type-set-field', field=_field, in_port=_in_port) if _field.type == fd.VLAN_VID: self.log.info('set-field-type-valn-vid', vlan_vid=_field.vlan_vid & 0xfff) else: self.log.error('unsupported-action-set-field-type', field_type=_field.type) else: log.error('unsupported-action-type', action_type=action.type, in_port=_in_port) # # All flows created from ONU adapter should be OMCI based # except Exception as e: log.exception('failed-to-install-flow', e=e, flow=flow)
def update_flow_table(self, flows): device = self.adapter_agent.get_device(self.device_id) self.log.info('update flow table', flows=flows) for flow in flows: self.log.info('flow-details', device_id=self.device_id, flow=flow) classifier_info = dict() action_info = dict() is_down_stream = None _in_port = None try: _in_port = fd.get_in_port(flow) assert _in_port is not None # Right now there is only one NNI port. Get the NNI PORT and compare # with IN_PUT port number. Need to find better way. ports = self.adapter_agent.get_ports(device.id, Port.ETHERNET_NNI) for port in ports: if (port.port_no == _in_port): self.log.info('downstream-flow') is_down_stream = True break if is_down_stream is None: is_down_stream = False self.log.info('upstream-flow') for field in fd.get_ofb_fields(flow): if field.type == fd.ETH_TYPE: classifier_info['eth_type'] = field.eth_type self.log.info('field-type-eth-type', eth_type=classifier_info['eth_type']) elif field.type == fd.IP_PROTO: classifier_info['ip_proto'] = field.ip_proto self.log.info('field-type-ip-proto', ip_proto=classifier_info['ip_proto']) elif field.type == fd.IN_PORT: classifier_info['in_port'] = field.port self.log.info('field-type-in-port', in_port=classifier_info['in_port']) elif field.type == fd.VLAN_VID: classifier_info['vlan_vid'] = field.vlan_vid & 0xfff self.log.info('field-type-vlan-vid', vlan=classifier_info['vlan_vid']) elif field.type == fd.VLAN_PCP: classifier_info['vlan_pcp'] = field.vlan_pcp self.log.info('field-type-vlan-pcp', pcp=classifier_info['vlan_pcp']) elif field.type == fd.UDP_DST: classifier_info['udp_dst'] = field.udp_dst self.log.info('field-type-udp-dst', udp_dst=classifier_info['udp_dst']) elif field.type == fd.UDP_SRC: classifier_info['udp_src'] = field.udp_src self.log.info('field-type-udp-src', udp_src=classifier_info['udp_src']) elif field.type == fd.IPV4_DST: classifier_info['ipv4_dst'] = field.ipv4_dst self.log.info('field-type-ipv4-dst', ipv4_dst=classifier_info['ipv4_dst']) elif field.type == fd.IPV4_SRC: classifier_info['ipv4_src'] = field.ipv4_src self.log.info('field-type-ipv4-src', ipv4_dst=classifier_info['ipv4_src']) elif field.type == fd.METADATA: classifier_info['metadata'] = field.table_metadata self.log.info('field-type-metadata', metadata=classifier_info['metadata']) else: raise NotImplementedError('field.type={}'.format( field.type)) for action in fd.get_actions(flow): if action.type == fd.OUTPUT: action_info['output'] = action.output.port self.log.info('action-type-output', output=action_info['output'], in_port=classifier_info['in_port']) elif action.type == fd.POP_VLAN: action_info['pop_vlan'] = True self.log.info('action-type-pop-vlan', in_port=_in_port) elif action.type == fd.PUSH_VLAN: action_info['push_vlan'] = True action_info['tpid'] = action.push.ethertype self.log.info('action-type-push-vlan', push_tpid=action_info['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: # action_info['action_type'] = 'set_field' _field = action.set_field.field.ofb_field assert (action.set_field.field.oxm_class == OFPXMC_OPENFLOW_BASIC) self.log.info('action-type-set-field', field=_field, in_port=_in_port) if _field.type == fd.VLAN_VID: self.log.info('set-field-type-vlan-vid', vlan_vid=_field.vlan_vid & 0xfff) action_info['vlan_vid'] = (_field.vlan_vid & 0xfff) 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) # FIXME - Why ignore downstream flows? if is_down_stream is False: intf_id = self.intf_id_from_port_num(classifier_info['in_port']) onu_id = self.onu_id_from_port_num(classifier_info['in_port']) self.divide_and_add_flow(intf_id, onu_id, classifier_info, action_info) except Exception as e: self.log.exception('failed-to-install-flow', e=e, flow=flow)
def update_flow_table(self, device, flows): # # 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) import voltha.core.flow_decomposer as fd from voltha.protos.openflow_13_pb2 import OFPXMC_OPENFLOW_BASIC, ofp_port def is_downstream(port): return port == 100 # Need a better way def is_upstream(port): return not is_downstream(port) omci = self._omci for flow in flows: _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.info('bulk-flow-update', device_id=device.id, flow=flow) try: _in_port = fd.get_in_port(flow) assert _in_port is not None if is_downstream(_in_port): self.log.info('downstream-flow') elif is_upstream(_in_port): self.log.info('upstream-flow') else: raise Exception('port should be 1 or 2 by our convention') _out_port = fd.get_out_port(flow) # may be None self.log.info('out-port', out_port=_out_port) for field in fd.get_ofb_fields(flow): if field.type == fd.ETH_TYPE: _type = field.eth_type self.log.info('field-type-eth-type', eth_type=_type) elif field.type == fd.IP_PROTO: _proto = field.ip_proto self.log.info('field-type-ip-proto', ip_proto=_proto) elif field.type == fd.IN_PORT: _port = field.port self.log.info('field-type-in-port', in_port=_port) elif field.type == fd.VLAN_VID: _vlan_vid = field.vlan_vid & 0xfff self.log.info('field-type-vlan-vid', vlan=_vlan_vid) elif field.type == fd.VLAN_PCP: _vlan_pcp = field.vlan_pcp self.log.info('field-type-vlan-pcp', pcp=_vlan_pcp) elif field.type == fd.UDP_DST: _udp_dst = field.udp_dst self.log.info('field-type-udp-dst', udp_dst=_udp_dst) elif field.type == fd.UDP_SRC: _udp_src = field.udp_src self.log.info('field-type-udp-src', udp_src=_udp_src) elif field.type == fd.IPV4_DST: _ipv4_dst = field.ipv4_dst self.log.info('field-type-ipv4-dst', ipv4_dst=_ipv4_dst) elif field.type == fd.IPV4_SRC: _ipv4_src = field.ipv4_src self.log.info('field-type-ipv4-src', ipv4_dst=_ipv4_src) elif field.type == fd.METADATA: _metadata = field.table_metadata self.log.info('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.info('action-type-output', output=_output, in_port=_in_port) elif action.type == fd.POP_VLAN: self.log.info('action-type-pop-vlan', in_port=_in_port) elif action.type == fd.PUSH_VLAN: _push_tpid = action.push.ethertype log.info('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.info('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.info('set-field-type-valn-vid', _set_vlan_vid) else: self.log.error('unsupported-action-set-field-type', field_type=_field.type) else: log.error('unsupported-action-type', action_type=action.type, in_port=_in_port) # # All flows created from ONU adapter should be OMCI based # if _vlan_vid == 0 and _set_vlan_vid != None and _set_vlan_vid != 0: # allow priority tagged packets # Set AR - ExtendedVlanTaggingOperationConfigData # 514 - RxVlanTaggingOperationTable - add VLAN <cvid> to priority tagged pkts - c-vid results = yield omci.send_delete_vlan_tagging_filter_data(0x2102) # self.send_set_vlan_tagging_filter_data(0x2102, _set_vlan_vid) results = yield omci.send_create_vlan_tagging_filter_data( 0x2102, _set_vlan_vid) results = yield omci.send_set_extended_vlan_tagging_operation_vlan_configuration_data_untagged( 0x202, 0x1000, _set_vlan_vid) results = yield omci.send_set_extended_vlan_tagging_operation_vlan_configuration_data_single_tag( 0x202, 8, 0, 0, 1, 8, _set_vlan_vid) # Set AR - ExtendedVlanTaggingOperationConfigData # 514 - RxVlanTaggingOperationTable - add VLAN <cvid> to priority tagged pkts - c-vid ''' results = yield omci.send_set_extended_vlan_tagging_operation_vlan_configuration_data_single_tag(0x205, 8, 0, 0, ''' except Exception as e: log.exception('failed-to-install-flow', e=e, flow=flow)
def _decode_traffic_selector(self, flow): """ Extract traffic selection settings """ self.in_port = fd.get_in_port(flow) if self.in_port > OFPP_MAX: log.warn('logical-input-ports-not-supported') return False for field in fd.get_ofb_fields(flow): if field.type == IN_PORT: assert self.in_port == field.port, 'Multiple Input Ports found in flow rule' elif field.type == VLAN_VID: self.vlan_vid = field.vlan_vid & 0xfff log.debug('*** field.type == VLAN_VID', value=field.vlan_vid, vlan_id=self.vlan_vid) self._is_multicast = False # TODO: self.vlan_id in self._handler.multicast_vlans elif field.type == VLAN_PCP: log.debug('*** field.type == VLAN_PCP', value=field.vlan_pcp) self.vlan_pcp = field.vlan_pcp elif field.type == ETH_TYPE: log.debug('*** field.type == ETH_TYPE', value=field.eth_type) self.etype = field.eth_type elif field.type == IP_PROTO: log.debug('*** field.type == IP_PROTO', value=field.ip_proto) self.proto = field.ip_proto if self.proto not in _supported_ip_protocols: log.error('Unsupported IP Protocol', ip_proto=self.proto) return False elif field.type == IPV4_DST: log.debug('*** field.type == IPV4_DST', value=field.ipv4_dst) self.ipv4_dst = field.ipv4_dst elif field.type == UDP_DST: log.debug('*** field.type == UDP_DST', value=field.udp_dst) self.udp_dst = field.udp_dst elif field.type == UDP_SRC: log.debug('*** field.type == UDP_SRC', value=field.udp_src) self.udp_src = field.udp_src elif field.type == METADATA: log.debug('*** field.type == METADATA', value=field.table_metadata) self.inner_vid = field.table_metadata log.debug('*** field.type == METADATA', value=field.table_metadata, inner_vid=self.inner_vid) else: log.warn('unsupported-selection-field', type=field.type) self._status_message = 'Unsupported field.type={}'.format( field.type) return False return True
def _decode_traffic_selector(self, flow): """ Extract EVC related traffic selection settings """ self.in_port = fd.get_in_port(flow) if self.in_port > OFPP_MAX: log.warn('logical-input-ports-not-supported', in_port=self.in_port) return False for field in fd.get_ofb_fields(flow): if field.type == IN_PORT: if self._handler.is_nni_port(self.in_port) or self._handler.is_uni_port(self.in_port): self._logical_port = self.in_port elif field.type == VLAN_VID: if field.vlan_vid >= OFPVID_PRESENT + 4095: self.vlan_id = None # pre-ONOS v1.13.5 or old EAPOL Rule else: self.vlan_id = field.vlan_vid & 0xfff log.debug('*** field.type == VLAN_VID', value=field.vlan_vid, vlan_id=self.vlan_id) elif field.type == VLAN_PCP: log.debug('*** field.type == VLAN_PCP', value=field.vlan_pcp) self.pcp = field.vlan_pcp elif field.type == ETH_TYPE: log.debug('*** field.type == ETH_TYPE', value=field.eth_type) self.eth_type = field.eth_type elif field.type == IP_PROTO: log.debug('*** field.type == IP_PROTO', value=field.ip_proto) self.ip_protocol = field.ip_proto if self.ip_protocol not in _supported_ip_protocols: log.error('Unsupported IP Protocol', protocol=self.ip_protocol) return False elif field.type == IPV4_DST: log.debug('*** field.type == IPV4_DST', value=field.ipv4_dst) self.ipv4_dst = field.ipv4_dst elif field.type == UDP_DST: log.debug('*** field.type == UDP_DST', value=field.udp_dst) self.udp_dst = field.udp_dst elif field.type == UDP_SRC: log.debug('*** field.type == UDP_SRC', value=field.udp_src) self.udp_src = field.udp_src elif field.type == METADATA: if self._handler.is_nni_port(self.in_port): # Downstream flow log.debug('*** field.type == METADATA', value=field.table_metadata) if field.table_metadata > 4095: # ONOS v1.13.5 or later. c-vid in upper 32-bits vid = field.table_metadata & 0x0FFF if vid > 0: self.inner_vid = vid # CTag is never '0' elif field.table_metadata > 0: # Pre-ONOS v1.13.5 (vid without the 4096 offset) self.inner_vid = field.table_metadata else: # Upstream flow pass # Not used upstream at this time log.debug('*** field.type == METADATA', value=field.table_metadata, inner_vid=self.inner_vid) else: log.warn('unsupported-selection-field', type=field.type) self._status_message = 'Unsupported field.type={}'.format(field.type) return False return True
def update_flow_table(self, device, flows): self.log.debug('function-entry', device=device, flows=flows) # # 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 def is_downstream(port): return port == self._pon_port_number def is_upstream(port): return not is_downstream(port) for flow in flows: _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('bulk-flow-update', device_id=device.id, flow=flow) 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('ignorning-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) except Exception as e: self.log.exception('failed-to-install-flow', e=e, flow=flow)
def _decode_traffic_selector(self, flow): """ Extract EVC related traffic selection settings """ self.in_port = fd.get_in_port(flow) if self.in_port > OFPP_MAX: log.warn('logical-input-ports-not-supported', in_port=self.in_port) return False for field in fd.get_ofb_fields(flow): if field.type == IN_PORT: if self._handler.is_nni_port( self.in_port) or self._handler.is_uni_port( self.in_port): self._logical_port = self.in_port elif field.type == VLAN_VID: if field.vlan_vid >= ofp.OFPVID_PRESENT + 4095: self.vlan_id = None # pre-ONOS v1.13.5 or old EAPOL Rule else: self.vlan_id = field.vlan_vid & 0xfff log.debug('*** field.type == VLAN_VID', value=field.vlan_vid, vlan_id=self.vlan_id) elif field.type == VLAN_PCP: log.debug('*** field.type == VLAN_PCP', value=field.vlan_pcp) self.pcp = field.vlan_pcp elif field.type == ETH_TYPE: log.debug('*** field.type == ETH_TYPE', value=field.eth_type) self.eth_type = field.eth_type elif field.type == IP_PROTO: log.debug('*** field.type == IP_PROTO', value=field.ip_proto) self.ip_protocol = field.ip_proto if self.ip_protocol not in _supported_ip_protocols: log.error('Unsupported IP Protocol', protocol=self.ip_protocol) return False elif field.type == IPV4_DST: log.debug('*** field.type == IPV4_DST', value=field.ipv4_dst) self.ipv4_dst = field.ipv4_dst elif field.type == UDP_DST: log.debug('*** field.type == UDP_DST', value=field.udp_dst) self.udp_dst = field.udp_dst elif field.type == UDP_SRC: log.debug('*** field.type == UDP_SRC', value=field.udp_src) self.udp_src = field.udp_src elif field.type == METADATA: log.debug('*** field.type == METADATA', value=field.table_metadata) if 0xFFFFFFFF >= field.table_metadata > ofp.OFPVID_PRESENT + 4095: # Default flows for old-style controller flows self.inner_vid = None elif field.table_metadata > 0xFFFFFFFF: # ONOS v1.13.5 or later. c-vid in upper 32-bits self.inner_vid = field.table_metadata >> 32 else: # Pre- ONOS v1.13.5 self.inner_vid = field.table_metadata log.debug('*** field.type == METADATA', value=field.table_metadata, inner_vid=self.inner_vid) else: log.warn('unsupported-selection-field', type=field.type) self._status_message = 'Unsupported field.type={}'.format( field.type) return False return True