diff --git a/common/vrouter/base.py b/common/vrouter/base.py index 857842ed4..b5388d2cb 100644 --- a/common/vrouter/base.py +++ b/common/vrouter/base.py @@ -11,6 +11,8 @@ import random from security_group import get_secgrp_id_from_name, SecurityGroupFixture from tcutils.agent.vrouter_lib import * +from policy_test import PolicyFixture +from vn_policy_test import VN_Policy_Fixture class BaseVrouterTest(BaseNeutronTest): @@ -45,6 +47,77 @@ def tearDownClass(cls): super(BaseVrouterTest, cls).tearDownClass() # end tearDownClass + def _create_resources(self, test_type='intra-node', no_of_client=1, + no_of_server=1): + ''' + test_type: can be intra-node or inter-node + ''' + compute_hosts = self.orch.get_hosts() + if (len(compute_hosts) < 2) and (test_type == 'inter-node'): + raise self.skipTest("Skipping test case,\ + this test needs atleast 2 compute nodes") + + node_name1 = compute_hosts[0] + node_ip1 = self.inputs.compute_info[node_name1] + node_name2 = compute_hosts[0] + node_ip2 = self.inputs.compute_info[node_name2] + + if test_type == 'inter-node': + node_name2 = compute_hosts[1] + node_ip2 = self.inputs.compute_info[node_name2] + + self.vn_fixtures = self.create_vns(count=2) + self.verify_vns(self.vn_fixtures) + self.vn1_fixture = self.vn_fixtures[0] + self.vn2_fixture = self.vn_fixtures[1] + self.client_fixtures = self.create_vms(vn_fixture=self.vn1_fixture, + count=no_of_client, node_name=node_name1, image_name='ubuntu-traffic') + self.server_fixtures = self.create_vms(vn_fixture=self.vn2_fixture, + count=no_of_server, node_name=node_name2, image_name='ubuntu-traffic') + self.client_fixture = self.client_fixtures[0] + self.server_fixture = self.server_fixtures[0] + + policy_name = 'policy1' + policy_rules = [ + { + 'direction': '<>', 'simple_action': 'pass', + 'protocol': 'any', + 'source_network': self.vn1_fixture.vn_name, + 'dest_network': self.vn2_fixture.vn_name, + } + ] + self.policy_fixture = self.useFixture( + PolicyFixture( + policy_name=policy_name, + rules_list=policy_rules, + inputs=self.inputs, + connections=self.connections, + api=True)) + + self.vn1_policy_fixture = self.useFixture( + VN_Policy_Fixture( + connections=self.connections, + vn_name=self.vn1_fixture.vn_name, + policy_obj={self.vn1_fixture.vn_name : \ + [self.policy_fixture.policy_obj]}, + vn_obj={self.vn1_fixture.vn_name : self.vn1_fixture}, + vn_policys=[policy_name], + project_name=self.project.project_name)) + + self.vn2_policy_fixture = self.useFixture( + VN_Policy_Fixture( + connections=self.connections, + vn_name=self.vn2_fixture.vn_name, + policy_obj={self.vn2_fixture.vn_name : \ + [self.policy_fixture.policy_obj]}, + vn_obj={self.vn2_fixture.vn_name : self.vn2_fixture}, + vn_policys=[policy_name], + project_name=self.project.project_name)) + + self.verify_vms(self.client_fixtures + self.server_fixtures) + + #end _create_resources + @retry(delay=2, tries=15) def get_vna_route_with_retry(self, agent_inspect, vrf_id, ip, prefix): ''' @@ -147,7 +220,8 @@ def disable_policy_for_vms(self, vm_fixtures, disable=True): def add_fat_flow_to_vmis(self, vmi_ids, fat_flow_config): '''vmi_ids: list of vmi ids - fat_flow_config: dictionary of format {'proto':,'port':} + fat_flow_config: dictionary of format {'proto':,'port':, + 'ignore_address': } ''' for vmi_id in vmi_ids: self.vnc_h.add_fat_flow_to_vmi(vmi_id, fat_flow_config) @@ -163,6 +237,34 @@ def remove_fat_flow_on_vmis(self, vmi_ids, fat_flow_config): return True + def add_fat_flow_to_vns(self, vn_fixtures, fat_flow_config): + '''vn_fixtures: list of vn fixtures + fat_flow_config: dictionary of format {'proto':,'port':, + 'ignore_address': } + ''' + ignore_address = fat_flow_config.get('ignore_address', None) + if ignore_address: + proto_type = ProtocolType(protocol=fat_flow_config['proto'], + port=fat_flow_config['port'], ignore_address=ignore_address) + else: + proto_type = ProtocolType(protocol=fat_flow_config['proto'], + port=fat_flow_config['port']) + for vn in vn_fixtures: + fat_config = vn.get_fat_flow_protocols() + if fat_config: + fat_config.fat_flow_protocol.append(proto_type) + else: + fat_config = FatFlowProtocols(fat_flow_protocol=[proto_type]) + vn.set_fat_flow_protocols(fat_config) + + return True + + def delete_fat_flow_from_vns(self, vn_fixtures): + '''Removes all Fat flow config from VNs''' + fat_config = FatFlowProtocols() + for vn in vn_fixtures: + vn.set_fat_flow_protocols(fat_config) + def add_proto_based_flow_aging_time(self, proto, port=0, timeout=180): self.vnc_h.add_proto_based_flow_aging_time(proto, port, timeout) self.addCleanup(self.vnc_h.delete_proto_based_flow_aging_time, @@ -588,7 +690,8 @@ def verify_flow_on_compute(self, compute_fixture, source_ip, dest_ip, 'compute, please check logs..') def verify_fat_flow_on_compute(self, compute_fixture, source_ip, dest_ip, - dest_port, proto, vrf_id, fat_flow_count=1): + dest_port, proto, vrf_id, fat_flow_count=1, + sport=0): ''' Verifies Fat flow on specific compute node ''' @@ -596,7 +699,7 @@ def verify_fat_flow_on_compute(self, compute_fixture, source_ip, dest_ip, (ff_count, rf_count) = compute_fixture.get_flow_count( source_ip=source_ip, dest_ip=dest_ip, - source_port=0, + source_port=sport, dest_port=dest_port, proto=proto, vrf_id=vrf_id @@ -605,12 +708,13 @@ def verify_fat_flow_on_compute(self, compute_fixture, source_ip, dest_ip, str_log = 'FAILED' else: str_log = 'PASSED' - self.logger.debug("Fat flow verification %s on node: %s for VMs - " - "Sender: %s, Receiver: %s, " - "Fat flow expected: %s, got:%s" % ( + self.logger.info("Fat flow verification %s on node: %s for - " + "SIP: %s, DIP: %s, sport: %s, dport: %s, " + "vrf-id: %s " + "Fat flow expected: %s, got: %s" % ( str_log, compute_fixture.ip, - source_ip, dest_ip, + source_ip, dest_ip, sport, dest_port, vrf_id, fat_flow_count, ff_count)) assert ff_count == fat_flow_count, ('Fat flow count mismatch on ' @@ -661,8 +765,9 @@ def verify_fat_flow(self, sender_vm_fix_list, dst_vm_fix, return True def verify_fat_flow_with_traffic(self, sender_vm_fix_list, dst_vm_fix, - proto, dest_port, traffic=True, - expected_flow_count=1, fat_flow_count=1, af=None): + proto, dest_port=None, traffic=True, + expected_flow_count=1, fat_flow_count=1, af=None, + fat_flow_config=None, sport_list=None, dport_list=None): ''' Common method to be used for Fat and non-Fat flow verifications: 1. Use 2 different source ports from each sender VM to send traffic @@ -676,65 +781,211 @@ def verify_fat_flow_with_traffic(self, sender_vm_fix_list, dst_vm_fix, ''' af = af or self.inputs.get_af() #Use 2 different source ports for each sender VM - sport_list = [10000, 10001] + sport_list = sport_list or [10000, 10001] + dport_list = dport_list or [dest_port] + fat_flow_dport = dest_port or 0 dst_compute_fix = self.compute_fixtures_dict[dst_vm_fix.vm_node_ip] + if fat_flow_config: + #mask both source and dest port in the flow + if fat_flow_config['port'] == 0: + fat_flow_dport = 0 #Start the traffic from each of the VM in sender_vm_fix_list to dst_vm_fix if traffic: for fix in sender_vm_fix_list: - for port in sport_list: - assert self.send_nc_traffic(fix, dst_vm_fix, port, - dest_port, proto, ip=dst_vm_fix.get_vm_ips(af=af)[0]) + for sport in sport_list: + for dport in dport_list: + assert self.send_nc_traffic(fix, dst_vm_fix, sport, + dport, proto, ip=dst_vm_fix.get_vm_ips(af=af)[0]) - #Verify the flows on sender computes for each sender/receiver VMs and ports + #Verify the non-Fat flows on sender computes for each sender/receiver VMs and ports for fix in sender_vm_fix_list: - for port in sport_list: - compute_fix = self.compute_fixtures_dict[fix.vm_node_ip] - (ff_count, rf_count) = compute_fix.get_flow_count( - source_ip=fix.get_vm_ips(af=af)[0], - dest_ip=dst_vm_fix.get_vm_ips(af=af)[0], - source_port=port, - dest_port=dest_port, - proto=proto, - vrf_id=compute_fix.get_vrf_id( - fix.vn_fq_names[0]) - ) - assert ff_count == expected_flow_count, ('Flows count mismatch on ' - 'sender compute, got:%s, expected:%s' % ( - ff_count, expected_flow_count)) - assert rf_count == expected_flow_count, ('Flows count mismatch on ' - 'sender compute, got:%s, expected:%s' % ( - rf_count, expected_flow_count)) - - #For the case when sender and receiver are on different nodes - if dst_vm_fix.vm_node_ip != fix.vm_node_ip: - #Flow with source and dest port should not be created on dest node, if Fat flow is expected - if fat_flow_count: - expected_count_dst = 0 - else: - expected_count_dst = expected_flow_count - (ff_count, rf_count) = dst_compute_fix.get_flow_count( - source_ip=fix.get_vm_ips(af=af)[0], - dest_ip=dst_vm_fix.get_vm_ips(af=af)[0], - source_port=port, - dest_port=dest_port, - proto=proto, - vrf_id=dst_compute_fix.get_vrf_id( - dst_vm_fix.vn_fq_names[0]) - ) - assert ff_count == expected_count_dst, ('Flows count ' - 'mismatch on dest compute, got:%s, expected:%s' % ( - ff_count, expected_count_dst)) - assert rf_count == expected_count_dst, ('Flows count ' - 'mismatch on dest compute, got:%s, expected:%s' % ( - rf_count, expected_count_dst)) + for sport in sport_list: + for dport in dport_list: + compute_fix = self.compute_fixtures_dict[fix.vm_node_ip] + (ff_count, rf_count) = compute_fix.get_flow_count( + source_ip=fix.get_vm_ips(af=af)[0], + dest_ip=dst_vm_fix.get_vm_ips(af=af)[0], + source_port=sport, + dest_port=dport, + proto=proto, + vrf_id=compute_fix.get_vrf_id( + fix.vn_fq_names[0]) + ) + assert ff_count == expected_flow_count, ('Flows count mismatch on ' + 'sender compute, got:%s, expected:%s' % ( + ff_count, expected_flow_count)) + assert rf_count == expected_flow_count, ('Flows count mismatch on ' + 'sender compute, got:%s, expected:%s' % ( + rf_count, expected_flow_count)) + + #For the case when sender and receiver are on different nodes + if dst_vm_fix.vm_node_ip != fix.vm_node_ip: + #Flow with source and dest port should not be created on dest node, if Fat flow is expected + if fat_flow_count: + expected_count_dst = 0 + else: + expected_count_dst = expected_flow_count + (ff_count, rf_count) = dst_compute_fix.get_flow_count( + source_ip=fix.get_vm_ips(af=af)[0], + dest_ip=dst_vm_fix.get_vm_ips(af=af)[0], + source_port=sport, + dest_port=dport, + proto=proto, + vrf_id=dst_compute_fix.get_vrf_id( + dst_vm_fix.vn_fq_names[0]) + ) + assert ff_count == expected_count_dst, ('Flows count ' + 'mismatch on dest compute, got:%s, expected:%s' % ( + ff_count, expected_count_dst)) + assert rf_count == expected_count_dst, ('Flows count ' + 'mismatch on dest compute, got:%s, expected:%s' % ( + rf_count, expected_count_dst)) #FAT flow verification assert self.verify_fat_flow(sender_vm_fix_list, dst_vm_fix, - proto, dest_port, fat_flow_count, af=af) + proto, fat_flow_dport, fat_flow_count, af=af) self.logger.info("Fat flow verification passed for " - "protocol %s and port %s" % (proto, dest_port)) + "protocol %s and port %s" % (proto, fat_flow_dport)) + return True + + def verify_fat_flow_with_ignore_addrs(self, sender_vm_fix_list, + dst_vm_fix_list, fat_flow_config, traffic=True, + fat_flow_count=1, af=None, icmp_error=False, fat_config_on='server', + sport=10000, dport=53): + ''' + Common method to be used for Fat flow verification with ignore addrs + ''' + af = af or self.inputs.get_af() + #Use 2 different source ports for each sender VM + port1 = dport + port2 = sport + dport_list = [port1, port1+1] + sport_list = [port2, port2+1] + fat_flow_dport = dport_list[0] + fat_flow_sport = 0 + fat_flow_sip = None + fat_flow_dip = None + proto = fat_flow_config['proto'] + ignore_address = fat_flow_config.get('ignore_address') + + if fat_flow_config['port'] == 0: + #mask both source and dest port in the flow + fat_flow_dport = 0 + fat_flow_sport = 0 + else: + if fat_config_on == 'server': + dport_list = [port1] + #mask only source port + fat_flow_sport = 0 + fat_flow_dport = dport_list[0] + elif fat_config_on == 'client': + sport_list = [port2] + #mask only dst port + fat_flow_dport = 0 + fat_flow_sport = sport_list[0] + else: + fat_flow_sport = 0 + fat_flow_dport = 0 + dport_list = [port1] + fat_flow_dport = dport_list[0] + + #mask source IP + if ignore_address == 'source': + if fat_config_on == 'server': + #use 1 client and multiple server VMs + sender_vm_fix_list = [sender_vm_fix_list[0]] + fat_flow_dip = '0.0.0.0' if af == 'v4' else '::' + fat_flow_sip = sender_vm_fix_list[0].get_vm_ips(af=af)[0] + elif fat_config_on == 'client' or fat_config_on == 'all': + #use multiple clients and 1 server VM + dst_vm_fix_list = [dst_vm_fix_list[0]] + fat_flow_sip = '0.0.0.0' if af == 'v4' else '::' + fat_flow_dip = dst_vm_fix_list[0].get_vm_ips(af=af)[0] + #mask dest IP + elif ignore_address == 'destination': + if fat_config_on == 'server': + #use multiple clients and 1 server VM + dst_vm_fix_list = [dst_vm_fix_list[0]] + fat_flow_sip = '0.0.0.0' if af == 'v4' else '::' + fat_flow_dip = dst_vm_fix_list[0].get_vm_ips(af=af)[0] + #Disable rpf + self.vnc_lib_fixture.set_rpf_mode( + dst_vm_fix_list[0].vn_fq_names[0], 'disable') + elif fat_config_on == 'client' or fat_config_on == 'all': + #use 1 client and multiple server VMs + sender_vm_fix_list = [sender_vm_fix_list[0]] + fat_flow_dip = '0.0.0.0' if af == 'v4' else '::' + fat_flow_sip = sender_vm_fix_list[0].get_vm_ips(af=af)[0] + #Disable rpf + self.vnc_lib_fixture.set_rpf_mode( + sender_vm_fix_list[0].vn_fq_names[0], 'disable') + elif ignore_address == None: + if fat_config_on == 'server': + #use multiple clients and 1 server VM + dst_vm_fix_list = [dst_vm_fix_list[0]] + elif fat_config_on == 'client' or fat_config_on == 'all': + #use 1 client and multiple server VMs + sender_vm_fix_list = [sender_vm_fix_list[0]] + + #For intra-node traffic + if dst_vm_fix_list[0].vm_node_ip == sender_vm_fix_list[0].vm_node_ip: + compute_fix = self.compute_fixtures_dict[sender_vm_fix_list[0].vm_node_ip] + vrf_id = None + #For inter-node traffic + else: + if fat_config_on == 'server': + compute_fix = self.compute_fixtures_dict[dst_vm_fix_list[0].vm_node_ip] + vrf_id = compute_fix.get_vrf_id(dst_vm_fix_list[0].vn_fq_names[0]) + elif fat_config_on == 'client': + compute_fix = self.compute_fixtures_dict[sender_vm_fix_list[0].vm_node_ip] + vrf_id = compute_fix.get_vrf_id(sender_vm_fix_list[0].vn_fq_names[0]) + + #Start the traffic + if traffic: + for svm in sender_vm_fix_list: + for dvm in dst_vm_fix_list: + for sport in sport_list: + for dport in dport_list: + assert self.send_nc_traffic(svm, dvm, sport, + dport, proto, ip=dvm.get_vm_ips(af=af)[0], + receiver=(not icmp_error)) + + #FAT flow verification + if ignore_address == 'destination': + self.verify_fat_flow_on_compute(compute_fix, + fat_flow_sip, fat_flow_dip, + fat_flow_dport, proto, + vrf_id, fat_flow_count=fat_flow_count, + sport=fat_flow_sport) + if fat_config_on == 'server': + #Enable back rpf + self.vnc_lib_fixture.set_rpf_mode( + dst_vm_fix_list[0].vn_fq_names[0], 'enable') + elif fat_config_on == 'client' or fat_config_on == 'all': + #Enable back rpf + self.vnc_lib_fixture.set_rpf_mode( + sender_vm_fix_list[0].vn_fq_names[0], 'enable') + elif ignore_address == 'source': + self.verify_fat_flow_on_compute(compute_fix, + fat_flow_sip, fat_flow_dip, + fat_flow_dport, proto, + vrf_id, fat_flow_count=2*fat_flow_count, + sport=fat_flow_sport) + elif ignore_address == None and fat_flow_config['port'] == 0: + for svm in sender_vm_fix_list: + for dvm in dst_vm_fix_list: + self.verify_fat_flow_on_compute(compute_fix, + svm.get_vm_ips(af=af)[0], + dvm.get_vm_ips(af=af)[0], fat_flow_dport, proto, + vrf_id, fat_flow_count=fat_flow_count, + sport=fat_flow_sport) + + #Verify NO hold flows + action = 'HOLD' + self.verify_flow_action(compute_fix, action, + src_vrf=vrf_id, exp=False) return True def get_vrouter_route(self, prefix, vn_fixture=None, vrf_id=None, diff --git a/fixtures/contrailapi.py b/fixtures/contrailapi.py index 6973b82a3..424dee0bb 100644 --- a/fixtures/contrailapi.py +++ b/fixtures/contrailapi.py @@ -591,10 +591,16 @@ def disable_policy_on_vmi(self, vmi_id, disable=True): def add_fat_flow_to_vmi(self, vmi_id, fat_flow_config): '''vmi_id: vmi id where Fat flow config is to be added - fat_flow_config: dictionary of format {'proto':,'port':} + fat_flow_config: dictionary of format {'proto':,'port':, + 'ignore_address': } ''' - proto_type = ProtocolType(protocol=fat_flow_config['proto'], - port=fat_flow_config['port']) + ignore_address = fat_flow_config.get('ignore_address', None) + if ignore_address: + proto_type = ProtocolType(protocol=fat_flow_config['proto'], + port=fat_flow_config['port'], ignore_address=ignore_address) + else: + proto_type = ProtocolType(protocol=fat_flow_config['proto'], + port=fat_flow_config['port']) vmi_obj = self._vnc.virtual_machine_interface_read(id=vmi_id) fat_config = vmi_obj.get_virtual_machine_interface_fat_flow_protocols() @@ -622,7 +628,8 @@ def remove_fat_flow_on_vmi(self, vmi_id, fat_flow_config): if fat_config_get: for config in fat_config_get.fat_flow_protocol: if config.protocol == fat_flow_config['proto'] and \ - config.port == fat_flow_config['port']: + config.port == fat_flow_config['port'] and \ + config.ignore_address == fat_flow_config.get('ignore_address'): fat_config_get.fat_flow_protocol.remove(config) vmi_obj.set_virtual_machine_interface_fat_flow_protocols( fat_config_get) diff --git a/fixtures/vn_test.py b/fixtures/vn_test.py index 5d39b741e..f09ef8cba 100644 --- a/fixtures/vn_test.py +++ b/fixtures/vn_test.py @@ -1925,6 +1925,26 @@ def add_slo(self, slo_obj): vn_obj.add_security_logging_object(slo_obj) vnc_lib.virtual_network_update(vn_obj) + def set_fat_flow_protocols(self, fat_flow_protos): + '''Set the fat flow for VN + fat_flow_protos: obj of FatFlowProtocols + ''' + vnc_lib = self.vnc_lib_h + vn_obj = vnc_lib.virtual_network_read( + fq_name=self.vn_fq_name.split(':')) + vn_obj.set_virtual_network_fat_flow_protocols(fat_flow_protos) + vnc_lib.virtual_network_update(vn_obj) + self.logger.info("Set Fat flow on VN %s: %s" % ( + self.vn_fq_name, fat_flow_protos)) + + def get_fat_flow_protocols(self): + '''Get the fat flow for VN''' + vnc_lib = self.vnc_lib_h + vn_obj = vnc_lib.virtual_network_read( + fq_name=self.vn_fq_name.split(':')) + fat_flow_protos = vn_obj.get_virtual_network_fat_flow_protocols() + return fat_flow_protos + def verify_routing_instance_snat(self): ''' Verify the routing instance fabric SNAT flag is same as its virtual network flag diff --git a/scripts/vrouter/test_fat_flow.py b/scripts/vrouter/test_fat_flow.py index 191e66406..fe662adcc 100644 --- a/scripts/vrouter/test_fat_flow.py +++ b/scripts/vrouter/test_fat_flow.py @@ -258,7 +258,7 @@ def test_fat_flow_with_aap(self): Description: Verify Fat flows with allowed address pair Steps: 1. launch 1 VN and launch 4 VMs in it.2 client VMs and 2 server VMs on different node. - 2. on server VMs, config Fat flow for udp. + 2. on server VMs, config Fat flow for udp with port 0 3. from client VMs,send udp traffic to servers and verify mastership and Fat flow 4. Induce mastership switch and verify the Fat flow again @@ -296,9 +296,10 @@ def test_fat_flow_with_aap(self): proto = 'udp' dport = 53 + fat_port = 0 baseport = random.randint(12000, 65000) sport = [str(baseport), str(baseport+1)] - fat_flow_config = {'proto':proto,'port':dport} + fat_flow_config = {'proto':proto,'port':fat_port} self.add_fat_flow_to_vmis([port1_obj['id'], port2_obj['id']], fat_flow_config) port_list = [port1_obj, port2_obj] @@ -313,7 +314,7 @@ def test_fat_flow_with_aap(self): assert vm1_fixture.add_ip_on_vm(vIP) assert client_fixtures[0].ping_with_certainty(vIP), 'Ping to vIP failure' - assert self.vrrp_mas_chk(vrrp_master, vn1_fixture, vIP) + assert self.vrrp_mas_chk(dst_vm=vrrp_master, vn=vn1_fixture, ip=vIP) for vm in client_fixtures: for port in sport: @@ -324,7 +325,7 @@ def test_fat_flow_with_aap(self): vrf_id_dst = dst_compute_fix.get_vrf_id(vrrp_master.vn_fq_names[0]) for vm in client_fixtures: self.verify_fat_flow_on_compute(dst_compute_fix, vm.vm_ip, - vIP, dport, proto, vrf_id_dst, + vIP, fat_port, proto, vrf_id_dst, fat_flow_count=1) if is_v6(vIP): @@ -336,7 +337,7 @@ def test_fat_flow_with_aap(self): self.logger.info( '%s should become the new VRRP master' % vm2_fixture.vm_name) vrrp_master = vm2_fixture - assert self.vrrp_mas_chk(vrrp_master, vn1_fixture, vIP) + assert self.vrrp_mas_chk(dst_vm=vrrp_master, vn=vn1_fixture, ip=vIP) for vm in client_fixtures: for port in sport: @@ -347,9 +348,104 @@ def test_fat_flow_with_aap(self): vrf_id_dst = dst_compute_fix.get_vrf_id(vrrp_master.vn_fq_names[0]) for vm in client_fixtures: self.verify_fat_flow_on_compute(dst_compute_fix, vm.vm_ip, - vIP, dport, proto, vrf_id_dst, + vIP, fat_port, proto, vrf_id_dst, fat_flow_count=1) + @preposttest_wrapper + def test_fat_flow_with_aap_ignore_addrs(self): + """ + Description: Verify Fat flows with ignore addrs with allowed address pair + Steps: + 1. launch 1 VN and launch 4 VMs in it.2 client VMs and 2 server VMs on different node. + 2. on server VMs, config Fat flow for udp with port 0 + 3. from client VMs,send udp traffic to servers and + verify mastership and Fat flow + 4. Induce mastership switch and verify the Fat flow again + Pass criteria: + 1. Fat flow and mastership verification should pass + """ + compute_hosts = self.orch.get_hosts() + if len(compute_hosts) < 2: + raise self.skipTest("Skipping test case," + "this test needs atleast 2 compute nodes") + + vn1_fixture = self.create_vns(count=1)[0] + vm1_name = get_random_name('vm1') + vm2_name = get_random_name('vm2') + result = False + vIP = self.get_random_ip_from_vn(vn1_fixture)[0] + image = 'ubuntu-traffic' + + port1_obj = self.create_port(net_id=vn1_fixture.vn_id) + port2_obj = self.create_port(net_id=vn1_fixture.vn_id) + vm1_fixture = self.create_vm(vn1_fixture, vm1_name, + image_name=image, + port_ids=[port1_obj['id']], + node_name=compute_hosts[0]) + vm2_fixture = self.create_vm(vn1_fixture, vm2_name, + image_name=image, + port_ids=[port2_obj['id']], + node_name=compute_hosts[0]) + + client_fixtures = self.create_vms(vn_fixture= vn1_fixture,count=2, + node_name=compute_hosts[1], image_name=image) + assert vm1_fixture.wait_till_vm_is_up(), 'VM does not seem to be up' + assert vm2_fixture.wait_till_vm_is_up(), 'VM does not seem to be up' + self.verify_vms(client_fixtures) + + proto = 'udp' + dport_list = [53, 54] + baseport = random.randint(12000, 65000) + sport_list = [str(baseport), str(baseport+1)] + port_list = [port1_obj, port2_obj] + + for port in port_list: + self.config_aap(port, vIP, mac=port['mac_address']) + self.config_vrrp(vm1_fixture, vIP, '20') + self.config_vrrp(vm2_fixture, vIP, '10') + vrrp_master = vm1_fixture + if is_v6(vIP): + #current version of vrrpd does not support IPv6, as a workaround add the vIP + # on one of the VM and start ping6 to make the VM as master + assert vm1_fixture.add_ip_on_vm(vIP) + assert client_fixtures[0].ping_with_certainty(vIP), 'Ping to vIP failure' + + assert self.vrrp_mas_chk(dst_vm=vrrp_master, vn=vn1_fixture, ip=vIP) + + fat_ignore_src = {'proto':proto,'port':dport_list[0], + 'ignore_address':'source'} + fat_ignore_dst = {'proto':proto,'port':dport_list[1], + 'ignore_address':'destination'} + fat_ignore_dst_port_0 = {'proto':proto,'port':0, + 'ignore_address':'destination'} + fat_config_list = [fat_ignore_src, fat_ignore_dst, + fat_ignore_dst_port_0] + + dst_compute_fix = self.compute_fixtures_dict[vrrp_master.vm_node_ip] + vrf_id_dst = dst_compute_fix.get_vrf_id(vrrp_master.vn_fq_names[0]) + for fat_config in fat_config_list: + self.add_fat_flow_to_vmis([port1_obj['id'], port2_obj['id']], + fat_config) + for vm in client_fixtures: + for sport in sport_list: + for dport in dport_list: + assert self.send_nc_traffic(vm, vrrp_master, + sport, dport, proto, ip=vIP) + + if fat_config['ignore_address'] == 'source': + fat_src_ip = '0.0.0.0' if self.inputs.get_af() == 'v4' else '::' + for vm in client_fixtures: + self.verify_fat_flow_on_compute(dst_compute_fix, vm.vm_ip, + fat_src_ip, fat_config['port'], proto, vrf_id_dst, + fat_flow_count=1) + if fat_config['ignore_address'] == 'destination': + fat_dst_ip = '0.0.0.0' if self.inputs.get_af() == 'v4' else '::' + self.verify_fat_flow_on_compute(dst_compute_fix, fat_dst_ip, + vIP, fat_config['port'], proto, vrf_id_dst, + fat_flow_count=1) + self.remove_fat_flow_on_vmis([port1_obj['id'], port2_obj['id']], + fat_config) + @preposttest_wrapper def test_fat_flow_lbaasv2(self): '''Creates Lbaas pool with lb-method ROUND ROBIN, 3 members and vip diff --git a/serial_scripts/vrouter/test_fat_flow_serial.py b/serial_scripts/vrouter/test_fat_flow_serial.py index 67a9bd434..9d7666712 100644 --- a/serial_scripts/vrouter/test_fat_flow_serial.py +++ b/serial_scripts/vrouter/test_fat_flow_serial.py @@ -203,6 +203,344 @@ def test_fat_flow_with_service_chain(self): self.logger.info("Fat flow got deleted after aging timeout as expected") + @preposttest_wrapper + def test_fat_flow_port_zero_intra_node(self): + """ + Description: Verify Fat flow with port 0 for inter node traffic + sub-cases: + a. Fat config on server VMI + b. Fat config on client VMI + Steps: + 1. Create 2 VNs and connect using policy + 2. launch 2 client VMs and 1 server VM and config Fat flow + 3. start traffic and verify Fat flow on required compute nodes + Pass criteria: + step 3 should pass + """ + self._create_resources(test_type='intra-node', no_of_client=2, + no_of_server=1) + + #Configure Fat flow on server VM + proto = 'udp' + dport_list = [53, 54] + server_vmi_id = self.server_fixtures[0].get_vmi_ids().values() + fat_flow_config = {'proto':proto,'port':0} + self.add_fat_flow_to_vmis(server_vmi_id, fat_flow_config) + + #Set udp aging timeout to 300 sec + flow_timeout = 300 + self.add_proto_based_flow_aging_time(proto, 0, flow_timeout) + + afs = ['v4', 'v6'] if 'dual' in self.inputs.get_af() else [self.inputs.get_af()] + for af in afs: + self.verify_fat_flow_with_traffic(self.client_fixtures,self.server_fixtures[0], + proto, af=af, fat_flow_config=fat_flow_config, + dport_list=dport_list) + + #Remove Fat flow from server VM + self.remove_fat_flow_on_vmis(server_vmi_id, fat_flow_config) + #Add Fat flow on client VMs + client1_vmi_id = self.client_fixtures[0].get_vmi_ids().values() + client2_vmi_id = self.client_fixtures[1].get_vmi_ids().values() + self.add_fat_flow_to_vmis(client1_vmi_id+client2_vmi_id, + fat_flow_config) + + #Clear all the flows before starting traffic + self.delete_all_flows_on_vms_compute( + self.server_fixtures + self.client_fixtures) + #When Fat flow with port 0 is configured on client VMs + sport_list = [10000, 10001] + compute_fix = self.compute_fixtures_dict[self.client_fixtures[0].vm_node_ip] + for af in afs: + for client_vm in self.client_fixtures: + for sport in sport_list: + for dport in dport_list: + assert self.send_nc_traffic(client_vm, + self.server_fixtures[0], sport, + dport, proto, + ip=self.server_fixtures[0].get_vm_ips(af=af)[0]) + + for client_vm in self.client_fixtures: + vrf_id_src = compute_fix.get_vrf_id(client_vm.vn_fq_names[0]) + self.verify_fat_flow_on_compute(compute_fix, + client_vm.get_vm_ips(af=af)[0], + self.server_fixtures[0].get_vm_ips(af=af)[0], 0, proto, + vrf_id_src, fat_flow_count=1) + + @preposttest_wrapper + def test_fat_flow_ignore_addrs(self): + """ + Description: Verify Fat flow with ignore address for inter node traffic + sub-cases: + a. ignore source and specific port + b. ignore destination and specific port + c. ignore source and port 0 + d. ignore destination and port 0 + Steps: + 1. Create 2 VNs and connect using policy + 2. launch VMs and config Fat flow on client/server VMs + 3. start traffic and verify Fat flow on required compute nodes + Pass criteria: + step 3 should pass + """ + self._create_resources(test_type='inter-node', no_of_client=2, + no_of_server=2) + proto = 'udp' + dport_list = [53] + sport_list = [10000] + + #Set udp aging timeout to 300 sec + flow_timeout = 300 + self.add_proto_based_flow_aging_time(proto, 0, flow_timeout) + + fat_config_on = ['server'] + for config in fat_config_on: + vmi_ids = [] + if config == 'server': + port = dport_list[0] + for vm in self.server_fixtures: + vmi_ids.extend(vm.get_vmi_ids().values()) + elif config == 'client': + port = sport_list[0] + for vm in self.client_fixtures: + vmi_ids.extend(vm.get_vmi_ids().values()) + fat_config_list = [ + {'proto':proto,'port':port, 'ignore_address':'source'}, + {'proto':proto,'port':port, 'ignore_address':'destination'}, + {'proto':proto,'port':0, 'ignore_address':'source'}, + {'proto':proto,'port':0, 'ignore_address':'destination'}, + {'proto':proto,'port':0} + ] + + for fat_config in fat_config_list: + self.add_fat_flow_to_vmis(vmi_ids, fat_config) + self.verify_fat_flow_with_ignore_addrs(self.client_fixtures, + self.server_fixtures, fat_config, + fat_config_on=config) + self.remove_fat_flow_on_vmis(vmi_ids, fat_config) + + @preposttest_wrapper + def test_fat_flow_ignore_addrs_icmp_error(self): + """ + Description: Verify Fat flow with ignore address for icmp error for inter node traffic + sub-cases: + a. ignore source and specific port on server VMI + b. ignore destination and specific port on server VMI + c. ignore source and port 0 on server VMI + d. ignore destination and port 0 on server VMI + Steps: + 1. Create 2 VNs and connect using policy + 2. launch VMs and config Fat flow on server VMs + 3. start traffic and verify Fat flow on required compute nodes + Pass criteria: + step 3 should pass + """ + self._create_resources(test_type='inter-node', no_of_client=2, + no_of_server=2) + proto = 'udp' + dport_list = [53] + sport_list = [10000] + + #Set udp aging timeout to 300 sec + flow_timeout = 300 + self.add_proto_based_flow_aging_time(proto, 0, flow_timeout) + + fat_config_on = ['client', 'server'] + for config in fat_config_on: + vmi_ids = [] + if config == 'server': + port = dport_list[0] + for vm in self.server_fixtures: + vmi_ids.extend(vm.get_vmi_ids().values()) + elif config == 'client': + port = sport_list[0] + for vm in self.client_fixtures: + vmi_ids.extend(vm.get_vmi_ids().values()) + fat_config_list = [ + {'proto':proto,'port':port, 'ignore_address':'source'}, + {'proto':proto,'port':port, 'ignore_address':'destination'}, + {'proto':proto,'port':0, 'ignore_address':'source'}, + {'proto':proto,'port':0, 'ignore_address':'destination'}, + {'proto':proto,'port':0} + ] + + for fat_config in fat_config_list: + self.add_fat_flow_to_vmis(vmi_ids, fat_config) + self.verify_fat_flow_with_ignore_addrs(self.client_fixtures, + self.server_fixtures, fat_config, icmp_error=True, + fat_config_on=config) + self.remove_fat_flow_on_vmis(vmi_ids, fat_config) + + @preposttest_wrapper + def test_fat_flow_ignore_addrs_icmp_error_intra_node(self): + """ + Description: Verify Fat flow with ignore address for icmp error for intra node traffic + Steps: + 1. Create 2 VNs and connect using policy + 2. launch VMs and config Fat flow on server VMs + 3. start traffic and verify Fat flow on required compute nodes + Pass criteria: + step 3 should pass + """ + self._create_resources(test_type='intra-node', no_of_client=2, + no_of_server=2) + proto = 'udp' + dport_list = [53] + sport_list = [10000] + + #Set udp aging timeout to 300 sec + flow_timeout = 300 + self.add_proto_based_flow_aging_time(proto, 0, flow_timeout) + + fat_config_on = 'server' + vmi_ids = [] + port = dport_list[0] + for vm in self.server_fixtures: + vmi_ids.extend(vm.get_vmi_ids().values()) + fat_config_list = [ + {'proto':proto,'port':port, 'ignore_address':'destination'}, + {'proto':proto,'port':0, 'ignore_address':'destination'}, + {'proto':proto,'port':0} + ] + + for fat_config in fat_config_list: + self.add_fat_flow_to_vmis(vmi_ids, fat_config) + self.verify_fat_flow_with_ignore_addrs(self.client_fixtures, + self.server_fixtures, fat_config, icmp_error=True, + fat_config_on=fat_config_on) + self.remove_fat_flow_on_vmis(vmi_ids, fat_config) + + @preposttest_wrapper + def test_fat_flow_at_vn(self): + """ + Description: Verify Fat flow at VN level + sub-cases: + a. ignore source and specific port + b. ignore destination and specific port + c. ignore source and port 0 + d. ignore destination and port 0 + Steps: + 1. Create 2 VNs and connect using policy + 2. launch VMs and config Fat flow on client/server VMs + 3. start traffic and verify Fat flow on required compute nodes + Pass criteria: + step 3 should pass + """ + self._create_resources(test_type='inter-node', no_of_client=2, + no_of_server=2) + proto = 'udp' + dport_list = [10000] + sport_list = [10000] + + #Set aging timeout to 300 sec + flow_timeout = 300 + self.add_proto_based_flow_aging_time(proto, 0, flow_timeout) + + fat_config_on = ['server'] + for config in fat_config_on: + vns = [] + if config == 'server': + port = dport_list[0] + vns.append(self.vn2_fixture) + elif config == 'client': + port = sport_list[0] + vns.append(self.vn1_fixture) + fat_config_list = [ + {'proto':proto,'port':port, 'ignore_address':'source'}, + {'proto':proto,'port':port, 'ignore_address':'destination'}, + {'proto':proto,'port':0, 'ignore_address':'source'}, + {'proto':proto,'port':0, 'ignore_address':'destination'}, + {'proto':proto,'port':0} + ] + + for fat_config in fat_config_list: + self.add_fat_flow_to_vns(vns, fat_config) + self.verify_fat_flow_with_ignore_addrs(self.client_fixtures, + self.server_fixtures, fat_config, + fat_config_on=config, sport=sport_list[0], + dport=dport_list[0]) + self.delete_fat_flow_from_vns(vns) + + @preposttest_wrapper + def test_fat_flow_at_vn_intra_vn(self): + """ + Description: Verify Fat flow at VN level and intra-vn/node traffic + Steps: + 1. Create 2 VNs and connect using policy + 2. launch VMs and config Fat flow on client/server VMs + 3. start traffic and verify Fat flow on required compute nodes + Pass criteria: + step 3 should pass + """ + self._create_resources(test_type='inter-node', no_of_client=4, + no_of_server=1) + proto = 'udp' + dport_list = [53] + sport_list = [10000] + + #Set udp aging timeout to 300 sec + flow_timeout = 300 + self.add_proto_based_flow_aging_time(proto, 0, flow_timeout) + client_fixs = [self.client_fixtures[0], self.client_fixtures[1]] + server_fixs = [self.client_fixtures[2], self.client_fixtures[3]] + port = dport_list[0] + vns = [self.vn1_fixture] + fat_config_list = [ + {'proto':proto,'port':port, 'ignore_address':'destination'}, + {'proto':proto,'port':0, 'ignore_address':'destination'}, + {'proto':proto,'port':0} + ] + + for fat_config in fat_config_list: + self.add_fat_flow_to_vns(vns, fat_config) + self.verify_fat_flow_with_ignore_addrs(client_fixs, + server_fixs, fat_config, + fat_config_on='all') + self.delete_fat_flow_from_vns(vns) + + @preposttest_wrapper + def test_fat_flow_vn_vmi(self): + """ + Description: configure Fat flow on both VN and VMI + Steps: + 1. Create 2 VNs and connect using policy + 2. launch VMs and config Fat flow on VMI and VN both + 3. start traffic and verify Fat flow on required compute nodes + Pass criteria: + step 3 should pass + """ + self._create_resources(test_type='inter-node', no_of_client=4, + no_of_server=1) + proto = 'udp' + dport_list = [11000] + sport_list = [10000] + + #Set aging timeout to 300 sec + flow_timeout = 300 + self.add_proto_based_flow_aging_time(proto, 0, flow_timeout) + port = dport_list[0] + vns = [self.vn2_fixture] + vmi_ids = [] + for vm in self.server_fixtures: + vmi_ids.extend(vm.get_vmi_ids().values()) + fat_config_vn = { + 'proto':proto,'port':0, 'ignore_address':'destination' + } + fat_config_vmi = { + 'proto':proto,'port':dport_list[0], 'ignore_address':'destination' + } + self.add_fat_flow_to_vns(vns, fat_config_vn) + self.add_fat_flow_to_vmis(vmi_ids, fat_config_vmi) + self.verify_fat_flow_with_ignore_addrs(self.client_fixtures, + self.server_fixtures, fat_config_vmi, + fat_config_on='server', sport=sport_list[0], + dport=dport_list[0]) + + self.verify_fat_flow_with_ignore_addrs(self.client_fixtures, + self.server_fixtures, fat_config_vn, + fat_config_on='server', sport=sport_list[0], + dport=dport_list[0]) + class FatFlowSerialIpv6(FatFlowSerial): @classmethod def setUpClass(cls):