Multiple Mirror ports using OVS (Open vSwitch)

I’ve recently started playing around with Open vSwitch with KVM, mainly because I wanted a way of monitoring traffic floating around on the network. Setting up a mirror is fairly well documented- it’s on the man page for ovs-vsctl for one thing. But what about mirroring the same port to multiple destinations? I had this specific requirement, it might seem niche, but from a quick Google I found other people had been trying to achieve the same goal, but couldn’t find any instructions for it myself.

So, in my setup, I had a CentOS host with traffic coming in on port enp0s31f6 – which i’m going to rename eth0 for the purpose of this tutorial, because i hate typing that out. Say I now wanted to monitor the traffic on this interface in a monitoring VM, I would do something like this. Again, it’s pretty well documented on the OVS website.

First, set up the bridge, with a tap to the eth port, and a new tap that our vm is going to use. We’ll add the extra tap we’re going to use later, too.

# ovs-vsctl add-br br0
# ip tuntap add mode tap tap0
# ovs-vsctl add-port br0 tap0
# ip tuntap add mode tap tap1
# ovs-vsctl add-port br0 tap1
# ovs-vsctl add-port br0 eth0

Next, I’d create the vm. I’ve been using virt-manager since I personally prefer GUIs to hacking around with XML. We want to add our tap here, a macvtap interface and ensure the mode is ‘passthrough’.

libvirt macvtap

We now want to set up the mirroring. To mirror everything from eth0 the command is:

# ovs-vsctl — set Bridge br0 mirrors=@m \
— –id=@eth0 get Port eth0 \
— –id=@tap0 get Port tap0 \
— –id=@m create Mirror name=mymirror select-dst-port=@eth0 select-src-port=@eth0 output-port=@tap0

Once you have done this, try a tcpdump on eth0 on the host, and simultaneously on the interface in our newly created guest. You should identical traffic on both interfaces. But now the bit where i had to do a tiny bit of thinking- how to mirror the same interface to two different ports. OVS won’t let you enter multiple output-ports- it will return a message along the lines of

ovs-vsctl: @tap0,@tap1: 2 value(s) specified but the maximum number is 1

Now, if we continue with our configuration we set up, running

# ovs-vsctl list Bridge br0

Will show something like this

_uuid : 48b28a5d-4a9f-4dd8-88ac-4092472360de
auto_attach : []
controller : []
datapath_id : “0000507b9df0bb96”
datapath_type : “”
datapath_version : “<unknown>”
external_ids : {}
fail_mode : []
flood_vlans : []
flow_tables : {}
ipfix : []
mcast_snooping_enable: false
mirrors : [baee8f91-57a5-45ab-b71c-faabeea2255a]
name : “br0”
netflow : []
other_config : {}
ports : [579e15c6-72c5-4f1a-ac53-14d57317311b, aa5dcb98-bd6f-4637-ac4a-e0003a32cd42, b4fba15c-1a78-4393-a742-cc3937b814f2, cd4d7f8e-5d7e-4552-ac52-c65bc022dfbe]
protocols : []
rstp_enable : false
rstp_status : {}
sflow : []
status : {}
stp_enable : false

What we want to do, is add a list of entries to ‘mirrors’. I’m not sure if there’s a way to append to any of these config fields, so the way i achieved the problem was to set both mirrors in one go. I achieved it like this:

# ovs-vsctl — set Bridge br0 mirrors=@m,@m2 \
— –id=@eth0 get Port eth0\
— –id=@tap0 get Port tap0 \
— –id=@tap1 get Port tap1 \
— –id=@m create Mirror name=mymirror select-dst-port=@eth0 select-src-port=@eth0 output-port=@tap0 \
— –id=@m2 create Mirror name=myothermirror select-dst-port=@eth0 select-src-port=@eth0 output-port=@tap1

Now, a tcpdump should confirm that all three ports are seeing the traffic originally destined for eth0. Problem solved!

One thought on “Multiple Mirror ports using OVS (Open vSwitch)”

Leave a comment