def leaf_device_default_rules(device): ports = self.root_proxy.get('/devices/{}/ports'.format(device.id)) upstream_ports = [ port for port in ports if port.type == Port.PON_ONU \ or port.type == Port.VENET_ONU ] assert len(upstream_ports) == 1 downstream_ports = [ port for port in ports if port.type == Port.ETHERNET_UNI ] # it is possible that the downstream ports are not # created, but the flow_decomposition has already # kicked in. In such scenarios, cut short the processing # and return. if len(downstream_ports) == 0: return None, None # assert len(downstream_ports) == 1 upstream_port = upstream_ports[0] flows = OrderedDict() for downstream_port in downstream_ports: flows.update(OrderedDict((f.id, f) for f in [ mk_flow_stat( priority=500, match_fields=[ in_port(downstream_port.port_no), vlan_vid(ofp.OFPVID_PRESENT | 0) ], actions=[ set_field(vlan_vid(ofp.OFPVID_PRESENT | device.vlan)), output(upstream_port.port_no) ] ), mk_flow_stat( priority=500, match_fields=[ in_port(downstream_port.port_no), vlan_vid(0) ], actions=[ push_vlan(0x8100), set_field(vlan_vid(ofp.OFPVID_PRESENT | device.vlan)), output(upstream_port.port_no) ] ), mk_flow_stat( priority=500, match_fields=[ in_port(upstream_port.port_no), vlan_vid(ofp.OFPVID_PRESENT | device.vlan) ], actions=[ set_field(vlan_vid(ofp.OFPVID_PRESENT | 0)), output(downstream_port.port_no) ] ), ])) groups = OrderedDict() return flows, groups
def leaf_device_default_rules(device): ports = self.root_proxy.get('/devices/{}/ports'.format(device.id)) upstream_ports = [ port for port in ports if port.type == Port.PON_ONU \ or port.type == Port.VENET_ONU ] assert len(upstream_ports) == 1 downstream_ports = [ port for port in ports if port.type == Port.ETHERNET_UNI ] # assert len(downstream_ports) == 1 flows = OrderedDict((f.id, f) for f in [ mk_flow_stat( priority=500, match_fields=[ in_port(downstream_ports[0].port_no), vlan_vid(ofp.OFPVID_PRESENT | 0) ], actions=[ set_field(vlan_vid(ofp.OFPVID_PRESENT | device.vlan)), output(upstream_ports[0].port_no) ] ), mk_flow_stat( priority=500, match_fields=[ in_port(downstream_ports[0].port_no), vlan_vid(0) ], actions=[ push_vlan(0x8100), set_field(vlan_vid(ofp.OFPVID_PRESENT | device.vlan)), output(upstream_ports[0].port_no) ] ), mk_flow_stat( priority=500, match_fields=[ in_port(upstream_ports[0].port_no), vlan_vid(ofp.OFPVID_PRESENT | device.vlan) ], actions=[ set_field(vlan_vid(ofp.OFPVID_PRESENT | 0)), output(downstream_ports[0].port_no) ] ), ]) groups = OrderedDict() return flows, groups
def root_device_default_rules(device): ports = self.root_proxy.get('/devices/{}/ports'.format(device.id)) upstream_ports = [ port for port in ports if port.type == Port.ETHERNET_NNI ] assert len(upstream_ports) == 1 downstream_ports = [ port for port in ports if port.type == Port.PON_OLT \ or port.type == Port.VENET_OLT ] _is_any_venet_port = any(_port.type == Port.VENET_OLT for _port in downstream_ports) if _is_any_venet_port != True: assert len(downstream_ports) == 1, \ 'Initially, we only handle one PON port' flows = OrderedDict((f.id, f) for f in [ mk_flow_stat( priority=2000, match_fields=[ in_port(upstream_ports[0].port_no), vlan_vid(ofp.OFPVID_PRESENT | 4000), vlan_pcp(0) ], actions=[ pop_vlan(), output(downstream_ports[0].port_no) ] ) ]) groups = OrderedDict() return flows, groups
def _list_and_update_logical_device_flows(self, id): # retrieve flow list res = self.get('/api/v1/logical_devices/{}/flows'.format(id)) len_before = len(res['items']) # add some flows req = ofp.FlowTableUpdate( id=id, flow_mod=mk_simple_flow_mod( cookie=randint(1, 10000000000), priority=len_before, match_fields=[ in_port(129) ], actions=[ output(1) ] ) ) res = self.post('/api/v1/logical_devices/{}/flows'.format(id), MessageToDict(req, preserving_proto_field_name=True), expected_http_code=200) # TODO check some stuff on res res = self.get('/api/v1/logical_devices/{}/flows'.format(id)) len_after = len(res['items']) self.assertGreater(len_after, len_before)
def _list_and_update_local_logical_device_flows(self, id): # retrieve flow list res = self.get('/api/v1/local/logical_devices/{}/flows'.format(id)) len_before = len(res['items']) t0 = time() # add some flows for _ in xrange(10): req = ofp.FlowTableUpdate( id=id, flow_mod=mk_simple_flow_mod( cookie=randint(1, 10000000000), priority=randint(1, 10000), # to make it unique match_fields=[ in_port(129) ], actions=[ output(1) ] ) ) self.post('/api/v1/local/logical_devices/{}/flows'.format(id), MessageToDict(req, preserving_proto_field_name=True), expected_http_code=200) print time() - t0 res = self.get('/api/v1/local/logical_devices/{}/flows'.format(id)) len_after = len(res['items']) self.assertGreater(len_after, len_before)
def handle_packet_in_event(self, logical_port_no, packet): self.log.debug('handle-packet-in', logical_port_no=logical_port_no) packet_in = ofp.ofp_packet_in( # buffer_id=0, reason=ofp.OFPR_ACTION, # table_id=0, # cookie=0, match=ofp.ofp_match( type=ofp.OFPMT_OXM, oxm_fields=[ ofp.ofp_oxm_field( oxm_class=ofp.OFPXMC_OPENFLOW_BASIC, ofb_field=in_port(logical_port_no) ) ] ), data=packet ) packet_in = ofp.PacketIn(id=self.device.data_model.logical_device_id, packet_in=packet_in) ''' # FIXME - change this to use kafka lh = self.device.data_model.adapter_agent.core.get_local_handler() lh.core.packet_in_queue.put(packet_in) ''' kafka_send_pb('voltha.pktin', packet_in)
def update_flow_table(self, flows): stub = ponsim_pb2_grpc.PonSimStub(self.get_channel()) self.log.info('pushing-olt-flow-table') eapol_flows = {} eapol_flow_without_vlan = False for flow in flows: classifier_info = self.get_classifier_info(flow) self.log.debug('classifier_info', classifier_info=classifier_info) if IP_PROTO in classifier_info: if classifier_info[IP_PROTO] == 17: if UDP_SRC in classifier_info: if classifier_info[UDP_SRC] == 68: self.log.info('dhcp upstream flow add') elif classifier_info[UDP_SRC] == 67: self.log.info('dhcp downstream flow add') self.to_controller(flow) elif classifier_info[IP_PROTO] == 2: self.log.info('igmp flow add') self.to_controller(flow) else: self.log.warn("Invalid-Classifier-to-handle", classifier_info=classifier_info) elif ETH_TYPE in classifier_info: if classifier_info[ETH_TYPE] == EAP_ETH_TYPE: self.log.info('eapol flow add') self.to_controller(flow) if VLAN_VID in classifier_info: eapol_flows[classifier_info[VLAN_VID]] = flow else: eapol_flow_without_vlan = True # The OLT app is now adding EAPOL flows with VLAN_VID=4091 but Ponsim can't # properly handle this because it uses VLAN_VID to encode the UNI port ID. # Add an EAPOL trap flow with no VLAN_VID match if we see the 4091 match. if 4091 in eapol_flows and not eapol_flow_without_vlan: new_eapol_flow = [ fd.mk_flow_stat( priority=10000, match_fields=[fd.in_port(1), fd.eth_type(EAP_ETH_TYPE)], actions=[fd.output(ofp.OFPP_CONTROLLER)] ) ] flows.extend(new_eapol_flow) self.log.info('add eapol flow with no VLAN_VID match') stub.UpdateFlowTable(FlowTable( port=0, flows=flows )) self.log.info('success')
def handle_packet_in_event(self, _, msg): self.log.debug('handle-packet-in', msg=msg) logical_port_no, packet = msg packet_in = ofp.ofp_packet_in( # buffer_id=0, reason=ofp.OFPR_ACTION, # table_id=0, # cookie=0, match=ofp.ofp_match(type=ofp.OFPMT_OXM, oxm_fields=[ ofp.ofp_oxm_field( oxm_class=ofp.OFPXMC_OPENFLOW_BASIC, ofb_field=in_port(logical_port_no)) ]), data=packet) self.packet_in(packet_in)
def handle_packet_in_event(self, _, msg): self.log.debug('handle-packet-in', msg=msg) logical_port_no, packet = msg packet_in = ofp.ofp_packet_in( # buffer_id=0, reason=ofp.OFPR_ACTION, # table_id=0, # cookie=0, match=ofp.ofp_match( type=ofp.OFPMT_OXM, oxm_fields=[ ofp.ofp_oxm_field( oxm_class=ofp.OFPXMC_OPENFLOW_BASIC, ofb_field=in_port(logical_port_no) ) ] ), data=packet ) self.packet_in(packet_in)
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_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 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)