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 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 _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 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 _decode_traffic_treatment(self): self.output = fd.get_out_port(self._flow) if self.output > OFPP_MAX: log.warn('logical-output-ports-not-supported') return False for act in fd.get_actions(self._flow): if act.type == fd.OUTPUT: assert self.output == act.output.port, 'Multiple Output Ports found in flow rule' pass # Handled earlier elif act.type == POP_VLAN: # log.info('*** action.type == POP_VLAN') self.pop_vlan += 1 elif act.type == PUSH_VLAN: # log.info('*** action.type == PUSH_VLAN', value=act.push) # TODO: Do we want to test the ethertype for support? tpid = act.push.ethertype self.push_vlan_tpid.append(tpid) elif act.type == SET_FIELD: # log.info('*** action.type == SET_FIELD', value=act.set_field.field) assert ( act.set_field.field.oxm_class == ofp.OFPXMC_OPENFLOW_BASIC) field = act.set_field.field.ofb_field if field.type == VLAN_VID: self.push_vlan_id.append(field.vlan_vid & 0xfff) else: # TODO: May need to modify ce-preservation log.warn('unsupported-action', action=act) self._status_message = 'Unsupported action.type={}'.format( act.type) return False return True
def _decode_traffic_treatment(self, flow): self.out_port = fd.get_out_port(flow) if self.out_port > OFPP_MAX: log.warn('logical-output-ports-not-supported') return False for act in fd.get_actions(flow): if act.type == fd.OUTPUT: assert self.out_port == act.output.port, 'Multiple Output Ports found in flow rule' pass # Handled earlier elif act.type == POP_VLAN: log.debug('*** action.type == POP_VLAN') self.pop_vlan = True elif act.type == PUSH_VLAN: log.debug('*** action.type == PUSH_VLAN', value=act.push) tpid = act.push.ethertype self.push_tpid = tpid assert tpid == 0x8100, 'Only TPID 0x8100 is currently supported' elif act.type == SET_FIELD: log.debug('*** action.type == SET_FIELD', value=act.set_field.field) assert ( act.set_field.field.oxm_class == ofp.OFPXMC_OPENFLOW_BASIC) field = act.set_field.field.ofb_field if field.type == VLAN_VID: self.set_vlan_vid = field.vlan_vid & 0xfff else: log.warn('unsupported-action', action=act) self._status_message = 'Unsupported action.type={}'.format( act.type) return False return True
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 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_eapol_flow(self, intf_id, onu_id, logical_flow, alloc_id, gemport_id, eapol_flow_category=EAPOL_PRIMARY_FLOW, vlan_id=DEFAULT_MGMT_VLAN): uplink_classifier = dict() uplink_classifier[ETH_TYPE] = EAP_ETH_TYPE uplink_classifier[PACKET_TAG_TYPE] = SINGLE_TAG uplink_classifier[VLAN_VID] = vlan_id uplink_action = dict() uplink_action[TRAP_TO_HOST] = True pon_intf_onu_id = (intf_id, onu_id) # Add Upstream EAPOL Flow. if eapol_flow_category == EAPOL_PRIMARY_FLOW: uplink_flow_id = self.resource_mgr.get_flow_id(pon_intf_onu_id) else: uplink_flow_id = self.resource_mgr.get_flow_id(pon_intf_onu_id) upstream_flow = openolt_pb2.Flow( access_intf_id=intf_id, onu_id=onu_id, flow_id=uplink_flow_id, flow_type=UPSTREAM, alloc_id=alloc_id, network_intf_id=0, gemport_id=gemport_id, classifier=self.mk_classifier(uplink_classifier), action=self.mk_action(uplink_action), priority=logical_flow.priority) logical_flow = copy.deepcopy(logical_flow) logical_flow.match.oxm_fields.extend( fd.mk_oxm_fields([fd.vlan_vid(vlan_id | 0x1000)])) logical_flow.match.type = OFPMT_OXM if self.add_flow_to_device(upstream_flow, logical_flow): if eapol_flow_category == EAPOL_PRIMARY_FLOW: flow_info = self._get_flow_info_as_json_blob( upstream_flow, EAPOL_PRIMARY_FLOW) self.update_flow_info_to_kv_store(upstream_flow.access_intf_id, upstream_flow.onu_id, upstream_flow.flow_id, flow_info) else: flow_info = self._get_flow_info_as_json_blob( upstream_flow, EAPOL_SECONDARY_FLOW) self.update_flow_info_to_kv_store(upstream_flow.access_intf_id, upstream_flow.onu_id, upstream_flow.flow_id, flow_info) if vlan_id == DEFAULT_MGMT_VLAN: # Add Downstream EAPOL Flow, Only for first EAP flow (BAL # requirement) special_vlan_downstream_flow = 4000 - onu_id downlink_classifier = dict() downlink_classifier[PACKET_TAG_TYPE] = SINGLE_TAG downlink_classifier[VLAN_VID] = special_vlan_downstream_flow downlink_action = dict() downlink_action[PUSH_VLAN] = True downlink_action[VLAN_VID] = vlan_id pon_intf_onu_id = (intf_id, onu_id) downlink_flow_id = self.resource_mgr.get_flow_id(pon_intf_onu_id) downstream_flow = openolt_pb2.Flow( access_intf_id=intf_id, onu_id=onu_id, flow_id=downlink_flow_id, flow_type=DOWNSTREAM, alloc_id=alloc_id, network_intf_id=0, gemport_id=gemport_id, classifier=self.mk_classifier(downlink_classifier), action=self.mk_action(downlink_action), priority=logical_flow.priority) downstream_logical_flow = ofp_flow_stats( id=logical_flow.id, cookie=logical_flow.cookie, table_id=logical_flow.table_id, priority=logical_flow.priority, flags=logical_flow.flags) downstream_logical_flow.match.oxm_fields.extend( fd.mk_oxm_fields([ fd.in_port(fd.get_out_port(logical_flow)), fd.vlan_vid(special_vlan_downstream_flow | 0x1000) ])) downstream_logical_flow.match.type = OFPMT_OXM downstream_logical_flow.instructions.extend( fd.mk_instructions_from_actions([ fd.output(self.platform.mk_uni_port_num(intf_id, onu_id)) ])) if self.add_flow_to_device(downstream_flow, downstream_logical_flow): flow_info = self._get_flow_info_as_json_blob( downstream_flow, EAPOL_PRIMARY_FLOW) self.update_flow_info_to_kv_store( downstream_flow.access_intf_id, downstream_flow.onu_id, downstream_flow.flow_id, flow_info)
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') _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: 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) if is_down_stream is False: intf_id, onu_id = self.parse_port_no( classifier_info['in_port']) self.divide_and_add_flow(onu_id, intf_id, classifier_info, action_info) except Exception as e: self.log.exception('failed-to-install-flow', e=e, flow=flow)
def add_eapol_flow(self, intf_id, onu_id, logical_flow, eapol_id=EAPOL_FLOW_INDEX, vlan_id=DEFAULT_MGMT_VLAN): uplink_classifier = {} uplink_classifier[ETH_TYPE] = EAP_ETH_TYPE uplink_classifier[PACKET_TAG_TYPE] = SINGLE_TAG uplink_classifier[VLAN_VID] = vlan_id uplink_action = {} uplink_action[TRAP_TO_HOST] = True # Add Upstream EAPOL Flow. pon_intf_onu_id = (intf_id, onu_id) gemport_id = self.resource_mgr.get_gemport_id( pon_intf_onu_id=pon_intf_onu_id ) alloc_id = self.resource_mgr.get_alloc_id( pon_intf_onu_id=pon_intf_onu_id ) uplink_flow_id = self.platform.mk_flow_id(intf_id, onu_id, eapol_id) upstream_flow = openolt_pb2.Flow( onu_id=onu_id, flow_id=uplink_flow_id, flow_type=UPSTREAM, access_intf_id=intf_id, gemport_id=gemport_id, alloc_id=alloc_id, priority=logical_flow.priority, classifier=self.mk_classifier(uplink_classifier), action=self.mk_action(uplink_action)) logical_flow = copy.deepcopy(logical_flow) logical_flow.match.oxm_fields.extend(fd.mk_oxm_fields([fd.vlan_vid( vlan_id | 0x1000)])) logical_flow.match.type = OFPMT_OXM self.add_flow_to_device(upstream_flow, logical_flow) if vlan_id == DEFAULT_MGMT_VLAN: # Add Downstream EAPOL Flow, Only for first EAP flow (BAL # requirement) special_vlan_downstream_flow = 4000 - onu_id downlink_classifier = {} downlink_classifier[PACKET_TAG_TYPE] = SINGLE_TAG downlink_classifier[VLAN_VID] = special_vlan_downstream_flow downlink_action = {} downlink_action[PUSH_VLAN] = True downlink_action[VLAN_VID] = vlan_id downlink_flow_id = self.platform.mk_flow_id( intf_id, onu_id, DOWNSTREAM_FLOW_FOR_PACKET_OUT) downstream_flow = openolt_pb2.Flow( onu_id=onu_id, flow_id=downlink_flow_id, flow_type=DOWNSTREAM, access_intf_id=intf_id, gemport_id=gemport_id, priority=logical_flow.priority, classifier=self.mk_classifier(downlink_classifier), action=self.mk_action(downlink_action)) downstream_logical_flow = ofp_flow_stats( id=logical_flow.id, cookie=logical_flow.cookie, table_id=logical_flow.table_id, priority=logical_flow.priority, flags=logical_flow.flags) downstream_logical_flow.match.oxm_fields.extend(fd.mk_oxm_fields([ fd.in_port(fd.get_out_port(logical_flow)), fd.vlan_vid((special_vlan_downstream_flow) | 0x1000)])) downstream_logical_flow.match.type = OFPMT_OXM downstream_logical_flow.instructions.extend( fd.mk_instructions_from_actions([fd.output( self.platform.mk_uni_port_num(intf_id, onu_id))])) self.add_flow_to_device(downstream_flow, downstream_logical_flow)
def add_eapol_flow(self, intf_id, onu_id, uni_id, port_no, logical_flow, alloc_id, gemport_id, vlan_id=DEFAULT_MGMT_VLAN): uplink_classifier = dict() uplink_classifier[ETH_TYPE] = EAP_ETH_TYPE uplink_classifier[PACKET_TAG_TYPE] = SINGLE_TAG uplink_classifier[VLAN_VID] = vlan_id uplink_action = dict() uplink_action[TRAP_TO_HOST] = True flow_store_cookie = self._get_flow_store_cookie(uplink_classifier, gemport_id) if self.resource_mgr.is_flow_cookie_on_kv_store(intf_id, onu_id, uni_id, flow_store_cookie): self.log.debug('flow-exists--not-re-adding') else: # Add Upstream EAPOL Flow. uplink_flow_id = self.resource_mgr.get_flow_id( intf_id, onu_id, uni_id, flow_store_cookie ) upstream_flow = openolt_pb2.Flow( access_intf_id=intf_id, onu_id=onu_id, uni_id=uni_id, flow_id=uplink_flow_id, flow_type=UPSTREAM, alloc_id=alloc_id, network_intf_id=self.data_model.olt_nni_intf_id(), gemport_id=gemport_id, classifier=self.mk_classifier(uplink_classifier), action=self.mk_action(uplink_action), priority=logical_flow.priority, port_no=port_no, cookie=logical_flow.cookie) logical_flow = copy.deepcopy(logical_flow) logical_flow.match.oxm_fields.extend(fd.mk_oxm_fields([fd.vlan_vid( vlan_id | 0x1000)])) logical_flow.match.type = OFPMT_OXM if self.add_flow_to_device(upstream_flow, logical_flow): flow_info = self._get_flow_info_as_json_blob(upstream_flow, flow_store_cookie) self.update_flow_info_to_kv_store(upstream_flow.access_intf_id, upstream_flow.onu_id, upstream_flow.uni_id, upstream_flow.flow_id, flow_info) if vlan_id == DEFAULT_MGMT_VLAN: # Add Downstream EAPOL Flow, Only for first EAP flow (BAL # requirement) # On one of the platforms (Broadcom BAL), when same DL classifier # vlan was used across multiple ONUs, eapol flow re-adds after # flow delete (cases of onu reboot/disable) fails. # In order to generate unique vlan, a combination of intf_id # onu_id and uni_id is used. # uni_id defaults to 0, so add 1 to it. special_vlan_downstream_flow = 4090 - intf_id * onu_id * (uni_id+1) # Assert that we do not generate invalid vlans under no condition assert special_vlan_downstream_flow >= 2 downlink_classifier = dict() downlink_classifier[PACKET_TAG_TYPE] = SINGLE_TAG downlink_classifier[VLAN_VID] = special_vlan_downstream_flow downlink_action = dict() downlink_action[PUSH_VLAN] = True downlink_action[VLAN_VID] = vlan_id flow_store_cookie = self._get_flow_store_cookie( downlink_classifier, gemport_id) if self.resource_mgr.is_flow_cookie_on_kv_store( intf_id, onu_id, uni_id, flow_store_cookie): self.log.debug('flow-exists--not-re-adding') else: downlink_flow_id = self.resource_mgr.get_flow_id( intf_id, onu_id, uni_id, flow_store_cookie ) downstream_flow = openolt_pb2.Flow( access_intf_id=intf_id, onu_id=onu_id, uni_id=uni_id, flow_id=downlink_flow_id, flow_type=DOWNSTREAM, alloc_id=alloc_id, network_intf_id=self.data_model.olt_nni_intf_id(), gemport_id=gemport_id, classifier=self.mk_classifier(downlink_classifier), action=self.mk_action(downlink_action), priority=logical_flow.priority, port_no=port_no, cookie=logical_flow.cookie) downstream_logical_flow = ofp_flow_stats( id=logical_flow.id, cookie=logical_flow.cookie, table_id=logical_flow.table_id, priority=logical_flow.priority, flags=logical_flow.flags) downstream_logical_flow.match.oxm_fields.extend( fd.mk_oxm_fields( [fd.in_port(fd.get_out_port(logical_flow)), fd.vlan_vid(special_vlan_downstream_flow | 0x1000)])) downstream_logical_flow.match.type = OFPMT_OXM downstream_logical_flow.instructions.extend( fd.mk_instructions_from_actions([fd.output( self.platform.mk_uni_port_num(intf_id, onu_id, uni_id))])) if self.add_flow_to_device(downstream_flow, downstream_logical_flow): flow_info = self._get_flow_info_as_json_blob( downstream_flow, flow_store_cookie) self.update_flow_info_to_kv_store( downstream_flow.access_intf_id, downstream_flow.onu_id, downstream_flow.uni_id, downstream_flow.flow_id, flow_info)
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_eapol_flow(self, intf_id, onu_id, logical_flow, uplink_eapol_id=EAPOL_FLOW_INDEX, downlink_eapol_id=EAPOL_DOWNLINK_FLOW_INDEX, vlan_id=DEFAULT_MGMT_VLAN): uplink_classifier = {} uplink_classifier['eth_type'] = EAP_ETH_TYPE uplink_classifier['pkt_tag_type'] = 'single_tag' uplink_classifier['vlan_vid'] = vlan_id uplink_action = {} uplink_action['trap_to_host'] = True gemport_id = self.platform.mk_gemport_id(intf_id, onu_id) # Add Upstream EAPOL Flow. uplink_flow_id = self.platform.mk_flow_id(intf_id, onu_id, uplink_eapol_id) upstream_flow = openolt_pb2.Flow( onu_id=onu_id, flow_id=uplink_flow_id, flow_type="upstream", access_intf_id=intf_id, gemport_id=gemport_id, priority=logical_flow.priority, classifier=self.mk_classifier(uplink_classifier), action=self.mk_action(uplink_action)) logical_flow = copy.deepcopy(logical_flow) logical_flow.match.oxm_fields.extend(fd.mk_oxm_fields([fd.vlan_vid( vlan_id | 0x1000)])) logical_flow.match.type = OFPMT_OXM self.add_flow_to_device(upstream_flow, logical_flow) if vlan_id == DEFAULT_MGMT_VLAN: # Add Downstream EAPOL Flow, Only for first EAP flow downlink_classifier = {} downlink_classifier['pkt_tag_type'] = 'single_tag' downlink_classifier['vlan_vid'] = 4000 - onu_id downlink_action = {} downlink_action['push_vlan'] = True downlink_action['vlan_vid'] = vlan_id downlink_flow_id = self.platform.mk_flow_id(intf_id, onu_id, downlink_eapol_id) downstream_flow = openolt_pb2.Flow( onu_id=onu_id, flow_id=downlink_flow_id, flow_type="downstream", access_intf_id=intf_id, gemport_id=gemport_id, priority=logical_flow.priority, classifier=self.mk_classifier(downlink_classifier), action=self.mk_action(downlink_action)) downstream_logical_flow = ofp_flow_stats(id=logical_flow.id, cookie=logical_flow.cookie, table_id=logical_flow.table_id, priority=logical_flow.priority, flags=logical_flow.flags) downstream_logical_flow.match.oxm_fields.extend(fd.mk_oxm_fields([ fd.in_port(fd.get_out_port(logical_flow)), fd.vlan_vid((4000 - onu_id) | 0x1000)])) downstream_logical_flow.match.type = OFPMT_OXM downstream_logical_flow.instructions.extend( fd.mk_instructions_from_actions([fd.output( self.platform.mk_uni_port_num(intf_id, onu_id))])) self.add_flow_to_device(downstream_flow, downstream_logical_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 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 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)