未验证 提交 3a9e6ed7 编写于 作者: Q Qianqian Zhu 提交者: GitHub

Merge pull request #1576 from pezhang/bug1634361

Add enabling port mirror with bridge backend
import logging
import re
import time
from avocado.utils import process
from virttest import utils_net
from virttest import env_process
from virttest import error_context
@error_context.context_aware
def run(test, params, env):
"""
Test port mirror with bridge backend
1) Create a private bridge
2) Set private bridge promisc mode and up
3) Boot 3 VMs over private bridge
4) Mirror all traffic on bridge to tap device connected to VM1
5) Start tcpdump in VM1 to dump icmp packets from VM2 to VM3
6) Ping VM3 from VM2
7) Stop Ping in VM2
8) Stop tcpdump and check results
:param test: KVM test object
:param params: Dictionary with the test parameters
:param env: Dictionary with test environment.
"""
def mirror_bridge_to_tap(tap_name):
"""
Mirror all packages on bridge to tap device connected to vm vNIC
:param tap_name: name of tap connected to vm
"""
enable_promisc_cmd = params.get("enable_promisc_cmd")
tc_qdisc_add_ingress = params.get("tc_qdisc_add_ingress")
tc_filter_show_dev = params.get("tc_filter_show_dev")
tc_filter_replace_dev = params.get("tc_filter_replace_dev") % tap_name
tc_qdisc_replace = params.get("tc_qdisc_replace")
process.system_output(enable_promisc_cmd)
process.system_output(tc_qdisc_add_ingress)
process.system_output(tc_filter_show_dev)
process.system_output(tc_filter_replace_dev)
process.system_output(tc_qdisc_replace)
tc_qdisc_show_dev = params.get("tc_qdisc_show_dev")
output = process.system_output(tc_qdisc_show_dev).decode()
port = re.findall("qdisc prio (.*):", output)[0]
tc_filter_show_dev_port = params.get("tc_filter_show_dev_port") % port
tc_filter_replace_dev_port = params.get(
"tc_filter_replace_dev_port") % (port, tap_name)
process.system_output(tc_filter_show_dev_port)
process.system_output(tc_filter_replace_dev_port)
def check_tcpdump(output, src_ip, des_ip, ping_count):
"""
Check tcpdump result.
:parm output: string of tcpdump output.
:parm src_ip: ip to ping
:parm des_ip: ip to receive ping
:parm ping_count: total ping packets number
:return: bool type result.
"""
rex_request = r".*IP %s > %s.*ICMP echo request.*" % (
src_ip, des_ip)
rex_reply = r".*IP %s > %s.*ICMP echo reply.*" % (
des_ip, src_ip)
request_num = 0
reply_num = 0
for idx, _ in enumerate(output.splitlines()):
if re.match(rex_request, _):
request_num += 1
elif re.match(rex_reply, _):
reply_num += 1
if request_num != ping_count or reply_num != ping_count:
logging.debug(
"Unexpect request or reply number. "
"current request number is: %d, "
"current reply number is: %d, "
"expected request and reply number is: %d. "
% (request_num, reply_num, ping_count))
return False
return True
brname = params.get("private_bridge", "tmpbr")
net_mask = params.get("net_mask", "24")
login_timeout = int(params.get("login_timeout", "600"))
stop_NM_cmd = params.get("stop_NM_cmd")
stop_firewall_cmd = params.get("stop_firewall_cmd")
add_private_bridge_cmd = params.get("add_private_bridge_cmd")
tcpdump_cmd = params.get("tcpdump_cmd")
tcpdump_log = params.get("tcpdump_log")
get_tcpdump_log_cmd = params.get("get_tcpdump_log_cmd")
ping_count = int(params.get("ping_count"))
error_context.context("Create a private bridge", logging.info)
process.system_output(add_private_bridge_cmd, shell=True)
params['netdst'] = brname
params["start_vm"] = "yes"
vm_names = params.get("vms").split()
vms_info = {}
try:
for vm_name in vm_names:
env_process.preprocess_vm(test, params, env, vm_name)
vm = env.get_vm(vm_name)
vm.verify_alive()
ip = params["ip_%s" % vm_name]
mac = vm.get_mac_address()
session = vm.wait_for_serial_login(timeout=login_timeout)
session.cmd(stop_NM_cmd, ignore_all_errors=True)
session.cmd(stop_firewall_cmd, ignore_all_errors=True)
nic_name = utils_net.get_linux_ifname(session, mac)
ifname = vm.get_ifname()
ifup_cmd = "ifconfig %s %s/%s up" % (nic_name, ip, net_mask)
session.cmd(ifup_cmd)
vms_info[vm_name] = [vm, ifname, ip, session, nic_name]
vm_mirror = vm_names[0]
vm_src = vm_names[1]
vm_des = vm_names[2]
error_context.context(
"Mirror all packets on bridge to tap device conncted to %s"
% vm_mirror)
tap_ifname = vms_info[vm_mirror][0].virtnet[0].ifname
mirror_bridge_to_tap(tap_ifname)
error_context.context("Start tcpdump in %s"
% vm_mirror, logging.info)
tcpdump_cmd = params.get("tcpdump_cmd") % (
vms_info[vm_des][2], tcpdump_log)
logging.info("tcpdump command: %s" % tcpdump_cmd)
vms_info[vm_mirror][3].sendline(tcpdump_cmd)
time.sleep(5)
error_context.context("Start ping from %s to %s" %
(vm_src, vm_des), logging.info)
ping_cmd = params.get("ping_cmd") % vms_info[vm_des][2]
vms_info[vm_src][3].cmd(ping_cmd, timeout=150)
error_context.context("Check tcpdump results", logging.info)
time.sleep(5)
vms_info[vm_mirror][3].cmd_output_safe("pkill tcpdump")
tcpdump_content = vms_info[vm_mirror][3].cmd_output(
get_tcpdump_log_cmd).strip()
if not check_tcpdump(
tcpdump_content, vms_info[vm_src][2], vms_info[vm_des][2], ping_count):
test.fail("tcpdump results are not expected, mirror fail.")
finally:
for vm in vms_info:
vms_info[vm][0].destroy(gracefully=False)
tc_qdisc_del_ingress = params.get("tc_qdisc_del_ingress")
tc_qdisc_del_root = params.get("tc_qdisc_del_root")
process.system_output(tc_qdisc_del_ingress)
process.system_output(tc_qdisc_del_root)
process.system_output("ip link delete %s" % brname)
- bridge_mirror:
only Linux
only bridge
type = bridge_mirror
vms = "vm1 vm2 vm3"
start_vm = no
private_bridge = tmpbr
add_private_bridge_cmd = "ip link add name ${private_bridge} type bridge;"
add_private_bridge_cmd += "ip link set ${private_bridge} up"
tcpdump_cmd = "tcpdump -l -n host %s and icmp > %s &"
tcpdump_log = "/tmp/tcpdump.log"
get_tcpdump_log_cmd = "cat ${tcpdump_log}"
ping_count = 10
ping_cmd = "ping %s -c ${ping_count} -i 0.1"
net_mask = "24"
ip_vm1 = "192.168.1.1"
ip_vm2 = "192.168.1.2"
ip_vm3 = "192.168.1.3"
image_snapshot = yes
login_timeout = 720
stop_NM_cmd = "systemctl stop NetworkManager"
stop_firewall_cmd = "systemctl stop firewalld.service"
enable_promisc_cmd = "ifconfig ${private_bridge} promisc up"
tc_qdisc = "/sbin/tc qdisc"
tc_filter = "/sbin/tc filter"
tc_qdisc_add_ingress = "${tc_qdisc} add dev ${private_bridge} ingress"
tc_filter_show_dev = "${tc_filter} show dev ${private_bridge} parent ffff:"
tc_filter_replace_dev = "${tc_filter} replace dev ${private_bridge} parent ffff: protocol ip u32 match u8 0 0 action mirred egress mirror dev %s"
tc_qdisc_replace = "${tc_qdisc} replace dev ${private_bridge} parent root prio"
tc_qdisc_show_dev = "${tc_qdisc} show dev ${private_bridge}"
tc_filter_show_dev_port = "${tc_filter} show dev ${private_bridge} parent %s:"
tc_filter_replace_dev_port = "${tc_filter} replace dev ${private_bridge} parent %s: protocol ip u32 match u8 0 0 action mirred egress mirror dev %s"
tc_qdisc_del_ingress = "${tc_qdisc} del dev ${private_bridge} ingress"
tc_qdisc_del_root = "${tc_qdisc} del dev ${private_bridge} root"
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册