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 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 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 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)