def test_setup_flows_req(self): gx_req1 = ActivateFlowsRequest() gx_req2 = ActivateFlowsRequest() gy_req = ActivateFlowsRequest( request_origin=RequestOriginType(type=RequestOriginType.GY), ) setup_req = SetupPolicyRequest(requests=[gx_req1, gx_req2, gy_req]) self.pipelined_srv.SetupPolicyFlows(setup_req, MagicMock()) self._enforcer_app.handle_restart.assert_called_with( [gx_req1, gx_req2]) self._enforcement_stats.handle_restart.assert_called_with( [gx_req1, gx_req2]) self._gy_app.handle_restart.assert_called_with([gy_req])
def activate_flows(client, args): request = ActivateFlowsRequest( sid=SIDUtils.to_pb(args.imsi), rule_ids=args.rule_ids.split(','), request_origin=RequestOriginType(type=RequestOriginType.GX)) response = client.ActivateFlows(request) _print_rule_mod_results(response.static_rule_results)
def _activate_subscriber_rules(self): try_grpc_call_with_retries( lambda: self._pipelined_stub.ActivateFlows( ActivateFlowsRequest(sid=SIDUtils.to_pb(self.cfg.imsi), rule_ids=self._static_rule_names, dynamic_rules=self._dynamic_rules)) )
def activate_flows(client, args): request = ActivateFlowsRequest( sid=SIDUtils.to_pb(args.imsi), ip_addr=args.ipv4, policies=[ VersionedPolicy( rule=PolicyRule( id=args.rule_id, priority=args.priority, hard_timeout=args.hard_timeout, flow_list=[ FlowDescription( match=FlowMatch( ip_dst=convert_ipv4_str_to_ip_proto(args.ipv4_dst), direction=FlowMatch.UPLINK, ), ), FlowDescription( match=FlowMatch( ip_src=convert_ipv4_str_to_ip_proto(args.ipv4_dst), direction=FlowMatch.DOWNLINK, ), ), ], ), version=1, ), ], request_origin=RequestOriginType(type=RequestOriginType.GX), shard_id=args.shard_id, ) response = client.ActivateFlows(request) _print_rule_mod_results(response.policy_results)
def CreateSession(self, request, context): """ Handles create session request from MME by installing the necessary flows in pipelined's enforcement app. """ sid = request.sid logging.info('Create session request for sid: %s' % sid.id) try: # Gather the set of policy rules to use if self._captive_portal_enabled(sid): rules = [] rules.extend(self._get_whitelisted_policies()) rules.extend(self._get_redirect_policies()) else: rules = self._get_allow_all_traffic_policies() # Activate the flows in the enforcement app in pipelined act_request = ActivateFlowsRequest(sid=sid, ip_addr=request.ue_ipv4, dynamic_rules=rules) act_response = self._pipelined.ActivateFlows( act_request, timeout=self.RPC_TIMEOUT) for res in act_response.dynamic_rule_results: if res.result != res.SUCCESS: # Hmm rolling back partial success is difficult # Let's just log this for now logging.error('Failed to activate rule: %s' % res.rule_id) except RpcError as err: self._set_rpc_error(context, err) return session_manager_pb2.LocalCreateSessionResponse()
def _activate_subscriber_rules(self): try_grpc_call_with_retries( lambda: self._pipelined_stub.ActivateFlows( ActivateFlowsRequest( sid=SIDUtils.to_pb(self.cfg.imsi), policies=self._policies, ), ), )
def CreateAddQERinPDR( qos_enforce_rule: QoSEnforceRuleEntry, ue_ip_addr: str, apn_ambr: AggregatedMaximumBitrate, ) -> ActivateFlowsRequest: if qos_enforce_rule.allow == 'YES': allow = FlowDescription.PERMIT else: allow = FlowDescription.DENY ip_dst = None ip_src = None if qos_enforce_rule.ipv4_dst: ip_dst = convert_ipv4_str_to_ip_proto(qos_enforce_rule.ipv4_dst) ip_src = convert_ipv4_str_to_ip_proto(qos_enforce_rule.ipv4_dst) if qos_enforce_rule.direction == FlowMatch.UPLINK: flow_list = [ FlowDescription( match=FlowMatch( ip_dst=ip_dst, direction=qos_enforce_rule.direction, ), action=allow, ), ] else: flow_list = [ FlowDescription( match=FlowMatch( ip_src=ip_src, direction=qos_enforce_rule.direction, ), action=allow, ), ] qos_enforce_rule = ActivateFlowsRequest( sid=SIDUtils.to_pb(qos_enforce_rule.imsi), ip_addr=ue_ip_addr, policies=[ VersionedPolicy( rule=PolicyRule( id=qos_enforce_rule.rule_id, priority=qos_enforce_rule.priority, hard_timeout=qos_enforce_rule.hard_timeout, flow_list=flow_list, ), version=1, ), ], request_origin=RequestOriginType(type=RequestOriginType.N4), apn_ambr=apn_ambr, ) return qos_enforce_rule
def test_activate_flows_req(self): rule = PolicyRule(id="rule1", priority=100, flow_list=[]) policies = [VersionedPolicy(rule=rule, version=1)] req = ActivateFlowsRequest( sid=SubscriberID(id="imsi12345"), ip_addr="1.2.3.4", msisdn=b'magma', uplink_tunnel=0x1, downlink_tunnel=0x2, policies=policies, ) ip_addr = IPAddress( version=IPAddress.IPV4, address=req.ip_addr.encode('utf-8'), ) self.pipelined_srv.ActivateFlows(req, MagicMock()) # Not using assert_called_with because protos comparison assert self._enforcement_stats.activate_rules.call_args.args[ 0] == req.sid.id assert self._enforcement_stats.activate_rules.call_args.args[ 1] == req.msisdn assert self._enforcement_stats.activate_rules.call_args.args[ 2] == req.uplink_tunnel assert self._enforcement_stats.activate_rules.call_args.args[ 3].version == ip_addr.version assert self._enforcement_stats.activate_rules.call_args.args[ 3].address == ip_addr.address assert self._enforcement_stats.activate_rules.call_args.args[ 4] == req.apn_ambr assert self._enforcement_stats.activate_rules.call_args.args[5][ 0].version == policies[0].version assert self._enforcement_stats.activate_rules.call_args.args[ 6] == req.shard_id assert self._enforcement_stats.activate_rules.call_args.args[7] == 0 assert self._enforcer_app.activate_rules.call_args.args[ 0] == req.sid.id assert self._enforcer_app.activate_rules.call_args.args[ 1] == req.msisdn assert self._enforcer_app.activate_rules.call_args.args[ 2] == req.uplink_tunnel assert self._enforcer_app.activate_rules.call_args.args[ 3].version == ip_addr.version assert self._enforcer_app.activate_rules.call_args.args[ 3].address == ip_addr.address assert self._enforcer_app.activate_rules.call_args.args[ 4] == req.apn_ambr assert self._enforcer_app.activate_rules.call_args.args[5][ 0].version == policies[0].version assert self._enforcer_app.activate_rules.call_args.args[ 6] == req.shard_id assert self._enforcer_app.activate_rules.call_args.args[7] == 0
def activate_dynamic_rule(client, args): request = ActivateFlowsRequest( sid=SIDUtils.to_pb(args.imsi), dynamic_rules=[PolicyRule( id=args.rule_id, priority=args.priority, hard_timeout=args.hard_timeout, flow_list=[ FlowDescription(match=FlowMatch( ipv4_dst=args.ipv4_dst, direction=FlowMatch.UPLINK)), FlowDescription(match=FlowMatch( ipv4_src=args.ipv4_dst, direction=FlowMatch.DOWNLINK)), ], )]) client.ActivateFlows(request)
def activate_gy_redirect(client, args): request = ActivateFlowsRequest( sid=SIDUtils.to_pb(args.imsi), ip_addr=args.ipv4, dynamic_rules=[ PolicyRule(id=args.rule_id, priority=999, flow_list=[], redirect=RedirectInformation( support=1, address_type=2, server_address=args.redirect_addr)) ], request_origin=RequestOriginType(type=RequestOriginType.GY)) response = client.ActivateFlows(request) _print_rule_mod_results(response.dynamic_rule_results)
def _build_activate_flows_data(ue_dict, disable_qos): activate_flow_reqs = [] if disable_qos: print("QOS Disabled") apn_ambr = None else: print("QOS Enabled") apn_ambr = AggregatedMaximumBitrate( max_bandwidth_ul=1000000000, max_bandwidth_dl=1000000000, ) for ue in ue_dict: request = ActivateFlowsRequest( sid=SIDUtils.to_pb(ue.imsi_str), ip_addr=ue.ipv4_src, policies=[ VersionedPolicy( rule=PolicyRule( id=ue.rule_id, priority=10, flow_list=[ FlowDescription(match=FlowMatch( ip_dst=convert_ipv4_str_to_ip_proto( ue.ipv4_src), direction=FlowMatch.UPLINK, ), ), FlowDescription(match=FlowMatch( ip_src=convert_ipv4_str_to_ip_proto( ue.ipv4_dst), direction=FlowMatch.DOWNLINK, ), ), ], ), version=1, ), ], request_origin=RequestOriginType(type=RequestOriginType.GX), apn_ambr=apn_ambr, ) request_dict = json_format.MessageToDict(request) # Dumping ActivateFlows request into json activate_flow_reqs.append(request_dict) with open('activate_flows.json', 'w') as file: json.dump(activate_flow_reqs, file, separators=(',', ':'))
def activate_dynamic_rule(client, args): request = ActivateFlowsRequest( sid=SIDUtils.to_pb(args.imsi), dynamic_rules=[ PolicyRule( id=args.rule_id, priority=args.priority, hard_timeout=args.hard_timeout, flow_list=[ FlowDescription(match=FlowMatch( ipv4_dst=args.ipv4_dst, direction=FlowMatch.UPLINK)), FlowDescription(match=FlowMatch( ipv4_src=args.ipv4_dst, direction=FlowMatch.DOWNLINK)), ], ) ], request_origin=RequestOriginType(type=RequestOriginType.GX)) response = client.ActivateFlows(request) _print_rule_mod_results(response.dynamic_rule_results)
def CreateAddQERinPDR(qos_enforce_rule: QoSEnforceRuleEntry, ue_ip_addr: str) -> ActivateFlowsRequest: if qos_enforce_rule.allow == 'YES': allow = FlowDescription.PERMIT else: allow = FlowDescription.DENY ip_dst = None ip_src = None if qos_enforce_rule.ipv4_dst: ip_dst = convert_ipv4_str_to_ip_proto(qos_enforce_rule.ipv4_dst) ip_src = convert_ipv4_str_to_ip_proto(qos_enforce_rule.ipv4_dst) if qos_enforce_rule.direction == FlowMatch.UPLINK: flow_list = [ FlowDescription(match=FlowMatch( ip_dst=ip_dst, direction=qos_enforce_rule.direction), action=allow) ] else: flow_list = [ FlowDescription(match=FlowMatch( ip_src=ip_src, direction=qos_enforce_rule.direction), action=allow) ] qos_enforce_rule = ActivateFlowsRequest( sid=SIDUtils.to_pb(qos_enforce_rule.imsi), ip_addr=ue_ip_addr, dynamic_rules=[ PolicyRule(id=qos_enforce_rule.rule_id, priority=qos_enforce_rule.priority, hard_timeout=qos_enforce_rule.hard_timeout, flow_list=flow_list) ], request_origin=RequestOriginType(type=RequestOriginType.N4)) return qos_enforce_rule
def activate_gy_redirect(client, args): request = ActivateFlowsRequest( sid=SIDUtils.to_pb(args.imsi), ip_addr=args.ipv4, policies=[ VersionedPolicy( rule=PolicyRule( id=args.rule_id, priority=999, flow_list=[], redirect=RedirectInformation( support=1, address_type=2, server_address=args.redirect_addr, ), ), version=1, ), ], request_origin=RequestOriginType(type=RequestOriginType.GY), shard_id=args.shard_id, ) response = client.ActivateFlows(request) _print_rule_mod_results(response.policy_results)
def test_enforcement_restart(self): """ Adds rules using the setup feature 1) Empty SetupFlowsRequest - assert default flows 2) Add 2 imsis, add 2 policies(sub1_rule_temp, sub2_rule_keep), - assert everything is properly added 3) Same imsis 1 new policy, 1 old (sub2_new_rule, sub2_rule_keep) - assert everything is properly added 4) Empty SetupFlowsRequest - assert default flows """ fake_controller_setup( enf_controller=self.enforcement_controller, enf_stats_controller=self.enforcement_stats_controller, startup_flow_controller=self.startup_flows_contoller) snapshot_verifier = SnapshotVerifier(self, self.BRIDGE, self.service_manager, 'default_flows') with snapshot_verifier: pass imsi1 = 'IMSI010000000088888' imsi2 = 'IMSI010000000012345' sub2_ip = '192.168.128.74' flow_list1 = [ FlowDescription(match=FlowMatch(ipv4_dst='45.10.0.0/24', direction=FlowMatch.UPLINK), action=FlowDescription.PERMIT), FlowDescription(match=FlowMatch(ipv4_dst='45.11.0.0/24', direction=FlowMatch.UPLINK), action=FlowDescription.PERMIT) ] flow_list2 = [ FlowDescription(match=FlowMatch(ipv4_dst='10.10.1.0/24', direction=FlowMatch.UPLINK), action=FlowDescription.PERMIT) ] policies1 = [ PolicyRule(id='sub1_rule_temp', priority=2, flow_list=flow_list1), ] policies2 = [ PolicyRule(id='sub2_rule_keep', priority=3, flow_list=flow_list2) ] enf_stat_name = [imsi1 + '|sub1_rule_temp', imsi2 + '|sub2_rule_keep'] self.service_manager.session_rule_version_mapper.update_version( imsi1, 'sub1_rule_temp') self.service_manager.session_rule_version_mapper.update_version( imsi2, 'sub2_rule_keep') setup_flows_request = SetupFlowsRequest(requests=[ ActivateFlowsRequest(sid=SIDUtils.to_pb(imsi1), dynamic_rules=policies1), ActivateFlowsRequest(sid=SIDUtils.to_pb(imsi2), dynamic_rules=policies2), ], epoch=global_epoch) fake_controller_setup( enf_controller=self.enforcement_controller, enf_stats_controller=self.enforcement_stats_controller, startup_flow_controller=self.startup_flows_contoller, setup_flows_request=setup_flows_request) sub_context = RyuDirectSubscriberContext(imsi2, sub2_ip, self.enforcement_controller, self._enforcement_tbl_num) isolator = RyuDirectTableIsolator( RyuForwardFlowArgsBuilder.from_subscriber( sub_context.cfg).build_requests(), self.testing_controller) pkt_sender = ScapyPacketInjector(self.IFACE) packets = IPPacketBuilder()\ .set_ip_layer('10.10.1.8/20', sub2_ip)\ .set_ether_layer(self.MAC_DEST, "00:00:00:00:00:00")\ .build() pkts_sent = 4096 pkts_matched = 256 flow_query = FlowQuery(self._enforcement_tbl_num, self.testing_controller, match=flow_match_to_magma_match( flow_list2[0].match)) flow_verifier = FlowVerifier([ FlowTest( FlowQuery(self._enforcement_tbl_num, self.testing_controller), pkts_sent), FlowTest(flow_query, pkts_matched) ], self._wait_func(enf_stat_name)) snapshot_verifier = SnapshotVerifier(self, self.BRIDGE, self.service_manager, 'before_restart') with isolator, flow_verifier, snapshot_verifier: pkt_sender.send(packets) flow_verifier.verify() flow_list1 = [ FlowDescription(match=FlowMatch(ipv4_dst='24.10.0.0/24', direction=FlowMatch.UPLINK), action=FlowDescription.PERMIT) ] policies = [ PolicyRule(id='sub2_new_rule', priority=2, flow_list=flow_list1), PolicyRule(id='sub2_rule_keep', priority=3, flow_list=flow_list2) ] self.service_manager.session_rule_version_mapper.update_version( imsi2, 'sub2_new_rule') enf_stat_name = [imsi2 + '|sub2_new_rule', imsi2 + '|sub2_rule_keep'] setup_flows_request = SetupFlowsRequest(requests=[ ActivateFlowsRequest(sid=SIDUtils.to_pb(imsi2), dynamic_rules=policies) ], epoch=global_epoch) fake_controller_setup( enf_controller=self.enforcement_controller, enf_stats_controller=self.enforcement_stats_controller, startup_flow_controller=self.startup_flows_contoller, setup_flows_request=setup_flows_request) flow_verifier = FlowVerifier([FlowTest(flow_query, pkts_matched)], self._wait_func(enf_stat_name)) snapshot_verifier = SnapshotVerifier(self, self.BRIDGE, self.service_manager, 'after_restart') with flow_verifier, snapshot_verifier: pass fake_controller_setup( enf_controller=self.enforcement_controller, enf_stats_controller=self.enforcement_stats_controller, startup_flow_controller=self.startup_flows_contoller) snapshot_verifier = SnapshotVerifier(self, self.BRIDGE, self.service_manager, 'default_flows') with snapshot_verifier: pass
def activate_flows(client, args): request = ActivateFlowsRequest( sid=SIDUtils.to_pb(args.imsi), rule_ids=args.rule_ids.split(',')) client.ActivateFlows(request)
def stress_test_grpc(client, args): print("WARNING: DO NOT USE ON PRODUCTION SETUPS") delta_time = 1 / args.attaches_per_sec print("Attach every ~{0} seconds".format(delta_time)) if args.disable_qos: print("QOS Disabled") apn_ambr = None else: print("QOS Enabled") apn_ambr = AggregatedMaximumBitrate( max_bandwidth_ul=1000000000, max_bandwidth_dl=1000000000, ) for i in range(0, args.test_iterations): print("Starting iteration {0} of attach/detach requests".format(i)) ue_dict = _gen_ue_set(args.num_of_ues) print("Starting attaches") timestamp = datetime.now() completed_reqs = 0 for ue in ue_dict: grpc_start_timestamp = datetime.now() request = ActivateFlowsRequest( sid=SIDUtils.to_pb(ue.imsi_str), ip_addr=ue.ipv4_src, policies=[ VersionedPolicy( rule=PolicyRule( id=ue.rule_id, priority=10, flow_list=[ FlowDescription( match=FlowMatch( ip_dst=convert_ipv4_str_to_ip_proto(ue.ipv4_src), direction=FlowMatch.UPLINK, ), ), FlowDescription( match=FlowMatch( ip_src=convert_ipv4_str_to_ip_proto(ue.ipv4_dst), direction=FlowMatch.DOWNLINK, ), ), ], ), version=1, ), ], request_origin=RequestOriginType(type=RequestOriginType.GX), apn_ambr=apn_ambr, ) response = client.ActivateFlows(request) if any( r.result != RuleModResult.SUCCESS for r in response.policy_results ): _print_rule_mod_results(response.policy_results) grpc_end_timestamp = datetime.now() call_duration = (grpc_end_timestamp - grpc_start_timestamp).total_seconds() if call_duration < delta_time: time.sleep(delta_time - call_duration) if completed_reqs % LOG_INCREMENT == 0: print("Finished {0}".format(completed_reqs)) completed_reqs += 1 duration = (datetime.now() - timestamp).total_seconds() print( "Finished {0} attaches in {1} seconds".format( len(ue_dict), duration, ), ) print("Actual attach rate = {0} UEs per sec".format(round(len(ue_dict) / duration))) time.sleep(args.time_between_detach) print("Starting detaches") timestamp = datetime.now() completed_reqs = 0 for ue in ue_dict: grpc_start_timestamp = datetime.now() request = DeactivateFlowsRequest( sid=SIDUtils.to_pb(ue.imsi_str), ip_addr=ue.ipv4_src, policies=[ VersionedPolicyID( rule_id=ue.rule_id, version=1, ), ], request_origin=RequestOriginType(type=RequestOriginType.GX), remove_default_drop_flows=True, ) response = client.DeactivateFlows(request) if response.result != DeactivateFlowsResult.SUCCESS: _print_rule_mod_results(response.policy_results) grpc_end_timestamp = datetime.now() call_duration = (grpc_end_timestamp - grpc_start_timestamp).total_seconds() if call_duration < delta_time: time.sleep(delta_time - call_duration) if completed_reqs % LOG_INCREMENT == 0: print("Finished {0}".format(completed_reqs)) completed_reqs += 1 duration = (datetime.now() - timestamp).total_seconds() print( "Finished {0} detaches in {1} seconds".format( len(ue_dict), duration, ), ) print( "Actual detach rate = {0} UEs per sec".format( round(len(ue_dict) / duration), ), )
def stress_test_grpc(client, args): print("WARNING: DO NOT USE ON PRODUCTION SETUPS") UEInfo = namedtuple('UEInfo', ['imsi_str', 'ipv4_src', 'ipv4_dst', 'rule_id']) delta_time = 1/args.attaches_per_sec print("Attach every ~{0} seconds".format(delta_time)) if args.disable_qos: print("QOS Disabled") apn_ambr = None else: print("QOS Enabled") apn_ambr = AggregatedMaximumBitrate( max_bandwidth_ul=1000000000, max_bandwidth_dl=1000000000, ) def _gen_ue_set(num_of_ues): imsi = 123000000 ue_set = set() for _ in range(0, num_of_ues): imsi_str = "IMSI" + str(imsi) ipv4_src = ".".join(str(random.randint(0, 255)) for _ in range(4)) ipv4_dst = ".".join(str(random.randint(0, 255)) for _ in range(4)) rule_id = "allow." + imsi_str ue_set.add(UEInfo(imsi_str, ipv4_src, ipv4_dst, rule_id)) imsi = imsi + 1 return ue_set for i in range (0, args.test_iterations): print("Starting iteration {0} of attach/detach requests".format(i)) ue_dict = _gen_ue_set(args.num_of_ues) print("Starting attaches") timestamp = datetime.now() for ue in ue_dict: grpc_start_timestamp = datetime.now() request = ActivateFlowsRequest( sid=SIDUtils.to_pb(ue.imsi_str), ip_addr=ue.ipv4_src, dynamic_rules=[PolicyRule( id=ue.rule_id, priority=10, flow_list=[ FlowDescription(match=FlowMatch( ip_dst=convert_ipv4_str_to_ip_proto(ue.ipv4_src), direction=FlowMatch.UPLINK)), FlowDescription(match=FlowMatch( ip_src=convert_ipv4_str_to_ip_proto(ue.ipv4_dst), direction=FlowMatch.DOWNLINK)), ], )], request_origin=RequestOriginType(type=RequestOriginType.GX), apn_ambr=apn_ambr, ) response = client.ActivateFlows(request) if any(r.result != RuleModResult.SUCCESS for r in response.dynamic_rule_results): _print_rule_mod_results(response.dynamic_rule_results) grpc_end_timestamp = datetime.now() call_duration = (grpc_end_timestamp - grpc_start_timestamp).total_seconds() if call_duration < delta_time: time.sleep(delta_time - call_duration) duration = (datetime.now() - timestamp).total_seconds() print("Finished {0} attaches in {1} seconds".format(len(ue_dict), duration)) print("Actual attach rate = {0} UEs per sec".format(round(len(ue_dict)/duration))) time.sleep(args.time_between_detach) print("Starting detaches") timestamp = datetime.now() for ue in ue_dict: grpc_start_timestamp = datetime.now() request = DeactivateFlowsRequest( sid=SIDUtils.to_pb(ue.imsi_str), ip_addr=ue.ipv4_src, rule_ids=[ue.rule_id], request_origin=RequestOriginType(type=RequestOriginType.GX), remove_default_drop_flows=True) response = client.DeactivateFlows(request) if response.result != DeactivateFlowsResult.SUCCESS: _print_rule_mod_results(response.dynamic_rule_results) grpc_end_timestamp = datetime.now() call_duration = (grpc_end_timestamp - grpc_start_timestamp).total_seconds() if call_duration < delta_time: time.sleep(delta_time - call_duration) duration = (datetime.now() - timestamp).total_seconds() print("Finished {0} detaches in {1} seconds".format(len(ue_dict), duration)) print("Actual detach rate = {0} UEs per sec", round(len(ue_dict)/duration))
def test_url_redirect(self): """ Partial redirection test, checks if flows were added properly for url based redirection. Assert: 1 Packet is matched Packet bypass flows are added Flow learn action is triggered - another flow is added to the table """ fake_controller_setup( enf_controller=self.enforcement_controller, enf_stats_controller=self.enforcement_stats_controller, startup_flow_controller=self.startup_flows_contoller, ) redirect_ips = ["185.128.101.5", "185.128.121.4"] self.enforcement_controller._redirect_manager._dns_cache.get( "about.sha.ddih.org", lambda: redirect_ips, max_age=42, ) imsi = 'IMSI010000000088888' sub_ip = '192.168.128.74' flow_list = [FlowDescription(match=FlowMatch())] policy = PolicyRule( id='redir_test', priority=3, flow_list=flow_list, redirect=RedirectInformation( support=1, address_type=2, server_address="http://about.sha.ddih.org/", ), ) # ============================ Subscriber ============================ sub_context = RyuDirectSubscriberContext( imsi, sub_ip, self.enforcement_controller, self._tbl_num, ) setup_flows_request = SetupFlowsRequest( requests=[ ActivateFlowsRequest( sid=SIDUtils.to_pb(imsi), ip_addr=sub_ip, policies=[VersionedPolicy(rule=policy, version=1)], ), ], epoch=global_epoch, ) fake_controller_setup( enf_controller=self.enforcement_controller, enf_stats_controller=self.enforcement_stats_controller, startup_flow_controller=self.startup_flows_contoller, setup_flows_request=setup_flows_request, ) isolator = RyuDirectTableIsolator( RyuForwardFlowArgsBuilder.from_subscriber( sub_context.cfg).build_requests(), self.testing_controller, ) pkt_sender = ScapyPacketInjector(self.IFACE) packet = TCPPacketBuilder()\ .set_tcp_layer(42132, 80, 321)\ .set_tcp_flags("S")\ .set_ip_layer('151.42.41.122', sub_ip)\ .set_ether_layer(self.MAC_DEST, "00:00:00:00:00:00")\ .build() snapshot_verifier = SnapshotVerifier( self, self.BRIDGE, self.service_manager, ) with isolator, sub_context, snapshot_verifier: pkt_sender.send(packet)
def test_enforcement_restart(self): """ Adds rules using the setup feature 1) Empty SetupFlowsRequest - assert default flows 2) Add 2 imsis, add 2 policies(sub1_rule_temp, sub2_rule_keep), - assert everything is properly added 3) Same imsis 1 new policy, 1 old (sub2_new_rule, sub2_rule_keep) - assert everything is properly added 4) Empty SetupFlowsRequest - assert default flows """ self.enforcement_controller._rule_mapper = RuleIDToNumMapper() self.enforcement_stats_controller._rule_mapper = RuleIDToNumMapper() fake_controller_setup( enf_controller=self.enforcement_controller, enf_stats_controller=self.enforcement_stats_controller, startup_flow_controller=self.startup_flows_contoller, ) snapshot_verifier = SnapshotVerifier( self, self.BRIDGE, self.service_manager, 'default_flows', ) with snapshot_verifier: pass imsi1 = 'IMSI010000000088888' imsi2 = 'IMSI010000000012345' sub2_ip = '192.168.128.74' flow_list1 = [ FlowDescription( match=FlowMatch( ip_dst=convert_ipv4_str_to_ip_proto('45.10.0.0/24'), direction=FlowMatch.UPLINK, ), action=FlowDescription.PERMIT, ), FlowDescription( match=FlowMatch( ip_dst=convert_ipv4_str_to_ip_proto('45.11.0.0/24'), direction=FlowMatch.UPLINK, ), action=FlowDescription.PERMIT, ), ] flow_list2 = [ FlowDescription( match=FlowMatch( ip_dst=convert_ipv4_str_to_ip_proto('10.10.1.0/24'), direction=FlowMatch.UPLINK, ), action=FlowDescription.PERMIT, ), ] policies1 = [ VersionedPolicy( rule=PolicyRule(id='sub1_rule_temp', priority=2, flow_list=flow_list1), version=1, ), ] policies2 = [ VersionedPolicy( rule=PolicyRule(id='sub2_rule_keep', priority=3, flow_list=flow_list2), version=1, ), ] enf_stat_name = [ imsi1 + '|sub1_rule_temp' + '|' + sub2_ip, imsi2 + '|sub2_rule_keep' + '|' + sub2_ip, ] self.service_manager.session_rule_version_mapper.save_version( imsi1, convert_ipv4_str_to_ip_proto(sub2_ip), 'sub1_rule_temp', 1, ) self.service_manager.session_rule_version_mapper.save_version( imsi2, convert_ipv4_str_to_ip_proto(sub2_ip), 'sub2_rule_keep', 1, ) setup_flows_request = SetupFlowsRequest( requests=[ ActivateFlowsRequest( sid=SIDUtils.to_pb(imsi1), ip_addr=sub2_ip, policies=policies1, ), ActivateFlowsRequest( sid=SIDUtils.to_pb(imsi2), ip_addr=sub2_ip, policies=policies2, ), ], epoch=global_epoch, ) # Simulate clearing the dict self.service_manager.session_rule_version_mapper\ ._version_by_imsi_and_rule = {} fake_controller_setup( enf_controller=self.enforcement_controller, enf_stats_controller=self.enforcement_stats_controller, startup_flow_controller=self.startup_flows_contoller, setup_flows_request=setup_flows_request, ) sub_context = RyuDirectSubscriberContext( imsi2, sub2_ip, self.enforcement_controller, self._enforcement_tbl_num, ) isolator = RyuDirectTableIsolator( RyuForwardFlowArgsBuilder.from_subscriber( sub_context.cfg).build_requests(), self.testing_controller, ) pkt_sender = ScapyPacketInjector(self.IFACE) packets = IPPacketBuilder()\ .set_ip_layer('10.10.1.8/20', sub2_ip)\ .set_ether_layer(self.MAC_DEST, "00:00:00:00:00:00")\ .build() snapshot_verifier = SnapshotVerifier( self, self.BRIDGE, self.service_manager, 'before_restart', ) with isolator, snapshot_verifier: pkt_sender.send(packets) flow_list1 = [ FlowDescription( match=FlowMatch( ip_dst=convert_ipv4_str_to_ip_proto('24.10.0.0/24'), direction=FlowMatch.UPLINK, ), action=FlowDescription.PERMIT, ), ] policies = [ VersionedPolicy( rule=PolicyRule(id='sub2_new_rule', priority=2, flow_list=flow_list1), version=1, ), VersionedPolicy( rule=PolicyRule(id='sub2_rule_keep', priority=3, flow_list=flow_list2), version=1, ), ] enf_stat_name = [ imsi2 + '|sub2_new_rule' + '|' + sub2_ip + "|" + "1", imsi2 + '|sub2_rule_keep' + '|' + sub2_ip + "|" + "1", ] setup_flows_request = SetupFlowsRequest( requests=[ ActivateFlowsRequest( sid=SIDUtils.to_pb(imsi2), ip_addr=sub2_ip, policies=policies, ), ], epoch=global_epoch, ) fake_controller_setup( enf_controller=self.enforcement_controller, enf_stats_controller=self.enforcement_stats_controller, startup_flow_controller=self.startup_flows_contoller, setup_flows_request=setup_flows_request, ) snapshot_verifier = SnapshotVerifier( self, self.BRIDGE, self.service_manager, 'after_restart', ) with snapshot_verifier: pass fake_controller_setup( enf_controller=self.enforcement_controller, enf_stats_controller=self.enforcement_stats_controller, startup_flow_controller=self.startup_flows_contoller, ) snapshot_verifier = SnapshotVerifier( self, self.BRIDGE, self.service_manager, 'default_flows_w_packets', ) with snapshot_verifier: pass
def test_enforcement_stats_restart(self): """ Adds 2 policies to subscriber, verifies that EnforcementStatsController reports correct stats to sessiond Assert: UPLINK policy matches 128 packets (*34 = 4352 bytes) DOWNLINK policy matches 256 packets (*34 = 8704 bytes) No other stats are reported The controller is then restarted with the same SetupFlowsRequest, - assert flows keep their packet counts """ fake_controller_setup( enf_controller=self.enforcement_controller, enf_stats_controller=self.enforcement_stats_controller, startup_flow_controller=self.startup_flows_contoller) snapshot_verifier = SnapshotVerifier(self, self.BRIDGE, self.service_manager, 'default_flows') with snapshot_verifier: pass imsi = 'IMSI001010000000013' sub_ip = '192.168.128.74' num_pkts_tx_match = 128 num_pkts_rx_match = 256 """ Create 2 policy rules for the subscriber """ flow_list1 = [ FlowDescription(match=FlowMatch(ipv4_dst='45.10.0.0/25', direction=FlowMatch.UPLINK), action=FlowDescription.PERMIT) ] flow_list2 = [ FlowDescription(match=FlowMatch(ipv4_src='45.10.0.0/24', direction=FlowMatch.DOWNLINK), action=FlowDescription.PERMIT) ] policies = [ PolicyRule(id='tx_match', priority=3, flow_list=flow_list1), PolicyRule(id='rx_match', priority=5, flow_list=flow_list2) ] enf_stat_name = [imsi + '|tx_match', imsi + '|rx_match'] self.service_manager.session_rule_version_mapper.update_version( imsi, 'tx_match') self.service_manager.session_rule_version_mapper.update_version( imsi, 'rx_match') """ Setup subscriber, setup table_isolation to fwd pkts """ self._static_rule_dict[policies[0].id] = policies[0] self._static_rule_dict[policies[1].id] = policies[1] sub_context = RyuDirectSubscriberContext( imsi, sub_ip, self.enforcement_controller, self._enforcement_tbl_num, self.enforcement_stats_controller, nuke_flows_on_exit=False).add_static_rule( policies[0].id).add_static_rule(policies[1].id) isolator = RyuDirectTableIsolator( RyuForwardFlowArgsBuilder.from_subscriber( sub_context.cfg).build_requests(), self.testing_controller) """ Create 2 sets of packets, for policry rule1&2 """ pkt_sender = ScapyPacketInjector(self.IFACE) packet1 = IPPacketBuilder()\ .set_ip_layer('45.10.0.0/20', sub_ip)\ .set_ether_layer(self.MAC_DEST, "00:00:00:00:00:00")\ .build() packet2 = IPPacketBuilder()\ .set_ip_layer(sub_ip, '45.10.0.0/20')\ .set_ether_layer(self.MAC_DEST, "00:00:00:00:00:00")\ .build() # =========================== Verification =========================== flow_verifier = FlowVerifier([], self._wait_func(enf_stat_name)) snapshot_verifier = SnapshotVerifier(self, self.BRIDGE, self.service_manager, 'initial_flows') """ Send packets, wait until pkts are received by ovs and enf stats """ with isolator, sub_context, flow_verifier, snapshot_verifier: pkt_sender.send(packet1) pkt_sender.send(packet2) stats = get_enforcement_stats( self.enforcement_stats_controller._report_usage.call_args_list) self.assertEqual(stats[enf_stat_name[0]].sid, imsi) self.assertEqual(stats[enf_stat_name[0]].rule_id, "tx_match") self.assertEqual(stats[enf_stat_name[0]].bytes_rx, 0) self.assertEqual(stats[enf_stat_name[0]].bytes_tx, num_pkts_tx_match * len(packet1)) self.assertEqual(stats[enf_stat_name[1]].sid, imsi) self.assertEqual(stats[enf_stat_name[1]].rule_id, "rx_match") self.assertEqual(stats[enf_stat_name[1]].bytes_tx, 0) # downlink packets will discount ethernet header by default # so, only count the IP portion total_bytes_pkt2 = num_pkts_rx_match * len(packet2[IP]) self.assertEqual(stats[enf_stat_name[1]].bytes_rx, total_bytes_pkt2) # NOTE this value is 5 because the EnforcementStatsController rule # reporting doesn't reset on clearing flows(lingers from old tests) self.assertEqual(len(stats), 5) setup_flows_request = SetupFlowsRequest(requests=[ ActivateFlowsRequest(sid=SIDUtils.to_pb(imsi), rule_ids=[policies[0].id, policies[1].id]), ], epoch=global_epoch) fake_controller_setup( enf_controller=self.enforcement_controller, enf_stats_controller=self.enforcement_stats_controller, startup_flow_controller=self.startup_flows_contoller, setup_flows_request=setup_flows_request) snapshot_verifier = SnapshotVerifier(self, self.BRIDGE, self.service_manager, 'after_restart') with flow_verifier, snapshot_verifier: pass self.assertEqual(stats[enf_stat_name[0]].bytes_tx, num_pkts_tx_match * len(packet1))
def test_url_redirect(self): """ Partial redirection test, checks if flows were added properly for url based redirection. Assert: 1 Packet is matched Packet bypass flows are added Flow learn action is triggered - another flow is added to the table """ fake_controller_setup( enf_controller=self.enforcement_controller, enf_stats_controller=self.enforcement_stats_controller, startup_flow_controller=self.startup_flows_contoller) redirect_ips = ["185.128.101.5", "185.128.121.4"] self.enforcement_controller._redirect_manager._dns_cache.get( "about.sha.ddih.org", lambda: redirect_ips, max_age=42) imsi = 'IMSI010000000088888' sub_ip = '192.168.128.74' flow_list = [FlowDescription(match=FlowMatch())] policy = PolicyRule(id='redir_test', priority=3, flow_list=flow_list, redirect=RedirectInformation( support=1, address_type=2, server_address="http://about.sha.ddih.org/")) # ============================ Subscriber ============================ sub_context = RyuDirectSubscriberContext(imsi, sub_ip, self.enforcement_controller, self._tbl_num) setup_flows_request = SetupFlowsRequest(requests=[ ActivateFlowsRequest(sid=SIDUtils.to_pb(imsi), ip_addr=sub_ip, dynamic_rules=[policy]), ], epoch=global_epoch) fake_controller_setup( enf_controller=self.enforcement_controller, enf_stats_controller=self.enforcement_stats_controller, startup_flow_controller=self.startup_flows_contoller, setup_flows_request=setup_flows_request) isolator = RyuDirectTableIsolator( RyuForwardFlowArgsBuilder.from_subscriber( sub_context.cfg).build_requests(), self.testing_controller) pkt_sender = ScapyPacketInjector(self.IFACE) packet = TCPPacketBuilder()\ .set_tcp_layer(42132, 80, 321)\ .set_tcp_flags("S")\ .set_ip_layer('151.42.41.122', sub_ip)\ .set_ether_layer(self.MAC_DEST, "00:00:00:00:00:00")\ .build() # Check if these flows were added (queries should return flows) permit_outbound, permit_inbound = [], [] for ip in redirect_ips: permit_outbound.append( FlowQuery(self._tbl_num, self.testing_controller, match=flow_match_to_magma_match( FlowMatch(ipv4_dst=ip, direction=FlowMatch.UPLINK)))) permit_inbound.append( FlowQuery(self._tbl_num, self.testing_controller, match=flow_match_to_magma_match( FlowMatch(ipv4_src=ip, direction=FlowMatch.DOWNLINK)))) learn_action_flow = flow_match_to_magma_match( FlowMatch(ip_proto=6, direction=FlowMatch.DOWNLINK, ipv4_src=self.BRIDGE_IP_ADDRESS, ipv4_dst=sub_ip)) learn_action_query = FlowQuery(self._tbl_num, self.testing_controller, learn_action_flow) # =========================== Verification =========================== # 1 packet sent, permit rules installed, learn action installed. Since # the enforcement table is entered via the DPI table and the scratch # enforcement table, the number of packets handled by the table is 2. flow_verifier = FlowVerifier( [ FlowTest(FlowQuery(self._tbl_num, self.testing_controller), 2), FlowTest(learn_action_query, 0, flow_count=1) ] + [FlowTest(query, 0, flow_count=1) for query in permit_outbound] + [FlowTest(query, 0, flow_count=1) for query in permit_inbound], lambda: wait_after_send(self.testing_controller)) snapshot_verifier = SnapshotVerifier(self, self.BRIDGE, self.service_manager) with isolator, sub_context, flow_verifier, snapshot_verifier: pkt_sender.send(packet) flow_verifier.verify()
def test_enforcement_ipv6_restart(self): """ Adds rules using the setup feature 1) Empty SetupFlowsRequest - assert default flows 2) Add imsi with ipv6 policy - assert everything is properly added """ fake_controller_setup( enf_controller=self.enforcement_controller, enf_stats_controller=self.enforcement_stats_controller, startup_flow_controller=self.startup_flows_contoller, ) snapshot_verifier = SnapshotVerifier( self, self.BRIDGE, self.service_manager, 'default_flows', ) with snapshot_verifier: pass imsi = 'IMSI010000002388888' sub_ip = b'fe80:24c3:d0ff:fef3:9d21:4407:d337:1928' flow_list = [ FlowDescription( match=FlowMatch( ip_dst=convert_ipv6_bytes_to_ip_proto(b'fe80::'), direction=FlowMatch.UPLINK, ), action=FlowDescription.PERMIT, ), ] policies = [ VersionedPolicy( rule=PolicyRule(id='ipv6_rule', priority=2, flow_list=flow_list), version=1, ), ] enf_stat_name = [imsi + '|ipv6_rule' + '|' + str(sub_ip) + "|" + "1"] setup_flows_request = SetupFlowsRequest( requests=[ ActivateFlowsRequest( sid=SIDUtils.to_pb(imsi), ipv6_addr=sub_ip, policies=policies, ), ], epoch=global_epoch, ) fake_controller_setup( enf_controller=self.enforcement_controller, enf_stats_controller=self.enforcement_stats_controller, startup_flow_controller=self.startup_flows_contoller, setup_flows_request=setup_flows_request, ) snapshot_verifier = SnapshotVerifier( self, self.BRIDGE, self.service_manager, 'after_restart', ) with snapshot_verifier: pass fake_controller_setup( enf_controller=self.enforcement_controller, enf_stats_controller=self.enforcement_stats_controller, startup_flow_controller=self.startup_flows_contoller, ) snapshot_verifier = SnapshotVerifier( self, self.BRIDGE, self.service_manager, 'default_flows', ) with snapshot_verifier: pass