+
+
+AT_SETUP([ofproto-dpif - mirroring, select_all])
+OVS_VSWITCHD_START
+ADD_OF_PORTS([br0], 1, 2, 3)
+ovs-vsctl \
+ set Bridge br0 mirrors=@m --\
+ --id=@p3 get Port p3 --\
+ --id=@m create Mirror name=mymirror select_all=true output_port=@p3
+
+AT_DATA([flows.txt], [dnl
+in_port=1 actions=output:2
+in_port=2 actions=output:1
+])
+AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
+
+flow="in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)"
+AT_CHECK([ovs-appctl ofproto/trace br0 "$flow"], [0], [stdout])
+AT_CHECK_UNQUOTED([tail -1 stdout], [0],
+ [Datapath actions: 2,3
+])
+
+flow="in_port(2),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)"
+AT_CHECK([ovs-appctl ofproto/trace br0 "$flow"], [0], [stdout])
+AT_CHECK_UNQUOTED([tail -1 stdout], [0],
+ [Datapath actions: 1,3
+])
+
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+
+AT_SETUP([ofproto-dpif - mirroring, select_src])
+OVS_VSWITCHD_START
+ADD_OF_PORTS([br0], 1, 2, 3)
+ovs-vsctl \
+ set Bridge br0 mirrors=@m --\
+ --id=@p1 get Port p1 -- --id=@p3 get Port p3 --\
+ --id=@m create Mirror name=mymirror select_src_port=@p1 output_port=@p3
+
+AT_DATA([flows.txt], [dnl
+in_port=1 actions=output:2
+in_port=2 actions=output:1
+])
+AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
+
+flow="in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)"
+AT_CHECK([ovs-appctl ofproto/trace br0 "$flow"], [0], [stdout])
+AT_CHECK_UNQUOTED([tail -1 stdout], [0],
+ [Datapath actions: 2,3
+])
+
+flow="in_port(2),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)"
+AT_CHECK([ovs-appctl ofproto/trace br0 "$flow"], [0], [stdout])
+AT_CHECK_UNQUOTED([tail -1 stdout], [0],
+ [Datapath actions: 1
+])
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+AT_SETUP([ofproto-dpif - mirroring, OFPP_NONE ingress port])
+OVS_VSWITCHD_START
+ADD_OF_PORTS([br0], 1, 2)
+ovs-vsctl \
+ set Bridge br0 mirrors=@m --\
+ --id=@p2 get Port p2 --\
+ --id=@m create Mirror name=mymirror select_all=true output_port=@p2
+
+AT_CHECK([ovs-ofctl add-flow br0 action=output:1])
+
+# "in_port" defaults to OFPP_NONE if it's not specified.
+flow="icmp,dl_src=50:54:00:00:00:05,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_ttl=128,icmp_type=8,icmp_code=0"
+AT_CHECK([ovs-appctl ofproto/trace br0 "$flow"], [0], [stdout])
+AT_CHECK_UNQUOTED([tail -1 stdout], [0],
+ [Datapath actions: 1,2
+])
+
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+
+AT_SETUP([ofproto-dpif - mirroring, select_dst])
+OVS_VSWITCHD_START
+ADD_OF_PORTS([br0], 1, 2, 3)
+ovs-vsctl \
+ set Bridge br0 mirrors=@m --\
+ --id=@p2 get Port p2 -- --id=@p3 get Port p3 --\
+ --id=@m create Mirror name=mymirror select_dst_port=@p2 output_port=@p3
+
+AT_DATA([flows.txt], [dnl
+in_port=1 actions=output:2
+in_port=2 actions=output:1
+])
+AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
+
+flow="in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)"
+AT_CHECK([ovs-appctl ofproto/trace br0 "$flow"], [0], [stdout])
+AT_CHECK_UNQUOTED([tail -1 stdout], [0],
+ [Datapath actions: 2,3
+])
+
+flow="in_port(2),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)"
+AT_CHECK([ovs-appctl ofproto/trace br0 "$flow"], [0], [stdout])
+AT_CHECK_UNQUOTED([tail -1 stdout], [0],
+ [Datapath actions: 1
+])
+
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+
+AT_SETUP([ofproto-dpif - mirroring, select_vlan])
+OVS_VSWITCHD_START
+ADD_OF_PORTS([br0], 1, 2, 3)
+ovs-vsctl \
+ set Bridge br0 mirrors=@m --\
+ --id=@p2 get Port p2 -- --id=@p3 get Port p3 --\
+ --id=@m create Mirror name=mymirror select_all=true select_vlan=11 output_port=@p3
+
+AT_DATA([flows.txt], [dnl
+in_port=1, actions=output:2
+])
+AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
+
+flow="in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)"
+AT_CHECK([ovs-appctl ofproto/trace br0 "$flow"], [0], [stdout])
+AT_CHECK_UNQUOTED([tail -1 stdout], [0],
+ [Datapath actions: 2
+])
+
+flow="in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x8100),vlan(vid=10,pcp=0),encap(eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0))"
+AT_CHECK([ovs-appctl ofproto/trace br0 "$flow"], [0], [stdout])
+AT_CHECK_UNQUOTED([tail -1 stdout], [0],
+ [Datapath actions: 2
+])
+
+flow="in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x8100),vlan(vid=11,pcp=0),encap(eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0))"
+AT_CHECK([ovs-appctl ofproto/trace br0 "$flow"], [0], [stdout])
+AT_CHECK_UNQUOTED([tail -1 stdout], [0],
+ [Datapath actions: 2,3
+])
+
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+
+AT_SETUP([ofproto-dpif - mirroring, output_port])
+OVS_VSWITCHD_START
+ADD_OF_PORTS([br0], 1, 2, 3)
+ovs-vsctl \
+ set Bridge br0 mirrors=@m --\
+ --id=@p3 get Port p3 --\
+ --id=@m create Mirror name=mymirror select_all=true output_port=@p3
+
+AT_DATA([flows.txt], [dnl
+in_port=1 actions=mod_vlan_vid:17,output:2
+in_port=2 actions=output:1
+])
+AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
+
+flow="in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)"
+AT_CHECK([ovs-appctl ofproto/trace br0 "$flow"], [0], [stdout])
+AT_CHECK_UNQUOTED([tail -1 stdout], [0],
+ [Datapath actions: push_vlan(vid=17,pcp=0),2,pop_vlan,3
+])
+
+flow="in_port(2),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)"
+AT_CHECK([ovs-appctl ofproto/trace br0 "$flow"], [0], [stdout])
+AT_CHECK_UNQUOTED([tail -1 stdout], [0],
+ [Datapath actions: 1,3
+])
+
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+AT_SETUP([ofproto-dpif - mirroring, output_vlan])
+OVS_VSWITCHD_START
+ADD_OF_PORTS([br0], 1, 2)
+ovs-vsctl \
+ set Bridge br0 mirrors=@m --\
+ --id=@m create Mirror name=mymirror select_all=true output_vlan=12
+
+AT_DATA([flows.txt], [dnl
+in_port=1 actions=output:2
+in_port=2 actions=mod_vlan_vid:17,output:1
+])
+AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
+
+flow="in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)"
+AT_CHECK([ovs-appctl ofproto/trace br0 "$flow"], [0], [stdout])
+actual=`tail -1 stdout | sed 's/Datapath actions: //'`
+
+expected="2,push_vlan(vid=12,pcp=0),1,2,100"
+AT_CHECK([ovs-dpctl normalize-actions "$flow" "$expected"], [0], [stdout])
+mv stdout expout
+AT_CHECK([ovs-dpctl normalize-actions "$flow" "$actual"], [0], [expout])
+
+flow="in_port(2),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)"
+AT_CHECK([ovs-appctl ofproto/trace br0 "$flow"], [0], [stdout])
+actual=`tail -1 stdout | sed 's/Datapath actions: //'`
+
+expected="push_vlan(vid=17,pcp=0),1,pop_vlan,push_vlan(vid=12,pcp=0),1,2,100"
+AT_CHECK([ovs-dpctl normalize-actions "$flow" "$expected"], [0], [stdout])
+mv stdout expout
+AT_CHECK([ovs-dpctl normalize-actions "$flow" "$actual"], [0], [expout])
+
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+m4_define([OFPROTO_TRACE],
+ [flow="$2"
+ AT_CHECK([ovs-appctl ofproto/trace $1 "$flow" $3], [0], [stdout])
+ actual=`tail -1 stdout | sed 's/Datapath actions: //'`
+ expected="$4"
+ AT_CHECK([ovs-dpctl normalize-actions "$flow" "$expected" $5],
+ [0], [stdout])
+ mv stdout expout
+ AT_CHECK([ovs-dpctl normalize-actions "$flow" "$actual" $5],
+ [0], [expout])])
+
+AT_SETUP([ofproto-dpif - MAC learning])
+OVS_VSWITCHD_START([set bridge br0 fail-mode=standalone])
+ADD_OF_PORTS([br0], 1, 2, 3)
+
+arp='eth_type(0x0806),arp(sip=192.168.0.1,tip=192.168.0.2,op=1,sha=50:54:00:00:00:05,tha=00:00:00:00:00:00)'
+
+# Trace an ARP packet arriving on p3, to create a MAC learning entry.
+OFPROTO_TRACE(
+ [br0],
+ [in_port(3),eth(src=50:54:00:00:00:05,dst=ff:ff:ff:ff:ff:ff),$arp],
+ [-generate],
+ [1,2,100])
+
+# Check for the MAC learning entry.
+AT_CHECK_UNQUOTED([ovs-appctl fdb/show br0 | sed 's/[[0-9]]\{1,\}$/?/'], [0], [dnl
+ port VLAN MAC Age
+ 3 0 50:54:00:00:00:05 ?
+])
+
+# Trace a packet arrival destined for the learned MAC.
+# (This will also learn a MAC.)
+OFPROTO_TRACE(
+ [br0],
+ [in_port(1),eth(src=50:54:00:00:00:06,dst=50:54:00:00:00:05),$arp],
+ [-generate],
+ [3])
+
+# Check for both MAC learning entries.
+AT_CHECK_UNQUOTED([ovs-appctl fdb/show br0 | sed 's/[[0-9]]\{1,\}$/?/'], [0], [dnl
+ port VLAN MAC Age
+ 3 0 50:54:00:00:00:05 ?
+ 1 0 50:54:00:00:00:06 ?
+])
+
+# Trace a packet arrival that updates the first learned MAC entry.
+OFPROTO_TRACE(
+ [br0],
+ [in_port(2),eth(src=50:54:00:00:00:05,dst=ff:ff:ff:ff:ff:ff),$arp],
+ [-generate],
+ [1,3,100])
+
+# Check that the MAC learning entry was updated.
+AT_CHECK_UNQUOTED([ovs-appctl fdb/show br0 | sed 's/[[0-9]]\{1,\}$/?/'], [0], [dnl
+ port VLAN MAC Age
+ 1 0 50:54:00:00:00:06 ?
+ 2 0 50:54:00:00:00:05 ?
+])
+
+# Add another bridge.
+AT_CHECK(
+ [ovs-vsctl \
+ -- add-br br1 \
+ -- set bridge br1 datapath-type=dummy \
+ -- add-port br1 p4 -- set interface p4 type=dummy \
+ -- add-port br1 p5 -- set interface p5 type=dummy])
+
+# Trace some packet arrivals in br1 to create MAC learning entries there too.
+OFPROTO_TRACE(
+ [br1],
+ [in_port(4),eth(src=50:54:00:00:00:06,dst=ff:ff:ff:ff:ff:ff),$arp],
+ [-generate],
+ [5,101])
+OFPROTO_TRACE(
+ [br1],
+ [in_port(5),eth(src=50:54:00:00:00:07,dst=ff:ff:ff:ff:ff:ff),$arp],
+ [-generate],
+ [4,101])
+
+# Check that the MAC learning entries were added.
+AT_CHECK_UNQUOTED([ovs-appctl fdb/show br1 | sed 's/[[0-9]]\{1,\}$/?/'], [0], [dnl
+ port VLAN MAC Age
+ 4 0 50:54:00:00:00:06 ?
+ 5 0 50:54:00:00:00:07 ?
+])
+
+# Delete port p1 and see that its MAC learning entry disappeared, and
+# that the MAC learning entry for the same MAC was also deleted from br1.
+AT_CHECK([ovs-vsctl del-port p1])
+AT_CHECK_UNQUOTED([ovs-appctl fdb/show br0 | sed 's/[[0-9]]\{1,\}$/?/'], [0], [dnl
+ port VLAN MAC Age
+ 2 0 50:54:00:00:00:05 ?
+])
+AT_CHECK_UNQUOTED([ovs-appctl fdb/show br1 | sed 's/[[0-9]]\{1,\}$/?/'], [0], [dnl
+ port VLAN MAC Age
+ 5 0 50:54:00:00:00:07 ?
+])
+
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+AT_SETUP([ofproto-dpif - MAC table overflow])
+OVS_VSWITCHD_START(
+ [set bridge br0 fail-mode=standalone other-config:mac-table-size=10 -- \
+ add-port br0 p1 -- set Interface p1 type=dummy -- \
+ add-port br0 p2 -- set Interface p2 type=dummy -- \
+ add-port br0 p3 -- set Interface p3 type=dummy])
+
+arp='eth_type(0x0806),arp(sip=192.168.0.1,tip=192.168.0.2,op=1,sha=50:54:00:00:00:05,tha=00:00:00:00:00:00)'
+
+AT_CHECK([ovs-appctl time/stop])
+
+# Trace 10 ARP packets arriving on p3, to create MAC learning entries.
+for i in 0 1 2 3 4 5 6 7 8 9; do
+ OFPROTO_TRACE(
+ [br0],
+ [in_port(3),eth(src=50:54:00:00:00:0$i,dst=ff:ff:ff:ff:ff:ff),$arp],
+ [-generate],
+ [1,2,100])
+ ovs-appctl time/warp 1000
+done
+
+# Check for the MAC learning entries.
+AT_CHECK_UNQUOTED([ovs-appctl fdb/show br0 | sed 's/ *[[0-9]]\{1,\}$//' | sort],
+ [0], [dnl
+ 3 0 50:54:00:00:00:00
+ 3 0 50:54:00:00:00:01
+ 3 0 50:54:00:00:00:02
+ 3 0 50:54:00:00:00:03
+ 3 0 50:54:00:00:00:04
+ 3 0 50:54:00:00:00:05
+ 3 0 50:54:00:00:00:06
+ 3 0 50:54:00:00:00:07
+ 3 0 50:54:00:00:00:08
+ 3 0 50:54:00:00:00:09
+ port VLAN MAC Age
+])
+
+# Trace another ARP packet on another MAC.
+OFPROTO_TRACE(
+ [br0],
+ [in_port(3),eth(src=50:54:00:00:00:10,dst=ff:ff:ff:ff:ff:ff),$arp],
+ [-generate],
+ [1,2,100])
+
+# Check that the new one chased the oldest one out of the table.
+AT_CHECK_UNQUOTED([ovs-appctl fdb/show br0 | sed 's/[[0-9]]\{1,\}$/?/' | sort],
+ [0], [dnl
+ 3 0 50:54:00:00:00:01 ?
+ 3 0 50:54:00:00:00:02 ?
+ 3 0 50:54:00:00:00:03 ?
+ 3 0 50:54:00:00:00:04 ?
+ 3 0 50:54:00:00:00:05 ?
+ 3 0 50:54:00:00:00:06 ?
+ 3 0 50:54:00:00:00:07 ?
+ 3 0 50:54:00:00:00:08 ?
+ 3 0 50:54:00:00:00:09 ?
+ 3 0 50:54:00:00:00:10 ?
+ port VLAN MAC Age
+])
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+dnl Test that sFlow samples packets correctly.
+AT_SETUP([ofproto-dpif - sFlow packet sampling])
+AT_CHECK([perl $srcdir/choose-port.pl], [0], [stdout])
+SFLOW_PORT=`cat stdout`
+OVS_VSWITCHD_START([set Bridge br0 fail-mode=standalone])
+
+ovs-appctl time/stop
+
+ADD_OF_PORTS([br0], 1, 2)
+ovs-vsctl \
+ set Interface br0 options:ifindex=1002 -- \
+ set Interface p1 options:ifindex=1004 -- \
+ set Interface p2 options:ifindex=1003 -- \
+ set Bridge br0 sflow=@sf -- \
+ --id=@sf create sflow targets=\"127.0.0.1:$SFLOW_PORT\" \
+ header=128 sampling=1 polling=1
+ON_EXIT([kill `cat test-sflow.pid`])
+AT_CHECK([test-sflow --detach --no-chdir --pidfile $SFLOW_PORT:127.0.0.1 > sflow.log])
+AT_CAPTURE_FILE([sflow.log])
+
+dnl open with ARP packets to seed the bridge-learning. The output
+dnl ifIndex numbers should be reported predictably after that.
+dnl Since we set sampling=1 we should see all of these packets
+dnl reported. Sorting the output by data-source and seqNo makes
+dnl it deterministic. Ensuring that we send at least two packets
+dnl into each port means we get to check the seq nos are
+dnl incrementing correctly.
+
+ovs-appctl netdev-dummy/receive p1 'in_port(2),eth(src=50:54:00:00:00:05,dst=FF:FF:FF:FF:FF:FF),eth_type(0x0806),arp(sip=192.168.0.2,tip=192.168.0.1,op=1,sha=50:54:00:00:00:05,tha=00:00:00:00:00:00)'
+ovs-appctl netdev-dummy/receive p2 'in_port(1),eth(src=50:54:00:00:00:07,dst=FF:FF:FF:FF:FF:FF),eth_type(0x0806),arp(sip=192.168.0.1,tip=192.168.0.2,op=1,sha=50:54:00:00:00:07,tha=00:00:00:00:00:00)'
+ovs-appctl netdev-dummy/receive p1 'in_port(2),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)'
+ovs-appctl netdev-dummy/receive p2 'in_port(1),eth(src=50:54:00:00:00:07,dst=50:54:00:00:00:05),eth_type(0x0800),ipv4(src=192.168.0.2,dst=192.168.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=0,code=0)'
+ovs-appctl netdev-dummy/receive p2 'in_port(1),eth(src=50:54:00:00:00:07,dst=50:54:00:00:00:05),eth_type(0x86dd),ipv6(src=fe80::1,dst=fe80::2,label=0,proto=10,tclass=0x70,hlimit=128,frag=no)'
+
+dnl sleep long enough to get more than one counter sample
+dnl from each datasource so we can check sequence numbers
+for i in `seq 1 30`; do
+ ovs-appctl time/warp 100
+done
+OVS_VSWITCHD_STOP
+ovs-appctl -t test-sflow exit
+
+AT_CHECK([[sort sflow.log | $EGREP 'HEADER|ERROR' | sed 's/ /\
+ /g']], [0], [dnl
+HEADER
+ dgramSeqNo=1
+ ds=127.0.0.1>0:1003
+ fsSeqNo=1
+ in_vlan=0
+ in_priority=0
+ out_vlan=0
+ out_priority=0
+ meanSkip=1
+ samplePool=1
+ dropEvents=0
+ in_ifindex=1003
+ in_format=0
+ out_ifindex=2
+ out_format=2
+ hdr_prot=1
+ pkt_len=64
+ stripped=4
+ hdr_len=60
+ hdr=FF-FF-FF-FF-FF-FF-50-54-00-00-00-07-08-06-00-01-08-00-06-04-00-01-50-54-00-00-00-07-C0-A8-00-01-00-00-00-00-00-00-C0-A8-00-02-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
+HEADER
+ dgramSeqNo=1
+ ds=127.0.0.1>0:1003
+ fsSeqNo=2
+ in_vlan=0
+ in_priority=0
+ out_vlan=0
+ out_priority=0
+ meanSkip=1
+ samplePool=2
+ dropEvents=0
+ in_ifindex=1003
+ in_format=0
+ out_ifindex=1004
+ out_format=0
+ hdr_prot=1
+ pkt_len=64
+ stripped=4
+ hdr_len=60
+ hdr=50-54-00-00-00-05-50-54-00-00-00-07-08-00-45-00-00-1C-00-00-00-00-40-01-F9-8D-C0-A8-00-02-C0-A8-00-01-00-00-FF-FF-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
+HEADER
+ dgramSeqNo=1
+ ds=127.0.0.1>0:1003
+ fsSeqNo=3
+ in_vlan=0
+ in_priority=0
+ out_vlan=0
+ out_priority=0
+ meanSkip=1
+ samplePool=3
+ dropEvents=0
+ in_ifindex=1003
+ in_format=0
+ out_ifindex=1004
+ out_format=0
+ hdr_prot=1
+ pkt_len=64
+ stripped=4
+ hdr_len=60
+ hdr=50-54-00-00-00-05-50-54-00-00-00-07-86-DD-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
+HEADER
+ dgramSeqNo=1
+ ds=127.0.0.1>0:1004
+ fsSeqNo=1
+ in_vlan=0
+ in_priority=0
+ out_vlan=0
+ out_priority=0
+ meanSkip=1
+ samplePool=1
+ dropEvents=0
+ in_ifindex=1004
+ in_format=0
+ out_ifindex=2
+ out_format=2
+ hdr_prot=1
+ pkt_len=64
+ stripped=4
+ hdr_len=60
+ hdr=FF-FF-FF-FF-FF-FF-50-54-00-00-00-05-08-06-00-01-08-00-06-04-00-01-50-54-00-00-00-05-C0-A8-00-02-00-00-00-00-00-00-C0-A8-00-01-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
+HEADER
+ dgramSeqNo=1
+ ds=127.0.0.1>0:1004
+ fsSeqNo=2
+ in_vlan=0
+ in_priority=0
+ out_vlan=0
+ out_priority=0
+ meanSkip=1
+ samplePool=2
+ dropEvents=0
+ in_ifindex=1004
+ in_format=0
+ out_ifindex=1003
+ out_format=0
+ hdr_prot=1
+ pkt_len=64
+ stripped=4
+ hdr_len=60
+ hdr=50-54-00-00-00-07-50-54-00-00-00-05-08-00-45-00-00-1C-00-00-00-00-40-01-F9-8D-C0-A8-00-01-C0-A8-00-02-08-00-F7-FF-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
+])
+
+AT_CHECK([[sort sflow.log | $EGREP 'IFCOUNTERS|ERROR' | head -6 | sed 's/ /\
+ /g']], [0], [dnl
+IFCOUNTERS
+ dgramSeqNo=2
+ ds=127.0.0.1>0:1002
+ csSeqNo=1
+ ifindex=1002
+ type=6
+ ifspeed=100000000
+ direction=0
+ status=3
+ in_octets=0
+ in_unicasts=0
+ in_multicasts=0
+ in_broadcasts=4294967295
+ in_discards=0
+ in_errors=0
+ in_unknownprotos=4294967295
+ out_octets=120
+ out_unicasts=2
+ out_multicasts=4294967295
+ out_broadcasts=4294967295
+ out_discards=0
+ out_errors=0
+ promiscuous=0
+IFCOUNTERS
+ dgramSeqNo=2
+ ds=127.0.0.1>0:1003
+ csSeqNo=1
+ ifindex=1003
+ type=6
+ ifspeed=100000000
+ direction=0
+ status=0
+ in_octets=98
+ in_unicasts=3
+ in_multicasts=0
+ in_broadcasts=4294967295
+ in_discards=0
+ in_errors=0
+ in_unknownprotos=4294967295
+ out_octets=120
+ out_unicasts=2
+ out_multicasts=4294967295
+ out_broadcasts=4294967295
+ out_discards=0
+ out_errors=0
+ promiscuous=0
+IFCOUNTERS
+ dgramSeqNo=2
+ ds=127.0.0.1>0:1004
+ csSeqNo=1
+ ifindex=1004
+ type=6
+ ifspeed=100000000
+ direction=0
+ status=0
+ in_octets=84
+ in_unicasts=2
+ in_multicasts=0
+ in_broadcasts=4294967295
+ in_discards=0
+ in_errors=0
+ in_unknownprotos=4294967295
+ out_octets=180
+ out_unicasts=3
+ out_multicasts=4294967295
+ out_broadcasts=4294967295
+ out_discards=0
+ out_errors=0
+ promiscuous=0
+IFCOUNTERS
+ dgramSeqNo=3
+ ds=127.0.0.1>0:1002
+ csSeqNo=2
+ ifindex=1002
+ type=6
+ ifspeed=100000000
+ direction=0
+ status=3
+ in_octets=0
+ in_unicasts=0
+ in_multicasts=0
+ in_broadcasts=4294967295
+ in_discards=0
+ in_errors=0
+ in_unknownprotos=4294967295
+ out_octets=120
+ out_unicasts=2
+ out_multicasts=4294967295
+ out_broadcasts=4294967295
+ out_discards=0
+ out_errors=0
+ promiscuous=0
+IFCOUNTERS
+ dgramSeqNo=3
+ ds=127.0.0.1>0:1003
+ csSeqNo=2
+ ifindex=1003
+ type=6
+ ifspeed=100000000
+ direction=0
+ status=0
+ in_octets=98
+ in_unicasts=3
+ in_multicasts=0
+ in_broadcasts=4294967295
+ in_discards=0
+ in_errors=0
+ in_unknownprotos=4294967295
+ out_octets=120
+ out_unicasts=2
+ out_multicasts=4294967295
+ out_broadcasts=4294967295
+ out_discards=0
+ out_errors=0
+ promiscuous=0
+IFCOUNTERS
+ dgramSeqNo=3
+ ds=127.0.0.1>0:1004
+ csSeqNo=2
+ ifindex=1004
+ type=6
+ ifspeed=100000000
+ direction=0
+ status=0
+ in_octets=84
+ in_unicasts=2
+ in_multicasts=0
+ in_broadcasts=4294967295
+ in_discards=0
+ in_errors=0
+ in_unknownprotos=4294967295
+ out_octets=180
+ out_unicasts=3
+ out_multicasts=4294967295
+ out_broadcasts=4294967295
+ out_discards=0
+ out_errors=0
+ promiscuous=0
+])
+AT_CLEANUP
+
+
+
+dnl Test that basic NetFlow reports flow statistics correctly:
+dnl - The initial packet of a flow are correctly accounted.
+dnl - Later packets within a flow are correctly accounted.
+dnl - Flow actions changing (in this case, due to MAC learning)
+dnl cause a record to be sent.
+AT_SETUP([ofproto-dpif - NetFlow flow expiration])
+
+AT_CHECK([perl $srcdir/choose-port.pl], [0], [stdout])
+NETFLOW_PORT=`cat stdout`
+
+OVS_VSWITCHD_START([set Bridge br0 fail-mode=standalone])
+ADD_OF_PORTS([br0], 1, 2)
+ovs-vsctl \
+ set Bridge br0 netflow=@nf -- \
+ --id=@nf create NetFlow targets=\"127.0.0.1:$NETFLOW_PORT\" \
+ engine_id=1 engine_type=2 active_timeout=30 add-id-to-interface=false
+
+ON_EXIT([kill `cat test-netflow.pid`])
+AT_CHECK([test-netflow --detach --no-chdir --pidfile $NETFLOW_PORT:127.0.0.1 > netflow.log])
+AT_CAPTURE_FILE([netflow.log])
+
+for delay in 1000 30000; do
+ ovs-appctl netdev-dummy/receive p1 'in_port(2),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)'
+ ovs-appctl netdev-dummy/receive p2 'in_port(1),eth(src=50:54:00:00:00:07,dst=50:54:00:00:00:05),eth_type(0x0800),ipv4(src=192.168.0.2,dst=192.168.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=0,code=0)'
+
+ ovs-appctl time/warp $delay
+done
+
+sleep 1
+OVS_VSWITCHD_STOP
+ovs-appctl -t test-netflow exit
+
+AT_CHECK([[sed -e 's/, uptime [0-9]*//
+s/, now [0-9.]*//
+s/time \([0-9]*\)\.\.\.\1$/time <moment>/
+s/time [0-9]*\.\.\.[0-9]*/time <range>/
+' netflow.log | sort]], [0],
+ [
+header: v5, seq 0, engine 2,1
+header: v5, seq 1, engine 2,1
+seq 0: 192.168.0.1 > 192.168.0.2, if 1 > 65535, 1 pkts, 60 bytes, ICMP 8:0, time <moment>
+seq 1: 192.168.0.1 > 192.168.0.2, if 1 > 2, 1 pkts, 60 bytes, ICMP 8:0, time <moment>
+seq 1: 192.168.0.2 > 192.168.0.1, if 2 > 1, 2 pkts, 120 bytes, ICMP 0:0, time <range>
+])
+AT_CLEANUP
+
+dnl Test that basic NetFlow reports active expirations correctly.
+AT_SETUP([ofproto-dpif - NetFlow active expiration])
+
+AT_CHECK([perl $srcdir/choose-port.pl], [0], [stdout])
+NETFLOW_PORT=`cat stdout`
+
+OVS_VSWITCHD_START([set Bridge br0 fail-mode=standalone])
+ADD_OF_PORTS([br0], 1, 2)
+ovs-vsctl \
+ set Bridge br0 netflow=@nf -- \
+ --id=@nf create NetFlow targets=\"127.0.0.1:$NETFLOW_PORT\" \
+ engine_id=1 engine_type=2 active_timeout=10 add-id-to-interface=false
+
+ON_EXIT([kill `cat test-netflow.pid`])
+AT_CHECK([test-netflow --detach --no-chdir --pidfile $NETFLOW_PORT:127.0.0.1 > netflow.log])AT_CAPTURE_FILE([netflow.log])
+
+AT_CHECK([ovs-appctl time/stop])
+n=1
+while test $n -le 60; do
+ n=`expr $n + 1`
+
+ ovs-appctl netdev-dummy/receive p1 'in_port(2),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=1234,dst=80)'
+ ovs-appctl netdev-dummy/receive p2 'in_port(1),eth(src=50:54:00:00:00:07,dst=50:54:00:00:00:05),eth_type(0x0800),ipv4(src=192.168.0.2,dst=192.168.0.1,proto=6,tos=0,ttl=64,frag=no),tcp(src=80,dst=1234)'
+
+ ovs-appctl time/warp 1000
+done
+
+ovs-appctl time/warp 10000
+
+sleep 1
+OVS_VSWITCHD_STOP
+ovs-appctl -t test-netflow exit
+
+# Count the number of reported packets:
+# - From source to destination before MAC learning kicks in (just one).
+# - From source to destination after that.
+# - From destination to source.
+n_learn=0
+n_in=0
+n_out=0
+n_other=0
+n_recs=0
+none=0
+while read line; do
+ pkts=`echo "$line" | sed 's/.*, \([[0-9]]*\) pkts,.*/\1/'`
+ case $pkts in
+ [[0-9]]*) ;;
+ *) continue ;;
+ esac
+
+ case $line in
+ "seq "*": 192.168.0.1 > 192.168.0.2, if 1 > 65535, "*" pkts, "*" bytes, TCP 1234 > 80, time "*)
+ counter=n_learn
+ ;;
+ "seq "*": 192.168.0.1 > 192.168.0.2, if 1 > 2, "*" pkts, "*" bytes, TCP 1234 > 80, time "*)
+ counter=n_in
+ ;;
+ "seq "*": 192.168.0.2 > 192.168.0.1, if 2 > 1, "*" pkts, "*" bytes, TCP 80 > 1234, time "*)
+ counter=n_out
+ ;;
+ *)
+ counter=n_other
+ ;;
+ esac
+ eval $counter=\`expr \$$counter + \$pkts\`
+ n_recs=`expr $n_recs + 1`
+done < netflow.log
+
+# There should be exactly 1 MAC learning packet,
+# exactly 59 other packets in that direction,
+# and exactly 60 packets in the other direction.
+AT_CHECK([echo $n_learn $n_in $n_out $n_other], [0], [1 59 60 0
+])
+
+# There should be 1 expiration for MAC learning,
+# at least 5 active and a final expiration in one direction,
+# and at least 5 active and a final expiration in the other direction.
+echo $n_recs
+AT_CHECK([test $n_recs -ge 13])
+
+AT_CLEANUP
+
+AT_SETUP([idle_age and hard_age increase over time])
+OVS_VSWITCHD_START
+
+# get_ages DURATION HARD IDLE
+#
+# Fetch the flow duration, hard age, and idle age into the variables
+# whose names are given as arguments. Rounds DURATION down to the
+# nearest integer. If hard_age doesn't appear in the output, sets
+# HARD to "none". If idle_age doesn't appear in the output, sets IDLE
+# to 0.
+get_ages () {
+ AT_CHECK([ovs-ofctl dump-flows br0], [0], [stdout])
+
+ duration=`sed -n 's/.*duration=\([[0-9]]*\)\(\.[[0-9]]*\)\{0,1\}s.*/\1/p' stdout`
+ AT_CHECK([[expr X"$duration" : 'X[0-9][0-9]*$']], [0], [ignore])
+ AS_VAR_COPY([$1], [duration])
+
+ hard=`sed -n 's/.*hard_age=\([[0-9]]*\),.*/\1/p' stdout`
+ if test X"$hard" = X; then
+ hard=none
+ else
+ AT_CHECK([[expr X"$hard" : 'X[0-9][0-9]*$']], [0], [ignore])
+ fi
+ AS_VAR_COPY([$2], [hard])
+
+ idle=`sed -n 's/.*idle_age=\([[0-9]]*\),.*/\1/p' stdout`
+ if test X"$idle" = X; then
+ idle=0
+ else
+ AT_CHECK([[expr X"$idle" : 'X[0-9][0-9]*$']], [0], [ignore])
+ fi
+ AS_VAR_COPY([$3], [idle])
+}
+
+# Add a flow and get its initial hard and idle age.
+AT_CHECK([ovs-ofctl add-flow br0 hard_timeout=199,idle_timeout=188,actions=drop])
+get_ages duration1 hard1 idle1
+
+# Warp time forward by 10 seconds, then modify the flow's actions.
+ovs-appctl time/warp 10000
+get_ages duration2 hard2 idle2
+AT_CHECK([ovs-ofctl mod-flows br0 actions=flood])
+
+# Warp time forward by 10 seconds.
+ovs-appctl time/warp 10000
+get_ages duration3 hard3 idle3
+
+# Warp time forward 10 more seconds, then pass some packets through the flow,
+# then warp forward a few more times because idle times are only updated
+# occasionally.
+ovs-appctl time/warp 10000
+ovs-appctl netdev-dummy/receive br0 'in_port(0),eth(src=50:54:00:00:00:07,dst=50:54:00:00:00:05),eth_type(0x0800),ipv4(src=192.168.0.2,dst=192.168.0.1,proto=6,tos=0,ttl=64,frag=no),tcp(src=80,dst=1234)'
+ovs-appctl time/warp 1000
+ovs-appctl time/warp 1000
+ovs-appctl time/warp 1000
+get_ages duration4 hard4 idle4
+
+printf "duration: %4s => %4s => %4s => %4s\n" $duration1 $duration2 $duration3 $duration4
+printf "hard_age: %4s => %4s => %4s => %4s\n" $hard1 $hard2 $hard3 $hard4
+printf "idle_age: %4s => %4s => %4s => %4s\n" $idle1 $idle2 $idle3 $idle4
+
+# Duration should increase steadily over time.
+AT_CHECK([test $duration1 -lt $duration2])
+AT_CHECK([test $duration2 -lt $duration3])
+AT_CHECK([test $duration3 -lt $duration4])
+
+# Hard age should be "none" initially because it's the same as flow_duration,
+# then it should increase.
+AT_CHECK([test $hard1 = none])
+AT_CHECK([test $hard2 = none])
+AT_CHECK([test $hard3 != none])
+AT_CHECK([test $hard4 != none])
+AT_CHECK([test $hard3 -lt $hard4])
+
+# Idle age should increase from 1 to 2 to 3, then decrease.
+AT_CHECK([test $idle1 -lt $idle2])
+AT_CHECK([test $idle2 -lt $idle3])
+AT_CHECK([test $idle3 -gt $idle4])
+
+# Check some invariant relationships.
+AT_CHECK([test $duration1 = $idle1])
+AT_CHECK([test $duration2 = $idle2])
+AT_CHECK([test $duration3 = $idle3])
+AT_CHECK([test $idle3 -gt $hard3])
+AT_CHECK([test $idle4 -lt $hard4])
+AT_CHECK([test $hard4 -lt $duration4])
+
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+AT_SETUP([ofproto-dpif - fin_timeout])
+OVS_VSWITCHD_START
+AT_DATA([flows.txt], [dnl
+in_port=1 actions=output:2
+in_port=2 actions=mod_vlan_vid:17,output:1
+])
+AT_CHECK([ovs-ofctl add-flow br0 'idle_timeout=60,actions=fin_timeout(idle_timeout=5)'])
+AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip], [0],
+[NXST_FLOW reply:
+ idle_timeout=60, actions=fin_timeout(idle_timeout=5)
+])
+# Check that a TCP SYN packet does not change the timeout. (Because
+# flow stats updates are mainly what implements the fin_timeout
+# feature, we warp forward a couple of times to ensure that flow stats
+# run before re-checking the flow table.)
+AT_CHECK([ovs-appctl netdev-dummy/receive br0 0021853763af0026b98cb0f908004500003c2e2440004006465dac11370dac11370b828b0016751e267b00000000a00216d017360000020405b40402080a2d25085f0000000001030307], [0], [success
+])
+AT_CHECK([ovs-appctl time/warp 1000 && ovs-appctl time/warp 1000], [0], [warped
+warped
+])
+AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip], [0],
+[NXST_FLOW reply:
+ n_packets=1, n_bytes=74, idle_timeout=60, actions=fin_timeout(idle_timeout=5)
+])
+# Check that a TCP FIN packet does change the timeout.
+AT_CHECK([ovs-appctl netdev-dummy/receive br0 0021853763af0026b98cb0f90800451000342e3e40004006463bac11370dac11370b828b0016751e319dfc96399b801100717ae800000101080a2d250a9408579588], [0], [success
+])
+AT_CHECK([ovs-appctl time/warp 1000 && ovs-appctl time/warp 1000], [0], [warped
+warped
+])
+AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip], [0],
+[NXST_FLOW reply:
+ n_packets=2, n_bytes=140, idle_timeout=5, actions=fin_timeout(idle_timeout=5)
+])
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+AT_SETUP([ofproto-dpif - ovs-appctl dpif/dump-dps])
+OVS_VSWITCHD_START([add-br br1 -- set bridge br1 datapath-type=dummy])
+ADD_OF_PORTS([br0], [1], [2])
+ADD_OF_PORTS([br1], [3])
+
+AT_CHECK([ovs-appctl dpif/dump-dps], [0], [dnl
+dummy@br0
+dummy@br1
+])
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+AT_SETUP([ofproto-dpif - ovs-appctl dpif/show])
+OVS_VSWITCHD_START([add-br br1 -- set bridge br1 datapath-type=dummy])
+ADD_OF_PORTS([br0], [1], [2])
+ADD_OF_PORTS([br1], [3])
+
+AT_CHECK([ovs-appctl dpif/show], [0], [dnl
+br0 (dummy@ovs-dummy):
+ lookups: hit:0 missed:0
+ flows: cur: 0, avg: 0.000, max: 0, life span: 0(ms)
+ overall avg: add rate: 0.000/min, del rate: 0.000/min
+ br0 65534/100: (dummy)
+ p1 1/1: (dummy)
+ p2 2/2: (dummy)
+br1 (dummy@ovs-dummy):
+ lookups: hit:0 missed:0
+ flows: cur: 0, avg: 0.000, max: 0, life span: 0(ms)
+ overall avg: add rate: 0.000/min, del rate: 0.000/min
+ br1 65534/101: (dummy)
+ p3 3/3: (dummy)
+])
+
+AT_CHECK([ovs-appctl dpif/show br0], [0], [dnl
+br0 (dummy@ovs-dummy):
+ lookups: hit:0 missed:0
+ flows: cur: 0, avg: 0.000, max: 0, life span: 0(ms)
+ overall avg: add rate: 0.000/min, del rate: 0.000/min
+ br0 65534/100: (dummy)
+ p1 1/1: (dummy)
+ p2 2/2: (dummy)
+])
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+AT_SETUP([ofproto-dpif - ovs-appctl dpif/dump-flows])
+OVS_VSWITCHD_START([add-br br1 -- \
+ set bridge br1 datapath-type=dummy fail-mode=secure])
+ADD_OF_PORTS([br0], [1], [2])
+ADD_OF_PORTS([br1], [3])
+
+AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)'], [0], [success
+])
+AT_CHECK([ovs-appctl netdev-dummy/receive p2 'in_port(2),eth(src=50:54:00:00:00:07,dst=50:54:00:00:00:05),eth_type(0x0800),ipv4(src=192.168.0.2,dst=192.168.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=0,code=0)'], [0], [success
+])
+AT_CHECK([ovs-appctl netdev-dummy/receive p3 'in_port(3),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.0.0.2,dst=10.0.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)'], [0], [success
+])
+
+AT_CHECK([ovs-appctl dpif/dump-flows br0 | sort | STRIP_USED], [0], [dnl
+in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0), packets:0, bytes:0, used:0.0s, actions:userspace(pid=0,slow_path(controller))
+in_port(2),eth(src=50:54:00:00:00:07,dst=50:54:00:00:00:05),eth_type(0x0800),ipv4(src=192.168.0.2,dst=192.168.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=0,code=0), packets:0, bytes:0, used:0.0s, actions:userspace(pid=0,slow_path(controller))
+])
+
+AT_CHECK([ovs-appctl dpif/dump-flows br1 | sort | STRIP_USED], [0], [dnl
+in_port(3),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.0.0.2,dst=10.0.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0), packets:0, bytes:0, used:0.0s, actions:userspace(pid=0,slow_path(controller))
+])
+
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+AT_SETUP([ofproto-dpif - ovs-appctl dpif/del-flows])
+OVS_VSWITCHD_START([add-br br1 -- \
+ set bridge br1 datapath-type=dummy fail-mode=secure])
+ADD_OF_PORTS([br0], [1], [2])
+ADD_OF_PORTS([br1], [3])
+
+AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)'], [0], [success
+])
+AT_CHECK([ovs-appctl netdev-dummy/receive p2 'in_port(2),eth(src=50:54:00:00:00:07,dst=50:54:00:00:00:05),eth_type(0x0800),ipv4(src=192.168.0.2,dst=192.168.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=0,code=0)'], [0], [success
+])
+AT_CHECK([ovs-appctl netdev-dummy/receive p3 'in_port(3),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.0.0.2,dst=10.0.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)'], [0], [success
+])
+
+AT_CHECK([ovs-appctl dpif/dump-flows br0 | sort | STRIP_USED], [0], [dnl
+in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0), packets:0, bytes:0, used:0.0s, actions:userspace(pid=0,slow_path(controller))
+in_port(2),eth(src=50:54:00:00:00:07,dst=50:54:00:00:00:05),eth_type(0x0800),ipv4(src=192.168.0.2,dst=192.168.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=0,code=0), packets:0, bytes:0, used:0.0s, actions:userspace(pid=0,slow_path(controller))
+])
+
+AT_CHECK([ovs-appctl dpif/dump-flows br1 | sort | STRIP_USED], [0], [dnl
+in_port(3),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.0.0.2,dst=10.0.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0), packets:0, bytes:0, used:0.0s, actions:userspace(pid=0,slow_path(controller))
+])
+
+AT_CHECK([ovs-appctl dpif/del-flows br0])
+AT_CHECK([ovs-appctl dpif/dump-flows br0 | sort | STRIP_USED], [0], [dnl
+])
+
+AT_CHECK([ovs-appctl dpif/dump-flows br1 | sort | STRIP_USED], [0], [dnl
+in_port(3),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.0.0.2,dst=10.0.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0), packets:0, bytes:0, used:0.0s, actions:userspace(pid=0,slow_path(controller))
+])
+
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+AT_SETUP([ofproto-dpif - patch ports])
+OVS_VSWITCHD_START([add-br br1 \
+-- set bridge br1 datapath-type=dummy fail-mode=secure \
+-- add-port br1 pbr1 -- set int pbr1 type=patch options:peer=pbr0 \
+-- add-port br0 pbr0 -- set int pbr0 type=patch options:peer=pbr1])
+
+ADD_OF_PORTS([br0], [2])
+ADD_OF_PORTS([br1], [3])
+
+AT_CHECK([ovs-ofctl add-flow br0 actions=LOCAL,output:1,output:2])
+AT_CHECK([ovs-ofctl add-flow br1 actions=LOCAL,output:1,output:3])
+
+for i in $(seq 1 10); do
+ ovs-appctl netdev-dummy/receive br0 'in_port(100),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)'
+done
+
+for i in $(seq 1 5); do
+ ovs-appctl netdev-dummy/receive br1 'in_port(101),eth(src=50:54:00:00:00:07,dst=50:54:00:00:00:05),eth_type(0x0800),ipv4(src=192.168.0.2,dst=192.168.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)'
+done
+
+AT_CHECK([ovs-appctl time/warp 1000 && ovs-appctl time/warp 1000], [0], [warped
+warped
+])
+
+AT_CHECK([ovs-appctl dpif/show], [0], [dnl
+br0 (dummy@ovs-dummy):
+ lookups: hit:9 missed:1
+ flows: cur: 1, avg: 1.000, max: 1, life span: 0(ms)
+ overall avg: add rate: 0.000/min, del rate: 0.000/min
+ br0 65534/100: (dummy)
+ p2 2/2: (dummy)
+ pbr0 1/none: (patch: peer=pbr1)
+br1 (dummy@ovs-dummy):
+ lookups: hit:4 missed:1
+ flows: cur: 1, avg: 1.000, max: 1, life span: 0(ms)
+ overall avg: add rate: 0.000/min, del rate: 0.000/min
+ br1 65534/101: (dummy)
+ p3 3/3: (dummy)
+ pbr1 1/none: (patch: peer=pbr0)
+])
+
+AT_CHECK([ovs-appctl dpif/dump-flows br0 | STRIP_USED], [0], [dnl
+in_port(100),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0), packets:9, bytes:540, used:0.0s, actions:101,3,2
+]),
+AT_CHECK([ovs-appctl dpif/dump-flows br1 | STRIP_USED], [0], [dnl
+in_port(101),eth(src=50:54:00:00:00:07,dst=50:54:00:00:00:05),eth_type(0x0800),ipv4(src=192.168.0.2,dst=192.168.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0), packets:4, bytes:240, used:0.0s, actions:100,2,3
+])
+
+AT_CHECK([ovs-ofctl dump-ports br0 pbr0], [0], [dnl
+OFPST_PORT reply (xid=0x4): 1 ports
+ port 1: rx pkts=5, bytes=300, drop=0, errs=0, frame=0, over=0, crc=0
+ tx pkts=10, bytes=600, drop=0, errs=0, coll=0
+])
+
+AT_CHECK([ovs-ofctl dump-ports br1 pbr1], [0], [dnl
+OFPST_PORT reply (xid=0x4): 1 ports
+ port 1: rx pkts=10, bytes=600, drop=0, errs=0, frame=0, over=0, crc=0
+ tx pkts=5, bytes=300, drop=0, errs=0, coll=0
+])
+
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+AT_SETUP([ofproto-dpif - ovs-appctl dpif/show rates])
+OVS_VSWITCHD_START([set Bridge br0 fail-mode=secure])
+ADD_OF_PORTS([br0], 1, 2)
+
+AT_CHECK([ovs-ofctl add-flow br0 actions=LOCAL,output:1,output:2])
+
+for i in $(seq 1 61); do
+ ovs-appctl netdev-dummy/receive br0 'in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)'
+ ovs-appctl time/warp 10000
+ ovs-appctl time/warp 50000
+done
+
+AT_CHECK([ovs-appctl time/warp 10000], [0], [warped
+])
+
+AT_CHECK([ovs-appctl dpif/show | sed 's/ 10[[0-9]]\{3\}(ms)$/ 10000(ms)/'], [0], [dnl
+br0 (dummy@ovs-dummy):
+ lookups: hit:0 missed:61
+ flows: cur: 0, avg: 1.000, max: 1, life span: 10000(ms)
+ hourly avg: add rate: 0.641/min, del rate: 0.635/min
+ overall avg: add rate: 1.000/min, del rate: 0.984/min
+ br0 65534/100: (dummy)
+ p1 1/1: (dummy)
+ p2 2/2: (dummy)
+])
+
+OVS_VSWITCHD_STOP
+AT_CLEANUP