def flow_extract_info(self, flow, flow_direction): uni_port_no = None if flow_direction == "upstream": for field in fd.get_ofb_fields(flow): if field.type == fd.IN_PORT: uni_port_no = field.port break elif flow_direction == "downstream": for field in fd.get_ofb_fields(flow): if field.type == fd.METADATA: uni_port_no = field.table_metadata & 0xFFFFFFFF break if uni_port_no is None: for action in fd.get_actions(flow): if action.type == fd.OUTPUT: uni_port_no = action.output.port break if uni_port_no is None: uni_port_no = fd.get_metadata_from_write_metadata( flow) & 0xFFFFFFFF if uni_port_no is None: raise ValueError pon_intf = self.intf_id_from_uni_port_num(uni_port_no) onu_id = self.onu_id_from_uni_port_num(uni_port_no) uni_id = self.uni_id_from_port_num(uni_port_no) return int(pon_intf), int(onu_id), int(uni_id)
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 is_eap_enabled(self, intf_id, onu_id, uni_id): flows = self.logical_flows_proxy.get('/').items for flow in flows: eap_flow = False eap_intf_id = None eap_onu_id = None eap_uni_id = None for field in fd.get_ofb_fields(flow): if field.type == fd.ETH_TYPE: if field.eth_type == EAP_ETH_TYPE: eap_flow = True if field.type == fd.IN_PORT: eap_intf_id = self.platform.intf_id_from_uni_port_num( field.port) eap_onu_id = self.platform.onu_id_from_port_num(field.port) eap_uni_id = self.platform.uni_id_from_port_num(field.port) if eap_flow: self.log.debug('eap flow detected', onu_id=onu_id, uni_id=uni_id, intf_id=intf_id, eap_intf_id=eap_intf_id, eap_onu_id=eap_onu_id, eap_uni_id=eap_uni_id) if eap_flow and intf_id == eap_intf_id \ and onu_id == eap_onu_id and uni_id == eap_uni_id: return True, flow return False, None
def update_flow_table(self, flows): stub = ponsim_pb2.PonSimStub(self.get_channel()) self.log.info('pushing-olt-flow-table') for flow in flows: classifier_info = {} 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']) if ('ip_proto' in classifier_info and (classifier_info['ip_proto'] == 17 or classifier_info['ip_proto'] == 2)) or ( 'eth_type' in classifier_info and classifier_info['eth_type'] == 0x888e): for action in fd.get_actions(flow): if action.type == ofp.OFPAT_OUTPUT: action.output.port = ofp.OFPP_CONTROLLER self.log.info('out_port', out_port=fd.get_out_port(flow)) stub.UpdateFlowTable(FlowTable(port=0, flows=flows)) self.log.info('success')
def get_classifier_info(self, flow): classifier_info = {} for field in fd.get_ofb_fields(flow): if field.type == fd.ETH_TYPE: classifier_info[ETH_TYPE] = field.eth_type elif field.type == fd.IP_PROTO: classifier_info[IP_PROTO] = field.ip_proto elif field.type == fd.IN_PORT: classifier_info[IN_PORT] = field.port elif field.type == fd.VLAN_VID: classifier_info[VLAN_VID] = field.vlan_vid & 0xfff elif field.type == fd.VLAN_PCP: classifier_info[VLAN_PCP] = field.vlan_pcp elif field.type == fd.UDP_DST: classifier_info[UDP_DST] = field.udp_dst elif field.type == fd.UDP_SRC: classifier_info[UDP_SRC] = field.udp_src elif field.type == fd.IPV4_DST: classifier_info[IPV4_DST] = field.ipv4_dst elif field.type == fd.IPV4_SRC: classifier_info[IPV4_SRC] = field.ipv4_src elif field.type == fd.METADATA: classifier_info[METADATA] = field.table_metadata else: self.log.debug('field-type-unhandled field.type={}'.format( field.type)) return classifier_info
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 _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 _decode_traffic_treatment(self): out_port = fd.get_out_port(self._flow) log.debug('OutPort: {}', out_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_treatment(self): out_port = fd.get_out_port(self._flow) log.debug('OutPort: {}', out_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 _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 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 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 _clear_flow_id_from_rm(self, flow, flow_id, flow_direction): uni_port_no = None flow_category = HSIA_FLOW # default child_device_id = None if flow_direction == UPSTREAM: for field in fd.get_ofb_fields(flow): if field.type == fd.IN_PORT: is_uni, child_device_id = self._is_uni_port(field.port) if is_uni: uni_port_no = field.port elif field.type == fd.IP_PROTO: if field.ip_proto == IGMP_PROTO: flow_category = IGMP_FLOW elif field.type == fd.ETH_TYPE: if field.eth_type == EAP_ETH_TYPE: flow_category = EAPOL_PRIMARY_FLOW elif field.eth_type == LLDP_ETH_TYPE: flow_category = LLDP_FLOW elif flow_direction == DOWNSTREAM: for field in fd.get_ofb_fields(flow): if field.type == fd.METADATA: uni_port = field.table_metadata & 0xFFFFFFFF is_uni, child_device_id = self._is_uni_port(uni_port) if is_uni: uni_port_no = field.port if uni_port_no is None: for action in fd.get_actions(flow): if action.type == fd.OUTPUT: is_uni, child_device_id = \ self._is_uni_port(action.output.port) if is_uni: uni_port_no = action.output.port if flow_category and child_device_id: child_device = self.adapter_agent.get_device(child_device_id) pon_intf = child_device.proxy_address.channel_id onu_id = child_device.proxy_address.onu_id flows = self.resource_mgr.get_flow_id_info(pon_intf, onu_id, flow_id) assert (isinstance(flows, list)) self.log.debug("retrieved-flows", flows=flows) for idx in range(len(flows)): if flow_direction == flows[idx]['flow_type']: flows.pop(idx) self.update_flow_info_to_kv_store(pon_intf, onu_id, flow_id, flows) if len(flows) > 0: # There are still flows referencing the same flow_id. # So the flow should not be freed yet. # For ex: Case of HSIA where same flow is shared # between DS and US. return self.resource_mgr.free_flow_id(pon_intf, onu_id, flow_id) else: self.log.error("invalid-info", uni_port_no=uni_port_no, flow_category=flow_category, child_device_id=child_device_id)
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): self.log.debug('add flow', flow=flow) classifier_info = dict() action_info = dict() 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: if fd.get_goto_table_id(flow) is None: self.log.debug('being taken care of by ONU', flow=flow) return action_info[POP_VLAN] = True self.log.debug('action-type-pop-vlan', in_port=classifier_info[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=classifier_info[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=classifier_info[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=classifier_info[IN_PORT]) if fd.get_goto_table_id(flow) is not None \ and POP_VLAN not in action_info: self.log.debug('being taken care of by ONU', flow=flow) return if OUTPUT not in action_info and METADATA in classifier_info: # find flow in the next table next_flow = self.find_next_flow(flow) if next_flow is None: return action_info[OUTPUT] = fd.get_out_port(next_flow) for field in fd.get_ofb_fields(next_flow): if field.type == fd.VLAN_VID: classifier_info[METADATA] = field.vlan_vid & 0xfff self.log.debug('flow-ports', classifier_inport=classifier_info[IN_PORT], action_output=action_info[OUTPUT]) (port_no, intf_id, onu_id, uni_id) \ = self.platform.extract_access_from_flow( classifier_info[IN_PORT], action_info[OUTPUT]) # LLDP flow has nothing to do with any particular subscriber. # So, lets not care about the Tech-profile, meters etc. # Just add the flow and return. if ETH_TYPE in classifier_info and \ classifier_info[ETH_TYPE] == LLDP_ETH_TYPE: self.log.debug('lldp flow add') self.add_lldp_flow(flow, port_no) return if ETH_TYPE in classifier_info and \ classifier_info[ETH_TYPE] == IPV4_ETH_TYPE and \ IP_PROTO in classifier_info and \ classifier_info[IP_PROTO] == 2: self.log.debug('igmp flow add ignored, not implemented yet') return if IP_PROTO in classifier_info and \ classifier_info[IP_PROTO] == 17 and \ UDP_SRC in classifier_info and \ classifier_info[UDP_SRC] == 67: self.log.debug('ignore trap-dhcp-from-nni-flow') # self.add_dhcp_trap_nni(flow, classifier_info, port_no, # network_intf_id=0) return self.divide_and_add_flow(intf_id, onu_id, uni_id, port_no, classifier_info, action_info, 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 get_vlan(self, flow): for field in fd.get_ofb_fields(flow): if field.type == fd.VLAN_VID: return field.vlan_vid return None
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 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 add_flow(self, flow): self.log.debug('add flow', flow=flow) classifier_info = dict() action_info = dict() 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: if fd.get_goto_table_id(flow) is None: self.log.debug('being taken care of by ONU', flow=flow) return action_info[POP_VLAN] = True self.log.debug('action-type-pop-vlan', in_port=classifier_info[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=classifier_info[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=classifier_info[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=classifier_info[IN_PORT]) if fd.get_goto_table_id(flow) is not None and not POP_VLAN in \ action_info: self.log.debug('being taken care of by ONU', flow=flow) return if not OUTPUT in action_info and METADATA in classifier_info: #find flow in the next table next_flow = self.find_next_flow(flow) if next_flow is None: return action_info[OUTPUT] = fd.get_out_port(next_flow) for field in fd.get_ofb_fields(next_flow): if field.type == fd.VLAN_VID: classifier_info[METADATA] = field.vlan_vid & 0xfff (intf_id, onu_id) = self.platform.extract_access_from_flow( classifier_info[IN_PORT], action_info[OUTPUT]) self.divide_and_add_flow(intf_id, onu_id, classifier_info, action_info, 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