def verify_paging_flow_rules(self, ip_list): # Check if paging flows are created print("************ Verifying paging flow rules") num_paging_flows_to_be_verified = 1 for ip in ip_list: ue_ip_str = str(ip) print("Verifying paging flow for ip", ue_ip_str) for i in range(self.MAX_NUM_RETRIES): print("Get paging flows: attempt ", i) paging_flows = get_flows( self.datapath, { "table_id": self.SPGW_TABLE, "match": { "nw_dst": ue_ip_str, "eth_type": 2048, "priority": 5, }, }, ) if len(paging_flows) == num_paging_flows_to_be_verified: break time.sleep(5) # sleep for 5 seconds before retrying assert (len(paging_flows) == num_paging_flows_to_be_verified ), "Paging flow missing for UE" # TODO - Verify that the action is to send to controller """controller_port = 4294967293
def _simple_get(args): query = {"table_id": args.table_id} flows = get_flows(datapath, query) print("FlowEntry Match : captured packets") for flowentry in flows: print("Prior ", flowentry["priority"], end=' - ') print(flowentry["match"], flowentry["packet_count"], sep=', pkts: ')
def verify_flow_rules(self, num_ul_flows, dl_flow_rules=None): GTP_PORT = self.gtpBridgeUtil.get_gtp_port_no() # Check if UL and DL OVS flows are created print("************ Verifying flow rules") # UPLINK print("Checking for uplink flow") # try at least 5 times before failing as gateway # might take some time to install the flows in ovs for i in range(self.MAX_NUM_RETRIES): print("Get uplink flows: attempt ", i) uplink_flows = get_flows( self.datapath, { "table_id": self.SPGW_TABLE, "match": { "in_port": GTP_PORT, } }, ) if len(uplink_flows) == num_ul_flows: break time.sleep(5) # sleep for 5 seconds before retrying assert len(uplink_flows) == num_ul_flows, "Uplink flow missing for UE" assert uplink_flows[0]["match"]["tunnel_id"] is not None # DOWNLINK print("Checking for downlink flow") self._verify_dl_flow(dl_flow_rules)
def test_attach_asr_tcp_data(self): """ attach + send ASR Req to session manager with a""" """ single UE """ num_ues = 1 self._s1ap_wrapper.configUEDevice(num_ues) datapath = get_datapath() req = self._s1ap_wrapper.ue_req print( "********************** Running End to End attach for ", "UE id ", req.ue_id, ) # Now actually complete the attach self._s1ap_wrapper._s1_util.attach( req.ue_id, s1ap_types.tfwCmd.UE_END_TO_END_ATTACH_REQUEST, s1ap_types.tfwCmd.UE_ATTACH_ACCEPT_IND, s1ap_types.ueAttachAccept_t, ) # Wait on EMM Information from MME self._s1ap_wrapper._s1_util.receive_emm_info() print("Sleeping for 5 seconds") time.sleep(5) print( "********************** Sending ASR for IMSI", "".join([str(i) for i in req.imsi]), ) self._sessionManager_util.create_AbortSessionRequest( "IMSI" + "".join([str(i) for i in req.imsi]), ) # Receive NW initiated detach request response = self._s1ap_wrapper.s1_util.get_response() self.assertEqual( response.msg_type, s1ap_types.tfwCmd.UE_NW_INIT_DETACH_REQUEST.value, ) print("**************** Received NW initiated Detach Req") print("**************** Sending Detach Accept") # Send detach accept detach_accept = s1ap_types.ueTrigDetachAcceptInd_t() detach_accept.ue_Id = req.ue_id self._s1ap_wrapper._s1_util.issue_cmd( s1ap_types.tfwCmd.UE_TRIGGERED_DETACH_ACCEPT, detach_accept) print("Sleeping for 5 seconds") time.sleep(5) print("Checking that uplink/downlink flows were deleted") flows = get_flows(datapath, { "table_id": self.SPGW_TABLE, "priority": 0 }) self.assertEqual(len(flows), 2, "There should only be 2 default table 0 flows")
def lookup(self, match=None, cookie=None): return [ FlowStats(flow["packet_count"], flow["byte_count"], flow["duration_sec"], flow["cookie"]) for flow in get_flows( self._datapath, _generate_ryu_req(self._table_id, self._match, self._cookie), self._ovs_ip) ]
def test_default_metering_flows(self): datapath = get_datapath() print('Checking for default table 3 flows') flows = get_flows(datapath, { 'table_id': self.METERING_TABLE, 'priority': 0 }) self.assertEqual(len(flows), 2, 'There should be 2 default table 3 flows')
def _verify_ue_metering_flows(self, ue): datapath = get_datapath() flows = get_flows(datapath, { 'table_id': self.METERING_TABLE, 'priority': 10 }) self.assertEqual( 2, len(flows), 'There should be 2 UE metering flows, ' 'found {}'.format(len(flows))) ue_ip = str(self._s1ap_wrapper._s1_util.get_ip(ue.ue_id)) self._verify_downlink_flow(flows, ue_ip) self._verify_uplink_flow(flows, ue_ip)
def test_attach_detach_setsessionrules_tcp_data(self): """ Attach/detach + make set session rule calls to session manager twice + run UL and DL tcp traffic with a single UE """ num_ues = 1 self._s1ap_wrapper.configUEDevice(num_ues) datapath = get_datapath() MAX_NUM_RETRIES = 5 internet = { "apn_name": "internet", # APN-name "qci": 9, # qci "priority": 15, # priority "pre_cap": 0, # preemption-capability "pre_vul": 0, # preemption-vulnerability "mbr_ul": 100000, # MBR UL "mbr_dl": 150000, # MBR DL } # APN list to be configured apn_list = [internet] req = self._s1ap_wrapper.ue_req self._s1ap_wrapper.configAPN( "IMSI" + "".join([str(i) for i in req.imsi]), apn_list, default=False, ) print( "********************** Running End to End attach for ", "UE id ", req.ue_id, ) # Now actually complete the attach self._s1ap_wrapper._s1_util.attach( req.ue_id, s1ap_types.tfwCmd.UE_END_TO_END_ATTACH_REQUEST, s1ap_types.tfwCmd.UE_ATTACH_ACCEPT_IND, s1ap_types.ueAttachAccept_t, ) # Wait on EMM Information from MME self._s1ap_wrapper._s1_util.receive_emm_info() # UL Flow description #1 ulFlow1 = { "ip_proto": FlowMatch.IPPROTO_TCP, # Protocol Type "tcp_dst_port": 5001, # TCP Server Port "direction": FlowMatch.UPLINK, # Direction } # DL Flow description #1 dlFlow1 = { "ip_proto": FlowMatch.IPPROTO_TCP, # Protocol Type "tcp_dst_port": 7001, # TCP UE Port "direction": FlowMatch.DOWNLINK, # Direction } ulFlow2 = { "ip_proto": FlowMatch.IPPROTO_UDP, # Protocol Type "direction": FlowMatch.UPLINK, # Direction } # DL Flow description #1 dlFlow2 = { "ip_proto": FlowMatch.IPPROTO_UDP, # Protocol Type "direction": FlowMatch.DOWNLINK, # Direction } # Flow list to be configured flow_list = [ ulFlow1, dlFlow1, ulFlow2, dlFlow2, ] # QoS max_bw_ul = 20000 max_bw_dl = 35000 qos = { "qci": 8, # qci value [1 to 9] "priority": 0, # Range [0-255] "max_req_bw_ul": max_bw_ul, # MAX bw Uplink "max_req_bw_dl": max_bw_dl, # MAX bw Downlink "gbr_ul": 1000, # GBR Uplink "gbr_dl": 2000, # GBR Downlink "arp_prio": 15, # ARP priority "pre_cap": 1, # pre-emption capability "pre_vul": 1, # pre-emption vulnerability } policy_id = "tcp_udp_1" print("Sleeping for 5 seconds") time.sleep(5) print( "********************** Set Session Rule for IMSI", "".join([str(i) for i in req.imsi]), ) self._sessionManager_util.send_SetSessionRules( "IMSI" + "".join([str(i) for i in req.imsi]), policy_id, flow_list, qos, ) # Receive Activate dedicated bearer request response = self._s1ap_wrapper.s1_util.get_response() self.assertEqual( response.msg_type, s1ap_types.tfwCmd.UE_ACT_DED_BER_REQ.value, ) act_ded_ber_ctxt_req = response.cast( s1ap_types.UeActDedBearCtxtReq_t, ) # Send Activate dedicated bearer accept self._s1ap_wrapper.sendActDedicatedBearerAccept( req.ue_id, act_ded_ber_ctxt_req.bearerId, ) policy_id = "tcp_udp_2" print("Sleeping for 5 seconds") time.sleep(5) print( "********************** Set Session Rule for IMSI", "".join([str(i) for i in req.imsi]), ) self._sessionManager_util.send_SetSessionRules( "IMSI" + "".join([str(i) for i in req.imsi]), policy_id, flow_list, qos, ) # First rule is replaced by the second rule # Triggers a delete bearer followed by a create bearer request # Receive Deactivate dedicated bearer request response = self._s1ap_wrapper.s1_util.get_response() self.assertEqual( response.msg_type, s1ap_types.tfwCmd.UE_DEACTIVATE_BER_REQ.value, ) deactivate_ber_ctxt_req = response.cast( s1ap_types.UeDeActvBearCtxtReq_t, ) # Send Deactivate dedicated bearer accept self._s1ap_wrapper.sendDeactDedicatedBearerAccept( req.ue_id, deactivate_ber_ctxt_req.bearerId, ) # Receive Activate dedicated bearer request response = self._s1ap_wrapper.s1_util.get_response() self.assertEqual( response.msg_type, s1ap_types.tfwCmd.UE_ACT_DED_BER_REQ.value, ) act_ded_ber_ctxt_req = response.cast( s1ap_types.UeActDedBearCtxtReq_t, ) # Send Activate dedicated bearer accept self._s1ap_wrapper.sendActDedicatedBearerAccept( req.ue_id, act_ded_ber_ctxt_req.bearerId, ) print("Sleeping for 2 seconds") time.sleep(2) # Check if UL and DL OVS flows are created gtp_br_util = GTPBridgeUtils() gtp_port_no = gtp_br_util.get_gtp_port_no() # UPLINK print("Checking for uplink flow") # try at least 5 times before failing as gateway # might take some time to install the flows in ovs for i in range(MAX_NUM_RETRIES): print("Get uplink flows: attempt ", i) uplink_flows = get_flows( datapath, { "table_id": self.SPGW_TABLE, "match": { "in_port": gtp_port_no }, }, ) if len(uplink_flows) > 1: break time.sleep(5) # sleep for 5 seconds before retrying assert len(uplink_flows) == 2, "There should be 2 UL flow rules for UE" self.assertIsNotNone( uplink_flows[0]["match"]["tunnel_id"], "Uplink flow missing tunnel id match", ) self.assertIsNotNone( uplink_flows[1]["match"]["tunnel_id"], "Uplink flow missing tunnel id match", ) # DOWNLINK print("Checking for downlink flow") ue_ip = str(self._s1ap_wrapper._s1_util.get_ip(req.ue_id)) # try at least 5 times before failing as gateway # might take some time to install the flows in ovs for i in range(MAX_NUM_RETRIES): print("Get downlink flows: attempt ", i) downlink_flows = get_flows( datapath, { "table_id": self.SPGW_TABLE, "match": { "nw_dst": ue_ip, "eth_type": 2048, "in_port": self.LOCAL_PORT, }, }, ) if len(downlink_flows) > 1: break time.sleep(5) # sleep for 5 seconds before retrying assert len( downlink_flows) == 3, "Downlink flows must have been 3 for UE" self.assertEqual( downlink_flows[0]["match"]["ipv4_dst"], ue_ip, "UE IP match missing from downlink flow", ) actions = downlink_flows[0]["instructions"][0]["actions"] has_tunnel_action = any(action for action in actions if action["field"] == "tunnel_id" and action["type"] == "SET_FIELD") self.assertTrue( has_tunnel_action, "Downlink flow missing set tunnel action", ) # Get UL Flow Rule for TCP flows for verifying rate limits enforced print( "**********************Get uplink TCP flow for UE before UL traffic test:" ) uplink_flow_b = get_flows( datapath, { "table_id": self.SPGW_TABLE, "match": { "in_port": gtp_port_no }, "priority": 65535, }, ) print(uplink_flow_b) with self._s1ap_wrapper.configUplinkTest(req, duration=20, is_udp=False) as test: test.verify() # Get UL Flow Rule for TCP flows for verifying rate limits enforced print( "**********************Get uplink TCP flow for UE after UL traffic test:" ) uplink_flow_a = get_flows( datapath, { "table_id": self.SPGW_TABLE, "match": { "in_port": gtp_port_no }, "priority": 65535, }, ) print(uplink_flow_a) tcp_bytes = (uplink_flow_a[0]['byte_count'] - uplink_flow_b[0]['byte_count']) tcp_time = (uplink_flow_a[0]['duration_sec'] - uplink_flow_b[0]['duration_sec']) tcp_rate = 8 * tcp_bytes / tcp_time print("TCP UL Rate from OVS: %.2fbps" % tcp_rate) # Allow for a 10% error margin assert 0.9 * tcp_rate < max_bw_ul, "UL Rate for TCP flow violates UL rate policy for UE" # Get DL Flow Rule for TCP flows for verifying rate limits enforced print( "**********************Get downlink TCP flow for UE before DL traffic test:" ) downlink_flow_b = get_flows( datapath, { "table_id": self.SPGW_TABLE, "match": { "ipv4_dst": ue_ip, "eth_type": 2048, "in_port": self.LOCAL_PORT, "ip_proto": FlowMatch.IPPROTO_TCP, "tcp_dst": 7001, }, }, ) print(downlink_flow_b) with self._s1ap_wrapper.configDownlinkTest(req, duration=20, is_udp=False) as test: test.verify() # Get DL Flow Rule for TCP flows for verifying rate limits enforced print( "**********************Get downlink TCP flow for UE after DL traffic test:" ) downlink_flow_a = get_flows( datapath, { "table_id": self.SPGW_TABLE, "match": { "ipv4_dst": ue_ip, "eth_type": 2048, "in_port": self.LOCAL_PORT, "ip_proto": FlowMatch.IPPROTO_TCP, "tcp_dst": 7001, }, }, ) print(downlink_flow_a) tcp_bytes = (downlink_flow_a[0]['byte_count'] - downlink_flow_b[0]['byte_count']) tcp_time = (downlink_flow_a[0]['duration_sec'] - downlink_flow_b[0]['duration_sec']) tcp_rate = 8 * tcp_bytes / tcp_time print("TCP DL Rate from OVS: %.2fbps" % tcp_rate) # Allow for a 10% error margin assert 0.9 * tcp_rate < max_bw_dl, "DL Rate for TCP flow violates DL rate policy for UE" time.sleep(2) # sleep for 2 seconds before detaching print( "********************** Running UE detach for UE id ", req.ue_id, ) # Now detach the UE self._s1ap_wrapper.s1_util.detach( req.ue_id, s1ap_types.ueDetachType_t.UE_NORMAL_DETACH.value, True, ) # Verify that all UL/DL flows are deleted self._s1ap_wrapper.s1_util.verify_flow_rules_deletion()
def _verify_dl_flow(self, dl_flow_rules=None): # try at least 5 times before failing as gateway # might take some time to install the flows in ovs # Verify the total number of DL flows for this UE ip address num_dl_flows = 1 for key, value in dl_flow_rules.items(): tcp_src_port = 0 ip_proto = 0 ue_ip6_str = None ue_ip_str = str(key) if key.version == 6: ue_ip6_str = ipaddress.ip_network((ue_ip_str + "/64"), strict=False).with_netmask ue_ip_addr = ue_ip6_str if key.version == 6 else ue_ip_str dst_addr = "nw_dst" if key.version == 4 else "ipv6_dst" key_to_be_matched = "ipv4_src" if key.version == 4 else "ipv6_src" eth_typ = 2048 if key.version == 4 else 34525 # Set to 1 for the default bearer total_num_dl_flows_to_be_verified = 1 for item in value: for flow in item: if (flow["direction"] == FlowMatch.DOWNLINK and key_to_be_matched in flow): total_num_dl_flows_to_be_verified += 1 total_dl_ovs_flows_created = get_flows( self.datapath, { "table_id": self.SPGW_TABLE, "match": { dst_addr: ue_ip_addr, "eth_type": eth_typ, "in_port": self.LOCAL_PORT, }, }, ) assert (len(total_dl_ovs_flows_created) == total_num_dl_flows_to_be_verified) # Now verify the rules for every flow for item in value: for flow in item: if (flow["direction"] == FlowMatch.DOWNLINK and key_to_be_matched in flow): ip_src_addr = flow[key_to_be_matched] ip_src = "ipv4_src" if key.version == 4 else "ipv6_src" ip_dst = "ipv4_dst" if key.version == 4 else "ipv6_dst" tcp_src_port = flow["tcp_src_port"] ip_proto = flow["ip_proto"] for i in range(self.MAX_NUM_RETRIES): print("Get downlink flows: attempt ", i) downlink_flows = get_flows( self.datapath, { "table_id": self.SPGW_TABLE, "match": { ip_dst: ue_ip_addr, "eth_type": eth_typ, "in_port": self.LOCAL_PORT, ip_src: ip_src_addr, "tcp_src": tcp_src_port, "ip_proto": ip_proto, }, }, ) if len(downlink_flows) >= num_dl_flows: break time.sleep( 5) # sleep for 5 seconds before retrying assert (len(downlink_flows) >= num_dl_flows), "Downlink flow missing for UE" assert downlink_flows[0]["match"][ip_dst] == ue_ip_addr actions = downlink_flows[0]["instructions"][0][ "actions"] has_tunnel_action = any( action for action in actions if action["field"] == "tunnel_id" and action["type"] == "SET_FIELD") assert bool(has_tunnel_action)
def _verify_dl_flow(self, dl_flow_rules=None): # try at least 5 times before failing as gateway # might take some time to install the flows in ovs # Verify the total number of DL flows for this UE ip address num_dl_flows = 1 for key, value in dl_flow_rules.items(): ipv4_src_addr = None tcp_src_port = 0 ip_proto = 0 ue_ip_str = str(key) # Set to 1 for the default bearer total_num_dl_flows_to_be_verified = 1 for item in value: for flow in item: if flow["direction"] == "DL": total_num_dl_flows_to_be_verified += 1 total_dl_ovs_flows_created = get_flows( self.datapath, { "table_id": self.SPGW_TABLE, "match": { "nw_dst": ue_ip_str, "eth_type": 2048, "in_port": self.LOCAL_PORT, }, }, ) assert (len(total_dl_ovs_flows_created) == total_num_dl_flows_to_be_verified) # Now verify the rules for every flow for item in value: for flow in item: if flow["direction"] == "DL": ipv4_src_addr = flow["ipv4_src"] tcp_src_port = flow["tcp_src_port"] ip_proto = (FlowMatch.IPPROTO_TCP if (flow["ip_proto"] == "TCP") else FlowMatch.IPPROTO_UDP) for i in range(self.MAX_NUM_RETRIES): print("Get downlink flows: attempt ", i) downlink_flows = get_flows( self.datapath, { "table_id": self.SPGW_TABLE, "match": { "nw_dst": ue_ip_str, "eth_type": 2048, "in_port": self.LOCAL_PORT, "ipv4_src": ipv4_src_addr, "tcp_src": tcp_src_port, "ip_proto": ip_proto, }, }, ) if len(downlink_flows) >= num_dl_flows: break time.sleep( 5) # sleep for 5 seconds before retrying assert (len(downlink_flows) >= num_dl_flows), "Downlink flow missing for UE" assert (downlink_flows[0]["match"]["ipv4_dst"] == ue_ip_str) actions = downlink_flows[0]["instructions"][0][ "actions"] has_tunnel_action = any( action for action in actions if action["field"] == "tunnel_id" and action["type"] == "SET_FIELD") assert bool(has_tunnel_action)
def test_attach_detach_with_ovs(self): """ Basic sanity check of UE downlink/uplink flows during attach and detach procedures. """ datapath = get_datapath() MAX_NUM_RETRIES = 5 print("Checking for default table 0 flows") flows = get_flows(datapath, { "table_id": self.SPGW_TABLE, "priority": 0 }) self.assertEqual(len(flows), 1, "There should only be 1 default table 0 flow") self._s1ap_wrapper.configUEDevice(1) req = self._s1ap_wrapper.ue_req print("Running End to End attach for UE id ", req.ue_id) self._s1ap_wrapper._s1_util.attach( req.ue_id, s1ap_types.tfwCmd.UE_END_TO_END_ATTACH_REQUEST, s1ap_types.tfwCmd.UE_ATTACH_ACCEPT_IND, s1ap_types.ueAttachAccept_t) self._s1ap_wrapper._s1_util.receive_emm_info() # UPLINK print("Checking for uplink flow") # try at least 5 times before failing as gateway # might take some time to install the flows in ovs for i in range(MAX_NUM_RETRIES): print("Get uplink flows: attempt ", i) uplink_flows = get_flows(datapath, { "table_id": self.SPGW_TABLE, "match": { "in_port": self.GTP_PORT } }) if len(uplink_flows) > 0: break time.sleep(5) # sleep for 5 seconds before retrying self.assertEqual(len(uplink_flows), 1, "Uplink flow missing for UE") self.assertIsNotNone(uplink_flows[0]["match"]["tunnel_id"], "Uplink flow missing tunnel id match") self.check_imsi_metadata(uplink_flows[0], req) # DOWNLINK print("Checking for downlink flow") ue_ip = str(self._s1ap_wrapper._s1_util.get_ip(req.ue_id)) # Ryu can't match on ipv4_dst, so match on uplink in port # try at least 5 times before failing as gateway # might take some time to install the flows in ovs for i in range(MAX_NUM_RETRIES): print("Get downlink flows: attempt ", i) downlink_flows = get_flows( datapath, { "table_id": self.SPGW_TABLE, "match": { "nw_dst": ue_ip, "eth_type": 2048, "in_port": self.LOCAL_PORT } }) if len(downlink_flows) > 0: break time.sleep(5) # sleep for 5 seconds before retrying self.assertEqual(len(downlink_flows), 1, "Downlink flow missing for UE") self.assertEqual(downlink_flows[0]["match"]["ipv4_dst"], ue_ip, "UE IP match missing from downlink flow") actions = downlink_flows[0]["instructions"][0]["actions"] has_tunnel_action = any(action for action in actions if action["field"] == "tunnel_id" and action["type"] == "SET_FIELD") self.assertTrue(has_tunnel_action, "Downlink flow missing set tunnel action") self.check_imsi_metadata(downlink_flows[0], req) print("Running UE detach for UE id ", req.ue_id) # Now detach the UE self._s1ap_wrapper.s1_util.detach( req.ue_id, s1ap_types.ueDetachType_t.UE_NORMAL_DETACH.value, True) print("Checking that uplink/downlink flows were deleted") flows = get_flows(datapath, { "table_id": self.SPGW_TABLE, "priority": 0 }) self.assertEqual(len(flows), 1, "There should only be 1 default table 0 flow")
def test_attach_detach_with_he(self): """ Attach/detach + send ReAuth Req to session manager with a single UE along with Header enrichment. This test validates that same data test wotks with HE policy applied. Header enrichment should be as transparent as possible. """ num_ues = 1 detach_type = [ s1ap_types.ueDetachType_t.UE_NORMAL_DETACH.value, s1ap_types.ueDetachType_t.UE_SWITCHOFF_DETACH.value, ] wait_for_s1 = [True, False] self._s1ap_wrapper.configUEDevice(num_ues) datapath = get_datapath() MAX_NUM_RETRIES = 5 gtp_br_util = GTPBridgeUtils() PROXY_PORT = gtp_br_util.get_proxy_port_no() utils = HeaderEnrichmentUtils() for i in range(num_ues): req = self._s1ap_wrapper.ue_req print( "********************** Running End to End attach for ", "UE id ", req.ue_id, ) # Now actually complete the attach self._s1ap_wrapper._s1_util.attach( req.ue_id, s1ap_types.tfwCmd.UE_END_TO_END_ATTACH_REQUEST, s1ap_types.tfwCmd.UE_ATTACH_ACCEPT_IND, s1ap_types.ueAttachAccept_t, ) # Wait on EMM Information from MME self._s1ap_wrapper._s1_util.receive_emm_info() # UL Flow description #1 ulFlow1 = { "ipv4_dst": "192.168.129.42", # IPv4 destination address "tcp_dst_port": 5002, # TCP dest port "ip_proto": FlowMatch.IPPROTO_TCP, # Protocol Type "direction": FlowMatch.UPLINK, # Direction } # Flow list to be configured flow_list = [ ulFlow1, ] # QoS qos = { "qci": 5, # qci value [1 to 9] "priority": 0, # Range [0-255] "max_req_bw_ul": 10000000, # MAX bw Uplink "max_req_bw_dl": 15000000, # MAX bw Downlink "gbr_ul": 1000000, # GBR Uplink "gbr_dl": 2000000, # GBR Downlink "arp_prio": 15, # ARP priority "pre_cap": 1, # pre-emption capability "pre_vul": 1, # pre-emption vulnerability } policy_id = "ims-voice" print("Sleeping for 5 seconds") time.sleep(5) imsi = "IMSI" + "".join([str(i) for i in req.imsi]) he_domain1 = "192.168.129.42" assert utils.he_count_record_of_imsi_to_domain(imsi, he_domain1) == 0 print("********************** Sending RAR for ", imsi) self._sessionManager_util.send_ReAuthRequest( "IMSI" + "".join([str(i) for i in req.imsi]), policy_id, flow_list, qos, he_urls=HeaderEnrichment(urls=[he_domain1]), ) # Receive Activate dedicated bearer request response = self._s1ap_wrapper.s1_util.get_response() self.assertEqual(response.msg_type, s1ap_types.tfwCmd.UE_ACT_DED_BER_REQ.value) act_ded_ber_ctxt_req = response.cast( s1ap_types.UeActDedBearCtxtReq_t) print("Sleeping for 5 seconds") time.sleep(5) # Send Activate dedicated bearer accept self._s1ap_wrapper.sendActDedicatedBearerAccept( req.ue_id, act_ded_ber_ctxt_req.bearerId) # Check if UL and DL OVS flows are created # UPLINK print("Checking for uplink proxy flow for port: ", PROXY_PORT) # try at least 5 times before failing as gateway # might take some time to install the flows in ovs for i in range(MAX_NUM_RETRIES): uplink_flows = gtp_br_util.get_flows(self.HE_TABLE) if len(uplink_flows) > 1: break time.sleep(1) # sleep for 5 seconds before retrying assert len(uplink_flows) > 1, "HE flow missing for UE" assert utils.he_count_record_of_imsi_to_domain(imsi, he_domain1) == 1 print( "********************** Deleting dedicated bearer for IMSI", "".join([str(i) for i in req.imsi]), ) self._spgw_util.delete_bearer( "IMSI" + "".join([str(i) for i in req.imsi]), 5, 6) response = self._s1ap_wrapper.s1_util.get_response() self.assertEqual( response.msg_type, s1ap_types.tfwCmd.UE_DEACTIVATE_BER_REQ.value, ) print("******************* Received deactivate eps bearer context") deactv_bearer_req = response.cast(s1ap_types.UeDeActvBearCtxtReq_t) self._s1ap_wrapper.sendDeactDedicatedBearerAccept( req.ue_id, deactv_bearer_req.bearerId) print("Sleeping for 5 seconds") time.sleep(5) print( "********************** Running UE detach for UE id ", req.ue_id, ) # Now detach the UE self._s1ap_wrapper.s1_util.detach(req.ue_id, detach_type[i], wait_for_s1[i]) print("Checking that uplink/downlink flows were deleted") flows = get_flows(datapath, { "table_id": self.SPGW_TABLE, "priority": 0 }) self.assertEqual(len(flows), 2, "There should only be 2 default table 0 flows") time.sleep(20) assert utils.he_count_record_of_imsi_to_domain(imsi, he_domain1) == 0
def test_attach_detach_multiple_rar_tcp_data(self): """ attach + send two ReAuth Reqs to session manager with a""" """ single UE + send TCP data + detach""" """ Verify that the data is sent on 2nd dedicated bearer as it has""" """ matching PFs and higher priority""" num_ues = 1 detach_type = [ s1ap_types.ueDetachType_t.UE_NORMAL_DETACH.value, s1ap_types.ueDetachType_t.UE_SWITCHOFF_DETACH.value, ] wait_for_s1 = [True, False] self._s1ap_wrapper.configUEDevice(num_ues) datapath = get_datapath() MAX_NUM_RETRIES = 5 gtp_br_util = GTPBridgeUtils() GTP_PORT = gtp_br_util.get_gtp_port_no() for i in range(num_ues): req = self._s1ap_wrapper.ue_req print( "********************** Running End to End attach for ", "UE id ", req.ue_id, ) # Now actually complete the attach attach = self._s1ap_wrapper._s1_util.attach( req.ue_id, s1ap_types.tfwCmd.UE_END_TO_END_ATTACH_REQUEST, s1ap_types.tfwCmd.UE_ATTACH_ACCEPT_IND, s1ap_types.ueAttachAccept_t, ) # Wait on EMM Information from MME self._s1ap_wrapper._s1_util.receive_emm_info() # UL Flow description #1 ulFlow1 = { "ipv4_dst": "192.168.129.42", # IPv4 destination address "tcp_dst_port": 5002, # TCP dest port "ip_proto": FlowMatch.IPPROTO_TCP, # Protocol Type "direction": FlowMatch.UPLINK, # Direction } # UL Flow description #2 ulFlow2 = { "ipv4_dst": "192.168.129.42", # IPv4 destination address "tcp_dst_port": 5001, # TCP dest port "ip_proto": FlowMatch.IPPROTO_TCP, # Protocol Type "direction": FlowMatch.UPLINK, # Direction } # UL Flow description #3 ulFlow3 = { "ipv4_dst": "192.168.129.64", # IPv4 destination address "tcp_dst_port": 5003, # TCP dest port "ip_proto": FlowMatch.IPPROTO_TCP, # Protocol Type "direction": FlowMatch.UPLINK, # Direction } # UL Flow description #4 ulFlow4 = { "ipv4_dst": "192.168.129.42", # IPv4 destination address "tcp_dst_port": 5001, # TCP dest port "ip_proto": FlowMatch.IPPROTO_TCP, # Protocol Type "direction": FlowMatch.UPLINK, # Direction } # DL Flow description #1 dlFlow1 = { "ipv4_src": "192.168.129.42", # IPv4 source address "tcp_src_port": 5001, # TCP source port "ip_proto": FlowMatch.IPPROTO_TCP, # Protocol Type "direction": FlowMatch.DOWNLINK, # Direction } # DL Flow description #2 dlFlow2 = { "ipv4_src": "192.168.129.64", # IPv4 source address "tcp_src_port": 5002, # TCP source port "ip_proto": FlowMatch.IPPROTO_TCP, # Protocol Type "direction": FlowMatch.DOWNLINK, # Direction } # DL Flow description #3 dlFlow3 = { "ipv4_src": "192.168.129.64", # IPv4 source address "tcp_src_port": 5003, # TCP source port "ip_proto": FlowMatch.IPPROTO_TCP, # Protocol Type "direction": FlowMatch.DOWNLINK, # Direction } # DL Flow description #4 dlFlow4 = { "ipv4_src": "192.168.129.42", # IPv4 source address "tcp_src_port": 5001, # TCP source port "ip_proto": FlowMatch.IPPROTO_TCP, # Protocol Type "direction": FlowMatch.DOWNLINK, # Direction } # Flow lists to be configured flow_list1 = [ ulFlow1, ulFlow2, ulFlow3, dlFlow1, dlFlow2, dlFlow3, ] flow_list2 = [ ulFlow4, dlFlow4, ] # QoS qos1 = { "qci": 5, # qci value [1 to 9] "priority": 5, # Range [0-255] "max_req_bw_ul": 10000000, # MAX bw Uplink "max_req_bw_dl": 15000000, # MAX bw Downlink "gbr_ul": 1000000, # GBR Uplink "gbr_dl": 2000000, # GBR Downlink "arp_prio": 15, # ARP priority "pre_cap": 1, # pre-emption capability "pre_vul": 1, # pre-emption vulnerability } qos2 = { "qci": 1, # qci value [1 to 9] "priority": 1, # Range [0-255] "max_req_bw_ul": 10000000, # MAX bw Uplink "max_req_bw_dl": 15000000, # MAX bw Downlink "gbr_ul": 1000000, # GBR Uplink "gbr_dl": 2000000, # GBR Downlink "arp_prio": 1, # ARP priority "pre_cap": 1, # pre-emption capability "pre_vul": 1, # pre-emption vulnerability } policy_id1 = "ims-voice" policy_id2 = "internet" print("Sleeping for 5 seconds") time.sleep(5) print( "********************** Sending RAR for IMSI", "".join([str(i) for i in req.imsi]), ) self._sessionManager_util.send_ReAuthRequest( "IMSI" + "".join([str(i) for i in req.imsi]), policy_id1, flow_list1, qos1, ) # Receive Activate dedicated bearer request response = self._s1ap_wrapper.s1_util.get_response() self.assertEqual( response.msg_type, s1ap_types.tfwCmd.UE_ACT_DED_BER_REQ.value ) act_ded_ber_ctxt_req1 = response.cast( s1ap_types.UeActDedBearCtxtReq_t ) print("Sleeping for 5 seconds") time.sleep(5) # Send Activate dedicated bearer accept self._s1ap_wrapper.sendActDedicatedBearerAccept( req.ue_id, act_ded_ber_ctxt_req1.bearerId ) print( "********************** Sending 2nd RAR for IMSI", "".join([str(i) for i in req.imsi]), ) self._sessionManager_util.send_ReAuthRequest( "IMSI" + "".join([str(i) for i in req.imsi]), policy_id2, flow_list2, qos2, ) # Receive Activate dedicated bearer request response = self._s1ap_wrapper.s1_util.get_response() self.assertEqual( response.msg_type, s1ap_types.tfwCmd.UE_ACT_DED_BER_REQ.value ) act_ded_ber_ctxt_req2 = response.cast( s1ap_types.UeActDedBearCtxtReq_t ) print("Sleeping for 5 seconds") time.sleep(5) # Send Activate dedicated bearer accept self._s1ap_wrapper.sendActDedicatedBearerAccept( req.ue_id, act_ded_ber_ctxt_req2.bearerId ) # Check if UL and DL OVS flows are created # UPLINK print("Checking for uplink flow") # try at least 5 times before failing as gateway # might take some time to install the flows in ovs for i in range(MAX_NUM_RETRIES): print("Get uplink flows: attempt ", i) uplink_flows = get_flows( datapath, { "table_id": self.SPGW_TABLE, "match": {"in_port": GTP_PORT}, }, ) if len(uplink_flows) > 2: break time.sleep(5) # sleep for 5 seconds before retrying assert len(uplink_flows) > 2, "Uplink flow missing for UE" self.assertIsNotNone( uplink_flows[0]["match"]["tunnel_id"], "Uplink flow missing tunnel id match", ) # DOWNLINK print("Checking for downlink flow") ue_ip = str(self._s1ap_wrapper._s1_util.get_ip(req.ue_id)) # try at least 5 times before failing as gateway # might take some time to install the flows in ovs for i in range(MAX_NUM_RETRIES): print("Get downlink flows: attempt ", i) downlink_flows = get_flows( datapath, { "table_id": self.SPGW_TABLE, "match": { "nw_dst": ue_ip, "eth_type": 2048, "in_port": self.LOCAL_PORT, }, }, ) if len(downlink_flows) > 2: break time.sleep(5) # sleep for 5 seconds before retrying assert len(downlink_flows) > 2, "Downlink flow missing for UE" self.assertEqual( downlink_flows[0]["match"]["ipv4_dst"], ue_ip, "UE IP match missing from downlink flow", ) actions = downlink_flows[0]["instructions"][0]["actions"] has_tunnel_action = any( action for action in actions if action["field"] == "tunnel_id" and action["type"] == "SET_FIELD" ) self.assertTrue( has_tunnel_action, "Downlink flow missing set tunnel action" ) with self._s1ap_wrapper.configUplinkTest(req, duration=1) as test: test.verify() print("Sleeping for 5 seconds") time.sleep(5) print( "********************** Deleting dedicated bearer for IMSI", "".join([str(i) for i in req.imsi]), ) self._spgw_util.delete_bearer( "IMSI" + "".join([str(i) for i in req.imsi]), attach.esmInfo.epsBearerId, act_ded_ber_ctxt_req1.bearerId, ) response = self._s1ap_wrapper.s1_util.get_response() self.assertEqual( response.msg_type, s1ap_types.tfwCmd.UE_DEACTIVATE_BER_REQ.value, ) print("******************* Received deactivate eps bearer context") deactv_bearer_req = response.cast(s1ap_types.UeDeActvBearCtxtReq_t) self._s1ap_wrapper.sendDeactDedicatedBearerAccept( req.ue_id, deactv_bearer_req.bearerId ) print("Sleeping for 5 seconds") time.sleep(5) print( "********************** Running UE detach for UE id ", req.ue_id, ) # Now detach the UE self._s1ap_wrapper.s1_util.detach( req.ue_id, detach_type[i], wait_for_s1[i] ) print("Checking that uplink/downlink flows were deleted") flows = get_flows( datapath, {"table_id": self.SPGW_TABLE, "priority": 0} ) self.assertEqual( len(flows), 2, "There should only be 2 default table 0 flows" )
def test_attach_detach_rar_tcp_data_with_he(self): """ Attach/detach + send ReAuth Req to session manager with a single UE along with Header enrichment. This test validates that same data test wotks with HE policy applied. Header enrichment should be as transparent as possible. """ num_ues = 1 detach_type = [ s1ap_types.ueDetachType_t.UE_NORMAL_DETACH.value, s1ap_types.ueDetachType_t.UE_SWITCHOFF_DETACH.value, ] wait_for_s1 = [True, False] self._s1ap_wrapper.configUEDevice(num_ues) datapath = get_datapath() MAX_NUM_RETRIES = 5 gtp_br_util = GTPBridgeUtils() GTP_PORT = gtp_br_util.get_gtp_port_no() utils = HeaderEnrichmentUtils() for i in range(num_ues): req = self._s1ap_wrapper.ue_req print( "********************** Running End to End attach for ", "UE id ", req.ue_id, ) # Now actually complete the attach self._s1ap_wrapper._s1_util.attach( req.ue_id, s1ap_types.tfwCmd.UE_END_TO_END_ATTACH_REQUEST, s1ap_types.tfwCmd.UE_ATTACH_ACCEPT_IND, s1ap_types.ueAttachAccept_t, ) # Wait on EMM Information from MME self._s1ap_wrapper._s1_util.receive_emm_info() # UL Flow description #1 ulFlow1 = { "ipv4_dst": "192.168.129.42", # IPv4 destination address "tcp_dst_port": 5002, # TCP dest port "ip_proto": FlowMatch.IPPROTO_TCP, # Protocol Type "direction": FlowMatch.UPLINK, # Direction } # UL Flow description #2 ulFlow2 = { "ipv4_dst": "192.168.129.42", # IPv4 destination address "tcp_dst_port": 5001, # TCP dest port "ip_proto": FlowMatch.IPPROTO_TCP, # Protocol Type "direction": FlowMatch.UPLINK, # Direction } # UL Flow description #3 ulFlow3 = { "ipv4_dst": "192.168.129.64", # IPv4 destination address "tcp_dst_port": 5003, # TCP dest port "ip_proto": FlowMatch.IPPROTO_TCP, # Protocol Type "direction": FlowMatch.UPLINK, # Direction } # UL Flow description #4 ulFlow4 = { "ipv4_dst": "192.168.129.42", # IPv4 destination address "tcp_dst_port": 5004, # TCP dest port "ip_proto": FlowMatch.IPPROTO_TCP, # Protocol Type "direction": FlowMatch.UPLINK, # Direction } # DL Flow description #1 dlFlow1 = { "ipv4_src": "192.168.129.42", # IPv4 source address "tcp_src_port": 5001, # TCP source port "ip_proto": FlowMatch.IPPROTO_TCP, # Protocol Type "direction": FlowMatch.DOWNLINK, # Direction } # DL Flow description #2 dlFlow2 = { "ipv4_src": "192.168.129.64", # IPv4 source address "tcp_src_port": 5002, # TCP source port "ip_proto": FlowMatch.IPPROTO_TCP, # Protocol Type "direction": FlowMatch.DOWNLINK, # Direction } # DL Flow description #3 dlFlow3 = { "ipv4_src": "192.168.129.64", # IPv4 source address "tcp_src_port": 5003, # TCP source port "ip_proto": FlowMatch.IPPROTO_TCP, # Protocol Type "direction": FlowMatch.DOWNLINK, # Direction } # DL Flow description #4 dlFlow4 = { "ipv4_src": "192.168.129.42", # IPv4 source address "tcp_src_port": 5004, # TCP source port "ip_proto": FlowMatch.IPPROTO_TCP, # Protocol Type "direction": FlowMatch.DOWNLINK, # Direction } # Flow list to be configured flow_list = [ ulFlow1, ulFlow2, ulFlow3, ulFlow4, dlFlow1, dlFlow2, dlFlow3, dlFlow4, ] # QoS qos = { "qci": 5, # qci value [1 to 9] "priority": 0, # Range [0-255] "max_req_bw_ul": 10000000, # MAX bw Uplink "max_req_bw_dl": 15000000, # MAX bw Downlink "gbr_ul": 1000000, # GBR Uplink "gbr_dl": 2000000, # GBR Downlink "arp_prio": 15, # ARP priority "pre_cap": 1, # pre-emption capability "pre_vul": 1, # pre-emption vulnerability } policy_id = "ims-voice" print("Sleeping for 5 seconds") time.sleep(5) imsi = "IMSI" + "".join([str(i) for i in req.imsi]) print( "********************** Sending RAR for ", imsi, ) he_domain1 = "192.168.128.1" assert utils.he_count_record_of_imsi_to_domain(imsi, he_domain1) == 0 self._sessionManager_util.send_ReAuthRequest( "IMSI" + "".join([str(i) for i in req.imsi]), policy_id, flow_list, qos, he_urls=HeaderEnrichment(urls=[he_domain1]), ) # Receive Activate dedicated bearer request response = self._s1ap_wrapper.s1_util.get_response() self.assertEqual( response.msg_type, s1ap_types.tfwCmd.UE_ACT_DED_BER_REQ.value, ) act_ded_ber_ctxt_req = response.cast( s1ap_types.UeActDedBearCtxtReq_t, ) print("Sleeping for 5 seconds") time.sleep(5) # Send Activate dedicated bearer accept self._s1ap_wrapper.sendActDedicatedBearerAccept( req.ue_id, act_ded_ber_ctxt_req.bearerId, ) # Check if UL and DL OVS flows are created # UPLINK print("Checking for uplink flow") # try at least 5 times before failing as gateway # might take some time to install the flows in ovs for i in range(MAX_NUM_RETRIES): print("Get uplink flows: attempt ", i) uplink_flows = get_flows( datapath, { "table_id": self.SPGW_TABLE, "match": { "in_port": GTP_PORT }, }, ) if len(uplink_flows) > 1: break time.sleep(5) # sleep for 5 seconds before retrying assert len(uplink_flows) > 1, "Uplink flow missing for UE" self.assertIsNotNone( uplink_flows[0]["match"]["tunnel_id"], "Uplink flow missing tunnel id match", ) # DOWNLINK print("Checking for downlink flow") ue_ip = str(self._s1ap_wrapper._s1_util.get_ip(req.ue_id)) # try at least 5 times before failing as gateway # might take some time to install the flows in ovs for i in range(MAX_NUM_RETRIES): print("Get downlink flows: attempt ", i) downlink_flows = get_flows( datapath, { "table_id": self.SPGW_TABLE, "match": { "nw_dst": ue_ip, "eth_type": 2048, "in_port": self.LOCAL_PORT, }, }, ) if len(downlink_flows) > 1: break time.sleep(5) # sleep for 5 seconds before retrying assert len(downlink_flows) > 1, "Downlink flow missing for UE" self.assertEqual( downlink_flows[0]["match"]["ipv4_dst"], ue_ip, "UE IP match missing from downlink flow", ) actions = downlink_flows[0]["instructions"][0]["actions"] has_tunnel_action = any(action for action in actions if action["field"] == "tunnel_id" and action["type"] == "SET_FIELD") self.assertTrue( has_tunnel_action, "Downlink flow missing set tunnel action", ) print("Sleeping for 5 seconds") time.sleep(5) with self._s1ap_wrapper.configUplinkTest(req, duration=1) as test: test.verify() assert utils.he_count_record_of_imsi_to_domain(imsi, he_domain1) == 1 print( "********************** Deleting dedicated bearer for IMSI", "".join([str(i) for i in req.imsi]), ) self._spgw_util.delete_bearer( "IMSI" + "".join([str(i) for i in req.imsi]), 5, 6, ) response = self._s1ap_wrapper.s1_util.get_response() self.assertEqual( response.msg_type, s1ap_types.tfwCmd.UE_DEACTIVATE_BER_REQ.value, ) print("******************* Received deactivate eps bearer context") deactv_bearer_req = response.cast(s1ap_types.UeDeActvBearCtxtReq_t) self._s1ap_wrapper.sendDeactDedicatedBearerAccept( req.ue_id, deactv_bearer_req.bearerId, ) print("Sleeping for 5 seconds") time.sleep(5) print( "********************** Running UE detach for UE id ", req.ue_id, ) # Now detach the UE self._s1ap_wrapper.s1_util.detach( req.ue_id, detach_type[i], wait_for_s1[i], ) time.sleep(20) assert utils.he_count_record_of_imsi_to_domain(imsi, he_domain1) == 0 # Verify that all UL/DL flows are deleted self._s1ap_wrapper.s1_util.verify_flow_rules_deletion()