AT_BANNER([ofproto-dpif])

m4_divert_push([PREPARE_TESTS])

# Helper function to check the spread of dp_hash flows over buckets in the datapath
check_dpflow_stats () {
    min_flows=$1
    min_buckets=$2
    dpflows=`cat`
    if [[ $# -eq 3 ]]; then
        echo "$dpflows" | grep "actions:hash"
        n_flows=`echo "$dpflows" | grep -c dp_hash`
        n_buckets=`echo "$dpflows" | grep dp_hash | grep -o "actions:[[0-9]]*" | sort | uniq -c | wc -l`
    else
        n_flows=`echo "$dpflows" | wc -l`
        n_buckets=`echo "$dpflows" | grep -o "actions:[[0-9]]*" | sort | uniq -c | wc -l`
    fi
    if [[ $n_flows -ge $min_flows ]]; then flows=ok; else flows=nok; fi
    if [[ $n_buckets -ge $min_buckets ]]; then buckets=ok; else buckets=nok; fi
    echo "n_flows=$flows n_buckets=$buckets"
}

m4_divert_pop([PREPARE_TESTS])


AT_SETUP([ofproto-dpif - revalidator/wait])
OVS_VSWITCHD_START
AT_CHECK([ovs-appctl revalidator/wait])
OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - active-backup bonding (with primary)])

dnl Create br0 with members p1, p2 and p7, creating bond0 with p1 and
dnl    p2 (p1 as primary) and br1 with members p3, p4 and p8.
dnl toggle p1,p2 of bond0 up and down to test bonding in active-backup mode.
dnl With p1 down and p2 up/active, bring p1 back up.  Since p1 is the primary,
dnl it should become active.
OVS_VSWITCHD_START(
  [add-bond br0 bond0 p1 p2 bond_mode=active-backup \
                other_config:bond-primary=p1 -- \
   set interface p1 type=dummy options:pstream=punix:$OVS_RUNDIR/p1.sock ofport_request=1 -- \
   set interface p2 type=dummy options:pstream=punix:$OVS_RUNDIR/p2.sock ofport_request=2 -- \
   add-port br0 p7 -- set interface p7 ofport_request=7 type=dummy -- \
   add-br br1 -- \
   set bridge br1 other-config:hwaddr=aa:66:aa:66:00:00 -- \
   set bridge br1 datapath-type=dummy other-config:datapath-id=1234 \
                  fail-mode=secure -- \
   add-port br1 p3 -- set interface p3 type=dummy options:stream=unix:$OVS_RUNDIR/p1.sock ofport_request=3 -- \
   add-port br1 p4 -- set interface p4 type=dummy options:stream=unix:$OVS_RUNDIR/p2.sock ofport_request=4 -- \
   add-port br1 p8 -- set interface p8 ofport_request=8 type=dummy --])
AT_CHECK([ovs-appctl vlog/set dpif:dbg dpif_netdev:dbg])
WAIT_FOR_DUMMY_PORTS([p3], [p4])
OVS_WAIT_UNTIL([test -n "`ovs-appctl bond/show | grep 'active-backup primary: p1'`"])


AT_CHECK([ovs-ofctl add-flow br0 action=normal])
AT_CHECK([ovs-ofctl add-flow br1 action=normal])
ovs-appctl netdev-dummy/set-admin-state up
ovs-appctl time/warp 100
ovs-appctl netdev-dummy/set-admin-state p2 down
ovs-appctl time/stop
ovs-appctl time/warp 100
AT_CHECK([ovs-appctl netdev-dummy/receive p7 'in_port(7),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)'])
AT_CHECK([ovs-appctl netdev-dummy/receive p7 'in_port(7),eth(src=50:54:00:00:00:0b,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(src=10.0.0.3,dst=10.0.0.4,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)'])
ovs-appctl time/warp 100
ovs-appctl netdev-dummy/set-admin-state p2 up
ovs-appctl netdev-dummy/set-admin-state p1 down
ovs-appctl time/warp 100
AT_CHECK([ovs-appctl netdev-dummy/receive p7 'in_port(7),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0d),eth_type(0x0800),ipv4(src=10.0.0.5,dst=10.0.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)'])
AT_CHECK([ovs-appctl netdev-dummy/receive p7 'in_port(7),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0e),eth_type(0x0800),ipv4(src=10.0.0.6,dst=10.0.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)'])
ovs-appctl time/warp 2000 100
AT_CHECK([ovs-appctl dpctl/dump-flows | grep 'in_port([[348]])' | strip_xout], [0], [dnl
recirc_id(0),in_port(3),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(frag=no), packets:0, bytes:0, used:never, actions: <del>
recirc_id(0),in_port(3),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:0b,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(frag=no), packets:0, bytes:0, used:never, actions: <del>
recirc_id(0),in_port(4),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0d),eth_type(0x0800),ipv4(frag=no), packets:0, bytes:0, used:never, actions: <del>
recirc_id(0),in_port(4),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0e),eth_type(0x0800),ipv4(frag=no), packets:0, bytes:0, used:never, actions: <del>
recirc_id(0),in_port(4),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:09,dst=ff:ff:ff:ff:ff:ff),eth_type(0x8035), packets:0, bytes:0, used:never, actions: <del>
recirc_id(0),in_port(4),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:0b,dst=ff:ff:ff:ff:ff:ff),eth_type(0x8035), packets:0, bytes:0, used:never, actions: <del>
])

ovs-appctl netdev-dummy/set-admin-state p1 up
ovs-appctl time/warp 100
OVS_WAIT_UNTIL_EQUAL([ovs-appctl bond/show | STRIP_RECIRC_ID | STRIP_ACTIVE_MEMBER_MAC], [dnl
---- bond0 ----
bond_mode: active-backup
bond may use recirculation: no, <del>
bond-hash-basis: 0
lb_output action: disabled, bond-id: -1
updelay: 0 ms
downdelay: 0 ms
lacp_status: off
lacp_fallback_ab: false
active-backup primary: p1
<active member mac del>

member p1: enabled
  active member
  may_enable: true

member p2: enabled
  may_enable: true
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - active-backup bonding (primary validation)])
dnl Make a switch with 3 ports in a bond, so that when we delete one of
dnl the ports from the bond, there are still 2 ports left and the bond
dnl remains functional.
OVS_VSWITCHD_START(
  [add-bond br0 bond0 p1 p2 p3 bond_mode=active-backup \
                other_config:bond-primary=p1 -- \
   set interface p1 type=dummy options:pstream=punix:$OVS_RUNDIR/p1.sock ofport_request=1 -- \
   set interface p2 type=dummy options:pstream=punix:$OVS_RUNDIR/p2.sock ofport_request=2 -- \
   set interface p3 type=dummy options:pstream=punix:$OVS_RUNDIR/p3.sock ofport_request=3 -- \
   add-port br0 p7 -- set interface p7 ofport_request=7 type=dummy --])
AT_CHECK([ovs-appctl vlog/set dpif:dbg dpif_netdev:dbg])

dnl Make sure the initial primary member is set
OVS_WAIT_UNTIL([test -n "`ovs-appctl bond/show | grep 'active-backup primary: p1'`"])

dnl Down the primary member and verify that we switched.  Then
dnl bring the primary back and verify that we switched back to the
dnl primary.
ovs-appctl netdev-dummy/set-admin-state p1 down
ovs-appctl time/warp 100
OVS_WAIT_UNTIL([test -n "`ovs-appctl bond/show | fgrep 'member p1: disabled'`"])
ovs-appctl netdev-dummy/set-admin-state p1 up
ovs-appctl time/warp 100
OVS_WAIT_UNTIL_EQUAL([ovs-appctl bond/show | STRIP_RECIRC_ID | STRIP_ACTIVE_MEMBER_MAC], [dnl
---- bond0 ----
bond_mode: active-backup
bond may use recirculation: no, <del>
bond-hash-basis: 0
lb_output action: disabled, bond-id: -1
updelay: 0 ms
downdelay: 0 ms
lacp_status: off
lacp_fallback_ab: false
active-backup primary: p1
<active member mac del>

member p1: enabled
  active member
  may_enable: true

member p2: enabled
  may_enable: true

member p3: enabled
  may_enable: true
])

dnl Now delete the primary and verify that the output shows that the
dnl primary is no longer an member
ovs-vsctl --id=@p1 get Interface p1 -- remove Port bond0 interfaces @p1
ovs-appctl time/warp 100
OVS_WAIT_UNTIL([test -n "`ovs-appctl bond/show | fgrep 'active-backup primary: p1 (no such member)'`"])

dnl Now re-add the primary and verify that the output shows that the
dnl primary is available again.
dnl
dnl First, get the UUIDs of the members that exist on bond0.
dnl Strip the trailing ] so that we can add a new UUID to the end.
uuids=`ovs-vsctl get Port bond0 interfaces | sed -e 's/]//'`
dnl Create a new port "p1" and add its UUID to the set of members
dnl on bond0.
ovs-vsctl \
   --id=@p1 create Interface name=p1 type=dummy options:pstream=punix:$OVS_RUNDIR/p1.sock ofport_request=1 -- \
   set Port bond0 interfaces="$uuids, @p1]"
ovs-appctl time/warp 100
OVS_WAIT_UNTIL_EQUAL([ovs-appctl bond/show | STRIP_RECIRC_ID | STRIP_ACTIVE_MEMBER_MAC], [dnl
---- bond0 ----
bond_mode: active-backup
bond may use recirculation: no, <del>
bond-hash-basis: 0
lb_output action: disabled, bond-id: -1
updelay: 0 ms
downdelay: 0 ms
lacp_status: off
lacp_fallback_ab: false
active-backup primary: p1
<active member mac del>

member p1: enabled
  active member
  may_enable: true

member p2: enabled
  may_enable: true

member p3: enabled
  may_enable: true
])

dnl Switch to another primary
ovs-vsctl set port bond0 other_config:bond-primary=p2
ovs-appctl time/warp 100
OVS_WAIT_UNTIL_EQUAL([ovs-appctl bond/show | STRIP_RECIRC_ID | STRIP_ACTIVE_MEMBER_MAC], [dnl
---- bond0 ----
bond_mode: active-backup
bond may use recirculation: no, <del>
bond-hash-basis: 0
lb_output action: disabled, bond-id: -1
updelay: 0 ms
downdelay: 0 ms
lacp_status: off
lacp_fallback_ab: false
active-backup primary: p2
<active member mac del>

member p1: enabled
  may_enable: true

member p2: enabled
  active member
  may_enable: true

member p3: enabled
  may_enable: true
])

dnl Remove the "bond-primary" config directive from the bond.
AT_CHECK([ovs-vsctl remove Port bond0 other_config bond-primary])
ovs-appctl time/warp 100
OVS_WAIT_UNTIL_EQUAL([ovs-appctl bond/show | STRIP_RECIRC_ID | STRIP_ACTIVE_MEMBER_MAC], [dnl
---- bond0 ----
bond_mode: active-backup
bond may use recirculation: no, <del>
bond-hash-basis: 0
lb_output action: disabled, bond-id: -1
updelay: 0 ms
downdelay: 0 ms
lacp_status: off
lacp_fallback_ab: false
active-backup primary: <none>
<active member mac del>

member p1: enabled
  may_enable: true

member p2: enabled
  active member
  may_enable: true

member p3: enabled
  may_enable: true
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - active-backup bonding (without primary)])
dnl Create br0 with members p1, p2 and p7, creating bond0 with p1 and p2
dnl    and br1 with members p3, p4 and p8.
dnl toggle p1,p2 of bond0 up and down to test bonding in active-backup mode.
OVS_VSWITCHD_START(
  [add-bond br0 bond0 p1 p2 bond_mode=active-backup --\
   set interface p1 type=dummy options:pstream=punix:$OVS_RUNDIR/p1.sock ofport_request=1 -- \
   set interface p2 type=dummy options:pstream=punix:$OVS_RUNDIR/p2.sock ofport_request=2 -- \
   add-port br0 p7 -- set interface p7 ofport_request=7 type=dummy -- \
   add-br br1 -- \
   set bridge br1 other-config:hwaddr=aa:66:aa:66:00:00 -- \
   set bridge br1 datapath-type=dummy other-config:datapath-id=1234 \
                  fail-mode=secure -- \
   add-port br1 p3 -- set interface p3 type=dummy options:stream=unix:$OVS_RUNDIR/p1.sock ofport_request=3 -- \
   add-port br1 p4 -- set interface p4 type=dummy options:stream=unix:$OVS_RUNDIR/p2.sock ofport_request=4 -- \
   add-port br1 p8 -- set interface p8 ofport_request=8 type=dummy --])
AT_CHECK([ovs-appctl vlog/set dpif:dbg dpif_netdev:dbg])
WAIT_FOR_DUMMY_PORTS([p3], [p4])
OVS_WAIT_UNTIL([test -n "`ovs-appctl bond/show | grep 'active-backup primary: <none>'`"])

AT_CHECK([ovs-ofctl add-flow br0 action=normal])
AT_CHECK([ovs-ofctl add-flow br1 action=normal])
ovs-appctl netdev-dummy/set-admin-state up
ovs-appctl time/warp 100
ovs-appctl netdev-dummy/set-admin-state p2 down
ovs-appctl time/stop
ovs-appctl time/warp 100
AT_CHECK([ovs-appctl netdev-dummy/receive p7 'in_port(7),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)'])
AT_CHECK([ovs-appctl netdev-dummy/receive p7 'in_port(7),eth(src=50:54:00:00:00:0b,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(src=10.0.0.3,dst=10.0.0.4,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)'])
ovs-appctl time/warp 100
ovs-appctl netdev-dummy/set-admin-state p2 up
ovs-appctl netdev-dummy/set-admin-state p1 down
ovs-appctl time/warp 100
AT_CHECK([ovs-appctl netdev-dummy/receive p7 'in_port(7),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0d),eth_type(0x0800),ipv4(src=10.0.0.5,dst=10.0.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)'])
AT_CHECK([ovs-appctl netdev-dummy/receive p7 'in_port(7),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0e),eth_type(0x0800),ipv4(src=10.0.0.6,dst=10.0.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)'])
ovs-appctl time/warp 2000 100
AT_CHECK([ovs-appctl dpctl/dump-flows | grep 'in_port([[348]])' | strip_xout], [0], [dnl
recirc_id(0),in_port(3),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(frag=no), packets:0, bytes:0, used:never, actions: <del>
recirc_id(0),in_port(3),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:0b,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(frag=no), packets:0, bytes:0, used:never, actions: <del>
recirc_id(0),in_port(4),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0d),eth_type(0x0800),ipv4(frag=no), packets:0, bytes:0, used:never, actions: <del>
recirc_id(0),in_port(4),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0e),eth_type(0x0800),ipv4(frag=no), packets:0, bytes:0, used:never, actions: <del>
recirc_id(0),in_port(4),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:09,dst=ff:ff:ff:ff:ff:ff),eth_type(0x8035), packets:0, bytes:0, used:never, actions: <del>
recirc_id(0),in_port(4),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:0b,dst=ff:ff:ff:ff:ff:ff),eth_type(0x8035), packets:0, bytes:0, used:never, actions: <del>
])
OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - balance-slb bonding])
# Create br0 with members bond0(p1, p2, p3) and p7,
#    and br1 with members p4, p5, p6 and p8.
#    p1 <-> p4, p2 <-> p5, p3 <-> p6
# Send some traffic, make sure the traffic are spread based on source mac.
OVS_VSWITCHD_START(
  [add-bond br0 bond0 p1 p2 p3 bond_mode=balance-slb --\
   set interface p1 type=dummy options:pstream=punix:$OVS_RUNDIR/p1.sock ofport_request=1 -- \
   set interface p2 type=dummy options:pstream=punix:$OVS_RUNDIR/p2.sock ofport_request=2 -- \
   set interface p3 type=dummy options:pstream=punix:$OVS_RUNDIR/p3.sock ofport_request=3 -- \
   add-port br0 p7 -- set interface p7 ofport_request=7 type=dummy -- \
   add-br br1 -- \
   set bridge br1 other-config:hwaddr=aa:66:aa:66:00:00 -- \
   set bridge br1 datapath-type=dummy other-config:datapath-id=1234 \
                  fail-mode=secure -- \
   add-port br1 p4 -- set interface p4 type=dummy options:stream=unix:$OVS_RUNDIR/p1.sock ofport_request=4 -- \
   add-port br1 p5 -- set interface p5 type=dummy options:stream=unix:$OVS_RUNDIR/p2.sock ofport_request=5 -- \
   add-port br1 p6 -- set interface p6 type=dummy options:stream=unix:$OVS_RUNDIR/p3.sock ofport_request=6 -- \
   add-port br1 p8 -- set interface p8 ofport_request=8 type=dummy --])
WAIT_FOR_DUMMY_PORTS([p4], [p5], [p6])
AT_CHECK([ovs-ofctl add-flow br0 action=normal])
AT_CHECK([ovs-ofctl add-flow br1 action=normal])
AT_CHECK([ovs-appctl netdev-dummy/set-admin-state up], 0, [OK
])
ovs-appctl time/stop
ovs-appctl time/warp 100
(
for i in `seq 0 100 |xargs printf '%02x\n'`;
    do
    pkt="in_port(7),eth(src=50:54:00:00:00:$i,dst=50:54:00:00:01:00),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)"
    AT_CHECK([ovs-appctl netdev-dummy/receive p7 $pkt])
    done
)
ovs-appctl time/warp 100
AT_CHECK([ovs-appctl dpif/dump-flows br1 > br1_flows.txt])
# Make sure there is resonable distribution to all three ports.
# We don't want to make this check precise, in case hash function changes.
AT_CHECK([test `egrep 'in_port\(4\)' br1_flows.txt |wc -l` -gt 3])
AT_CHECK([test `egrep 'in_port\(5\)' br1_flows.txt |wc -l` -gt 3])
AT_CHECK([test `egrep 'in_port\(6\)' br1_flows.txt |wc -l` -gt 3])
OVS_VSWITCHD_STOP
AT_CLEANUP

# SEND_TCP_BOND_PKTS([p_name], [p_ofport], [packet_len])
#
# Sends 256 packets to port 'p_name' with different TCP destination ports.
m4_define([SEND_TCP_BOND_PKTS],
   [
    len_cmd=""
    if test -n "$3"; then
        len_cmd=" --len $3"
    fi
    for i in `seq 0 255`; do
        pkt="in_port($2),eth(src=50:54:00:00:00:05,dst=50:54:00:00:01:00),eth_type(0x0800),ipv4(src=10.0.0.2,dst=10.0.0.1,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=$i),tcp_flags(ack)"
        ovs-appctl netdev-dummy/receive $1 $pkt$len_cmd
    done
   ]
)

AT_SETUP([ofproto-dpif - balance-tcp bonding])
# Create br0 with members bond0(p1, p2, p3) and p7,
#    and br1 with members bond1(p4, p5, p6) and p8.
#    bond0 <-> bond1
# Send some traffic, make sure the traffic are spread based on L4 headers.
OVS_VSWITCHD_START(
  [add-bond br0 bond0 p1 p2 p3 bond_mode=balance-tcp lacp=active \
        other-config:lacp-time=fast other-config:bond-rebalance-interval=0 --\
   set interface p1 type=dummy options:pstream=punix:$OVS_RUNDIR/p1.sock ofport_request=1 -- \
   set interface p2 type=dummy options:pstream=punix:$OVS_RUNDIR/p2.sock ofport_request=2 -- \
   set interface p3 type=dummy options:pstream=punix:$OVS_RUNDIR/p3.sock ofport_request=3 -- \
   add-port br0 p7 -- set interface p7 ofport_request=7 type=dummy -- \
   add-br br1 -- \
   set bridge br1 other-config:hwaddr=aa:66:aa:66:00:00 -- \
   set bridge br1 datapath-type=dummy other-config:datapath-id=1234 \
                  fail-mode=secure -- \
   add-bond br1 bond1 p4 p5 p6 bond_mode=balance-tcp lacp=active \
        other-config:lacp-time=fast other-config:bond-rebalance-interval=0 --\
   set interface p4 type=dummy options:stream=unix:$OVS_RUNDIR/p1.sock ofport_request=4 -- \
   set interface p5 type=dummy options:stream=unix:$OVS_RUNDIR/p2.sock ofport_request=5 -- \
   set interface p6 type=dummy options:stream=unix:$OVS_RUNDIR/p3.sock ofport_request=6 -- \
   add-port br1 p8 -- set interface p8 ofport_request=8 type=dummy --])
AT_CHECK([ovs-appctl netdev-dummy/set-admin-state up], 0, [OK
])
AT_CHECK([ovs-ofctl add-flow br0 action=normal])
AT_CHECK([ovs-ofctl add-flow br1 action=normal])
AT_CHECK([ovs-appctl upcall/disable-megaflows], [0], [megaflows disabled
], [])
OVS_WAIT_WHILE([ovs-appctl bond/show | grep "may_enable: false"])
ovs-appctl time/stop
ovs-appctl time/warp 100
ovs-appctl lacp/show > lacp.txt
ovs-appctl bond/show > bond.txt
# Check that lb_output is not enabled by default.
AT_CHECK([grep -q '^lb_output action: disabled' bond.txt])
AT_CHECK([SEND_TCP_BOND_PKTS([p7], [7])])
ovs-appctl time/warp 300 100
AT_CHECK([ovs-appctl dpif/dump-flows br0 |grep tcp > br0_flows.txt])
AT_CHECK([ovs-appctl dpif/dump-flows br1 |grep tcp > br1_flows.txt])
# Make sure there is resonable distribution to all three ports.
# We don't want to make this check precise, in case hash function changes.
AT_CHECK([test $(grep -c in_port.4 br1_flows.txt) -gt 24])
AT_CHECK([test $(grep -c in_port.5 br1_flows.txt) -gt 24])
AT_CHECK([test $(grep -c in_port.6 br1_flows.txt) -gt 24])
# Check that bonding is doing dp_hash.
AT_CHECK([grep -q dp_hash br0_flows.txt])
# Enabling lb_output.
AT_CHECK([ovs-vsctl set Port bond0 other_config:lb-output-action=true])
OVS_WAIT_UNTIL([ovs-appctl bond/show | grep -q '^lb_output action: enabled'])
ovs-appctl time/warp 10000 500
ovs-appctl revalidator/wait
OVS_WAIT_WHILE([ovs-appctl dpif/dump-flows br1 | grep -q tcp])
AT_CHECK([SEND_TCP_BOND_PKTS([p7], [7])])
ovs-appctl time/warp 300 100
AT_CHECK([ovs-appctl dpif/dump-flows br0 | grep tcp > br0_flows.txt])
AT_CHECK([ovs-appctl dpif/dump-flows br1 | grep tcp > br1_flows.txt])
# Make sure there is resonable distribution to all three ports, again.
AT_CHECK([test $(grep -c in_port.4 br1_flows.txt) -gt 24])
AT_CHECK([test $(grep -c in_port.5 br1_flows.txt) -gt 24])
AT_CHECK([test $(grep -c in_port.6 br1_flows.txt) -gt 24])
AT_CHECK([grep -q lb_output br0_flows.txt])

AT_CHECK([test $(ovs-appctl dpif-netdev/bond-show | grep -c bucket) -eq 256])
AT_CHECK([ovs-vsctl set Port bond0 other_config:lb-output-action=false])
OVS_WAIT_UNTIL([test -z "$(ovs-appctl dpif-netdev/bond-show)"])

OVS_VSWITCHD_STOP()
AT_CLEANUP

# Make sure that rebalancing works after link state changes.
AT_SETUP([ofproto-dpif - balance-tcp bonding rebalance after link state changes])
# Create br0 with interfaces bond0(p1, p2) and p5,
#    and br1 with interfaces bond1(p3, p4) and p6.
#    bond0 <-> bond1
# Send some traffic, set link state down and up for p2,
# send big amount of traffic to trigger rebalancing and
# make sure that some hashes rebalanced.
OVS_VSWITCHD_START(
  [add-bond br0 bond0 p1 p2 bond_mode=balance-tcp lacp=active \
        other-config:lacp-time=fast other-config:bond-rebalance-interval=1000 --\
   set interface p1 type=dummy options:pstream=punix:$OVS_RUNDIR/p1.sock ofport_request=1 mtu_request=65535 -- \
   set interface p2 type=dummy options:pstream=punix:$OVS_RUNDIR/p2.sock ofport_request=2 mtu_request=65535 -- \
   add-port br0 p5 -- set interface p5 ofport_request=5 type=dummy mtu_request=65535 -- \
   add-br br1 -- \
   set bridge br1 other-config:hwaddr=aa:66:aa:66:00:00 -- \
   set bridge br1 datapath-type=dummy other-config:datapath-id=1234 \
                  fail-mode=secure -- \
   add-bond br1 bond1 p3 p4 bond_mode=balance-tcp lacp=active \
        other-config:lacp-time=fast other-config:bond-rebalance-interval=1000 --\
   set interface p3 type=dummy options:stream=unix:$OVS_RUNDIR/p1.sock ofport_request=3 mtu_request=65535 -- \
   set interface p4 type=dummy options:stream=unix:$OVS_RUNDIR/p2.sock ofport_request=4 mtu_request=65535 -- \
   add-port br1 p6 -- set interface p6 ofport_request=6 type=dummy mtu_request=65535 --])
AT_CHECK([ovs-appctl vlog/set bond:dbg])
AT_CHECK([ovs-appctl netdev-dummy/set-admin-state up], 0, [OK
])
AT_CHECK([ovs-ofctl add-flow br0 action=normal])
AT_CHECK([ovs-ofctl add-flow br1 action=normal])
AT_CHECK([ovs-appctl upcall/disable-megaflows], [0], [megaflows disabled
], [])
OVS_WAIT_WHILE([ovs-appctl bond/show | grep "may_enable: false"])

ovs-appctl time/stop
ovs-appctl time/warp 2000 200

# Send some traffic to distribute all the hashes between ports.
AT_CHECK([SEND_TCP_BOND_PKTS([p5], [5], [65500])])

# Wait for rebalancing for per-hash stats accounting.
ovs-appctl time/warp 1000 100

# Check that p2 handles some hashes.
ovs-appctl bond/show > bond1.txt
AT_CHECK([sed -n '/member p2/,/^$/p' bond1.txt | grep 'hash'], [0], [ignore])

# Move p2 down to force all hashes move to p1
AT_CHECK([ovs-appctl netdev-dummy/set-admin-state p2 down], 0, [OK
])

ovs-appctl time/warp 200 100
# Check that all hashes moved form p2
ovs-appctl bond/show > bond2.txt
AT_CHECK([sed -n '/member p2/,/^$/p' bond2.txt | grep 'hash'], [1], [ignore])

# Move p2 up
AT_CHECK([ovs-appctl netdev-dummy/set-admin-state p2 up], 0, [OK
])

# Send some packets to trigger rebalancing.
AT_CHECK([SEND_TCP_BOND_PKTS([p5], [5], [65500])])

# Wait for rebalancing
ovs-appctl time/warp 1000 100

# Check that some hashes was shifted to p2
ovs-appctl bond/show > bond3.txt
AT_CHECK([sed -n '/member p2/,/^$/p' bond3.txt | grep 'hash'], [0], [ignore])

OVS_VSWITCHD_STOP()
AT_CLEANUP


# Makes sure recirculation does not change the way packet is handled.
AT_SETUP([ofproto-dpif - balance-tcp bonding, different recirc flow ])
OVS_VSWITCHD_START(
  [add-bond br0 bond0 p1 p2 bond_mode=balance-tcp lacp=active \
       other-config:lacp-time=fast other-config:bond-rebalance-interval=0 -- \
   set interface p1 type=dummy options:pstream=punix:$OVS_RUNDIR/p1.sock ofport_request=1 -- \
   set interface p2 type=dummy options:pstream=punix:$OVS_RUNDIR/p2.sock ofport_request=2 -- \
   add-br br1 -- \
   set bridge br1 other-config:hwaddr=aa:66:aa:66:00:00 -- \
   set bridge br1 datapath-type=dummy other-config:datapath-id=1234 \
       fail-mode=standalone -- \
   add-bond br1 bond1 p3 p4 bond_mode=balance-tcp lacp=active \
       other-config:lacp-time=fast other-config:bond-rebalance-interval=0 -- \
   set interface p3 type=dummy options:stream=unix:$OVS_RUNDIR/p1.sock ofport_request=3 -- \
   set interface p4 type=dummy options:stream=unix:$OVS_RUNDIR/p2.sock ofport_request=4 -- \
   add-port br1 br1- -- set interface br1- type=patch options:peer=br1+ ofport_request=100 -- \
   add-br br-int -- \
   set bridge br-int other-config:hwaddr=aa:77:aa:77:00:00 -- \
   set bridge br-int datapath-type=dummy other-config:datapath-id=1235 \
       fail-mode=secure -- \
   add-port br-int br1+ -- set interface br1+ type=patch options:peer=br1- ofport_request=101 -- \
   add-port br-int p5 -- set interface p5 ofport_request=5 type=dummy
])
AT_CHECK([ovs-appctl netdev-dummy/set-admin-state up], 0, [OK
])

# Waits for all ifaces enabled.
OVS_WAIT_UNTIL([test `ovs-appctl bond/show | grep -- "may_enable: true" |  wc -l` -ge 4])

# The dl_vlan flow should not be ever matched,
# since recirculation should not change the flow handling.
AT_DATA([flows.txt], [dnl
table=0 priority=1 in_port=5 actions=mod_vlan_vid:1,output(101)
table=0 priority=2 in_port=5 dl_vlan=1 actions=drop
])
AT_CHECK([ovs-ofctl add-flows br-int flows.txt])

# Sends a packet to trigger recirculation.
AT_CHECK([ovs-appctl netdev-dummy/receive p5 "in_port(5),eth(src=50:54:00:00:00:05,dst=50:54:00:00:01:00),eth_type(0x0800),ipv4(src=10.0.0.2,dst=10.0.0.1)"])

# Collects flow stats.
AT_CHECK([ovs-appctl revalidator/purge], [0])

# Checks the flow stats in br1, should only be one flow with non-zero
# 'n_packets' from internal table.
AT_CHECK([ovs-appctl bridge/dump-flows br1 | ofctl_strip | grep -- "n_packets" | grep -- "table_id" | sed -e 's/output:[[0-9]][[0-9]]*/output/'] , [0], [dnl
table_id=254, n_packets=1, n_bytes=38, priority=20,recirc_id=0x0,dp_hash=0x0/0xff,actions=output
])

# Checks the flow stats in br-int, should be only one match.
AT_CHECK([ovs-ofctl dump-flows br-int | ofctl_strip | sort], [0], [dnl
 n_packets=1, n_bytes=34, priority=1,in_port=5 actions=mod_vlan_vid:1,output:101
 priority=2,in_port=5,dl_vlan=1 actions=drop
NXST_FLOW reply:
])

OVS_VSWITCHD_STOP()
AT_CLEANUP

AT_SETUP([ofproto-dpif - resubmit])
OVS_VSWITCHD_START
add_of_ports br0 1 10 11 12 13 14 15 16 17 18 19 20 21
AT_DATA([flows.txt], [dnl
table=0 in_port=1 priority=1000 icmp actions=output(10),resubmit(2),output(19),resubmit(3),output(21)
table=0 in_port=2 priority=1500 icmp actions=output(11),resubmit(,1),output(16),resubmit(2,1),output(18)
table=0 in_port=3 priority=2000 icmp actions=output(20)
table=1 in_port=1 priority=1000 icmp actions=output(12),resubmit(4,1),output(13),resubmit(3),output(15)
table=1 in_port=2 priority=1500 icmp actions=output(17),resubmit(,2)
table=1 in_port=3 priority=1500 icmp actions=output(14),resubmit(,2)
])
AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
AT_CHECK([ovs-appctl ofproto/trace br0 'in_port=p1,dl_src=50:54:00:00:00:05,dl_dst=50:54:00:00:00:07,dl_type=0x0800,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_proto=1,nw_tos=0,nw_ttl=128,icmp_type=8,icmp_code=0'], [0], [stdout])
AT_CHECK([tail -1 stdout], [0],
  [Datapath actions: 10,11,12,13,14,15,16,17,18,19,20,21
])
OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - goto table])
OVS_VSWITCHD_START
add_of_ports br0 1 10 11
echo "table=0 in_port=1 actions=output(10),goto_table(1)" > flows.txt
for i in `seq 1 63`; do echo "table=$i actions=goto_table($(($i+1)))"; done >> flows.txt
echo "table=64 actions=output(11)" >> flows.txt
AT_CHECK([ovs-ofctl -O OpenFlow12 add-flows br0 flows.txt])
AT_CHECK([ovs-appctl ofproto/trace br0 'in_port=1,dl_src=50:54:00:00:00:05,dl_dst=50:54:00:00:00:07,dl_type=0x0800,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_proto=1,nw_tos=0,nw_ttl=128,icmp_type=8,icmp_code=0'], [0], [stdout])
AT_CHECK([tail -1 stdout], [0],
  [Datapath actions: 10,11
])
OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - write actions])
OVS_VSWITCHD_START
add_of_ports br0 1 10 11 12 13
AT_DATA([flows.txt], [dnl
table=0 in_port=1,ip actions=output(10),write_actions(set_field:192.168.3.90->ip_src,output(12)),goto_table(1)
table=1 ip actions=write_actions(output(13)),goto_table(2)
table=2 ip actions=set_field:192.168.3.91->ip_src,output(11)
])
AT_CHECK([ovs-ofctl -O OpenFlow12 add-flows br0 flows.txt])
AT_CHECK([ovs-appctl ofproto/trace br0 'in_port=1,dl_src=50:54:00:00:00:05,dl_dst=50:54:00:00:00:07,dl_type=0x0800,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_proto=1,nw_tos=0,nw_ttl=128,icmp_type=8,icmp_code=0'], [0], [stdout])
AT_CHECK([tail -2 stdout], [0],
  [Megaflow: recirc_id=0,eth,ip,in_port=1,nw_src=192.168.0.1,nw_frag=no
Datapath actions: 10,set(ipv4(src=192.168.3.91)),11,set(ipv4(src=192.168.3.90)),13
])
OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - modify IPv6 Neighbor Solitication (ND)])
OVS_VSWITCHD_START
add_of_ports br0 1 10 11 12 13
AT_DATA([flows.txt], [dnl
table=0 in_port=1,icmp6,icmpv6_type=135 actions=output(10),write_actions(set_field:fe80::3->nd_target,set_field:aa:aa:aa:aa:aa:aa->nd_sll,output(12)),goto_table(1)
table=1 icmp6 actions=write_actions(output(13)),goto_table(2)
table=2 in_port=1,icmp6,icmpv6_type=135 actions=set_field:fe80::4->nd_target,set_field:cc:cc:cc:cc:cc:cc->nd_sll,output(11)
])
AT_CHECK([ovs-ofctl -O OpenFlow12 add-flows br0 flows.txt])
AT_CHECK([ovs-appctl ofproto/trace br0 'in_port=1,dl_src=50:54:00:00:00:05,dl_dst=50:54:00:00:00:07,icmp6,ipv6_src=fe80::1,ipv6_dst=fe80::2,nw_tos=0,nw_ttl=128,icmpv6_type=135,nd_target=fe80::2020,nd_sll=66:55:44:33:22:11'], [0], [stdout])
AT_CHECK([tail -4 stdout], [0],
  [Megaflow: recirc_id=0,eth,icmp6,in_port=1,nw_frag=no,icmp_type=0x87/0xff,icmp_code=0x0/0xff,nd_target=fe80::2020,nd_sll=66:55:44:33:22:11
Datapath actions: 10,set(nd(target=fe80::4,sll=cc:cc:cc:cc:cc:cc)),11,set(nd(target=fe80::3,sll=aa:aa:aa:aa:aa:aa)),13
This flow is handled by the userspace slow path because it:
  - Uses action(s) not supported by datapath.
])
OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - clear actions])
OVS_VSWITCHD_START
add_of_ports br0 1 10 11 12
AT_DATA([flows.txt], [dnl
table=0 in_port=1,ip actions=output(10),write_actions(set_field:192.168.3.90->ip_src,output(12)),goto_table(1)
table=1 tcp actions=set_field:91->tp_src,output(11),clear_actions
])
AT_CHECK([ovs-ofctl -O OpenFlow12 add-flows br0 flows.txt])
AT_CHECK([ovs-appctl ofproto/trace br0 'in_port=1,dl_src=50:54:00:00:00:05,dl_dst=50:54:00:00:00:07,dl_type=0x0800,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_proto=6,nw_tos=0,nw_ttl=128,tp_src=8,tp_dst=9'], [0], [stdout])
AT_CHECK([tail -2 stdout], [0],
  [Megaflow: recirc_id=0,eth,tcp,in_port=1,nw_frag=no,tp_src=8
Datapath actions: 10,set(tcp(src=91)),11
])
OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - group chaining])
OVS_VSWITCHD_START
add_of_ports br0 1 10 11
AT_CHECK([ovs-ofctl -O OpenFlow12 add-group br0 'group_id=1234,type=all,bucket=set_field:192.168.3.90->ip_src,group:123,bucket=output:11'])
AT_CHECK([ovs-ofctl -O OpenFlow12 add-group br0 'group_id=123,type=all,bucket=output:10'])
AT_CHECK([ovs-ofctl -O OpenFlow12 add-flow br0 'ip actions=group:1234'])
AT_CHECK([ovs-appctl ofproto/trace br0 'in_port=1,dl_src=50:54:00:00:00:05,dl_dst=50:54:00:00:00:07,dl_type=0x0800,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_proto=1,nw_tos=0,nw_ttl=128,icmp_type=8,icmp_code=0'], [0], [stdout])
AT_CHECK([tail -1 stdout], [0],
  [Datapath actions: set(ipv4(src=192.168.3.90)),10,set(ipv4(src=192.168.0.1)),11
])
OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - all group in action list])
OVS_VSWITCHD_START
add_of_ports br0 1 10 11
AT_CHECK([ovs-ofctl -O OpenFlow12 add-group br0 'group_id=1234,type=all,bucket=output:10,set_field:192.168.3.90->ip_src,bucket=output:11'])
AT_CHECK([ovs-ofctl -O OpenFlow12 add-flow br0 'ip actions=group:1234'])
AT_CHECK([ovs-appctl ofproto/trace br0 'in_port=1,dl_src=50:54:00:00:00:05,dl_dst=50:54:00:00:00:07,dl_type=0x0800,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_proto=1,nw_tos=0,nw_ttl=128,icmp_type=8,icmp_code=0'], [0], [stdout])
# Must match on the source address to be able to restore it's value for
# the second bucket
AT_CHECK([tail -2 stdout], [0],
  [Megaflow: recirc_id=0,eth,ip,in_port=1,nw_src=192.168.0.1,nw_frag=no
Datapath actions: set(ipv4(src=192.168.3.90)),10,set(ipv4(src=192.168.0.1)),11
])
OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - indirect group in action list])
OVS_VSWITCHD_START
add_of_ports br0 1 10
AT_CHECK([ovs-ofctl -O OpenFlow12 add-group br0 group_id=1234,type=indirect,bucket=output:10])
AT_CHECK([ovs-ofctl -O OpenFlow12 add-flow br0 'ip actions=group:1234'])
AT_CHECK([ovs-appctl ofproto/trace br0 'in_port=1,dl_src=50:54:00:00:00:05,dl_dst=50:54:00:00:00:07,dl_type=0x0800,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_proto=1,nw_tos=0,nw_ttl=128,icmp_type=8,icmp_code=0'], [0], [stdout])
AT_CHECK([tail -1 stdout], [0],
  [Datapath actions: 10
])
OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - group actions have no effect afterwards])
OVS_VSWITCHD_START
add_of_ports br0 1 10
AT_CHECK([ovs-ofctl -O OpenFlow12 add-group br0 'group_id=1234,type=select,bucket=set_field:192.168.3.90->ip_src,output:10'])
AT_CHECK([ovs-ofctl -O OpenFlow12 add-flow br0 'ip actions=group:1234,output:10'])

for d in 0 1 2 3; do
    pkt="in_port(1),eth(src=50:54:00:00:00:07,dst=50:54:00:00:00:1),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.1.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)"
    AT_CHECK([ovs-appctl netdev-dummy/receive p1 $pkt])
done

AT_CHECK([ovs-appctl dpctl/dump-flows | sed 's/dp_hash(.*\/0xf)/dp_hash(0xXXXX\/0xf)/' |  sed 's/packets.*actions:/actions:/' | strip_ufid | strip_used | sort], [0], [dnl
flow-dump from the main thread:
recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), actions:hash(sym_l4(0)),recirc(0x1)
recirc_id(0x1),dp_hash(0xXXXX/0xf),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(src=192.168.0.1,frag=no), actions:set(ipv4(src=192.168.3.90)),10,set(ipv4(src=192.168.0.1)),10
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - all group in action set])
OVS_VSWITCHD_START
add_of_ports br0 1 10 11
AT_CHECK([ovs-ofctl -O OpenFlow12 add-group br0 'group_id=1234,type=all,bucket=output:10,set_field:192.168.3.90->ip_src,bucket=output:11'])
AT_CHECK([ovs-ofctl -O OpenFlow12 add-flow br0 'ip actions=write_actions(group:1234)'])
AT_CHECK([ovs-appctl ofproto/trace br0 'in_port=1,dl_src=50:54:00:00:00:05,dl_dst=50:54:00:00:00:07,dl_type=0x0800,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_proto=1,nw_tos=0,nw_ttl=128,icmp_type=8,icmp_code=0'], [0], [stdout])
# Must match on the source address to be able to restore it's value for
# the third bucket
AT_CHECK([tail -2 stdout], [0],
  [Megaflow: recirc_id=0,eth,ip,in_port=1,nw_src=192.168.0.1,nw_frag=no
Datapath actions: set(ipv4(src=192.168.3.90)),10,set(ipv4(src=192.168.0.1)),11
])
OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - indirect group in action set])
OVS_VSWITCHD_START
add_of_ports br0 1 10
AT_CHECK([ovs-ofctl -O OpenFlow12 add-group br0 group_id=1234,type=indirect,bucket=output:10])
AT_CHECK([ovs-ofctl -O OpenFlow12 add-flow br0 'ip actions=write_actions(group:1234)'])
AT_CHECK([ovs-appctl ofproto/trace br0 'in_port=1,dl_src=50:54:00:00:00:05,dl_dst=50:54:00:00:00:07,dl_type=0x0800,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_proto=1,nw_tos=0,nw_ttl=128,icmp_type=8,icmp_code=0'], [0], [stdout])
AT_CHECK([tail -1 stdout], [0],
  [Datapath actions: 10
])
OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - patch port with action set])
OVS_VSWITCHD_START([ \
    add-br br1 -- \
    set bridge br1 datapath-type=dummy fail-mode=secure -- \
    add-port br0 patch10 -- \
    set interface patch10 type=patch options:peer=patch20 ofport_request=10 -- \
    add-port br1 patch20 -- \
    set interface patch20 type=patch options:peer=patch10 ofport_request=20
    ])
add_of_ports br0 1
add_of_ports br1 2
AT_CHECK([ovs-ofctl -O OpenFlow12 add-flow br1 'ip actions=write_actions(pop_vlan,output:2)'])
AT_CHECK([ovs-ofctl -O OpenFlow12 add-flow br0 'ip actions=output:10'])
AT_CHECK([ovs-appctl ofproto/trace br1 'in_port=20,dl_src=50:54:00:00:00:05,dl_dst=50:54:00:00:00:07,dl_vlan=100,dl_type=0x0800,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_proto=1,nw_tos=0,nw_ttl=128,icmp_type=8,icmp_code=0'], [0], [stdout])
AT_CHECK([tail -1 stdout], [0],
  [Datapath actions: pop_vlan,2
])
AT_CHECK([ovs-appctl ofproto/trace br0 'in_port=1,dl_src=50:54:00:00:00:05,dl_dst=50:54:00:00:00:07,dl_vlan=100,dl_type=0x0800,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_proto=1,nw_tos=0,nw_ttl=128,icmp_type=8,icmp_code=0'], [0], [stdout])
AT_CHECK([tail -1 stdout], [0],
  [Datapath actions: pop_vlan,2
])
OVS_VSWITCHD_STOP
AT_CLEANUP


AT_SETUP([ofproto-dpif - select group])

OVS_VSWITCHD_START
add_of_ports br0 1 10 11

ovs-appctl vlog/set ofproto_dpif:file:dbg
AT_CHECK([ovs-ofctl -O OpenFlow12 add-group br0 'group_id=1234,type=select,bucket=output:10,bucket=output:11'])
AT_CHECK([grep -A6 "Constructing select group 1234" ovs-vswitchd.log | sed 's/^.*ofproto_dpif/ofproto_dpif/'], [0], [dnl
ofproto_dpif|DBG|Constructing select group 1234
ofproto_dpif|DBG|No selection method specified. Trying dp_hash.
ofproto_dpif|DBG|  Minimum weight: 1, total weight: 2
ofproto_dpif|DBG|  Using 16 hash values:
ofproto_dpif|DBG|  Bucket 0: weight=1, target=8.00 hits=8
ofproto_dpif|DBG|  Bucket 1: weight=1, target=8.00 hits=8
ofproto_dpif|DBG|Use dp_hash with 16 hash values using algorithm 1.
])
AT_CHECK([ovs-ofctl -O OpenFlow12 add-flow br0 'ip actions=write_actions(group:1234)'])

# Try a bunch of different flows and make sure that they get distributed
# # at least somewhat.
for d in 0 1 2 3; do
    for s in 1 2 3 4 ; do
        pkt="in_port(1),eth(src=50:54:00:00:00:07,dst=50:54:00:00:00:1),eth_type(0x0800),ipv4(src=192.168.0.$s,dst=192.168.1.$d,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)"
        AT_CHECK([ovs-appctl netdev-dummy/receive p1 $pkt])
    done
done

AT_CHECK([ovs-appctl dpctl/dump-flows | sort | strip_ufid | strip_used | check_dpflow_stats 5 2 dp_hash], [0], [dnl
recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:15, bytes:1590, used:0.0s, actions:hash(sym_l4(0)),recirc(0x1)
n_flows=ok n_buckets=ok
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - select group with watch port])

OVS_VSWITCHD_START
add_of_ports br0 1 10 11
AT_CHECK([ovs-ofctl -O OpenFlow12 add-group br0 'group_id=1234,type=select,bucket=watch_port:10,output:10,bucket=output:11'])
AT_CHECK([ovs-ofctl -O OpenFlow12 add-flow br0 'ip actions=write_actions(group:1234)'])

for d in 0 1 2 3; do
        pkt="in_port(1),eth(src=50:54:00:00:00:07,dst=50:54:00:00:00:1),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 netdev-dummy/receive p1 $pkt])
done

AT_CHECK([ovs-appctl dpctl/dump-flows | sort| sed 's/dp_hash(.*\/0xf)/dp_hash(0xXXXX\/0xf)/' | strip_ufid | strip_used], [0], [dnl
flow-dump from the main thread:
recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:3, bytes:318, used:0.0s, actions:hash(sym_l4(0)),recirc(0x1)
recirc_id(0x1),dp_hash(0xXXXX/0xf),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:3, bytes:318, used:0.0s, actions:11
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - select group with weights])

# Helper function to check the accuracy of distribution of packets over buckets
check_group_stats () {
    buckets=`grep -o 'packet_count=[[0-9]]*' | cut -d'=' -f2 | tail -n +2`
    i=0
    for bucket in $buckets; do
        min=$1
        shift
        if [[ $bucket -ge $min ]]; then
            echo "bucket$i >= $min"
        else
            echo "bucket$i < $min"
        fi
        i=`expr $i + 1`
        if [[ $i -ge 4 ]]; then break; fi
    done
}

OVS_VSWITCHD_START
add_of_ports br0 1 10 11 12 13 14

ovs-appctl vlog/set ofproto_dpif:file:dbg
AT_CHECK([ovs-ofctl -O OpenFlow13 add-group br0 'group_id=1234,type=select,bucket=weight:5,output:10,bucket=weight:10,output:11,bucket=weight:25,output:12,bucket=weight:60,output:13,bucket=weight:0,output:14'])
AT_CHECK([grep -A9 "Constructing select group 1234" ovs-vswitchd.log | sed 's/^.*ofproto_dpif/ofproto_dpif/'], [0], [dnl
ofproto_dpif|DBG|Constructing select group 1234
ofproto_dpif|DBG|No selection method specified. Trying dp_hash.
ofproto_dpif|DBG|  Minimum weight: 5, total weight: 100
ofproto_dpif|DBG|  Using 32 hash values:
ofproto_dpif|DBG|  Bucket 0: weight=5, target=1.60 hits=2
ofproto_dpif|DBG|  Bucket 1: weight=10, target=3.20 hits=3
ofproto_dpif|DBG|  Bucket 2: weight=25, target=8.00 hits=8
ofproto_dpif|DBG|  Bucket 3: weight=60, target=19.20 hits=19
ofproto_dpif|DBG|  Bucket 4: weight=0, target=0.00 hits=0
ofproto_dpif|DBG|Use dp_hash with 32 hash values using algorithm 1.
])
AT_CHECK([ovs-ofctl -O OpenFlow12 add-flow br0 'ip actions=write_actions(group:1234)'])

# Try 1000 different flows and make sure that they get distributed according to weights
for d1 in 0 1 2 3 4 5 6 7 8 9 ; do
  for d2 in 0 1 2 3 4 5 6 7 8 9 ; do
    for s in 0 1 2 3 4 5 6 7 8 9 ; do
      pkt="in_port(1),eth(src=50:54:00:00:00:07,dst=50:54:00:00:00:1),eth_type(0x0800),ipv4(src=192.168.1.$s,dst=192.168.$d1.$d2,proto=6,tos=0,ttl=128,frag=no),tcp(src=1000$s,dst=1000)"
      AT_CHECK([ovs-appctl netdev-dummy/receive p1 $pkt])
    done
  done
done

# Check balanced distribution over 32 dp_hash values
AT_CHECK([ovs-appctl dpctl/dump-flows | sort | strip_ufid | strip_used | check_dpflow_stats 32 4 dp_hash], [0], [dnl
recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:999, bytes:117882, used:0.0s, actions:hash(sym_l4(0)),recirc(0x1)
n_flows=ok n_buckets=ok
])

# Check that actual distribution over the buckets is reasonably accurate:
                ideal weights       dp_hash values
#   bucket0:    5%*1000 = 50        2/32*1000 = 63
#   bucket1:    10%*1000 = 100      3/32*1000 = 94
#   bucket2:    25%*1000 = 250      8/32*1000 = 250
#   bucket3:    60%*1000 = 600      19/32*1000 = 594
#   bucket4:    0                   0

ovs-appctl time/warp 1000
AT_CHECK([ovs-ofctl -O OpenFlow13 dump-group-stats br0 | sed 's/duration=[[0-9]]\.[[0-9]]*s,//' | check_group_stats 40 80 200 500],
[0], [dnl
bucket0 >= 40
bucket1 >= 80
bucket2 >= 200
bucket3 >= 500
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - select group with explicit dp_hash selection method])

OVS_VSWITCHD_START
add_of_ports br0 1 10 11

ovs-appctl vlog/set ofproto_dpif:file:dbg
AT_CHECK([ovs-ofctl -O OpenFlow15 add-group br0 'group_id=1234,type=select,selection_method=dp_hash,bucket=output:10,bucket=output:11'])
AT_CHECK([grep -A6 "Constructing select group 1234" ovs-vswitchd.log | sed 's/^.*ofproto_dpif/ofproto_dpif/'], [0], [dnl
ofproto_dpif|DBG|Constructing select group 1234
ofproto_dpif|DBG|Selection method specified: dp_hash.
ofproto_dpif|DBG|  Minimum weight: 1, total weight: 2
ofproto_dpif|DBG|  Using 16 hash values:
ofproto_dpif|DBG|  Bucket 0: weight=1, target=8.00 hits=8
ofproto_dpif|DBG|  Bucket 1: weight=1, target=8.00 hits=8
ofproto_dpif|DBG|Use dp_hash with 16 hash values using algorithm 0.
])

# Fall back to legacy hash with zero buckets
AT_CHECK([ovs-ofctl -O OpenFlow15 add-group br0 'group_id=1235,type=select,selection_method=dp_hash'])
AT_CHECK([grep -A3 "Constructing select group 1235" ovs-vswitchd.log | sed 's/^.*ofproto_dpif/ofproto_dpif/'], [0], [dnl
ofproto_dpif|DBG|Constructing select group 1235
ofproto_dpif|DBG|Selection method specified: dp_hash.
ofproto_dpif|DBG|  Don't apply dp_hash method without buckets.
ofproto_dpif|DBG|Falling back to default hash method.
])

# Fall back to legacy hash with zero buckets
AT_CHECK([ovs-ofctl -O OpenFlow15 add-group br0 'group_id=1236,type=select,selection_method=dp_hash,bucket=weight=1,output:10,bucket=weight=1000,output:11'])
AT_CHECK([grep -A4 "Constructing select group 1236" ovs-vswitchd.log | sed 's/^.*ofproto_dpif/ofproto_dpif/'], [0], [dnl
ofproto_dpif|DBG|Constructing select group 1236
ofproto_dpif|DBG|Selection method specified: dp_hash.
ofproto_dpif|DBG|  Minimum weight: 1, total weight: 1001
ofproto_dpif|DBG|  Too many hash values required: 1024
ofproto_dpif|DBG|Falling back to default hash method.
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - select group with legacy hash selection method])

OVS_VSWITCHD_START
add_of_ports br0 1 10 11

ovs-appctl vlog/set ofproto_dpif:file:dbg
AT_CHECK([ovs-ofctl -O OpenFlow15 add-group br0 'group_id=1234,type=select,selection_method=hash,bucket=output:10,bucket=output:11'])
AT_CHECK([grep -A2 "Constructing select group 1234" ovs-vswitchd.log | sed 's/^.*ofproto_dpif/ofproto_dpif/'], [0], [dnl
ofproto_dpif|DBG|Constructing select group 1234
ofproto_dpif|DBG|Selection method specified: hash.
ofproto_dpif|DBG|No hash fields. Falling back to default hash method.
])

AT_CHECK([ovs-ofctl -O OpenFlow15 add-flow br0 'ip actions=write_actions(group:1234)'])

# Try 16 flows with differing default hash values.
for d in 0 1 2 3; do
    for s in 1 2 3 4 ; do
        pkt="in_port(1),eth(src=50:54:00:00:00:07,dst=50:54:00:00:00:1),eth_type(0x0800),ipv4(src=192.168.0.$s,dst=192.168.1.$d,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)"
        AT_CHECK([ovs-appctl netdev-dummy/receive p1 $pkt])
    done
done

# Check that the packets installed 16 data path flows and each of the two
# buckets is hit at least once.
AT_CHECK([ovs-appctl dpctl/dump-flows | strip_ufid | strip_used | sort | check_dpflow_stats 16 2], [0], [dnl
n_flows=ok n_buckets=ok
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - select group with custom hash selection method])

OVS_VSWITCHD_START
add_of_ports br0 1 10 11

# Check that parse failures after 'fields' parsing work
AT_CHECK([ovs-ofctl -O OpenFlow10 add-group br0 'group_id=1,type=select,fields(eth_dst),bukket=output:10'], [1], ,[dnl
ovs-ofctl: unknown keyword bukket
])

# Check that fields are rejected without "selection_method=hash".
AT_CHECK([ovs-ofctl -O OpenFlow15 add-group br0 'group_id=1235,type=select,fields(eth_dst,ip_dst,tcp_dst),bucket=output:10,bucket=output:11'], 1, [], [dnl
ovs-ofctl: fields may only be specified with "selection_method=hash"
])

# Check that selection_method_param without selection_method is rejected.
AT_CHECK([ovs-ofctl -O OpenFlow15 add-group br0 'group_id=1235,type=select,selection_method_param=1,bucket=output:10,bucket=output:11'], 1, [], [dnl
ovs-ofctl: selection_method_param is only allowed with "selection_method"
])

AT_CHECK([ovs-ofctl -O OpenFlow15 add-group br0 'group_id=1234,type=select,selection_method=hash,fields(eth_dst,ip_dst,tcp_dst),bucket=output:10,bucket=output:11'])
AT_CHECK([ovs-ofctl -O OpenFlow15 add-flow br0 'ip actions=write_actions(group:1234)'])

# Try 16 flows with differing custom hash and check that they give rise to
# 16 data path flows and each of the two buckets is hit at least once
for d in 0 1 2 3 4 5 6 7 8 9 a b c d e f; do
    pkt="in_port(1),eth(src=50:54:00:00:00:07,dst=50:54:00:00:00:$d),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 netdev-dummy/receive p1 $pkt])
done

AT_CHECK([ovs-appctl dpctl/dump-flows | strip_ufid | strip_used | sort | check_dpflow_stats 16 2], [0], [dnl
n_flows=ok n_buckets=ok
])

AT_CHECK([ovs-appctl revalidator/purge], [0])

# Try 16 flows that differ only in fields that are not part of the custom
# hash and check that there is only a single datapath flow
for d in 0 1 2 3 4 5 6 7 8 9 a b c d e f; do
    pkt="in_port(1),eth(src=50:54:00:00:00:$d,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 netdev-dummy/receive p1 $pkt])
done

AT_CHECK([ovs-appctl dpctl/dump-flows | grep -c recirc_id], [0], [dnl
1
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - fast failover group])
OVS_VSWITCHD_START
add_of_ports br0 1 10 11
AT_CHECK([ovs-ofctl -O OpenFlow12 add-group br0 'group_id=1234,type=ff,bucket=watch_port:10,output:10,bucket=watch_port:11,output:11'])
AT_CHECK([ovs-ofctl -O OpenFlow12 add-flow br0 'ip actions=write_actions(group:1234)'])
AT_CHECK([ovs-appctl ofproto/trace br0 'in_port=1,dl_src=50:54:00:00:00:05,dl_dst=50:54:00:00:00:07,dl_type=0x0800,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_proto=1,nw_tos=0,nw_ttl=128,icmp_type=8,icmp_code=0'], [0], [stdout])
AT_CHECK([tail -1 stdout], [0],
  [Datapath actions: 10
])
OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - group stats single bucket])
OVS_VSWITCHD_START
add_of_ports br0 1 10 11
AT_CHECK([ovs-ofctl -O OpenFlow12 add-group br0 'group_id=1234,type=select,bucket=output:10,weight=2000,bucket=output:11,weight=0'])
AT_CHECK([ovs-ofctl -O OpenFlow12 add-flow br0 'ip actions=write_actions(group:1234)'])
(
for i in `seq 0 2`;
    do
    pkt="in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:01:00),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)"
    AT_CHECK([ovs-appctl netdev-dummy/receive p1 $pkt])
    done
)
AT_CHECK([ovs-appctl revalidator/purge], [0])
AT_CHECK([ovs-ofctl -O OpenFlow12 -vwarn dump-group-stats br0], [0], [stdout])
AT_CHECK([strip_xids < stdout | sort], [0], [dnl
 group_id=1234,ref_count=1,packet_count=3,byte_count=318,bucket0:packet_count=3,byte_count=318,bucket1:packet_count=0,byte_count=0
OFPST_GROUP reply (OF1.2):
])
OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - group stats all buckets])
OVS_VSWITCHD_START
add_of_ports br0 1 10 11
AT_CHECK([ovs-ofctl -O OpenFlow12 add-group br0 'group_id=1234,type=all,bucket=output:10,bucket=output:11'])
AT_CHECK([ovs-ofctl -O OpenFlow12 add-flow br0 'ip actions=write_actions(group:1234)'])
(
for i in `seq 0 2`;
    do
    pkt="in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:01:00),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)"
    AT_CHECK([ovs-appctl netdev-dummy/receive p1 $pkt])
    done
)
AT_CHECK([ovs-appctl revalidator/purge], [0])
AT_CHECK([ovs-ofctl -O OpenFlow12 -vwarn dump-group-stats br0], [0], [stdout])
AT_CHECK([strip_xids < stdout | sort], [0], [dnl
 group_id=1234,ref_count=1,packet_count=3,byte_count=318,bucket0:packet_count=3,byte_count=318,bucket1:packet_count=3,byte_count=318
OFPST_GROUP reply (OF1.2):
])
OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - registers])
OVS_VSWITCHD_START
add_of_ports br0 20 21 22 33 90
AT_DATA([flows.txt], [dnl
in_port=90                 actions=resubmit:2,resubmit:3,resubmit:4,resubmit:91
in_port=91                 actions=resubmit:5,resubmit:6,resubmit:7,resubmit:92
in_port=92                 actions=resubmit:8,resubmit:9,resubmit:10,resubmit:11,resubmit:93
in_port=93                 actions=resubmit:12,resubmit:13,resubmit:14,resubmit:15

in_port=2                  actions=load:0x000db000->NXM_NX_REG0[[]]
in_port=3                  actions=load:0xdea->NXM_NX_REG0[[20..31]]
in_port=4                  actions=load:0xeef->NXM_NX_REG0[[0..11]]
in_port=5                  actions=move:NXM_NX_REG0[[]]->NXM_NX_REG1[[]]
in_port=6                  actions=load:0x22222222->NXM_NX_REG2[[]]
in_port=7                  actions=move:NXM_NX_REG1[[20..31]]->NXM_NX_REG2[[0..11]]
in_port=8                  actions=move:NXM_NX_REG1[[0..11]]->NXM_NX_REG2[[20..31]]
in_port=9,reg0=0xdeadbeef  actions=output:20
in_port=10,reg1=0xdeadbeef actions=output:21
in_port=11,reg2=0xeef22dea actions=output:22

dnl Sanilty check all registers
in_port=12 actions=load:0x10->NXM_NX_REG0[[]],load:0x11->NXM_NX_REG1[[]],load:0x12->NXM_NX_REG2[[]]
in_port=13 actions=load:0x13->NXM_NX_REG3[[]],load:0x14->NXM_NX_REG4[[]],load:0x15->NXM_NX_REG5[[]]
in_port=14 actions=load:0x16->NXM_NX_REG6[[]],load:0x17->NXM_NX_REG7[[]]
in_port=15,reg0=0x10,reg1=0x11,reg2=0x12,reg3=0x13,reg4=0x14,reg5=0x15,reg6=0x16,reg7=0x17 actions=output:33

])
AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(90),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)'], [0], [stdout])
AT_CHECK([tail -1 stdout], [0],
  [Datapath actions: 20,21,22,33
])
OVS_VSWITCHD_STOP
AT_CLEANUP

dnl Tests that the standardized xregs are mapped onto the legacy OVS registers
dnl in the manner documented in ovs-ofctl(8).
AT_SETUP([ofproto-dpif - extended registers])
OVS_VSWITCHD_START
add_of_ports br0 1 2 3
AT_DATA([flows.txt], [dnl
table=0     actions=load:0xfedcba9876543210->OXM_OF_PKT_REG1[[]],resubmit(,1)
table=1,reg2=0xfedcba98,reg3=0x76543210   actions=2

# These low-priority rules shouldn't match.  They're here only to make really
# sure that the test fails if either of the above rules fails to match.
table=0,priority=0                        actions=3
table=1,priority=0                        actions=3
])
AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
AT_CHECK([ovs-appctl ofproto/trace ovs-dummy '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)'], [0], [stdout])
AT_CHECK([tail -1 stdout], [0], [Datapath actions: 2
])
OVS_VSWITCHD_STOP
AT_CLEANUP

dnl Tests that the standardized xxregs are mapped onto the legacy OVS
dnl registers in the manner documented in ovs-ofctl(8).
AT_SETUP([ofproto-dpif - extended-extended registers])
OVS_VSWITCHD_START
add_of_ports br0 1 2 3
AT_DATA([flows.txt], [dnl
table=0 actions=load:0x0123456789abcdeffedcba9876543210->NXM_NX_XXREG1[[]],resubmit(,1)
table=1,reg4=0x01234567,reg5=0x89abcdef,reg6=0xfedcba98,reg7=0x76543210   actions=2

# These low-priority rules shouldn't match.  They're here only to make really
# sure that the test fails if either of the above rules fails to match.
table=0,priority=0                        actions=3
table=1,priority=0                        actions=3
])
AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
AT_CHECK([ovs-appctl ofproto/trace ovs-dummy '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)'], [0], [stdout])
AT_CHECK([tail -1 stdout], [0], [Datapath actions: 2
])
OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - load and move order])
OVS_VSWITCHD_START
add_of_ports br0 1 10 11
AT_CHECK([ovs-ofctl -O OpenFlow12 add-group br0 'group_id=1234,type=all,bucket=output:10,move:NXM_NX_REG1[[]]->NXM_OF_IP_SRC[[]],bucket=output:11'])
AT_CHECK([ovs-ofctl -O OpenFlow12 add-flow br0 'ip actions=write_actions(load:0xffffffff->NXM_NX_REG1[[]],move:NXM_NX_REG1[[]]->NXM_NX_REG2[[]],group:1234)'])
AT_CHECK([ovs-appctl ofproto/trace br0 'in_port=1,dl_src=50:54:00:00:00:05,dl_dst=50:54:00:00:00:07,dl_type=0x0800,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_proto=1,nw_tos=0,nw_ttl=128,icmp_type=8,icmp_code=0'], [0], [stdout])
AT_CHECK([tail -2 stdout], [0],
  [Megaflow: recirc_id=0,eth,ip,in_port=1,nw_src=192.168.0.1,nw_frag=no
Datapath actions: set(ipv4(src=255.255.255.255)),10,set(ipv4(src=192.168.0.1)),11
])
OVS_VSWITCHD_STOP
AT_CLEANUP

dnl Tests that 1.5 copy-field can copy into the standardized xregs.
AT_SETUP([ofproto-dpif - copy-field into extended registers])
OVS_VSWITCHD_START
add_of_ports br0 1 2 3
AT_DATA([flows.txt], [dnl
table=0     actions=move:OXM_OF_ETH_SRC[[0..47]]->OXM_OF_PKT_REG0[[0..47]],goto_table(1)
table=1,xreg0=0x0000505400000005   actions=2

# These low-priority rules shouldn't match.  They're here only to make really
# sure that the test fails if either of the above rules fails to match.
table=0,priority=0                        actions=3
table=1,priority=0                        actions=3
])
AT_CHECK([ovs-ofctl -O OpenFlow15 add-flows br0 flows.txt])
AT_CHECK([ovs-appctl ofproto/trace ovs-dummy '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)'], [0], [stdout])
AT_CHECK([tail -1 stdout], [0], [Datapath actions: 2
])
OVS_VSWITCHD_STOP
AT_CLEANUP

dnl Tests that 1.5 set-field with mask in the metadata register.
AT_SETUP([ofproto-dpif - masked set-field into metadata])
OVS_VSWITCHD_START
add_of_ports br0 1 2 3
AT_DATA([flows.txt], [dnl
table=0     actions=set_field:0xfafafafa5a5a5a5a->metadata,goto_table(1)
table=1     actions=set_field:0x6b/0xff->metadata,goto_table(2)
table=2,metadata=0xfafafafa5a5a5a6b  actions=2

# These low-priority rules shouldn't match.  They're here only to make really
# sure that the test fails if either of the above rules fails to match.
table=0,priority=0                        actions=3
table=1,priority=0                        actions=3
table=2,priority=0                        actions=3
])
AT_CHECK([ovs-ofctl -O OpenFlow15 add-flows br0 flows.txt])
AT_CHECK([ovs-appctl ofproto/trace ovs-dummy '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)'], [0], [stdout])
AT_CHECK([tail -1 stdout], [0], [Datapath actions: 2
])
OVS_VSWITCHD_STOP
AT_CLEANUP


AT_SETUP([ofproto-dpif - actset_output])
OVS_VSWITCHD_START
add_of_ports br0 1 2 3 4 5 6 7 8 9 10 11 12 13
AT_DATA([flows.txt], [dnl
table=0,actset_output=unset     actions=write_actions(output(2)),goto_table(1)
table=1     actions=move:ONFOXM_ET_ACTSET_OUTPUT[[0..31]]->OXM_OF_PKT_REG0[[0..31]],goto_table(2)

# Verify that actset_output got set.
table=2,priority=20,actset_output=2  actions=4,goto_table(3)
table=2,priority=10                  actions=5,goto_table(3)

# Verify that xreg0 got copied properly from actset_output.
table=3,priority=20,xreg0=2  actions=6,goto_table(4)
table=3,priority=10          actions=7,goto_table(4)

# Verify that xxreg0 got copied properly from actset_output.
table=3,priority=20,xxreg0=2  actions=6,goto_table(4)
table=3,priority=10           actions=7,goto_table(4)

# Verify that adding a group action unsets actset_output,
# even if output follows group.
table=4 actions=write_actions(group(5),output(10)),goto_table(5)
table=5,priority=20,actset_output=unset  actions=8,goto_table(6)
table=5,priority=10                      actions=9,goto_table(6)

# Verify that adding another output action doesn't change actset_output
# (since there's still a group).
table=6 actions=write_actions(output(3)),goto_table(7)
table=7,priority=20,actset_output=unset  actions=10,goto_table(8)
table=7,priority=10                      actions=11,goto_table(8)

# Verify that clearing the action set, then writing an output action,
# causes actset_output to be set again.
table=8,actions=clear_actions,write_actions(output(3),output(2)),goto_table(9)
table=9,priority=20,actset_output=2 actions=12
table=9,priority=10                 actions=13
])
AT_CHECK([ovs-ofctl -O OpenFlow13 add-group br0 'group_id=5,type=all,bucket=output:1'])
AT_CHECK([ovs-ofctl -O OpenFlow13 add-flows br0 flows.txt])
AT_CHECK([ovs-appctl ofproto/trace ovs-dummy '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)'], [0], [stdout])
AT_CHECK([tail -1 stdout], [0], [Datapath actions: 4,6,8,10,12,2
])
OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - push-pop])
OVS_VSWITCHD_START
add_of_ports br0 20 21 22 33 90
AT_DATA([flows.txt], [dnl
in_port=90           actions=load:20->NXM_NX_REG0[[0..7]],load:21->NXM_NX_REG1[[0..7]],load:22->NXM_NX_REG2[[0..7]], load:33->NXM_NX_REG3[[0..7]], push:NXM_NX_REG0[[]], push:NXM_NX_REG1[[0..7]],push:NXM_NX_REG2[[0..15]], push:NXM_NX_REG3[[]], resubmit:2, resubmit:3, resubmit:4, resubmit:5
in_port=2            actions=pop:NXM_NX_REG0[[0..7]],output:NXM_NX_REG0[[]]
in_port=3            actions=pop:NXM_NX_REG1[[0..7]],output:NXM_NX_REG1[[]]
in_port=4            actions=pop:NXM_NX_REG2[[0..15]],output:NXM_NX_REG2[[]]
in_port=5            actions=pop:NXM_NX_REG3[[]],output:NXM_NX_REG3[[]]

])
AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(90),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)'], [0], [stdout])
AT_CHECK([tail -1 stdout], [0],
  [Datapath actions: 33,22,21,20
])
OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - output])
OVS_VSWITCHD_START
add_of_ports br0 1 9 10 11 55 66 77 88
AT_DATA([flows.txt], [dnl
in_port=1 actions=resubmit:2,resubmit:3,resubmit:4,resubmit:5,resubmit:6,resubmit:7,resubmit:8
in_port=2 actions=output:9
in_port=3 actions=load:55->NXM_NX_REG0[[]],output:NXM_NX_REG0[[]],load:66->NXM_NX_REG1[[]]
in_port=4 actions=output:10,output:NXM_NX_REG0[[]],output:NXM_NX_REG1[[]],output:11
in_port=5 actions=load:77->NXM_NX_REG0[[0..15]],load:88->NXM_NX_REG0[[16..31]]
in_port=6 actions=output:NXM_NX_REG0[[0..15]],output:NXM_NX_REG0[[16..31]]
in_port=7 actions=load:0x110000ff->NXM_NX_REG0[[]],output:NXM_NX_REG0[[]]
in_port=8 actions=1,9,load:9->NXM_OF_IN_PORT[[]],1,9
])
AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
AT_CHECK([ovs-appctl ofproto/trace ovs-dummy '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)'], [0], [stdout])
AT_CHECK([tail -1 stdout], [0],
  [Datapath actions: 9,55,10,55,66,11,77,88,9,1
])
OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - dec_ttl])
OVS_VSWITCHD_START
add_of_ports br0 1 2 3 4
AT_DATA([flows.txt], [dnl
table=0 in_port=1 action=dec_ttl,output:2,resubmit(1,1),output:4
table=1 in_port=1 action=dec_ttl,output:3
])
AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
AT_CHECK([ovs-appctl ofproto/trace ovs-dummy '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=111,tos=0,ttl=2,frag=no)' -generate], [0], [stdout])
AT_CHECK([tail -4 stdout], [0], [
Final flow: ip,in_port=1,vlan_tci=0x0000,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_proto=111,nw_tos=0,nw_ecn=0,nw_ttl=1
Megaflow: recirc_id=0,eth,ip,in_port=1,nw_ttl=2,nw_frag=no
Datapath actions: set(ipv4(ttl=1)),2,userspace(pid=0,controller(reason=2,dont_send=0,continuation=0,recirc_id=1,rule_cookie=0,controller_id=0,max_len=65535)),4
])
AT_CHECK([ovs-appctl ofproto/trace ovs-dummy '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=111,tos=0,ttl=3,frag=no)'], [0], [stdout])
AT_CHECK([tail -2 stdout], [0],
  [Megaflow: recirc_id=0,eth,ip,in_port=1,nw_ttl=3,nw_frag=no
Datapath actions: set(ipv4(ttl=2)),2,set(ipv4(ttl=1)),3,4
])
AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x86dd),ipv6(src=::1,dst=::2,label=0,proto=10,tclass=0x70,hlimit=128,frag=no)'], [0], [stdout])
AT_CHECK([tail -2 stdout], [0],
  [Megaflow: recirc_id=0,eth,ipv6,in_port=1,nw_ttl=128,nw_frag=no
Datapath actions: set(ipv6(hlimit=127)),2,set(ipv6(hlimit=126)),3,4
])

AT_CAPTURE_FILE([ofctl_monitor.log])
AT_CHECK([ovs-ofctl -P nxt_packet_in monitor br0 65534 invalid_ttl --detach --no-chdir --pidfile 2> ofctl_monitor.log])

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=111,tos=0,ttl=2,frag=no)'

OVS_APP_EXIT_AND_WAIT([ovs-ofctl])
AT_CHECK([cat ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): table_id=1 cookie=0x0 total_len=34 in_port=1 (via invalid_ttl) data_len=34 (unbuffered)
ip,vlan_tci=0x0000,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_proto=111,nw_tos=0,nw_ecn=0,nw_ttl=1
])
OVS_VSWITCHD_STOP
AT_CLEANUP

dnl A dec_ttl action at offset 32 in ofpacts will cause the ofpacts
dnl buffer to be resized just before pushing the id of the dec_ttl action.
dnl Thus the implementation must account for this by using the
dnl reallocated buffer rather than the original buffer.
dnl
dnl A number of similar rules are added to try and exercise
dnl xrealloc sufficiently that it returns a different base pointer
AT_SETUP([ofproto-dpif - dec_ttl without arguments at offset 32 in ofpacts])
OVS_VSWITCHD_START
add_of_ports br0 1
(for i in `seq 0 255`; do
  printf "dl_src=10:11:11:11:11:%02x actions=output:1,output:1,output:1,dec_ttl,controller\n" $i
 done) > flows.txt
AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
OVS_VSWITCHD_STOP
AT_CLEANUP

dnl A dec_ttl action at offset 32 in ofpacts will cause the ofpacts
dnl buffer to be resized just before pushing the id of the dec_ttl action.
dnl Thus the implementation must account for this by using the
dnl reallocated buffer rather than the original buffer.
dnl
dnl A number of similar rules are added to try and exercise
dnl xrealloc sufficiently that it returns a different base pointer
AT_SETUP([ofproto-dpif - dec_ttl with arguments at offset 32 in ofpacts])
OVS_VSWITCHD_START
add_of_ports br0 1
(for i in `seq 0 255`; do
  printf "dl_src=10:11:11:11:11:%02x actions=output:1,output:1,output:1,dec_ttl(1),controller\n" $i
 done) > flows.txt
AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
OVS_VSWITCHD_STOP
AT_CLEANUP

dnl A note action at offset 24 in ofpacts will cause the ofpacts
dnl buffer to be resized just before pushing the id of the dec_ttl action.
dnl Thus the implementation must account for this by using the
dnl reallocated buffer rather than the original buffer.
dnl
dnl A number of similar rules are added to try and exercise
dnl xrealloc sufficiently that it returns a different base pointer
AT_SETUP([ofproto-dpif - note at offset 24 in ofpacts])
OVS_VSWITCHD_START
add_of_ports br0 1
(for i in `seq 0 255`; do
  printf "dl_src=10:11:11:11:11:%02x actions=output:1,output:1,note:ff,controller\n" $i
 done) > flows.txt
AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
OVS_VSWITCHD_STOP
AT_CLEANUP

dnl As of OVS-2.5, a note action after 4 set_field actions are likely to
dnl trigger ofpbuf reallocation during decode (~1KB into ofpacts buffer).
dnl Using `make check-valgrind' here checks for use-after-free in this
dnl codepath.
AT_SETUP([ofproto-dpif - note action deep inside ofpacts])
OVS_VSWITCHD_START
AT_CHECK([ovs-ofctl add-flow br0 'actions=set_field:0x1->metadata,set_field:0x2->metadata,set_field:0x3->metadata,set_field:0x4->metadata,note:00000000000000000000000000000000,note:00000000000000000000000000000000'])
OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - output, OFPP_NONE ingress port])
OVS_VSWITCHD_START
add_of_ports br0 1 2

AT_CHECK([ovs-ofctl add-flow br0 action=normal])

# "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,icmp_type=8,icmp_code=0"
AT_CHECK([ovs-appctl ofproto/trace br0 "$flow"], [0], [stdout])
AT_CHECK([tail -1 stdout | sed 's/Datapath actions: //' | tr "," "\n" | sort -n], [0], [dnl
1
2
100
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - DSCP])
OVS_VSWITCHD_START([add-port br0 p1 -- set Interface p1 type=dummy])
add_of_ports br0 9
AT_DATA([flows.txt], [dnl
actions=output:LOCAL,enqueue:1:1,enqueue:1:2,enqueue:1:2,enqueue:1:1,output:1,mod_nw_tos:0,output:1,output:LOCAL
])
AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
AT_CHECK([ovs-vsctl -- \
        set Port p1 qos=@newqos --\
        --id=@newqos create QoS type=linux-htb queues=1=@q1,2=@q2 --\
        --id=@q1 create Queue dscp=1 --\
        --id=@q2 create Queue dscp=2], [0], [ignore])
AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(9),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=1.1.1.1,dst=2.2.2.2,proto=1,tos=0xff,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])
AT_CHECK([tail -2 stdout], [0],
  [Megaflow: recirc_id=0,skb_priority=0,eth,ip,in_port=9,nw_tos=252,nw_frag=no
Datapath actions: dnl
100,dnl
set(ipv4(tos=0x4/0xfc)),set(skb_priority(0x1)),1,dnl
set(ipv4(tos=0x8/0xfc)),set(skb_priority(0x2)),1,dnl
1,dnl
set(ipv4(tos=0x4/0xfc)),set(skb_priority(0x1)),1,dnl
set(ipv4(tos=0xfc/0xfc)),set(skb_priority(0)),1,dnl
set(ipv4(tos=0/0xfc)),1,100
])
OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - output/flood flags])
OVS_VSWITCHD_START
add_of_ports br0 1 2 3 4 5 6 7

AT_DATA([flows.txt], [dnl
in_port=local actions=local,flood
in_port=1 actions=flood
in_port=2 actions=all
in_port=3 actions=output:LOCAL,output:1,output:2,output:3,output:4,output:5,output:6,output:7
in_port=4 actions=enqueue:LOCAL:1,enqueue:1:1,enqueue:2:1,enqueue:3:2,enqueue:4:1,enqueue:5:1,enqueue:6:1,enqueue:7:1
])
AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
AT_CHECK([ovs-ofctl mod-port br0 5 noforward])
AT_CHECK([ovs-ofctl mod-port br0 6 noflood])

AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(100),eth(src=00:00:00:00:00:01,dst=00:00:00:00:00:02),eth_type(0x0900)'], [0], [stdout])
AT_CHECK([tail -1 stdout \
| sed -e 's/Datapath actions: //' | tr ',' '\n' | sort], [0], [dnl
1
2
3
4
7
])

AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=00:00:00:00:00:01,dst=00:00:00:00:00:02),eth_type(0x0900)'], [0], [stdout])
AT_CHECK([tail -1 stdout \
| sed -e 's/Datapath actions: //' | tr ',' '\n' | sort], [0], [dnl
100
2
3
4
7
])

AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2),eth(src=00:00:00:00:00:01,dst=00:00:00:00:00:02),eth_type(0x0900)'], [0], [stdout])
AT_CHECK([tail -1 stdout \
| sed -e 's/Datapath actions: //' | tr ',' '\n' | sort], [0], [dnl
1
100
3
4
6
7
])

AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(3),eth(src=00:00:00:00:00:01,dst=00:00:00:00:00:02),eth_type(0x0900)'], [0], [stdout])
AT_CHECK([tail -1 stdout], [0],
  [Datapath actions: 100,1,2,4,6,7
])

AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(4),eth(src=00:00:00:00:00:01,dst=00:00:00:00:00:02),eth_type(0x0900)'], [0], [stdout])
AT_CHECK([tail -1 stdout], [0],
  [Datapath actions: set(skb_priority(0x1)),100,1,2,set(skb_priority(0x2)),3,set(skb_priority(0x1)),6,7
])
OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - Default Table Miss - OF1.0 (OFPTC_TABLE_MISS_CONTROLLER)])
OVS_VSWITCHD_START([dnl
   add-port br0 p1 -- set Interface p1 type=dummy
])
on_exit 'kill `cat ovs-ofctl.pid`'

AT_CAPTURE_FILE([ofctl_monitor.log])

AT_CHECK([ovs-ofctl -P nxt_packet_in monitor br0 65534 --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3 ; do
    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=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9),tcp_flags(syn)'
done
OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6])
OVS_APP_EXIT_AND_WAIT([ovs-ofctl])
AT_CHECK([cat ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): cookie=0x0 total_len=54 in_port=1 (via no_match) data_len=54 (unbuffered)
tcp,vlan_tci=0x0000,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_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=9,tcp_flags=syn tcp_csum:2e7e
dnl
NXT_PACKET_IN (xid=0x0): cookie=0x0 total_len=54 in_port=1 (via no_match) data_len=54 (unbuffered)
tcp,vlan_tci=0x0000,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_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=9,tcp_flags=syn tcp_csum:2e7e
dnl
NXT_PACKET_IN (xid=0x0): cookie=0x0 total_len=54 in_port=1 (via no_match) data_len=54 (unbuffered)
tcp,vlan_tci=0x0000,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_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=9,tcp_flags=syn tcp_csum:2e7e
])

AT_CHECK([ovs-appctl time/warp 5000], [0], [ignore])
AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
NXST_FLOW reply:
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - Default Table Miss - OF1.3 (OFPTC_TABLE_MISS_DROP)])
OVS_VSWITCHD_START([dnl
   add-port br0 p1 -- set Interface p1 type=dummy
])
on_exit 'kill `cat ovs-ofctl.pid`'

AT_CAPTURE_FILE([ofctl_monitor.log])
AT_CHECK([ovs-ofctl del-flows br0])

AT_CHECK([ovs-ofctl monitor -OOpenFlow13 -P standard br0 65534 --detach --no-chdir --pidfile 2> ofctl_monitor.log])

dnl Test that missed packets are dropped
for i in 1 2 3 ; do
    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=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9),tcp_flags(ack,syn)'
done
OVS_APP_EXIT_AND_WAIT([ovs-ofctl])

AT_CHECK([cat ofctl_monitor.log], [0], [dnl
])

AT_CHECK([ovs-appctl time/warp 5000], [0], [ignore])
AT_CHECK([ovs-ofctl -OOpenFlow13 dump-flows br0 | ofctl_strip | sort], [0], [dnl
OFPST_FLOW reply (OF1.3):
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - Table Miss - goto table and OFPTC_TABLE_MISS_CONTROLLER])
OVS_VSWITCHD_START([dnl
   add-port br0 p1 -- set Interface p1 type=dummy
])
on_exit 'kill `cat ovs-ofctl.pid`'

AT_CAPTURE_FILE([ofctl_monitor.log])
AT_CHECK([ovs-ofctl -OOpenFlow12 add-flow br0 'table=0 actions=goto_table(1)'])

AT_CHECK([ovs-ofctl monitor -P standard br0 65534 --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3 ; do
    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=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9),tcp_flags(urg|rst)'
done
OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6])
OVS_APP_EXIT_AND_WAIT([ovs-ofctl])
AT_CHECK([cat ofctl_monitor.log], [0], [dnl
OFPT_PACKET_IN (xid=0x0): total_len=54 in_port=1 (via no_match) data_len=54 (unbuffered)
tcp,vlan_tci=0x0000,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_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=9,tcp_flags=rst|urg tcp_csum:2e5c
dnl
OFPT_PACKET_IN (xid=0x0): total_len=54 in_port=1 (via no_match) data_len=54 (unbuffered)
tcp,vlan_tci=0x0000,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_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=9,tcp_flags=rst|urg tcp_csum:2e5c
dnl
OFPT_PACKET_IN (xid=0x0): total_len=54 in_port=1 (via no_match) data_len=54 (unbuffered)
tcp,vlan_tci=0x0000,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_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=9,tcp_flags=rst|urg tcp_csum:2e5c
])

AT_CHECK([ovs-appctl revalidator/purge], [0])
AT_CHECK([ovs-ofctl -OOpenFlow12 dump-flows br0 | ofctl_strip | sort], [0], [dnl
 n_packets=3, n_bytes=162, actions=goto_table:1
OFPST_FLOW reply (OF1.2):
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - Table Miss - resubmit and OFPTC_TABLE_MISS_CONTROLLER])
OVS_VSWITCHD_START([dnl
   add-port br0 p1 -- set Interface p1 type=dummy
])
on_exit 'kill `cat ovs-ofctl.pid`'

AT_CAPTURE_FILE([ofctl_monitor.log])
AT_CHECK([ovs-ofctl -OOpenFlow12 add-flow br0 'table=0 actions=resubmit(1,1)'])

AT_CHECK([ovs-ofctl monitor -P standard br0 65534 --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3 ; do
    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=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9),tcp_flags(0x010)'
done

OVS_APP_EXIT_AND_WAIT([ovs-ofctl])
AT_CHECK([cat ofctl_monitor.log], [0], [dnl
])

AT_CHECK([ovs-appctl revalidator/purge], [0])
AT_CHECK([ovs-ofctl -OOpenFlow12 dump-flows br0 | ofctl_strip | sort], [0], [dnl
 n_packets=3, n_bytes=354, actions=resubmit(1,1)
OFPST_FLOW reply (OF1.2):
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - Table Miss - OFPTC_TABLE_MISS_CONTINUE])
OVS_VSWITCHD_START([dnl
   add-port br0 p1 -- set Interface p1 type=dummy
])
on_exit 'kill `cat ovs-ofctl.pid`'

AT_CAPTURE_FILE([ofctl_monitor.log])
AT_CHECK([ovs-ofctl add-flow br0 'table=1 dl_src=10:11:11:11:11:11 actions=controller'])
AT_CHECK([ovs-ofctl -OOpenFlow11 mod-table br0 all continue])

dnl Miss table 0, Hit table 1
AT_CHECK([ovs-ofctl monitor br0 65534 -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3 ; do
    ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=10:11:11:11:11:11,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=8,dst=9),tcp_flags(0x010)'
done
OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6])
OVS_APP_EXIT_AND_WAIT([ovs-ofctl])

AT_CHECK([cat ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): table_id=1 cookie=0x0 total_len=118 in_port=1 (via action) data_len=118 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=10:11:11:11:11:11,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=9,tcp_flags=ack tcp_csum:4a2c
dnl
NXT_PACKET_IN (xid=0x0): table_id=1 cookie=0x0 total_len=118 in_port=1 (via action) data_len=118 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=10:11:11:11:11:11,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=9,tcp_flags=ack tcp_csum:4a2c
dnl
NXT_PACKET_IN (xid=0x0): table_id=1 cookie=0x0 total_len=118 in_port=1 (via action) data_len=118 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=10:11:11:11:11:11,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=9,tcp_flags=ack tcp_csum:4a2c
])

dnl Hit table 0, Miss all other tables, sent to controller
AT_CHECK([ovs-ofctl monitor br0 65534 -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3 ; do
    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=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9),tcp_flags(0x010)'
done
OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6])
OVS_APP_EXIT_AND_WAIT([ovs-ofctl])

AT_CHECK([cat ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): table_id=253 cookie=0x0 total_len=118 in_port=1 (via no_match) data_len=118 (unbuffered)
tcp,vlan_tci=0x0000,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_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=9,tcp_flags=ack tcp_csum:4a2c
dnl
NXT_PACKET_IN (xid=0x0): table_id=253 cookie=0x0 total_len=118 in_port=1 (via no_match) data_len=118 (unbuffered)
tcp,vlan_tci=0x0000,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_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=9,tcp_flags=ack tcp_csum:4a2c
dnl
NXT_PACKET_IN (xid=0x0): table_id=253 cookie=0x0 total_len=118 in_port=1 (via no_match) data_len=118 (unbuffered)
tcp,vlan_tci=0x0000,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_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=9,tcp_flags=ack tcp_csum:4a2c
])

AT_CHECK([ovs-appctl revalidator/purge], [0])
AT_CHECK([ovs-ofctl -OOpenFlow12 dump-flows br0 | ofctl_strip | sort], [0], [dnl
 table=1, n_packets=3, n_bytes=354, dl_src=10:11:11:11:11:11 actions=CONTROLLER:65535
OFPST_FLOW reply (OF1.2):
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - Table Miss - goto table and OFPTC_TABLE_MISS_CONTINUE])
OVS_VSWITCHD_START([dnl
   add-port br0 p1 -- set Interface p1 type=dummy
])
on_exit 'kill `cat ovs-ofctl.pid`'

AT_CAPTURE_FILE([ofctl_monitor.log])
AT_DATA([flows.txt], [dnl
table=0 actions=goto_table(1)
table=2 dl_src=10:11:11:11:11:11 actions=controller
])
AT_CHECK([ovs-ofctl -OOpenFlow12 add-flows br0 flows.txt])
AT_CHECK([ovs-ofctl -OOpenFlow11 mod-table br0 all continue])

dnl Hit table 0, Miss table 1, Hit table 2
AT_CHECK([ovs-ofctl monitor br0 65534 -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3 ; do
    ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=10:11:11:11:11:11,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=8,dst=9),tcp_flags(0x010)'
done
OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6])
OVS_APP_EXIT_AND_WAIT(ovs-ofctl)

AT_CHECK([cat ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): table_id=2 cookie=0x0 total_len=118 in_port=1 (via action) data_len=118 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=10:11:11:11:11:11,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=9,tcp_flags=ack tcp_csum:4a2c
dnl
NXT_PACKET_IN (xid=0x0): table_id=2 cookie=0x0 total_len=118 in_port=1 (via action) data_len=118 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=10:11:11:11:11:11,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=9,tcp_flags=ack tcp_csum:4a2c
dnl
NXT_PACKET_IN (xid=0x0): table_id=2 cookie=0x0 total_len=118 in_port=1 (via action) data_len=118 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=10:11:11:11:11:11,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=9,tcp_flags=ack tcp_csum:4a2c
])

dnl Hit table 1, Miss all other tables, sent to controller
AT_CHECK([ovs-ofctl monitor br0 65534 -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3 ; do
    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=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9),tcp_flags(0x010)'
done
OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6])
OVS_APP_EXIT_AND_WAIT([ovs-ofctl])

AT_CHECK([cat ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): table_id=253 cookie=0x0 total_len=118 in_port=1 (via no_match) data_len=118 (unbuffered)
tcp,vlan_tci=0x0000,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_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=9,tcp_flags=ack tcp_csum:4a2c
dnl
NXT_PACKET_IN (xid=0x0): table_id=253 cookie=0x0 total_len=118 in_port=1 (via no_match) data_len=118 (unbuffered)
tcp,vlan_tci=0x0000,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_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=9,tcp_flags=ack tcp_csum:4a2c
dnl
NXT_PACKET_IN (xid=0x0): table_id=253 cookie=0x0 total_len=118 in_port=1 (via no_match) data_len=118 (unbuffered)
tcp,vlan_tci=0x0000,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_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=9,tcp_flags=ack tcp_csum:4a2c
])

AT_CHECK([ovs-appctl revalidator/purge], [0])
AT_CHECK([ovs-ofctl -OOpenFlow12 dump-flows br0 | ofctl_strip | sort], [0], [dnl
 n_packets=6, n_bytes=708, actions=goto_table:1
 table=2, n_packets=3, n_bytes=354, dl_src=10:11:11:11:11:11 actions=CONTROLLER:65535
OFPST_FLOW reply (OF1.2):
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - Table Miss - resubmit and OFPTC_TABLE_MISS_CONTINUE])
OVS_VSWITCHD_START([dnl
   add-port br0 p1 -- set Interface p1 type=dummy
])
on_exit 'kill `cat ovs-ofctl.pid`'

AT_CAPTURE_FILE([ofctl_monitor.log])
AT_DATA([flows.txt], [dnl
table=0 actions=resubmit(1,1)
table=2 dl_src=10:11:11:11:11:11 actions=controller
])
AT_CHECK([ovs-ofctl -OOpenFlow12 add-flows br0 flows.txt])
AT_CHECK([ovs-ofctl -OOpenFlow11 mod-table br0 all continue])

dnl Hit table 0, Miss table 1, Dropped
AT_CHECK([ovs-ofctl monitor br0 65534 -P standard --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3 ; do
    ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=10:11:11:11:11:11,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=8,dst=9),tcp_flags(0x010)'
done
OVS_APP_EXIT_AND_WAIT(ovs-ofctl)

AT_CHECK([cat ofctl_monitor.log], [0], [dnl
])

dnl Hit table 1, Dropped
AT_CHECK([ovs-ofctl monitor br0 65534 -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3 ; do
    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=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9),tcp_flags(0x010)'
done
OVS_APP_EXIT_AND_WAIT([ovs-ofctl])

AT_CHECK([cat ofctl_monitor.log], [0], [dnl
])

AT_CHECK([ovs-appctl revalidator/purge], [0])
AT_CHECK([ovs-ofctl -OOpenFlow12 dump-flows br0 | ofctl_strip | sort], [0], [dnl
 n_packets=6, n_bytes=708, actions=resubmit(1,1)
 table=2, dl_src=10:11:11:11:11:11 actions=CONTROLLER:65535
OFPST_FLOW reply (OF1.2):
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - Table Miss - OFPTC_TABLE_MISS_DROP])
OVS_VSWITCHD_START([dnl
   add-port br0 p1 -- set Interface p1 type=dummy
])
on_exit 'kill `cat ovs-ofctl.pid`'

AT_CAPTURE_FILE([ofctl_monitor.log])
AT_CHECK([ovs-ofctl -OOpenFlow11 mod-table br0 all drop])

AT_CHECK([ovs-ofctl monitor -P standard br0 65534 --detach --no-chdir --pidfile 2> ofctl_monitor.log])

dnl Test that missed packets are dropped
for i in 1 2 3 ; do
    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=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9),tcp_flags(0x010)'
done
OVS_APP_EXIT_AND_WAIT([ovs-ofctl])

AT_CHECK([cat ofctl_monitor.log], [0], [dnl
])

AT_CHECK([ovs-appctl time/warp 5000], [0], [ignore])
AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
NXST_FLOW reply:
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - Table Miss - goto table and OFPTC_TABLE_MISS_DROP])
OVS_VSWITCHD_START([dnl
   add-port br0 p1 -- set Interface p1 type=dummy
])
on_exit 'kill `cat ovs-ofctl.pid`'

AT_CAPTURE_FILE([ofctl_monitor.log])
AT_CHECK([ovs-ofctl del-flows br0])
AT_CHECK([ovs-ofctl -OOpenFlow12 add-flow br0 'table=0 actions=goto_table(1)'])
AT_CHECK([ovs-ofctl -OOpenFlow11 mod-table br0 all drop])

AT_CHECK([ovs-ofctl monitor -P standard br0 65534 --detach --no-chdir --pidfile 2> ofctl_monitor.log])

dnl Test that missed packets are dropped
for i in 1 2 3 ; do
    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=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9),tcp_flags(0x010)'
done
OVS_APP_EXIT_AND_WAIT([ovs-ofctl])

AT_CHECK([cat ofctl_monitor.log], [0], [dnl
])

AT_CHECK([ovs-appctl revalidator/purge], [0])
AT_CHECK([ovs-ofctl -OOpenFlow12 dump-flows br0 | ofctl_strip | sort], [0], [dnl
 n_packets=3, n_bytes=354, actions=goto_table:1
OFPST_FLOW reply (OF1.2):
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - Table Miss - resubmit and OFPTC_TABLE_MISS_DROP])
OVS_VSWITCHD_START([dnl
   add-port br0 p1 -- set Interface p1 type=dummy
])
on_exit 'kill `cat ovs-ofctl.pid`'

AT_CAPTURE_FILE([ofctl_monitor.log])
AT_CHECK([ovs-ofctl del-flows br0])
AT_CHECK([ovs-ofctl -OOpenFlow12 add-flow br0 'table=0 actions=resubmit(1,1)'])
AT_CHECK([ovs-ofctl -OOpenFlow11 mod-table br0 all drop])

AT_CHECK([ovs-ofctl monitor -P standard br0 65534 --detach --no-chdir --pidfile 2> ofctl_monitor.log])

dnl Test that missed packets are dropped
for i in 1 2 3 ; do
    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=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9),tcp_flags(0x010)'
done
OVS_APP_EXIT_AND_WAIT([ovs-ofctl])

AT_CHECK([cat ofctl_monitor.log], [0], [dnl
])

AT_CHECK([ovs-appctl revalidator/purge], [0])
AT_CHECK([ovs-ofctl -OOpenFlow12 dump-flows br0 | ofctl_strip | sort], [0], [dnl
 n_packets=3, n_bytes=354, actions=resubmit(1,1)
OFPST_FLOW reply (OF1.2):
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - controller])
OVS_VSWITCHD_START([dnl
   add-port br0 p1 -- set Interface p1 type=dummy
])
on_exit 'kill `cat ovs-ofctl.pid`'

AT_CAPTURE_FILE([ofctl_monitor.log])
AT_DATA([flows.txt], [dnl
cookie=0x0 dl_src=10:11:11:11:11:11 actions=controller
cookie=0x1 dl_src=20:22:22:22:22:22 actions=controller,resubmit(80,1)
cookie=0x2 dl_src=30:33:33:33:33:33 actions=mod_vlan_vid:15,controller

cookie=0x3 table=1 in_port=80 actions=load:1->NXM_NX_REG0[[]],mod_vlan_vid:80,controller,resubmit(81,2)
cookie=0x4 table=2 in_port=81 actions=load:2->NXM_NX_REG1[[]],mod_dl_src:80:81:81:81:81:81,controller,resubmit(82,3)
cookie=0x5 table=3 in_port=82 actions=load:3->NXM_NX_REG2[[]],mod_dl_dst:82:82:82:82:82:82,controller,resubmit(83,4)
cookie=0x6 table=4 in_port=83 actions=load:4->NXM_NX_REG3[[]],mod_nw_src:83.83.83.83,controller,resubmit(84,5)
cookie=0x7 table=5 in_port=84 actions=load:5->NXM_NX_REG4[[]],load:6->NXM_NX_TUN_ID[[]],mod_nw_dst:84.84.84.84,controller,resubmit(85,6)
cookie=0x8 table=6 in_port=85 actions=mod_tp_src:85,controller,resubmit(86,7)
cookie=0x9 table=7 in_port=86 actions=mod_tp_dst:86,controller,controller
cookie=0xa dl_src=40:44:44:44:44:41 actions=mod_vlan_vid:99,mod_vlan_pcp:1,controller
cookie=0xd dl_src=80:88:88:88:88:88 arp actions=load:2->OXM_OF_ARP_OP[[]],controller,load:0xc0a88001->OXM_OF_ARP_SPA[[]],controller,load:0x404444444441->OXM_OF_ARP_THA[[]],load:0x01010101->OXM_OF_ARP_SPA[[]],load:0x02020202->OXM_OF_ARP_TPA[[]],controller
])
AT_CHECK([ovs-ofctl add-flows br0 flows.txt])

dnl Flow miss.
AT_CHECK([ovs-ofctl monitor -P standard br0 65534 --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3 ; do
    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=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9),tcp_flags(0x010)'
done
OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6])
OVS_APP_EXIT_AND_WAIT(ovs-ofctl)

AT_CHECK([cat ofctl_monitor.log], [0], [dnl
OFPT_PACKET_IN (xid=0x0): total_len=118 in_port=1 (via no_match) data_len=118 (unbuffered)
tcp,vlan_tci=0x0000,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_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=9,tcp_flags=ack tcp_csum:4a2c
dnl
OFPT_PACKET_IN (xid=0x0): total_len=118 in_port=1 (via no_match) data_len=118 (unbuffered)
tcp,vlan_tci=0x0000,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_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=9,tcp_flags=ack tcp_csum:4a2c
dnl
OFPT_PACKET_IN (xid=0x0): total_len=118 in_port=1 (via no_match) data_len=118 (unbuffered)
tcp,vlan_tci=0x0000,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_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=9,tcp_flags=ack tcp_csum:4a2c
])

dnl Singleton controller action.
AT_CHECK([ovs-ofctl monitor -P standard br0 65534 --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3 ; do
    ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=10:11:11:11:11:11,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=8,dst=10),tcp_flags(0x002)'
done
OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6])
OVS_APP_EXIT_AND_WAIT(ovs-ofctl)

AT_CHECK([cat ofctl_monitor.log], [0], [dnl
OFPT_PACKET_IN (xid=0x0): total_len=54 in_port=1 (via action) data_len=54 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=10:11:11:11:11:11,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=10,tcp_flags=syn tcp_csum:2e7d
OFPT_PACKET_IN (xid=0x0): total_len=54 in_port=1 (via action) data_len=54 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=10:11:11:11:11:11,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=10,tcp_flags=syn tcp_csum:2e7d
OFPT_PACKET_IN (xid=0x0): total_len=54 in_port=1 (via action) data_len=54 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=10:11:11:11:11:11,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=10,tcp_flags=syn tcp_csum:2e7d
])

dnl Modified controller action.
AT_CHECK([ovs-ofctl monitor -P standard br0 65534 --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3 ; do
    ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=30:33:33:33:33:33,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=8,dst=10),tcp_flags(0x001)'
done
OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6])
OVS_APP_EXIT_AND_WAIT(ovs-ofctl)

AT_CHECK([cat ofctl_monitor.log], [0], [dnl
OFPT_PACKET_IN (xid=0x0): total_len=58 in_port=1 (via action) data_len=58 (unbuffered)
tcp,dl_vlan=15,dl_vlan_pcp=0,vlan_tci1=0x0000,dl_src=30:33:33:33:33:33,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=10,tcp_flags=fin tcp_csum:2e7e
dnl
OFPT_PACKET_IN (xid=0x0): total_len=58 in_port=1 (via action) data_len=58 (unbuffered)
tcp,dl_vlan=15,dl_vlan_pcp=0,vlan_tci1=0x0000,dl_src=30:33:33:33:33:33,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=10,tcp_flags=fin tcp_csum:2e7e
dnl
OFPT_PACKET_IN (xid=0x0): total_len=58 in_port=1 (via action) data_len=58 (unbuffered)
tcp,dl_vlan=15,dl_vlan_pcp=0,vlan_tci1=0x0000,dl_src=30:33:33:33:33:33,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=10,tcp_flags=fin tcp_csum:2e7e
])

dnl Modified VLAN controller action.
AT_CHECK([ovs-ofctl monitor br0 65534 -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3; do
    ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=40:44:44:44:44:41,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=16,tos=0,ttl=64,frag=no)'
done
OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6])
OVS_APP_EXIT_AND_WAIT(ovs-ofctl)

AT_CHECK([cat ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=38 in_port=1 (via action) data_len=38 (unbuffered)
ip,dl_vlan=99,dl_vlan_pcp=1,vlan_tci1=0x0000,dl_src=40:44:44:44:44:41,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_proto=16,nw_tos=0,nw_ecn=0,nw_ttl=64
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=38 in_port=1 (via action) data_len=38 (unbuffered)
ip,dl_vlan=99,dl_vlan_pcp=1,vlan_tci1=0x0000,dl_src=40:44:44:44:44:41,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_proto=16,nw_tos=0,nw_ecn=0,nw_ttl=64
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=38 in_port=1 (via action) data_len=38 (unbuffered)
ip,dl_vlan=99,dl_vlan_pcp=1,vlan_tci1=0x0000,dl_src=40:44:44:44:44:41,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_proto=16,nw_tos=0,nw_ecn=0,nw_ttl=64
])

dnl Checksum TCP.
AT_CHECK([ovs-ofctl monitor br0 65534 -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 ; do
    ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=20:22:22:22:22:22,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=8,dst=11),tcp_flags(0x001)'
done
OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 18])
OVS_APP_EXIT_AND_WAIT([ovs-ofctl])

AT_CHECK([cat ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): cookie=0x1 total_len=54 in_port=1 (via action) data_len=54 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=20:22:22:22:22:22,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=11,tcp_flags=fin tcp_csum:2e7d
dnl
NXT_PACKET_IN (xid=0x0): table_id=1 cookie=0x3 total_len=58 reg0=0x1,in_port=1 (via action) data_len=58 (unbuffered)
tcp,dl_vlan=80,dl_vlan_pcp=0,vlan_tci1=0x0000,dl_src=20:22:22:22:22:22,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=11,tcp_flags=fin tcp_csum:2e7d
dnl
NXT_PACKET_IN (xid=0x0): table_id=2 cookie=0x4 total_len=58 reg0=0x1,reg1=0x2,in_port=1 (via action) data_len=58 (unbuffered)
tcp,dl_vlan=80,dl_vlan_pcp=0,vlan_tci1=0x0000,dl_src=80:81:81:81:81:81,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=11,tcp_flags=fin tcp_csum:2e7d
dnl
NXT_PACKET_IN (xid=0x0): table_id=3 cookie=0x5 total_len=58 reg0=0x1,reg1=0x2,reg2=0x3,in_port=1 (via action) data_len=58 (unbuffered)
tcp,dl_vlan=80,dl_vlan_pcp=0,vlan_tci1=0x0000,dl_src=80:81:81:81:81:81,dl_dst=82:82:82:82:82:82,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=11,tcp_flags=fin tcp_csum:2e7d
dnl
NXT_PACKET_IN (xid=0x0): table_id=4 cookie=0x6 total_len=58 reg0=0x1,reg1=0x2,reg2=0x3,reg3=0x4,in_port=1 (via action) data_len=58 (unbuffered)
tcp,dl_vlan=80,dl_vlan_pcp=0,vlan_tci1=0x0000,dl_src=80:81:81:81:81:81,dl_dst=82:82:82:82:82:82,nw_src=83.83.83.83,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=11,tcp_flags=fin tcp_csum:4880
dnl
NXT_PACKET_IN (xid=0x0): table_id=5 cookie=0x7 total_len=58 reg0=0x1,reg1=0x2,reg2=0x3,reg3=0x4,reg4=0x5,tun_id=0x6,in_port=1 (via action) data_len=58 (unbuffered)
tcp,dl_vlan=80,dl_vlan_pcp=0,vlan_tci1=0x0000,dl_src=80:81:81:81:81:81,dl_dst=82:82:82:82:82:82,nw_src=83.83.83.83,nw_dst=84.84.84.84,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=11,tcp_flags=fin tcp_csum:6082
dnl
NXT_PACKET_IN (xid=0x0): table_id=6 cookie=0x8 total_len=58 reg0=0x1,reg1=0x2,reg2=0x3,reg3=0x4,reg4=0x5,tun_id=0x6,in_port=1 (via action) data_len=58 (unbuffered)
tcp,dl_vlan=80,dl_vlan_pcp=0,vlan_tci1=0x0000,dl_src=80:81:81:81:81:81,dl_dst=82:82:82:82:82:82,nw_src=83.83.83.83,nw_dst=84.84.84.84,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=85,tp_dst=11,tcp_flags=fin tcp_csum:6035
dnl
NXT_PACKET_IN (xid=0x0): table_id=7 cookie=0x9 total_len=58 reg0=0x1,reg1=0x2,reg2=0x3,reg3=0x4,reg4=0x5,tun_id=0x6,in_port=1 (via action) data_len=58 (unbuffered)
tcp,dl_vlan=80,dl_vlan_pcp=0,vlan_tci1=0x0000,dl_src=80:81:81:81:81:81,dl_dst=82:82:82:82:82:82,nw_src=83.83.83.83,nw_dst=84.84.84.84,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=85,tp_dst=86,tcp_flags=fin tcp_csum:5fea
dnl
NXT_PACKET_IN (xid=0x0): table_id=7 cookie=0x9 total_len=58 reg0=0x1,reg1=0x2,reg2=0x3,reg3=0x4,reg4=0x5,tun_id=0x6,in_port=1 (via action) data_len=58 (unbuffered)
tcp,dl_vlan=80,dl_vlan_pcp=0,vlan_tci1=0x0000,dl_src=80:81:81:81:81:81,dl_dst=82:82:82:82:82:82,nw_src=83.83.83.83,nw_dst=84.84.84.84,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=85,tp_dst=86,tcp_flags=fin tcp_csum:5fea
])

dnl Checksum UDP.
AT_CHECK([ovs-ofctl monitor br0 65534 -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 ; do
    ovs-appctl netdev-dummy/receive p1 '50 54 00 00 00 07 20 22 22 22 22 22 08 00 45 00 00 1C 00 00 00 00 00 11 00 00 C0 A8 00 01 C0 A8 00 02 00 08 00 0B 00 00 12 34 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00'
done
OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 18])
OVS_APP_EXIT_AND_WAIT([ovs-ofctl])

AT_CHECK([cat ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): cookie=0x1 total_len=60 in_port=1 (via action) data_len=60 (unbuffered)
udp,vlan_tci=0x0000,dl_src=20:22:22:22:22:22,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=0,tp_src=8,tp_dst=11 udp_csum:1234
dnl
NXT_PACKET_IN (xid=0x0): table_id=1 cookie=0x3 total_len=64 reg0=0x1,in_port=1 (via action) data_len=64 (unbuffered)
udp,dl_vlan=80,dl_vlan_pcp=0,vlan_tci1=0x0000,dl_src=20:22:22:22:22:22,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=0,tp_src=8,tp_dst=11 udp_csum:1234
dnl
NXT_PACKET_IN (xid=0x0): table_id=2 cookie=0x4 total_len=64 reg0=0x1,reg1=0x2,in_port=1 (via action) data_len=64 (unbuffered)
udp,dl_vlan=80,dl_vlan_pcp=0,vlan_tci1=0x0000,dl_src=80:81:81:81:81:81,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=0,tp_src=8,tp_dst=11 udp_csum:1234
dnl
NXT_PACKET_IN (xid=0x0): table_id=3 cookie=0x5 total_len=64 reg0=0x1,reg1=0x2,reg2=0x3,in_port=1 (via action) data_len=64 (unbuffered)
udp,dl_vlan=80,dl_vlan_pcp=0,vlan_tci1=0x0000,dl_src=80:81:81:81:81:81,dl_dst=82:82:82:82:82:82,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=0,tp_src=8,tp_dst=11 udp_csum:1234
dnl
NXT_PACKET_IN (xid=0x0): table_id=4 cookie=0x6 total_len=64 reg0=0x1,reg1=0x2,reg2=0x3,reg3=0x4,in_port=1 (via action) data_len=64 (unbuffered)
udp,dl_vlan=80,dl_vlan_pcp=0,vlan_tci1=0x0000,dl_src=80:81:81:81:81:81,dl_dst=82:82:82:82:82:82,nw_src=83.83.83.83,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=0,tp_src=8,tp_dst=11 udp_csum:2c37
dnl
NXT_PACKET_IN (xid=0x0): table_id=5 cookie=0x7 total_len=64 reg0=0x1,reg1=0x2,reg2=0x3,reg3=0x4,reg4=0x5,tun_id=0x6,in_port=1 (via action) data_len=64 (unbuffered)
udp,dl_vlan=80,dl_vlan_pcp=0,vlan_tci1=0x0000,dl_src=80:81:81:81:81:81,dl_dst=82:82:82:82:82:82,nw_src=83.83.83.83,nw_dst=84.84.84.84,nw_tos=0,nw_ecn=0,nw_ttl=0,tp_src=8,tp_dst=11 udp_csum:4439
dnl
NXT_PACKET_IN (xid=0x0): table_id=6 cookie=0x8 total_len=64 reg0=0x1,reg1=0x2,reg2=0x3,reg3=0x4,reg4=0x5,tun_id=0x6,in_port=1 (via action) data_len=64 (unbuffered)
udp,dl_vlan=80,dl_vlan_pcp=0,vlan_tci1=0x0000,dl_src=80:81:81:81:81:81,dl_dst=82:82:82:82:82:82,nw_src=83.83.83.83,nw_dst=84.84.84.84,nw_tos=0,nw_ecn=0,nw_ttl=0,tp_src=85,tp_dst=11 udp_csum:43ec
dnl
NXT_PACKET_IN (xid=0x0): table_id=7 cookie=0x9 total_len=64 reg0=0x1,reg1=0x2,reg2=0x3,reg3=0x4,reg4=0x5,tun_id=0x6,in_port=1 (via action) data_len=64 (unbuffered)
udp,dl_vlan=80,dl_vlan_pcp=0,vlan_tci1=0x0000,dl_src=80:81:81:81:81:81,dl_dst=82:82:82:82:82:82,nw_src=83.83.83.83,nw_dst=84.84.84.84,nw_tos=0,nw_ecn=0,nw_ttl=0,tp_src=85,tp_dst=86 udp_csum:43a1
dnl
NXT_PACKET_IN (xid=0x0): table_id=7 cookie=0x9 total_len=64 reg0=0x1,reg1=0x2,reg2=0x3,reg3=0x4,reg4=0x5,tun_id=0x6,in_port=1 (via action) data_len=64 (unbuffered)
udp,dl_vlan=80,dl_vlan_pcp=0,vlan_tci1=0x0000,dl_src=80:81:81:81:81:81,dl_dst=82:82:82:82:82:82,nw_src=83.83.83.83,nw_dst=84.84.84.84,nw_tos=0,nw_ecn=0,nw_ttl=0,tp_src=85,tp_dst=86 udp_csum:43a1
])

dnl Modified ARP controller action.
AT_CHECK([ovs-ofctl monitor br0 65534 -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3; do
    ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=80:88:88:88:88:88,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:05,tha=00:00:00:00:00:00)'
done

OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 18])
OVS_APP_EXIT_AND_WAIT([ovs-ofctl])
AT_CHECK([cat ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): cookie=0xd total_len=42 in_port=1 (via action) data_len=42 (unbuffered)
arp,vlan_tci=0x0000,dl_src=80:88:88:88:88:88,dl_dst=ff:ff:ff:ff:ff:ff,arp_spa=192.168.0.1,arp_tpa=192.168.0.2,arp_op=2,arp_sha=50:54:00:00:00:05,arp_tha=00:00:00:00:00:00
NXT_PACKET_IN (xid=0x0): cookie=0xd total_len=42 in_port=1 (via action) data_len=42 (unbuffered)
arp,vlan_tci=0x0000,dl_src=80:88:88:88:88:88,dl_dst=ff:ff:ff:ff:ff:ff,arp_spa=192.168.128.1,arp_tpa=192.168.0.2,arp_op=2,arp_sha=50:54:00:00:00:05,arp_tha=00:00:00:00:00:00
NXT_PACKET_IN (xid=0x0): cookie=0xd total_len=42 in_port=1 (via action) data_len=42 (unbuffered)
arp,vlan_tci=0x0000,dl_src=80:88:88:88:88:88,dl_dst=ff:ff:ff:ff:ff:ff,arp_spa=1.1.1.1,arp_tpa=2.2.2.2,arp_op=2,arp_sha=50:54:00:00:00:05,arp_tha=40:44:44:44:44:41
NXT_PACKET_IN (xid=0x0): cookie=0xd total_len=42 in_port=1 (via action) data_len=42 (unbuffered)
arp,vlan_tci=0x0000,dl_src=80:88:88:88:88:88,dl_dst=ff:ff:ff:ff:ff:ff,arp_spa=192.168.0.1,arp_tpa=192.168.0.2,arp_op=2,arp_sha=50:54:00:00:00:05,arp_tha=00:00:00:00:00:00
NXT_PACKET_IN (xid=0x0): cookie=0xd total_len=42 in_port=1 (via action) data_len=42 (unbuffered)
arp,vlan_tci=0x0000,dl_src=80:88:88:88:88:88,dl_dst=ff:ff:ff:ff:ff:ff,arp_spa=192.168.128.1,arp_tpa=192.168.0.2,arp_op=2,arp_sha=50:54:00:00:00:05,arp_tha=00:00:00:00:00:00
NXT_PACKET_IN (xid=0x0): cookie=0xd total_len=42 in_port=1 (via action) data_len=42 (unbuffered)
arp,vlan_tci=0x0000,dl_src=80:88:88:88:88:88,dl_dst=ff:ff:ff:ff:ff:ff,arp_spa=1.1.1.1,arp_tpa=2.2.2.2,arp_op=2,arp_sha=50:54:00:00:00:05,arp_tha=40:44:44:44:44:41
NXT_PACKET_IN (xid=0x0): cookie=0xd total_len=42 in_port=1 (via action) data_len=42 (unbuffered)
arp,vlan_tci=0x0000,dl_src=80:88:88:88:88:88,dl_dst=ff:ff:ff:ff:ff:ff,arp_spa=192.168.0.1,arp_tpa=192.168.0.2,arp_op=2,arp_sha=50:54:00:00:00:05,arp_tha=00:00:00:00:00:00
NXT_PACKET_IN (xid=0x0): cookie=0xd total_len=42 in_port=1 (via action) data_len=42 (unbuffered)
arp,vlan_tci=0x0000,dl_src=80:88:88:88:88:88,dl_dst=ff:ff:ff:ff:ff:ff,arp_spa=192.168.128.1,arp_tpa=192.168.0.2,arp_op=2,arp_sha=50:54:00:00:00:05,arp_tha=00:00:00:00:00:00
NXT_PACKET_IN (xid=0x0): cookie=0xd total_len=42 in_port=1 (via action) data_len=42 (unbuffered)
arp,vlan_tci=0x0000,dl_src=80:88:88:88:88:88,dl_dst=ff:ff:ff:ff:ff:ff,arp_spa=1.1.1.1,arp_tpa=2.2.2.2,arp_op=2,arp_sha=50:54:00:00:00:05,arp_tha=40:44:44:44:44:41
])

AT_CHECK([ovs-appctl time/warp 5000], [0], [ignore])

dnl Checksum SCTP.
AT_CHECK([ovs-ofctl monitor br0 65534 -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 ; do
    ovs-appctl netdev-dummy/receive p1 '50 54 00 00 00 07 20 22 22 22 22 22 08 00 45 00 00 24 00 00 00 00 00 84 00 00 C0 A8 00 01 C0 A8 00 02 04 58 08 af 00 00 00 00 d9 d7 91 57 01 00 00 34 cf 28 ec 4e 00 01 40 00 00 0a ff ff b7 53 24 19 00 05 00 08 7f 00 00 01 00 05 00 08 c0 a8 02 07 00 0c 00 06 00 05 00 00 80 00 00 04 c0 00 00 04'
done

AT_CHECK([ovs-appctl time/warp 1000], [0], [ignore])
OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 18])
OVS_APP_EXIT_AND_WAIT([ovs-ofctl])
AT_CHECK([cat ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): cookie=0x1 total_len=98 in_port=1 (via action) data_len=98 (unbuffered)
sctp,vlan_tci=0x0000,dl_src=20:22:22:22:22:22,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=0,tp_src=1112,tp_dst=2223 sctp_csum:d9d79157
dnl
NXT_PACKET_IN (xid=0x0): table_id=1 cookie=0x3 total_len=102 reg0=0x1,in_port=1 (via action) data_len=102 (unbuffered)
sctp,dl_vlan=80,dl_vlan_pcp=0,vlan_tci1=0x0000,dl_src=20:22:22:22:22:22,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=0,tp_src=1112,tp_dst=2223 sctp_csum:d9d79157
dnl
NXT_PACKET_IN (xid=0x0): table_id=2 cookie=0x4 total_len=102 reg0=0x1,reg1=0x2,in_port=1 (via action) data_len=102 (unbuffered)
sctp,dl_vlan=80,dl_vlan_pcp=0,vlan_tci1=0x0000,dl_src=80:81:81:81:81:81,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=0,tp_src=1112,tp_dst=2223 sctp_csum:d9d79157
dnl
NXT_PACKET_IN (xid=0x0): table_id=3 cookie=0x5 total_len=102 reg0=0x1,reg1=0x2,reg2=0x3,in_port=1 (via action) data_len=102 (unbuffered)
sctp,dl_vlan=80,dl_vlan_pcp=0,vlan_tci1=0x0000,dl_src=80:81:81:81:81:81,dl_dst=82:82:82:82:82:82,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=0,tp_src=1112,tp_dst=2223 sctp_csum:d9d79157
dnl
NXT_PACKET_IN (xid=0x0): table_id=4 cookie=0x6 total_len=102 reg0=0x1,reg1=0x2,reg2=0x3,reg3=0x4,in_port=1 (via action) data_len=102 (unbuffered)
sctp,dl_vlan=80,dl_vlan_pcp=0,vlan_tci1=0x0000,dl_src=80:81:81:81:81:81,dl_dst=82:82:82:82:82:82,nw_src=83.83.83.83,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=0,tp_src=1112,tp_dst=2223 sctp_csum:d9d79157
dnl
NXT_PACKET_IN (xid=0x0): table_id=5 cookie=0x7 total_len=102 reg0=0x1,reg1=0x2,reg2=0x3,reg3=0x4,reg4=0x5,tun_id=0x6,in_port=1 (via action) data_len=102 (unbuffered)
sctp,dl_vlan=80,dl_vlan_pcp=0,vlan_tci1=0x0000,dl_src=80:81:81:81:81:81,dl_dst=82:82:82:82:82:82,nw_src=83.83.83.83,nw_dst=84.84.84.84,nw_tos=0,nw_ecn=0,nw_ttl=0,tp_src=1112,tp_dst=2223 sctp_csum:d9d79157
dnl
NXT_PACKET_IN (xid=0x0): table_id=6 cookie=0x8 total_len=102 reg0=0x1,reg1=0x2,reg2=0x3,reg3=0x4,reg4=0x5,tun_id=0x6,in_port=1 (via action) data_len=102 (unbuffered)
sctp,dl_vlan=80,dl_vlan_pcp=0,vlan_tci1=0x0000,dl_src=80:81:81:81:81:81,dl_dst=82:82:82:82:82:82,nw_src=83.83.83.83,nw_dst=84.84.84.84,nw_tos=0,nw_ecn=0,nw_ttl=0,tp_src=85,tp_dst=2223 sctp_csum:dd778f5f
dnl
NXT_PACKET_IN (xid=0x0): table_id=7 cookie=0x9 total_len=102 reg0=0x1,reg1=0x2,reg2=0x3,reg3=0x4,reg4=0x5,tun_id=0x6,in_port=1 (via action) data_len=102 (unbuffered)
sctp,dl_vlan=80,dl_vlan_pcp=0,vlan_tci1=0x0000,dl_src=80:81:81:81:81:81,dl_dst=82:82:82:82:82:82,nw_src=83.83.83.83,nw_dst=84.84.84.84,nw_tos=0,nw_ecn=0,nw_ttl=0,tp_src=85,tp_dst=86 sctp_csum:62051f56
dnl
NXT_PACKET_IN (xid=0x0): table_id=7 cookie=0x9 total_len=102 reg0=0x1,reg1=0x2,reg2=0x3,reg3=0x4,reg4=0x5,tun_id=0x6,in_port=1 (via action) data_len=102 (unbuffered)
sctp,dl_vlan=80,dl_vlan_pcp=0,vlan_tci1=0x0000,dl_src=80:81:81:81:81:81,dl_dst=82:82:82:82:82:82,nw_src=83.83.83.83,nw_dst=84.84.84.84,nw_tos=0,nw_ecn=0,nw_ttl=0,tp_src=85,tp_dst=86 sctp_csum:62051f56
])

AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
 cookie=0x1, n_packets=3, n_bytes=212, dl_src=20:22:22:22:22:22 actions=CONTROLLER:65535,resubmit(80,1)
 cookie=0x2, n_packets=3, n_bytes=162, dl_src=30:33:33:33:33:33 actions=mod_vlan_vid:15,CONTROLLER:65535
 cookie=0x3, table=1, n_packets=3, n_bytes=212, in_port=80 actions=load:0x1->NXM_NX_REG0[[]],mod_vlan_vid:80,CONTROLLER:65535,resubmit(81,2)
 cookie=0x4, table=2, n_packets=3, n_bytes=212, in_port=81 actions=load:0x2->NXM_NX_REG1[[]],mod_dl_src:80:81:81:81:81:81,CONTROLLER:65535,resubmit(82,3)
 cookie=0x5, table=3, n_packets=3, n_bytes=212, in_port=82 actions=load:0x3->NXM_NX_REG2[[]],mod_dl_dst:82:82:82:82:82:82,CONTROLLER:65535,resubmit(83,4)
 cookie=0x6, table=4, n_packets=3, n_bytes=212, in_port=83 actions=load:0x4->NXM_NX_REG3[[]],mod_nw_src:83.83.83.83,CONTROLLER:65535,resubmit(84,5)
 cookie=0x7, table=5, n_packets=3, n_bytes=212, in_port=84 actions=load:0x5->NXM_NX_REG4[[]],load:0x6->NXM_NX_TUN_ID[[]],mod_nw_dst:84.84.84.84,CONTROLLER:65535,resubmit(85,6)
 cookie=0x8, table=6, n_packets=3, n_bytes=212, in_port=85 actions=mod_tp_src:85,CONTROLLER:65535,resubmit(86,7)
 cookie=0x9, table=7, n_packets=3, n_bytes=212, in_port=86 actions=mod_tp_dst:86,CONTROLLER:65535,CONTROLLER:65535
 cookie=0xa, n_packets=3, n_bytes=102, dl_src=40:44:44:44:44:41 actions=mod_vlan_vid:99,mod_vlan_pcp:1,CONTROLLER:65535
 cookie=0xd, n_packets=3, n_bytes=126, arp,dl_src=80:88:88:88:88:88 actions=load:0x2->NXM_OF_ARP_OP[[]],CONTROLLER:65535,load:0xc0a88001->NXM_OF_ARP_SPA[[]],CONTROLLER:65535,load:0x404444444441->NXM_NX_ARP_THA[[]],load:0x1010101->NXM_OF_ARP_SPA[[]],load:0x2020202->NXM_OF_ARP_TPA[[]],CONTROLLER:65535
 n_packets=3, n_bytes=162, dl_src=10:11:11:11:11:11 actions=CONTROLLER:65535
NXST_FLOW reply:
])

OVS_VSWITCHD_STOP
AT_CLEANUP


AT_SETUP([ofproto-dpif - controller with slow-path action])
OVS_VSWITCHD_START
add_of_ports br0 1 2

AT_CHECK([ovs-ofctl add-flow br0 "in_port=1,actions=debug_slow,controller"])

AT_CHECK([ovs-ofctl monitor -P standard br0 65534 --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3 ; do
    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=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9),tcp_flags(0x010)'
done

OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 3])
OVS_APP_EXIT_AND_WAIT(ovs-ofctl)

AT_CHECK([cat ofctl_monitor.log], [0], [dnl
OFPT_PACKET_IN (xid=0x0): total_len=118 in_port=1 (via action) data_len=118 (unbuffered)
tcp,vlan_tci=0x0000,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_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=9,tcp_flags=ack tcp_csum:4a2c
dnl
OFPT_PACKET_IN (xid=0x0): total_len=118 in_port=1 (via action) data_len=118 (unbuffered)
tcp,vlan_tci=0x0000,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_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=9,tcp_flags=ack tcp_csum:4a2c
dnl
OFPT_PACKET_IN (xid=0x0): total_len=118 in_port=1 (via action) data_len=118 (unbuffered)
tcp,vlan_tci=0x0000,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_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=9,tcp_flags=ack tcp_csum:4a2c
])

OVS_VSWITCHD_STOP
AT_CLEANUP


AT_SETUP([ofproto-dpif - controller action without megaflows])
OVS_VSWITCHD_START
add_of_ports br0 1

AT_CHECK([ovs-ofctl add-flow br0 in_port=1,action=controller])
AT_CHECK([ovs-appctl upcall/disable-megaflows], [0], [dnl
megaflows disabled
])

AT_CAPTURE_FILE([ofctl_monitor.log])
AT_CHECK([ovs-ofctl monitor br0 65534 invalid_ttl -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2; do
    AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x1234)'])
done

OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 4])
OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])

AT_CHECK([ovs-appctl dpctl/dump-flows | sed 's/.*\(packets:\)/\1/' | sed 's/used:[[0-9]].[[0-9]]*s/used:0.001s/'], [0], [dnl
flow-dump from the main thread:
packets:1, bytes:14, used:0.001s, actions:userspace(pid=0,controller(reason=1,dont_send=0,continuation=0,recirc_id=1,rule_cookie=0,controller_id=0,max_len=65535))
])

AT_CHECK([cat ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): cookie=0x0 total_len=14 in_port=1 (via action) data_len=14 (unbuffered)
vlan_tci=0x0000,dl_src=50:54:00:00:00:09,dl_dst=50:54:00:00:00:0a,dl_type=0x1234
NXT_PACKET_IN (xid=0x0): cookie=0x0 total_len=14 in_port=1 (via action) data_len=14 (unbuffered)
vlan_tci=0x0000,dl_src=50:54:00:00:00:09,dl_dst=50:54:00:00:00:0a,dl_type=0x1234
])

AT_CHECK([ovs-appctl revalidator/purge])
AT_CHECK([ovs-ofctl monitor br0 65534 invalid_ttl -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

dnl Add a controller meter.
AT_CHECK([ovs-ofctl -O OpenFlow13 add-meter br0 'meter=controller pktps stats bands=type=drop rate=2'])

dnl Advance time by 1 second.
AT_CHECK([ovs-appctl time/warp 1000], [0], [ignore])

for i in `seq 1 8`; do
    AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x4321)'])
done

AT_CHECK([ovs-appctl dpctl/dump-flows | sed 's/.*\(packets:\)/\1/' | sed 's/used:[[0-9]].[[0-9]]*s/used:0.001s/'], [0], [dnl
flow-dump from the main thread:
packets:7, bytes:98, used:0.001s, actions:sample(sample=100.0%,actions(meter(0),userspace(pid=0,controller(reason=1,dont_send=0,continuation=0,recirc_id=2,rule_cookie=0,controller_id=0,max_len=65535))))
])

AT_CHECK([ovs-appctl time/warp 1], [0], [ignore])
OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])

dnl Out of 8 packets we sent, two were passed by the rate limiter, and
dnl the rest of packets were blocked.
AT_CHECK([cat ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): cookie=0x0 total_len=14 in_port=1 (via action) data_len=14 (unbuffered)
vlan_tci=0x0000,dl_src=50:54:00:00:00:09,dl_dst=50:54:00:00:00:0a,dl_type=0x4321
NXT_PACKET_IN (xid=0x0): cookie=0x0 total_len=14 in_port=1 (via action) data_len=14 (unbuffered)
vlan_tci=0x0000,dl_src=50:54:00:00:00:09,dl_dst=50:54:00:00:00:0a,dl_type=0x4321
])
dnl Check meter stats to make it gives the same picture;
dnl 7 packets hit the meter, but 6 packets are dropped by band0.
AT_CHECK([ovs-ofctl -O OpenFlow13 meter-stats br0 | strip_timers], [0], [dnl
OFPST_METER reply (OF1.3) (xid=0x2):
meter:controller flow_count:0 packet_in_count:8 byte_in_count:112 duration:0.0s bands:
0: packet_count:6 byte_count:84
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - MPLS handling])
OVS_VSWITCHD_START([dnl
   add-port br0 p1 -- set Interface p1 type=dummy
])
on_exit 'kill `cat ovs-ofctl.pid`'

AT_CAPTURE_FILE([ofctl_monitor.log])
AT_DATA([flows.txt], [dnl
cookie=0xa dl_src=40:44:44:44:44:42 actions=push_mpls:0x8847,load:10->OXM_OF_MPLS_LABEL[[]],load:3->OXM_OF_MPLS_TC[[]],controller
cookie=0xa dl_src=41:44:44:44:44:42 actions=push_mpls:0x8847,load:10->OXM_OF_MPLS_LABEL[[]],load:3->OXM_OF_MPLS_TC[[]],pop_mpls:0x0800,controller
cookie=0xa dl_src=40:44:44:44:44:43 actions=push_mpls:0x8847,load:10->OXM_OF_MPLS_LABEL[[]],load:3->OXM_OF_MPLS_TC[[]],controller
cookie=0xa dl_src=40:44:44:44:44:44 actions=push_mpls:0x8847,load:10->OXM_OF_MPLS_LABEL[[]],load:3->OXM_OF_MPLS_TC[[]],controller
cookie=0xa dl_src=40:44:44:44:44:45 actions=push_mpls:0x8847,load:10->OXM_OF_MPLS_LABEL[[]],load:3->OXM_OF_MPLS_TC[[]],dec_mpls_ttl,controller
cookie=0xa dl_src=40:44:44:44:44:46 actions=push_mpls:0x8847,load:10->OXM_OF_MPLS_LABEL[[]],load:3->OXM_OF_MPLS_TC[[]],set_mpls_ttl(10),controller
cookie=0xa dl_src=40:44:44:44:44:47 actions=push_mpls:0x8847,load:10->OXM_OF_MPLS_LABEL[[]],load:3->OXM_OF_MPLS_TC[[]],dec_mpls_ttl,set_mpls_ttl(10),controller
cookie=0xa dl_src=40:44:44:44:44:48 actions=push_mpls:0x8847,load:10->OXM_OF_MPLS_LABEL[[]],load:3->OXM_OF_MPLS_TC[[]],set_mpls_ttl(10),dec_mpls_ttl,controller
cookie=0xa mpls,dl_src=40:44:44:44:44:49 actions=push_mpls:0x8848,load:10->OXM_OF_MPLS_LABEL[[]],CONTROLLER:65535
cookie=0xb dl_src=50:55:55:55:55:55 dl_type=0x8847 actions=load:1000->OXM_OF_MPLS_LABEL[[]],controller
cookie=0xd dl_src=60:66:66:66:66:66 actions=pop_mpls:0x0800,controller
cookie=0xc dl_src=70:77:77:77:77:77 actions=push_mpls:0x8848,load:1000->OXM_OF_MPLS_LABEL[[]],load:7->OXM_OF_MPLS_TC[[]],controller

cookie=0xd dl_src=60:66:66:66:00:01 actions=pop_mpls:0x0800,dec_ttl,controller
cookie=0xd dl_src=60:66:66:66:00:02 actions=pop_mpls:0x0800,load:0xa000001->OXM_OF_IPV4_DST[[]],controller
cookie=0xd dl_src=60:66:66:66:00:03 actions=pop_mpls:0x0800,move:OXM_OF_IPV4_DST[[]]->OXM_OF_IPV4_SRC[[]],controller
cookie=0xd dl_src=60:66:66:66:00:04 actions=pop_mpls:0x0800,push:OXM_OF_IPV4_DST[[]],pop:OXM_OF_IPV4_SRC[[]],controller
cookie=0xd dl_src=60:66:66:66:00:05 actions=pop_mpls:0x0800,multipath(eth_src,50,modulo_n,1,0,OXM_OF_IPV4_SRC[[0..7]]),controller
cookie=0xd dl_src=60:66:66:66:00:06 actions=pop_mpls:0x0800,bundle_load(eth_src,50,hrw,ofport,OXM_OF_IPV4_SRC[[0..15]],members:1,2),controller
cookie=0xd dl_src=60:66:66:66:00:07 actions=pop_mpls:0x0800,learn(table=1,hard_timeout=60,eth_type=0x800,nw_proto=6,OXM_OF_IPV4_SRC[[]]=OXM_OF_IPV4_DST[[]]),controller

cookie=0xd dl_src=60:66:66:66:00:08 actions=pop_mpls:0x0806,resubmit(1,1)
cookie=0xd table=1 arp actions=controller

cookie=0xdeadbeef table=2 dl_src=60:66:66:66:00:09 actions=pop_mpls:0x0800,mod_nw_tos:48
cookie=0xd dl_src=60:66:66:66:00:09 actions=resubmit(,2),controller
cookie=0xd dl_src=60:66:66:66:00:0a actions=pop_mpls:0x0800,mod_nw_dst:10.0.0.1,controller
cookie=0xd dl_src=60:66:66:66:00:0b actions=pop_mpls:0x0800,mod_nw_src:10.0.0.1,controller

cookie=0xd dl_src=60:66:66:66:01:00 actions=pop_mpls:0x8848,controller
cookie=0xd dl_src=60:66:66:66:01:01 actions=pop_mpls:0x8847,dec_mpls_ttl,controller
cookie=0xd dl_src=60:66:66:66:01:02 actions=pop_mpls:0x8848,load:3->OXM_OF_MPLS_TC[[]],controller

cookie=0xd dl_src=60:66:66:66:02:00 actions=pop_mpls:0x8847,pop_mpls:0x0800,controller
cookie=0xe dl_src=60:66:66:66:02:01 actions=pop_mpls:0x8848,pop_mpls:0x0800,dec_ttl,controller
cookie=0xe dl_src=60:66:66:66:02:10 actions=pop_mpls:0x8847,dec_mpls_ttl,pop_mpls:0x0800,dec_ttl,controller

cookie=0xe dl_src=60:66:66:66:03:00 actions=pop_mpls:0x8848,pop_mpls:0x8848,controller
cookie=0xe dl_src=60:66:66:66:03:01 actions=pop_mpls:0x8847,pop_mpls:0x8847,dec_mpls_ttl,controller
cookie=0xe dl_src=60:66:66:66:03:10 actions=pop_mpls:0x8848,dec_mpls_ttl,pop_mpls:0x8848,dec_mpls_ttl,controller

cookie=0xf dl_src=60:66:66:66:04:00 actions=pop_mpls:0x0800,push_mpls:0x8847,controller
cookie=0xf dl_src=60:66:66:66:04:01 actions=pop_mpls:0x0800,push_mpls:0x8848,dec_mpls_ttl,controller
cookie=0xf dl_src=60:66:66:66:04:10 actions=pop_mpls:0x0800,dec_ttl,push_mpls:0x8848,dec_mpls_ttl,controller

cookie=0x5 dl_src=60:66:66:66:05:00 actions=push_mpls:0x8848,pop_mpls:0x8847,controller
cookie=0x5 dl_src=60:66:66:66:05:01 actions=push_mpls:0x8847,pop_mpls:0x8848,dec_mpls_ttl,controller
cookie=0x5 dl_src=60:66:66:66:05:10 actions=push_mpls:0x8848,dec_mpls_ttl,pop_mpls:0x8847,dec_mpls_ttl,controller
])
AT_CHECK([ovs-ofctl add-flows br0 flows.txt])

dnl Modified MPLS controller action.
AT_CHECK([ovs-ofctl monitor br0 65534 -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3; do
    ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=40:44:44:44:44:42,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=17,tos=0,ttl=64,frag=no),udp(src=7777,dst=80)'
done
OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6])
OVS_APP_EXIT_AND_WAIT(ovs-ofctl)

AT_CHECK([cat ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=110 in_port=1 (via action) data_len=110 (unbuffered)
mpls,vlan_tci=0x0000,dl_src=40:44:44:44:44:42,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=3,mpls_ttl=64,mpls_bos=1
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=110 in_port=1 (via action) data_len=110 (unbuffered)
mpls,vlan_tci=0x0000,dl_src=40:44:44:44:44:42,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=3,mpls_ttl=64,mpls_bos=1
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=110 in_port=1 (via action) data_len=110 (unbuffered)
mpls,vlan_tci=0x0000,dl_src=40:44:44:44:44:42,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=3,mpls_ttl=64,mpls_bos=1
])

dnl Modified MPLS controller action.
AT_CHECK([ovs-ofctl monitor br0 65534 -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3; do
    ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=41:44:44:44:44:42,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=16,tos=0,ttl=64,frag=no)'
done
OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6])
OVS_APP_EXIT_AND_WAIT(ovs-ofctl)

AT_CHECK([cat ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=34 in_port=1 (via action) data_len=34 (unbuffered)
ip,vlan_tci=0x0000,dl_src=41:44:44:44:44:42,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_proto=16,nw_tos=0,nw_ecn=0,nw_ttl=64
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=34 in_port=1 (via action) data_len=34 (unbuffered)
ip,vlan_tci=0x0000,dl_src=41:44:44:44:44:42,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_proto=16,nw_tos=0,nw_ecn=0,nw_ttl=64
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=34 in_port=1 (via action) data_len=34 (unbuffered)
ip,vlan_tci=0x0000,dl_src=41:44:44:44:44:42,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_proto=16,nw_tos=0,nw_ecn=0,nw_ttl=64
])

dnl Modified MPLS controller action.
AT_CHECK([ovs-ofctl monitor br0 65534 -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

dnl in_port(1),eth(src=00:01:02:03:04:05,dst=10:11:12:13:14:15),eth_type(0x8847),mpls(label=100,tc=3,ttl=64,bos=1)

for i in 1 2 3; do
    ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=40:44:44:44:44:43,dst=50:54:00:00:00:07),eth_type(0x8847),mpls(label=11,tc=3,ttl=64,bos=1)'
done
OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6])
OVS_APP_EXIT_AND_WAIT(ovs-ofctl)

AT_CHECK([cat ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=22 in_port=1 (via action) data_len=22 (unbuffered)
mpls,vlan_tci=0x0000,dl_src=40:44:44:44:44:43,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=3,mpls_ttl=64,mpls_bos=0,mpls_lse1=46912
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=22 in_port=1 (via action) data_len=22 (unbuffered)
mpls,vlan_tci=0x0000,dl_src=40:44:44:44:44:43,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=3,mpls_ttl=64,mpls_bos=0,mpls_lse1=46912
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=22 in_port=1 (via action) data_len=22 (unbuffered)
mpls,vlan_tci=0x0000,dl_src=40:44:44:44:44:43,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=3,mpls_ttl=64,mpls_bos=0,mpls_lse1=46912
])

dnl Modified MPLS controller action.
AT_CHECK([ovs-ofctl monitor br0 65534 -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3; do
    ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=40:44:44:44:44:44,dst=50:54:00:00:00:07),eth_type(0x8100),vlan(vid=99,pcp=7),encap(eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=16,tos=0,ttl=64,frag=no))'
done
OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6])
OVS_APP_EXIT_AND_WAIT(ovs-ofctl)

AT_CHECK([cat ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=42 in_port=1 (via action) data_len=42 (unbuffered)
mpls,dl_vlan=99,dl_vlan_pcp=7,vlan_tci1=0x0000,dl_src=40:44:44:44:44:44,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=3,mpls_ttl=64,mpls_bos=1
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=42 in_port=1 (via action) data_len=42 (unbuffered)
mpls,dl_vlan=99,dl_vlan_pcp=7,vlan_tci1=0x0000,dl_src=40:44:44:44:44:44,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=3,mpls_ttl=64,mpls_bos=1
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=42 in_port=1 (via action) data_len=42 (unbuffered)
mpls,dl_vlan=99,dl_vlan_pcp=7,vlan_tci1=0x0000,dl_src=40:44:44:44:44:44,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=3,mpls_ttl=64,mpls_bos=1
])

dnl Modified MPLS controller action.
AT_CHECK([ovs-ofctl monitor br0 65534 -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3; do
    ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=40:44:44:44:44:45,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=16,tos=0,ttl=64,frag=no)'
done
OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6])
OVS_APP_EXIT_AND_WAIT(ovs-ofctl)

AT_CHECK([cat ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=38 in_port=1 (via action) data_len=38 (unbuffered)
mpls,vlan_tci=0x0000,dl_src=40:44:44:44:44:45,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=3,mpls_ttl=63,mpls_bos=1
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=38 in_port=1 (via action) data_len=38 (unbuffered)
mpls,vlan_tci=0x0000,dl_src=40:44:44:44:44:45,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=3,mpls_ttl=63,mpls_bos=1
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=38 in_port=1 (via action) data_len=38 (unbuffered)
mpls,vlan_tci=0x0000,dl_src=40:44:44:44:44:45,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=3,mpls_ttl=63,mpls_bos=1
])

dnl Modified MPLS controller action.
AT_CHECK([ovs-ofctl monitor br0 65534 -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3; do
    ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=40:44:44:44:44:46,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=16,tos=0,ttl=64,frag=no)'
done
OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6])
OVS_APP_EXIT_AND_WAIT(ovs-ofctl)

AT_CHECK([cat ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=38 in_port=1 (via action) data_len=38 (unbuffered)
mpls,vlan_tci=0x0000,dl_src=40:44:44:44:44:46,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=3,mpls_ttl=10,mpls_bos=1
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=38 in_port=1 (via action) data_len=38 (unbuffered)
mpls,vlan_tci=0x0000,dl_src=40:44:44:44:44:46,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=3,mpls_ttl=10,mpls_bos=1
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=38 in_port=1 (via action) data_len=38 (unbuffered)
mpls,vlan_tci=0x0000,dl_src=40:44:44:44:44:46,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=3,mpls_ttl=10,mpls_bos=1
])

dnl Modified MPLS controller action.
AT_CHECK([ovs-ofctl monitor br0 65534 -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3; do
    ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=40:44:44:44:44:47,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=16,tos=0,ttl=64,frag=no)'
done
OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6])
OVS_APP_EXIT_AND_WAIT(ovs-ofctl)

AT_CHECK([cat ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=38 in_port=1 (via action) data_len=38 (unbuffered)
mpls,vlan_tci=0x0000,dl_src=40:44:44:44:44:47,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=3,mpls_ttl=10,mpls_bos=1
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=38 in_port=1 (via action) data_len=38 (unbuffered)
mpls,vlan_tci=0x0000,dl_src=40:44:44:44:44:47,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=3,mpls_ttl=10,mpls_bos=1
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=38 in_port=1 (via action) data_len=38 (unbuffered)
mpls,vlan_tci=0x0000,dl_src=40:44:44:44:44:47,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=3,mpls_ttl=10,mpls_bos=1
])

AT_CHECK([ovs-appctl time/warp 5000], [0], [ignore])

dnl Modified MPLS controller action.
AT_CHECK([ovs-ofctl monitor br0 65534 -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3; do
    ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=40:44:44:44:44:49,dst=50:54:00:00:00:07),eth_type(0x8847),mpls(label=10,tc=3,ttl=64,bos=1)'
done
OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6])
OVS_APP_EXIT_AND_WAIT([ovs-ofctl])

AT_CHECK([cat ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=22 in_port=1 (via action) data_len=22 (unbuffered)
mplsm,vlan_tci=0x0000,dl_src=40:44:44:44:44:49,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=3,mpls_ttl=64,mpls_bos=0,mpls_lse1=42816
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=22 in_port=1 (via action) data_len=22 (unbuffered)
mplsm,vlan_tci=0x0000,dl_src=40:44:44:44:44:49,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=3,mpls_ttl=64,mpls_bos=0,mpls_lse1=42816
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=22 in_port=1 (via action) data_len=22 (unbuffered)
mplsm,vlan_tci=0x0000,dl_src=40:44:44:44:44:49,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=3,mpls_ttl=64,mpls_bos=0,mpls_lse1=42816
])

AT_CHECK([ovs-appctl time/warp 5000], [0], [ignore])

dnl Modified MPLS controller action.
AT_CHECK([ovs-ofctl monitor br0 65534 -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3; do
    ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=40:44:44:44:44:48,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=16,tos=0,ttl=64,frag=no)'
done
OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6])
OVS_APP_EXIT_AND_WAIT(ovs-ofctl)

AT_CHECK([cat ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=38 in_port=1 (via action) data_len=38 (unbuffered)
mpls,vlan_tci=0x0000,dl_src=40:44:44:44:44:48,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=3,mpls_ttl=9,mpls_bos=1
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=38 in_port=1 (via action) data_len=38 (unbuffered)
mpls,vlan_tci=0x0000,dl_src=40:44:44:44:44:48,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=3,mpls_ttl=9,mpls_bos=1
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=38 in_port=1 (via action) data_len=38 (unbuffered)
mpls,vlan_tci=0x0000,dl_src=40:44:44:44:44:48,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=3,mpls_ttl=9,mpls_bos=1
])

dnl Modified MPLS actions.
AT_CHECK([ovs-ofctl monitor br0 65534 -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3; do
    ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:55:55:55:55:55,dst=50:54:00:00:00:07),eth_type(0x8847),mpls(label=100,tc=7,ttl=64,bos=1)'
done
OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6])
OVS_APP_EXIT_AND_WAIT(ovs-ofctl)

AT_CHECK([cat ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): cookie=0xb total_len=18 in_port=1 (via action) data_len=18 (unbuffered)
mpls,vlan_tci=0x0000,dl_src=50:55:55:55:55:55,dl_dst=50:54:00:00:00:07,mpls_label=1000,mpls_tc=7,mpls_ttl=64,mpls_bos=1
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xb total_len=18 in_port=1 (via action) data_len=18 (unbuffered)
mpls,vlan_tci=0x0000,dl_src=50:55:55:55:55:55,dl_dst=50:54:00:00:00:07,mpls_label=1000,mpls_tc=7,mpls_ttl=64,mpls_bos=1
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xb total_len=18 in_port=1 (via action) data_len=18 (unbuffered)
mpls,vlan_tci=0x0000,dl_src=50:55:55:55:55:55,dl_dst=50:54:00:00:00:07,mpls_label=1000,mpls_tc=7,mpls_ttl=64,mpls_bos=1
])

dnl Modified MPLS ipv6 controller action.
AT_CHECK([ovs-ofctl monitor br0 65534 -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3; do
    ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=70:77:77:77:77:77,dst=50:54:00:00:00:07),eth_type(0x86dd),ipv6(src=::1,dst=::2,label=0,proto=10,tclass=0x70,hlimit=128,frag=no)'
done
OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6])
OVS_APP_EXIT_AND_WAIT(ovs-ofctl)

AT_CHECK([cat ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): cookie=0xc total_len=58 in_port=1 (via action) data_len=58 (unbuffered)
mplsm,vlan_tci=0x0000,dl_src=70:77:77:77:77:77,dl_dst=50:54:00:00:00:07,mpls_label=1000,mpls_tc=7,mpls_ttl=128,mpls_bos=1
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xc total_len=58 in_port=1 (via action) data_len=58 (unbuffered)
mplsm,vlan_tci=0x0000,dl_src=70:77:77:77:77:77,dl_dst=50:54:00:00:00:07,mpls_label=1000,mpls_tc=7,mpls_ttl=128,mpls_bos=1
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xc total_len=58 in_port=1 (via action) data_len=58 (unbuffered)
mplsm,vlan_tci=0x0000,dl_src=70:77:77:77:77:77,dl_dst=50:54:00:00:00:07,mpls_label=1000,mpls_tc=7,mpls_ttl=128,mpls_bos=1
])


dnl Modified MPLS pop action.
dnl The input is a frame with two MPLS headers which tcpdump -vve shows as:
dnl 60:66:66:66:66:66 > 50:54:00:00:00:07, ethertype MPLS multicast (0x8847), length 66: MPLS (label 20, exp 0, ttl 32)
dnl             (tos 0x0, ttl 64, id 0, offset 0, flags [none], proto TCP (6), length 44)

AT_CHECK([ovs-ofctl monitor br0 65534 -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3; do
    ovs-appctl netdev-dummy/receive p1 '50 54 00 00 00 07 60 66 66 66 66 66 88 47 00 01 41 20 45 00 00 2c 00 00 00 00 40 06 3b 78 c0 a8 00 01 c0 a8 00 02 00 50 00 00 00 00 00 2a 00 00 00 2a 50 00 27 10 77 44 00 00 48 4f 47 45'
done
#for i in 2 3; do
#    ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=60:66:66:66:66:66,dst=50:54:00:00:00:07),eth_type(0x8847),mpls(label=10,tc=3,ttl=100,bos=1)'
#done
OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6])
OVS_APP_EXIT_AND_WAIT(ovs-ofctl)

AT_CHECK([cat ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): cookie=0xd total_len=58 in_port=1 (via action) data_len=58 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=60:66:66:66:66:66,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=80,tp_dst=0,tcp_flags=0 tcp_csum:7744
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xd total_len=58 in_port=1 (via action) data_len=58 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=60:66:66:66:66:66,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=80,tp_dst=0,tcp_flags=0 tcp_csum:7744
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xd total_len=58 in_port=1 (via action) data_len=58 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=60:66:66:66:66:66,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=80,tp_dst=0,tcp_flags=0 tcp_csum:7744
])

AT_CHECK([ovs-appctl time/warp 5000], [0], [ignore])

dnl Modified MPLS pop action.
dnl The input is a frame with a single MPLS label stack entry which tcpdump -vve shows as:
dnl 60:66:66:66:00:01 > 50:54:00:00:00:07, ethertype MPLS multicast (0x8848), length 62: MPLS (label 20, exp 0, [S], ttl 32)
dnl             (tos 0x0, ttl 255, id 0, offset 0, flags [none], proto TCP (6), length 44)
dnl         192.168.0.1.80 > 192.168.0.2.0: Flags [none], cksum 0x77ec (correct), seq 42:46, win 10000, length 4
AT_CHECK([ovs-ofctl monitor br0 65534 -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3; do
    ovs-appctl netdev-dummy/receive p1 '50 54 00 00 00 07 60 66 66 66 00 01 88 48 00 01 41 20 45 00 00 2c 00 00 00 00 ff 06 3a 78 c0 a8 00 01 c0 a8 00 02 00 50 00 00 00 00 00 2a 00 00 00 2a 50 00 27 10 77 44 00 00 48 4f 47 45'
done
OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6])
OVS_APP_EXIT_AND_WAIT(ovs-ofctl)

AT_CHECK([strip_metadata < ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): cookie=0xd total_len=58 in_port=1 (via action) data_len=58 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=60:66:66:66:00:01,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=254,tp_src=80,tp_dst=0,tcp_flags=0 tcp_csum:7744
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xd total_len=58 in_port=1 (via action) data_len=58 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=60:66:66:66:00:01,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=254,tp_src=80,tp_dst=0,tcp_flags=0 tcp_csum:7744
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xd total_len=58 in_port=1 (via action) data_len=58 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=60:66:66:66:00:01,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=254,tp_src=80,tp_dst=0,tcp_flags=0 tcp_csum:7744
])

AT_CHECK([ovs-appctl time/warp 5000], [0], [ignore])

dnl Modified MPLS pop action.
dnl The input is a frame with a single MPLS label stack entry which tcpdump -vve shows as:
dnl 60:66:66:66:00:02 > 50:54:00:00:00:07, ethertype MPLS unicast (0x8847), length 62: MPLS (label 20, exp 0, [S], ttl 32)
dnl             (tos 0x0, ttl 255, id 0, offset 0, flags [none], proto TCP (6), length 44)
dnl         192.168.0.1.80 > 192.168.0.2.0: Flags [none], cksum 0x77ec (correct), seq 42:46, win 10000, length 4
AT_CHECK([ovs-ofctl monitor br0 65534 -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3; do
    ovs-appctl netdev-dummy/receive p1 '50 54 00 00 00 07 60 66 66 66 00 02 88 47 00 01 41 20 45 00 00 2c 00 00 00 00 ff 06 3a 78 c0 a8 00 01 c0 a8 00 02 00 50 00 00 00 00 00 2a 00 00 00 2a 50 00 27 10 77 44 00 00 48 4f 47 45'
done
OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6])
OVS_APP_EXIT_AND_WAIT(ovs-ofctl)

AT_CHECK([strip_metadata < ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): cookie=0xd total_len=58 in_port=1 (via action) data_len=58 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=60:66:66:66:00:02,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=10.0.0.1,nw_tos=0,nw_ecn=0,nw_ttl=255,tp_src=80,tp_dst=0,tcp_flags=0 tcp_csum:2dee
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xd total_len=58 in_port=1 (via action) data_len=58 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=60:66:66:66:00:02,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=10.0.0.1,nw_tos=0,nw_ecn=0,nw_ttl=255,tp_src=80,tp_dst=0,tcp_flags=0 tcp_csum:2dee
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xd total_len=58 in_port=1 (via action) data_len=58 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=60:66:66:66:00:02,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=10.0.0.1,nw_tos=0,nw_ecn=0,nw_ttl=255,tp_src=80,tp_dst=0,tcp_flags=0 tcp_csum:2dee
])

AT_CHECK([ovs-appctl time/warp 5000], [0], [ignore])

dnl Modified MPLS pop action.
dnl The input is a frame with a single MPLS label stack entry which tcpdump -vve shows as:
dnl 60:66:66:66:00:03 > 50:54:00:00:00:07, ethertype MPLS multicast (0x8848), length 62: MPLS (label 20, exp 0, [S], ttl 32)
dnl             (tos 0x0, ttl 255, id 0, offset 0, flags [none], proto TCP (6), length 44)
dnl         192.168.0.1.80 > 192.168.0.2.0: Flags [none], cksum 0x77ec (correct), seq 42:46, win 10000, length 4
AT_CHECK([ovs-ofctl monitor br0 65534 -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3; do
    ovs-appctl netdev-dummy/receive p1 '50 54 00 00 00 07 60 66 66 66 00 03 88 48 00 01 41 20 45 00 00 2c 00 00 00 00 ff 06 3a 78 c0 a8 00 01 c0 a8 00 02 00 50 00 00 00 00 00 2a 00 00 00 2a 50 00 27 10 77 44 00 00 48 4f 47 45'
done
OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6])
OVS_APP_EXIT_AND_WAIT(ovs-ofctl)

AT_CHECK([strip_metadata < ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): cookie=0xd total_len=58 in_port=1 (via action) data_len=58 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=60:66:66:66:00:03,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.2,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=255,tp_src=80,tp_dst=0,tcp_flags=0 tcp_csum:7743
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xd total_len=58 in_port=1 (via action) data_len=58 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=60:66:66:66:00:03,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.2,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=255,tp_src=80,tp_dst=0,tcp_flags=0 tcp_csum:7743
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xd total_len=58 in_port=1 (via action) data_len=58 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=60:66:66:66:00:03,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.2,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=255,tp_src=80,tp_dst=0,tcp_flags=0 tcp_csum:7743
])

AT_CHECK([ovs-appctl time/warp 5000], [0], [ignore])

dnl Modified MPLS pop action.
dnl The input is a frame with a single MPLS label stack entry which tcpdump -vve shows as:
dnl 60:66:66:66:00:04 > 50:54:00:00:00:07, ethertype MPLS unicast (0x8847), length 62: MPLS (label 20, exp 0, [S], ttl 32)
dnl             (tos 0x0, ttl 255, id 0, offset 0, flags [none], proto TCP (6), length 44)
dnl         192.168.0.1.80 > 192.168.0.2.0: Flags [none], cksum 0x77ec (correct), seq 42:46, win 10000, length 4
AT_CHECK([ovs-ofctl monitor br0 65534 -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3; do
    ovs-appctl netdev-dummy/receive p1 '50 54 00 00 00 07 60 66 66 66 00 04 88 47 00 01 41 20 45 00 00 2c 00 00 00 00 ff 06 3a 78 c0 a8 00 01 c0 a8 00 02 00 50 00 00 00 00 00 2a 00 00 00 2a 50 00 27 10 77 44 00 00 48 4f 47 45'
done
OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6])
OVS_APP_EXIT_AND_WAIT(ovs-ofctl)

AT_CHECK([strip_metadata < ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): cookie=0xd total_len=58 in_port=1 (via action) data_len=58 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=60:66:66:66:00:04,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.2,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=255,tp_src=80,tp_dst=0,tcp_flags=0 tcp_csum:7743
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xd total_len=58 in_port=1 (via action) data_len=58 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=60:66:66:66:00:04,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.2,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=255,tp_src=80,tp_dst=0,tcp_flags=0 tcp_csum:7743
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xd total_len=58 in_port=1 (via action) data_len=58 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=60:66:66:66:00:04,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.2,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=255,tp_src=80,tp_dst=0,tcp_flags=0 tcp_csum:7743
])

AT_CHECK([ovs-appctl time/warp 5000], [0], [ignore])

dnl Modified MPLS pop action.
dnl The input is a frame with a single MPLS label stack entry which tcpdump -vve shows as:
dnl 60:66:66:66:00:05 > 50:54:00:00:00:07, ethertype MPLS unicast (0x8847), length 62: MPLS (label 20, exp 0, [S], ttl 32)
dnl             (tos 0x0, ttl 255, id 0, offset 0, flags [none], proto TCP (6), length 44)
dnl         192.168.0.1.80 > 192.168.0.2.0: Flags [none], cksum 0x77ec (correct), seq 42:46, win 10000, length 4
AT_CHECK([ovs-ofctl monitor br0 65534 -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3; do
    ovs-appctl netdev-dummy/receive p1 '50 54 00 00 00 07 60 66 66 66 00 05 88 48 00 01 41 20 45 00 00 2c 00 00 00 00 ff 06 3a 78 c0 a8 00 01 c0 a8 00 02 00 50 00 00 00 00 00 2a 00 00 00 2a 50 00 27 10 77 44 00 00 48 4f 47 45'
done
OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6])
OVS_APP_EXIT_AND_WAIT(ovs-ofctl)

AT_CHECK([strip_metadata < ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): cookie=0xd total_len=58 in_port=1 (via action) data_len=58 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=60:66:66:66:00:05,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.0,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=255,tp_src=80,tp_dst=0,tcp_flags=0 tcp_csum:7745
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xd total_len=58 in_port=1 (via action) data_len=58 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=60:66:66:66:00:05,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.0,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=255,tp_src=80,tp_dst=0,tcp_flags=0 tcp_csum:7745
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xd total_len=58 in_port=1 (via action) data_len=58 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=60:66:66:66:00:05,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.0,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=255,tp_src=80,tp_dst=0,tcp_flags=0 tcp_csum:7745
])

AT_CHECK([ovs-appctl time/warp 5000], [0], [ignore])

dnl Modified MPLS pop action.
dnl The input is a frame with a single MPLS label stack entry which tcpdump -vve shows as:
dnl 60:66:66:66:00:06 > 50:54:00:00:00:07, ethertype MPLS multicast (0x8848), length 62: MPLS (label 20, exp 0, [S], ttl 32)
dnl             (tos 0x0, ttl 255, id 0, offset 0, flags [none], proto TCP (6), length 44)
dnl         192.168.0.1.80 > 192.168.0.2.0: Flags [none], cksum 0x77ec (correct), seq 42:46, win 10000, length 4
AT_CHECK([ovs-ofctl monitor br0 65534 -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3; do
    ovs-appctl netdev-dummy/receive p1 '50 54 00 00 00 07 60 66 66 66 00 06 88 47 00 01 41 20 45 00 00 2c 00 00 00 00 ff 06 3a 78 c0 a8 00 01 c0 a8 00 02 00 50 00 00 00 00 00 2a 00 00 00 2a 50 00 27 10 77 44 00 00 48 4f 47 45'
done
OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6])
OVS_APP_EXIT_AND_WAIT(ovs-ofctl)

AT_CHECK([strip_metadata < ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): cookie=0xd total_len=58 in_port=1 (via action) data_len=58 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=60:66:66:66:00:06,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=255,tp_src=80,tp_dst=0,tcp_flags=0 tcp_csum:7744
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xd total_len=58 in_port=1 (via action) data_len=58 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=60:66:66:66:00:06,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=255,tp_src=80,tp_dst=0,tcp_flags=0 tcp_csum:7744
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xd total_len=58 in_port=1 (via action) data_len=58 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=60:66:66:66:00:06,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=255,tp_src=80,tp_dst=0,tcp_flags=0 tcp_csum:7744
])

AT_CHECK([ovs-appctl time/warp 5000], [0], [ignore])

dnl Modified MPLS pop action.
dnl The input is a frame with a single MPLS label stack entry which tcpdump -vve shows as:
dnl 60:66:66:66:00:07 > 50:54:00:00:00:07, ethertype MPLS multicast (0x8848), length 62: MPLS (label 20, exp 0, [S], ttl 32)
dnl             (tos 0x0, ttl 255, id 0, offset 0, flags [none], proto TCP (6), length 44)
dnl         192.168.0.1.80 > 192.168.0.2.0: Flags [none], cksum 0x77ec (correct), seq 42:46, win 10000, length 4
AT_CHECK([ovs-ofctl monitor br0 65534 -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3; do
    ovs-appctl netdev-dummy/receive p1 '50 54 00 00 00 07 60 66 66 66 00 07 88 48 00 01 41 20 45 00 00 2c 00 00 00 00 ff 06 3a 78 c0 a8 00 01 c0 a8 00 02 00 50 00 00 00 00 00 2a 00 00 00 2a 50 00 27 10 77 44 00 00 48 4f 47 45'
done
OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6])
OVS_APP_EXIT_AND_WAIT(ovs-ofctl)

AT_CHECK([strip_metadata < ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): cookie=0xd total_len=58 in_port=1 (via action) data_len=58 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=60:66:66:66:00:07,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=255,tp_src=80,tp_dst=0,tcp_flags=0 tcp_csum:7744
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xd total_len=58 in_port=1 (via action) data_len=58 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=60:66:66:66:00:07,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=255,tp_src=80,tp_dst=0,tcp_flags=0 tcp_csum:7744
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xd total_len=58 in_port=1 (via action) data_len=58 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=60:66:66:66:00:07,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=255,tp_src=80,tp_dst=0,tcp_flags=0 tcp_csum:7744
])

AT_CHECK([ovs-appctl time/warp 5000], [0], [ignore])

dnl Modified MPLS pop action.
dnl The input is an ARP frame with a single MPLS label stack entry which tcpdump -vve shows as:
dnl 60:66:66:66:00:08 > ff:ff:ff:ff:ff:ff, ethertype MPLS unicast (0x8847), length 46: MPLS (label 20, exp 0, [S], ttl 32)
AT_CHECK([ovs-ofctl monitor br0 65534 -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3; do
    ovs-appctl netdev-dummy/receive p1 'ff ff ff ff ff ff 60 66 66 66 00 08 88 47 00 01 41 20 00 01 08 00 06 04 00 02 60 66 66 66 00 08 c0 a8 00 01 ff ff ff ff ff ff ff ff ff ff'
done
OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6])
OVS_APP_EXIT_AND_WAIT(ovs-ofctl)

AT_CHECK([strip_metadata < ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): table_id=1 cookie=0xd total_len=42 in_port=1 (via action) data_len=42 (unbuffered)
arp,vlan_tci=0x0000,dl_src=60:66:66:66:00:08,dl_dst=ff:ff:ff:ff:ff:ff,arp_spa=192.168.0.1,arp_tpa=255.255.255.255,arp_op=2,arp_sha=60:66:66:66:00:08,arp_tha=ff:ff:ff:ff:ff:ff
dnl
NXT_PACKET_IN (xid=0x0): table_id=1 cookie=0xd total_len=42 in_port=1 (via action) data_len=42 (unbuffered)
arp,vlan_tci=0x0000,dl_src=60:66:66:66:00:08,dl_dst=ff:ff:ff:ff:ff:ff,arp_spa=192.168.0.1,arp_tpa=255.255.255.255,arp_op=2,arp_sha=60:66:66:66:00:08,arp_tha=ff:ff:ff:ff:ff:ff
dnl
NXT_PACKET_IN (xid=0x0): table_id=1 cookie=0xd total_len=42 in_port=1 (via action) data_len=42 (unbuffered)
arp,vlan_tci=0x0000,dl_src=60:66:66:66:00:08,dl_dst=ff:ff:ff:ff:ff:ff,arp_spa=192.168.0.1,arp_tpa=255.255.255.255,arp_op=2,arp_sha=60:66:66:66:00:08,arp_tha=ff:ff:ff:ff:ff:ff
])

AT_CHECK([ovs-appctl time/warp 5000], [0], [ignore])

dnl Modified MPLS pop action.
dnl The input is a frame with a single MPLS label stack entry which tcpdump -vve shows as:
dnl 60:66:66:66:00:09 > 50:54:00:00:00:07, ethertype MPLS multicast (0x8848), length 62: MPLS (label 20, exp 0, [S], ttl 32)
dnl             (tos 0x0, ttl 255, id 0, offset 0, flags [none], proto TCP (6), length 44)
dnl         192.168.0.1.80 > 192.168.0.2.0: Flags [none], cksum 0x77ec (correct), seq 42:46, win 10000, length 4
AT_CHECK([ovs-ofctl monitor br0 65534 -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3; do
    ovs-appctl netdev-dummy/receive p1 '50 54 00 00 00 07 60 66 66 66 00 09 88 48 00 01 41 20 45 00 00 2c 00 00 00 00 ff 06 3a 78 c0 a8 00 01 c0 a8 00 02 00 50 00 00 00 00 00 2a 00 00 00 2a 50 00 27 10 77 44 00 00 48 4f 47 45'
done
OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6])
OVS_APP_EXIT_AND_WAIT(ovs-ofctl)

AT_CHECK([strip_metadata < ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): cookie=0xd total_len=58 in_port=1 (via action) data_len=58 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=60:66:66:66:00:09,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=48,nw_ecn=0,nw_ttl=255,tp_src=80,tp_dst=0,tcp_flags=0 tcp_csum:7744
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xd total_len=58 in_port=1 (via action) data_len=58 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=60:66:66:66:00:09,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=48,nw_ecn=0,nw_ttl=255,tp_src=80,tp_dst=0,tcp_flags=0 tcp_csum:7744
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xd total_len=58 in_port=1 (via action) data_len=58 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=60:66:66:66:00:09,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=48,nw_ecn=0,nw_ttl=255,tp_src=80,tp_dst=0,tcp_flags=0 tcp_csum:7744
])

AT_CHECK([ovs-appctl time/warp 5000], [0], [ignore])

dnl Modified MPLS pop action.
dnl The input is a frame with a single MPLS label stack entry which tcpdump -vve shows as:
dnl 60:66:66:66:00:0a > 50:54:00:00:00:07, ethertype MPLS multicast (0x8848), length 62: MPLS (label 20, exp 0, [S], ttl 32)
dnl             (tos 0x0, ttl 255, id 0, offset 0, flags [none], proto TCP (6), length 44)
dnl         192.168.0.1.80 > 192.168.0.2.0: Flags [none], cksum 0x77ec (correct), seq 42:46, win 10000, length 4
AT_CHECK([ovs-ofctl monitor br0 65534 -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3; do
    ovs-appctl netdev-dummy/receive p1 '50 54 00 00 00 07 60 66 66 66 00 0a 88 48 00 01 41 20 45 00 00 2c 00 00 00 00 ff 06 3a 78 c0 a8 00 01 c0 a8 00 02 00 50 00 00 00 00 00 2a 00 00 00 2a 50 00 27 10 77 44 00 00 48 4f 47 45'
done
OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6])
OVS_APP_EXIT_AND_WAIT(ovs-ofctl)

AT_CHECK([strip_metadata < ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): cookie=0xd total_len=58 in_port=1 (via action) data_len=58 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=60:66:66:66:00:0a,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=10.0.0.1,nw_tos=0,nw_ecn=0,nw_ttl=255,tp_src=80,tp_dst=0,tcp_flags=0 tcp_csum:2dee
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xd total_len=58 in_port=1 (via action) data_len=58 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=60:66:66:66:00:0a,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=10.0.0.1,nw_tos=0,nw_ecn=0,nw_ttl=255,tp_src=80,tp_dst=0,tcp_flags=0 tcp_csum:2dee
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xd total_len=58 in_port=1 (via action) data_len=58 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=60:66:66:66:00:0a,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=10.0.0.1,nw_tos=0,nw_ecn=0,nw_ttl=255,tp_src=80,tp_dst=0,tcp_flags=0 tcp_csum:2dee
])

AT_CHECK([ovs-appctl time/warp 5000], [0], [ignore])

dnl Modified MPLS pop action.
dnl The input is a frame with a single MPLS label stack entry which tcpdump -vve shows as:
dnl 60:66:66:66:00:0b > 50:54:00:00:00:07, ethertype MPLS multicast (0x8848), length 62: MPLS (label 20, exp 0, [S], ttl 32)
dnl             (tos 0x0, ttl 255, id 0, offset 0, flags [none], proto TCP (6), length 44)
dnl         192.168.0.1.80 > 192.168.0.2.0: Flags [none], cksum 0x77ec (correct), seq 42:46, win 10000, length 4
AT_CHECK([ovs-ofctl monitor br0 65534 -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3; do
    ovs-appctl netdev-dummy/receive p1 '50 54 00 00 00 07 60 66 66 66 00 0b 88 48 00 01 41 20 45 00 00 2c 00 00 00 00 ff 06 3a 78 c0 a8 00 01 c0 a8 00 02 00 50 00 00 00 00 00 2a 00 00 00 2a 50 00 27 10 77 44 00 00 48 4f 47 45'
done
OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6])
OVS_APP_EXIT_AND_WAIT(ovs-ofctl)

AT_CHECK([strip_metadata < ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): cookie=0xd total_len=58 in_port=1 (via action) data_len=58 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=60:66:66:66:00:0b,dl_dst=50:54:00:00:00:07,nw_src=10.0.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=255,tp_src=80,tp_dst=0,tcp_flags=0 tcp_csum:2ded
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xd total_len=58 in_port=1 (via action) data_len=58 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=60:66:66:66:00:0b,dl_dst=50:54:00:00:00:07,nw_src=10.0.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=255,tp_src=80,tp_dst=0,tcp_flags=0 tcp_csum:2ded
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xd total_len=58 in_port=1 (via action) data_len=58 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=60:66:66:66:00:0b,dl_dst=50:54:00:00:00:07,nw_src=10.0.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=255,tp_src=80,tp_dst=0,tcp_flags=0 tcp_csum:2ded
])

AT_CHECK([ovs-appctl time/warp 5000], [0], [ignore])

dnl Modified MPLS pop action.
dnl The input is a frame with two MPLS label stack entries which tcpdump -vve shows as:
dnl 60:66:66:66:01:00 > 50:54:00:00:00:07, ethertype MPLS multicast (0x8848), length 66: MPLS (label 20, exp 0, ttl 32)
dnl             (label 20, exp 0, [S], ttl 31)
dnl             (tos 0x0, ttl 254, id 0, offset 0, flags [none], proto TCP (6), length 44)
dnl        192.168.0.1.80 > 192.168.0.2.0: Flags [none], cksum 0x7744 (correct), seq 42:46, win 10000, length 4
AT_CHECK([ovs-ofctl monitor br0 65534 -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3; do
    ovs-appctl netdev-dummy/receive p1 '50 54 00 00 00 07 60 66 66 66 01 00 88 48 00 01 40 20 00 01 41 1f 45 00 00 2c 00 00 00 00 ff 06 3b 78 c0 a8 00 01 c0 a8 00 02 00 50 00 00 00 00 00 2a 00 00 00 2a 50 00 27 10 77 44 00 00 48 4f 47 45'
done
OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6])
OVS_APP_EXIT_AND_WAIT(ovs-ofctl)

AT_CHECK([cat ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): cookie=0xd total_len=62 in_port=1 (via action) data_len=62 (unbuffered)
mplsm,vlan_tci=0x0000,dl_src=60:66:66:66:01:00,dl_dst=50:54:00:00:00:07,mpls_label=20,mpls_tc=0,mpls_ttl=31,mpls_bos=1
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xd total_len=62 in_port=1 (via action) data_len=62 (unbuffered)
mplsm,vlan_tci=0x0000,dl_src=60:66:66:66:01:00,dl_dst=50:54:00:00:00:07,mpls_label=20,mpls_tc=0,mpls_ttl=31,mpls_bos=1
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xd total_len=62 in_port=1 (via action) data_len=62 (unbuffered)
mplsm,vlan_tci=0x0000,dl_src=60:66:66:66:01:00,dl_dst=50:54:00:00:00:07,mpls_label=20,mpls_tc=0,mpls_ttl=31,mpls_bos=1
])

AT_CHECK([ovs-appctl time/warp 5000], [0], [ignore])

dnl Modified MPLS pop action.
dnl The input is a frame with two MPLS label stack entries which tcpdump -vve shows as:
dnl 60:66:66:66:01:01 > 50:54:00:00:00:07, ethertype MPLS unicast (0x8847), length 66: MPLS (label 20, exp 0, ttl 32)
dnl             (label 20, exp 0, [S], ttl 31)
dnl             (tos 0x0, ttl 254, id 0, offset 0, flags [none], proto TCP (6), length 44)
dnl        192.168.0.1.80 > 192.168.0.2.0: Flags [none], cksum 0x7744 (correct), seq 42:46, win 10000, length 4
AT_CHECK([ovs-ofctl monitor br0 65534 -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3; do
    ovs-appctl netdev-dummy/receive p1 '50 54 00 00 00 07 60 66 66 66 01 01 88 47 00 01 40 20 00 01 41 1f 45 00 00 2c 00 00 00 00 ff 06 3b 78 c0 a8 00 01 c0 a8 00 02 00 50 00 00 00 00 00 2a 00 00 00 2a 50 00 27 10 77 44 00 00 48 4f 47 45'
done
OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6])
OVS_APP_EXIT_AND_WAIT(ovs-ofctl)

AT_CHECK([cat ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): cookie=0xd total_len=62 in_port=1 (via action) data_len=62 (unbuffered)
mpls,vlan_tci=0x0000,dl_src=60:66:66:66:01:01,dl_dst=50:54:00:00:00:07,mpls_label=20,mpls_tc=0,mpls_ttl=30,mpls_bos=1
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xd total_len=62 in_port=1 (via action) data_len=62 (unbuffered)
mpls,vlan_tci=0x0000,dl_src=60:66:66:66:01:01,dl_dst=50:54:00:00:00:07,mpls_label=20,mpls_tc=0,mpls_ttl=30,mpls_bos=1
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xd total_len=62 in_port=1 (via action) data_len=62 (unbuffered)
mpls,vlan_tci=0x0000,dl_src=60:66:66:66:01:01,dl_dst=50:54:00:00:00:07,mpls_label=20,mpls_tc=0,mpls_ttl=30,mpls_bos=1
])

AT_CHECK([ovs-appctl time/warp 5000], [0], [ignore])

dnl Modified MPLS pop action.
dnl The input is a frame with two MPLS label stack entries which tcpdump -vve shows as:
dnl 60:66:66:66:01:02 > 50:54:00:00:00:07, ethertype MPLS multicast (0x8848), length 66: MPLS (label 20, exp 0, ttl 32)
dnl             (label 20, exp 0, [S], ttl 31)
dnl             (tos 0x0, ttl 254, id 0, offset 0, flags [none], proto TCP (6), length 44)
dnl        192.168.0.1.80 > 192.168.0.2.0: Flags [none], cksum 0x7744 (correct), seq 42:46, win 10000, length 4
AT_CHECK([ovs-ofctl monitor br0 65534 -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3; do
    ovs-appctl netdev-dummy/receive p1 '50 54 00 00 00 07 60 66 66 66 01 02 88 48 00 01 40 20 00 01 41 1f 45 00 00 2c 00 00 00 00 ff 06 3b 78 c0 a8 00 01 c0 a8 00 02 00 50 00 00 00 00 00 2a 00 00 00 2a 50 00 27 10 77 44 00 00 48 4f 47 45'
done
OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6])
OVS_APP_EXIT_AND_WAIT(ovs-ofctl)

AT_CHECK([cat ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): cookie=0xd total_len=62 in_port=1 (via action) data_len=62 (unbuffered)
mplsm,vlan_tci=0x0000,dl_src=60:66:66:66:01:02,dl_dst=50:54:00:00:00:07,mpls_label=20,mpls_tc=3,mpls_ttl=31,mpls_bos=1
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xd total_len=62 in_port=1 (via action) data_len=62 (unbuffered)
mplsm,vlan_tci=0x0000,dl_src=60:66:66:66:01:02,dl_dst=50:54:00:00:00:07,mpls_label=20,mpls_tc=3,mpls_ttl=31,mpls_bos=1
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xd total_len=62 in_port=1 (via action) data_len=62 (unbuffered)
mplsm,vlan_tci=0x0000,dl_src=60:66:66:66:01:02,dl_dst=50:54:00:00:00:07,mpls_label=20,mpls_tc=3,mpls_ttl=31,mpls_bos=1
])

AT_CHECK([ovs-appctl time/warp 5000], [0], [ignore])

dnl Modified MPLS pop action.
dnl The input is a frame with two MPLS label stack entries which tcpdump -vve shows as:
dnl 60:66:66:66:02:00 > 50:54:00:00:02:00, ethertype MPLS unicast (0x8847), length 66: MPLS (label 20, exp 0, ttl 32)
dnl             (label 20, exp 0, [S], ttl 31)
dnl             (tos 0x0, ttl 254, id 0, offset 0, flags [none], proto TCP (6), length 44)
dnl        192.168.0.1.80 > 192.168.0.2.0: Flags [none], cksum 0x7744 (correct), seq 42:46, win 10000, length 4
AT_CHECK([ovs-ofctl monitor br0 65534 -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3; do
    ovs-appctl netdev-dummy/receive p1 '50 54 00 00 00 07 60 66 66 66 02 00 88 47 00 01 40 20 00 01 41 1f 45 00 00 2c 00 00 00 00 ff 06 3b 78 c0 a8 00 01 c0 a8 00 02 00 50 00 00 00 00 00 2a 00 00 00 2a 50 00 27 10 77 44 00 00 48 4f 47 45'
done
OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6])
OVS_APP_EXIT_AND_WAIT(ovs-ofctl)

AT_CHECK([cat ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): cookie=0xd total_len=58 in_port=1 (via action) data_len=58 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=60:66:66:66:02:00,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=255,tp_src=80,tp_dst=0,tcp_flags=0 tcp_csum:7744
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xd total_len=58 in_port=1 (via action) data_len=58 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=60:66:66:66:02:00,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=255,tp_src=80,tp_dst=0,tcp_flags=0 tcp_csum:7744
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xd total_len=58 in_port=1 (via action) data_len=58 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=60:66:66:66:02:00,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=255,tp_src=80,tp_dst=0,tcp_flags=0 tcp_csum:7744
])

AT_CHECK([ovs-appctl time/warp 5000], [0], [ignore])

dnl Modified MPLS pop action.
dnl The input is a frame with two MPLS label stack entries which tcpdump -vve shows as:
dnl 60:66:66:66:02:01 > 50:54:00:00:02:01, ethertype MPLS multicast (0x8848), length 66: MPLS (label 20, exp 0, ttl 32)
dnl             (label 20, exp 0, [S], ttl 31)
dnl             (tos 0x0, ttl 254, id 0, offset 0, flags [none], proto TCP (6), length 44)
dnl        192.168.0.1.80 > 192.168.0.2.0: Flags [none], cksum 0x7744 (correct), seq 42:46, win 10000, length 4
AT_CHECK([ovs-ofctl monitor br0 65534 -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3; do
    ovs-appctl netdev-dummy/receive p1 '50 54 00 00 00 07 60 66 66 66 02 01 88 48 00 01 40 20 00 01 41 1f 45 00 00 2c 00 00 00 00 ff 06 3b 78 c0 a8 00 01 c0 a8 00 02 00 50 00 00 00 00 00 2a 00 00 00 2a 50 00 27 10 77 44 00 00 48 4f 47 45'
done

OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6])
OVS_APP_EXIT_AND_WAIT(ovs-ofctl)

AT_CHECK([strip_metadata < ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): cookie=0xe total_len=58 in_port=1 (via action) data_len=58 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=60:66:66:66:02:01,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=254,tp_src=80,tp_dst=0,tcp_flags=0 tcp_csum:7744
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xe total_len=58 in_port=1 (via action) data_len=58 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=60:66:66:66:02:01,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=254,tp_src=80,tp_dst=0,tcp_flags=0 tcp_csum:7744
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xe total_len=58 in_port=1 (via action) data_len=58 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=60:66:66:66:02:01,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=254,tp_src=80,tp_dst=0,tcp_flags=0 tcp_csum:7744
])

AT_CHECK([ovs-appctl time/warp 5000], [0], [ignore])

dnl Modified MPLS pop action.
dnl The input is a frame with two MPLS label stack entries which tcpdump -vve shows as:
dnl 60:66:66:66:02:10 > 50:54:00:00:00:07, ethertype MPLS unicast (0x8847), length 66: MPLS (label 20, exp 0, ttl 32)
dnl             (label 20, exp 0, [S], ttl 31)
dnl             (tos 0x0, ttl 254, id 0, offset 0, flags [none], proto TCP (6), length 44)
dnl        192.168.0.1.80 > 192.168.0.2.0: Flags [none], cksum 0x7744 (correct), seq 42:46, win 10000, length 4
AT_CHECK([ovs-ofctl monitor br0 65534 -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3; do
    ovs-appctl netdev-dummy/receive p1 '50 54 00 00 00 07 60 66 66 66 02 10 88 47 00 01 40 20 00 01 41 1f 45 00 00 2c 00 00 00 00 ff 06 3b 78 c0 a8 00 01 c0 a8 00 02 00 50 00 00 00 00 00 2a 00 00 00 2a 50 00 27 10 77 44 00 00 48 4f 47 45'
done
OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6])
OVS_APP_EXIT_AND_WAIT(ovs-ofctl)

AT_CHECK([strip_metadata < ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): cookie=0xe total_len=58 in_port=1 (via action) data_len=58 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=60:66:66:66:02:10,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=254,tp_src=80,tp_dst=0,tcp_flags=0 tcp_csum:7744
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xe total_len=58 in_port=1 (via action) data_len=58 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=60:66:66:66:02:10,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=254,tp_src=80,tp_dst=0,tcp_flags=0 tcp_csum:7744
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xe total_len=58 in_port=1 (via action) data_len=58 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=60:66:66:66:02:10,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=254,tp_src=80,tp_dst=0,tcp_flags=0 tcp_csum:7744
])

AT_CHECK([ovs-appctl time/warp 5000], [0], [ignore])

dnl Modified MPLS pop action.
dnl The input is a frame with three MPLS label stack entries which tcpdump -vve shows as:
dnl 60:66:66:66:03:00 > 50:54:00:00:00:07, ethertype MPLS unicast (0x8847), length 66: MPLS (label 20, exp 0, ttl 32)
dnl             (label 20, exp 0, ttl 31)
dnl             (label 20, exp 0, [S], ttl 30)
dnl             (tos 0x0, ttl 254, id 0, offset 0, flags [none], proto TCP (6), length 44)
dnl        192.168.0.1.80 > 192.168.0.2.0: Flags [none], cksum 0x7744 (correct), seq 42:46, win 10000, length 4
AT_CHECK([ovs-ofctl monitor br0 65534 -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3; do
    ovs-appctl netdev-dummy/receive p1 '50 54 00 00 00 07 60 66 66 66 03 00 88 47 00 01 40 20 00 01 40 1f 00 01 41 1e 45 00 00 2c 00 00 00 00 ff 06 3b 78 c0 a8 00 01 c0 a8 00 02 00 50 00 00 00 00 00 2a 00 00 00 2a 50 00 27 10 77 44 00 00 48 4f 47 45'
done
OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6])
OVS_APP_EXIT_AND_WAIT(ovs-ofctl)

AT_CHECK([cat ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): cookie=0xe total_len=62 in_port=1 (via action) data_len=62 (unbuffered)
mplsm,vlan_tci=0x0000,dl_src=60:66:66:66:03:00,dl_dst=50:54:00:00:00:07,mpls_label=20,mpls_tc=0,mpls_ttl=30,mpls_bos=1
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xe total_len=62 in_port=1 (via action) data_len=62 (unbuffered)
mplsm,vlan_tci=0x0000,dl_src=60:66:66:66:03:00,dl_dst=50:54:00:00:00:07,mpls_label=20,mpls_tc=0,mpls_ttl=30,mpls_bos=1
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xe total_len=62 in_port=1 (via action) data_len=62 (unbuffered)
mplsm,vlan_tci=0x0000,dl_src=60:66:66:66:03:00,dl_dst=50:54:00:00:00:07,mpls_label=20,mpls_tc=0,mpls_ttl=30,mpls_bos=1
])

AT_CHECK([ovs-appctl time/warp 5000], [0], [ignore])

dnl Modified MPLS pop action.
dnl The input is a frame with three MPLS label stack entries which tcpdump -vve shows as:
dnl 60:66:66:66:03:01 > 50:54:00:00:00:00, ethertype MPLS multicast (0x8848), length 66: MPLS (label 20, exp 0, ttl 32)
dnl             (label 20, exp 0, ttl 31)
dnl             (label 20, exp 0, [S], ttl 30)
dnl             (tos 0x0, ttl 254, id 0, offset 0, flags [none], proto TCP (6), length 44)
dnl        192.168.0.1.80 > 192.168.0.2.0: Flags [none], cksum 0x7744 (correct), seq 42:46, win 10000, length 4
AT_CHECK([ovs-ofctl monitor br0 65534 -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3; do
    ovs-appctl netdev-dummy/receive p1 '50 54 00 00 00 07 60 66 66 66 03 01 88 48 00 01 40 20 00 01 40 1f 00 01 41 1e 45 00 00 2c 00 00 00 00 ff 06 3b 78 c0 a8 00 01 c0 a8 00 02 00 50 00 00 00 00 00 2a 00 00 00 2a 50 00 27 10 77 44 00 00 48 4f 47 45'
done
OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6])
OVS_APP_EXIT_AND_WAIT(ovs-ofctl)

AT_CHECK([cat ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): cookie=0xe total_len=62 in_port=1 (via action) data_len=62 (unbuffered)
mpls,vlan_tci=0x0000,dl_src=60:66:66:66:03:01,dl_dst=50:54:00:00:00:07,mpls_label=20,mpls_tc=0,mpls_ttl=29,mpls_bos=1
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xe total_len=62 in_port=1 (via action) data_len=62 (unbuffered)
mpls,vlan_tci=0x0000,dl_src=60:66:66:66:03:01,dl_dst=50:54:00:00:00:07,mpls_label=20,mpls_tc=0,mpls_ttl=29,mpls_bos=1
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xe total_len=62 in_port=1 (via action) data_len=62 (unbuffered)
mpls,vlan_tci=0x0000,dl_src=60:66:66:66:03:01,dl_dst=50:54:00:00:00:07,mpls_label=20,mpls_tc=0,mpls_ttl=29,mpls_bos=1
])

AT_CHECK([ovs-appctl time/warp 5000], [0], [ignore])

dnl Modified MPLS pop action.
dnl The input is a frame with three MPLS label stack entries which tcpdump -vve shows as:
dnl 60:66:66:66:03:10 > 50:54:00:00:00:00, ethertype MPLS unicast (0x8847), length 66: MPLS (label 20, exp 0, ttl 32)
dnl             (label 20, exp 0, ttl 31)
dnl             (label 20, exp 0, [S], ttl 30)
dnl             (tos 0x0, ttl 254, id 0, offset 0, flags [none], proto TCP (6), length 44)
dnl        192.168.0.1.80 > 192.168.0.2.0: Flags [none], cksum 0x7744 (correct), seq 42:46, win 10000, length 4
AT_CHECK([ovs-ofctl monitor br0 65534 -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3; do
    ovs-appctl netdev-dummy/receive p1 '50 54 00 00 00 07 60 66 66 66 03 10 88 47 00 01 40 20 00 01 40 1f 00 01 41 1e 45 00 00 2c 00 00 00 00 ff 06 3b 78 c0 a8 00 01 c0 a8 00 02 00 50 00 00 00 00 00 2a 00 00 00 2a 50 00 27 10 77 44 00 00 48 4f 47 45'
done
OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6])
OVS_APP_EXIT_AND_WAIT(ovs-ofctl)

AT_CHECK([cat ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): cookie=0xe total_len=62 in_port=1 (via action) data_len=62 (unbuffered)
mplsm,vlan_tci=0x0000,dl_src=60:66:66:66:03:10,dl_dst=50:54:00:00:00:07,mpls_label=20,mpls_tc=0,mpls_ttl=29,mpls_bos=1
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xe total_len=62 in_port=1 (via action) data_len=62 (unbuffered)
mplsm,vlan_tci=0x0000,dl_src=60:66:66:66:03:10,dl_dst=50:54:00:00:00:07,mpls_label=20,mpls_tc=0,mpls_ttl=29,mpls_bos=1
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xe total_len=62 in_port=1 (via action) data_len=62 (unbuffered)
mplsm,vlan_tci=0x0000,dl_src=60:66:66:66:03:10,dl_dst=50:54:00:00:00:07,mpls_label=20,mpls_tc=0,mpls_ttl=29,mpls_bos=1
])

AT_CHECK([ovs-appctl time/warp 5000], [0], [ignore])

dnl Modified MPLS pop action.
dnl The input is a frame with a single MPLS label stack entry which tcpdump -vve shows as:
dnl 60:66:66:66:04:00 > 50:54:00:00:00:07, ethertype MPLS multicast (0x8848), length 62: MPLS (label 20, exp 0, [S], ttl 32)
dnl             (tos 0x0, ttl 255, id 0, offset 0, flags [none], proto TCP (6), length 44)
dnl         192.168.0.1.80 > 192.168.0.2.0: Flags [none], cksum 0x77ec (correct), seq 42:46, win 10000, length 4
AT_CHECK([ovs-ofctl monitor br0 65534 -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3; do
    ovs-appctl netdev-dummy/receive p1 '50 54 00 00 00 07 60 66 66 66 04 00 88 48 00 01 41 20 45 00 00 2c 00 00 00 00 ff 06 3a 78 c0 a8 00 01 c0 a8 00 02 00 50 00 00 00 00 00 2a 00 00 00 2a 50 00 27 10 77 44 00 00 48 4f 47 45'
done
OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6])
OVS_APP_EXIT_AND_WAIT(ovs-ofctl)

AT_CHECK([strip_metadata < ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): cookie=0xf total_len=62 in_port=1 (via action) data_len=62 (unbuffered)
mpls,vlan_tci=0x0000,dl_src=60:66:66:66:04:00,dl_dst=50:54:00:00:00:07,mpls_label=0,mpls_tc=0,mpls_ttl=255,mpls_bos=1
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xf total_len=62 in_port=1 (via action) data_len=62 (unbuffered)
mpls,vlan_tci=0x0000,dl_src=60:66:66:66:04:00,dl_dst=50:54:00:00:00:07,mpls_label=0,mpls_tc=0,mpls_ttl=255,mpls_bos=1
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xf total_len=62 in_port=1 (via action) data_len=62 (unbuffered)
mpls,vlan_tci=0x0000,dl_src=60:66:66:66:04:00,dl_dst=50:54:00:00:00:07,mpls_label=0,mpls_tc=0,mpls_ttl=255,mpls_bos=1
])

AT_CHECK([ovs-appctl time/warp 5000], [0], [ignore])

dnl Modified MPLS pop action.
dnl The input is a frame with a single MPLS label stack entry which tcpdump -vve shows as:
dnl 60:66:66:66:04:01 > 50:54:00:00:00:07, ethertype MPLS unicast (0x8847), length 62: MPLS (label 20, exp 0, [S], ttl 32)
dnl             (tos 0x0, ttl 255, id 0, offset 0, flags [none], proto TCP (6), length 44)
dnl         192.168.0.1.80 > 192.168.0.2.0: Flags [none], cksum 0x77ec (correct), seq 42:46, win 10000, length 4
AT_CHECK([ovs-ofctl monitor br0 65534 -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3; do
    ovs-appctl netdev-dummy/receive p1 '50 54 00 00 00 07 60 66 66 66 04 01 88 47 00 01 41 20 45 00 00 2c 00 00 00 00 ff 06 3a 78 c0 a8 00 01 c0 a8 00 02 00 50 00 00 00 00 00 2a 00 00 00 2a 50 00 27 10 77 44 00 00 48 4f 47 45'
done
OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6])
OVS_APP_EXIT_AND_WAIT(ovs-ofctl)

AT_CHECK([strip_metadata < ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): cookie=0xf total_len=62 in_port=1 (via action) data_len=62 (unbuffered)
mplsm,vlan_tci=0x0000,dl_src=60:66:66:66:04:01,dl_dst=50:54:00:00:00:07,mpls_label=0,mpls_tc=0,mpls_ttl=254,mpls_bos=1
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xf total_len=62 in_port=1 (via action) data_len=62 (unbuffered)
mplsm,vlan_tci=0x0000,dl_src=60:66:66:66:04:01,dl_dst=50:54:00:00:00:07,mpls_label=0,mpls_tc=0,mpls_ttl=254,mpls_bos=1
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xf total_len=62 in_port=1 (via action) data_len=62 (unbuffered)
mplsm,vlan_tci=0x0000,dl_src=60:66:66:66:04:01,dl_dst=50:54:00:00:00:07,mpls_label=0,mpls_tc=0,mpls_ttl=254,mpls_bos=1
])

AT_CHECK([ovs-appctl time/warp 5000], [0], [ignore])

dnl Modified MPLS pop action.
dnl The input is a frame with a single MPLS label stack entry which tcpdump -vve shows as:
dnl 60:66:66:66:04:10 > 50:54:00:00:00:07, ethertype MPLS multicast (0x8848), length 62: MPLS (label 20, exp 0, [S], ttl 32)
dnl             (tos 0x0, ttl 255, id 0, offset 0, flags [none], proto TCP (6), length 44)
dnl         192.168.0.1.80 > 192.168.0.2.0: Flags [none], cksum 0x77ec (correct), seq 42:46, win 10000, length 4
AT_CHECK([ovs-ofctl monitor br0 65534 -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3; do
    ovs-appctl netdev-dummy/receive p1 '50 54 00 00 00 07 60 66 66 66 04 10 88 48 00 01 41 20 45 00 00 2c 00 00 00 00 ff 06 3a 78 c0 a8 00 01 c0 a8 00 02 00 50 00 00 00 00 00 2a 00 00 00 2a 50 00 27 10 77 44 00 00 48 4f 47 45'
done
OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6])
OVS_APP_EXIT_AND_WAIT(ovs-ofctl)

AT_CHECK([strip_metadata <  ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): cookie=0xf total_len=62 in_port=1 (via action) data_len=62 (unbuffered)
mplsm,vlan_tci=0x0000,dl_src=60:66:66:66:04:10,dl_dst=50:54:00:00:00:07,mpls_label=0,mpls_tc=0,mpls_ttl=253,mpls_bos=1
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xf total_len=62 in_port=1 (via action) data_len=62 (unbuffered)
mplsm,vlan_tci=0x0000,dl_src=60:66:66:66:04:10,dl_dst=50:54:00:00:00:07,mpls_label=0,mpls_tc=0,mpls_ttl=253,mpls_bos=1
dnl
NXT_PACKET_IN (xid=0x0): cookie=0xf total_len=62 in_port=1 (via action) data_len=62 (unbuffered)
mplsm,vlan_tci=0x0000,dl_src=60:66:66:66:04:10,dl_dst=50:54:00:00:00:07,mpls_label=0,mpls_tc=0,mpls_ttl=253,mpls_bos=1
])

AT_CHECK([ovs-appctl time/warp 5000], [0], [ignore])

dnl Modified MPLS pop action.
dnl The input is a frame with a single MPLS label stack entry which tcpdump -vve shows as:
dnl 60:66:66:66:05:00 > 50:54:00:00:00:07, ethertype MPLS unicast (0x8847), length 62: MPLS (label 20, exp 0, [S], ttl 32)
dnl             (tos 0x0, ttl 255, id 0, offset 0, flags [none], proto TCP (6), length 44)
dnl         192.168.0.1.80 > 192.168.0.2.0: Flags [none], cksum 0x77ec (correct), seq 42:46, win 10000, length 4
AT_CHECK([ovs-ofctl monitor br0 65534 -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3; do
    ovs-appctl netdev-dummy/receive p1 '50 54 00 00 00 07 60 66 66 66 05 00 88 47 00 01 41 20 45 00 00 2c 00 00 00 00 ff 06 3a 78 c0 a8 00 01 c0 a8 00 02 00 50 00 00 00 00 00 2a 00 00 00 2a 50 00 27 10 77 44 00 00 48 4f 47 45'
done

OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6])
OVS_APP_EXIT_AND_WAIT(ovs-ofctl)

AT_CHECK([cat ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): cookie=0x5 total_len=62 in_port=1 (via action) data_len=62 (unbuffered)
mpls,vlan_tci=0x0000,dl_src=60:66:66:66:05:00,dl_dst=50:54:00:00:00:07,mpls_label=20,mpls_tc=0,mpls_ttl=32,mpls_bos=1
dnl
NXT_PACKET_IN (xid=0x0): cookie=0x5 total_len=62 in_port=1 (via action) data_len=62 (unbuffered)
mpls,vlan_tci=0x0000,dl_src=60:66:66:66:05:00,dl_dst=50:54:00:00:00:07,mpls_label=20,mpls_tc=0,mpls_ttl=32,mpls_bos=1
dnl
NXT_PACKET_IN (xid=0x0): cookie=0x5 total_len=62 in_port=1 (via action) data_len=62 (unbuffered)
mpls,vlan_tci=0x0000,dl_src=60:66:66:66:05:00,dl_dst=50:54:00:00:00:07,mpls_label=20,mpls_tc=0,mpls_ttl=32,mpls_bos=1
])

AT_CHECK([ovs-appctl time/warp 5000], [0], [ignore])

dnl Modified MPLS pop action.
dnl The input is a frame with a single MPLS label stack entry which tcpdump -vve shows as:
dnl 60:66:66:66:05:01 > 50:54:00:00:00:07, ethertype MPLS multicast (0x8848), length 62: MPLS (label 20, exp 0, [S], ttl 32)
dnl             (tos 0x0, ttl 255, id 0, offset 0, flags [none], proto TCP (6), length 44)
dnl         192.168.0.1.80 > 192.168.0.2.0: Flags [none], cksum 0x77ec (correct), seq 42:46, win 10000, length 4
AT_CHECK([ovs-ofctl monitor br0 65534 -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3; do
    ovs-appctl netdev-dummy/receive p1 '50 54 00 00 00 07 60 66 66 66 05 01 88 48 00 01 41 20 45 00 00 2c 00 00 00 00 ff 06 3a 78 c0 a8 00 01 c0 a8 00 02 00 50 00 00 00 00 00 2a 00 00 00 2a 50 00 27 10 77 44 00 00 48 4f 47 45'
done
OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6])
OVS_APP_EXIT_AND_WAIT(ovs-ofctl)

AT_CHECK([cat ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): cookie=0x5 total_len=62 in_port=1 (via action) data_len=62 (unbuffered)
mplsm,vlan_tci=0x0000,dl_src=60:66:66:66:05:01,dl_dst=50:54:00:00:00:07,mpls_label=20,mpls_tc=0,mpls_ttl=31,mpls_bos=1
dnl
NXT_PACKET_IN (xid=0x0): cookie=0x5 total_len=62 in_port=1 (via action) data_len=62 (unbuffered)
mplsm,vlan_tci=0x0000,dl_src=60:66:66:66:05:01,dl_dst=50:54:00:00:00:07,mpls_label=20,mpls_tc=0,mpls_ttl=31,mpls_bos=1
dnl
NXT_PACKET_IN (xid=0x0): cookie=0x5 total_len=62 in_port=1 (via action) data_len=62 (unbuffered)
mplsm,vlan_tci=0x0000,dl_src=60:66:66:66:05:01,dl_dst=50:54:00:00:00:07,mpls_label=20,mpls_tc=0,mpls_ttl=31,mpls_bos=1
])

AT_CHECK([ovs-appctl time/warp 5000], [0], [ignore])

dnl Modified MPLS pop action.
dnl The input is a frame with a single MPLS label stack entry which tcpdump -vve shows as:
dnl 60:66:66:66:05:10 > 50:54:00:00:00:07, ethertype MPLS unicast (0x8847), length 62: MPLS (label 20, exp 0, [S], ttl 32)
dnl             (tos 0x0, ttl 255, id 0, offset 0, flags [none], proto TCP (6), length 44)
dnl         192.168.0.1.80 > 192.168.0.2.0: Flags [none], cksum 0x77ec (correct), seq 42:46, win 10000, length 4
AT_CHECK([ovs-ofctl monitor br0 65534 -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3; do
    ovs-appctl netdev-dummy/receive p1 '50 54 00 00 00 07 60 66 66 66 05 10 88 47 00 01 41 20 45 00 00 2c 00 00 00 00 ff 06 3a 78 c0 a8 00 01 c0 a8 00 02 00 50 00 00 00 00 00 2a 00 00 00 2a 50 00 27 10 77 44 00 00 48 4f 47 45'
done

OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6])
OVS_APP_EXIT_AND_WAIT(ovs-ofctl)

AT_CHECK([cat ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): cookie=0x5 total_len=62 in_port=1 (via action) data_len=62 (unbuffered)
mpls,vlan_tci=0x0000,dl_src=60:66:66:66:05:10,dl_dst=50:54:00:00:00:07,mpls_label=20,mpls_tc=0,mpls_ttl=31,mpls_bos=1
dnl
NXT_PACKET_IN (xid=0x0): cookie=0x5 total_len=62 in_port=1 (via action) data_len=62 (unbuffered)
mpls,vlan_tci=0x0000,dl_src=60:66:66:66:05:10,dl_dst=50:54:00:00:00:07,mpls_label=20,mpls_tc=0,mpls_ttl=31,mpls_bos=1
dnl
NXT_PACKET_IN (xid=0x0): cookie=0x5 total_len=62 in_port=1 (via action) data_len=62 (unbuffered)
mpls,vlan_tci=0x0000,dl_src=60:66:66:66:05:10,dl_dst=50:54:00:00:00:07,mpls_label=20,mpls_tc=0,mpls_ttl=31,mpls_bos=1
])

AT_CHECK([ovs-appctl revalidator/purge], [0])
AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
 cookie=0x5, n_packets=3, n_bytes=186, dl_src=60:66:66:66:05:00 actions=push_mpls:0x8848,pop_mpls:0x8847,CONTROLLER:65535
 cookie=0x5, n_packets=3, n_bytes=186, dl_src=60:66:66:66:05:01 actions=push_mpls:0x8847,pop_mpls:0x8848,dec_mpls_ttl,CONTROLLER:65535
 cookie=0x5, n_packets=3, n_bytes=186, dl_src=60:66:66:66:05:10 actions=push_mpls:0x8848,dec_mpls_ttl,pop_mpls:0x8847,dec_mpls_ttl,CONTROLLER:65535
 cookie=0xa, n_packets=3, n_bytes=102, dl_src=40:44:44:44:44:45 actions=push_mpls:0x8847,load:0xa->OXM_OF_MPLS_LABEL[[]],load:0x3->OXM_OF_MPLS_TC[[]],dec_mpls_ttl,CONTROLLER:65535
 cookie=0xa, n_packets=3, n_bytes=102, dl_src=40:44:44:44:44:46 actions=push_mpls:0x8847,load:0xa->OXM_OF_MPLS_LABEL[[]],load:0x3->OXM_OF_MPLS_TC[[]],set_mpls_ttl(10),CONTROLLER:65535
 cookie=0xa, n_packets=3, n_bytes=102, dl_src=40:44:44:44:44:47 actions=push_mpls:0x8847,load:0xa->OXM_OF_MPLS_LABEL[[]],load:0x3->OXM_OF_MPLS_TC[[]],dec_mpls_ttl,set_mpls_ttl(10),CONTROLLER:65535
 cookie=0xa, n_packets=3, n_bytes=102, dl_src=40:44:44:44:44:48 actions=push_mpls:0x8847,load:0xa->OXM_OF_MPLS_LABEL[[]],load:0x3->OXM_OF_MPLS_TC[[]],set_mpls_ttl(10),dec_mpls_ttl,CONTROLLER:65535
 cookie=0xa, n_packets=3, n_bytes=102, dl_src=41:44:44:44:44:42 actions=push_mpls:0x8847,load:0xa->OXM_OF_MPLS_LABEL[[]],load:0x3->OXM_OF_MPLS_TC[[]],pop_mpls:0x0800,CONTROLLER:65535
 cookie=0xa, n_packets=3, n_bytes=114, dl_src=40:44:44:44:44:44 actions=push_mpls:0x8847,load:0xa->OXM_OF_MPLS_LABEL[[]],load:0x3->OXM_OF_MPLS_TC[[]],CONTROLLER:65535
 cookie=0xa, n_packets=3, n_bytes=318, dl_src=40:44:44:44:44:42 actions=push_mpls:0x8847,load:0xa->OXM_OF_MPLS_LABEL[[]],load:0x3->OXM_OF_MPLS_TC[[]],CONTROLLER:65535
 cookie=0xa, n_packets=3, n_bytes=54, dl_src=40:44:44:44:44:43 actions=push_mpls:0x8847,load:0xa->OXM_OF_MPLS_LABEL[[]],load:0x3->OXM_OF_MPLS_TC[[]],CONTROLLER:65535
 cookie=0xa, n_packets=3, n_bytes=54, mpls,dl_src=40:44:44:44:44:49 actions=push_mpls:0x8848,load:0xa->OXM_OF_MPLS_LABEL[[]],CONTROLLER:65535
 cookie=0xb, n_packets=3, n_bytes=54, mpls,dl_src=50:55:55:55:55:55 actions=load:0x3e8->OXM_OF_MPLS_LABEL[[]],CONTROLLER:65535
 cookie=0xc, n_packets=3, n_bytes=162, dl_src=70:77:77:77:77:77 actions=push_mpls:0x8848,load:0x3e8->OXM_OF_MPLS_LABEL[[]],load:0x7->OXM_OF_MPLS_TC[[]],CONTROLLER:65535
 cookie=0xd, n_packets=3, n_bytes=138, dl_src=60:66:66:66:00:08 actions=pop_mpls:0x0806,resubmit(1,1)
 cookie=0xd, n_packets=3, n_bytes=186, dl_src=60:66:66:66:00:01 actions=pop_mpls:0x0800,dec_ttl,CONTROLLER:65535
 cookie=0xd, n_packets=3, n_bytes=186, dl_src=60:66:66:66:00:02 actions=pop_mpls:0x0800,load:0xa000001->NXM_OF_IP_DST[[]],CONTROLLER:65535
 cookie=0xd, n_packets=3, n_bytes=186, dl_src=60:66:66:66:00:03 actions=pop_mpls:0x0800,move:NXM_OF_IP_DST[[]]->NXM_OF_IP_SRC[[]],CONTROLLER:65535
 cookie=0xd, n_packets=3, n_bytes=186, dl_src=60:66:66:66:00:04 actions=pop_mpls:0x0800,push:NXM_OF_IP_DST[[]],pop:NXM_OF_IP_SRC[[]],CONTROLLER:65535
 cookie=0xd, n_packets=3, n_bytes=186, dl_src=60:66:66:66:00:05 actions=pop_mpls:0x0800,multipath(eth_src,50,modulo_n,1,0,NXM_OF_IP_SRC[[0..7]]),CONTROLLER:65535
 cookie=0xd, n_packets=3, n_bytes=186, dl_src=60:66:66:66:00:06 actions=pop_mpls:0x0800,bundle_load(eth_src,50,hrw,ofport,NXM_OF_IP_SRC[[0..15]],members:1,2),CONTROLLER:65535
 cookie=0xd, n_packets=3, n_bytes=186, dl_src=60:66:66:66:00:07 actions=pop_mpls:0x0800,learn(table=1,hard_timeout=60,eth_type=0x800,nw_proto=6,NXM_OF_IP_SRC[[]]=NXM_OF_IP_DST[[]]),CONTROLLER:65535
 cookie=0xd, n_packets=3, n_bytes=186, dl_src=60:66:66:66:00:09 actions=resubmit(,2),CONTROLLER:65535
 cookie=0xd, n_packets=3, n_bytes=186, dl_src=60:66:66:66:00:0a actions=pop_mpls:0x0800,mod_nw_dst:10.0.0.1,CONTROLLER:65535
 cookie=0xd, n_packets=3, n_bytes=186, dl_src=60:66:66:66:00:0b actions=pop_mpls:0x0800,mod_nw_src:10.0.0.1,CONTROLLER:65535
 cookie=0xd, n_packets=3, n_bytes=186, dl_src=60:66:66:66:66:66 actions=pop_mpls:0x0800,CONTROLLER:65535
 cookie=0xd, n_packets=3, n_bytes=198, dl_src=60:66:66:66:01:00 actions=pop_mpls:0x8848,CONTROLLER:65535
 cookie=0xd, n_packets=3, n_bytes=198, dl_src=60:66:66:66:01:01 actions=pop_mpls:0x8847,dec_mpls_ttl,CONTROLLER:65535
 cookie=0xd, n_packets=3, n_bytes=198, dl_src=60:66:66:66:01:02 actions=pop_mpls:0x8848,load:0x3->OXM_OF_MPLS_TC[[]],CONTROLLER:65535
 cookie=0xd, n_packets=3, n_bytes=198, dl_src=60:66:66:66:02:00 actions=pop_mpls:0x8847,pop_mpls:0x0800,CONTROLLER:65535
 cookie=0xd, table=1, n_packets=3, n_bytes=126, arp actions=CONTROLLER:65535
 cookie=0xdeadbeef, table=2, n_packets=3, n_bytes=186, dl_src=60:66:66:66:00:09 actions=pop_mpls:0x0800,mod_nw_tos:48
 cookie=0xe, n_packets=3, n_bytes=198, dl_src=60:66:66:66:02:01 actions=pop_mpls:0x8848,pop_mpls:0x0800,dec_ttl,CONTROLLER:65535
 cookie=0xe, n_packets=3, n_bytes=198, dl_src=60:66:66:66:02:10 actions=pop_mpls:0x8847,dec_mpls_ttl,pop_mpls:0x0800,dec_ttl,CONTROLLER:65535
 cookie=0xe, n_packets=3, n_bytes=210, dl_src=60:66:66:66:03:00 actions=pop_mpls:0x8848,pop_mpls:0x8848,CONTROLLER:65535
 cookie=0xe, n_packets=3, n_bytes=210, dl_src=60:66:66:66:03:01 actions=pop_mpls:0x8847,pop_mpls:0x8847,dec_mpls_ttl,CONTROLLER:65535
 cookie=0xe, n_packets=3, n_bytes=210, dl_src=60:66:66:66:03:10 actions=pop_mpls:0x8848,dec_mpls_ttl,pop_mpls:0x8848,dec_mpls_ttl,CONTROLLER:65535
 cookie=0xf, n_packets=3, n_bytes=186, dl_src=60:66:66:66:04:00 actions=pop_mpls:0x0800,push_mpls:0x8847,CONTROLLER:65535
 cookie=0xf, n_packets=3, n_bytes=186, dl_src=60:66:66:66:04:01 actions=pop_mpls:0x0800,push_mpls:0x8848,dec_mpls_ttl,CONTROLLER:65535
 cookie=0xf, n_packets=3, n_bytes=186, dl_src=60:66:66:66:04:10 actions=pop_mpls:0x0800,dec_ttl,push_mpls:0x8848,dec_mpls_ttl,CONTROLLER:65535
NXST_FLOW reply:
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - MPLS handling with goto_table])
OVS_VSWITCHD_START([dnl
   add-port br0 p1 -- set Interface p1 type=dummy
])
on_exit 'kill `cat ovs-ofctl.pid`'

AT_CAPTURE_FILE([ofctl_monitor.log])
AT_DATA([flows.txt], [dnl
table=0 mplsm actions=pop_mpls:0x800,goto_table(1)
table=1 ip,ip_dscp=8 actions=controller
])
AT_CHECK([ovs-ofctl -O OpenFlow12 add-flows br0 flows.txt])


dnl Modified MPLS pop action.
dnl The input is a frame with a single MPLS label stack entry which tcpdump -vve shows as:
dnl 60:66:66:66:00:08 > 50:54:00:00:00:01, ethertype MPLS multicast (0x8848), length 62: MPLS (label 20, exp 0, [S], ttl 32)
dnl             (tos 0x20, ttl 255, id 0, offset 0, flags [none], proto TCP (6), length 44)
dnl         192.168.0.1.80 > 192.168.0.2.0: Flags [none], cksum 0x77ec (correct), seq 42:46, win 10000, length 4
AT_CHECK([ovs-ofctl -O OpenFlow12 monitor br0 65534 -P standard --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3; do
    ovs-appctl netdev-dummy/receive p1 '50 54 00 00 00 01 60 66 66 66 00 08 88 48 00 01 41 20 45 20 00 2c 00 00 00 00 ff 06 3a 78 c0 a8 00 01 c0 a8 00 02 00 50 00 00 00 00 00 2a 00 00 00 2a 50 00 27 10 77 44 00 00 48 4f 47 45'
done
OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6])
OVS_APP_EXIT_AND_WAIT(ovs-ofctl)

AT_CHECK([strip_metadata < ofctl_monitor.log], [0], [dnl
OFPT_PACKET_IN (OF1.2) (xid=0x0): table_id=1 total_len=58 in_port=1 (via action) data_len=58 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=60:66:66:66:00:08,dl_dst=50:54:00:00:00:01,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=32,nw_ecn=0,nw_ttl=255,tp_src=80,tp_dst=0,tcp_flags=0 tcp_csum:7744
dnl
OFPT_PACKET_IN (OF1.2) (xid=0x0): table_id=1 total_len=58 in_port=1 (via action) data_len=58 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=60:66:66:66:00:08,dl_dst=50:54:00:00:00:01,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=32,nw_ecn=0,nw_ttl=255,tp_src=80,tp_dst=0,tcp_flags=0 tcp_csum:7744
dnl
OFPT_PACKET_IN (OF1.2) (xid=0x0): table_id=1 total_len=58 in_port=1 (via action) data_len=58 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=60:66:66:66:00:08,dl_dst=50:54:00:00:00:01,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=32,nw_ecn=0,nw_ttl=255,tp_src=80,tp_dst=0,tcp_flags=0 tcp_csum:7744
])

AT_CHECK([ovs-appctl revalidator/purge], [0])
AT_CHECK([ovs-ofctl -O OpenFlow12 dump-flows br0 | ofctl_strip | sort], [0], [dnl
 n_packets=3, n_bytes=186, mplsm actions=pop_mpls:0x0800,goto_table:1
 table=1, n_packets=3, n_bytes=174, ip,nw_tos=32 actions=CONTROLLER:65535
OFPST_FLOW reply (OF1.2):
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - MPLS handling with write_actions])
OVS_VSWITCHD_START([dnl
   add-port br0 p1 -- set Interface p1 type=dummy
])
on_exit 'kill `cat ovs-ofctl.pid`'

dnl N.B: The first (and only) action that accesses L3 data after the
dnl pop_mpls action is present in write_actions. This exercises recirculation
dnl triggered in write_actions due to a previous action not in write actions.
AT_CAPTURE_FILE([ofctl_monitor.log])
AT_DATA([flows.txt], [dnl
mplsm actions=pop_mpls:0x800,write_actions(dec_ttl,controller)
])
AT_CHECK([ovs-ofctl -O OpenFlow12 add-flows br0 flows.txt])

dnl Modified MPLS pop action.
dnl The input is a frame with a single MPLS label stack entry which tcpdump -vve shows as:
dnl 60:66:66:66:00:08 > 50:54:00:00:00:01, ethertype MPLS multicast (0x8848), length 62: MPLS (label 20, exp 0, [S], ttl 32)
dnl             (tos 0x20, ttl 255, id 0, offset 0, flags [none], proto TCP (6), length 44)
dnl         192.168.0.1.80 > 192.168.0.2.0: Flags [none], cksum 0x77ec (correct), seq 42:46, win 10000, length 4
AT_CHECK([ovs-ofctl -O OpenFlow12 monitor br0 65534 -P standard --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3; do
    ovs-appctl netdev-dummy/receive p1 '50 54 00 00 00 01 60 66 66 66 00 08 88 48 00 01 41 20 45 20 00 2c 00 00 00 00 ff 06 3a 78 c0 a8 00 01 c0 a8 00 02 00 50 00 00 00 00 00 2a 00 00 00 2a 50 00 27 10 77 44 00 00 48 4f 47 45'
done
OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6])
OVS_APP_EXIT_AND_WAIT(ovs-ofctl)

AT_CHECK([strip_metadata < ofctl_monitor.log], [0], [dnl
OFPT_PACKET_IN (OF1.2) (xid=0x0): total_len=58 in_port=1 (via action) data_len=58 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=60:66:66:66:00:08,dl_dst=50:54:00:00:00:01,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=32,nw_ecn=0,nw_ttl=254,tp_src=80,tp_dst=0,tcp_flags=0 tcp_csum:7744
dnl
OFPT_PACKET_IN (OF1.2) (xid=0x0): total_len=58 in_port=1 (via action) data_len=58 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=60:66:66:66:00:08,dl_dst=50:54:00:00:00:01,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=32,nw_ecn=0,nw_ttl=254,tp_src=80,tp_dst=0,tcp_flags=0 tcp_csum:7744
dnl
OFPT_PACKET_IN (OF1.2) (xid=0x0): total_len=58 in_port=1 (via action) data_len=58 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=60:66:66:66:00:08,dl_dst=50:54:00:00:00:01,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=32,nw_ecn=0,nw_ttl=254,tp_src=80,tp_dst=0,tcp_flags=0 tcp_csum:7744
])

AT_CHECK([ovs-appctl revalidator/purge], [0])
AT_CHECK([ovs-ofctl -O OpenFlow12 dump-flows br0 | ofctl_strip | sort], [0], [dnl
 n_packets=3, n_bytes=186, mplsm actions=pop_mpls:0x0800,write_actions(dec_ttl,CONTROLLER:65535)
OFPST_FLOW reply (OF1.2):
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - table-miss flow (OpenFlow 1.0)])
OVS_VSWITCHD_START([dnl
   add-port br0 p1 -- set Interface p1 type=dummy
])
on_exit 'kill `cat ovs-ofctl.pid`'

AT_CAPTURE_FILE([ofctl_monitor.log])
# A table-miss flow has priority 0 and no match
AT_CHECK([ovs-ofctl --protocols=OpenFlow10 add-flow br0 'priority=0 actions=output:CONTROLLER'])

dnl Singleton controller action.
AT_CHECK([ovs-ofctl monitor -P standard --protocols=OpenFlow10 br0 65534 --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3 ; do
    ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=10:11:11:11:11:11,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=8,dst=10),tcp_flags(0x002)'
done
OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6])
OVS_APP_EXIT_AND_WAIT([ovs-ofctl])

AT_CHECK([cat ofctl_monitor.log], [0], [dnl
OFPT_PACKET_IN (xid=0x0): total_len=54 in_port=1 (via action) data_len=54 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=10:11:11:11:11:11,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=10,tcp_flags=syn tcp_csum:2e7d
dnl
OFPT_PACKET_IN (xid=0x0): total_len=54 in_port=1 (via action) data_len=54 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=10:11:11:11:11:11,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=10,tcp_flags=syn tcp_csum:2e7d
dnl
OFPT_PACKET_IN (xid=0x0): total_len=54 in_port=1 (via action) data_len=54 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=10:11:11:11:11:11,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=10,tcp_flags=syn tcp_csum:2e7d
])

AT_CHECK([ovs-appctl revalidator/purge], [0])
AT_CHECK([ovs-ofctl --protocols=OpenFlow10 dump-flows br0 | ofctl_strip | sort], [0], [dnl
 n_packets=3, n_bytes=162, priority=0 actions=CONTROLLER:65535
NXST_FLOW reply:
])

OVS_VSWITCHD_STOP
AT_CLEANUP


AT_SETUP([ofproto-dpif - table-miss flow (OpenFlow 1.3)])
OVS_VSWITCHD_START([dnl
   add-port br0 p1 -- set Interface p1 type=dummy
])
on_exit 'kill `cat ovs-ofctl.pid`'

AT_CAPTURE_FILE([ofctl_monitor.log])
# A table-miss flow has priority 0 and no match
AT_CHECK([ovs-ofctl --protocols=OpenFlow13 add-flow br0 'priority=0 actions=output:CONTROLLER'])

dnl Singleton controller action.
AT_CHECK([ovs-ofctl monitor -P standard --protocols=OpenFlow13 br0 65534 --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3 ; do
    ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=10:11:11:11:11:11,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=8,dst=10),tcp_flags(0x002)'
done
OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6])
OVS_APP_EXIT_AND_WAIT([ovs-ofctl])

AT_CHECK([ovs-appctl time/warp 5000], [0], [ignore])

AT_CHECK([cat ofctl_monitor.log], [0], [dnl
OFPT_PACKET_IN (OF1.3) (xid=0x0): cookie=0x0 total_len=54 in_port=1 (via no_match) data_len=54 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=10:11:11:11:11:11,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=10,tcp_flags=syn tcp_csum:2e7d
dnl
OFPT_PACKET_IN (OF1.3) (xid=0x0): cookie=0x0 total_len=54 in_port=1 (via no_match) data_len=54 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=10:11:11:11:11:11,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=10,tcp_flags=syn tcp_csum:2e7d
dnl
OFPT_PACKET_IN (OF1.3) (xid=0x0): cookie=0x0 total_len=54 in_port=1 (via no_match) data_len=54 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=10:11:11:11:11:11,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=10,tcp_flags=syn tcp_csum:2e7d
])

AT_CHECK([ovs-appctl revalidator/purge], [0])
AT_CHECK([ovs-ofctl --protocols=OpenFlow13 dump-flows br0 | ofctl_strip | sort], [0], [dnl
 n_packets=3, n_bytes=162, priority=0 actions=CONTROLLER:65535
OFPST_FLOW reply (OF1.3):
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - table-miss flow with async config (OpenFlow 1.3)])
OVS_VSWITCHD_START([dnl
   add-port br0 p1 -- set Interface p1 type=dummy
])
on_exit 'kill `cat ovs-ofctl.pid`'

ovs-appctl time/stop

AT_CAPTURE_FILE([ofctl_monitor.log])
# A table-miss flow has priority 0 and no match
AT_CHECK([ovs-ofctl --protocols=OpenFlow13 add-flow br0 'priority=0 actions=output:CONTROLLER'])

dnl Singleton controller action.
AT_CHECK([ovs-ofctl monitor -P standard --protocols=OpenFlow13 br0 65534 --detach --no-chdir --pidfile 2> ofctl_monitor.log])

# Become secondary (OF 1.3), which should disable everything except port status.
ovs-appctl -t ovs-ofctl ofctl/send 041800180000000200000003000000000000000000000001

# Ensure that ovs-vswitchd gets a chance to reply before sending another command.
ovs-appctl time/warp 500 100

# Use OF 1.3 OFPT_SET_ASYNC to enable OFPR_NO_MATCH for secondary only.
ovs-appctl -t ovs-ofctl ofctl/send 041c002000000002000000000000000100000000000000000000000000000000

ovs-appctl time/warp 500 100
for i in 1 2 3 ; do
    ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=10:11:11:11:11:11,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=8,dst=10),tcp_flags(0x002)'
done
OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6])
OVS_APP_EXIT_AND_WAIT([ovs-ofctl])

AT_CHECK([ovs-appctl revalidator/purge], [0])
AT_CHECK([cat ofctl_monitor.log], [0], [dnl
send: OFPT_ROLE_REQUEST (OF1.3) (xid=0x2): role=secondary generation_id=1
OFPT_ROLE_REPLY (OF1.3) (xid=0x2): role=secondary generation_id=1
dnl
send: OFPT_SET_ASYNC (OF1.3) (xid=0x2):
 primary:
       PACKET_IN: (off)
     PORT_STATUS: (off)
    FLOW_REMOVED: (off)
     ROLE_STATUS: (off)
    TABLE_STATUS: (off)
  REQUESTFORWARD: (off)

 secondary:
       PACKET_IN: no_match
     PORT_STATUS: (off)
    FLOW_REMOVED: (off)
     ROLE_STATUS: (off)
    TABLE_STATUS: (off)
  REQUESTFORWARD: (off)
dnl
OFPT_PACKET_IN (OF1.3) (xid=0x0): cookie=0x0 total_len=54 in_port=1 (via no_match) data_len=54 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=10:11:11:11:11:11,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=10,tcp_flags=syn tcp_csum:2e7d
dnl
OFPT_PACKET_IN (OF1.3) (xid=0x0): cookie=0x0 total_len=54 in_port=1 (via no_match) data_len=54 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=10:11:11:11:11:11,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=10,tcp_flags=syn tcp_csum:2e7d
dnl
OFPT_PACKET_IN (OF1.3) (xid=0x0): cookie=0x0 total_len=54 in_port=1 (via no_match) data_len=54 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=10:11:11:11:11:11,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=10,tcp_flags=syn tcp_csum:2e7d
])

AT_CHECK([ovs-appctl time/warp 5000], [0], [ignore])

AT_CHECK([ovs-ofctl --protocols=OpenFlow13 dump-flows br0 | ofctl_strip | sort], [0], [dnl
 n_packets=3, n_bytes=162, priority=0 actions=CONTROLLER:65535
OFPST_FLOW reply (OF1.3):
])

OVS_VSWITCHD_STOP
AT_CLEANUP


AT_SETUP([ofproto-dpif - table-miss flow (OpenFlow 1.4)])
OVS_VSWITCHD_START([dnl
   add-port br0 p1 -- set Interface p1 type=dummy
])
on_exit 'kill `cat ovs-ofctl.pid`'

AT_CAPTURE_FILE([ofctl_monitor.log])
# A table-miss flow has priority 0 and no match
AT_CHECK([ovs-ofctl --protocols=OpenFlow14 add-flow br0 'priority=0 actions=output:CONTROLLER'])

dnl Singleton controller action.
AT_CHECK([ovs-ofctl monitor -P standard --protocols=OpenFlow14 br0 65534 --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3 ; do
    ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=10:11:11:11:11:11,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=8,dst=10),tcp_flags(0x002)'
done
OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6])
OVS_APP_EXIT_AND_WAIT([ovs-ofctl])

AT_CHECK([ovs-appctl revalidator/purge], [0])
AT_CHECK([cat ofctl_monitor.log], [0], [dnl
OFPT_PACKET_IN (OF1.4) (xid=0x0): cookie=0x0 total_len=54 in_port=1 (via no_match) data_len=54 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=10:11:11:11:11:11,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=10,tcp_flags=syn tcp_csum:2e7d
dnl
OFPT_PACKET_IN (OF1.4) (xid=0x0): cookie=0x0 total_len=54 in_port=1 (via no_match) data_len=54 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=10:11:11:11:11:11,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=10,tcp_flags=syn tcp_csum:2e7d
dnl
OFPT_PACKET_IN (OF1.4) (xid=0x0): cookie=0x0 total_len=54 in_port=1 (via no_match) data_len=54 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=10:11:11:11:11:11,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=10,tcp_flags=syn tcp_csum:2e7d
])

AT_CHECK([ovs-appctl time/warp 5000], [0], [ignore])

AT_CHECK([ovs-ofctl --protocols=OpenFlow14 dump-flows br0 | ofctl_strip | sort], [0], [dnl
 n_packets=3, n_bytes=162, priority=0 actions=CONTROLLER:65535
OFPST_FLOW reply (OF1.4):
])

OVS_VSWITCHD_STOP
AT_CLEANUP


AT_SETUP([ofproto-dpif - packet-in reasons (Openflow 1.3)])
OVS_VSWITCHD_START([dnl
   add-port br0 p1 -- set Interface p1 type=dummy
])
on_exit 'kill `cat ovs-ofctl.pid`'

AT_CAPTURE_FILE([ofctl_monitor.log])
AT_DATA([flows.txt], [dnl
table=0 in_port=1 actions=write_actions(output(CONTROLLER)),goto_table(1)
table=1 actions=output(CONTROLLER),goto_table(2)
table=2 actions=group:1234
])
AT_CHECK([ovs-ofctl --protocols=OpenFlow13 add-group br0 'group_id=1234,type=all,bucket=output:10,bucket=output:CONTROLLER'])
AT_CHECK([ovs-ofctl --protocols=OpenFlow13 add-flows br0 flows.txt])

dnl Singleton controller action.
AT_CHECK([ovs-ofctl monitor -P standard --protocols=OpenFlow13 br0 65534 --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3 ; do
    ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=10:11:11:11:11:11,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=8,dst=10),tcp_flags(0x002)'
done
AT_CHECK([ovs-ofctl packet-out br0 'in_port=NONE, packet=505400000007101111111111080045000028000000004006f97cc0a80001c0a800020008000a0000000000000000500200002e7d0000, actions=controller'])
OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 7])
OVS_APP_EXIT_AND_WAIT([ovs-ofctl])

AT_CHECK([ovs-appctl time/warp 5000], [0], [ignore])

AT_CHECK([cat ofctl_monitor.log], [0], [dnl
OFPT_PACKET_IN (OF1.3) (xid=0x0): table_id=1 cookie=0x0 total_len=54 in_port=1 (via action) data_len=54 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=10:11:11:11:11:11,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=10,tcp_flags=syn tcp_csum:2e7d
dnl
OFPT_PACKET_IN (OF1.3) (xid=0x0): table_id=2 cookie=0x0 total_len=54 in_port=1 (via action) data_len=54 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=10:11:11:11:11:11,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=10,tcp_flags=syn tcp_csum:2e7d
dnl
OFPT_PACKET_IN (OF1.3) (xid=0x0): cookie=0x0 total_len=54 in_port=1 (via action) data_len=54 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=10:11:11:11:11:11,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=10,tcp_flags=syn tcp_csum:2e7d
dnl
OFPT_PACKET_IN (OF1.3) (xid=0x0): table_id=1 cookie=0x0 total_len=54 in_port=1 (via action) data_len=54 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=10:11:11:11:11:11,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=10,tcp_flags=syn tcp_csum:2e7d
dnl
OFPT_PACKET_IN (OF1.3) (xid=0x0): table_id=2 cookie=0x0 total_len=54 in_port=1 (via action) data_len=54 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=10:11:11:11:11:11,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=10,tcp_flags=syn tcp_csum:2e7d
dnl
OFPT_PACKET_IN (OF1.3) (xid=0x0): cookie=0x0 total_len=54 in_port=1 (via action) data_len=54 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=10:11:11:11:11:11,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=10,tcp_flags=syn tcp_csum:2e7d
dnl
OFPT_PACKET_IN (OF1.3) (xid=0x0): table_id=1 cookie=0x0 total_len=54 in_port=1 (via action) data_len=54 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=10:11:11:11:11:11,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=10,tcp_flags=syn tcp_csum:2e7d
dnl
OFPT_PACKET_IN (OF1.3) (xid=0x0): table_id=2 cookie=0x0 total_len=54 in_port=1 (via action) data_len=54 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=10:11:11:11:11:11,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=10,tcp_flags=syn tcp_csum:2e7d
dnl
OFPT_PACKET_IN (OF1.3) (xid=0x0): cookie=0x0 total_len=54 in_port=1 (via action) data_len=54 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=10:11:11:11:11:11,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=10,tcp_flags=syn tcp_csum:2e7d
dnl
OFPT_PACKET_IN (OF1.3) (xid=0x0): total_len=54 in_port=ANY (via action) data_len=54 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=10:11:11:11:11:11,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=10,tcp_flags=syn tcp_csum:2e7d
])

AT_CHECK([ovs-appctl time/warp 5000], [0], [ignore])

AT_CHECK([ovs-ofctl --protocols=OpenFlow13 dump-flows br0 | ofctl_strip | sort], [0], [dnl
 n_packets=3, n_bytes=162, in_port=1 actions=write_actions(CONTROLLER:65535),goto_table:1
 table=1, n_packets=3, n_bytes=162, actions=CONTROLLER:65535,goto_table:2
 table=2, n_packets=3, n_bytes=162, actions=group:1234
OFPST_FLOW reply (OF1.3):
])

OVS_VSWITCHD_STOP
AT_CLEANUP


AT_SETUP([ofproto-dpif - packet-in reasons (Openflow 1.4)])
OVS_VSWITCHD_START([dnl
   add-port br0 p1 -- set Interface p1 type=dummy
])
on_exit 'kill `cat ovs-ofctl.pid`'

AT_CAPTURE_FILE([ofctl_monitor.log])
AT_DATA([flows.txt], [dnl
table=0 in_port=1 actions=write_actions(output(CONTROLLER)),goto_table(1)
table=1 actions=output(CONTROLLER),goto_table(2)
table=2 actions=group:1234
])
AT_CHECK([ovs-ofctl --protocols=OpenFlow14 add-group br0 'group_id=1234,type=all,bucket=output:10,bucket=output:CONTROLLER'])
AT_CHECK([ovs-ofctl --protocols=OpenFlow14 add-flows br0 flows.txt])

dnl Singleton controller action.
AT_CHECK([ovs-ofctl monitor -P standard --protocols=OpenFlow14 br0 65534 --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3 ; do
    ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=10:11:11:11:11:11,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=8,dst=10),tcp_flags(0x002)'
done
AT_CHECK([ovs-ofctl packet-out br0 'in_port=NONE, packet=505400000007101111111111080045000028000000004006f97cc0a80001c0a800020008000a0000000000000000500200002e7d0000, actions=controller'])
OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 7])
OVS_APP_EXIT_AND_WAIT([ovs-ofctl])

AT_CHECK([ovs-appctl time/warp 5000], [0], [ignore])

AT_CHECK([cat ofctl_monitor.log], [0], [dnl
OFPT_PACKET_IN (OF1.4) (xid=0x0): table_id=1 cookie=0x0 total_len=54 in_port=1 (via action) data_len=54 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=10:11:11:11:11:11,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=10,tcp_flags=syn tcp_csum:2e7d
dnl
OFPT_PACKET_IN (OF1.4) (xid=0x0): table_id=2 cookie=0x0 total_len=54 in_port=1 (via group) data_len=54 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=10:11:11:11:11:11,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=10,tcp_flags=syn tcp_csum:2e7d
dnl
OFPT_PACKET_IN (OF1.4) (xid=0x0): cookie=0x0 total_len=54 in_port=1 (via action_set) data_len=54 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=10:11:11:11:11:11,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=10,tcp_flags=syn tcp_csum:2e7d
dnl
OFPT_PACKET_IN (OF1.4) (xid=0x0): table_id=1 cookie=0x0 total_len=54 in_port=1 (via action) data_len=54 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=10:11:11:11:11:11,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=10,tcp_flags=syn tcp_csum:2e7d
dnl
OFPT_PACKET_IN (OF1.4) (xid=0x0): table_id=2 cookie=0x0 total_len=54 in_port=1 (via group) data_len=54 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=10:11:11:11:11:11,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=10,tcp_flags=syn tcp_csum:2e7d
dnl
OFPT_PACKET_IN (OF1.4) (xid=0x0): cookie=0x0 total_len=54 in_port=1 (via action_set) data_len=54 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=10:11:11:11:11:11,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=10,tcp_flags=syn tcp_csum:2e7d
dnl
OFPT_PACKET_IN (OF1.4) (xid=0x0): table_id=1 cookie=0x0 total_len=54 in_port=1 (via action) data_len=54 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=10:11:11:11:11:11,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=10,tcp_flags=syn tcp_csum:2e7d
dnl
OFPT_PACKET_IN (OF1.4) (xid=0x0): table_id=2 cookie=0x0 total_len=54 in_port=1 (via group) data_len=54 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=10:11:11:11:11:11,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=10,tcp_flags=syn tcp_csum:2e7d
dnl
OFPT_PACKET_IN (OF1.4) (xid=0x0): cookie=0x0 total_len=54 in_port=1 (via action_set) data_len=54 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=10:11:11:11:11:11,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=10,tcp_flags=syn tcp_csum:2e7d
dnl
OFPT_PACKET_IN (OF1.4) (xid=0x0): total_len=54 in_port=ANY (via packet_out) data_len=54 (unbuffered)
tcp,vlan_tci=0x0000,dl_src=10:11:11:11:11:11,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=10,tcp_flags=syn tcp_csum:2e7d
])

AT_CHECK([ovs-appctl time/warp 5000], [0], [ignore])

AT_CHECK([ovs-ofctl --protocols=OpenFlow14 dump-flows br0 | ofctl_strip | sort], [0], [dnl
 n_packets=3, n_bytes=162, in_port=1 actions=write_actions(CONTROLLER:65535),goto_table:1
 table=1, n_packets=3, n_bytes=162, actions=CONTROLLER:65535,goto_table:2
 table=2, n_packets=3, n_bytes=162, actions=group:1234
OFPST_FLOW reply (OF1.4):
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - packet-in reasons (Openflow 1.3)])

OVS_VSWITCHD_START([dnl
    set bridge br0 datapath_type=dummy \
        protocols=OpenFlow10,OpenFlow13,OpenFlow14,OpenFlow15 -- \
    add-port br0 p1 -- set Interface p1 type=dummy ofport_request=1])

AT_CHECK([
    ovs-ofctl -OOpenFlow13 del-flows br0
    ovs-ofctl -OOpenFlow13 add-group br0 "group_id=6000,type=all,bucket=actions=controller,bucket=actions=resubmit(,48),bucket=actions=resubmit(,81)"
    ovs-ofctl -OOpenFlow13 add-flow br0 "table=0, in_port=1, vlan_tci=0x0000/0x1fff actions=write_metadata:0x67870000000000/0xffffff0000000001,goto_table:17"
    ovs-ofctl -OOpenFlow13 add-flow br0 "table=17,  priority=10,metadata=0x67870000000000/0xffffff0000000000 actions=write_metadata:0xe067870000000000/0xfffffffffffffffe,goto_table:60"
    ovs-ofctl -OOpenFlow13 add-flow br0 "table=60,  priority=0 actions=resubmit(,17)"
    ovs-ofctl -OOpenFlow13 add-flow br0 "table=17,  priority=10,metadata=0xe067870000000000/0xffffff0000000000 actions=write_metadata:0x67871d4d000000/0xfffffffffffffffe,goto_table:43"
    ovs-ofctl -OOpenFlow13 add-flow br0 "table=43,  priority=100,icmp actions=group:6000"
    ovs-ofctl -OOpenFlow13 add-flow br0 "table=48, priority=0 actions=resubmit(,49),resubmit(,50)"
    ovs-ofctl -OOpenFlow13 add-flow br0 "table=50, priority=0 actions=controller"
], [0], [ignore])

AT_CHECK([ovs-ofctl monitor -OOpenFlow13 -P standard br0 65534 --detach --no-chdir --pidfile 2> ofctl_monitor.log])

AT_CHECK([
    ovs-appctl netdev-dummy/receive p1 1e2ce92a669e3a6dd2099cab0800450000548a53400040011addc0a80a0ac0a80a1e08006f200a4d0001fc509a58000000002715020000000000101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637
], [0], [ignore])

OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 1])
OVS_APP_EXIT_AND_WAIT(ovs-ofctl)

AT_CHECK([cat ofctl_monitor.log], [0], [dnl
OFPT_PACKET_IN (OF1.3) (xid=0x0): table_id=43 cookie=0x0 total_len=98 metadata=0x67871d4d000000,in_port=1 (via action) data_len=98 (unbuffered)
icmp,vlan_tci=0x0000,dl_src=3a:6d:d2:09:9c:ab,dl_dst=1e:2c:e9:2a:66:9e,nw_src=192.168.10.10,nw_dst=192.168.10.30,nw_tos=0,nw_ecn=0,nw_ttl=64,icmp_type=8,icmp_code=0 icmp_csum:6f20
dnl
OFPT_PACKET_IN (OF1.3) (xid=0x0): table_id=50 cookie=0x0 total_len=98 metadata=0x67871d4d000000,in_port=1 (via no_match) data_len=98 (unbuffered)
icmp,vlan_tci=0x0000,dl_src=3a:6d:d2:09:9c:ab,dl_dst=1e:2c:e9:2a:66:9e,nw_src=192.168.10.10,nw_dst=192.168.10.30,nw_tos=0,nw_ecn=0,nw_ttl=64,icmp_type=8,icmp_code=0 icmp_csum:6f20
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - ARP modification slow-path])
OVS_VSWITCHD_START
add_of_ports br0 1 2

ovs-vsctl -- set Interface p2 type=dummy options:pcap=p2.pcap
ovs-ofctl add-flow br0 'in_port=1,arp actions=load:2->OXM_OF_ARP_OP[[]],2,load:0xc0a88001->OXM_OF_ARP_SPA[[]],2,load:0x404444444441->OXM_OF_ARP_THA[[]],2'

# Input some packets that should follow the arp modification slow-path.
for i in 1 2 3; do
    ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=80:88:88:88:88:88,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:05,tha=00:00:00:00:00:00)'
done
AT_CHECK([ovs-appctl time/warp 5000], [0], [ignore])

# Check the packets that were output.
AT_CHECK([ovs-ofctl parse-pcap p2.pcap], [0], [dnl
arp,in_port=ANY,vlan_tci=0x0000,dl_src=80:88:88:88:88:88,dl_dst=ff:ff:ff:ff:ff:ff,arp_spa=192.168.0.1,arp_tpa=192.168.0.2,arp_op=2,arp_sha=50:54:00:00:00:05,arp_tha=00:00:00:00:00:00
arp,in_port=ANY,vlan_tci=0x0000,dl_src=80:88:88:88:88:88,dl_dst=ff:ff:ff:ff:ff:ff,arp_spa=192.168.128.1,arp_tpa=192.168.0.2,arp_op=2,arp_sha=50:54:00:00:00:05,arp_tha=00:00:00:00:00:00
arp,in_port=ANY,vlan_tci=0x0000,dl_src=80:88:88:88:88:88,dl_dst=ff:ff:ff:ff:ff:ff,arp_spa=192.168.128.1,arp_tpa=192.168.0.2,arp_op=2,arp_sha=50:54:00:00:00:05,arp_tha=40:44:44:44:44:41
arp,in_port=ANY,vlan_tci=0x0000,dl_src=80:88:88:88:88:88,dl_dst=ff:ff:ff:ff:ff:ff,arp_spa=192.168.0.1,arp_tpa=192.168.0.2,arp_op=2,arp_sha=50:54:00:00:00:05,arp_tha=00:00:00:00:00:00
arp,in_port=ANY,vlan_tci=0x0000,dl_src=80:88:88:88:88:88,dl_dst=ff:ff:ff:ff:ff:ff,arp_spa=192.168.128.1,arp_tpa=192.168.0.2,arp_op=2,arp_sha=50:54:00:00:00:05,arp_tha=00:00:00:00:00:00
arp,in_port=ANY,vlan_tci=0x0000,dl_src=80:88:88:88:88:88,dl_dst=ff:ff:ff:ff:ff:ff,arp_spa=192.168.128.1,arp_tpa=192.168.0.2,arp_op=2,arp_sha=50:54:00:00:00:05,arp_tha=40:44:44:44:44:41
arp,in_port=ANY,vlan_tci=0x0000,dl_src=80:88:88:88:88:88,dl_dst=ff:ff:ff:ff:ff:ff,arp_spa=192.168.0.1,arp_tpa=192.168.0.2,arp_op=2,arp_sha=50:54:00:00:00:05,arp_tha=00:00:00:00:00:00
arp,in_port=ANY,vlan_tci=0x0000,dl_src=80:88:88:88:88:88,dl_dst=ff:ff:ff:ff:ff:ff,arp_spa=192.168.128.1,arp_tpa=192.168.0.2,arp_op=2,arp_sha=50:54:00:00:00:05,arp_tha=00:00:00:00:00:00
arp,in_port=ANY,vlan_tci=0x0000,dl_src=80:88:88:88:88:88,dl_dst=ff:ff:ff:ff:ff:ff,arp_spa=192.168.128.1,arp_tpa=192.168.0.2,arp_op=2,arp_sha=50:54:00:00:00:05,arp_tha=40:44:44:44:44:41
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - VLAN handling])
OVS_VSWITCHD_START(
  [set Bridge br0 fail-mode=standalone -- \
   add-port br0 p1                                  trunks=10,12 -- \
   add-port br0 p2                           tag=10              -- \
   add-port br0 p3                           tag=12              \
                   other-config:priority-tags=if-nonzero         -- \
   add-port br0 p4                           tag=12              -- \
   add-port br0 p5 vlan_mode=native-tagged   tag=10              -- \
   add-port br0 p6 vlan_mode=native-tagged   tag=10 trunks=10,12 -- \
   add-port br0 p7 vlan_mode=native-untagged tag=12              -- \
   add-port br0 p8 vlan_mode=native-untagged tag=12 trunks=10,12 \
                   other-config:priority-tags=if-nonzero         -- \
   add-port br0 p9 vlan_mode=dot1q-tunnel    tag=10              other-config:qinq-ethtype=802.1q  -- \
   add-port br0 p10 vlan_mode=dot1q-tunnel   tag=10 cvlans=10,12 other-config:qinq-ethtype=802.1q  -- \
   add-port br0 p11 vlan_mode=dot1q-tunnel   tag=12              other-config:qinq-ethtype=802.1q  -- \
   add-port br0 p12 vlan_mode=dot1q-tunnel   tag=12              other-config:qinq-ethtype=802.1q  \
                   other-config:priority-tags=if-nonzero         -- \
   set Interface p1 type=dummy -- \
   set Interface p2 type=dummy -- \
   set Interface p3 type=dummy -- \
   set Interface p4 type=dummy -- \
   set Interface p5 type=dummy -- \
   set Interface p6 type=dummy -- \
   set Interface p7 type=dummy -- \
   set Interface p8 type=dummy -- \
   set Interface p9 type=dummy -- \
   set Interface p10 type=dummy -- \
   set Interface p11 type=dummy -- \
   set Interface p12 type=dummy --])

dnl Each of these specifies an in_port by number, a VLAN VID (or "none"),
dnl a VLAN PCP (used if the VID isn't "none") and the expected set of datapath
dnl actions.
for tuple in \
        "100 none 0 drop" \
        "100 0    0 drop" \
        "100 0    1 drop" \
        "100 10   0 1,5,6,7,8,pop_vlan,2,9" \
        "100 10   1 1,5,6,7,8,pop_vlan,2,9" \
        "100 11   0 5,7" \
        "100 11   1 5,7" \
        "100 12   0 1,5,6,pop_vlan,3,4,7,8,11,12" \
        "100 12   1 1,5,6,pop_vlan,4,7,11,push_vlan(vid=0,pcp=1),3,8,12" \
        "1  none 0 drop" \
        "1  0    0 drop" \
        "1  0    1 drop" \
        "1  10   0 5,6,7,8,100,pop_vlan,2,9" \
        "1  10   1 5,6,7,8,100,pop_vlan,2,9" \
        "1  11   0 drop" \
        "1  11   1 drop" \
        "1  12   0 5,6,100,pop_vlan,3,4,7,8,11,12" \
        "1  12   1 5,6,100,pop_vlan,4,7,11,push_vlan(vid=0,pcp=1),3,8,12" \
        "2  none 0 9,push_vlan(vid=10,pcp=0),1,5,6,7,8,100" \
        "2  0    0 pop_vlan,9,push_vlan(vid=10,pcp=0),1,5,6,7,8,100" \
        "2  0    1 pop_vlan,9,push_vlan(vid=10,pcp=1),1,5,6,7,8,100" \
        "2  10   0 drop" \
        "2  10   1 drop" \
        "2  11   0 drop" \
        "2  11   1 drop" \
        "2  12   0 drop" \
        "2  12   1 drop" \
        "3  none 0 4,7,8,11,12,push_vlan(vid=12,pcp=0),1,5,6,100" \
        "3  0    0 pop_vlan,4,7,8,11,12,push_vlan(vid=12,pcp=0),1,5,6,100" \
        "3  0    1 8,12,pop_vlan,4,7,11,push_vlan(vid=12,pcp=1),1,5,6,100" \
        "3  10   0 drop" \
        "3  10   1 drop" \
        "3  11   0 drop" \
        "3  11   1 drop" \
        "3  12   0 drop" \
        "3  12   1 drop" \
        "4  none 0 3,7,8,11,12,push_vlan(vid=12,pcp=0),1,5,6,100" \
        "4  0    0 pop_vlan,3,7,8,11,12,push_vlan(vid=12,pcp=0),1,5,6,100" \
        "4  0    1 3,8,12,pop_vlan,7,11,push_vlan(vid=12,pcp=1),1,5,6,100" \
        "4  10   0 drop" \
        "4  10   1 drop" \
        "4  11   0 drop" \
        "4  11   1 drop" \
        "4  12   0 drop" \
        "4  12   1 drop" \
        "5  none 0 2,9,push_vlan(vid=10,pcp=0),1,6,7,8,100" \
        "5  0    0 pop_vlan,2,9,push_vlan(vid=10,pcp=0),1,6,7,8,100" \
        "5  0    1 pop_vlan,2,9,push_vlan(vid=10,pcp=1),1,6,7,8,100" \
        "5  10   0 1,6,7,8,100,pop_vlan,2,9" \
        "5  10   1 1,6,7,8,100,pop_vlan,2,9" \
        "5  11   0 7,100" \
        "5  11   1 7,100" \
        "5  12   0 1,6,100,pop_vlan,3,4,7,8,11,12" \
        "5  12   1 1,6,100,pop_vlan,4,7,11,push_vlan(vid=0,pcp=1),3,8,12" \
        "6  none 0 2,9,push_vlan(vid=10,pcp=0),1,5,7,8,100" \
        "6  0    0 pop_vlan,2,9,push_vlan(vid=10,pcp=0),1,5,7,8,100" \
        "6  0    1 pop_vlan,2,9,push_vlan(vid=10,pcp=1),1,5,7,8,100" \
        "6  10   0 1,5,7,8,100,pop_vlan,2,9" \
        "6  10   1 1,5,7,8,100,pop_vlan,2,9" \
        "6  11   0 drop" \
        "6  11   1 drop" \
        "6  12   0 1,5,100,pop_vlan,3,4,7,8,11,12" \
        "6  12   1 1,5,100,pop_vlan,4,7,11,push_vlan(vid=0,pcp=1),3,8,12" \
        "7  none 0 3,4,8,11,12,push_vlan(vid=12,pcp=0),1,5,6,100" \
        "7  0    0 pop_vlan,3,4,8,11,12,push_vlan(vid=12,pcp=0),1,5,6,100" \
        "7  0    1 3,8,12,pop_vlan,4,11,push_vlan(vid=12,pcp=1),1,5,6,100" \
        "7  10   0 1,5,6,8,100,pop_vlan,2,9" \
        "7  10   1 1,5,6,8,100,pop_vlan,2,9" \
        "7  11   0 5,100" \
        "7  11   1 5,100" \
        "7  12   0 1,5,6,100,pop_vlan,3,4,8,11,12" \
        "7  12   1 1,5,6,100,pop_vlan,4,11,push_vlan(vid=0,pcp=1),3,8,12" \
        "8  none 0 3,4,7,11,12,push_vlan(vid=12,pcp=0),1,5,6,100" \
        "8  0    0 pop_vlan,3,4,7,11,12,push_vlan(vid=12,pcp=0),1,5,6,100" \
        "8  0    1 3,12,pop_vlan,4,7,11,push_vlan(vid=12,pcp=1),1,5,6,100" \
        "8  10   0 1,5,6,7,100,pop_vlan,2,9" \
        "8  10   1 1,5,6,7,100,pop_vlan,2,9" \
        "8  11   0 drop" \
        "8  11   1 drop" \
        "8  12   0 1,5,6,100,pop_vlan,3,4,7,11,12" \
        "8  12   1 1,5,6,100,pop_vlan,4,7,11,push_vlan(vid=0,pcp=1),3,12" \
        "9  none 0 2,push_vlan(vid=10,pcp=0),1,5,6,7,8,100" \
        "9  10   0 10,push_vlan(vid=10,pcp=0),1,5,6,7,8,100" \
        "9  11   0 push_vlan(vid=10,pcp=0),1,5,6,7,8,100" \
        "10 none 0 drop" \
        "10 0    0 drop" \
        "10 11   0 drop" \
        "10 12   0 9,push_vlan(vid=10,pcp=0),1,5,6,7,8,100" \
        "11 10   0 7,8,12,push_vlan(vid=12,pcp=0),1,5,6,100" \
        "11 10   1 7,8,12,push_vlan(vid=12,pcp=0),1,5,6,100"
do
  set $tuple
  in_port=$1
  vlan=$2
  pcp=$3
  expected=$4

  if test $vlan = none; then
    flow="in_port($in_port),eth(src=50:54:00:00:00:01,dst=ff:ff:ff:ff:ff:ff),eth_type(0xabcd)"
  else
    flow="in_port($in_port),eth(src=50:54:00:00:00:01,dst=ff:ff:ff:ff:ff:ff),eth_type(0x8100),vlan(vid=$vlan,pcp=$pcp),encap(eth_type(0xabcd))"
  fi

  echo "----------------------------------------------------------------------"
  echo "in_port=$in_port vlan=$vlan pcp=$pcp"

  AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow"], [0], [stdout])
  actual=`tail -1 stdout | sed 's/Datapath actions: //'`

  AT_CHECK([ovs-dpctl normalize-actions "$flow" "$expected"], [0], [stdout])
  mv stdout expout
  AT_CHECK([ovs-dpctl normalize-actions "$flow" "$actual"], [0], [expout])
done

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - VLAN depth limit])
OVS_VSWITCHD_START([dnl
   add-port br0 p1 -- set Interface p1 type=dummy ofport_request=1 -- \
   add-port br0 p2 -- set Interface p2 type=dummy ofport_request=2 -- \
   add-port br0 p3 -- set Interface p3 type=dummy ofport_request=3
])

AT_DATA([flows.txt], [dnl
table=0 in_port=1,eth_type=0x8100,vlan_tci=0x0010/0x01ff actions=output:2
table=0 in_port=1,eth_type=0xabcd,vlan_tci=0x0010/0x01ff actions=output:3
])
AT_CHECK([ovs-ofctl -O OpenFlow13 add-flows br0 flows.txt])
flow="in_port(1),eth(src=00:11:22:33:44:55,dst=00:22:44:66:88:00),eth_type(0x8100),vlan(vid=16,pcp=0), \
      encap(eth_type(0x8100),vlan(vid=17,pcp=0),encap(eth_type(0xabcd)))"

AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow"], [0], [stdout])
AT_CHECK([tail -1 stdout], [0],
  [Datapath actions: 2
])

AT_CHECK([ovs-vsctl set Open_vswitch `ovs-vsctl show | head -n1` other_config:vlan-limit=0])
AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow"], [0], [stdout])
AT_CHECK([tail -1 stdout], [0],
  [Datapath actions: 3
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - Multi-VLAN actions])
OVS_VSWITCHD_START([dnl
   add-port br0 p1 -- set Interface p1 type=dummy ofport_request=1 -- \
   add-port br0 p2 -- set Interface p2 type=dummy ofport_request=2
])
AT_CHECK([ovs-vsctl set Open_vswitch `ovs-vsctl show | head -n1` other_config:vlan-limit=0])

AT_DATA([flows.txt], [dnl
table=0 in_port=1,vlan_tci=0x1100/0x1fff actions=pop_vlan,output:2
table=0 in_port=1,vlan_tci=0x1101/0x1fff actions=push_vlan:0x8100,set_field:0x1201/0x1fff->vlan_tci,output:2
table=0 in_port=1,vlan_tci=0x1102/0x1fff actions=push_vlan:0x88a8,set_field:0x1202/0x1fff->vlan_tci,output:2
table=0 in_port=1,vlan_tci=0x1103/0x1fff actions=set_field:0x1203/0x1fff->vlan_tci,output:2
table=0 in_port=1,vlan_tci=0x1104/0x1fff actions=pop_vlan,goto_table:1
table=1 vlan_tci=0 actions=output:2
table=1 vlan_tci=0x1300/0x1fff actions=pop_vlan,output:2
table=1 vlan_tci=0x1301/0x1fff actions=push_vlan:0x88a8,set_field:0x1401/0x1fff->vlan_tci,output:2
table=1 vlan_tci=0x1302/0x1fff actions=set_field:0x1402/0x1fff->vlan_tci,output:2
])

AT_CHECK([ovs-ofctl -O OpenFlow13 add-flows br0 flows.txt])

check_act() {
    psd_hdr="in_port(1),eth(src=00:11:22:33:44:55,dst=00:22:44:66:88:00),"
    AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$psd_hdr$1"], [0], [stdout])
    AT_CHECK_UNQUOTED([tail -1 stdout], [0], [Datapath actions: $2
])
}

check_act "eth_type(0x8100),vlan(vid=0x0100,pcp=0),encap(eth_type(0xabcd))" \
          "pop_vlan,2"

check_act "eth_type(0x8100),vlan(vid=0x0101,pcp=0),encap(eth_type(0xabcd))" \
          "push_vlan(vid=513,pcp=0),2"

check_act "eth_type(0x8100),vlan(vid=0x0102,pcp=0),encap(eth_type(0xabcd))" \
          "push_vlan(tpid=0x88a8,vid=514,pcp=0),2"

check_act "eth_type(0x8100),vlan(vid=0x0103,pcp=0),encap(eth_type(0xabcd))" \
          "pop_vlan,push_vlan(vid=515,pcp=0),2"

check_act "eth_type(0x8100),vlan(vid=0x0104,pcp=0),encap(eth_type(0xabcd))" \
          "pop_vlan,2"

check_act "eth_type(0x88a8),vlan(vid=0x0104,pcp=0),encap(eth_type(0x8100),\
vlan(vid=0x0300,pcp=0),encap(eth_type(0xabcd)))" "pop_vlan,pop_vlan,2"

check_act "eth_type(0x88a8),vlan(vid=0x0104,pcp=0),encap(eth_type(0x8100),\
vlan(vid=0x0301,pcp=0),encap(eth_type(0xabcd)))" \
          "pop_vlan,push_vlan(tpid=0x88a8,vid=1025,pcp=0),2"

check_act "eth_type(0x88a8),vlan(vid=0x0104,pcp=0),encap(eth_type(0x8100),\
vlan(vid=0x0302,pcp=0),encap(eth_type(0xabcd)))" \
          "pop_vlan,pop_vlan,push_vlan(vid=1026,pcp=0),2"

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - MPLS handling])
OVS_VSWITCHD_START([dnl
   add-port br0 p1 -- set Interface p1 type=dummy
])
on_exit 'kill `cat ovs-ofctl.pid`'

AT_CAPTURE_FILE([ofctl_monitor.log])
AT_DATA([flows.txt], [dnl
dl_src=40:44:44:44:00:00 actions=push_mpls:0x8847,controller
dl_src=40:44:44:44:00:01,mpls actions=push_mpls:0x8847,controller
dl_src=40:44:44:44:00:02,mpls actions=push_mpls:0x8848,controller
])
AT_CHECK([ovs-ofctl --protocols=OpenFlow12 add-flows br0 flows.txt])

dnl In this test, we push an MPLS tag to an ethernet packet.
AT_CHECK([ovs-ofctl --protocols=OpenFlow12 monitor br0 65534 -m -P standard --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3; do
    ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=40:44:44:44:00:00,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)'
done
OVS_WAIT_UNTIL([test `grep OFPT_PACKET_IN ofctl_monitor.log | wc -l` -ge 3])
OVS_APP_EXIT_AND_WAIT(ovs-ofctl)

AT_CHECK([ofctl_strip < ofctl_monitor.log], [0], [dnl
OFPT_PACKET_IN (OF1.2): total_len=122 in_port=1 (via action) data_len=122 (unbuffered)
mpls,vlan_tci=0x0000,dl_src=40:44:44:44:00:00,dl_dst=50:54:00:00:00:07,mpls_label=0,mpls_tc=0,mpls_ttl=64,mpls_bos=1
00000000  50 54 00 00 00 07 40 44-44 44 00 00 88 47 00 00
00000010  01 40 45 00 00 68 00 00-00 00 40 06 f9 3c c0 a8
00000020  00 01 c0 a8 00 02 00 00-00 00 00 00 00 00 00 00
00000030  00 00 50 00 00 00 4a 4d-00 00 00 01 02 03 04 05
00000040  06 07 08 09 0a 0b 0c 0d-0e 0f 10 11 12 13 14 15
00000050  16 17 18 19 1a 1b 1c 1d-1e 1f 20 21 22 23 24 25
00000060  26 27 28 29 2a 2b 2c 2d-2e 2f 30 31 32 33 34 35
00000070  36 37 38 39 3a 3b 3c 3d-3e 3f
OFPT_PACKET_IN (OF1.2): total_len=122 in_port=1 (via action) data_len=122 (unbuffered)
mpls,vlan_tci=0x0000,dl_src=40:44:44:44:00:00,dl_dst=50:54:00:00:00:07,mpls_label=0,mpls_tc=0,mpls_ttl=64,mpls_bos=1
00000000  50 54 00 00 00 07 40 44-44 44 00 00 88 47 00 00
00000010  01 40 45 00 00 68 00 00-00 00 40 06 f9 3c c0 a8
00000020  00 01 c0 a8 00 02 00 00-00 00 00 00 00 00 00 00
00000030  00 00 50 00 00 00 4a 4d-00 00 00 01 02 03 04 05
00000040  06 07 08 09 0a 0b 0c 0d-0e 0f 10 11 12 13 14 15
00000050  16 17 18 19 1a 1b 1c 1d-1e 1f 20 21 22 23 24 25
00000060  26 27 28 29 2a 2b 2c 2d-2e 2f 30 31 32 33 34 35
00000070  36 37 38 39 3a 3b 3c 3d-3e 3f
OFPT_PACKET_IN (OF1.2): total_len=122 in_port=1 (via action) data_len=122 (unbuffered)
mpls,vlan_tci=0x0000,dl_src=40:44:44:44:00:00,dl_dst=50:54:00:00:00:07,mpls_label=0,mpls_tc=0,mpls_ttl=64,mpls_bos=1
00000000  50 54 00 00 00 07 40 44-44 44 00 00 88 47 00 00
00000010  01 40 45 00 00 68 00 00-00 00 40 06 f9 3c c0 a8
00000020  00 01 c0 a8 00 02 00 00-00 00 00 00 00 00 00 00
00000030  00 00 50 00 00 00 4a 4d-00 00 00 01 02 03 04 05
00000040  06 07 08 09 0a 0b 0c 0d-0e 0f 10 11 12 13 14 15
00000050  16 17 18 19 1a 1b 1c 1d-1e 1f 20 21 22 23 24 25
00000060  26 27 28 29 2a 2b 2c 2d-2e 2f 30 31 32 33 34 35
00000070  36 37 38 39 3a 3b 3c 3d-3e 3f
])

dnl In this test, we push an MPLS tag to an MPLS packet. The LSE should be
dnl copied exactly, except for the BOS bit.
AT_CHECK([ovs-ofctl --protocols=OpenFlow12 monitor br0 65534 -m -P standard --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3; do
    ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=40:44:44:44:00:01,dst=50:54:00:00:00:07),eth_type(0x8847),mpls(label=10,tc=0,ttl=64,bos=1)'
done
OVS_WAIT_UNTIL([test `grep OFPT_PACKET_IN ofctl_monitor.log | wc -l` -ge 3])
OVS_APP_EXIT_AND_WAIT(ovs-ofctl)

AT_CHECK([ofctl_strip < ofctl_monitor.log], [0], [dnl
OFPT_PACKET_IN (OF1.2): total_len=22 in_port=1 (via action) data_len=22 (unbuffered)
mpls,vlan_tci=0x0000,dl_src=40:44:44:44:00:01,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=0,mpls_lse1=41280
00000000  50 54 00 00 00 07 40 44-44 44 00 01 88 47 00 00
00000010  a0 40 00 00 a1 40
dnl
OFPT_PACKET_IN (OF1.2): total_len=22 in_port=1 (via action) data_len=22 (unbuffered)
mpls,vlan_tci=0x0000,dl_src=40:44:44:44:00:01,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=0,mpls_lse1=41280
00000000  50 54 00 00 00 07 40 44-44 44 00 01 88 47 00 00
00000010  a0 40 00 00 a1 40
dnl
OFPT_PACKET_IN (OF1.2): total_len=22 in_port=1 (via action) data_len=22 (unbuffered)
mpls,vlan_tci=0x0000,dl_src=40:44:44:44:00:01,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=0,mpls_lse1=41280
00000000  50 54 00 00 00 07 40 44-44 44 00 01 88 47 00 00
00000010  a0 40 00 00 a1 40
])

dnl In this test, we push an MPLS tag to an MPLS packet. The LSE should be
dnl copied exactly, except for the BOS bit. The ethertype should be updated
dnl to the MPLS ethertype of the MPLS push action which differs to that
dnl of the input packet.
AT_CHECK([ovs-ofctl --protocols=OpenFlow12 monitor br0 65534 -m -P standard --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3; do
    ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=40:44:44:44:00:02,dst=50:54:00:00:00:07),eth_type(0x8847),mpls(label=10,tc=0,ttl=64,bos=1)'
done
OVS_WAIT_UNTIL([test `grep OFPT_PACKET_IN ofctl_monitor.log | wc -l` -ge 3])
OVS_APP_EXIT_AND_WAIT([ovs-ofctl])

AT_CHECK([ofctl_strip < ofctl_monitor.log], [0], [dnl
OFPT_PACKET_IN (OF1.2): total_len=22 in_port=1 (via action) data_len=22 (unbuffered)
mplsm,vlan_tci=0x0000,dl_src=40:44:44:44:00:02,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=0,mpls_lse1=41280
00000000  50 54 00 00 00 07 40 44-44 44 00 02 88 48 00 00
00000010  a0 40 00 00 a1 40
dnl
OFPT_PACKET_IN (OF1.2): total_len=22 in_port=1 (via action) data_len=22 (unbuffered)
mplsm,vlan_tci=0x0000,dl_src=40:44:44:44:00:02,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=0,mpls_lse1=41280
00000000  50 54 00 00 00 07 40 44-44 44 00 02 88 48 00 00
00000010  a0 40 00 00 a1 40
dnl
OFPT_PACKET_IN (OF1.2): total_len=22 in_port=1 (via action) data_len=22 (unbuffered)
mplsm,vlan_tci=0x0000,dl_src=40:44:44:44:00:02,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=0,mpls_lse1=41280
00000000  50 54 00 00 00 07 40 44-44 44 00 02 88 48 00 00
00000010  a0 40 00 00 a1 40
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - VLAN+MPLS handling])
OVS_VSWITCHD_START([dnl
   add-port br0 p1 -- set Interface p1 type=dummy
])
on_exit 'kill `cat ovs-ofctl.pid`'

AT_CAPTURE_FILE([ofctl_monitor.log])
AT_DATA([flows.txt], [dnl
cookie=0xa dl_src=40:44:44:44:54:50 actions=push_mpls:0x8847,load:10->OXM_OF_MPLS_LABEL[[]],push_vlan:0x8100,set_vlan_vid:99,set_vlan_pcp:1,controller
cookie=0xa dl_src=40:44:44:44:54:51 actions=push_mpls:0x8847,load:10->OXM_OF_MPLS_LABEL[[]],push_vlan:0x8100,set_vlan_vid:99,set_vlan_pcp:1,controller
cookie=0xa dl_src=40:44:44:44:54:52 actions=push_mpls:0x8847,load:10->OXM_OF_MPLS_LABEL[[]],push_vlan:0x8100,load:99->OXM_OF_VLAN_VID[[]],set_vlan_pcp:1,controller
cookie=0xa dl_src=40:44:44:44:54:53 actions=push_mpls:0x8847,load:10->OXM_OF_MPLS_LABEL[[]],push_vlan:0x8100,load:99->OXM_OF_VLAN_VID[[]],set_vlan_pcp:1,controller
cookie=0xa dl_src=40:44:44:44:54:54 actions=push_vlan:0x8100,set_vlan_vid:99,set_vlan_pcp:1,push_mpls:0x8847,load:10->OXM_OF_MPLS_LABEL[[]],controller
cookie=0xa dl_src=40:44:44:44:54:55 actions=push_vlan:0x8100,set_vlan_vid:99,set_vlan_pcp:1,push_mpls:0x8847,load:10->OXM_OF_MPLS_LABEL[[]],controller
cookie=0xa dl_src=40:44:44:44:54:56 actions=push_vlan:0x8100,load:99->OXM_OF_VLAN_VID[[]],set_vlan_pcp:1,push_mpls:0x8847,load:10->OXM_OF_MPLS_LABEL[[]],controller
cookie=0xa dl_src=40:44:44:44:54:57 actions=push_vlan:0x8100,load:99->OXM_OF_VLAN_VID[[]],set_vlan_pcp:1,push_mpls:0x8847,load:10->OXM_OF_MPLS_LABEL[[]],controller
cookie=0xa dl_src=40:44:44:44:54:58,vlan_tci=0x1000/0x1000 actions=load:99->OXM_OF_VLAN_VID[[]],set_vlan_pcp:1,push_mpls:0x8847,load:10->OXM_OF_MPLS_LABEL[[]],controller
cookie=0xa dl_src=40:44:44:44:54:59,vlan_tci=0x1000/0x1000 actions=push_mpls:0x8847,load:10->OXM_OF_MPLS_LABEL[[]],set_vlan_pcp:1,load:99->OXM_OF_VLAN_VID[[]],controller
])
AT_CHECK([ovs-ofctl --protocols=OpenFlow12 add-flows br0 flows.txt])

dnl Modified MPLS controller action.
dnl In this test, we push the MPLS tag before pushing a VLAN tag, so we see
dnl both of these in the final flow
AT_CHECK([ovs-ofctl --protocols=OpenFlow12 monitor br0 65534 -m -P standard --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3; do
    ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=40:44:44:44:54:50,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)'
done
OVS_WAIT_UNTIL([test `grep OFPT_PACKET_IN ofctl_monitor.log | wc -l` -ge 3])
OVS_APP_EXIT_AND_WAIT(ovs-ofctl)

AT_CHECK([ofctl_strip < ofctl_monitor.log], [0], [dnl
OFPT_PACKET_IN (OF1.2): total_len=126 in_port=1 (via action) data_len=126 (unbuffered)
mpls,dl_vlan=99,dl_vlan_pcp=1,vlan_tci1=0x0000,dl_src=40:44:44:44:54:50,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1
00000000  50 54 00 00 00 07 40 44-44 44 54 50 81 00 20 63
00000010  88 47 00 00 a1 40 45 00-00 68 00 00 00 00 40 06
00000020  f9 3c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00
00000030  00 00 00 00 00 00 50 00-00 00 4a 4d 00 00 00 01
00000040  02 03 04 05 06 07 08 09-0a 0b 0c 0d 0e 0f 10 11
00000050  12 13 14 15 16 17 18 19-1a 1b 1c 1d 1e 1f 20 21
00000060  22 23 24 25 26 27 28 29-2a 2b 2c 2d 2e 2f 30 31
00000070  32 33 34 35 36 37 38 39-3a 3b 3c 3d 3e 3f
OFPT_PACKET_IN (OF1.2): total_len=126 in_port=1 (via action) data_len=126 (unbuffered)
mpls,dl_vlan=99,dl_vlan_pcp=1,vlan_tci1=0x0000,dl_src=40:44:44:44:54:50,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1
00000000  50 54 00 00 00 07 40 44-44 44 54 50 81 00 20 63
00000010  88 47 00 00 a1 40 45 00-00 68 00 00 00 00 40 06
00000020  f9 3c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00
00000030  00 00 00 00 00 00 50 00-00 00 4a 4d 00 00 00 01
00000040  02 03 04 05 06 07 08 09-0a 0b 0c 0d 0e 0f 10 11
00000050  12 13 14 15 16 17 18 19-1a 1b 1c 1d 1e 1f 20 21
00000060  22 23 24 25 26 27 28 29-2a 2b 2c 2d 2e 2f 30 31
00000070  32 33 34 35 36 37 38 39-3a 3b 3c 3d 3e 3f
OFPT_PACKET_IN (OF1.2): total_len=126 in_port=1 (via action) data_len=126 (unbuffered)
mpls,dl_vlan=99,dl_vlan_pcp=1,vlan_tci1=0x0000,dl_src=40:44:44:44:54:50,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1
00000000  50 54 00 00 00 07 40 44-44 44 54 50 81 00 20 63
00000010  88 47 00 00 a1 40 45 00-00 68 00 00 00 00 40 06
00000020  f9 3c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00
00000030  00 00 00 00 00 00 50 00-00 00 4a 4d 00 00 00 01
00000040  02 03 04 05 06 07 08 09-0a 0b 0c 0d 0e 0f 10 11
00000050  12 13 14 15 16 17 18 19-1a 1b 1c 1d 1e 1f 20 21
00000060  22 23 24 25 26 27 28 29-2a 2b 2c 2d 2e 2f 30 31
00000070  32 33 34 35 36 37 38 39-3a 3b 3c 3d 3e 3f
])

dnl Modified MPLS controller action.
dnl In this test, the input packet is vlan-tagged, which should be kept as
dnl inner vlan.
AT_CHECK([ovs-ofctl --protocols=OpenFlow12 monitor br0 65534 -m -P standard --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3; do
    ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=40:44:44:44:54:51,dst=50:54:00:00:00:07),eth_type(0x8100),vlan(vid=88,pcp=7),encap(eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no))'
done
OVS_WAIT_UNTIL([test `grep OFPT_PACKET_IN ofctl_monitor.log | wc -l` -ge 3])
OVS_APP_EXIT_AND_WAIT(ovs-ofctl)

AT_CHECK([ofctl_strip < ofctl_monitor.log], [0], [dnl
OFPT_PACKET_IN (OF1.2): total_len=130 in_port=1 (via action) data_len=130 (unbuffered)
mpls,dl_vlan=99,dl_vlan_pcp=1,dl_vlan1=88,dl_vlan_pcp1=7,dl_src=40:44:44:44:54:51,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1
00000000  50 54 00 00 00 07 40 44-44 44 54 51 81 00 20 63
00000010  81 00 e0 58 88 47 00 00-a1 40 45 00 00 68 00 00
00000020  00 00 40 06 f9 3c c0 a8-00 01 c0 a8 00 02 00 00
00000030  00 00 00 00 00 00 00 00-00 00 50 00 00 00 4a 4d
00000040  00 00 00 01 02 03 04 05-06 07 08 09 0a 0b 0c 0d
00000050  0e 0f 10 11 12 13 14 15-16 17 18 19 1a 1b 1c 1d
00000060  1e 1f 20 21 22 23 24 25-26 27 28 29 2a 2b 2c 2d
00000070  2e 2f 30 31 32 33 34 35-36 37 38 39 3a 3b 3c 3d
00000080  3e 3f
OFPT_PACKET_IN (OF1.2): total_len=130 in_port=1 (via action) data_len=130 (unbuffered)
mpls,dl_vlan=99,dl_vlan_pcp=1,dl_vlan1=88,dl_vlan_pcp1=7,dl_src=40:44:44:44:54:51,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1
00000000  50 54 00 00 00 07 40 44-44 44 54 51 81 00 20 63
00000010  81 00 e0 58 88 47 00 00-a1 40 45 00 00 68 00 00
00000020  00 00 40 06 f9 3c c0 a8-00 01 c0 a8 00 02 00 00
00000030  00 00 00 00 00 00 00 00-00 00 50 00 00 00 4a 4d
00000040  00 00 00 01 02 03 04 05-06 07 08 09 0a 0b 0c 0d
00000050  0e 0f 10 11 12 13 14 15-16 17 18 19 1a 1b 1c 1d
00000060  1e 1f 20 21 22 23 24 25-26 27 28 29 2a 2b 2c 2d
00000070  2e 2f 30 31 32 33 34 35-36 37 38 39 3a 3b 3c 3d
00000080  3e 3f
OFPT_PACKET_IN (OF1.2): total_len=130 in_port=1 (via action) data_len=130 (unbuffered)
mpls,dl_vlan=99,dl_vlan_pcp=1,dl_vlan1=88,dl_vlan_pcp1=7,dl_src=40:44:44:44:54:51,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1
00000000  50 54 00 00 00 07 40 44-44 44 54 51 81 00 20 63
00000010  81 00 e0 58 88 47 00 00-a1 40 45 00 00 68 00 00
00000020  00 00 40 06 f9 3c c0 a8-00 01 c0 a8 00 02 00 00
00000030  00 00 00 00 00 00 00 00-00 00 50 00 00 00 4a 4d
00000040  00 00 00 01 02 03 04 05-06 07 08 09 0a 0b 0c 0d
00000050  0e 0f 10 11 12 13 14 15-16 17 18 19 1a 1b 1c 1d
00000060  1e 1f 20 21 22 23 24 25-26 27 28 29 2a 2b 2c 2d
00000070  2e 2f 30 31 32 33 34 35-36 37 38 39 3a 3b 3c 3d
00000080  3e 3f
])

dnl Modified MPLS controller action.
dnl In this test, we push the MPLS tag before pushing a VLAN tag, so we see
dnl both of these in the final flow
AT_CHECK([ovs-ofctl --protocols=OpenFlow12 monitor br0 65534 -m -P standard --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3; do
    ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=40:44:44:44:54:52,dst=52: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)'
done
OVS_WAIT_UNTIL([test `grep OFPT_PACKET_IN ofctl_monitor.log | wc -l` -ge 3])
OVS_APP_EXIT_AND_WAIT(ovs-ofctl)

AT_CHECK([ofctl_strip < ofctl_monitor.log], [0], [dnl
OFPT_PACKET_IN (OF1.2): total_len=126 in_port=1 (via action) data_len=126 (unbuffered)
mpls,dl_vlan=99,dl_vlan_pcp=1,vlan_tci1=0x0000,dl_src=40:44:44:44:54:52,dl_dst=52:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1
00000000  52 54 00 00 00 07 40 44-44 44 54 52 81 00 20 63
00000010  88 47 00 00 a1 40 45 00-00 68 00 00 00 00 40 06
00000020  f9 3c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00
00000030  00 00 00 00 00 00 50 00-00 00 4a 4d 00 00 00 01
00000040  02 03 04 05 06 07 08 09-0a 0b 0c 0d 0e 0f 10 11
00000050  12 13 14 15 16 17 18 19-1a 1b 1c 1d 1e 1f 20 21
00000060  22 23 24 25 26 27 28 29-2a 2b 2c 2d 2e 2f 30 31
00000070  32 33 34 35 36 37 38 39-3a 3b 3c 3d 3e 3f
OFPT_PACKET_IN (OF1.2): total_len=126 in_port=1 (via action) data_len=126 (unbuffered)
mpls,dl_vlan=99,dl_vlan_pcp=1,vlan_tci1=0x0000,dl_src=40:44:44:44:54:52,dl_dst=52:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1
00000000  52 54 00 00 00 07 40 44-44 44 54 52 81 00 20 63
00000010  88 47 00 00 a1 40 45 00-00 68 00 00 00 00 40 06
00000020  f9 3c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00
00000030  00 00 00 00 00 00 50 00-00 00 4a 4d 00 00 00 01
00000040  02 03 04 05 06 07 08 09-0a 0b 0c 0d 0e 0f 10 11
00000050  12 13 14 15 16 17 18 19-1a 1b 1c 1d 1e 1f 20 21
00000060  22 23 24 25 26 27 28 29-2a 2b 2c 2d 2e 2f 30 31
00000070  32 33 34 35 36 37 38 39-3a 3b 3c 3d 3e 3f
OFPT_PACKET_IN (OF1.2): total_len=126 in_port=1 (via action) data_len=126 (unbuffered)
mpls,dl_vlan=99,dl_vlan_pcp=1,vlan_tci1=0x0000,dl_src=40:44:44:44:54:52,dl_dst=52:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1
00000000  52 54 00 00 00 07 40 44-44 44 54 52 81 00 20 63
00000010  88 47 00 00 a1 40 45 00-00 68 00 00 00 00 40 06
00000020  f9 3c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00
00000030  00 00 00 00 00 00 50 00-00 00 4a 4d 00 00 00 01
00000040  02 03 04 05 06 07 08 09-0a 0b 0c 0d 0e 0f 10 11
00000050  12 13 14 15 16 17 18 19-1a 1b 1c 1d 1e 1f 20 21
00000060  22 23 24 25 26 27 28 29-2a 2b 2c 2d 2e 2f 30 31
00000070  32 33 34 35 36 37 38 39-3a 3b 3c 3d 3e 3f
])

dnl Modified MPLS controller action.
dnl In this test, the input packet is vlan-tagged, which should be kept as
dnl inner vlan.
AT_CHECK([ovs-ofctl --protocols=OpenFlow12 monitor br0 65534 -m -P standard --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3; do
    ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=40:44:44:44:54:53,dst=50:54:00:00:00:07),eth_type(0x8100),vlan(vid=88,pcp=7),encap(eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no))'
done
OVS_WAIT_UNTIL([test `grep OFPT_PACKET_IN ofctl_monitor.log | wc -l` -ge 3])
OVS_APP_EXIT_AND_WAIT(ovs-ofctl)

AT_CHECK([ofctl_strip < ofctl_monitor.log], [0], [dnl
OFPT_PACKET_IN (OF1.2): total_len=130 in_port=1 (via action) data_len=130 (unbuffered)
mpls,dl_vlan=99,dl_vlan_pcp=1,dl_vlan1=88,dl_vlan_pcp1=7,dl_src=40:44:44:44:54:53,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1
00000000  50 54 00 00 00 07 40 44-44 44 54 53 81 00 20 63
00000010  81 00 e0 58 88 47 00 00-a1 40 45 00 00 68 00 00
00000020  00 00 40 06 f9 3c c0 a8-00 01 c0 a8 00 02 00 00
00000030  00 00 00 00 00 00 00 00-00 00 50 00 00 00 4a 4d
00000040  00 00 00 01 02 03 04 05-06 07 08 09 0a 0b 0c 0d
00000050  0e 0f 10 11 12 13 14 15-16 17 18 19 1a 1b 1c 1d
00000060  1e 1f 20 21 22 23 24 25-26 27 28 29 2a 2b 2c 2d
00000070  2e 2f 30 31 32 33 34 35-36 37 38 39 3a 3b 3c 3d
00000080  3e 3f
OFPT_PACKET_IN (OF1.2): total_len=130 in_port=1 (via action) data_len=130 (unbuffered)
mpls,dl_vlan=99,dl_vlan_pcp=1,dl_vlan1=88,dl_vlan_pcp1=7,dl_src=40:44:44:44:54:53,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1
00000000  50 54 00 00 00 07 40 44-44 44 54 53 81 00 20 63
00000010  81 00 e0 58 88 47 00 00-a1 40 45 00 00 68 00 00
00000020  00 00 40 06 f9 3c c0 a8-00 01 c0 a8 00 02 00 00
00000030  00 00 00 00 00 00 00 00-00 00 50 00 00 00 4a 4d
00000040  00 00 00 01 02 03 04 05-06 07 08 09 0a 0b 0c 0d
00000050  0e 0f 10 11 12 13 14 15-16 17 18 19 1a 1b 1c 1d
00000060  1e 1f 20 21 22 23 24 25-26 27 28 29 2a 2b 2c 2d
00000070  2e 2f 30 31 32 33 34 35-36 37 38 39 3a 3b 3c 3d
00000080  3e 3f
OFPT_PACKET_IN (OF1.2): total_len=130 in_port=1 (via action) data_len=130 (unbuffered)
mpls,dl_vlan=99,dl_vlan_pcp=1,dl_vlan1=88,dl_vlan_pcp1=7,dl_src=40:44:44:44:54:53,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1
00000000  50 54 00 00 00 07 40 44-44 44 54 53 81 00 20 63
00000010  81 00 e0 58 88 47 00 00-a1 40 45 00 00 68 00 00
00000020  00 00 40 06 f9 3c c0 a8-00 01 c0 a8 00 02 00 00
00000030  00 00 00 00 00 00 00 00-00 00 50 00 00 00 4a 4d
00000040  00 00 00 01 02 03 04 05-06 07 08 09 0a 0b 0c 0d
00000050  0e 0f 10 11 12 13 14 15-16 17 18 19 1a 1b 1c 1d
00000060  1e 1f 20 21 22 23 24 25-26 27 28 29 2a 2b 2c 2d
00000070  2e 2f 30 31 32 33 34 35-36 37 38 39 3a 3b 3c 3d
00000080  3e 3f
])

dnl Modified MPLS controller action.
dnl In this test, we push the VLAN tag before pushing a MPLS tag, but these
dnl actions are reordered, so we see both of these in the final flow.
AT_CHECK([ovs-ofctl --protocols=OpenFlow12 monitor br0 65534 -m -P standard --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3; do
    ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=40:44:44:44:54:54,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)'
done
OVS_WAIT_UNTIL([test `grep OFPT_PACKET_IN ofctl_monitor.log | wc -l` -ge 3])
OVS_APP_EXIT_AND_WAIT(ovs-ofctl)

AT_CHECK([ofctl_strip < ofctl_monitor.log], [0], [dnl
OFPT_PACKET_IN (OF1.2): total_len=126 in_port=1 (via action) data_len=126 (unbuffered)
mpls,dl_vlan=99,dl_vlan_pcp=1,vlan_tci1=0x0000,dl_src=40:44:44:44:54:54,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1
00000000  50 54 00 00 00 07 40 44-44 44 54 54 81 00 20 63
00000010  88 47 00 00 a1 40 45 00-00 68 00 00 00 00 40 06
00000020  f9 3c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00
00000030  00 00 00 00 00 00 50 00-00 00 4a 4d 00 00 00 01
00000040  02 03 04 05 06 07 08 09-0a 0b 0c 0d 0e 0f 10 11
00000050  12 13 14 15 16 17 18 19-1a 1b 1c 1d 1e 1f 20 21
00000060  22 23 24 25 26 27 28 29-2a 2b 2c 2d 2e 2f 30 31
00000070  32 33 34 35 36 37 38 39-3a 3b 3c 3d 3e 3f
OFPT_PACKET_IN (OF1.2): total_len=126 in_port=1 (via action) data_len=126 (unbuffered)
mpls,dl_vlan=99,dl_vlan_pcp=1,vlan_tci1=0x0000,dl_src=40:44:44:44:54:54,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1
00000000  50 54 00 00 00 07 40 44-44 44 54 54 81 00 20 63
00000010  88 47 00 00 a1 40 45 00-00 68 00 00 00 00 40 06
00000020  f9 3c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00
00000030  00 00 00 00 00 00 50 00-00 00 4a 4d 00 00 00 01
00000040  02 03 04 05 06 07 08 09-0a 0b 0c 0d 0e 0f 10 11
00000050  12 13 14 15 16 17 18 19-1a 1b 1c 1d 1e 1f 20 21
00000060  22 23 24 25 26 27 28 29-2a 2b 2c 2d 2e 2f 30 31
00000070  32 33 34 35 36 37 38 39-3a 3b 3c 3d 3e 3f
OFPT_PACKET_IN (OF1.2): total_len=126 in_port=1 (via action) data_len=126 (unbuffered)
mpls,dl_vlan=99,dl_vlan_pcp=1,vlan_tci1=0x0000,dl_src=40:44:44:44:54:54,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1
00000000  50 54 00 00 00 07 40 44-44 44 54 54 81 00 20 63
00000010  88 47 00 00 a1 40 45 00-00 68 00 00 00 00 40 06
00000020  f9 3c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00
00000030  00 00 00 00 00 00 50 00-00 00 4a 4d 00 00 00 01
00000040  02 03 04 05 06 07 08 09-0a 0b 0c 0d 0e 0f 10 11
00000050  12 13 14 15 16 17 18 19-1a 1b 1c 1d 1e 1f 20 21
00000060  22 23 24 25 26 27 28 29-2a 2b 2c 2d 2e 2f 30 31
00000070  32 33 34 35 36 37 38 39-3a 3b 3c 3d 3e 3f
])

dnl Modified MPLS controller action.
dnl In this test, the input packet is vlan-tagged, which should be kept as
dnl inner vlan.
AT_CHECK([ovs-ofctl --protocols=OpenFlow12 monitor br0 65534 -m -P standard --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3; do
    ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=40:44:44:44:54:55,dst=50:54:00:00:00:07),eth_type(0x8100),vlan(vid=88,pcp=7),encap(eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no))'
done
OVS_WAIT_UNTIL([test `grep OFPT_PACKET_IN ofctl_monitor.log | wc -l` -ge 3])
OVS_APP_EXIT_AND_WAIT([ovs-ofctl])

AT_CHECK([ofctl_strip < ofctl_monitor.log], [0], [dnl
OFPT_PACKET_IN (OF1.2): total_len=130 in_port=1 (via action) data_len=130 (unbuffered)
mpls,dl_vlan=99,dl_vlan_pcp=1,dl_vlan1=88,dl_vlan_pcp1=7,dl_src=40:44:44:44:54:55,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1
00000000  50 54 00 00 00 07 40 44-44 44 54 55 81 00 20 63
00000010  81 00 e0 58 88 47 00 00-a1 40 45 00 00 68 00 00
00000020  00 00 40 06 f9 3c c0 a8-00 01 c0 a8 00 02 00 00
00000030  00 00 00 00 00 00 00 00-00 00 50 00 00 00 4a 4d
00000040  00 00 00 01 02 03 04 05-06 07 08 09 0a 0b 0c 0d
00000050  0e 0f 10 11 12 13 14 15-16 17 18 19 1a 1b 1c 1d
00000060  1e 1f 20 21 22 23 24 25-26 27 28 29 2a 2b 2c 2d
00000070  2e 2f 30 31 32 33 34 35-36 37 38 39 3a 3b 3c 3d
00000080  3e 3f
OFPT_PACKET_IN (OF1.2): total_len=130 in_port=1 (via action) data_len=130 (unbuffered)
mpls,dl_vlan=99,dl_vlan_pcp=1,dl_vlan1=88,dl_vlan_pcp1=7,dl_src=40:44:44:44:54:55,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1
00000000  50 54 00 00 00 07 40 44-44 44 54 55 81 00 20 63
00000010  81 00 e0 58 88 47 00 00-a1 40 45 00 00 68 00 00
00000020  00 00 40 06 f9 3c c0 a8-00 01 c0 a8 00 02 00 00
00000030  00 00 00 00 00 00 00 00-00 00 50 00 00 00 4a 4d
00000040  00 00 00 01 02 03 04 05-06 07 08 09 0a 0b 0c 0d
00000050  0e 0f 10 11 12 13 14 15-16 17 18 19 1a 1b 1c 1d
00000060  1e 1f 20 21 22 23 24 25-26 27 28 29 2a 2b 2c 2d
00000070  2e 2f 30 31 32 33 34 35-36 37 38 39 3a 3b 3c 3d
00000080  3e 3f
OFPT_PACKET_IN (OF1.2): total_len=130 in_port=1 (via action) data_len=130 (unbuffered)
mpls,dl_vlan=99,dl_vlan_pcp=1,dl_vlan1=88,dl_vlan_pcp1=7,dl_src=40:44:44:44:54:55,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1
00000000  50 54 00 00 00 07 40 44-44 44 54 55 81 00 20 63
00000010  81 00 e0 58 88 47 00 00-a1 40 45 00 00 68 00 00
00000020  00 00 40 06 f9 3c c0 a8-00 01 c0 a8 00 02 00 00
00000030  00 00 00 00 00 00 00 00-00 00 50 00 00 00 4a 4d
00000040  00 00 00 01 02 03 04 05-06 07 08 09 0a 0b 0c 0d
00000050  0e 0f 10 11 12 13 14 15-16 17 18 19 1a 1b 1c 1d
00000060  1e 1f 20 21 22 23 24 25-26 27 28 29 2a 2b 2c 2d
00000070  2e 2f 30 31 32 33 34 35-36 37 38 39 3a 3b 3c 3d
00000080  3e 3f
])

dnl Modified MPLS controller action.
dnl In this test, we push the VLAN tag before pushing a MPLS tag, but these
dnl actions are reordered, so we see both of these in the final flow.
AT_CHECK([ovs-ofctl --protocols=OpenFlow12 monitor br0 65534 -m -P standard --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3; do
    ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=40:44:44:44:54:56,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)'
done
OVS_WAIT_UNTIL([test `grep OFPT_PACKET_IN ofctl_monitor.log | wc -l` -ge 3])
OVS_APP_EXIT_AND_WAIT(ovs-ofctl)

AT_CHECK([ofctl_strip < ofctl_monitor.log], [0], [dnl
OFPT_PACKET_IN (OF1.2): total_len=126 in_port=1 (via action) data_len=126 (unbuffered)
mpls,dl_vlan=99,dl_vlan_pcp=1,vlan_tci1=0x0000,dl_src=40:44:44:44:54:56,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1
00000000  50 54 00 00 00 07 40 44-44 44 54 56 81 00 20 63
00000010  88 47 00 00 a1 40 45 00-00 68 00 00 00 00 40 06
00000020  f9 3c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00
00000030  00 00 00 00 00 00 50 00-00 00 4a 4d 00 00 00 01
00000040  02 03 04 05 06 07 08 09-0a 0b 0c 0d 0e 0f 10 11
00000050  12 13 14 15 16 17 18 19-1a 1b 1c 1d 1e 1f 20 21
00000060  22 23 24 25 26 27 28 29-2a 2b 2c 2d 2e 2f 30 31
00000070  32 33 34 35 36 37 38 39-3a 3b 3c 3d 3e 3f
OFPT_PACKET_IN (OF1.2): total_len=126 in_port=1 (via action) data_len=126 (unbuffered)
mpls,dl_vlan=99,dl_vlan_pcp=1,vlan_tci1=0x0000,dl_src=40:44:44:44:54:56,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1
00000000  50 54 00 00 00 07 40 44-44 44 54 56 81 00 20 63
00000010  88 47 00 00 a1 40 45 00-00 68 00 00 00 00 40 06
00000020  f9 3c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00
00000030  00 00 00 00 00 00 50 00-00 00 4a 4d 00 00 00 01
00000040  02 03 04 05 06 07 08 09-0a 0b 0c 0d 0e 0f 10 11
00000050  12 13 14 15 16 17 18 19-1a 1b 1c 1d 1e 1f 20 21
00000060  22 23 24 25 26 27 28 29-2a 2b 2c 2d 2e 2f 30 31
00000070  32 33 34 35 36 37 38 39-3a 3b 3c 3d 3e 3f
OFPT_PACKET_IN (OF1.2): total_len=126 in_port=1 (via action) data_len=126 (unbuffered)
mpls,dl_vlan=99,dl_vlan_pcp=1,vlan_tci1=0x0000,dl_src=40:44:44:44:54:56,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1
00000000  50 54 00 00 00 07 40 44-44 44 54 56 81 00 20 63
00000010  88 47 00 00 a1 40 45 00-00 68 00 00 00 00 40 06
00000020  f9 3c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00
00000030  00 00 00 00 00 00 50 00-00 00 4a 4d 00 00 00 01
00000040  02 03 04 05 06 07 08 09-0a 0b 0c 0d 0e 0f 10 11
00000050  12 13 14 15 16 17 18 19-1a 1b 1c 1d 1e 1f 20 21
00000060  22 23 24 25 26 27 28 29-2a 2b 2c 2d 2e 2f 30 31
00000070  32 33 34 35 36 37 38 39-3a 3b 3c 3d 3e 3f
])

dnl Modified MPLS controller action.
dnl In this test, the input packet is vlan-tagged, which should be kept as
dnl inner vlan.
AT_CHECK([ovs-ofctl --protocols=OpenFlow12 monitor br0 -m 65534 -P standard --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3; do
    ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=40:44:44:44:54:57,dst=50:54:00:00:00:07),eth_type(0x8100),vlan(vid=88,pcp=7),encap(eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no))'
done
OVS_WAIT_UNTIL([test `grep OFPT_PACKET_IN ofctl_monitor.log | wc -l` -ge 3])
OVS_APP_EXIT_AND_WAIT(ovs-ofctl)

AT_CHECK([ofctl_strip < ofctl_monitor.log], [0], [dnl
OFPT_PACKET_IN (OF1.2): total_len=130 in_port=1 (via action) data_len=130 (unbuffered)
mpls,dl_vlan=99,dl_vlan_pcp=1,dl_vlan1=88,dl_vlan_pcp1=7,dl_src=40:44:44:44:54:57,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1
00000000  50 54 00 00 00 07 40 44-44 44 54 57 81 00 20 63
00000010  81 00 e0 58 88 47 00 00-a1 40 45 00 00 68 00 00
00000020  00 00 40 06 f9 3c c0 a8-00 01 c0 a8 00 02 00 00
00000030  00 00 00 00 00 00 00 00-00 00 50 00 00 00 4a 4d
00000040  00 00 00 01 02 03 04 05-06 07 08 09 0a 0b 0c 0d
00000050  0e 0f 10 11 12 13 14 15-16 17 18 19 1a 1b 1c 1d
00000060  1e 1f 20 21 22 23 24 25-26 27 28 29 2a 2b 2c 2d
00000070  2e 2f 30 31 32 33 34 35-36 37 38 39 3a 3b 3c 3d
00000080  3e 3f
OFPT_PACKET_IN (OF1.2): total_len=130 in_port=1 (via action) data_len=130 (unbuffered)
mpls,dl_vlan=99,dl_vlan_pcp=1,dl_vlan1=88,dl_vlan_pcp1=7,dl_src=40:44:44:44:54:57,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1
00000000  50 54 00 00 00 07 40 44-44 44 54 57 81 00 20 63
00000010  81 00 e0 58 88 47 00 00-a1 40 45 00 00 68 00 00
00000020  00 00 40 06 f9 3c c0 a8-00 01 c0 a8 00 02 00 00
00000030  00 00 00 00 00 00 00 00-00 00 50 00 00 00 4a 4d
00000040  00 00 00 01 02 03 04 05-06 07 08 09 0a 0b 0c 0d
00000050  0e 0f 10 11 12 13 14 15-16 17 18 19 1a 1b 1c 1d
00000060  1e 1f 20 21 22 23 24 25-26 27 28 29 2a 2b 2c 2d
00000070  2e 2f 30 31 32 33 34 35-36 37 38 39 3a 3b 3c 3d
00000080  3e 3f
OFPT_PACKET_IN (OF1.2): total_len=130 in_port=1 (via action) data_len=130 (unbuffered)
mpls,dl_vlan=99,dl_vlan_pcp=1,dl_vlan1=88,dl_vlan_pcp1=7,dl_src=40:44:44:44:54:57,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1
00000000  50 54 00 00 00 07 40 44-44 44 54 57 81 00 20 63
00000010  81 00 e0 58 88 47 00 00-a1 40 45 00 00 68 00 00
00000020  00 00 40 06 f9 3c c0 a8-00 01 c0 a8 00 02 00 00
00000030  00 00 00 00 00 00 00 00-00 00 50 00 00 00 4a 4d
00000040  00 00 00 01 02 03 04 05-06 07 08 09 0a 0b 0c 0d
00000050  0e 0f 10 11 12 13 14 15-16 17 18 19 1a 1b 1c 1d
00000060  1e 1f 20 21 22 23 24 25-26 27 28 29 2a 2b 2c 2d
00000070  2e 2f 30 31 32 33 34 35-36 37 38 39 3a 3b 3c 3d
00000080  3e 3f
])

dnl Modified MPLS controller action.
dnl In this test, the input packet is vlan-tagged, which should be kept as
dnl inner vlan.
AT_CHECK([ovs-ofctl --protocols=OpenFlow12 monitor br0 65534 -m -P standard --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3; do
    ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=40:44:44:44:54:58,dst=50:54:00:00:00:07),eth_type(0x8100),vlan(vid=88,pcp=7),encap(eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no))'
done
OVS_WAIT_UNTIL([test `grep OFPT_PACKET_IN ofctl_monitor.log | wc -l` -ge 3])
OVS_APP_EXIT_AND_WAIT(ovs-ofctl)

AT_CHECK([ofctl_strip < ofctl_monitor.log], [0], [dnl
OFPT_PACKET_IN (OF1.2): total_len=126 in_port=1 (via action) data_len=126 (unbuffered)
mpls,dl_vlan=99,dl_vlan_pcp=1,vlan_tci1=0x0000,dl_src=40:44:44:44:54:58,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1
00000000  50 54 00 00 00 07 40 44-44 44 54 58 81 00 20 63
00000010  88 47 00 00 a1 40 45 00-00 68 00 00 00 00 40 06
00000020  f9 3c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00
00000030  00 00 00 00 00 00 50 00-00 00 4a 4d 00 00 00 01
00000040  02 03 04 05 06 07 08 09-0a 0b 0c 0d 0e 0f 10 11
00000050  12 13 14 15 16 17 18 19-1a 1b 1c 1d 1e 1f 20 21
00000060  22 23 24 25 26 27 28 29-2a 2b 2c 2d 2e 2f 30 31
00000070  32 33 34 35 36 37 38 39-3a 3b 3c 3d 3e 3f
OFPT_PACKET_IN (OF1.2): total_len=126 in_port=1 (via action) data_len=126 (unbuffered)
mpls,dl_vlan=99,dl_vlan_pcp=1,vlan_tci1=0x0000,dl_src=40:44:44:44:54:58,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1
00000000  50 54 00 00 00 07 40 44-44 44 54 58 81 00 20 63
00000010  88 47 00 00 a1 40 45 00-00 68 00 00 00 00 40 06
00000020  f9 3c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00
00000030  00 00 00 00 00 00 50 00-00 00 4a 4d 00 00 00 01
00000040  02 03 04 05 06 07 08 09-0a 0b 0c 0d 0e 0f 10 11
00000050  12 13 14 15 16 17 18 19-1a 1b 1c 1d 1e 1f 20 21
00000060  22 23 24 25 26 27 28 29-2a 2b 2c 2d 2e 2f 30 31
00000070  32 33 34 35 36 37 38 39-3a 3b 3c 3d 3e 3f
OFPT_PACKET_IN (OF1.2): total_len=126 in_port=1 (via action) data_len=126 (unbuffered)
mpls,dl_vlan=99,dl_vlan_pcp=1,vlan_tci1=0x0000,dl_src=40:44:44:44:54:58,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1
00000000  50 54 00 00 00 07 40 44-44 44 54 58 81 00 20 63
00000010  88 47 00 00 a1 40 45 00-00 68 00 00 00 00 40 06
00000020  f9 3c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00
00000030  00 00 00 00 00 00 50 00-00 00 4a 4d 00 00 00 01
00000040  02 03 04 05 06 07 08 09-0a 0b 0c 0d 0e 0f 10 11
00000050  12 13 14 15 16 17 18 19-1a 1b 1c 1d 1e 1f 20 21
00000060  22 23 24 25 26 27 28 29-2a 2b 2c 2d 2e 2f 30 31
00000070  32 33 34 35 36 37 38 39-3a 3b 3c 3d 3e 3f
])

dnl Modified MPLS controller action.
dnl In this test, the input packet is vlan-tagged, which should be modified
dnl before we push MPLS and VLAN tags.
AT_CHECK([ovs-ofctl --protocols=OpenFlow12 monitor br0 65534 -m -P standard --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3; do
    ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=40:44:44:44:54:59,dst=50:54:00:00:00:07),eth_type(0x8100),vlan(vid=88,pcp=7),encap(eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no))'
done
OVS_WAIT_UNTIL([test `grep OFPT_PACKET_IN ofctl_monitor.log | wc -l` -ge 3])
OVS_APP_EXIT_AND_WAIT([ovs-ofctl])

AT_CHECK([ofctl_strip < ofctl_monitor.log], [0], [dnl
OFPT_PACKET_IN (OF1.2): total_len=126 in_port=1 (via action) data_len=126 (unbuffered)
mpls,dl_vlan=99,dl_vlan_pcp=1,vlan_tci1=0x0000,dl_src=40:44:44:44:54:59,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1
00000000  50 54 00 00 00 07 40 44-44 44 54 59 81 00 20 63
00000010  88 47 00 00 a1 40 45 00-00 68 00 00 00 00 40 06
00000020  f9 3c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00
00000030  00 00 00 00 00 00 50 00-00 00 4a 4d 00 00 00 01
00000040  02 03 04 05 06 07 08 09-0a 0b 0c 0d 0e 0f 10 11
00000050  12 13 14 15 16 17 18 19-1a 1b 1c 1d 1e 1f 20 21
00000060  22 23 24 25 26 27 28 29-2a 2b 2c 2d 2e 2f 30 31
00000070  32 33 34 35 36 37 38 39-3a 3b 3c 3d 3e 3f
OFPT_PACKET_IN (OF1.2): total_len=126 in_port=1 (via action) data_len=126 (unbuffered)
mpls,dl_vlan=99,dl_vlan_pcp=1,vlan_tci1=0x0000,dl_src=40:44:44:44:54:59,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1
00000000  50 54 00 00 00 07 40 44-44 44 54 59 81 00 20 63
00000010  88 47 00 00 a1 40 45 00-00 68 00 00 00 00 40 06
00000020  f9 3c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00
00000030  00 00 00 00 00 00 50 00-00 00 4a 4d 00 00 00 01
00000040  02 03 04 05 06 07 08 09-0a 0b 0c 0d 0e 0f 10 11
00000050  12 13 14 15 16 17 18 19-1a 1b 1c 1d 1e 1f 20 21
00000060  22 23 24 25 26 27 28 29-2a 2b 2c 2d 2e 2f 30 31
00000070  32 33 34 35 36 37 38 39-3a 3b 3c 3d 3e 3f
OFPT_PACKET_IN (OF1.2): total_len=126 in_port=1 (via action) data_len=126 (unbuffered)
mpls,dl_vlan=99,dl_vlan_pcp=1,vlan_tci1=0x0000,dl_src=40:44:44:44:54:59,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1
00000000  50 54 00 00 00 07 40 44-44 44 54 59 81 00 20 63
00000010  88 47 00 00 a1 40 45 00-00 68 00 00 00 00 40 06
00000020  f9 3c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00
00000030  00 00 00 00 00 00 50 00-00 00 4a 4d 00 00 00 01
00000040  02 03 04 05 06 07 08 09-0a 0b 0c 0d 0e 0f 10 11
00000050  12 13 14 15 16 17 18 19-1a 1b 1c 1d 1e 1f 20 21
00000060  22 23 24 25 26 27 28 29-2a 2b 2c 2d 2e 2f 30 31
00000070  32 33 34 35 36 37 38 39-3a 3b 3c 3d 3e 3f
])

AT_CHECK([ovs-appctl revalidator/purge], [0])
AT_CHECK([ovs-ofctl --protocols=OpenFlow12 dump-flows br0 | ofctl_strip | sort], [0], [dnl
 cookie=0xa, n_packets=3, n_bytes=354, dl_src=40:44:44:44:54:50 actions=push_mpls:0x8847,load:0xa->OXM_OF_MPLS_LABEL[[]],push_vlan:0x8100,set_field:4195->vlan_vid,set_field:1->vlan_pcp,CONTROLLER:65535
 cookie=0xa, n_packets=3, n_bytes=354, dl_src=40:44:44:44:54:52 actions=push_mpls:0x8847,load:0xa->OXM_OF_MPLS_LABEL[[]],push_vlan:0x8100,load:0x63->OXM_OF_VLAN_VID[[]],set_field:1->vlan_pcp,CONTROLLER:65535
 cookie=0xa, n_packets=3, n_bytes=354, dl_src=40:44:44:44:54:54 actions=push_vlan:0x8100,set_field:4195->vlan_vid,set_field:1->vlan_pcp,push_mpls:0x8847,load:0xa->OXM_OF_MPLS_LABEL[[]],CONTROLLER:65535
 cookie=0xa, n_packets=3, n_bytes=354, dl_src=40:44:44:44:54:56 actions=push_vlan:0x8100,load:0x63->OXM_OF_VLAN_VID[[]],set_field:1->vlan_pcp,push_mpls:0x8847,load:0xa->OXM_OF_MPLS_LABEL[[]],CONTROLLER:65535
 cookie=0xa, n_packets=3, n_bytes=366, dl_src=40:44:44:44:54:51 actions=push_mpls:0x8847,load:0xa->OXM_OF_MPLS_LABEL[[]],push_vlan:0x8100,set_field:4195->vlan_vid,set_field:1->vlan_pcp,CONTROLLER:65535
 cookie=0xa, n_packets=3, n_bytes=366, dl_src=40:44:44:44:54:53 actions=push_mpls:0x8847,load:0xa->OXM_OF_MPLS_LABEL[[]],push_vlan:0x8100,load:0x63->OXM_OF_VLAN_VID[[]],set_field:1->vlan_pcp,CONTROLLER:65535
 cookie=0xa, n_packets=3, n_bytes=366, dl_src=40:44:44:44:54:55 actions=push_vlan:0x8100,set_field:4195->vlan_vid,set_field:1->vlan_pcp,push_mpls:0x8847,load:0xa->OXM_OF_MPLS_LABEL[[]],CONTROLLER:65535
 cookie=0xa, n_packets=3, n_bytes=366, dl_src=40:44:44:44:54:57 actions=push_vlan:0x8100,load:0x63->OXM_OF_VLAN_VID[[]],set_field:1->vlan_pcp,push_mpls:0x8847,load:0xa->OXM_OF_MPLS_LABEL[[]],CONTROLLER:65535
 cookie=0xa, n_packets=3, n_bytes=366, vlan_tci=0x1000/0x1000,dl_src=40:44:44:44:54:58 actions=load:0x63->OXM_OF_VLAN_VID[[]],set_field:1->vlan_pcp,push_mpls:0x8847,load:0xa->OXM_OF_MPLS_LABEL[[]],CONTROLLER:65535
 cookie=0xa, n_packets=3, n_bytes=366, vlan_tci=0x1000/0x1000,dl_src=40:44:44:44:54:59 actions=push_mpls:0x8847,load:0xa->OXM_OF_MPLS_LABEL[[]],set_field:1->vlan_pcp,load:0x63->OXM_OF_VLAN_VID[[]],CONTROLLER:65535
OFPST_FLOW reply (OF1.2):
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - fragment handling - trace])
OVS_VSWITCHD_START
add_of_ports br0 1 2 3 4 5 6 90
AT_DATA([flows.txt], [dnl
priority=75 tcp nw_frag=no    tp_dst=80 actions=move:OXM_OF_TCP_DST[[]]->OXM_OF_TCP_SRC[[]],output:1
priority=75 tcp nw_frag=first tp_dst=80 actions=move:OXM_OF_TCP_DST[[]]->OXM_OF_TCP_SRC[[]],output:2
priority=50 tcp nw_frag=no              actions=move:OXM_OF_TCP_DST[[]]->OXM_OF_TCP_SRC[[]],output:4
priority=50 tcp nw_frag=first           actions=move:OXM_OF_TCP_DST[[]]->OXM_OF_TCP_SRC[[]],output:5
priority=50 tcp nw_frag=later           actions=output:6
])
AT_CHECK([ovs-ofctl replace-flows br0 flows.txt])

base_flow="in_port(90),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=128"
no_flow="$base_flow,frag=no),tcp(src=12345,dst=80)"
first_flow="$base_flow,frag=first),tcp(src=12345,dst=80)"
later_flow="$base_flow,frag=later)"

    # mode    no  first  later
for tuple in \
    'normal    1     5      6' \
    'drop      1  drop   drop' \
    'nx-match  1     2      6'
do
  set $tuple
  mode=$1
  no=$2
  first=$3
  later=$4

  AT_CHECK([ovs-ofctl set-frags br0 $mode])
  for type in no first later; do
    eval flow=\$${type}_flow exp_output=\$$type
    printf "\n%s\n" "----$mode $type-----"
    AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow"], [0], [stdout])
    : > expout
    if test $mode = drop && test $type != no; then
        echo ' 0. Packets are IP fragments and the fragment handling mode is "drop".' >> expout
        echo "Datapath actions: $exp_output" >> expout
    elif test $type = later; then
        echo "Datapath actions: $exp_output" >> expout
    else
        echo "Datapath actions: set(tcp(src=80)),$exp_output" >> expout
    fi
    AT_CHECK([grep 'IP fragments' stdout; tail -1 stdout], [0], [expout])
  done
done
OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - fragment handling - upcall])
OVS_VSWITCHD_START
add_of_ports br0 1 2 3 4 5 6 90
AT_DATA([flows.txt], [dnl
priority=75 tcp ip_frag=no    tp_dst=80 actions=set_field:81->tcp_dst,output:1
priority=75 tcp ip_frag=first tp_dst=80 actions=set_field:81->tcp_dst,output:2
priority=50 tcp ip_frag=no              actions=set_field:81->tcp_dst,output:4
priority=50 tcp ip_frag=first           actions=set_field:81->tcp_dst,output:5
priority=50 tcp ip_frag=later           actions=output:6
])
AT_CHECK([ovs-ofctl replace-flows br0 flows.txt])

base_flow="in_port(90),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=128"
no_flow="$base_flow,frag=no),tcp(src=12345,dst=80)"
first_flow="$base_flow,frag=first),tcp(src=12345,dst=80)"
later_flow="$base_flow,frag=later)"

AT_CHECK([ovs-appctl vlog/set dpif:dbg dpif_netdev:dbg])

mode=normal

AT_CHECK([ovs-ofctl set-frags br0 $mode])
for type in no first later; do
  eval flow=\$${type}_flow
  printf "\n%s\n" "----$mode $type-----"

  AT_CHECK([ovs-appctl netdev-dummy/receive p90 "$flow"], [0], [stdout])
done

AT_CHECK([ovs-appctl dpctl/dump-flows], [0], [dnl
flow-dump from the main thread:
recirc_id(0),in_port(90),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(proto=6,frag=no),tcp(dst=80), packets:0, bytes:0, used:never, actions:set(tcp(dst=81)),1
recirc_id(0),in_port(90),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(proto=6,frag=first),tcp(dst=80), packets:0, bytes:0, used:never, actions:set(tcp(dst=81)),5
recirc_id(0),in_port(90),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(proto=6,frag=later), packets:0, bytes:0, used:never, actions:6
])

mode=drop

AT_CHECK([ovs-appctl revalidator/purge], [0])
AT_CHECK([ovs-ofctl set-frags br0 $mode])
for type in no first later; do
  eval flow=\$${type}_flow
  printf "\n%s\n" "----$mode $type-----"

  AT_CHECK([ovs-appctl netdev-dummy/receive p90 "$flow"], [0], [stdout])
done

AT_CHECK([ovs-appctl dpctl/dump-flows], [0], [dnl
flow-dump from the main thread:
recirc_id(0),in_port(90),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(proto=6,frag=no),tcp(dst=80), packets:0, bytes:0, used:never, actions:set(tcp(dst=81)),1
recirc_id(0),in_port(90),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=first), packets:0, bytes:0, used:never, actions:drop
recirc_id(0),in_port(90),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=later), packets:0, bytes:0, used:never, actions:drop
])

mode=nx-match

AT_CHECK([ovs-appctl revalidator/purge], [0])
AT_CHECK([ovs-ofctl set-frags br0 $mode])
for type in no first later; do
  eval flow=\$${type}_flow
  printf "\n%s\n" "----$mode $type-----"

  AT_CHECK([ovs-appctl netdev-dummy/receive p90 "$flow"], [0], [stdout])
done

AT_CHECK([ovs-appctl dpctl/dump-flows], [0], [dnl
flow-dump from the main thread:
recirc_id(0),in_port(90),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(proto=6,frag=no),tcp(dst=80), packets:0, bytes:0, used:never, actions:set(tcp(dst=81)),1
recirc_id(0),in_port(90),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(proto=6,frag=first),tcp(dst=80), packets:0, bytes:0, used:never, actions:set(tcp(dst=81)),2
recirc_id(0),in_port(90),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(proto=6,frag=later), packets:0, bytes:0, used:never, actions:6
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - fragment handling - actions])
OVS_VSWITCHD_START
add_of_ports br0 1 2 3 4 5 6 90

AT_CHECK([ovs-ofctl add-flow br0 "tcp,ip_frag=later actions=move:OXM_OF_TCP_DST[[0..7]]->OXM_OF_TCP_SRC[[0..7]],output:1"], [1], [], [stderr])
AT_CHECK([tail -2 stderr | sed 's/^.*|WARN|//'], [0], [dnl
source field tcp_dst lacks correct prerequisites
ovs-ofctl: actions are invalid with specified match (OFPBAC_MATCH_INCONSISTENT)
])

AT_CHECK([ovs-ofctl -O OpenFlow15 add-flow br0 "tcp,ip_frag=later actions=move:OXM_OF_PKT_REG0[[0..7]]->OXM_OF_TCP_SRC[[0..7]],output:1"], [1], [], [stderr])
AT_CHECK([tail -2 stderr | sed 's/^.*|WARN|//'], [0], [dnl
destination field tcp_src lacks correct prerequisites
ovs-ofctl: actions are invalid with specified match (OFPBAC_MATCH_INCONSISTENT)
])

AT_CHECK([ovs-ofctl add-flow br0 "udp,ip_frag=later actions=set_field:8888->udp_src,output:1"], [1], [], [stderr])
AT_CHECK([tail -2 stderr | sed 's/^.*|WARN|//'], [0], [dnl
set_field udp_src lacks correct prerequisites
ovs-ofctl: actions are invalid with specified match (OFPBAC_MATCH_INCONSISTENT)
])

AT_CHECK([ovs-ofctl add-flow br0 "udp,ip_frag=later actions=load:8888->NXM_OF_UDP_DST[[]],output:1"], [1], [], [stderr])
AT_CHECK([tail -2 stderr | sed 's/^.*|WARN|//'], [0], [dnl
set_field udp_dst lacks correct prerequisites
ovs-ofctl: actions are invalid with specified match (OFPBAC_MATCH_INCONSISTENT)
])

AT_CHECK([ovs-ofctl add-flow br0 "sctp,ip_frag=later actions=set_field:8888->sctp_src,output:1"], [1], [], [stderr])
AT_CHECK([tail -2 stderr | sed 's/^.*|WARN|//'], [0], [dnl
set_field sctp_src lacks correct prerequisites
ovs-ofctl: actions are invalid with specified match (OFPBAC_MATCH_INCONSISTENT)
])

AT_CHECK([ovs-ofctl add-flow br0 "sctp,ip_frag=later actions=set_field:8888->sctp_dst,output:1"], [1], [], [stderr])
AT_CHECK([tail -2 stderr | sed 's/^.*|WARN|//'], [0], [dnl
set_field sctp_dst lacks correct prerequisites
ovs-ofctl: actions are invalid with specified match (OFPBAC_MATCH_INCONSISTENT)
])

AT_CHECK([ovs-ofctl add-flow br0 "tcp,ip_frag=later actions=learn(table=1,hard_timeout=60,eth_type=0x800,nw_proto=6,NXM_OF_IP_SRC[[]]=NXM_OF_IP_DST[[]],NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],output:NXM_NX_REG0[[0..15]]),output:1"], [1], [], [stderr])
AT_CHECK([tail -2 stderr | sed 's/^.*|WARN|//'], [0], [dnl
source field tcp_dst lacks correct prerequisites
ovs-ofctl: actions are invalid with specified match (OFPBAC_MATCH_INCONSISTENT)
])

AT_DATA([flows.txt], [dnl
priority=75 tcp actions=load:42->OXM_OF_TCP_SRC[[0..7]],output:1
])
AT_CHECK([ovs-ofctl -O OpenFlow12 replace-flows br0 flows.txt])

AT_CHECK([ovs-appctl vlog/set dpif:dbg dpif_netdev:dbg])

mode=normal

AT_CHECK([ovs-ofctl set-frags br0 $mode])
for frag in 4000 6000 6008 4010; do
  printf "\n%s\n" "----$mode $frag-----"

  AT_CHECK([ovs-appctl netdev-dummy/receive p90 "0021853763af 0026b98cb0f9 0800 4500 003c 2e24 $frag 40 06 465d ac11370d ac11370b 828b 0016 751e267b 00000000 a002 16d0 1736 0000 02 04 05 b4 04 02 08 0a 2d 25 08 5f 00 00 00 00 01 03 03 07"])
done

dnl The set_field action only modifies 8 bits of the tcp_src, so both the flow
dnl wildcard and the set_field action have a mask of 0xFF. Up to (including)
dnl OVS-2.5, the wildcards and set_field mask are shared internally.
AT_CHECK([ovs-appctl dpctl/dump-flows | sed 's/used:[[0-9]].[[0-9]]*s/used:0.001s/'], [0], [dnl
flow-dump from the main thread:
recirc_id(0),in_port(90),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(proto=6,frag=no),tcp(src=33419/0xff), packets:0, bytes:0, used:never, actions:set(tcp(src=42/0xff)),1
recirc_id(0),in_port(90),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(proto=6,frag=first),tcp(src=33419/0xff), packets:0, bytes:0, used:never, actions:set(tcp(src=42/0xff)),1
recirc_id(0),in_port(90),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(proto=6,frag=later), packets:1, bytes:74, used:0.001s, actions:1
])

AT_CHECK([ovs-appctl revalidator/purge], [0])
AT_CHECK([ovs-ofctl set-frags br0 $mode])
for frag in 4000 6000 6008 4010; do
  printf "\n%s\n" "----$mode $frag truncated transport header -----"

  AT_CHECK([ovs-appctl netdev-dummy/receive p90 "0021853763af 0026b98cb0f9 0800 4500 0018 2e24 $frag 40 06 465d ac11370d ac11370b 828b 0016"])
done

AT_CHECK([ovs-appctl dpctl/dump-flows | sed 's/used:[[0-9]].[[0-9]]*s/used:0.001s/'], [0], [dnl
flow-dump from the main thread:
recirc_id(0),in_port(90),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(proto=6,frag=no),tcp(src=0/0xff), packets:0, bytes:0, used:never, actions:set(tcp(src=42/0xff)),1
recirc_id(0),in_port(90),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(proto=6,frag=first),tcp(src=0/0xff), packets:0, bytes:0, used:never, actions:set(tcp(src=42/0xff)),1
recirc_id(0),in_port(90),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(proto=6,frag=later), packets:1, bytes:38, used:0.001s, actions:1
])

AT_CHECK([ovs-appctl revalidator/purge], [0])
AT_CHECK([ovs-ofctl set-frags br0 $mode])
for frag in 4000 6000 6001 4002; do
  printf "\n%s\n" "----$mode $frag missing transport header-----"

  AT_CHECK([ovs-appctl netdev-dummy/receive p90 "0021853763af 0026b98cb0f9 0800 4500 0014 2e24 $frag 40 06 465d ac11370d ac11370b"])
done

AT_CHECK([ovs-appctl dpctl/dump-flows | sed 's/used:[[0-9]].[[0-9]]*s/used:0.001s/'], [0], [dnl
flow-dump from the main thread:
recirc_id(0),in_port(90),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(proto=6,frag=no),tcp(src=0/0xff), packets:0, bytes:0, used:never, actions:set(tcp(src=42/0xff)),1
recirc_id(0),in_port(90),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(proto=6,frag=first),tcp(src=0/0xff), packets:0, bytes:0, used:never, actions:set(tcp(src=42/0xff)),1
recirc_id(0),in_port(90),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(proto=6,frag=later), packets:1, bytes:34, used:0.001s, actions:1
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - handling of malformed TCP packets])
OVS_VSWITCHD_START
add_of_ports br0 1 90

dnl drop packet has tcp port 0-f but allow other tcp packets
AT_DATA([flows.txt], [dnl
priority=75 tcp tp_dst=0/0xfff0     actions=drop
priority=50 tcp                     actions=output:1
])
AT_CHECK([ovs-ofctl replace-flows br0 flows.txt])

dnl good tcp pkt, tcp(sport=100,dpor=16)
pkt1="be95df40fb57fa163e5ee3570800450000280001000040063e940a0a0a0a141414140064001000000000000000005002200053330000"

dnl malformed tcp pkt(tcp_hdr < 20 byte), tcp(sport=100,dport=16,dataofs=1)
pkt2="be95df40fb57fa163e5ee3570800450000280001000040063e940a0a0a0a141414140064001000000000000000001002200093330000"

dnl malformed tcp pkt(tcp_hdr > pkt_len), tcp(sport=100,dport=16,dataofs=15)
pkt3="be95df40fb57fa163e5ee3570800450000280001000040063e940a0a0a0a14141414006400100000000000000000f002200093330000"

AT_CHECK([ovs-appctl vlog/set dpif:dbg dpif_netdev:dbg])

AT_CHECK([ovs-appctl netdev-dummy/receive p90 "$pkt1"], [0], [stdout])
dnl for good tcp pkt, ovs can extract the tp_dst=16
AT_CHECK([ovs-appctl dpctl/dump-flows filter=in_port\(90\),tcp], [0], [dnl
flow-dump from the main thread:
recirc_id(0),in_port(90),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(proto=6,frag=no),tcp(dst=16/0xfff0), packets:0, bytes:0, used:never, actions:1
])

AT_CHECK([ovs-appctl revalidator/purge], [0], [stdout])
AT_CHECK([ovs-appctl netdev-dummy/receive p90 "$pkt2"], [0], [stdout])
dnl for malformed tcp pkt(tcp_hdr < 20 byte), ovs uses default value tp_dst=0
AT_CHECK([ovs-appctl dpctl/dump-flows filter=in_port\(90\),tcp], [0], [dnl
flow-dump from the main thread:
recirc_id(0),in_port(90),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(proto=6,frag=no),tcp(dst=0/0xfff0), packets:0, bytes:0, used:never, actions:drop
])

AT_CHECK([ovs-appctl revalidator/purge], [0], [stdout])
AT_CHECK([ovs-appctl netdev-dummy/receive p90 "$pkt3"], [0], [stdout])
dnl for malformed tcp pkt(tcp_hdr > pkt_len), ovs uses default value tp_dst=0
AT_CHECK([ovs-appctl dpctl/dump-flows filter=in_port\(90\),tcp], [0], [dnl
flow-dump from the main thread:
recirc_id(0),in_port(90),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(proto=6,frag=no),tcp(dst=0/0xfff0), packets:0, bytes:0, used:never, actions:drop
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - exit])
OVS_VSWITCHD_START
add_of_ports br0 1 2 3 10 11 12 13 14
AT_DATA([flows.txt], [dnl
in_port=1 actions=output:10,exit,output:11
in_port=2 actions=output:12,resubmit:1,output:12
in_port=3 actions=output:13,resubmit:2,output:14
])
AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
AT_CHECK([ovs-appctl ofproto/trace ovs-dummy '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)'], [0], [stdout])
AT_CHECK([tail -1 stdout], [0],
  [Datapath actions: 10
])
AT_CHECK([ovs-appctl ofproto/trace ovs-dummy '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)'], [0], [stdout])
AT_CHECK([tail -1 stdout], [0],
  [Datapath actions: 12,10
])
AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(3),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)'], [0], [stdout])
AT_CHECK([tail -1 stdout], [0],
  [Datapath actions: 13,12,10
])
OVS_VSWITCHD_STOP
AT_CLEANUP


AT_SETUP([ofproto-dpif - mirroring, select_all])
AT_KEYWORDS([mirror mirrors mirroring])
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 ovs-dummy "$flow"], [0], [stdout])
AT_CHECK_UNQUOTED([tail -1 stdout], [0],
  [Datapath actions: 3,2
])

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 ovs-dummy "$flow"], [0], [stdout])
AT_CHECK_UNQUOTED([tail -1 stdout], [0],
  [Datapath actions: 3,1
])

OVS_VSWITCHD_STOP
AT_CLEANUP


AT_SETUP([ofproto-dpif - mirroring, select_src])
AT_KEYWORDS([mirror mirrors mirroring])
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 ovs-dummy "$flow"], [0], [stdout])
AT_CHECK_UNQUOTED([tail -1 stdout], [0],
  [Datapath actions: 3,2
])

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 ovs-dummy "$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])
AT_KEYWORDS([mirror mirrors mirroring])
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])
AT_KEYWORDS([mirror mirrors mirroring])
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 ovs-dummy "$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 ovs-dummy "$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])
AT_KEYWORDS([mirror mirrors mirroring])
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 ovs-dummy "$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 ovs-dummy "$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 ovs-dummy "$flow"], [0], [stdout])
AT_CHECK_UNQUOTED([tail -1 stdout], [0],
  [Datapath actions: 3,2
])

OVS_VSWITCHD_STOP
AT_CLEANUP


AT_SETUP([ofproto-dpif - mirroring, output_port])
AT_KEYWORDS([mirror mirrors mirroring])
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 ovs-dummy "$flow"], [0], [stdout])
AT_CHECK_UNQUOTED([tail -1 stdout], [0],
  [Datapath actions: 3,push_vlan(vid=17,pcp=0),2
])

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 ovs-dummy "$flow"], [0], [stdout])
AT_CHECK_UNQUOTED([tail -1 stdout], [0],
  [Datapath actions: 3,1
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - mirroring, output_vlan])
AT_KEYWORDS([mirror mirrors mirroring])
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 ovs-dummy "$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 ovs-dummy "$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

# This verifies that we don't get duplicate mirroring when mirror_packet()
# might be invoked recursively, as a check against regression.
AT_SETUP([ofproto-dpif - multiple VLAN output mirrors])
AT_KEYWORDS([mirror mirrors mirroring])
OVS_VSWITCHD_START
add_of_ports br0 1 2 3
ovs-vsctl \
        -- set Bridge br0 fail-mode=standalone mirrors=@m1,@m2 \
        -- --id=@m1 create Mirror name=m1 select_all=true output_vlan=500 \
        -- --id=@m2 create Mirror name=m2 select_all=true output_vlan=501 \
        -- set Port br0 tag=0 \
        -- set Port p1 tag=0 \
        -- set Port p2 tag=500 \
        -- set Port p3 tag=501

flow='in_port=1'
AT_CHECK([ovs-appctl ofproto/trace br0 "$flow"], [0], [stdout])
AT_CHECK([tail -1 stdout | sed 's/Datapath actions: //
s/,/\
/g' | sort], [0], [100
2
3
])

OVS_VSWITCHD_STOP
AT_CLEANUP

# This test verifies that mirror state is preserved across recirculation.
#
# Otherwise, post-recirculation the ingress and the output to port 4
# would cause the packet to be mirrored to port 3 a second time.
AT_SETUP([ofproto-dpif - mirroring with recirculation])
AT_KEYWORDS([mirror mirrors mirroring])
OVS_VSWITCHD_START
add_of_ports br0 1 2 3 4
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=2,debug_recirc,4
])
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 ovs-dummy "$flow" -generate], [0], [stdout])
AT_CHECK_UNQUOTED([tail -1 stdout], [0], [Datapath actions: 3,2,recirc(0x1)
])
AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow,recirc_id(1)" -generate], [0], [stdout])
AT_CHECK_UNQUOTED([tail -1 stdout], [0], [Datapath actions: 4
])

OVS_VSWITCHD_STOP
AT_CLEANUP

# Tests below verify the snaplen support for mirroring
AT_SETUP([ofproto-dpif - mirroring, select_all with snaplen])
AT_KEYWORDS([mirror mirrors mirroring])
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 snaplen=100

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 ovs-dummy "$flow"], [0], [stdout])
AT_CHECK_UNQUOTED([tail -1 stdout], [0],
  [Datapath actions: trunc(100),3,2
])

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 ovs-dummy "$flow"], [0], [stdout])
AT_CHECK_UNQUOTED([tail -1 stdout], [0],
  [Datapath actions: trunc(100),3,1
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - mirroring, select_all with snaplen and reset snaplen])
AT_KEYWORDS([mirror mirrors mirroring])
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 snaplen=100

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 ovs-dummy "$flow"], [0], [stdout])
AT_CHECK_UNQUOTED([tail -1 stdout], [0],
  [Datapath actions: trunc(100),3,2
])

ovs-vsctl set mirror mymirror snaplen=77

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 ovs-dummy "$flow"], [0], [stdout])
AT_CHECK_UNQUOTED([tail -1 stdout], [0],
  [Datapath actions: trunc(77),3,1
])

ovs-vsctl set mirror mymirror snaplen=65535

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 ovs-dummy "$flow"], [0], [stdout])
AT_CHECK_UNQUOTED([tail -1 stdout], [0],
  [Datapath actions: 3,1
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - mirroring, select_src with snaplen])
AT_KEYWORDS([mirror mirrors mirroring])
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 snaplen=100

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 ovs-dummy "$flow"], [0], [stdout])
AT_CHECK_UNQUOTED([tail -1 stdout], [0],
  [Datapath actions: trunc(100),3,2
])

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 ovs-dummy "$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 with snaplen])
AT_KEYWORDS([mirror mirrors mirroring])
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 snaplen=100

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,trunc(100),2
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - mirroring, select_dst with snaplen])
AT_KEYWORDS([mirror mirrors mirroring])
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 snaplen=100

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 ovs-dummy "$flow"], [0], [stdout])
AT_CHECK_UNQUOTED([tail -1 stdout], [0],
  [Datapath actions: 2,trunc(100),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 ovs-dummy "$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 with snaplen])
AT_KEYWORDS([mirror mirrors mirroring])
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 snaplen=100

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 ovs-dummy "$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 ovs-dummy "$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 ovs-dummy "$flow"], [0], [stdout])
AT_CHECK_UNQUOTED([tail -1 stdout], [0],
  [Datapath actions: trunc(100),3,2
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - mirroring, output_port with snaplen])
AT_KEYWORDS([mirror mirrors mirroring])
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 snaplen=100

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 ovs-dummy "$flow"], [0], [stdout])
AT_CHECK_UNQUOTED([tail -1 stdout], [0],
  [Datapath actions: trunc(100),3,push_vlan(vid=17,pcp=0),2
])

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 ovs-dummy "$flow"], [0], [stdout])
AT_CHECK_UNQUOTED([tail -1 stdout], [0],
  [Datapath actions: trunc(100),3,1
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - mirroring, output_vlan with snaplen])
AT_KEYWORDS([mirror mirrors mirroring])
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 snaplen=100

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 ovs-dummy "$flow"], [0], [stdout])
actual=`tail -1 stdout | sed 's/Datapath actions: //'`
dnl Expect: "trunc(100),100,trunc(100),2,trunc(100),1", with different order
AT_CHECK([echo "$actual" | sed -n 's/.*\(trunc([0-9]*),[0-9]*,trunc([0-9]*),[0-9]*,trunc([0-9]*),[0-9]*\)/\1/p'], [0])

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 ovs-dummy "$flow"], [0], [stdout])
actual=`tail -1 stdout | sed 's/Datapath actions: //'`
AT_CHECK([echo "$actual" | sed -n 's/.*\(trunc([0-9]*),[0-9]*,trunc([0-9]*),[0-9]*,trunc([0-9]*),[0-9]*\)/\1/p'], [0])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - multiple VLAN output mirrors with snaplen])
AT_KEYWORDS([mirror mirrors mirroring])
OVS_VSWITCHD_START
add_of_ports br0 1 2 3
ovs-vsctl \
        -- set Bridge br0 fail-mode=standalone mirrors=@m1,@m2 \
       -- --id=@m1 create Mirror name=m1 select_all=true output_vlan=500 snaplen=200 \
       -- --id=@m2 create Mirror name=m2 select_all=true output_vlan=501 snaplen=300 \
       -- set Port br0 tag=0 \
       -- set Port p1 tag=0 \
       -- set Port p2 tag=500 \
       -- set Port p3 tag=501

flow="in_port=1"
AT_CHECK([ovs-appctl ofproto/trace br0 "$flow"], [0], [stdout])
AT_CHECK([tail -1 stdout | egrep "trunc\(200\),2,trunc\(300\),3,100|trunc\(300\),3,trunc\(200\),2,100"], [0], [stdout])

OVS_VSWITCHD_STOP
AT_CLEANUP

# This test verifies that the table ID is preserved across recirculation
# when a resubmit action requires it (because the action is relative to
# the current table rather than specifying a table).
AT_SETUP([ofproto-dpif - resubmit with recirculation])
OVS_VSWITCHD_START
add_of_ports br0 1 2 3

AT_DATA([flows.txt], [dnl
table=0 in_port=1  actions=2,resubmit(,1)
table=1 in_port=1  actions=debug_recirc,resubmit:55
table=1 in_port=55 actions=3
])
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 ovs-dummy "$flow" -generate], [0], [stdout])
AT_CHECK_UNQUOTED([tail -1 stdout], [0], [Datapath actions: 2,recirc(0x1)
])
AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow,recirc_id(1)" -generate], [0], [stdout])
AT_CHECK_UNQUOTED([tail -1 stdout], [0], [Datapath actions: 3
])

OVS_VSWITCHD_STOP
AT_CLEANUP


# This test verifies that tunnel metadata is preserved across
# recirculation.  At the time of recirculation, fields such as "tun_id"
# may be set before the tunnel is "valid" (ie, has a destination
# address), but the field should still be available after recirculation.
AT_SETUP([ofproto-dpif - resubmit with tun_id])
OVS_VSWITCHD_START
add_of_ports br0 1 2 3

AT_DATA([flows.txt], [dnl
table=0 in_port=1  actions=2,load:6->NXM_NX_TUN_ID[[]],resubmit(,1)
table=1 in_port=1  actions=debug_recirc,resubmit:55
table=1 in_port=55 actions=3
])
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 ovs-dummy "$flow" -generate], [0], [stdout])
AT_CHECK([grep "Final flow:" stdout], [0], [Final flow: icmp,tun_id=0x6,in_port=1,vlan_tci=0x0000,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_tos=0,nw_ecn=0,nw_ttl=128,icmp_type=8,icmp_code=0
])

AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow,recirc_id(1)" -generate], [0], [stdout])
AT_CHECK([grep "Final flow:" stdout], [0], [Final flow: recirc_id=0x1,eth,icmp,tun_id=0x6,in_port=1,vlan_tci=0x0000,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_tos=0,nw_ecn=0,nw_ttl=128,icmp_type=8,icmp_code=0
])

OVS_VSWITCHD_STOP
AT_CLEANUP


# This test verifies that "resubmit", when it triggers recirculation
# indirectly through the flow that it recursively invokes, is not
# re-executed when execution continues later post-recirculation.
AT_SETUP([ofproto-dpif - recirculation after resubmit])
OVS_VSWITCHD_START
add_of_ports br0 1 2

AT_DATA([flows.txt], [dnl
table=0 in_port=1 actions=resubmit(,1),2
table=1 in_port=1 actions=debug_recirc
])
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 ovs-dummy "$flow" -generate], [0], [stdout])
AT_CHECK_UNQUOTED([tail -1 stdout], [0], [Datapath actions: recirc(0x1)
])
AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow,recirc_id(1)" -generate], [0], [stdout])
AT_CHECK_UNQUOTED([tail -1 stdout], [0], [Datapath actions: 2
])

OVS_VSWITCHD_STOP
AT_CLEANUP

# Checks for regression against a bug in which OVS dropped packets
# with in_port=CONTROLLER when they were recirculated (because
# CONTROLLER isn't a real port and could not be looked up).
AT_SETUP([ofproto-dpif - packet-out recirculation])
OVS_VSWITCHD_START
add_of_ports br0 1 2

AT_DATA([flows.txt], [dnl
table=0 ip actions=mod_dl_dst:83:83:83:83:83:83,ct(table=1)
table=1 ip actions=ct(commit),output:2
])
AT_CHECK([ovs-ofctl add-flows br0 flows.txt])

packet=ffffffffffff00102030405008004500001c00000000401100000a000002ffffffff0035111100080000
AT_CHECK([ovs-ofctl packet-out br0 "in_port=controller packet=$packet actions=table"])

# Dumps out the flow table, extracts the number of packets that have gone
# through the (single) flow in table 1, and returns success if it's exactly 1.
#
# If this remains 0, then the recirculation isn't working properly since the
# packet never goes through flow in table 1.
check_flows () {
    n=$(ovs-ofctl dump-flows br0 table=1 | sed -n 's/.*n_packets=\([[0-9]]\{1,\}\).*/\1/p')
    echo "n_packets=$n"
    test "$n" = 1
}
OVS_WAIT_UNTIL([check_flows], [ovs-ofctl dump-flows br0])

OVS_VSWITCHD_STOP
AT_CLEANUP

# Checks for regression against a bug in which OVS crashed
# with in_port=OFPP_NONE or in_port=OFPP_CONTROLLER and
# recirculation is involved.
AT_SETUP([ofproto-dpif - packet-out recirculation with OFPP_NONE and OFPP_CONTROLLER])
OVS_VSWITCHD_START
add_of_ports br0 1 2

AT_DATA([flows.txt], [dnl
table=0 ip actions=mod_dl_dst:83:83:83:83:83:83,ct(table=1)
table=1 ip actions=ct(commit),normal
])
AT_CHECK([ovs-ofctl add-flows br0 flows.txt])

packet=ffffffffffff00102030405008004500001c00000000401100000a000002ffffffff0035111100080000
AT_CHECK([ovs-ofctl packet-out br0 "in_port=none,packet=$packet actions=table"])
AT_CHECK([ovs-ofctl packet-out br0 "in_port=controller,packet=$packet actions=table"])

# Dumps out the flow table, extracts the number of packets that have gone
# through the (single) flow in table 1, and returns success if it's exactly 2.
check_flows () {
    n=$(ovs-ofctl dump-flows br0 table=1 | sed -n 's/.*n_packets=\([[0-9]]\{1,\}\).*/\1/p')
    echo "n_packets=$n"
    test "$n" = 2
}
OVS_WAIT_UNTIL([check_flows], [ovs-ofctl dump-flows br0])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - debug_slow action])
OVS_VSWITCHD_START
add_of_ports br0 1 2 3

AT_CHECK([ovs-ofctl add-flow br0 "in_port=1,actions=debug_slow,2"])

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 ovs-dummy "$flow" -generate], [0], [stdout])
AT_CHECK_UNQUOTED([tail -3 stdout], [0], [Datapath actions: 2
This flow is handled by the userspace slow path because it:
  - Uses action(s) not supported by datapath.
])

OVS_VSWITCHD_STOP
AT_CLEANUP


dnl CHECK_CONTINUATION(TITLE, N_PORTS0, N_PORTS1, ACTIONS0, ACTIONS1, [EXTRA_SETUP])
dnl
dnl Checks the implementation of the continuation mechanism that allows the
dnl packet processing pipeline to be paused and resumed.  Starts by creating
dnl bridge br0 with N_PORTS0 ports numbered 1 through N_PORTS0, and adds the
dnl flows listed in ACTIONS0 to that bridge.  Then, injects a packet at port 1
dnl in the bridge, resuming each time the pipeline pauses, and expects a single
dnl packet to be output at each port 2 through N_PORTS0.  Then, as long as
dnl ACTIONS0 still contains at least one "pause" action, removes one of them
dnl and repeats the process.
dnl
dnl If N_PORTS1 is nonzero, also creates a bridge br1 and adds ports numbered
dnl N_PORTS0 + 1 to N_PORTS0 + N_PORTS1 to it, as well as flows ACTIONS1.
dnl ACTIONS1 may also contain "pause" actions.  Packets are only ever injected
dnl into port 1 on br0, so br1 only comes into action if a patch port (added
dnl by EXTRA_SETUP) jumps from one bridge to another.
dnl
dnl EXTRA_SETUP is an optional list of extra commands to run after setting up
dnl both bridges, e.g. to configure mirrors or patch ports.
m4_define([CHECK_CONTINUATION], [dnl
  m4_foreach([monitor_version], [[OpenFlow10], [OpenFlow13]], [dnl
    AT_SETUP([ofproto-dpif - continuation - $1 - monitor_version])
    AT_KEYWORDS([continuations pause resume])
    OVS_VSWITCHD_START

    # count_matches STRING
    #
    # Prints on stdout the number of occurrences of STRING in stdin.
    count_matches () {
        sed -n ":start
    s/$[1]//p
    t start" | wc -l
    }

    add_of_ports --pcap br0 `seq 1 $2`
    m4_if([$3], [0], [],
      [add_of_br 1
       add_of_ports --pcap br1 `seq m4_eval([$2 + 1]) m4_eval([$2 + $3])`])

    AT_CAPTURE_FILE([ofctl_monitor0.log])
    AT_CHECK([ovs-ofctl -O monitor_version monitor br0 resume --detach --no-chdir --pidfile=ovs-ofctl0.pid 2> ofctl_monitor0.log])
    m4_if([$3], [0], [],
      [AT_CAPTURE_FILE([ofctl_monitor1.log])
       AT_CHECK([ovs-ofctl -O monitor_version monitor br1 resume --detach --no-chdir --pidfile=ovs-ofctl1.pid 2> ofctl_monitor1.log])])

    actions0='$4'
    actions1='$5'
    $6
    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)"
    n_packets=0
    n_resumes=0
    while true; do
        printf "\n\nactions for br0:\n%s\n" "$actions0"
        m4_if([$3], [0], [], [printf "actions for br1:\n%s\n" "$actions1"])

        # Add flows.
        AT_CHECK([echo "$actions0" | sed 's/pause/controller(pause)/g' | ovs-ofctl -O OpenFlow13 add-flows br0 -])
        m4_if([$3], [0], [],
            [AT_CHECK([echo "$actions1" | sed 's/pause/controller(pause)/g' | ovs-ofctl -O OpenFlow13 add-flows br1 -])])

        # Make sure the datapath is up-to-date before sending the packet.
        ovs-appctl revalidator/wait

        # Run a packet through the switch.
        AT_CHECK([ovs-appctl netdev-dummy/receive p1 "$flow"], [0], [stdout])

        # Wait for the expected number of packets to show up.
        n_packets=$(expr $n_packets + 1)
        nports=m4_eval([$2 + $3])
        echo "waiting for $n_packets packets on p2 through p$nports..."
        OVS_WAIT_UNTIL([
            ok=true
            for i in $(seq 2 $nports); do
                n=$(ovs-ofctl parse-pcap p$i-tx.pcap | wc -l)
                printf "%d " $n
                if test $n_packets != $n; then ok=false; fi
            done
            echo
            $ok
        ])

        # Wait for the expected number of NXT_RESUMEs to be logged.
        n_resumes=$(expr $n_resumes + $(echo "$actions0 $actions1" | count_matches pause) )
        echo "waiting for $n_resumes NXT_RESUMEs..."
        OVS_WAIT_UNTIL([test $n_resumes = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])

        # Eliminate one "pause" from the actions.
        #
        # If there were none left, then we're done.
        next_actions0=`echo "$actions0" | sed '1,/pause/s/pause//'`
        if test X"$actions0" = X"$next_actions0"; then
            next_actions1=`echo "$actions1" | sed '1,/pause/s/pause//'`
            if test X"$actions1" = X"$next_actions1"; then
                break
            else
                actions1=$next_actions1
            fi
        else
            actions0=$next_actions0
        fi

        # Delete all the flows and verify that there are none, so that we
        # can be sure that our updated flow tables is actually in use
        # later.
        AT_CHECK([ovs-ofctl del-flows br0 && ovs-ofctl dump-flows br0 | strip_xids], [0],
          [NXST_FLOW reply:
])
        m4_if([$3], [0], [],
          [AT_CHECK([ovs-ofctl del-flows br1 && ovs-ofctl dump-flows br1 | strip_xids], [0],
             [NXST_FLOW reply:
])])
    done
    OVS_VSWITCHD_STOP
    AT_CLEANUP
  ])
])

# Check that pause at the end of the pipeline works OK.
#
# (xlate_continuation() has a special case for no-op actions; this
# fails without that special case.)
CHECK_CONTINUATION([pause at end of pipeline], [2], [0], [actions=2 pause])

# Check that remaining actions are preserved following resume.
CHECK_CONTINUATION([actions], [7], [0],
  [in_port=1 actions=pause 2 pause 3 pause 4 pause 5 pause 6 pause 7])

# Check that multiple levels of resubmit continue following resume.
#
# The "resubmit:55", which is relative to the current table, is
# particularly interesting because it checks that the notion of the
# current table is correctly preserved.
CHECK_CONTINUATION([resubmit], [10], [0],
  [table=0 in_port=1  actions=pause 2 pause resubmit(,1) pause 10 pause
   table=1 in_port=1  actions=pause 3 pause resubmit(,2) pause 9 pause
   table=2 in_port=1  actions=pause 4 pause resubmit(,3) pause 8 pause
   table=3 in_port=1  actions=pause 5 pause resubmit:55  pause 7 pause
   table=3 in_port=55 actions=pause 6 pause])

# Check that the action set is preserved across pause/resume.
CHECK_CONTINUATION([action set], [3], [0],
  [in_port=1 actions=1 pause resubmit(,1) pause 2
   table=1 actions=write_actions(3)])

# Check that goto_table instructions following pause work as expected.
CHECK_CONTINUATION([goto_table], [6], [0],
  [table=0 in_port=1 actions=pause 2 pause goto_table:1
   table=1 in_port=1 actions=pause 3 pause goto_table:2
   table=2 in_port=1 actions=pause 4 pause goto_table:3
   table=3 in_port=1 actions=pause 5 pause goto_table:4
   table=4 in_port=1 actions=pause 6 pause])

# Check that write_metadata instructions following pause work as expected.
CHECK_CONTINUATION([write_metadata], [6], [0],
  [table=0 in_port=1             actions=pause 2 pause write_metadata:1/1 goto_table:1
   table=1 in_port=1 metadata=1  actions=pause 3 pause write_metadata:2/2 goto_table:2
   table=2 in_port=1 metadata=3  actions=pause 4 pause write_metadata:4/4 goto_table:3
   table=3 in_port=1 metadata=7  actions=pause 5 pause write_metadata:8/8 goto_table:4
   table=4 in_port=1 metadata=15 actions=pause 6 pause])

# Check that metadata and the stack used by push and pop is preserved
# across pause/resume.
CHECK_CONTINUATION([data stack], [3], [0],
  [in_port=1 actions=pause dnl
                     set_field:1->reg0 dnl
                     pause dnl
                     set_field:2->reg1 dnl
                     pause dnl
                     output:NXM_NX_REG0[[]] dnl
                     pause dnl
                     push:NXM_NX_REG1[[]] dnl
                     dnl
                     pop:NXM_NX_REG2[[]] dnl
                     pause dnl
                     output:NXM_NX_REG2[[]] dnl
                     pause dnl
                     3])

# Check that mirror output occurs once and once only, even if
# separated by pause/resume.
CHECK_CONTINUATION([mirroring], [5], [0],
  [in_port=1 actions=pause 2 pause 3 pause 4 pause], [],
  [ovs-vsctl \
       set Bridge br0 mirrors=@m --\
       --id=@p2 get Port p2 --\
       --id=@p3 get Port p3 --\
       --id=@p4 get Port p4 --\
       --id=@p5 get Port p5 --\
       --id=@m create Mirror name=mymirror select_dst_port=@p2,@p3,@p4 output_port=@p5])

# Check that pause works in the presence of patch ports.
CHECK_CONTINUATION([patch ports], [4], [1],
  [table=0 in_port=1  actions=pause 2 resubmit(,1) pause 4
   table=1 in_port=1  actions=pause 3 pause 10 pause],
  [table=0 in_port=11 actions=pause 5 pause],
  [ovs-vsctl \
       -- add-port br0 patch10 \
       -- set interface patch10 type=patch options:peer=patch11 \
                                ofport_request=10 \
       -- add-port br1 patch11 \
       -- set interface patch11 type=patch options:peer=patch10 \
                                ofport_request=11])

AT_SETUP([ofproto-dpif - continuation flow stats])
AT_KEYWORDS([continuations pause resume])
OVS_VSWITCHD_START

add_of_ports --pcap br0 `seq 1 2`

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_DATA([flows.txt], [dnl
table=0 in_port=1 actions=set_field:1->reg1 controller(pause) resubmit(,2)
table=2 reg1=0x1 actions=2
])

AT_CHECK([ovs-ofctl -O OpenFlow13 add-flows br0 flows.txt])

AT_CAPTURE_FILE([ofctl_monitor0.log])
ovs-ofctl monitor br0 resume --detach --no-chdir \
--pidfile=ovs-ofctl0.pid 2> ofctl_monitor0.log

# Run a packet through the switch.
AT_CHECK([ovs-appctl netdev-dummy/receive p1 "$flow"], [0], [stdout])

# Check flow stats
AT_CHECK([ovs-ofctl dump-flows br0], [0], [stdout])
AT_CHECK([strip_xids < stdout | sed -n 's/duration=[[0-9]]*\.[[0-9]]*s/duration=0.0s/p' | sed -n 's/idle_age=[[0-9]]*/idle_age=0/p' | grep 'table=2'], [0], [dnl
 cookie=0x0, duration=0.0s, table=2, n_packets=1, n_bytes=106, idle_age=0, reg1=0x1 actions=output:2
])

# The packet should be received by port 2
AT_CHECK([test 1 = `$PYTHON3 "$top_srcdir/utilities/ovs-pcap.in" p2-tx.pcap | wc -l`])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - continuation with conntrack])
AT_KEYWORDS([continuations pause resume])
OVS_VSWITCHD_START

add_of_ports --pcap br0 `seq 1 2`

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_DATA([flows.txt], [dnl
table=0, in_port=1 icmp action=ct(table=1)
table=1, icmp action=controller(pause) resubmit(,2)
table=2, in_port=1 icmp ct_state=+trk+new action=output:2
])

AT_CHECK([ovs-ofctl -O OpenFlow13 add-flows br0 flows.txt])

AT_CAPTURE_FILE([ofctl_monitor0.log])
ovs-ofctl monitor br0 resume --detach --no-chdir \
--pidfile=ovs-ofctl0.pid 2> ofctl_monitor0.log

# Run a packet through the switch.
AT_CHECK([ovs-appctl netdev-dummy/receive p1 "$flow"], [0], [stdout])

# Check flow stats
AT_CHECK([ovs-ofctl dump-flows br0], [0], [stdout])
AT_CHECK([strip_xids < stdout | sed -n 's/duration=[[0-9]]*\.[[0-9]]*s/duration=0.0s/p' | sed -n 's/idle_age=[[0-9]]*/idle_age=0/p' | grep 'table=2'], [0], [dnl
 cookie=0x0, duration=0.0s, table=2, n_packets=1, n_bytes=106, idle_age=0, ct_state=+new+trk,icmp,in_port=1 actions=output:2
])

# The packet should be received by port 2
AT_CHECK([test 1 = `$PYTHON3 "$top_srcdir/utilities/ovs-pcap.in" p2-tx.pcap | wc -l`])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - continuation with patch port])
AT_KEYWORDS([continuations pause resume])
OVS_VSWITCHD_START(
    [add-port br0 p0 -- set Interface p0 type=dummy -- \
     add-port br0 patch- -- \
     set interface patch- type=patch options:peer=patch+ -- \
     add-br br1 -- set bridge br1 datapath-type=dummy fail-mode=secure -- \
     add-port br1 patch+ -- set interface patch+ type=patch options:peer=patch-
])
add_of_ports --pcap br1 1

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_DATA([flows.txt], [dnl
table=0, in_port=patch+ icmp action=controller(pause), resubmit(,1)
table=1, in_port=patch+ icmp action=ct(table=2)
table=2, in_port=patch+ icmp ct_state=+trk+new action=ct(commit, table=3)
table=3, in_port=patch+ icmp action=p1
])

AT_CHECK([ovs-ofctl add-flow br0 action=normal])
AT_CHECK([ovs-ofctl -O OpenFlow13 add-flows br1 flows.txt])

AT_CAPTURE_FILE([ofctl_monitor.log])
ovs-ofctl monitor br1 resume --detach --no-chdir --pidfile=ovs-ofctl.pid 2> ofctl_monitor.log

# Run a packet through the switch.
AT_CHECK([ovs-appctl netdev-dummy/receive p0 "$flow"], [0], [stdout])

# Check flow stats
AT_CHECK([ovs-ofctl dump-flows br1], [0], [stdout])
AT_CHECK([strip_xids < stdout | sed -n 's/duration=[[0-9]]*\.[[0-9]]*s/duration=0.0s/p' | sed -n 's/idle_age=[[0-9]]*/idle_age=0/p' | grep 'table=3' | grep -v 'commit'], [0], [dnl
 cookie=0x0, duration=0.0s, table=3, n_packets=1, n_bytes=106, idle_age=0, icmp,in_port=1 actions=output:2
])

# The packet should be received by port 1
AT_CHECK([test 1 = `$PYTHON3 "$top_srcdir/utilities/ovs-pcap.in" p1-tx.pcap | wc -l`])

OVS_VSWITCHD_STOP
AT_CLEANUP

# Check that pause works after the packet is cloned.
AT_SETUP([ofproto-dpif - continuation after clone])
AT_KEYWORDS([continuations clone pause resume])
OVS_VSWITCHD_START

add_of_ports --pcap br0 `seq 1 3`

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_DATA([flows.txt], [dnl
table=0 in_port=1 actions=set_field:1->reg1 resubmit(,2)
table=1 reg1=0x5 actions=controller(pause) resubmit(,3)
table=1 reg1=0x1 actions=2
table=2 in_port=1 actions=clone(set_field:5->reg1, resubmit(,1))
table=3 reg1=0x1 actions=3
table=3 reg1=0x5 actions=2
])

AT_CHECK([ovs-ofctl -O OpenFlow13 add-flows br0 flows.txt])

AT_CAPTURE_FILE([ofctl_monitor0.log])
ovs-ofctl monitor br0 resume --detach --no-chdir \
--pidfile=ovs-ofctl0.pid 2> ofctl_monitor0.log

# Run a packet through the switch.
AT_CHECK([ovs-appctl netdev-dummy/receive p1 "$flow"], [0], [stdout])

ovs-vsctl show
ovs-ofctl dump-flows br0

# The packet should be received by port 2 and not port 3
AT_CHECK([test 1 = `$PYTHON3 "$top_srcdir/utilities/ovs-pcap.in" p2-tx.pcap | wc -l`])
AT_CHECK([test 0 = `$PYTHON3 "$top_srcdir/utilities/ovs-pcap.in" p3-tx.pcap | wc -l`])

# NXT_RESUMEs should be 1 and reg1 should be set to 0x5.
OVS_WAIT_UNTIL([test 1 = `cat ofctl_monitor*.log | grep NXT_RESUME | grep -c reg1=0x5`])

OVS_VSWITCHD_STOP
AT_CLEANUP

# Two testcases below are for the ofproto/trace command
# The first one tests all correct syntax:
# ofproto/trace [dp_name] odp_flow [-generate|packet]
# ofproto/trace br_name br_flow [-generate|packet]
AT_SETUP([ofproto-dpif - ofproto/trace command 1])
OVS_VSWITCHD_START([set bridge br0 fail-mode=standalone])
add_of_ports br0 1 2 3

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])

odp_flow="in_port(p1)"
br_flow="in_port=1"
# Test command: ofproto/trace odp_flow with in_port as a name.
AT_CHECK([ovs-appctl ofproto/trace "$odp_flow"], [0], [stdout])
AT_CHECK([tail -1 stdout], [0], [dnl
Datapath actions: 2
])

odp_flow="in_port(1)"
# Test command: ofproto/trace odp_flow
AT_CHECK([ovs-appctl ofproto/trace "$odp_flow"], [0], [stdout])
AT_CHECK([tail -1 stdout], [0], [dnl
Datapath actions: 2
])

# Test command: ofproto/trace dp_name odp_flow
AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$odp_flow"], [0], [stdout])
AT_CHECK([tail -1 stdout], [0], [dnl
Datapath actions: 2
])
# Test commmand: ofproto/trace br_name br_flow
AT_CHECK([ovs-appctl ofproto/trace br0 "$br_flow"], [0], [stdout])
AT_CHECK([tail -1 stdout], [0], [dnl
Datapath actions: 2
])

# Delete the inserted flows
AT_CHECK([ovs-ofctl del-flows br0 "in_port=1"], [0], [stdout])
AT_CHECK([ovs-ofctl del-flows br0 "in_port=2"], [0], [stdout])

# This section below tests the [-generate] option
odp_flow="in_port(3),eth(src=50:54:00:00:00:05,dst=ff:ff:ff:ff:ff:ff)"
br_flow="arp,in_port=3,vlan_tci=0x0000,dl_src=50:54:00:00:00:05,dl_dst=ff:ff:ff:ff:ff:ff"

# Test command: ofproto/trace odp_flow
AT_CHECK([ovs-appctl ofproto/trace "$odp_flow"], [0], [stdout])
# Check for no MAC learning entry
AT_CHECK_UNQUOTED([ovs-appctl fdb/show br0 | sed 's/[[0-9]]\{1,\}$/?/'], [0], [dnl
 port  VLAN  MAC                Age
])

# Test command: ofproto/trace br_name br_flow
AT_CHECK([ovs-appctl ofproto/trace br0 "$br_flow"], [0], [stdout])
# Check for no MAC learning entry
AT_CHECK_UNQUOTED([ovs-appctl fdb/show br0 | sed 's/[[0-9]]\{1,\}$/?/'], [0], [dnl
 port  VLAN  MAC                Age
])

# Test command: ofproto/trace odp_flow -generate
AT_CHECK([ovs-appctl ofproto/trace "$odp_flow" -generate], [0], [stdout])
# 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    ?
])

# Test command: ofproto/trace dp_name odp_flow -generate
AT_CHECK([ovs-appctl ofproto/trace ovs-dummy \
  "in_port(1),eth(src=50:54:00:00:00:06,dst=50:54:00:00:00:05)" \
  -generate], [0], [stdout])
# 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    ?
])

# Test command: ofproto/trace br_name br_flow -generate
AT_CHECK([ovs-appctl ofproto/trace br0 \
  "in_port=2,dl_src=50:54:00:00:00:07,dl_dst=50:54:00:00:00:06" \
  -generate], [0], [stdout])
# 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    ?
    2     0  50:54:00:00:00:07    ?
])

# This section beflow tests the [packet] option
# The ovs-tcpundump of packets between port1 and port2
pkt1to2="50540000000250540000000108064500001C000100004001F98CC0A80001C0A800020800F7FF00000000"
pkt2to1="50540000000150540000000208064500001C000100004001F98CC0A80002C0A800010800F7FF00000000"

# Construct the MAC learning table
AT_CHECK([ovs-appctl ofproto/trace ovs-dummy \
  "in_port(1),eth(src=50:54:00:00:00:01,dst=ff:ff:ff:ff:ff:ff)" \
  -generate], [0], [stdout])

# Construct the MAC learning table
AT_CHECK([ovs-appctl ofproto/trace ovs-dummy \
  "in_port(2),eth(src=50:54:00:00:00:02,dst=ff:ff:ff:ff:ff:ff)" \
  -generate], [0], [stdout])

# Test command: ofproto/trace odp_flow packet
AT_CHECK([ovs-appctl ofproto/trace \
  "in_port(1),skb_priority(1),skb_mark(2)" "$pkt1to2"], [0], [stdout])
AT_CHECK([tail -1 stdout], [0], [dnl
Datapath actions: 2
])
AT_CHECK([head -n 3 stdout], [0], [dnl
Flow: pkt_mark=0x2,skb_priority=0x1,arp,in_port=1,vlan_tci=0x0000,dl_src=50:54:00:00:00:01,dl_dst=50:54:00:00:00:02,arp_spa=0.0.0.0,arp_tpa=0.0.0.0,arp_op=0,arp_sha=00:00:00:00:00:00,arp_tha=00:00:00:00:00:00

bridge("br0")
])

# Test command: ofproto/trace dp_name odp_flow packet
AT_CHECK([ovs-appctl ofproto/trace ovs-dummy \
  "in_port(1),skb_priority(1),skb_mark(2)" "$pkt1to2"], [0], [stdout])
AT_CHECK([tail -1 stdout], [0], [dnl
Datapath actions: 2
])
AT_CHECK([head -n 3 stdout], [0], [dnl
Flow: pkt_mark=0x2,skb_priority=0x1,arp,in_port=1,vlan_tci=0x0000,dl_src=50:54:00:00:00:01,dl_dst=50:54:00:00:00:02,arp_spa=0.0.0.0,arp_tpa=0.0.0.0,arp_op=0,arp_sha=00:00:00:00:00:00,arp_tha=00:00:00:00:00:00

bridge("br0")
])

# Test command: ofproto/trace br_name br_flow packet
AT_CHECK([ovs-appctl ofproto/trace br0 \
  "in_port=2,skb_priority=2,pkt_mark=1" "$pkt2to1"], [0], [stdout],[stderr])
AT_CHECK([tail -1 stdout], [0], [dnl
Datapath actions: 1
])
AT_CHECK([head -n 3 stdout], [0], [dnl
Flow: pkt_mark=0x1,skb_priority=0x2,arp,in_port=2,vlan_tci=0x0000,dl_src=50:54:00:00:00:02,dl_dst=50:54:00:00:00:01,arp_spa=0.0.0.0,arp_tpa=0.0.0.0,arp_op=0,arp_sha=00:00:00:00:00:00,arp_tha=00:00:00:00:00:00

bridge("br0")
])

OVS_VSWITCHD_STOP
AT_CLEANUP

# The second test tests the corner cases
AT_SETUP([ofproto-dpif - ofproto/trace command 2])
OVS_VSWITCHD_START
add_of_ports br0 1 2

# Define flows
odp_flow="in_port(1),eth(src=50:54:00:00:00:01,dst=50:54:00:00:00:02)"
br_flow="in_port=1,dl_src=50:54:00:00:00:01,dl_dst=50:54:00:00:00:02"
# Define options
generate="-generate"
pkt="50540000000250540000000108064500001C000100004001F98CC0A80001C0A800020800F7FF00000000"

# Test incorrect command: ofproto/trace wrong_name odp_flow [-generate|packet]
m4_foreach(
[option],
[[],
["$generate"],
["$pkt"]],
[AT_CHECK([ovs-appctl ofproto/trace wrong_name "$odp_flow" option],
  [2], [], [stderr])
AT_CHECK([tail -2 stderr], [0], [dnl
Cannot find the datapath
ovs-appctl: ovs-vswitchd: server returned an error
])])

# Test incorrect command: ofproto/trace empty_string odp_flow [-generate|packet]
m4_foreach(
[option],
[[],
["$generate"],
["$pkt"]],
[AT_CHECK([ovs-appctl ofproto/trace "" "$odp_flow" option],
  [2], [], [stderr])
AT_CHECK([tail -2 stderr], [0], [dnl
Cannot find the datapath
ovs-appctl: ovs-vswitchd: server returned an error
])])

# Test incorrect command: ofproto/trace nonexist_dp_name odp_flow [-generate|packet]
m4_foreach(
[option],
[[],
["$generate"],
["$pkt"]],
[AT_CHECK([ovs-appctl ofproto/trace ovs-system "$odp_flow" option],
  [2], [], [stderr])
AT_CHECK([tail -2 stderr], [0], [dnl
Cannot find the datapath
ovs-appctl: ovs-vswitchd: server returned an error
])])

# Test incorrect command: ofproto/trace br_name odp_flow [-generate|packet]
m4_foreach(
[option],
[[],
["$generate"],
["$pkt"]],
[AT_CHECK([ovs-appctl ofproto/trace br0 "$odp_flow" option],
  [2], [], [stderr])
AT_CHECK([tail -2 stderr], [0], [dnl
Cannot find the datapath
ovs-appctl: ovs-vswitchd: server returned an error
])])

# Test incorrect command: ofproto/trace dp_name br_flow [-generate|packet]
m4_foreach(
[option],
[[],
["$generate"],
["$pkt"]],
[AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$br_flow" option],
  [2], [], [stderr])
AT_CHECK([tail -2 stderr], [0], [dnl
ovs-dummy: unknown bridge
ovs-appctl: ovs-vswitchd: server returned an error
])])

# Test incorrect command: ofproto/trace br_flow [-generate|packet]
m4_foreach(
[option],
[[],
["$generate"],
["$pkt"]],
[AT_CHECK([ovs-appctl ofproto/trace "$br_flow" option],
  [2], [], [stderr])
AT_CHECK([tail -2 stderr], [0], [dnl
syntax error at in_port=1,dl_src=50:54:00:00:00:01,dl_dst=50:54:00:00:00:02 (or the bridge name was omitted)
ovs-appctl: ovs-vswitchd: server returned an error
])])

# Test incorrect command: ofproto/trace dp_name odp_flow garbage_option
AT_CHECK([ovs-appctl ofproto/trace \
  ovs-dummy "$odp_flow" garbage_option],
  [2], [stdout],[stderr])
AT_CHECK([tail -2 stderr], [0], [dnl
Trailing garbage in packet data
ovs-appctl: ovs-vswitchd: server returned an error
])

# Test incorrect command: ofproto/trace with 0 argument
AT_CHECK([ovs-appctl ofproto/trace ], [2], [stdout],[stderr])
AT_CHECK([tail -2 stderr], [0], [dnl
"ofproto/trace" command requires at least 1 arguments
ovs-appctl: ovs-vswitchd: server returned an error
])

OVS_VSWITCHD_STOP
AT_CLEANUP

# The third test checks that the output of "ovs-dpctl -m" is valid to trace.
AT_SETUP([ofproto-dpif - ofproto/trace from dpctl output])
OVS_VSWITCHD_START([dnl
    set Open_vSwitch . other_config:max-idle=10000 \
    -- add-port br0 p1 -- set Interface p1 type=dummy])

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)'])
ovs-appctl revalidator/wait
AT_CHECK([ovs-appctl dpif/dump-flows -m br0 | sed 's/, packets.*$//' > dp_flows1.txt])

odp_flow=`cat dp_flows1.txt`
AT_CHECK([ovs-appctl ofproto/trace "$odp_flow" | sed 's/\([[Ff]]low:\).*/\1 <cleared>/'], [0], [dnl
Flow: <cleared>

bridge("br0")
-------------
 0. No match.
    drop

Final flow: <cleared>
Megaflow: <cleared>
Datapath actions: drop
])

dnl Now, try again without megaflows:
ovs-appctl upcall/disable-megaflows

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)'])
ovs-appctl revalidator/wait
AT_CHECK([ovs-appctl dpif/dump-flows -m br0 | sed 's/, packets.*$//' > dp_flows2.txt])

odp_flow=`cat dp_flows2.txt`
AT_CHECK([ovs-appctl ofproto/trace "$odp_flow" | sed 's/\([[Ff]]low:\).*/\1 <cleared>/'], [0], [dnl
Flow: <cleared>

bridge("br0")
-------------
 0. No match.
    drop

Final flow: <cleared>
Megaflow: <cleared>
Datapath actions: drop
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - ofproto/trace-packet-out])
OVS_VSWITCHD_START
add_of_ports br0 1 2 3

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])

AT_CHECK([ovs-appctl ofproto/trace-packet-out br0 in_port=1 'mod_vlan_vid:123,resubmit(,0)'], [0], [stdout])
AT_CHECK([tail -1 stdout], [0], [dnl
Datapath actions: push_vlan(vid=123,pcp=0),2
])

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(
  [ovs-dummy],
  [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(
  [ovs-dummy],
  [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(
  [ovs-dummy],
  [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_of_ports br1 4 5

# Trace some packet arrivals in br1 to create MAC learning entries there too.
OFPROTO_TRACE(
  [ovs-dummy],
  [in_port(4),eth(src=50:54:00:00:00:06,dst=ff:ff:ff:ff:ff:ff),$arp],
  [-generate],
  [5,101])
OFPROTO_TRACE(
  [ovs-dummy],
  [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_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)'

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(
      [ovs-dummy],
      [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(
  [ovs-dummy],
  [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

AT_SETUP([ofproto-dpif - MAC table overflow fairness])
OVS_VSWITCHD_START(
  [set bridge br0 fail-mode=standalone other-config:mac-table-size=10])
add_of_ports br0 1 2 3 4 5 6

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 packets with 2 different source MACs arriving on each of the 5
# ports, filling up the 10-entry learning table.
for i in 0 1 2 3 4 5 6 7 8 9; do
    p=`expr $i / 2 + 1`
    ovs-appctl ofproto/trace ovs-dummy "in_port($p),eth(src=50:54:00:00:00:0$i,dst=ff:ff:ff:ff:ff:ff),$arp" -generate
    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
    1     0  50:54:00:00:00:00
    1     0  50:54:00:00:00:01
    2     0  50:54:00:00:00:02
    2     0  50:54:00:00:00:03
    3     0  50:54:00:00:00:04
    3     0  50:54:00:00:00:05
    4     0  50:54:00:00:00:06
    4     0  50:54:00:00:00:07
    5     0  50:54:00:00:00:08
    5     0  50:54:00:00:00:09
 port  VLAN  MAC                Age
])

# Now trace 16 new MACs on another port.
for i in 0 1 2 3 4 5 6 7 8 9 a b c d e f; do
    ovs-appctl ofproto/trace ovs-dummy "in_port(6),eth(src=50:54:00:00:0$i:ff,dst=ff:ff:ff:ff:ff:ff),$arp" -generate
    ovs-appctl time/warp 1000
done

# Check the results.
#
# Our eviction algorithm on overflow is that an arbitrary (but deterministic)
# one of the ports with the most learned MACs loses the least recently used
# one.  Thus, the new port will end up with 3 MACs, 3 of the old ports with 1
# MAC each, and the other 2 of the old ports with 2 MACs each.
#
# (If someone changes lib/heap.c to do something different with equal-priority
# nodes, then the output below could change, but it would still follow the
# rules explained above.)
AT_CHECK_UNQUOTED([ovs-appctl fdb/show br0 | sed 's/ *[[0-9]]\{1,\}$//' | sort],
  [0], [dnl
    1     0  50:54:00:00:00:01
    2     0  50:54:00:00:00:03
    3     0  50:54:00:00:00:04
    3     0  50:54:00:00:00:05
    4     0  50:54:00:00:00:07
    5     0  50:54:00:00:00:08
    5     0  50:54:00:00:00:09
    6     0  50:54:00:00:0d:ff
    6     0  50:54:00:00:0e:ff
    6     0  50:54:00:00:0f:ff
 port  VLAN  MAC                Age
])
OVS_VSWITCHD_STOP
AT_CLEANUP

# CHECK_SFLOW_SAMPLING_PACKET(LOOPBACK_ADDR)
#
# Test that sFlow samples packets correctly using IPv4/IPv6 sFlow collector
m4_define([CHECK_SFLOW_SAMPLING_PACKET],
  [AT_XFAIL_IF([test "$IS_WIN32" = "yes"])
  OVS_VSWITCHD_START([set Bridge br0 fail-mode=standalone])

  on_exit 'kill `cat test-sflow.pid`'
  AT_CHECK([ovstest test-sflow --log-file --detach --no-chdir --pidfile 0:$1 > sflow.log], [0], [], [ignore])
  AT_CAPTURE_FILE([sflow.log])
  PARSE_LISTENING_PORT([test-sflow.log], [SFLOW_PORT])
  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=\"$1:$SFLOW_PORT\" \
       header=128 sampling=1 polling=1 agent=$LOOPBACK_INTERFACE

  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.
  dnl because packets from different ports can be handled by separate
  dnl threads, put some sleeps

  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)'
  sleep 1
  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)'
  sleep 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=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)'
  sleep 1
  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
  ovs-appctl time/warp 2000 100
  OVS_VSWITCHD_STOP
  OVS_APP_EXIT_AND_WAIT([test-sflow])

  AT_CHECK_UNQUOTED([[sort sflow.log | $EGREP 'HEADER|ERROR' | sed 's/ /\
        /g' | sed 's/\(.*\)ds=\[::1\]\(.*\)/\1ds=127.0.0.1\2/g' ]], [0], [dnl
HEADER
        dgramSeqNo=1
        ds=127.0.0.1>2:1000
        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=46
        stripped=4
        hdr_len=42
        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
HEADER
        dgramSeqNo=1
        ds=127.0.0.1>2:1000
        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=2
        out_format=2
        hdr_prot=1
        pkt_len=46
        stripped=4
        hdr_len=42
        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
HEADER
        dgramSeqNo=1
        ds=127.0.0.1>2:1000
        fsSeqNo=3
        in_vlan=0
        in_priority=0
        out_vlan=0
        out_priority=0
        meanSkip=1
        samplePool=3
        dropEvents=0
        in_ifindex=1004
        in_format=0
        out_ifindex=1003
        out_format=0
        hdr_prot=1
        pkt_len=110
        stripped=4
        hdr_len=106
        hdr=50-54-00-00-00-07-50-54-00-00-00-05-08-00-45-00-00-5C-00-00-00-00-40-01-F9-4D-C0-A8-00-01-C0-A8-00-02-08-00-13-FC-00-00-00-00-00-01-02-03-04-05-06-07-08-09-0A-0B-0C-0D-0E-0F-10-11-12-13-14-15-16-17-18-19-1A-1B-1C-1D-1E-1F-20-21-22-23-24-25-26-27-28-29-2A-2B-2C-2D-2E-2F-30-31-32-33-34-35-36-37-38-39-3A-3B-3C-3D-3E-3F
HEADER
        dgramSeqNo=1
        ds=127.0.0.1>2:1000
        fsSeqNo=4
        in_vlan=0
        in_priority=0
        out_vlan=0
        out_priority=0
        meanSkip=1
        samplePool=4
        dropEvents=0
        in_ifindex=1003
        in_format=0
        out_ifindex=1004
        out_format=0
        hdr_prot=1
        pkt_len=110
        stripped=4
        hdr_len=106
        hdr=50-54-00-00-00-05-50-54-00-00-00-07-08-00-45-00-00-5C-00-00-00-00-40-01-F9-4D-C0-A8-00-02-C0-A8-00-01-00-00-1B-FC-00-00-00-00-00-01-02-03-04-05-06-07-08-09-0A-0B-0C-0D-0E-0F-10-11-12-13-14-15-16-17-18-19-1A-1B-1C-1D-1E-1F-20-21-22-23-24-25-26-27-28-29-2A-2B-2C-2D-2E-2F-30-31-32-33-34-35-36-37-38-39-3A-3B-3C-3D-3E-3F
HEADER
        dgramSeqNo=1
        ds=127.0.0.1>2:1000
        fsSeqNo=5
        in_vlan=0
        in_priority=0
        out_vlan=0
        out_priority=0
        meanSkip=1
        samplePool=5
        dropEvents=0
        in_ifindex=1003
        in_format=0
        out_ifindex=1004
        out_format=0
        hdr_prot=1
        pkt_len=58
        stripped=4
        hdr_len=54
        hdr=50-54-00-00-00-05-50-54-00-00-00-07-86-DD-67-00-00-00-00-00-0A-80-FE-80-00-00-00-00-00-00-00-00-00-00-00-00-00-01-FE-80-00-00-00-00-00-00-00-00-00-00-00-00-00-02
])

  AT_CHECK_UNQUOTED([[sort sflow.log | $EGREP 'ETHCOUNTERS|IFCOUNTERS|ERROR|PORTNAME|OPENFLOWPORT' | head -24 | sed 's/ /\
        /g' | sed 's/\(.*\)ds=\[::1\]\(.*\)/\1ds=127.0.0.1\2/g' ]], [0], [dnl
ETHCOUNTERS
        dot3StatsAlignmentErrors=4294967295
        dot3StatsFCSErrors=4294967295
        dot3StatsSingleCollisionFrames=4294967295
        dot3StatsMultipleCollisionFrames=4294967295
        dot3StatsSQETestErrors=4294967295
        dot3StatsDeferredTransmissions=4294967295
        dot3StatsLateCollisions=4294967295
        dot3StatsExcessiveCollisions=4294967295
        dot3StatsInternalMacTransmitErrors=4294967295
        dot3StatsCarrierSenseErrors=4294967295
        dot3StatsFrameTooLongs=4294967295
        dot3StatsInternalMacReceiveErrors=4294967295
        dot3StatsSymbolErrors=4294967295
ETHCOUNTERS
        dot3StatsAlignmentErrors=4294967295
        dot3StatsFCSErrors=4294967295
        dot3StatsSingleCollisionFrames=4294967295
        dot3StatsMultipleCollisionFrames=4294967295
        dot3StatsSQETestErrors=4294967295
        dot3StatsDeferredTransmissions=4294967295
        dot3StatsLateCollisions=4294967295
        dot3StatsExcessiveCollisions=4294967295
        dot3StatsInternalMacTransmitErrors=4294967295
        dot3StatsCarrierSenseErrors=4294967295
        dot3StatsFrameTooLongs=4294967295
        dot3StatsInternalMacReceiveErrors=4294967295
        dot3StatsSymbolErrors=4294967295
ETHCOUNTERS
        dot3StatsAlignmentErrors=4294967295
        dot3StatsFCSErrors=4294967295
        dot3StatsSingleCollisionFrames=4294967295
        dot3StatsMultipleCollisionFrames=4294967295
        dot3StatsSQETestErrors=4294967295
        dot3StatsDeferredTransmissions=4294967295
        dot3StatsLateCollisions=4294967295
        dot3StatsExcessiveCollisions=4294967295
        dot3StatsInternalMacTransmitErrors=4294967295
        dot3StatsCarrierSenseErrors=4294967295
        dot3StatsFrameTooLongs=4294967295
        dot3StatsInternalMacReceiveErrors=4294967295
        dot3StatsSymbolErrors=4294967295
ETHCOUNTERS
        dot3StatsAlignmentErrors=4294967295
        dot3StatsFCSErrors=4294967295
        dot3StatsSingleCollisionFrames=4294967295
        dot3StatsMultipleCollisionFrames=4294967295
        dot3StatsSQETestErrors=4294967295
        dot3StatsDeferredTransmissions=4294967295
        dot3StatsLateCollisions=4294967295
        dot3StatsExcessiveCollisions=4294967295
        dot3StatsInternalMacTransmitErrors=4294967295
        dot3StatsCarrierSenseErrors=4294967295
        dot3StatsFrameTooLongs=4294967295
        dot3StatsInternalMacReceiveErrors=4294967295
        dot3StatsSymbolErrors=4294967295
ETHCOUNTERS
        dot3StatsAlignmentErrors=4294967295
        dot3StatsFCSErrors=4294967295
        dot3StatsSingleCollisionFrames=4294967295
        dot3StatsMultipleCollisionFrames=4294967295
        dot3StatsSQETestErrors=4294967295
        dot3StatsDeferredTransmissions=4294967295
        dot3StatsLateCollisions=4294967295
        dot3StatsExcessiveCollisions=4294967295
        dot3StatsInternalMacTransmitErrors=4294967295
        dot3StatsCarrierSenseErrors=4294967295
        dot3StatsFrameTooLongs=4294967295
        dot3StatsInternalMacReceiveErrors=4294967295
        dot3StatsSymbolErrors=4294967295
ETHCOUNTERS
        dot3StatsAlignmentErrors=4294967295
        dot3StatsFCSErrors=4294967295
        dot3StatsSingleCollisionFrames=4294967295
        dot3StatsMultipleCollisionFrames=4294967295
        dot3StatsSQETestErrors=4294967295
        dot3StatsDeferredTransmissions=4294967295
        dot3StatsLateCollisions=4294967295
        dot3StatsExcessiveCollisions=4294967295
        dot3StatsInternalMacTransmitErrors=4294967295
        dot3StatsCarrierSenseErrors=4294967295
        dot3StatsFrameTooLongs=4294967295
        dot3StatsInternalMacReceiveErrors=4294967295
        dot3StatsSymbolErrors=4294967295
IFCOUNTERS
        dgramSeqNo=1
        ds=127.0.0.1>0:1003
        csSeqNo=1
        ifindex=1003
        type=6
        ifspeed=100000000
        direction=0
        status=3
        in_octets=202
        in_unicasts=3
        in_multicasts=4294967295
        in_broadcasts=4294967295
        in_discards=4294967295
        in_errors=4294967295
        in_unknownprotos=4294967295
        out_octets=148
        out_unicasts=2
        out_multicasts=4294967295
        out_broadcasts=4294967295
        out_discards=4294967295
        out_errors=4294967295
        promiscuous=0
IFCOUNTERS
        dgramSeqNo=1
        ds=127.0.0.1>0:1004
        csSeqNo=1
        ifindex=1004
        type=6
        ifspeed=100000000
        direction=0
        status=3
        in_octets=148
        in_unicasts=2
        in_multicasts=4294967295
        in_broadcasts=4294967295
        in_discards=4294967295
        in_errors=4294967295
        in_unknownprotos=4294967295
        out_octets=202
        out_unicasts=3
        out_multicasts=4294967295
        out_broadcasts=4294967295
        out_discards=4294967295
        out_errors=4294967295
        promiscuous=0
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=4294967295
        in_broadcasts=4294967295
        in_discards=4294967295
        in_errors=4294967295
        in_unknownprotos=4294967295
        out_octets=84
        out_unicasts=2
        out_multicasts=4294967295
        out_broadcasts=4294967295
        out_discards=4294967295
        out_errors=4294967295
        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=4294967295
        in_broadcasts=4294967295
        in_discards=4294967295
        in_errors=4294967295
        in_unknownprotos=4294967295
        out_octets=84
        out_unicasts=2
        out_multicasts=4294967295
        out_broadcasts=4294967295
        out_discards=4294967295
        out_errors=4294967295
        promiscuous=0
IFCOUNTERS
        dgramSeqNo=3
        ds=127.0.0.1>0:1003
        csSeqNo=2
        ifindex=1003
        type=6
        ifspeed=100000000
        direction=0
        status=3
        in_octets=202
        in_unicasts=3
        in_multicasts=4294967295
        in_broadcasts=4294967295
        in_discards=4294967295
        in_errors=4294967295
        in_unknownprotos=4294967295
        out_octets=148
        out_unicasts=2
        out_multicasts=4294967295
        out_broadcasts=4294967295
        out_discards=4294967295
        out_errors=4294967295
        promiscuous=0
IFCOUNTERS
        dgramSeqNo=3
        ds=127.0.0.1>0:1004
        csSeqNo=2
        ifindex=1004
        type=6
        ifspeed=100000000
        direction=0
        status=3
        in_octets=148
        in_unicasts=2
        in_multicasts=4294967295
        in_broadcasts=4294967295
        in_discards=4294967295
        in_errors=4294967295
        in_unknownprotos=4294967295
        out_octets=202
        out_unicasts=3
        out_multicasts=4294967295
        out_broadcasts=4294967295
        out_discards=4294967295
        out_errors=4294967295
        promiscuous=0
OPENFLOWPORT
        datapath_id=18364758544493064720
        port_no=1
OPENFLOWPORT
        datapath_id=18364758544493064720
        port_no=1
OPENFLOWPORT
        datapath_id=18364758544493064720
        port_no=2
OPENFLOWPORT
        datapath_id=18364758544493064720
        port_no=2
OPENFLOWPORT
        datapath_id=18364758544493064720
        port_no=65534
OPENFLOWPORT
        datapath_id=18364758544493064720
        port_no=65534
PORTNAME
        portName=br0
PORTNAME
        portName=br0
PORTNAME
        portName=p1
PORTNAME
        portName=p1
PORTNAME
        portName=p2
PORTNAME
        portName=p2
])])

AT_SETUP([ofproto-dpif - static-mac add/del/flush])
OVS_VSWITCHD_START([set bridge br0 fail-mode=standalone])
add_of_ports br0 1 2

dnl Generate some dynamic fdb entries on some ports.
OFPROTO_TRACE([ovs-dummy], [in_port(1),eth(src=50:54:00:00:00:01)], [-generate], [100,2])
OFPROTO_TRACE([ovs-dummy], [in_port(2),eth(src=50:54:00:00:00:02)], [-generate], [100,1])

dnl Add some static mac entries.
AT_CHECK([ovs-appctl fdb/add br0 p1 0 50:54:00:00:01:01])
AT_CHECK([ovs-appctl fdb/add br0 p2 0 50:54:00:00:02:02])

dnl Check initial fdb.
AT_CHECK_UNQUOTED([ovs-appctl fdb/show br0 | sed 's/ *[[0-9]]\{1,\}$//' | grep -v port | sort], [0], [dnl
    1     0  50:54:00:00:00:01
    1     0  50:54:00:00:01:01  static
    2     0  50:54:00:00:00:02
    2     0  50:54:00:00:02:02  static
])

dnl Remove static mac entry.
AT_CHECK([ovs-appctl fdb/del br0 0 50:54:00:00:01:01])

dnl Check that entry is removed.
AT_CHECK_UNQUOTED([ovs-appctl fdb/show br0 | grep "50:54:00:00:01:01"], [1], [dnl
])

# Add some more cache and static entries, to test out flush operation
for i in 0 1 2 3 4 5 6 7 8 9 a b c d e f; do
    ovs-appctl ofproto/trace ovs-dummy "in_port(1),eth(src=50:54:00:00:0$i:ff)" -generate
    ovs-appctl fdb/add br0 p2 0 50:54:00:0$i:00:ff
done

for i in 0 1 2 3 4 5 6 7 8 9 a b c d e f; do
    ovs-appctl fdb/add br0 p2 0 50:54:00:0$i:00:ff
done

dnl Flush mac entries, only dynamic ones should be evicted.
AT_CHECK([ovs-appctl fdb/flush br0], [0], [dnl
table successfully flushed
])

dnl Count number of static entries remaining.
AT_CHECK_UNQUOTED([ovs-appctl fdb/stats-show br0 | grep static], [0], [dnl
  Current static MAC entries in the table : 17
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - static-mac mac moves])
OVS_VSWITCHD_START([set bridge br0 fail-mode=standalone])
add_of_ports br0 1 2

dnl Generate a dynamic entry.
OFPROTO_TRACE([ovs-dummy], [in_port(1),eth(src=50:54:00:00:00:00)], [-generate], [100,2])

dnl Convert dynamically learnt dl_src to a static-mac.
AT_CHECK([ovs-appctl fdb/add br0 p1 0 50:54:00:00:00:00], [0], [dnl
Overriding already existing dynamic entry on 1
])

dnl Check fdb.
AT_CHECK_UNQUOTED([ovs-appctl fdb/show br0 | sed 's/ *[[0-9]]\{1,\}$//' | grep -v port | sort], [0], [dnl
    1     0  50:54:00:00:00:00  static
])

dnl Move the static mac to different port.
AT_CHECK([ovs-appctl fdb/add br0 p2 0 50:54:00:00:00:00], [0], [dnl
Overriding already existing static entry on 1
])

dnl Check fdb.
AT_CHECK_UNQUOTED([ovs-appctl fdb/show br0 | sed 's/ *[[0-9]]\{1,\}$//' | grep -v port | sort], [0], [dnl
    2     0  50:54:00:00:00:00  static
])

dnl static-mac should not be converted to a dynamic one when a packet with same dl_src
dnl arrives on any port of the switch.
dnl Packet arriving on p1.
OFPROTO_TRACE([ovs-dummy], [in_port(1),eth(src=50:54:00:00:00:00)], [-generate], [100,2])
AT_CHECK_UNQUOTED([ovs-appctl fdb/show br0 | sed 's/ *[[0-9]]\{1,\}$//' | grep -v port | sort], [0], [dnl
    2     0  50:54:00:00:00:00  static
])

dnl Packet arriving on p2.
OFPROTO_TRACE([ovs-dummy], [in_port(2),eth(src=50:54:00:00:00:00)], [-generate], [100,1])
AT_CHECK_UNQUOTED([ovs-appctl fdb/show br0 | sed 's/ *[[0-9]]\{1,\}$//' | grep -v port | sort], [0], [dnl
    2     0  50:54:00:00:00:00  static
])

dnl Check mac_move coverage counter mac_learning_static_none_move.
AT_CHECK([ovs-appctl coverage/read-counter mac_learning_static_none_move], [0], [dnl
1
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - basic truncate action])
OVS_VSWITCHD_START
add_of_ports br0 1 2 3 4 5

AT_CHECK([ovs-vsctl -- set Interface p1 type=dummy options:pcap=p1.pcap])
AT_CHECK([ovs-vsctl -- set Interface p2 type=dummy options:pstream=punix:p2.sock])
AT_CHECK([ovs-vsctl -- set Interface p3 type=dummy   options:stream=unix:p2.sock])
AT_CHECK([ovs-vsctl -- set Interface p4 type=dummy options:pstream=punix:p4.sock])
AT_CHECK([ovs-vsctl -- set Interface p5 type=dummy   options:stream=unix:p4.sock])

AT_DATA([flows.txt], [dnl
in_port=3,actions=drop
in_port=5,actions=drop
in_port=1,actions=output(port=2,max_len=64),output:4
])
AT_CHECK([ovs-ofctl add-flows br0 flows.txt])

dnl Datapath actions
AT_CHECK([ovs-appctl ofproto/trace ovs-dummy '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=6,tos=4,ttl=128,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
AT_CHECK([tail -1 stdout], [0],
[Datapath actions: trunc(64),2,4
])

dnl An 170 byte packet
AT_CHECK([ovs-appctl netdev-dummy/receive p1 '000c29c8a0a4005056c0000808004500009cb4a6000040019003c0a8da01c0a8da640800cb5fa762000556f431ad0009388e08090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f'])

AT_CHECK([ovs-ofctl parse-pcap p1.pcap], [0], [dnl
icmp,in_port=ANY,vlan_tci=0x0000,dl_src=00:50:56:c0:00:08,dl_dst=00:0c:29:c8:a0:a4,nw_src=192.168.218.1,nw_dst=192.168.218.100,nw_tos=0,nw_ecn=0,nw_ttl=64,icmp_type=8,icmp_code=0
])

AT_CHECK([ovs-appctl revalidator/purge], [0])
dnl packet with truncated size
AT_CHECK([ovs-ofctl dump-flows br0 | grep "in_port=3" | sed -n 's/.*\(n\_bytes=[[0-9]]*\).*/\1/p'], [0], [dnl
n_bytes=64
])
dnl packet with original size
AT_CHECK([ovs-ofctl dump-flows br0 | grep "in_port=5" | sed -n 's/.*\(n\_bytes=[[0-9]]*\).*/\1/p'], [0], [dnl
n_bytes=170
])

dnl More complicated case
AT_CHECK([ovs-ofctl del-flows br0])
AT_DATA([flows.txt], [dnl
in_port=3,actions=drop
in_port=5,actions=drop
in_port=1,actions=output(port=2,max_len=64),output(port=2,max_len=128),output(port=4,max_len=60),output:2,output:4
])
AT_CHECK([ovs-ofctl add-flows br0 flows.txt])

dnl Datapath actions
AT_CHECK([ovs-appctl ofproto/trace ovs-dummy '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=6,tos=4,ttl=128,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
AT_CHECK([tail -1 stdout], [0],
[Datapath actions: trunc(64),2,trunc(128),2,trunc(60),4,2,4
])

dnl An 170 byte packet
AT_CHECK([ovs-appctl netdev-dummy/receive p1 '000c29c8a0a4005056c0000808004500009cb4a6000040019003c0a8da01c0a8da640800cb5fa762000556f431ad0009388e08090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f'])

AT_CHECK([ovs-appctl revalidator/purge], [0])
dnl packet size: 64 + 128 + 170 = 362
AT_CHECK([ovs-ofctl dump-flows br0 | grep "in_port=3" | sed -n 's/.*\(n\_bytes=[[0-9]]*\).*/\1/p'], [0], [dnl
n_bytes=362
])
dnl packet size: 60 + 170 = 230
AT_CHECK([ovs-ofctl dump-flows br0 | grep "in_port=5" | sed -n 's/.*\(n\_bytes=[[0-9]]*\).*/\1/p'], [0], [dnl
n_bytes=230
])

dnl syntax checking
AT_CHECK([ovs-ofctl add-flow br0 'actions=output(port=ALL,max_len=100)'], [1], [], [dnl
ovs-ofctl: output to unsupported truncate port: ALL
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - truncate and output to patch port])
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 ofport_request=1 \
-- add-port br0 pbr0 -- set int pbr0 type=patch options:peer=pbr1])

add_of_ports br0 2

AT_CHECK([ovs-ofctl add-flow br0 actions='output(port=1,max_len=100),output:2'])
AT_CHECK([ovs-ofctl add-flow br1 actions=NORMAL])

AT_CHECK([ovs-appctl ofproto/trace br0 in_port=LOCAL,dl_src=10:20:30:40:50:60],
[0], [stdout])
AT_CHECK([tail -1 stdout], [0], [Datapath actions: 2
])
dnl the output(port=1,max_len=100) fails the translation, only output:2 in datapath
AT_CHECK([grep "output_trunc does not support patch port [[0-9]]*" stdout], [0], [stdout])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - truncate and output to gre tunnel])
OVS_VSWITCHD_START([add-port br0 p1 -- set Interface p1 type=gre \
                    options:remote_ip=1.1.1.1 options:local_ip=2.2.2.2 \
                    options:key=5 ofport_request=1\
                    -- add-port br0 p2 -- set Interface p2 type=dummy \
                    ofport_request=2])
AT_DATA([flows.txt], [dnl
actions=output(max_len=100, port=1)
])
OVS_VSWITCHD_DISABLE_TUNNEL_PUSH_POP
AT_CHECK([ovs-ofctl add-flows br0 flows.txt])

AT_CHECK([ovs-appctl dpif/show | tail -n +3], [0], [dnl
    br0 65534/100: (dummy-internal)
    p1 1/1: (gre: key=5, local_ip=2.2.2.2, remote_ip=1.1.1.1)
    p2 2/2: (dummy)
])

dnl Basic
AT_CHECK([ovs-appctl ofproto/trace ovs-dummy '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=4,ttl=128,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
AT_CHECK([tail -1 stdout], [0],
  [Datapath actions: trunc(100),set(tunnel(tun_id=0x5,src=2.2.2.2,dst=1.1.1.1,ttl=64,flags(df|key))),1
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - sFlow packet sampling - IPv4 collector])
CHECK_SFLOW_SAMPLING_PACKET([127.0.0.1])
AT_CLEANUP

AT_SETUP([ofproto-dpif - sFlow packet sampling - IPv6 collector])
AT_SKIP_IF([test $HAVE_IPV6 = no])
CHECK_SFLOW_SAMPLING_PACKET([[[::1]]])
AT_CLEANUP

dnl Test sFlow LAG structures
AT_SETUP([ofproto-dpif - sFlow packet sampling - LACP structures])
AT_SKIP_IF([test "$IS_WIN32" = "yes"])
OVS_VSWITCHD_START([dnl
                    add-bond br0 bond p1 p2 --                          \
                    set Port bond lacp=active bond-mode=active-backup   \
                    other_config:lacp-time="fast"                       \
                    other_config:lacp-system-id=11:22:33:44:55:66       \
                    other_config:lacp-system-priority=54321 --          \
                    set Interface p1 type=dummy                         \
                    other_config:lacp-port-id=11                        \
                    other_config:lacp-port-priority=111                 \
                    other_config:lacp-aggregation-key=3333 --           \
                    set Interface p2 type=dummy                         \
                    other_config:lacp-port-id=22                        \
                    other_config:lacp-port-priority=222                 \
                    other_config:lacp-aggregation-key=3333 ])

on_exit 'kill `cat test-sflow.pid`'
AT_CHECK([ovstest test-sflow --log-file --detach --no-chdir --pidfile 0:127.0.0.1 > sflow.log], [0], [], [ignore])
AT_CAPTURE_FILE([sflow.log])
PARSE_LISTENING_PORT([test-sflow.log], [SFLOW_PORT])

ovs-appctl time/stop

ovs-vsctl \
      set Interface p1 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 agent=127.0.0.1

dnl sleep long enough to get the sFlow datagram flushed out (may be delayed for up to 1 second)
AT_CHECK([ovs-appctl time/warp 2000 100], [0], [ignore])
AT_CHECK([ovs-appctl revalidator/purge], [0])
OVS_VSWITCHD_STOP(["/failed to get flags for network device 127.0.0.1/d"])
OVS_APP_EXIT_AND_WAIT([test-sflow])
AT_CHECK([[sort sflow.log | $EGREP 'LACPCOUNTERS|ERROR' | head -n 1 | sed 's/ /\
        /g']], [0], [dnl
LACPCOUNTERS
        sysID=11:22:33:44:55:66
        partnerID=00:00:00:00:00:00
        aggID=3333
        actorAdmin=0x7
        actorOper=0xbf
        partnerAdmin=0x0
        partnerOper=0x2
        LACPDUsRx=0
        markerPDUsRx=4294967295
        markerRespPDUsRx=4294967295
        unknownRx=4294967295
        illegalRx=0
        LACPDUsTx=1
        markerPDUsTx=4294967295
        markerRespPDUsTx=4294967295
])

AT_CLEANUP

AT_SETUP([ofproto-dpif - sFlow packet sampling - tunnel set])
AT_XFAIL_IF([test "$IS_WIN32" = "yes"])
OVS_VSWITCHD_START([set Bridge br0 fail-mode=standalone])

dnl set up sFlow logging
AT_CHECK([ovstest test-sflow --log-file --detach --no-chdir --pidfile 0:127.0.0.1 > sflow.log], [0], [], [ignore])
AT_CAPTURE_FILE([sflow.log])
PARSE_LISTENING_PORT([test-sflow.log], [SFLOW_PORT])
ovs-appctl time/stop

OVS_VSWITCHD_DISABLE_TUNNEL_PUSH_POP
AT_CHECK([ovs-vsctl add-port br0 gre0 -- set Interface gre0 type=gre \
                    options:remote_ip=1.1.1.1 options:key=456 ofport_request=3])
AT_CHECK([ovs-vsctl add-port br0 p1 -- set Interface p1 type=dummy ofport_request=4])

AT_CHECK([ovs-ofctl add-flow br0 action=3])

dnl enable sflow
ovs-vsctl \
   set Bridge br0 sflow=@sf -- \
   --id=@sf create sflow targets=\"127.0.0.1:$SFLOW_PORT\" agent=127.0.0.1 \
     header=128 sampling=1 polling=0

dnl introduce a packet that will be flooded to the tunnel
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(4),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.10.10.2,dst=10.10.10.1,proto=1,tos=1,ttl=128,frag=no),icmp(type=8,code=0)'])

dnl sleep long enough to get the sFlow datagram flushed out (may be delayed for up to 1 second)
for i in `seq 1 30`; do
    ovs-appctl time/warp 100
done

OVS_APP_EXIT_AND_WAIT([test-sflow])

AT_CHECK_UNQUOTED([[sort sflow.log | $EGREP 'HEADER|ERROR' | sed 's/ /\
        /g']], [0], [dnl
HEADER
        dgramSeqNo=1
        ds=127.0.0.1>2:1000
        fsSeqNo=1
        tunnel4_out_length=0
        tunnel4_out_protocol=47
        tunnel4_out_src=0.0.0.0
        tunnel4_out_dst=1.1.1.1
        tunnel4_out_src_port=0
        tunnel4_out_dst_port=0
        tunnel4_out_tcp_flags=0
        tunnel4_out_tos=1
        tunnel_out_vni=456
        in_vlan=0
        in_priority=0
        out_vlan=0
        out_priority=0
        meanSkip=1
        samplePool=1
        dropEvents=0
        in_ifindex=0
        in_format=0
        out_ifindex=1
        out_format=2
        hdr_prot=1
        pkt_len=110
        stripped=4
        hdr_len=106
        hdr=50-54-00-00-00-0A-50-54-00-00-00-09-08-00-45-01-00-5C-00-00-00-00-80-01-12-8A-0A-0A-0A-02-0A-0A-0A-01-08-00-13-FC-00-00-00-00-00-01-02-03-04-05-06-07-08-09-0A-0B-0C-0D-0E-0F-10-11-12-13-14-15-16-17-18-19-1A-1B-1C-1D-1E-1F-20-21-22-23-24-25-26-27-28-29-2A-2B-2C-2D-2E-2F-30-31-32-33-34-35-36-37-38-39-3A-3B-3C-3D-3E-3F
])

OVS_VSWITCHD_STOP(["/failed to get flags for network device 127.0.0.1/d"])
AT_CLEANUP

AT_SETUP([ofproto-dpif - sFlow packet sampling - tunnel push])
AT_XFAIL_IF([test "$IS_WIN32" = "yes"])

OVS_VSWITCHD_START([add-port br0 p0 -- set Interface p0 type=dummy ofport_request=1 options:ifindex=1010])

dnl set up sFlow logging
AT_CHECK([ovstest test-sflow --log-file --detach --no-chdir --pidfile 0:127.0.0.1 > sflow.log], [0], [], [ignore])
AT_CAPTURE_FILE([sflow.log])
PARSE_LISTENING_PORT([test-sflow.log], [SFLOW_PORT])
ovs-appctl time/stop

AT_CHECK([ovs-appctl vlog/set dpif:dbg dpif_netdev:dbg])
AT_CHECK([ovs-vsctl add-br int-br -- set bridge int-br datapath_type=dummy], [0])
AT_CHECK([ovs-vsctl -- add-port int-br t1 -- set Interface t1 type=gre \
                       options:remote_ip=1.1.2.92 options:key=456 ofport_request=4\
                    -- add-port int-br vm1 -- set Interface vm1 type=dummy \
                       options:ifindex=2011 ofport_request=5
                       ], [0])

AT_CHECK([ovs-appctl dpif/show], [0], [dnl
dummy@ovs-dummy: hit:0 missed:0
  br0:
    br0 65534/100: (dummy-internal)
    p0 1/1: (dummy: ifindex=1010)
  int-br:
    int-br 65534/2: (dummy-internal)
    t1 4/4: (gre: key=456, remote_ip=1.1.2.92)
    vm1 5/3: (dummy: ifindex=2011)
])

dnl set up route to 1.1.2.92 via br0 and action=normal
AT_CHECK([ovs-appctl netdev-dummy/ip4addr br0 1.1.2.88/24], [0], [OK
])
AT_CHECK([ovs-appctl ovs/route/add 1.1.2.92/24 br0], [0], [OK
])
AT_CHECK([ovs-ofctl add-flow br0 action=normal])

dnl Prime ARP Cache for 1.1.2.92
AT_CHECK([ovs-appctl netdev-dummy/receive p0 'recirc_id(0),in_port(1),eth(src=f8:bc:12:44:34:b6,dst=ff:ff:ff:ff:ff:ff),eth_type(0x0806),arp(sip=1.1.2.92,tip=1.1.2.88,op=2,sha=f8:bc:12:44:34:b6,tha=00:00:00:00:00:00)'])

dnl configure sflow on int-br only
ovs-vsctl \
   set Bridge int-br sflow=@sf -- \
   --id=@sf create sflow targets=\"127.0.0.1:$SFLOW_PORT\" agent=127.0.0.1 \
     header=128 sampling=1 polling=0

dnl set up route to 192.168.1.2 via br0
AT_CHECK([ovs-appctl netdev-dummy/ip4addr br0 192.168.1.1/16], [0], [OK
])
AT_CHECK([ovs-appctl ovs/route/add 192.168.0.0/16 br0], [0], [OK
])

dnl add rule for int-br to force packet onto tunnel. There is no ifindex
dnl for this port so the sFlow output will just report that it went to
dnl 1 output (out_format=2, out_ifindex=1)
AT_CHECK([ovs-ofctl add-flow int-br "actions=4"])

AT_CHECK([ovs-appctl netdev-dummy/receive vm1 'in_port(3),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=192.168.1.1,dst=192.168.2.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)'])

dnl sleep long enough to get the sFlow datagram flushed out (may be delayed for up to 1 second)
for i in `seq 1 30`; do
    ovs-appctl time/warp 100
done

OVS_APP_EXIT_AND_WAIT([test-sflow])

AT_CHECK_UNQUOTED([[sort sflow.log | $EGREP 'HEADER|ERROR' | sed 's/ /\
        /g']], [0], [dnl
HEADER
        dgramSeqNo=1
        ds=127.0.0.1>2:1000
        fsSeqNo=1
        tunnel4_out_length=0
        tunnel4_out_protocol=47
        tunnel4_out_src=1.1.2.88
        tunnel4_out_dst=1.1.2.92
        tunnel4_out_src_port=0
        tunnel4_out_dst_port=0
        tunnel4_out_tcp_flags=0
        tunnel4_out_tos=0
        tunnel_out_vni=456
        in_vlan=0
        in_priority=0
        out_vlan=0
        out_priority=0
        meanSkip=1
        samplePool=1
        dropEvents=0
        in_ifindex=2011
        in_format=0
        out_ifindex=1
        out_format=2
        hdr_prot=1
        pkt_len=110
        stripped=4
        hdr_len=106
        hdr=50-54-00-00-00-0A-50-54-00-00-00-05-08-00-45-00-00-5C-00-00-00-00-80-01-B6-4D-C0-A8-01-01-C0-A8-02-02-08-00-13-FC-00-00-00-00-00-01-02-03-04-05-06-07-08-09-0A-0B-0C-0D-0E-0F-10-11-12-13-14-15-16-17-18-19-1A-1B-1C-1D-1E-1F-20-21-22-23-24-25-26-27-28-29-2A-2B-2C-2D-2E-2F-30-31-32-33-34-35-36-37-38-39-3A-3B-3C-3D-3E-3F
])

OVS_VSWITCHD_STOP(["/failed to get flags for network device 127.0.0.1/d"])
AT_CLEANUP

AT_SETUP([ofproto-dpif - sFlow packet sampling - MPLS])
AT_XFAIL_IF([test "$IS_WIN32" = "yes"])
OVS_VSWITCHD_START
AT_CHECK([ovs-appctl vlog/set dpif:dbg dpif_netdev:dbg])
add_of_ports br0 1 2
AT_DATA([flows.txt], [dnl
table=0 dl_src=50:54:00:00:00:09 actions=push_mpls:0x8847,set_mpls_label:789,set_mpls_tc:4,set_mpls_ttl:32,2
table=0 dl_src=50:54:00:00:00:0b actions=pop_mpls:0x0800,2
])
AT_CHECK([ovs-ofctl add-flows br0 flows.txt])

dnl set up sFlow logging
AT_CHECK([ovstest test-sflow --log-file --detach --no-chdir --pidfile 0:127.0.0.1 > sflow.log], [0], [], [ignore])
AT_CAPTURE_FILE([sflow.log])
PARSE_LISTENING_PORT([test-sflow.log], [SFLOW_PORT])
ovs-appctl time/stop

dnl configure sflow
ovs-vsctl \
   set Bridge br0 sflow=@sf -- \
   --id=@sf create sflow targets=\"127.0.0.1:$SFLOW_PORT\" agent=127.0.0.1 \
     header=128 sampling=1 polling=0

AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x8847),mpls(label=11,tc=3,ttl=64,bos=1)'])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800)'])

dnl sleep long enough to get the sFlow datagram flushed out (may be delayed for up to 1 second)
for i in `seq 1 30`; do
    ovs-appctl time/warp 100
done

OVS_APP_EXIT_AND_WAIT([test-sflow])

AT_CHECK_UNQUOTED([[sort sflow.log | $EGREP 'HEADER|ERROR' | sed 's/ /\
        /g']], [0], [dnl
HEADER
        dgramSeqNo=1
        ds=127.0.0.1>2:1000
        fsSeqNo=1
        mpls_label_0=789
        mpls_tc_0=4
        mpls_ttl_0=32
        mpls_bos_0=0
        mpls_label_1=11
        mpls_tc_1=3
        mpls_ttl_1=64
        mpls_bos_1=1
        in_vlan=0
        in_priority=0
        out_vlan=0
        out_priority=0
        meanSkip=1
        samplePool=1
        dropEvents=0
        in_ifindex=0
        in_format=0
        out_ifindex=1
        out_format=2
        hdr_prot=1
        pkt_len=22
        stripped=4
        hdr_len=18
        hdr=50-54-00-00-00-0A-50-54-00-00-00-09-88-47-00-00-B7-40
HEADER
        dgramSeqNo=1
        ds=127.0.0.1>2:1000
        fsSeqNo=2
        mpls_label_0=789
        mpls_tc_0=4
        mpls_ttl_0=32
        mpls_bos_0=1
        in_vlan=0
        in_priority=0
        out_vlan=0
        out_priority=0
        meanSkip=1
        samplePool=2
        dropEvents=0
        in_ifindex=0
        in_format=0
        out_ifindex=1
        out_format=2
        hdr_prot=1
        pkt_len=38
        stripped=4
        hdr_len=34
        hdr=50-54-00-00-00-0A-50-54-00-00-00-09-08-00-45-00-00-14-00-00-00-00-00-00-BA-EB-00-00-00-00-00-00-00-00
])

OVS_VSWITCHD_STOP(["/failed to get flags for network device 127.0.0.1/d"])
AT_CLEANUP


# CHECK_NETFLOW_EXPIRATION(LOOPBACK_ADDR)
#
# Test that basic NetFlow reports flow statistics correctly:
# The initial packet of a flow are correctly accounted.
# Later packets within a flow are correctly accounted.
# Flow actions changing (in this case, due to MAC learning)
# cause a record to be sent.
m4_define([CHECK_NETFLOW_EXPIRATION],
  [OVS_VSWITCHD_START([set Bridge br0 fail-mode=standalone])
  add_of_ports br0 1 2

  ovs-appctl time/stop
  on_exit 'kill `cat test-netflow.pid`'
  AT_CHECK([ovstest test-netflow --log-file --detach --no-chdir --pidfile 0:$1 > netflow.log], [0], [], [ignore])
  AT_CAPTURE_FILE([netflow.log])
  PARSE_LISTENING_PORT([test-netflow.log], [NETFLOW_PORT])

  ovs-vsctl \
     set Bridge br0 netflow=@nf -- \
     --id=@nf create NetFlow targets=\"$1:$NETFLOW_PORT\" \
       engine_id=1 engine_type=2 active_timeout=30 add-id-to-interface=false

  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)'
      sleep 1  # ensure the order in which these two packets are processed
      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

  ovs-appctl time/warp 6000
  ovs-appctl revalidator/wait
  OVS_VSWITCHD_STOP
  OVS_APP_EXIT_AND_WAIT([test-netflow])

  AT_CHECK([test `grep "192.168.0.1 > 192.168.0.2, if 1 > 65535, 1 pkts, 106 bytes, ICMP 8:0" netflow.log | wc -l` -eq 1])

  AT_CHECK([test `grep "192.168.0.1 > 192.168.0.2, if 1 > 2, 1 pkts, 106 bytes, ICMP 8:0" netflow.log | wc -l` -eq 1])

  combined=`grep "192.168.0.2 > 192.168.0.1, if 2 > 1, 2 pkts, 212 bytes, ICMP 0:0" netflow.log | wc -l`
  separate=`grep "192.168.0.2 > 192.168.0.1, if 2 > 1, 1 pkts, 106 bytes, ICMP 0:0" netflow.log | wc -l`
  AT_CHECK([test $separate = 2 || test $combined = 1], [0])])

AT_SETUP([ofproto-dpif - NetFlow flow expiration - IPv4 collector])
CHECK_NETFLOW_EXPIRATION([127.0.0.1])
AT_CLEANUP

AT_SETUP([ofproto-dpif - NetFlow flow expiration - IPv6 collector])
AT_SKIP_IF([test $HAVE_IPV6 = no])
CHECK_NETFLOW_EXPIRATION([[[::1]]])
AT_CLEANUP

# CHECK_NETFLOW_ACTIVE_EXPIRATION(LOOPBACK_ADDR)
#
# Test that basic NetFlow reports active expirations correctly.
m4_define([CHECK_NETFLOW_ACTIVE_EXPIRATION],
  [OVS_VSWITCHD_START([set Bridge br0 fail-mode=standalone])
  add_of_ports br0 1 2

  on_exit 'kill `cat test-netflow.pid`'
  AT_CHECK([ovstest test-netflow --log-file --detach --no-chdir --pidfile 0:$1 > netflow.log], [0], [], [ignore])
  AT_CAPTURE_FILE([netflow.log])
  PARSE_LISTENING_PORT([test-netflow.log], [NETFLOW_PORT])

  ovs-vsctl \
     set Bridge br0 netflow=@nf -- \
     --id=@nf create NetFlow targets=\"$1:$NETFLOW_PORT\" \
       engine_id=1 engine_type=2 active_timeout=10 add-id-to-interface=false

  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

  ovs-appctl revalidator/wait
  OVS_VSWITCHD_STOP
  OVS_APP_EXIT_AND_WAIT([test-netflow])

  # 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
])])

AT_SETUP([ofproto-dpif - NetFlow active expiration - IPv4 collector])
CHECK_NETFLOW_ACTIVE_EXPIRATION([127.0.0.1])
AT_CLEANUP

AT_SETUP([ofproto-dpif - NetFlow active expiration - IPv6 collector])
AT_SKIP_IF([test $HAVE_IPV6 = no])
CHECK_NETFLOW_ACTIVE_EXPIRATION([[[::1]]])
AT_CLEANUP

dnl In the absence of an IPFIX collector to verify protocol correctness, simply
dnl configure bridge IPFIX and ensure that sample action generation works at the
dnl datapath level.
AT_SETUP([ofproto-dpif - Bridge IPFIX sanity check])
OVS_VSWITCHD_START
add_of_ports br0 1 2 3

dnl Sample every packet using bridge-based sampling.
AT_CHECK([ovs-vsctl -- set bridge br0 ipfix=@fix -- \
                    --id=@fix create ipfix targets=\"127.0.0.1:4739\" \
                              sampling=1], [0], [ignore])

dnl Send some packets that should be sampled.
for i in `seq 1 3`; do
    AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800)'])
done
AT_CHECK([ovs-appctl dpctl/dump-flows | sed 's/.*\(packets:\)/\1/' | sed 's/used:[[0-9]].[[0-9]]*s/used:0.001s/'], [0], [dnl
flow-dump from the main thread:
packets:2, bytes:68, used:0.001s, actions:userspace(pid=0,ipfix(output_port=4294967295))
])

AT_CHECK([ovs-appctl revalidator/purge])

dnl Check sample is performed even if only one of the ports is present.
AT_DATA([flows.txt], [dnl
table=0,in_port=3,tcp actions=load:0xffff->NXM_OF_IN_PORT[],ct(zone=1,table=1)
table=1,tcp, actions=output:2
])
AT_CHECK([ovs-ofctl add-flows br0 flows.txt])

for i in `seq 1 3`; do
    AT_CHECK([ovs-appctl netdev-dummy/receive p3 'in_port(3),eth(src=50:54:00:00:00:08,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=192.168.0.2,dst=192.168.0.1,proto=6,tos=0,ttl=64,frag=no)'])
done

AT_CHECK([ovs-appctl dpctl/dump-flows | sed 's/.*\(packets:\)/\1/' | sed 's/used:[[0-9]].[[0-9]]*s/used:0.001s/' | sort], [0], [dnl
flow-dump from the main thread:
packets:2, bytes:236, used:0.001s, actions:userspace(pid=0,ipfix(output_port=2)),2
packets:2, bytes:236, used:0.001s, actions:userspace(pid=0,ipfix(output_port=4294967295)),ct(zone=1),recirc(0x1)
])

AT_CHECK([ovs-ofctl del-flows br0 in_port=3])
AT_CHECK([ovs-ofctl del-flows br0 table=1])

AT_CHECK([ovs-appctl revalidator/purge])
dnl
dnl Add a slowpath meter. The userspace action should be metered.
AT_CHECK([ovs-ofctl -O OpenFlow13 add-meter br0 'meter=slowpath pktps burst stats bands=type=drop rate=3 burst_size=1'])

dnl Send some packets that should be sampled and metered.
for i in `seq 1 3`; do
    AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800)'])
done
AT_CHECK([ovs-appctl dpctl/dump-flows | sed 's/.*\(packets:\)/\1/' | sed 's/used:[[0-9]].[[0-9]]*s/used:0.001s/'], [0], [dnl
flow-dump from the main thread:
packets:2, bytes:68, used:0.001s, actions:sample(sample=100.0%,actions(meter(0),userspace(pid=0,ipfix(output_port=4294967295))))
])

dnl Remove the IPFIX configuration.
AT_CHECK([ovs-vsctl clear bridge br0 ipfix])
AT_CHECK([ovs-appctl revalidator/purge])

dnl Send some more packets, to ensure that these are not sampled.
for i in `seq 1 3`; do
    AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800)'])
done
AT_CHECK([ovs-appctl dpctl/dump-flows | sed 's/.*\(packets:\)/\1/' | sed 's/used:[[0-9]].[[0-9]]*s/used:0.001s/'], [0], [dnl
flow-dump from the main thread:
packets:2, bytes:68, used:0.001s, actions:drop
])

OVS_VSWITCHD_STOP(["/sending to collector failed/d"])
AT_CLEANUP

dnl Bridge IPFIX statistics check
AT_SETUP([ofproto-dpif - Bridge IPFIX statistics check])
OVS_VSWITCHD_START
add_of_ports br0 1 2

dnl Negative test check.
AT_CHECK([ovs-ofctl dump-ipfix-bridge br0], [0], [dnl
OFPT_ERROR (xid=0x2): NXST_NOT_CONFIGURED
NXST_IPFIX_BRIDGE request (xid=0x2):
])

dnl Sample every packet using bridge-based sampling.
AT_CHECK([ovs-vsctl -- set bridge br0 ipfix=@fix -- \
                    --id=@fix create ipfix targets=\"127.0.0.1:4739\" \
                              sampling=1], [0], [ignore])

dnl Send some packets that should be sampled.
for i in `seq 1 20`; do
    AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800)'])
done

dnl There are 4 extra IPFIX template packets.
AT_CHECK([ovs-ofctl dump-ipfix-bridge br0 | sed 's/tx pkts=[[0-9]]*/tx pkts=24/' | sed 's/tx errs=[[0-9]]*/tx errs=0/'], [0], [dnl
NXST_IPFIX_BRIDGE reply (xid=0x2):
  bridge ipfix: flows=20, current flows=0, sampled pkts=20, ipv4 ok=0, ipv6 ok=0, tx pkts=24
                pkts errs=20, ipv4 errs=20, ipv6 errs=0, tx errs=0
])

dnl Remove the IPFIX configuration.
AT_CHECK([ovs-vsctl clear bridge br0 ipfix])
AT_CHECK([ovs-appctl revalidator/purge])

dnl Send some more packets, to ensure that these are not sampled.
for i in `seq 1 2`; do
    AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800)'])
done
AT_CHECK([ovs-ofctl dump-ipfix-bridge br0], [0], [dnl
OFPT_ERROR (xid=0x2): NXST_NOT_CONFIGURED
NXST_IPFIX_BRIDGE request (xid=0x2):
])

OVS_VSWITCHD_STOP(["/sending to collector failed/d"])
AT_CLEANUP

dnl Flow IPFIX sanity check
AT_SETUP([ofproto-dpif - Flow IPFIX sanity check])
OVS_VSWITCHD_START
add_of_ports br0 1 2

# Check for regression against a bug where an invalid target caused an
# assertion failure and a crash.
AT_CHECK([ovs-vsctl -- --id=@br0 get Bridge br0 \
                    -- --id=@ipfix create IPFIX targets=\"xyzzy\" \
                    -- --id=@cs create Flow_Sample_Collector_Set id=0 bridge=@br0 ipfix=@ipfix],
         [0], [ignore])

AT_CHECK([ovs-vsctl -- --id=@br0 get Bridge br0 \
                    -- --id=@ipfix create IPFIX targets=\"127.0.0.1:4739\" \
                    -- --id=@cs create Flow_Sample_Collector_Set id=1 bridge=@br0 ipfix=@ipfix],
         [0], [ignore])

AT_DATA([flows.txt], [dnl
in_port=1, actions=sample(probability=65535,collector_set_id=1),output:2
])

AT_CHECK([ovs-ofctl add-flows br0 flows.txt], [0], [ignore])

dnl Send some packets that should be sampled.
for i in `seq 1 3`; do
    AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800)'])
done
AT_CHECK([ovs-appctl dpctl/dump-flows | sed 's/.*\(packets:\)/\1/' | sed 's/used:[[0-9]].[[0-9]]*s/used:0.001s/'], [0], [dnl
flow-dump from the main thread:
packets:2, bytes:68, used:0.001s, actions:userspace(pid=0,flow_sample(probability=65535,collector_set_id=1,obs_domain_id=0,obs_point_id=0,output_port=4294967295)),2
])

dnl Remove the flow which contains sample action.
AT_CHECK([ovs-ofctl del-flows br0 in_port=1], [0], [ignore])
AT_CHECK([ovs-appctl revalidator/purge])

dnl Send some more packets, to ensure that these are not sampled.
for i in `seq 1 3`; do
    AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800)'])
done
AT_CHECK([ovs-appctl dpctl/dump-flows | sed 's/.*\(packets:\)/\1/' | sed 's/used:[[0-9]].[[0-9]]*s/used:0.001s/'], [0], [dnl
flow-dump from the main thread:
packets:2, bytes:68, used:0.001s, actions:drop
])

OVS_VSWITCHD_STOP(["/sending to collector failed/d
/xyzzy/d
/no collectors/d"])
AT_CLEANUP

dnl Flow IPFIX sanity check for tunnel set
AT_SETUP([ofproto-dpif - Flow IPFIX sanity check - tunnel set])
OVS_VSWITCHD_START([add-port br0 p1 -- set Interface p1 type=gre \
                    options:remote_ip=1.1.1.1 options:local_ip=2.2.2.2 \
                    options:key=5 ofport_request=1\
                    -- add-port br0 p2 -- set Interface p2 type=stt \
                    options:remote_ip=1.1.1.2 options:local_ip=2.2.2.3 \
                    options:key=6 ofport_request=2\
                    -- add-port br0 p3 -- set Interface p3 type=dummy \
                    ofport_request=3 \
                    -- --id=@br0 get Bridge br0 \
                    -- --id=@ipfix create IPFIX targets=\"127.0.0.1:4739\" \
                    -- --id=@cs create Flow_Sample_Collector_Set id=1 bridge=@br0 ipfix=@ipfix],
                   [<0>
<1>
])

OVS_VSWITCHD_DISABLE_TUNNEL_PUSH_POP

dnl Add openflow sample action without sampling_port.
AT_DATA([flows.txt], [dnl
in_port=3, actions=sample(probability=65535,collector_set_id=1),output:1
])
AT_CHECK([ovs-ofctl add-flows br0 flows.txt], [0], [ignore])

AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(3),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.10.10.2,dst=10.10.10.1,proto=1,tos=1,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])
AT_CHECK([tail -1 stdout], [0], [dnl
Datapath actions: userspace(pid=0,flow_sample(probability=65535,collector_set_id=1,obs_domain_id=0,obs_point_id=0,output_port=4294967295)),set(tunnel(tun_id=0x5,src=2.2.2.2,dst=1.1.1.1,tos=0x1,ttl=64,flags(df|key))),1
])

dnl Remove the flow which contains sample action.
AT_CHECK([ovs-ofctl del-flows br0 in_port=3], [0], [ignore])
AT_CHECK([ovs-appctl revalidator/purge])

dnl Add openflow sample action with sampling_port which is
dnl equal to output port.
AT_DATA([flows2.txt], [dnl
in_port=3, actions=sample(probability=65535,collector_set_id=1,sampling_port=1),output:1
])
AT_CHECK([ovs-ofctl add-flows br0 flows2.txt], [0], [ignore])

AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(3),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.10.10.2,dst=10.10.10.1,proto=1,tos=1,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])
dnl Make sure flow sample action in datapath is behind set tunnel
dnl action at egress point of tunnel port.
AT_CHECK([tail -1 stdout], [0], [dnl
Datapath actions: set(tunnel(tun_id=0x5,src=2.2.2.2,dst=1.1.1.1,tos=0x1,ttl=64,flags(df|key))),userspace(pid=0,flow_sample(probability=65535,collector_set_id=1,obs_domain_id=0,obs_point_id=0,output_port=1),tunnel_out_port=1),1
])

dnl Remove the flow which contains sample action.
AT_CHECK([ovs-ofctl del-flows br0 in_port=3], [0], [ignore])
AT_CHECK([ovs-appctl revalidator/purge])

dnl Add a rule with two sample actions and each sample action
dnl has a sampling_port
AT_DATA([flows3.txt], [dnl
in_port=3, actions=sample(probability=65535,collector_set_id=1,sampling_port=1),output:1,sample(probability=65535,collector_set_id=1,sampling_port=2),output:2
])
AT_CHECK([ovs-ofctl add-flows br0 flows3.txt], [0], [ignore])

AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(3),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.10.10.2,dst=10.10.10.1,proto=1,tos=1,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])
dnl Make sure flow sample action in datapath is behind set tunnel
dnl action at egress point of tunnel port.
AT_CHECK([tail -1 stdout], [0], [dnl
Datapath actions: set(tunnel(tun_id=0x5,src=2.2.2.2,dst=1.1.1.1,tos=0x1,ttl=64,flags(df|key))),userspace(pid=0,flow_sample(probability=65535,collector_set_id=1,obs_domain_id=0,obs_point_id=0,output_port=1),tunnel_out_port=1),1,set(tunnel(tun_id=0x6,src=2.2.2.3,dst=1.1.1.2,tos=0x1,ttl=64,tp_dst=7471,flags(df|key))),userspace(pid=0,flow_sample(probability=65535,collector_set_id=1,obs_domain_id=0,obs_point_id=0,output_port=7471),tunnel_out_port=7471),7471
])

dnl Remove the flow which contains sample action.
AT_CHECK([ovs-ofctl del-flows br0 in_port=3], [0], [ignore])
AT_CHECK([ovs-vsctl destroy Flow_Sample_Collector_Set 1], [0], [ignore])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - clone action])
OVS_VSWITCHD_START
add_of_ports br0 1 2 3 4

dnl Reversible open flow clone actions, no datapath clone action should be generated.
AT_DATA([flows.txt], [dnl
in_port=1, ip, actions=clone(set_field:192.168.3.3->ip_src),clone(set_field:192.168.4.4->ip_dst,output:2),clone(mod_dl_src:80:81:81:81:81:81,set_field:192.168.5.5->ip_dst,output:3),output:4
])
AT_CHECK([ovs-ofctl add-flows br0 flows.txt], [0], [ignore])

AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.10.10.2,dst=10.10.10.1,proto=1,tos=1,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])

AT_CHECK([tail -1 stdout], [0], [dnl
Datapath actions: set(ipv4(dst=192.168.4.4)),2,set(eth(src=80:81:81:81:81:81)),set(ipv4(dst=192.168.5.5)),3,set(eth(src=50:54:00:00:00:09)),set(ipv4(dst=10.10.10.1)),4
])

dnl Test flow xlate openflow clone action without using datapath clone action.
AT_CHECK([ovs-appctl dpif/set-dp-features br0 clone false], [0], [ignore])

AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.10.10.2,dst=10.10.10.1,proto=1,tos=1,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])

AT_CHECK([tail -1 stdout], [0], [dnl
Datapath actions: set(ipv4(dst=192.168.4.4)),2,set(eth(src=80:81:81:81:81:81)),set(ipv4(dst=192.168.5.5)),3,set(eth(src=50:54:00:00:00:09)),set(ipv4(dst=10.10.10.1)),4
])

AT_CHECK([ovs-appctl dpif/set-dp-features br0 sample_nesting 2], [0], [ignore])
AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.10.10.2,dst=10.10.10.1,proto=1,tos=1,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])

AT_CHECK([tail -1 stdout], [0], [dnl
Datapath actions: set(ipv4(dst=192.168.4.4)),2,set(eth(src=80:81:81:81:81:81)),set(ipv4(dst=192.168.5.5)),3,set(eth(src=50:54:00:00:00:09)),set(ipv4(dst=10.10.10.1)),4
])

dnl Mixing reversible and irreversible open flow clone actions. Datapath clone action
dnl should be generated when necessary.

dnl Restore the datapath support level.
AT_CHECK([ovs-appctl dpif/set-dp-features br0 clone true], [0], [])
AT_CHECK([ovs-appctl dpif/set-dp-features br0 sample_nesting 10], [0], [])

AT_DATA([flows.txt], [dnl
in_port=1, ip, actions=clone(set_field:192.168.3.3->ip_src),clone(set_field:192.168.4.4->ip_dst,output:2),clone(ct(commit),output:3),output:4
])
AT_CHECK([ovs-ofctl add-flows br0 flows.txt], [0], [ignore])

AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.10.10.2,dst=10.10.10.1,proto=1,tos=1,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])

AT_CHECK([tail -1 stdout], [0], [dnl
Datapath actions: set(ipv4(dst=192.168.4.4)),2,set(ipv4(dst=10.10.10.1)),clone(ct(commit),3),4
])

AT_CHECK([ovs-appctl dpif/set-dp-features br0 clone false], [0], [ignore])

AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.10.10.2,dst=10.10.10.1,proto=1,tos=1,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])

AT_CHECK([tail -1 stdout], [0], [dnl
Datapath actions: set(ipv4(dst=192.168.4.4)),2,set(ipv4(dst=10.10.10.1)),sample(sample=100.0%,actions(ct(commit),3)),4
])

AT_CHECK([ovs-appctl dpif/set-dp-features br0 sample_nesting 2], [0], [ignore])
AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.10.10.2,dst=10.10.10.1,proto=1,tos=1,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])

AT_CHECK([tail -1 stdout], [0], [dnl
Datapath actions: set(ipv4(dst=192.168.4.4)),2,set(ipv4(dst=10.10.10.1)),4
])
AT_CHECK([grep "Failed to compose clone action" stdout], [0], [ignore])

OVS_VSWITCHD_STOP
AT_CLEANUP

dnl Flow based IPFIX statistics check
AT_SETUP([ofproto-dpif - Flow IPFIX statistics check])
OVS_VSWITCHD_START
add_of_ports br0 1 2

dnl Negative test check.
AT_CHECK([ovs-ofctl dump-ipfix-flow br0], [0], [dnl
OFPT_ERROR (xid=0x2): NXST_NOT_CONFIGURED
NXST_IPFIX_FLOW request (xid=0x2):
])

AT_CHECK([ovs-vsctl -- --id=@br0 get Bridge br0 \
                    -- --id=@ipfix create IPFIX targets=\"127.0.0.1:4739\" \
                    -- --id=@cs create Flow_Sample_Collector_Set id=1 bridge=@br0 ipfix=@ipfix],
         [0], [ignore])

AT_DATA([flows.txt], [dnl
in_port=1, actions=sample(probability=65535,collector_set_id=1),output:2
])

AT_CHECK([ovs-ofctl add-flows br0 flows.txt], [0], [ignore])

dnl Send some packets that should be sampled.
for i in `seq 1 20`; do
    AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800)'])
done

dnl There are 4 extra IPFIX template packets.
AT_CHECK([ovs-ofctl dump-ipfix-flow br0 | sed 's/tx pkts=[[0-9]]*/tx pkts=24/' | sed 's/tx errs=[[0-9]]*/tx errs=0/'], [0], [dnl
NXST_IPFIX_FLOW reply (xid=0x2): 1 ids
  id   1: flows=20, current flows=0, sampled pkts=20, ipv4 ok=0, ipv6 ok=0, tx pkts=24
          pkts errs=20, ipv4 errs=20, ipv6 errs=0, tx errs=0
])

dnl Remove the flow which contains sample action.
AT_CHECK([ovs-ofctl del-flows br0 in_port=1], [0], [ignore])
AT_CHECK([ovs-vsctl destroy Flow_Sample_Collector_Set 1], [0], [ignore])
AT_CHECK([ovs-appctl revalidator/purge])

dnl Send some more packets, to ensure that these are not sampled.
for i in `seq 1 3`; do
    AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800)'])
done
AT_CHECK([ovs-ofctl dump-ipfix-flow br0], [0], [dnl
OFPT_ERROR (xid=0x2): NXST_NOT_CONFIGURED
NXST_IPFIX_FLOW request (xid=0x2):
])

OVS_VSWITCHD_STOP(["/sending to collector failed/d"])
AT_CLEANUP

AT_SETUP([ofproto-dpif - flow stats])
OVS_VSWITCHD_START
AT_CHECK([ovs-ofctl add-flow br0 "ip,actions=NORMAL"])
AT_CHECK([ovs-ofctl add-flow br0 "icmp,actions=NORMAL"])

ovs-appctl time/stop

for i in `seq 1 10`; do
    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)'
done

AT_CHECK([ovs-appctl time/warp 1000], [0], [ignore])
AT_CHECK([ovs-appctl revalidator/purge], [0])
AT_CHECK([ovs-ofctl dump-flows br0], [0], [stdout])
AT_CHECK([strip_xids < stdout | sed -n 's/duration=[[0-9]]*\.[[0-9]]*s/duration=0.0s/p' | sort], [0], [dnl
 cookie=0x0, duration=0.0s, table=0, n_packets=0, n_bytes=0, idle_age=1, icmp actions=NORMAL
 cookie=0x0, duration=0.0s, table=0, n_packets=10, n_bytes=1180, idle_age=1, ip actions=NORMAL
])
OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - flow stats reset_counts])
OVS_VSWITCHD_START
flow="ip,actions=NORMAL"

ovs-appctl time/stop

AT_CHECK([ovs-ofctl add-flow br0 $flow])

warp_and_dump_NXM () {
    AT_CHECK([ovs-appctl time/warp 1000], [0], [ignore])
    AT_CHECK([ovs-appctl revalidator/purge], [0])

    AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br0], [0], [stdout])
    if [[ $5 -gt 0 ]]; then
        expected=" cookie=0x0, duration=$1s, table=0, n_packets=$2, n_bytes=$3, idle_age=$4, hard_age=$5, ip actions=NORMAL"
    else
        expected=" cookie=0x0, duration=$1s, table=0, n_packets=$2, n_bytes=$3, idle_age=$4, ip actions=NORMAL"
    fi
    AT_CHECK_UNQUOTED([strip_xids < stdout | sed -n 's/duration=\([[0-9]]*\)\.*[[0-9]]*s/duration=\1s/p' | sort], [0], [dnl
$expected
])
}

warp_and_dump_OF () {
    AT_CHECK([ovs-appctl time/warp 1000], [0], [ignore])
    AT_CHECK([ovs-appctl revalidator/purge], [0])

    AT_CHECK_UNQUOTED([ovs-ofctl -O OpenFlow$1 dump-flows br0], [0], [stdout])
    if [[ $1 -lt 13 -o "$5X" = "X" ]]; then
        expected=" cookie=0x0, duration=$2s, table=0, n_packets=$3, n_bytes=$4, ip actions=NORMAL"
    else
        expected=" cookie=0x0, duration=$2s, table=0, n_packets=$3, n_bytes=$4, $5 ip actions=NORMAL"
    fi
    AT_CHECK_UNQUOTED([strip_xids < stdout | sed -n 's/duration=\([[0-9]]*\)\.*[[0-9]]*s/duration=\1s/p' | sort], [0], [dnl
$expected
])
}

send_packet () {
    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)'
}

# OpenFlow 1.0, implicit reset_counts
send_packet
warp_and_dump_NXM   1 1 118 1
AT_CHECK_UNQUOTED([ovs-ofctl -O OpenFlow10 add-flow br0 $flow])
# add-flow resets duration and counts,
# but idle age is inherited from the old flow
warp_and_dump_NXM   1 0 0  2

send_packet
warp_and_dump_NXM   2 1 118 1
AT_CHECK_UNQUOTED([ovs-ofctl -O OpenFlow10 mod-flows br0 $flow])
# mod-flows resets hard_age, but not counts
# but duration and idle_age is inherited from the old flow
warp_and_dump_NXM   3 1 118  2 1

# OpenFlow 1.1, implicit reset_counts
send_packet
warp_and_dump_OF 11 4 2 236
AT_CHECK_UNQUOTED([ovs-ofctl -O OpenFlow11 add-flow br0 $flow])
# add-flow resets duration and counts,
# but idle age is inherited from the old flow
warp_and_dump_NXM   1 0 0  2
warp_and_dump_OF 11 2 0 0

send_packet
warp_and_dump_OF 11 3 1 118
AT_CHECK_UNQUOTED([ovs-ofctl -O OpenFlow11 mod-flows br0 $flow])
# mod-flows resets hard_age, but not counts
# but duration and idle_age is inherited from the old flow
warp_and_dump_NXM   4 1 118  2 1
warp_and_dump_OF 11 5 1 118

# OpenFlow 1.2, explicit reset_counts
send_packet
warp_and_dump_OF 12 6 2 236
AT_CHECK_UNQUOTED([ovs-ofctl -O OpenFlow12 add-flow br0 $flow])
# add-flow without flags resets duration, but not counts,
# idle age is inherited from the old flow
warp_and_dump_NXM   1 2 236  2
warp_and_dump_OF 12 2 2 236

send_packet
warp_and_dump_OF 12 3 3 354
AT_CHECK_UNQUOTED([ovs-ofctl -O OpenFlow12 mod-flows br0 $flow])
# mod-flows without flags does not reset duration nor counts,
# idle age is inherited from the old flow
warp_and_dump_NXM   4 3 354  2 1
warp_and_dump_OF 12 5 3 354

send_packet
warp_and_dump_OF 12 6 4 472
AT_CHECK_UNQUOTED([ovs-ofctl -O OpenFlow12 add-flow br0 reset_counts,$flow])
# add-flow with reset_counts resets both duration and counts,
# idle age is inherited from the old flow
warp_and_dump_NXM   1 0 0  2
warp_and_dump_OF 12 2 0 0

send_packet
warp_and_dump_OF 12 3 1 118
AT_CHECK_UNQUOTED([ovs-ofctl -O OpenFlow12 mod-flows br0 reset_counts,$flow])
# mod-flows with reset_counts resets counts, but not duration,
# idle age is inherited from the old flow
warp_and_dump_NXM   4 0 0  2 1
warp_and_dump_OF 12 5 0 0

# OpenFlow > 1.3, explicit reset_counts
flow_mods_reset_counts () {
    # Reset to a known state
    AT_CHECK([ovs-ofctl add-flow br0 $flow])

    send_packet
    warp_and_dump_OF $1 1 1 118 reset_counts
    AT_CHECK_UNQUOTED([ovs-ofctl -O OpenFlow$1 add-flow br0 $flow])
    # add-flow without flags resets duration, but not counts,
    # idle age is inherited from the old flow
    warp_and_dump_NXM   1 1 118  2
    warp_and_dump_OF $1 2 1 118

    send_packet
    warp_and_dump_OF $1 3 2 236
    AT_CHECK_UNQUOTED([ovs-ofctl -O OpenFlow$1 mod-flows br0 $flow])
    # mod-flows without flags does not reset duration nor counts,
    # idle age is inherited from the old flow
    warp_and_dump_NXM   4 2 236  2 1
    warp_and_dump_OF $1 5 2 236

    send_packet
    warp_and_dump_OF $1 6 3 354
    AT_CHECK_UNQUOTED([ovs-ofctl -O OpenFlow$1 add-flow br0 reset_counts,$flow])
    # add-flow with reset_counts resets both duration and counts,
    # idle age is inherited from the old flow
    warp_and_dump_NXM   1 0 0  2
    warp_and_dump_OF $1 2 0 0 reset_counts

    send_packet
    warp_and_dump_OF $1 3 1 118 reset_counts
    AT_CHECK_UNQUOTED([ovs-ofctl -O OpenFlow$1 mod-flows br0 reset_counts,$flow])
    # mod-flows with reset_counts resets counts, but not duration,
    # idle age is inherited from the old flow
    warp_and_dump_NXM   4 0 0  2 1
    warp_and_dump_OF $1 5 0 0 reset_counts

    # Modify flow having reset_counts flag without reset_counts
    send_packet
    warp_and_dump_OF $1 6 1 118 reset_counts
    AT_CHECK_UNQUOTED([ovs-ofctl -O OpenFlow$1 mod-flows br0 $flow])
    warp_and_dump_NXM   7 1 118  2 1
    warp_and_dump_OF $1 8 1 118 reset_counts

    # Add flow having reset_counts flag without reset_counts
    send_packet
    warp_and_dump_OF $1 9 2 236 reset_counts
    AT_CHECK_UNQUOTED([ovs-ofctl -O OpenFlow$1 add-flow br0 $flow])
    warp_and_dump_NXM   1 2 236  2
    warp_and_dump_OF $1 2 2 236

    # Modify flow w/o reset_counts flag with a flow_mod having reset_counts
    send_packet
    warp_and_dump_OF $1 3 3 354
    AT_CHECK_UNQUOTED([ovs-ofctl -O OpenFlow$1 mod-flows br0 reset_counts,$flow])
    warp_and_dump_NXM   4 0 0  2 1
    warp_and_dump_OF $1 5 0 0
}

# OpenFlow versions >= 1.3 should behave the same way
flow_mods_reset_counts 13
flow_mods_reset_counts 14

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - flow stats reset_counts OpenFlow1.5])
OVS_VSWITCHD_START
flow="ip,actions=NORMAL"

ovs-appctl time/stop

AT_CHECK([ovs-ofctl add-flow br0 $flow])

warp_and_dump_OF () {
    AT_CHECK([ovs-appctl time/warp 1000], [0], [ignore])
    AT_CHECK([ovs-appctl revalidator/purge], [0])

    AT_CHECK_UNQUOTED([ovs-ofctl -O OpenFlow$1 dump-flows br0 ], [0], [stdout])
    if [[ "$6X" = "X" ]]; then
        expected=" cookie=0x0, duration=$2s, table=0, n_packets=$3, n_bytes=$4, idle_age=$5, ip actions=NORMAL"
    else
        expected=" cookie=0x0, duration=$2s, table=0, n_packets=$3, n_bytes=$4, $6 idle_age=$5, ip actions=NORMAL"
    fi
     AT_CHECK_UNQUOTED([strip_xids < stdout | sed -n 's/duration=\([[0-9]]*\)\.*[[0-9]]*s/duration=\1s/p' | sort], [0], [dnl
$expected
])
}

send_packet () {
    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)'
}

# OpenFlow 1.5, explicit reset_counts
flow_mods_reset_counts () {
    # Reset to a known state
    AT_CHECK([ovs-ofctl add-flow br0 $flow])

    send_packet
    warp_and_dump_OF $1 1 1 118 1 reset_counts
    AT_CHECK_UNQUOTED([ovs-ofctl -O OpenFlow$1 add-flow br0 $flow])
    # add-flow without flags resets duration, but not counts,
    # idle age is inherited from the old flow
    warp_and_dump_OF $1 1 1 118 2

    send_packet
    warp_and_dump_OF $1 2 2 236 1
    AT_CHECK_UNQUOTED([ovs-ofctl -O OpenFlow$1 mod-flows br0 $flow])
    # mod-flows without flags does not reset duration nor counts,
    # idle age is inherited from the old flow
    warp_and_dump_OF $1 3 2 236 2

    send_packet
    warp_and_dump_OF $1 4 3 354 1
    AT_CHECK_UNQUOTED([ovs-ofctl -O OpenFlow$1 add-flow br0 reset_counts,$flow])
    # add-flow with reset_counts resets both duration and counts,
    # idle age is inherited from the old flow
    warp_and_dump_OF $1 1 0 0 2 reset_counts

    send_packet
    warp_and_dump_OF $1 2 1 118 1 reset_counts
    AT_CHECK_UNQUOTED([ovs-ofctl -O OpenFlow$1 mod-flows br0 reset_counts,$flow])
    # mod-flows with reset_counts resets counts, but not duration,
    # idle age is inherited from the old flow
    warp_and_dump_OF $1 3 0 0 2 reset_counts

    # Modify flow having reset_counts flag without reset_counts
    send_packet
    warp_and_dump_OF $1 4 1 118 1 reset_counts
    AT_CHECK_UNQUOTED([ovs-ofctl -O OpenFlow$1 mod-flows br0 $flow])
    warp_and_dump_OF $1 5 1 118 2 reset_counts

    # Add flow having reset_counts flag without reset_counts
    send_packet
    warp_and_dump_OF $1 6 2 236 1 reset_counts
    AT_CHECK_UNQUOTED([ovs-ofctl -O OpenFlow$1 add-flow br0 $flow])
    warp_and_dump_OF $1 1 2 236 2

    # Modify flow w/o reset_counts flag with a flow_mod having reset_counts
    send_packet
    warp_and_dump_OF $1 2 3 354 1
    AT_CHECK_UNQUOTED([ovs-ofctl -O OpenFlow$1 mod-flows br0 reset_counts,$flow])
    warp_and_dump_OF $1 3 0 0 2
}

# OpenFlow versions >= 1.3 should behave the same way
flow_mods_reset_counts 15

OVS_VSWITCHD_STOP
AT_CLEANUP


AT_SETUP([ofproto-dpif - flow stats, set-n-threads])
OVS_VSWITCHD_START
AT_CHECK([ovs-ofctl add-flow br0 "ip,actions=NORMAL"])
AT_CHECK([ovs-ofctl add-flow br0 "icmp,actions=NORMAL"])

ovs-appctl time/stop

for i in `seq 1 10`; do
    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)'
done

ovs-appctl time/warp 100
AT_CHECK([ovs-vsctl set Open_vSwitch . other-config:n-revalidator-threads=2])
ovs-appctl time/warp 1000

AT_CHECK([ovs-ofctl dump-flows br0], [0], [stdout])
AT_CHECK([strip_xids < stdout | sed -n 's/duration=[[0-9]]*\.[[0-9]]*s/duration=0.0s/p' | sort], [0], [dnl
 cookie=0x0, duration=0.0s, table=0, n_packets=0, n_bytes=0, idle_age=1, icmp actions=NORMAL
 cookie=0x0, duration=0.0s, table=0, n_packets=10, n_bytes=1180, idle_age=1, ip actions=NORMAL
])
OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - 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

ovs-appctl time/stop
# 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 3000 1000
sleep 1
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
ovs-appctl time/stop
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])
AT_CHECK([ovs-appctl time/warp 1000 && ovs-appctl time/warp 1000], [0], [warped
warped
])
AT_CHECK([ovs-appctl revalidator/purge], [0])
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])
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], [], [],
                   [--dummy-numa="0,0,0,0,1,1,1,1"])
add_pmd_of_ports br0 1 2
add_of_ports br1 3

AT_CHECK([ovs-appctl dpif/show | sed 's/\(dummy-pmd: \).*)/\1<cleared>)/'], [0], [dnl
dummy@ovs-dummy: hit:0 missed:0
  br0:
    br0 65534/100: (dummy-internal)
    p1 1/1: (dummy-pmd: <cleared>)
    p2 2/2: (dummy-pmd: <cleared>)
  br1:
    br1 65534/101: (dummy-internal)
    p3 3/3: (dummy)
])
OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - ovs-appctl dpif/dump-flows])
# bump max-idle to avoid the flows being reclaimed behind us
OVS_VSWITCHD_START([add-br br1 -- \
                    set bridge br1 datapath-type=dummy fail-mode=secure -- \
                    set Open_vSwitch . other_config:max-idle=10000], [], [],
                    [--dummy-numa="0,0,0,0,1,1,1,1"])
add_of_ports br0 1
add_pmd_of_ports br0 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)'])
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)'])
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)'])
ovs-appctl revalidator/wait
AT_CHECK([ovs-appctl dpif/dump-flows br0 | strip_ufid | strip_used | sort], [0], [dnl
recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:0, bytes:0, used:never, actions:drop
recirc_id(0),in_port(2),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:0, bytes:0, used:never, actions:drop
])

AT_CHECK([ovs-appctl dpif/dump-flows br1 | strip_ufid | strip_used | sort], [0], [dnl
recirc_id(0),in_port(3),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:0, bytes:0, used:never, actions:drop
])

AT_CHECK([ovs-appctl dpif/dump-flows -m br0 | strip_ufid | strip_used | sort], [0], [dnl
skb_priority(0/0),skb_mark(0/0),ct_state(0/0),ct_zone(0/0),ct_mark(0/0),ct_label(0/0),recirc_id(0),dp_hash(0/0),in_port(p1),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:05/00:00:00:00:00:00,dst=50:54:00:00:00:07/00:00:00:00:00:00),eth_type(0x0800),ipv4(src=192.168.0.1/0.0.0.0,dst=192.168.0.2/0.0.0.0,proto=1/0,tos=0/0,ttl=64/0,frag=no),icmp(type=8/0,code=0/0), packets:0, bytes:0, used:never, actions:drop
skb_priority(0/0),skb_mark(0/0),ct_state(0/0),ct_zone(0/0),ct_mark(0/0),ct_label(0/0),recirc_id(0),dp_hash(0/0),in_port(p2),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:07/00:00:00:00:00:00,dst=50:54:00:00:00:05/00:00:00:00:00:00),eth_type(0x0800),ipv4(src=192.168.0.2/0.0.0.0,dst=192.168.0.1/0.0.0.0,proto=1/0,tos=0/0,ttl=64/0,frag=no),icmp(type=0/0,code=0/0), packets:0, bytes:0, used:never, actions:drop
])

AT_CHECK([ovs-appctl dpif/dump-flows -m br1 | strip_ufid | strip_used | sort], [0], [dnl
skb_priority(0/0),skb_mark(0/0),ct_state(0/0),ct_zone(0/0),ct_mark(0/0),ct_label(0/0),recirc_id(0),dp_hash(0/0),in_port(p3),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:09/00:00:00:00:00:00,dst=50:54:00:00:00:0a/00:00:00:00:00:00),eth_type(0x0800),ipv4(src=10.0.0.2/0.0.0.0,dst=10.0.0.1/0.0.0.0,proto=1/0,tos=0/0,ttl=64/0,frag=no),icmp(type=8/0,code=0/0), packets:0, bytes:0, used:never, actions:drop
])

OVS_VSWITCHD_STOP
AT_CLEANUP

m4_define([OFPROTO_DPIF_GET_FLOW],
  [AT_SETUP([ofproto-dpif - ovs-appctl dpif/get-flow$1])

   OVS_VSWITCHD_START([add-br br1 -- \
                       set bridge br1 datapath-type=dummy fail-mode=secure -- \
                       set Open_vSwitch . other_config:max-idle=10000], [], [],
                       [m4_if([$1], [], [], [--dummy-numa="0,0,0,0,1,1,1,1"])])

   func=`printf '%s_' "$1" | cut -c 4-`
   add_${func}of_ports br0 1 2

   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)'])
   ovs-appctl revalidator/wait
   AT_CHECK([ovs-appctl dpif/dump-flows -m br0], [0], [stdout])

   UFID=`sed -n 's/\(ufid:[[-0-9a-fA-F]]*\).*/\1/p' stdout`
   AT_CHECK([ovs-appctl dpctl/get-flow $UFID], [0], [dnl
recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:0, bytes:0, used:never, actions:drop
])

   OVS_VSWITCHD_STOP
   AT_CLEANUP])

OFPROTO_DPIF_GET_FLOW([])
OFPROTO_DPIF_GET_FLOW([ - pmd])

AT_SETUP([ofproto-dpif - MPLS actions that result in a userspace action])
OVS_VSWITCHD_START([dnl
   add-port br0 p1 -- set Interface p1 type=dummy
])
AT_CHECK([ovs-appctl vlog/set dpif:dbg dpif_netdev:dbg])
on_exit 'kill `cat ovs-ofctl.pid`'

AT_CAPTURE_FILE([ofctl_monitor.log])
AT_DATA([flows.txt], [dnl
dl_src=60:66:66:66:66:00 actions=push_mpls:0x8847,controller
dl_src=60:66:66:66:66:01 actions=pop_mpls:0x8847,controller
])
AT_CHECK([ovs-ofctl add-flows br0 flows.txt])

dnl Packet is sent to userspace because a MPLS push or pop action is applied to
dnl a packet with 2 MPLS LSEs but dpif-netdev can't handle any labels.
dnl
dnl The input is a frame with two MPLS labels which tcpdump -vve shows as:
dnl 60:66:66:66:66:00 > 50:54:00:00:00:07, ethertype MPLS unicast (0x8847), length 74: MPLS (label 20, exp 0, ttl 32)
dnl         (label 20, exp 0, [S], ttl 32)
dnl         (tos 0x0, ttl 64, id 0, offset 0, flags [none], proto TCP (6), length 44, bad cksum 3b78 (->f978)!)
dnl     192.168.0.1.80 > 192.168.0.2.0: Flags [none], cksum 0x7744 (correct), seq 42:46, win 10000, length 4

for dl_src in 00 01; do
    AT_CHECK([ovs-appctl netdev-dummy/receive p1 "505400000007 6066666666$dl_src 8847 00014020 00014120 45 00 00 2c 00 00 00 00 40 06 3b 78 c0 a8 00 01 c0 a8 00 02 00 50 00 00 00 00 00 2a 00 00 00 2a 50 00 27 10 77 44 00 00 48 4f 47 45"])
done
sleep 1  # wait for the datapath flow installed
AT_CHECK_UNQUOTED([strip_ufid < ovs-vswitchd.log | filter_flow_install | strip_used], [0], [dnl
recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(src=60:66:66:66:66:00),eth_type(0x8847),mpls(label=20,tc=0,ttl=32,bos=0,label=20,tc=0,ttl=32,bos=1), actions:push_mpls(label=20,tc=0,ttl=32,bos=0,eth_type=0x8847),userspace(pid=0,controller(reason=1,dont_send=0,continuation=0,recirc_id=1,rule_cookie=0,controller_id=0,max_len=65535))
recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(src=60:66:66:66:66:01),eth_type(0x8847),mpls(label=20/0x0,tc=0/0,ttl=32/0x0,bos=0/1,label=20/0xfffff,tc=0/7,ttl=32/0xff,bos=1/1), actions:pop_mpls(eth_type=0x8847),userspace(pid=0,controller(reason=1,dont_send=0,continuation=0,recirc_id=1,rule_cookie=0,controller_id=0,max_len=65535))
])

OVS_VSWITCHD_STOP
AT_CLEANUP


AT_SETUP([ofproto-dpif - MPLS actions that result in a drop])
OVS_VSWITCHD_START([dnl
   add-port br0 p1 -- set Interface p1 type=dummy
])
AT_CHECK([ovs-appctl vlog/set dpif:dbg dpif_netdev:dbg])
on_exit 'kill `cat ovs-ofctl.pid`'

AT_CAPTURE_FILE([ofctl_monitor.log])
AT_DATA([flows.txt], [dnl
dl_src=60:66:66:66:66:00 actions=push_mpls:0x8847,controller
dl_src=60:66:66:66:66:01 actions=pop_mpls:0x8847,controller
])
AT_CHECK([ovs-ofctl add-flows br0 flows.txt])

dnl Packet is dropped because an MPLS PUSH action is applied to a packet with
dnl 4 MPLS LSEs but ovs-vswitchd can only handle up to 3 MPLS LSEs and thus
dnl can't determine the resulting MPLS label after MPLS push/pop actions.
dnl
dnl The input is a frame with two MPLS headers which tcpdump -vve shows as:
dnl 60:66:66:66:66:01 > 50:54:00:00:00:07, ethertype MPLS unicast (0x8847), length 74: MPLS (label 20, exp 0, ttl 32)
dnl         (label 20, exp 0, ttl 32)
dnl         (label 20, exp 0, ttl 32)
dnl         (label 20, exp 0, [S], ttl 32)
dnl         (tos 0x0, ttl 64, id 0, offset 0, flags [none], proto TCP (6), length 44, bad cksum 3b78 (->f978)!)
dnl     192.168.0.1.80 > 192.168.0.2.0: Flags [none], cksum 0x7744 (correct), seq 42:46, win 10000, length 4

for dl_src in 00 01; do
    AT_CHECK([ovs-appctl netdev-dummy/receive p1 "505400000007 6066666666$dl_src 8847 00014020 00014120 45 00 00 2c 00 00 00 00 40 06 3b 78 c0 a8 00 01 c0 a8 00 02 00 50 00 00 00 00 00 2a 00 00 00 2a 50 00 27 10 77 44 00 00 48 4f 47 45"])
done
sleep 1  # wait for the datapath flow installed
AT_CHECK_UNQUOTED([strip_ufid < ovs-vswitchd.log | filter_flow_install | strip_used], [0], [dnl
recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(src=60:66:66:66:66:00),eth_type(0x8847),mpls(label=20,tc=0,ttl=32,bos=0,label=20,tc=0,ttl=32,bos=1), actions:push_mpls(label=20,tc=0,ttl=32,bos=0,eth_type=0x8847),userspace(pid=0,controller(reason=1,dont_send=0,continuation=0,recirc_id=1,rule_cookie=0,controller_id=0,max_len=65535))
recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(src=60:66:66:66:66:01),eth_type(0x8847),mpls(label=20/0x0,tc=0/0,ttl=32/0x0,bos=0/1,label=20/0xfffff,tc=0/7,ttl=32/0xff,bos=1/1), actions:pop_mpls(eth_type=0x8847),userspace(pid=0,controller(reason=1,dont_send=0,continuation=0,recirc_id=1,rule_cookie=0,controller_id=0,max_len=65535))
])

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-appctl upcall/disable-ufid], [0], [Datapath dumping tersely using UFID disabled
], [])
AT_CHECK([ovs-appctl time/stop])
AT_CHECK([ovs-appctl vlog/set dpif:dbg dpif_netdev:dbg])

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)'
    if [[ $i -eq 1 ]]; then
        sleep 1
    fi
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)'
    if [[ $i -eq 1 ]]; then
        sleep 1
    fi
done

AT_CHECK([ovs-appctl time/warp 500], [0],
[warped
])
sleep 1  # wait for log writer

AT_CHECK([ovs-appctl dpif/show], [0], [dnl
dummy@ovs-dummy: hit:13 missed:2
  br0:
    br0 65534/100: (dummy-internal)
    p2 2/2: (dummy)
    pbr0 1/none: (patch: peer=pbr1)
  br1:
    br1 65534/101: (dummy-internal)
    p3 3/3: (dummy)
    pbr1 1/none: (patch: peer=pbr0)
])

AT_CHECK([strip_ufid < ovs-vswitchd.log | filter_flow_install | strip_used], [0], [dnl
recirc_id(0),in_port(100),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), actions:101,3,2
recirc_id(0),in_port(101),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), actions:100,2,3
])

AT_CHECK([grep -e 'in_port(100).*packets:9' ovs-vswitchd.log | strip_ufid | filter_flow_dump], [0], [dnl
skb_priority(0/0),skb_mark(0/0),ct_state(0/0),ct_zone(0/0),ct_mark(0/0),ct_label(0/0),recirc_id(0),dp_hash(0/0),in_port(100),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:05/00:00:00:00:00:00,dst=50:54:00:00:00:07/00:00:00:00:00:00),eth_type(0x0800),ipv4(src=192.168.0.1/0.0.0.0,dst=192.168.0.2/0.0.0.0,proto=1/0,tos=0/0,ttl=64/0,frag=no),icmp(type=8/0,code=0/0), packets:9, bytes:954, used:0.0s, actions:101,3,2
])
AT_CHECK([grep -e 'in_port(101).*packets:4' ovs-vswitchd.log | strip_ufid | filter_flow_dump], [0], [dnl
skb_priority(0/0),skb_mark(0/0),ct_state(0/0),ct_zone(0/0),ct_mark(0/0),ct_label(0/0),recirc_id(0),dp_hash(0/0),in_port(101),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:07/00:00:00:00:00:00,dst=50:54:00:00:00:05/00:00:00:00:00:00),eth_type(0x0800),ipv4(src=192.168.0.2/0.0.0.0,dst=192.168.0.1/0.0.0.0,proto=1/0,tos=0/0,ttl=64/0,frag=no),icmp(type=8/0,code=0/0), packets:4, bytes:424, 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=530, drop=?, errs=?, frame=?, over=?, crc=?
           tx pkts=10, bytes=1060, drop=?, errs=?, coll=?
])

AT_CHECK([ovs-ofctl dump-ports br1 pbr1], [0], [dnl
OFPST_PORT reply (xid=0x4): 1 ports
  port  1: rx pkts=10, bytes=1060, drop=?, errs=?, frame=?, over=?, crc=?
           tx pkts=5, bytes=530, drop=?, errs=?, coll=?
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - patch ports - stack])
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-appctl upcall/disable-ufid], [0], [Datapath dumping tersely using UFID disabled
], [])
AT_CHECK([ovs-appctl time/stop])
AT_CHECK([ovs-appctl vlog/set dpif:dbg dpif_netdev:dbg])

AT_CHECK([ovs-ofctl add-flow br0 "ip actions=push:OXM_OF_IN_PORT[[0..31]],output:1,pop:OXM_OF_IPV4_SRC[[0..31]],output:2"])
# Try to pop from empty stack, and push and leave data to stack.
AT_CHECK([ovs-ofctl add-flow br1 "ip actions=pop:OXM_OF_IPV4_DST[[0..31]],push:NXM_NX_REG1[[0..31]],LOCAL"])

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)'

AT_CHECK([ovs-appctl time/warp 500], [0],
[warped
])

OVS_WAIT_UNTIL([test `grep flow_add ovs-vswitchd.log | wc -l` -ge 1])

AT_CHECK([ovs-appctl dpif/show], [0], [dnl
dummy@ovs-dummy: hit:0 missed:1
  br0:
    br0 65534/100: (dummy-internal)
    p2 2/2: (dummy)
    pbr0 1/none: (patch: peer=pbr1)
  br1:
    br1 65534/101: (dummy-internal)
    p3 3/3: (dummy)
    pbr1 1/none: (patch: peer=pbr0)
])

AT_CHECK([strip_ufid < ovs-vswitchd.log | filter_flow_install | strip_used], [0], [dnl
recirc_id(0),in_port(100),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(src=192.168.0.1,frag=no), actions:101,set(ipv4(src=255.255.255.254)),2
])

AT_CHECK([grep -e '|ofproto_dpif_xlate|WARN|' ovs-vswitchd.log | sed "s/^.*|WARN|//"], [0], [dnl
stack underflow on bridge br1 while processing icmp,in_port=LOCAL,vlan_tci=0x0000,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_tos=0,nw_ecn=0,nw_ttl=64,icmp_type=8,icmp_code=0
])

OVS_VSWITCHD_STOP(["/stack underflow/d"])
AT_CLEANUP

AT_SETUP([ofproto-dpif - port duration])
OVS_VSWITCHD_START([set Bridge br0 protocols=OpenFlow13])
add_of_ports br0 1 2

ovs-appctl time/stop
ovs-appctl time/warp 10000

AT_CHECK([ovs-ofctl -O openflow13 dump-ports br0], [0], [stdout])
AT_CHECK([sed -n 's/=[[0-9]][[0-9]]\(\.[[0-9]][[0-9]]*\)\{0,1\}s/=?s/p' stdout], [0],
[dnl
           duration=?s
           duration=?s
           duration=?s
])
OVS_VSWITCHD_STOP
AT_CLEANUP


AT_SETUP([ofproto-dpif - patch ports - meter (clone)])

OVS_VSWITCHD_START(
  [add-port br0 p0 -- set Interface p0 type=dummy ofport_request=1 -- \
   add-port br0 p1 -- set Interface p1 type=patch \
                                       options:peer=p2 ofport_request=2 -- \
   add-br br1 -- \
   set bridge br1 other-config:hwaddr=aa:66:aa:66:00:00 -- \
   set bridge br1 datapath-type=dummy other-config:datapath-id=1234 \
                  fail-mode=secure -- \
   add-port br1 p2 -- set Interface p2 type=patch \
                                       options:peer=p1 -- \
   add-port br1 p3 -- set Interface p3 type=dummy ofport_request=3])

AT_CHECK([ovs-ofctl -O OpenFlow13 add-meter br1 'meter=1 pktps stats bands=type=drop rate=2'])
AT_CHECK([ovs-ofctl del-flows br0])
AT_CHECK([ovs-ofctl -O OpenFlow13 add-flow br0 in_port=local,ip,actions=2,1])
AT_CHECK([ovs-ofctl -O OpenFlow13 add-flow br1 in_port=1,ip,actions=meter:1,3])

AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(100),eth(src=f8:bc:12:44:34:b6,dst=f8:bc:12:46:58:e0),eth_type(0x0800),ipv4(src=10.1.1.22,dst=10.0.0.3,proto=6,tos=0,ttl=64,frag=no),tcp(src=53295,dst=8080)'], [0], [stdout])
AT_CHECK([tail -1 stdout], [0],
  [Datapath actions: clone(meter(0),3),1
])

OVS_VSWITCHD_STOP
AT_CLEANUP

dnl ----------------------------------------------------------------------
AT_BANNER([ofproto-dpif -- megaflows])

AT_SETUP([ofproto-dpif megaflow - port classification])
OVS_VSWITCHD_START
AT_CHECK([ovs-appctl vlog/set dpif:dbg dpif_netdev:dbg])
add_of_ports br0 1 2
AT_DATA([flows.txt], [dnl
table=0 in_port=1 actions=output(2)
])
AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),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)'])
sleep 1
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:0b,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(src=10.0.0.4,dst=10.0.0.3,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)'])
sleep 1
AT_CHECK([filter_flow_install < ovs-vswitchd.log | strip_xout], [0], [dnl
recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), actions: <del>
])
OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif megaflow - L2 classification])
OVS_VSWITCHD_START
AT_CHECK([ovs-appctl vlog/set dpif:dbg dpif_netdev:dbg])
add_of_ports br0 1 2
AT_DATA([flows.txt], [dnl
table=0 in_port=1,dl_src=50:54:00:00:00:09 actions=output(2)
])
AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),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)'])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:0b,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(src=10.0.0.4,dst=10.0.0.3,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)'])
sleep 1
AT_CHECK([filter_flow_install < ovs-vswitchd.log | strip_xout], [0], [dnl
recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:09),eth_type(0x0800),ipv4(frag=no), actions: <del>
recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:0b),eth_type(0x0800),ipv4(frag=no), actions: <del>
])
OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif megaflow - L3 classification])
OVS_VSWITCHD_START
AT_CHECK([ovs-appctl vlog/set dpif:dbg dpif_netdev:dbg])
add_of_ports br0 1 2
AT_CHECK([ovs-vsctl set Bridge br0 flow_tables:0=@N1 -- --id=@N1 create Flow_Table name=t0 prefixes=nw_dst,nw_src], [0], [ignore], [])
AT_DATA([flows.txt], [dnl
table=0 in_port=1,icmp,nw_src=10.0.0.4 actions=output(2)
])
AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),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)'])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:0b,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(src=10.0.0.4,dst=10.0.0.3,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)'])
sleep 1
AT_CHECK([filter_flow_install < ovs-vswitchd.log | strip_xout], [0], [dnl
recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(src=10.0.0.2/255.255.255.252,frag=no), actions: <del>
recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(src=10.0.0.4,proto=1,frag=no), actions: <del>
])
OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif megaflow - IPv6 classification])
OVS_VSWITCHD_START
AT_CHECK([ovs-appctl vlog/set dpif:dbg dpif_netdev:dbg])
add_of_ports br0 1 2
AT_CHECK([ovs-vsctl set Bridge br0 flow_tables:0=@N1 -- --id=@N1 create Flow_Table name=t0 prefixes=ipv6_dst,ipv6_src], [0], [ignore], [])
AT_DATA([flows.txt], [dnl
table=0 in_port=1,ipv6,ipv6_src=2001:db8:3c4d:1:2:3:4:5 actions=output(2)
])
AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:07,dst=50:54:00:00:00:05),eth_type(0x86dd),ipv6(src=2001:db8:3c4d:1:2:3:4:5,dst=fe80::2,label=0,proto=10,tclass=0x70,hlimit=128,frag=no)'])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x86dd),ipv6(src=2001:db8:3c4d:5:4:3:2:1,dst=2001:db8:3c4d:1:2:3:4:1,label=0,proto=99,tclass=0x70,hlimit=64,frag=no)'])
sleep 1
AT_CHECK([filter_flow_install < ovs-vswitchd.log | strip_xout], [0], [dnl
recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x86dd),ipv6(src=2001:db8:3c4d:1:2:3:4:5,frag=no), actions: <del>
recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x86dd),ipv6(src=2001:db8:3c4d:5:4:3:2:1/ffff:ffff:ffff:fffc::,frag=no), actions: <del>
])
OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif megaflow - L4 classification])
OVS_VSWITCHD_START
AT_CHECK([ovs-appctl vlog/set dpif:dbg dpif_netdev:dbg])
add_of_ports br0 1 2
AT_DATA([flows.txt], [dnl
table=0 in_port=1,icmp,icmp_type=8 actions=output(2)
])
AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),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)'])
sleep 1
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:0b,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(src=10.0.0.4,dst=10.0.0.3,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)'])
sleep 1
AT_CHECK([filter_flow_install < ovs-vswitchd.log | strip_xout], [0], [dnl
recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(proto=1,frag=no),icmp(type=8), actions: <del>
])
OVS_VSWITCHD_STOP
AT_CLEANUP

m4_define([OFPROTO_DPIF_MEGAFLOW_NORMAL],
  [AT_SETUP([ofproto-dpif megaflow - normal$1])
   OVS_VSWITCHD_START([], [], [], [m4_if([$1], [], [], [--dummy-numa="0,0,0,0,1,1,1,1"])])
   AT_CHECK([ovs-appctl vlog/set dpif:dbg dpif_netdev:dbg])
   func=`printf '%s_' "$1" | cut -c 4-`
   add_${func}of_ports br0 1 2
   AT_CHECK([ovs-ofctl add-flow br0 action=normal])
   AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),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)'])
   AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:0b,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(src=10.0.0.4,dst=10.0.0.3,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)'])
   sleep 1
   AT_CHECK([filter_flow_install < ovs-vswitchd.log | strip_xout], [0], [dnl
recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(frag=no), actions: <del>
recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:0b,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(frag=no), actions: <del>
])
   OVS_VSWITCHD_STOP
   AT_CLEANUP])

OFPROTO_DPIF_MEGAFLOW_NORMAL([])
OFPROTO_DPIF_MEGAFLOW_NORMAL([ - pmd])

AT_SETUP([ofproto-dpif megaflow - mpls])
OVS_VSWITCHD_START
AT_CHECK([ovs-appctl vlog/set dpif:dbg dpif_netdev:dbg])
add_of_ports br0 1 2
AT_DATA([flows.txt], [dnl
table=0 dl_src=50:54:00:00:00:09 actions=push_mpls:0x8847,2
table=0 dl_src=50:54:00:00:00:0b actions=pop_mpls:0x0800,2
])
AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x8847),mpls(label=11,tc=3,ttl=64,bos=1)'])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:0b,dst=50:54:00:00:00:0a),eth_type(0x8847),mpls(label=11,tc=3,ttl=64,bos=1)'])
sleep 1
AT_CHECK([filter_flow_install < ovs-vswitchd.log | strip_xout_keep_actions], [0], [dnl
recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:09),eth_type(0x8847),mpls(label=11,tc=3,ttl=64,bos=1), actions:push_mpls(label=11,tc=3,ttl=64,bos=0,eth_type=0x8847),2
recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:0b),eth_type(0x8847),mpls(label=11/0x0,tc=3/0,ttl=64/0x0,bos=1/1), actions:pop_mpls(eth_type=0x800),2
])
OVS_VSWITCHD_STOP
AT_CLEANUP

# CHECK_MEGAFLOW_NETFLOW(LOOPBACK_ADDR)
m4_define([CHECK_MEGAFLOW_NETFLOW],
  [OVS_VSWITCHD_START
  AT_CHECK([ovs-appctl vlog/set dpif:dbg dpif_netdev:dbg])
  add_of_ports br0 1 2

  dnl NetFlow configuration disables wildcarding relevant fields
  on_exit 'kill `cat test-netflow.pid`'
  AT_CHECK([ovstest test-netflow --log-file --detach --no-chdir --pidfile 0:$1 > netflow.log], [0], [], [ignore])
  AT_CAPTURE_FILE([netflow.log])
  PARSE_LISTENING_PORT([test-netflow.log], [NETFLOW_PORT])
  ovs-vsctl \
     set Bridge br0 netflow=@nf -- \
     --id=@nf create NetFlow targets=\"$1:$NETFLOW_PORT\" \
       engine_id=1 engine_type=2 active_timeout=30 add-id-to-interface=false

  AT_CHECK([ovs-ofctl add-flow br0 action=normal])
  AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),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)'])
  AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:0b,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(src=10.0.0.4,dst=10.0.0.3,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)'])
  sleep 1
  AT_CHECK([filter_flow_install < ovs-vswitchd.log | strip_xout], [0], [dnl
recirc_id(0),in_port(1),packet_type(ns=0,id=0),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/0xfc,frag=no),icmp(type=8,code=0), actions: <del>
recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:0b,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(src=10.0.0.4,dst=10.0.0.3,proto=1,tos=0/0xfc,frag=no),icmp(type=8,code=0), actions: <del>
])
  OVS_APP_EXIT_AND_WAIT([test-netflow])
  OVS_VSWITCHD_STOP])

AT_SETUP([ofproto-dpif megaflow - netflow - IPv4 collector])
CHECK_MEGAFLOW_NETFLOW([127.0.0.1], [IPv4])
AT_CLEANUP

AT_SETUP([ofproto-dpif megaflow - netflow - IPv6 collector])
AT_SKIP_IF([test $HAVE_IPV6 = no])
CHECK_MEGAFLOW_NETFLOW([[[::1]]], [IPv6])
AT_CLEANUP

m4_define([OFPROTO_DPIF_MEGAFLOW_NORMAL_ACB_BOND],
  [AT_SETUP([ofproto-dpif megaflow - normal, active-backup bonding - $1])
   OVS_VSWITCHD_START(
     [add-port br0 p1 -- set Interface p1 type=$1 ofport_request=1 -- \
      add-bond br0 bond0 p2 p3 bond_mode=active-backup -- \
      set interface p2 type=$1 ofport_request=2 -- \
      set interface p3 type=$1 ofport_request=3], [], [],
      [m4_if([$1], [dummy-pmd], [--dummy-numa="0,0,0,0,1,1,1,1"], [])])
   AT_CHECK([ovs-appctl netdev-dummy/set-admin-state up], 0, [OK
])
   AT_CHECK([ovs-appctl vlog/set dpif:dbg dpif_netdev:dbg])

   AT_CHECK([ovs-ofctl add-flow br0 action=normal])
   AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),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)'])
   AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:0b,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(src=10.0.0.4,dst=10.0.0.3,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)'])
   sleep 1
   AT_CHECK([filter_flow_install < ovs-vswitchd.log | strip_xout], [0], [dnl
recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(frag=no), actions: <del>
recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:0b,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(frag=no), actions: <del>
])
   OVS_VSWITCHD_STOP
   AT_CLEANUP])

OFPROTO_DPIF_MEGAFLOW_NORMAL_ACB_BOND([dummy])
OFPROTO_DPIF_MEGAFLOW_NORMAL_ACB_BOND([dummy-pmd])

AT_SETUP([ofproto-dpif megaflow - normal, balance-slb bonding])
OVS_VSWITCHD_START(
  [add-port br0 p1 -- set Interface p1 type=dummy ofport_request=1 -- \
   add-bond br0 bond0 p2 p3 bond_mode=balance-slb -- \
   set interface p2 type=dummy ofport_request=2 -- \
   set interface p3 type=dummy ofport_request=3])
AT_CHECK([ovs-appctl netdev-dummy/set-admin-state up], 0, [OK
])
AT_CHECK([ovs-appctl vlog/set dpif:dbg dpif_netdev:dbg])

AT_CHECK([ovs-ofctl add-flow br0 action=normal])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),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)'])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:0b,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(src=10.0.0.4,dst=10.0.0.3,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)'])
sleep 1
AT_CHECK([filter_flow_install < ovs-vswitchd.log | strip_xout], [0], [dnl
recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(frag=no), actions: <del>
recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:0b,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(frag=no), actions: <del>
])
OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif megaflow - normal, balance-tcp bonding])
# Create bond0 on br0 with members p0 and p1
#    and bond1 on br1 with members p2 and p3
# with p0 patched to p2 and p1 patched to p3.
OVS_VSWITCHD_START(
  [add-bond br0 bond0 p0 p1 bond_mode=balance-tcp lacp=active \
                            other-config:lacp-time=fast \
                            other-config:bond-rebalance-interval=0 -- \
   set interface p0 type=patch options:peer=p2 ofport_request=1 -- \
   set interface p1 type=patch options:peer=p3 ofport_request=2 -- \
   add-br br1 -- \
   set bridge br1 other-config:hwaddr=aa:66:aa:66:00:00 -- \
   set bridge br1 datapath-type=dummy other-config:datapath-id=1234 \
                  fail-mode=secure -- \
   add-bond br1 bond1 p2 p3 bond_mode=balance-tcp lacp=active \
                            other-config:lacp-time=fast \
                            other-config:bond-rebalance-interval=0 -- \
   set interface p2 type=patch options:peer=p0 ofport_request=3 -- \
   set interface p3 type=patch options:peer=p1 ofport_request=4 --])

AT_CHECK([ovs-appctl netdev-dummy/set-admin-state up], 0, [OK
])
AT_CHECK([ovs-appctl vlog/set dpif:dbg dpif_netdev:dbg])
add_of_ports br0 7
AT_CHECK([ovs-ofctl add-flow br0 action=normal])
AT_CHECK([ovs-ofctl add-flow br1 action=normal])
ovs-appctl time/stop
ovs-appctl time/warp 5000
AT_CHECK([ovs-appctl netdev-dummy/receive p7 'in_port(1),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)'])
AT_CHECK([ovs-appctl netdev-dummy/receive p7 'in_port(1),eth(src=50:54:00:00:00:0b,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(src=10.0.0.4,dst=10.0.0.3,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)'])
sleep 1
AT_CHECK([filter_flow_install < ovs-vswitchd.log | strip_xout], [0], [dnl
recirc_id(0),in_port(7),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(frag=no), actions: <del>
recirc_id(0),in_port(7),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:0b,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(frag=no), actions: <del>
])
OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif megaflow - resubmit port action])
OVS_VSWITCHD_START
AT_CHECK([ovs-appctl vlog/set dpif:dbg dpif_netdev:dbg])
add_of_ports br0 1 2
AT_DATA([flows.txt], [dnl
table=0 in_port=1,ip actions=resubmit(90)
table=0 in_port=90,dl_src=50:54:00:00:00:09 actions=output(2)
])
AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),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)'])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:0b,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(src=10.0.0.4,dst=10.0.0.3,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)'])
sleep 1
AT_CHECK([filter_flow_install < ovs-vswitchd.log | strip_xout], [0], [dnl
recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:09),eth_type(0x0800),ipv4(frag=no), actions: <del>
recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:0b),eth_type(0x0800),ipv4(frag=no), actions: <del>
])
OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif megaflow - resubmit table action])
OVS_VSWITCHD_START
AT_CHECK([ovs-appctl vlog/set dpif:dbg dpif_netdev:dbg])
add_of_ports br0 1 2
AT_DATA([flows.txt], [dnl
table=0 in_port=1,ip actions=resubmit(,1)
table=1 dl_src=50:54:00:00:00:09 actions=output(2)
])
AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),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)'])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:0b,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(src=10.0.0.4,dst=10.0.0.3,proto=
1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)'])
sleep 1
AT_CHECK([filter_flow_install < ovs-vswitchd.log | strip_xout], [0], [dnl
recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:09),eth_type(0x0800),ipv4(frag=no), actions: <del>
recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:0b),eth_type(0x0800),ipv4(frag=no), actions: <del>
])
OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif megaflow - goto_table action])
OVS_VSWITCHD_START
AT_CHECK([ovs-appctl vlog/set dpif:dbg dpif_netdev:dbg])
add_of_ports br0 1 2
AT_DATA([flows.txt], [dnl
table=0 in_port=1,ip actions=goto_table(1)
table=1 dl_src=50:54:00:00:00:09 actions=output(2)
])
AT_CHECK([ovs-ofctl -O OpenFlow12 add-flows br0 flows.txt])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),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)'])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:0b,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(src=10.0.0.4,dst=10.0.0.3,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)'])
sleep 1
AT_CHECK([filter_flow_install < ovs-vswitchd.log | strip_xout], [0], [dnl
recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:09),eth_type(0x0800),ipv4(frag=no), actions: <del>
recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:0b),eth_type(0x0800),ipv4(frag=no), actions: <del>
])
OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif megaflow - mirroring, select_all])
AT_KEYWORDS([mirror mirrors mirroring])
OVS_VSWITCHD_START
AT_CHECK([ovs-appctl vlog/set dpif:dbg dpif_netdev:dbg])
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
])
AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),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)'])
sleep 1
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:0b,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(src=10.0.0.4,dst=10.0.0.3,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)'])
sleep 1
AT_CHECK([filter_flow_install < ovs-vswitchd.log | strip_xout], [0], [dnl
recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), actions: <del>
])
OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif megaflow - mirroring, select_vlan])
OVS_VSWITCHD_START
AT_CHECK([ovs-appctl vlog/set dpif:dbg dpif_netdev:dbg])
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])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x8100),vlan(vid=11,pcp=7),encap(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))'])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:0b,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(src=10.0.0.4,dst=10.0.0.3,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)'])
sleep 1
AT_CHECK([filter_flow_install < ovs-vswitchd.log | strip_xout], [0], [dnl
recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), actions: <del>
recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x8100),vlan(vid=11,pcp=7/0x0),encap(eth_type(0x0800),ipv4(frag=no)), actions: <del>
])
OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif megaflow - move action])
OVS_VSWITCHD_START
AT_CHECK([ovs-appctl vlog/set dpif:dbg dpif_netdev:dbg])
add_of_ports br0 1 2
AT_DATA([flows.txt], [dnl
table=0 in_port=1 ip,actions=move:NXM_OF_IP_SRC[[]]->NXM_NX_REG0[[]],resubmit(90)
table=0 in_port=90 ip,actions=move:NXM_NX_REG0[[]]->NXM_NX_REG1[[]],resubmit(91)
table=0 in_port=91 reg0=0x0a000002,actions=output(2)
])
AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),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)'])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:0b,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(src=10.0.0.4,dst=10.0.0.3,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)'])
sleep 1
AT_CHECK([filter_flow_install < ovs-vswitchd.log | strip_xout], [0], [dnl
recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(src=10.0.0.2,frag=no), actions: <del>
recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(src=10.0.0.4,frag=no), actions: <del>
])
OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif megaflow - push action])
OVS_VSWITCHD_START
AT_CHECK([ovs-appctl vlog/set dpif:dbg dpif_netdev:dbg])
add_of_ports br0 1 2
AT_DATA([flows.txt], [dnl
table=0 in_port=1 ip,actions=push:NXM_OF_IP_SRC[[]],output(2)
])
AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),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)'])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:0b,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(src=10.0.0.4,dst=10.0.0.3,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)'])
sleep 1
AT_CHECK([filter_flow_install < ovs-vswitchd.log | strip_xout], [0], [dnl
recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(src=10.0.0.2,frag=no), actions: <del>
recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(src=10.0.0.4,frag=no), actions: <del>
])
OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif megaflow - learning])
OVS_VSWITCHD_START
AT_CHECK([ovs-appctl vlog/set dpif:dbg dpif_netdev:dbg])
add_of_ports br0 1 2
AT_DATA([flows.txt], [dnl
table=0 in_port=1 actions=load:2->NXM_NX_REG0[[0..15]],learn(table=1,priority=65535,NXM_OF_ETH_SRC[[]],NXM_OF_VLAN_TCI[[0..11]],output:NXM_NX_REG0[[0..15]]),output:2
])
AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
ovs-appctl time/stop
# We send each packet twice because the first packet in each flow causes the
# flow table to change and thus revalidations, which (depending on timing)
# can keep a megaflow from being installed.  The revalidations are done by
# the second iteration, allowing the flows to be installed.
for i in 1 2; do
    AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),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)'])
    AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:0b,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(src=10.0.0.4,dst=10.0.0.3,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)'])
    ovs-appctl time/warp 100
done
sleep 1
dnl The original flow is missing due to a revalidation.
AT_CHECK([filter_flow_install < ovs-vswitchd.log | strip_xout], [0], [dnl
recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:09),eth_type(0x0800),ipv4(frag=no), actions: <del>
recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:0b),eth_type(0x0800),ipv4(frag=no), actions: <del>
])
OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif megaflow - tunnels])
OVS_VSWITCHD_START(
  [add-port br0 p1 -- set Interface p1 type=dummy ofport_request=1])
AT_CHECK([ovs-appctl vlog/set dpif:dbg dpif_netdev:dbg])
AT_CHECK([ovs-vsctl add-port br0 p2 -- set Interface p2 type=gre \
     options:remote_ip=1.1.1.1 ofport_request=2 options:key=flow])
AT_CHECK([ovs-vsctl add-port br0 p3 -- set Interface p3 type=dummy \
          ofport_request=3])
AT_CHECK([ovs-vsctl add-port br0 p4 -- set Interface p4 type=gre \
     options:remote_ip=1.1.1.2 options:tos=inherit options:ttl=inherit \
     ofport_request=4 options:key=flow])
AT_DATA([flows.txt], [dnl
in_port=1,actions=output(2)
in_port=3,actions=output(4)
])
AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
dnl ECN bits are always copied out, but don't use 0x3 (CE), since that
dnl will cause the packet to be dropped.
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),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=0xfd,ttl=128,frag=no),icmp(type=8,code=0)'])
sleep 1
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:0b,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(src=10.0.0.4,dst=10.0.0.3,proto=1,tos=0x1,ttl=64,frag=no),icmp(type=8,code=0)'])
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=0xfd,ttl=128,frag=no),icmp(type=8,code=0)'])
sleep 1
AT_CHECK([ovs-appctl netdev-dummy/receive p3 'in_port(3),eth(src=50:54:00:00:00:0b,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(src=10.0.0.4,dst=10.0.0.3,proto=1,tos=0x1,ttl=64,frag=no),icmp(type=8,code=0)'])
sleep 1
AT_CHECK([filter_flow_install < ovs-vswitchd.log | strip_xout], [0], [dnl
recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(tos=0xfd/0x3,frag=no), actions: <del>
recirc_id(0),in_port(3),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(tos=0x1,ttl=64,frag=no), actions: <del>
recirc_id(0),in_port(3),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(tos=0xfd,ttl=128,frag=no), actions: <del>
])
OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif megaflow - dec_ttl])
OVS_VSWITCHD_START
AT_CHECK([ovs-appctl vlog/set dpif:dbg dpif_netdev:dbg])
add_of_ports br0 1 2
AT_CHECK([ovs-vsctl set Bridge br0 flow_tables:0=@N1 -- --id=@N1 create Flow_Table name=t0 prefixes=nw_dst,nw_src], [0], [ignore], [])
AT_DATA([flows.txt], [dnl
table=0 in_port=1,icmp,nw_src=10.0.0.4 actions=dec_ttl,output(2)
])
AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),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)'])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:0b,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(src=10.0.0.4,dst=10.0.0.3,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)'])
sleep 1
AT_CHECK([filter_flow_install < ovs-vswitchd.log | strip_xout], [0], [dnl
recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(src=10.0.0.2/255.255.255.252,frag=no), actions: <del>
recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(src=10.0.0.4,proto=1,ttl=64,frag=no), actions: <del>
])
OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif megaflow - set dl_dst])
OVS_VSWITCHD_START
AT_CHECK([ovs-appctl vlog/set dpif:dbg dpif_netdev:dbg])
add_of_ports br0 1 2
AT_DATA([flows.txt], [dnl
table=0 in_port=1 actions=mod_dl_dst(50:54:00:00:00:0a),output(2)
])
AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),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)'])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:0b,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(src=10.0.0.4,dst=10.0.0.3,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)'])
sleep 1
dnl The first packet is essentially a no-op, as the new destination MAC is the
dnl same as the original.  The second entry actually updates the destination
dnl MAC.
AT_CHECK([strip_ufid < ovs-vswitchd.log | filter_flow_install | strip_used], [0], [dnl
recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(frag=no), actions:2
recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(frag=no), actions:set(eth(dst=50:54:00:00:00:0a)),2
])
OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif megaflow - set dl_dst with match on dl_src])
OVS_VSWITCHD_START
AT_CHECK([ovs-appctl vlog/set dpif:dbg dpif_netdev:dbg])
add_of_ports br0 1 2
AT_DATA([flows.txt], [dnl
table=0 in_port=1,dl_src=50:54:00:00:00:09 actions=mod_dl_dst(50:54:00:00:00:0a),output(2)
])
AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),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)'])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(src=10.0.0.4,dst=10.0.0.3,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)'])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:0b,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(src=10.0.0.6,dst=10.0.0.5,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)'])
sleep 1
dnl The first packet is essentially a no-op, as the new destination MAC is the
dnl same as the original.  The second entry actually updates the destination
dnl MAC.  The last one must be dropped as it doesn't match with dl_src.
AT_CHECK([strip_ufid < ovs-vswitchd.log | filter_flow_install | strip_used], [0], [dnl
recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(frag=no), actions:2
recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(frag=no), actions:set(eth(dst=50:54:00:00:00:0a)),2
recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:0b),eth_type(0x0800),ipv4(frag=no), actions:drop
])
OVS_VSWITCHD_STOP
AT_CLEANUP

m4_define([OFPROTO_DPIF_MEGAFLOW_DISABLED],
  [AT_SETUP([ofproto-dpif megaflow - disabled$1])
   OVS_VSWITCHD_START([], [], [], [m4_if([$1], [], [], [--dummy-numa="0,0,0,0,1,1,1,1"])])
   AT_CHECK([ovs-appctl vlog/set dpif:dbg dpif_netdev:dbg])
   func=`printf '%s_' "$1" | cut -c 4-`
   add_${func}of_ports br0 1 2
   AT_DATA([flows.txt], [dnl
table=0 in_port=1,ip,nw_dst=10.0.0.1 actions=output(2)
table=0 in_port=1,ip,nw_dst=10.0.0.3 actions=drop
])
   AT_CHECK([ovs-appctl upcall/disable-megaflows], [0], [megaflows disabled
], [])
   AT_CHECK([ovs-appctl upcall/disable-ufid], [0], [Datapath dumping tersely using UFID disabled
], [])
   AT_CHECK([ovs-appctl vlog/set dpif_netdev:dbg], [0], [], [])
   AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
   for i in 1 2 3 4; do
       AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),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)'])
       AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:0b,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(src=10.0.0.4,dst=10.0.0.3,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)'])
       if [[ $i -eq 1 ]]; then
           sleep 1
       fi
   done
   sleep 1
   AT_CHECK([strip_ufid < ovs-vswitchd.log | filter_flow_install | strip_used], [0], [dnl
skb_priority(0),skb_mark(0),ct_state(-new-est-rel-rpl-inv-trk-snat-dnat),ct_zone(0),ct_mark(0),ct_label(0),recirc_id(0),dp_hash(0),in_port(1),packet_type(ns=0,id=0),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), actions:2
skb_priority(0),skb_mark(0),ct_state(-new-est-rel-rpl-inv-trk-snat-dnat),ct_zone(0),ct_mark(0),ct_label(0),recirc_id(0),dp_hash(0),in_port(1),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:0b,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(src=10.0.0.4,dst=10.0.0.3,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0), actions:drop
])
   AT_CHECK([strip_ufid < ovs-vswitchd.log | filter_flow_dump | grep 'packets:3'], [0], [dnl
skb_priority(0),skb_mark(0),ct_state(0/0xff),ct_zone(0),ct_mark(0),ct_label(0),recirc_id(0),dp_hash(0),in_port(1),packet_type(ns=0,id=0),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:3, bytes:318, used:0.0s, actions:2
skb_priority(0),skb_mark(0),ct_state(0/0xff),ct_zone(0),ct_mark(0),ct_label(0),recirc_id(0),dp_hash(0),in_port(1),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:0b,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(src=10.0.0.4,dst=10.0.0.3,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0), packets:3, bytes:318, used:0.0s, actions:drop
])
   OVS_VSWITCHD_STOP
   AT_CLEANUP])

OFPROTO_DPIF_MEGAFLOW_DISABLED([])
OFPROTO_DPIF_MEGAFLOW_DISABLED([ - pmd])

AT_SETUP([ofproto-dpif - datapath port number change])
OVS_VSWITCHD_START([set Bridge br0 fail-mode=standalone])
add_of_ports br0 1

# Trace a flow that should output to p1.
AT_CHECK([ovs-appctl ofproto/trace br0 in_port=LOCAL,dl_src=10:20:30:40:50:60],
  [0], [stdout])
AT_CHECK([tail -1 stdout], [0], [Datapath actions: 1
])

# Change p1's port number to 5.
AT_CHECK([ovs-appctl dpif-dummy/change-port-number ovs-dummy p1 5])

# Trace a flow that should output to p1 in its new location.
AT_CHECK([ovs-appctl ofproto/trace br0 in_port=LOCAL,dl_src=10:20:30:40:50:60],
  [0], [stdout])
AT_CHECK([tail -1 stdout], [0], [Datapath actions: 5
])
OVS_VSWITCHD_STOP
AT_CLEANUP

# Tests the bundling with various bfd and cfm configurations.
AT_SETUP([ofproto - bundle with variable bfd/cfm config])
OVS_VSWITCHD_START([add-br br1 -- set bridge br1 datapath-type=dummy -- \
                    add-bond br0 br0bond p0 p2 bond-mode=active-backup -- \
                    add-bond br1 br1bond p1 p3 bond-mode=active-backup -- \
                    set Interface p1 type=patch options:peer=p0 ofport_request=2 -- \
                    set Interface p3 type=patch options:peer=p2 ofport_request=4 -- \
                    set Interface p0 type=patch options:peer=p1 ofport_request=1 -- \
                    set Interface p2 type=patch options:peer=p3 ofport_request=3 -- \
                    set Interface p0 bfd:enable=true bfd:min_tx=300 bfd:min_rx=300 -- \
                    set Interface p0 cfm_mpid=1 -- \
                    set Interface p1 bfd:enable=true bfd:min_tx=500 bfd:min_rx=500])

ovs-appctl time/stop
# advance the clock to stablize everything.
ovs-appctl time/warp 5000 100
# cfm/show should show 'recv' fault.
AT_CHECK([ovs-appctl cfm/show | sed -n '/^.*fault:.*/p'], [0], [dnl
  fault: recv
])
# bfd/show should show 'up'.
AT_CHECK([ovs-appctl bfd/show | sed -n '/^.*Session State:.*/p'], [0], [dnl
  Local Session State: up
  Remote Session State: up
  Local Session State: up
  Remote Session State: up
])
# bond/show should show 'may-enable: true' for all members.
AT_CHECK([ovs-appctl bond/show | sed -n '/^.*may_enable:.*/p'], [0], [dnl
  may_enable: true
  may_enable: true
  may_enable: true
  may_enable: true
])

# now disable the bfd on p1.
AT_CHECK([ovs-vsctl set Interface p1 bfd:enable=false])
# advance the clock to stablize everything.
ovs-appctl time/warp 5000 100
# cfm/show should show 'recv' fault.
AT_CHECK([ovs-appctl cfm/show | sed -n '/^.*fault:.*/p'], [0], [dnl
  fault: recv
])
# bfd/show should show 'down'.
AT_CHECK([ovs-appctl bfd/show | sed -n '/^.*Session State:.*/p'], [0], [dnl
  Local Session State: down
  Remote Session State: down
])
# bond/show should show 'may-enable: false' for p0.
AT_CHECK([ovs-appctl bond/show br0bond | sed -n '/^.*may_enable:.*/p'], [0], [dnl
  may_enable: false
  may_enable: true
])

# now enable the bfd on p1 and disable bfd on p0.
AT_CHECK([ovs-vsctl set Interface p1 bfd:enable=true])
AT_CHECK([ovs-vsctl set Interface p0 bfd:enable=false])
# advance the clock to stablize everything.
ovs-appctl time/warp 5000 100
# cfm/show should show 'recv' fault.
AT_CHECK([ovs-appctl cfm/show | sed -n '/^.*fault:.*/p'], [0], [dnl
  fault: recv
])
# bfd/show should show 'down'.
AT_CHECK([ovs-appctl bfd/show | sed -n '/^.*Session State:.*/p'], [0], [dnl
  Local Session State: down
  Remote Session State: down
])
# bond/show should show 'may-enable: false' for p0 and p1.
AT_CHECK([ovs-appctl bond/show | sed -n '/^.*may_enable:.*/p'], [0], [dnl
  may_enable: false
  may_enable: true
  may_enable: false
  may_enable: true
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - ofproto-dpif-monitor 1])
OVS_VSWITCHD_START([add-port br0 p0 -- set interface p0 type=gre options:remote_ip=1.2.3.4])

# enable bfd on p0.
AT_CHECK([ovs-vsctl set interface p0 bfd:enable=true])
# check log.
OVS_WAIT_UNTIL([grep "monitor thread created" ovs-vswitchd.log])
# disable bfd on p0.
AT_CHECK([ovs-vsctl set interface p0 bfd:enable=false])
# check log.
OVS_WAIT_UNTIL([grep "monitor thread terminated" ovs-vswitchd.log])
AT_CHECK([sed -e '/^.*ofproto_dpif_monitor.*$/d' < ovs-vswitchd.log > tmp && ovs-appctl vlog/close && mv tmp ovs-vswitchd.log && ovs-appctl vlog/reopen])

# enable cfm on p0.
AT_CHECK([ovs-vsctl set interface p0 cfm_mpid=10])
# check log.
OVS_WAIT_UNTIL([grep "monitor thread created" ovs-vswitchd.log])
# disable cfm on p0.
AT_CHECK([ovs-vsctl remove interface p0 cfm_mpid 10])
# check log.
OVS_WAIT_UNTIL([grep "monitor thread terminated" ovs-vswitchd.log])
AT_CHECK([sed -e '/^.*ofproto_dpif_monitor.*$/d' < ovs-vswitchd.log > tmp && ovs-appctl vlog/close && mv tmp ovs-vswitchd.log && ovs-appctl vlog/reopen])

# enable both bfd and cfm on p0.
AT_CHECK([ovs-vsctl set interface p0 bfd:enable=true cfm_mpid=10])
# check log.
OVS_WAIT_UNTIL([grep "monitor thread created" ovs-vswitchd.log])
# disable bfd on p0.
AT_CHECK([ovs-vsctl set interface p0 bfd:enable=false])
# check log, there should not be the log of thread terminated.
AT_CHECK([sed -n "s/^.*|ofproto_dpif_monitor(monitor[[0-9]]*)|INFO|\(.* terminated\)$/\1/p" ovs-vswitchd.log], [0], [dnl
])
# reenable bfd on p0.
AT_CHECK([ovs-vsctl set interface p0 bfd:enable=true])
# check log, should still be on log of thread created.
AT_CHECK([sed -n "s/^.*|ofproto_dpif_monitor(monitor[[0-9]]*)|INFO|\(.* created\)$/\1/p" ovs-vswitchd.log], [0], [dnl
monitor thread created
])
# disable bfd and cfm together.
AT_CHECK([ovs-vsctl set interface p0 bfd:enable=false -- remove interface p0 cfm_mpid 10])
# check log.
OVS_WAIT_UNTIL([grep "monitor thread terminated" ovs-vswitchd.log])

OVS_VSWITCHD_STOP
AT_CLEANUP

# this test helps avoid the deadlock between the main thread and monitor thread.
AT_SETUP([ofproto-dpif - ofproto-dpif-monitor 2])
OVS_VSWITCHD_START

for i in `seq 1 199`
do
    AT_CHECK([ovs-vsctl add-port br0 p$i -- set interface p$i type=gre options:remote_ip=1.2.3.4 options:key=$i bfd:enable=true])
done

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_BANNER([ofproto-dpif - flow translation resource limits])

dnl Resubmits to later tables do not count against the depth limit, so we
dnl can do 99 of them even though the maximum depth is 64.
AT_SETUP([ofproto-dpif - forward resubmit])
OVS_VSWITCHD_START
(for i in `seq 0 99`; do
    j=`expr $i + 1`
    echo "table=$i, actions=resubmit(,$j)"
 done
 echo "table=100, actions=local") > flows
AT_CHECK([ovs-ofctl add-flows br0 flows])
AT_CHECK([ovs-appctl -vpoll_loop:off ofproto/trace br0 'eth_dst=ff:ff:ff:ff:ff:ff'],
  [0], [stdout])
AT_CHECK([tail -1 stdout], [0], [Datapath actions: 100
])
OVS_VSWITCHD_STOP
AT_CLEANUP

dnl Resubmits to the same or an earlier table count against the depth limit,
dnl so only 64 of them are allowed.
AT_SETUP([ofproto-dpif - backward resubmit])
OVS_VSWITCHD_START
(echo "table=0, actions=resubmit(,66)"
 for i in `seq 2 66`; do
    j=`expr $i - 1`
    echo "table=$i, actions=resubmit(,$j)"
 done
 echo "table=1, actions=local") > flows
AT_CHECK([ovs-ofctl add-flows br0 flows])
AT_CHECK([ovs-appctl -vpoll_loop:off ofproto/trace br0 'eth_dst=ff:ff:ff:ff:ff:ff'],
  [0], [stdout])
AT_CHECK([tail -1 stdout], [0],
  [Translation failed (Recursion too deep), packet is dropped.
])
AT_CHECK([grep -c 'over max translation depth 64' stdout],
  [0], [1
])
OVS_VSWITCHD_STOP(["/resubmit actions recursed/d"])
AT_CLEANUP

AT_SETUP([ofproto-dpif - infinite resubmit])
OVS_VSWITCHD_START
AT_CHECK([ovs-ofctl add-flow br0 actions=resubmit:1,resubmit:2,output:3])
AT_CHECK([ovs-appctl -vpoll_loop:off ofproto/trace br0 'eth_dst=ff:ff:ff:ff:ff:ff'],
  [0], [stdout])
AT_CHECK([tail -1 stdout], [0],
  [Translation failed (Recursion too deep), packet is dropped.
])
AT_CHECK([grep -c 'over max translation depth 64' stdout],
  [0], [1
])
OVS_VSWITCHD_STOP(["/resubmit actions recursed/d"])
AT_CLEANUP

dnl Without using ofproto/trace, make sure the
dnl ofproto trace is still logged
AT_SETUP([ofproto-dpif - backward resubmit without trace])
OVS_VSWITCHD_START
(echo "table=0, actions=resubmit(,66)"
 for i in `seq 2 66`; do
    j=`expr $i - 1`
    echo "table=$i, actions=resubmit(,$j)"
 done
 echo "table=1, actions=local") > flows
AT_CHECK([ovs-ofctl add-flows br0 flows])

AT_CHECK([ovs-appctl netdev-dummy/receive br0 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x1234)'], [0], [stdout])

OVS_WAIT_UNTIL([grep 'packet is dropped' ovs-vswitchd.log])

dnl make sure the full ofproto trace dump is present
AT_CHECK([grep -c "^ *resubmit" ovs-vswitchd.log],
  [0], [66
])

OVS_VSWITCHD_STOP(["/over max translation depth/d
/ofproto_dpif_upcall/d"])
AT_CLEANUP

AT_SETUP([ofproto-dpif - exponential resubmit chain])
OVS_VSWITCHD_START
add_of_ports br0 1
(for i in `seq 1 64`; do
     j=`expr $i + 1`
     echo "in_port=$i, actions=resubmit:$j, resubmit:$j, local"
 done
 echo "in_port=65, actions=local") > flows
 AT_CHECK([ovs-ofctl add-flows br0 flows])
AT_CHECK([ovs-appctl -vpoll_loop:off ofproto/trace br0 'in_port=1'], [0], [stdout])
AT_CHECK([tail -1 stdout], [0],
  [Translation failed (Too many resubmits), packet is dropped.
])
AT_CHECK([grep -c 'over 4096 resubmit actions' stdout], [0], [1
])
OVS_VSWITCHD_STOP(["/over.*resubmit actions/d"])
AT_CLEANUP

AT_SETUP([ofproto-dpif - too many output actions])
OVS_VSWITCHD_START
add_of_ports br0 1
(for i in `seq 1 12`; do
     j=`expr $i + 1`
     echo "in_port=$i, actions=resubmit:$j, resubmit:$j, local"
 done
 echo "in_port=13, actions=local,local,local,local,local,local,local,local") > flows
AT_CHECK([ovs-ofctl add-flows br0 flows])
AT_CHECK([ovs-appctl -vpoll_loop:off ofproto/trace br0 'in_port=1'], [0], [stdout])
AT_CHECK([grep -c -e '- Uses action(s) not supported by datapath' stdout],
  [0], [1
])
AT_CHECK([grep -c 'resubmits yielded over 64 kB of actions' stdout], [0], [1
])
OVS_VSWITCHD_STOP(["/resubmits yielded over 64 kB of actions/d"])
AT_CLEANUP

AT_SETUP([ofproto-dpif - stack too deep])
OVS_VSWITCHD_START
add_of_ports br0 1
(for i in `seq 1 12`; do
     j=`expr $i + 1`
     echo "in_port=$i, actions=resubmit:$j, resubmit:$j, local"
 done
 push="push:NXM_NX_REG0[[]]"
 echo "in_port=13, actions=$push,$push,$push,$push,$push,$push,$push,$push") > flows
 AT_CHECK([ovs-ofctl add-flows br0 flows])
AT_CHECK([ovs-appctl -vpoll_loop:off ofproto/trace br0 'in_port=1'], [0], [stdout])
AT_CHECK([tail -1 stdout], [0],
  [Translation failed (Stack too deep), packet is dropped.
])
AT_CHECK([grep -c 'resubmits yielded over 64 kB of stack' stdout], [0], [1
])
OVS_VSWITCHD_STOP(["/resubmits yielded over 64 kB of stack/d"])
AT_CLEANUP


AT_SETUP([ofproto-dpif packet-out controller])
OVS_VSWITCHD_START
add_of_ports br0 1 2

AT_CHECK([ovs-ofctl add-flow br0 'dl_dst=50:54:00:00:00:0a actions=controller'])

AT_CAPTURE_FILE([ofctl_monitor.log])
AT_CHECK([ovs-ofctl monitor br0 65534 invalid_ttl -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3; do
        AT_CHECK([ovs-ofctl -O OpenFlow13 packet-out br0 CONTROLLER controller '50540000000a5054000000091234'])
done

OVS_APP_EXIT_AND_WAIT([ovs-ofctl])
AT_CHECK([cat ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): total_len=14 in_port=CONTROLLER (via action) data_len=14 (unbuffered)
vlan_tci=0x0000,dl_src=50:54:00:00:00:09,dl_dst=50:54:00:00:00:0a,dl_type=0x1234
dnl
NXT_PACKET_IN (xid=0x0): total_len=14 in_port=CONTROLLER (via action) data_len=14 (unbuffered)
vlan_tci=0x0000,dl_src=50:54:00:00:00:09,dl_dst=50:54:00:00:00:0a,dl_type=0x1234
dnl
NXT_PACKET_IN (xid=0x0): total_len=14 in_port=CONTROLLER (via action) data_len=14 (unbuffered)
vlan_tci=0x0000,dl_src=50:54:00:00:00:09,dl_dst=50:54:00:00:00:0a,dl_type=0x1234
])

AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
 dl_dst=50:54:00:00:00:0a actions=CONTROLLER:65535
NXST_FLOW reply:
])

AT_CHECK([ovs-ofctl -O OpenFlow13 dump-tables br0], [0],
  [OFPST_TABLE reply (OF1.3) (xid=0x2):
  table 0:
    active=1, lookup=0, matched=0

  table 1:
    active=0, lookup=0, matched=0

  tables 2...253: ditto
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif packet-out controller (patch port)])
OVS_VSWITCHD_START(
  [-- \
   add-port br0 p1 -- \
   set interface p1 type=patch options:peer=p2 -- \
   add-br br1 -- \
   set bridge br1 datapath-type=dummy -- \
   set bridge br1 fail-mode=secure -- \
   set bridge br1 protocols='[OpenFlow10,OpenFlow11,OpenFlow12,OpenFlow13]' -- \
   add-port br1 p2 -- \
   set interface p2 type=patch options:peer=p1 --])

AT_CAPTURE_FILE([ofctl_monitor.log])
AT_CHECK([ovs-ofctl monitor br1 65534 invalid_ttl -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3; do
        AT_CHECK([ovs-ofctl -O OpenFlow13 packet-out br0 CONTROLLER output:1 '50540000000a5054000000091234'])
done

OVS_APP_EXIT_AND_WAIT([ovs-ofctl])
AT_CHECK([cat ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): cookie=0x0 total_len=14 in_port=1 (via no_match) data_len=14 (unbuffered)
vlan_tci=0x0000,dl_src=50:54:00:00:00:09,dl_dst=50:54:00:00:00:0a,dl_type=0x1234
dnl
NXT_PACKET_IN (xid=0x0): cookie=0x0 total_len=14 in_port=1 (via no_match) data_len=14 (unbuffered)
vlan_tci=0x0000,dl_src=50:54:00:00:00:09,dl_dst=50:54:00:00:00:0a,dl_type=0x1234
dnl
NXT_PACKET_IN (xid=0x0): cookie=0x0 total_len=14 in_port=1 (via no_match) data_len=14 (unbuffered)
vlan_tci=0x0000,dl_src=50:54:00:00:00:09,dl_dst=50:54:00:00:00:0a,dl_type=0x1234
])

AT_CHECK([ovs-ofctl -O OpenFlow13 dump-tables br0], [0], [dnl
OFPST_TABLE reply (OF1.3) (xid=0x2):
  table 0:
    active=0, lookup=0, matched=0

  tables 1...253: ditto
])

AT_CHECK([ovs-ofctl -O OpenFlow13 dump-tables br1], [0], [dnl
OFPST_TABLE reply (OF1.3) (xid=0x2):
  table 0:
    active=0, lookup=3, matched=0

  table 1:
    active=0, lookup=0, matched=0

  tables 2...253: ditto
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif packet-out pipeline match field (OpenFlow 1.5)])
OVS_VSWITCHD_START

AT_CHECK([ovs-ofctl add-tlv-map br0 "{class=0xffff,type=0,len=8}->tun_metadata2"])
AT_CHECK([ovs-ofctl add-tlv-map br0 "{class=0xffff,type=1,len=4}->tun_metadata3"])
AT_DATA([flows.txt], [dnl
table=0,in_port=1 actions=controller
table=0,tun_id=3 actions=controller
table=0,metadata=5 actions=controller
table=0,reg0=1,reg4=2,reg8=3,reg12=5 actions=controller
table=0,tun_src=1.1.1.1,tun_dst=2.2.2.2,tun_gbp_id=0x01,tun_gbp_flags=0x03 actions=controller
table=0,tun_metadata3=0x11 actions=controller
])
AT_CHECK([ovs-ofctl -O OpenFlow15 add-flows br0 flows.txt])

AT_CHECK([ovs-ofctl -O OpenFlow15 -P standard monitor br0 --detach --no-chdir --pidfile])
ovs-appctl -t ovs-ofctl ofctl/send 0609000c0123456700000080
ovs-appctl -t ovs-ofctl ofctl/barrier
ovs-appctl -t ovs-ofctl ofctl/set-output-file monitor.log
AT_CAPTURE_FILE([monitor.log])

AT_CHECK([ovs-ofctl -O OpenFlow15 packet-out br0 "in_port=1 packet=0001020304050010203040501111 actions=table"])
AT_CHECK([ovs-ofctl -O OpenFlow15 packet-out br0 "in_port=2,tunnel_id=3 packet=0001020304050010203040502222 actions=table"])
AT_CHECK([ovs-ofctl -O OpenFlow15 packet-out br0 "in_port=2,metadata=5 packet=0001020304050010203040503333 actions=table"])
AT_CHECK([ovs-ofctl -O OpenFlow15 packet-out br0 "in_port=2,reg0=1,reg4=2,reg8=3,reg12=5 packet=0001020304050010203040503333 actions=table"])
AT_CHECK([ovs-ofctl -O OpenFlow15 packet-out br0 "in_port=2,tun_src=1.1.1.1,tun_dst=2.2.2.2,tun_gbp_id=0x01,tun_gbp_flags=0x03 packet=0001020304050010203040503333 actions=table"])
AT_CHECK([ovs-ofctl -O OpenFlow15 packet-out br0 "in_port=2,tun_metadata2=0x22,tun_metadata3=0x11 packet=0001020304050010203040503333 actions=table"])

ovs-appctl -t ovs-ofctl ofctl/barrier
OVS_APP_EXIT_AND_WAIT([ovs-ofctl])

AT_CHECK([sed 's/ (xid=0x[[0-9a-fA-F]]*)//' monitor.log], [0], [dnl
OFPT_PACKET_IN (OF1.5): cookie=0x0 total_len=14 in_port=1 (via packet_out) data_len=14 (unbuffered)
vlan_tci=0x0000,dl_src=00:10:20:30:40:50,dl_dst=00:01:02:03:04:05,dl_type=0x1111
OFPT_PACKET_IN (OF1.5): cookie=0x0 total_len=14 tun_id=0x3,in_port=2 (via packet_out) data_len=14 (unbuffered)
vlan_tci=0x0000,dl_src=00:10:20:30:40:50,dl_dst=00:01:02:03:04:05,dl_type=0x2222
OFPT_PACKET_IN (OF1.5): cookie=0x0 total_len=14 metadata=0x5,in_port=2 (via packet_out) data_len=14 (unbuffered)
vlan_tci=0x0000,dl_src=00:10:20:30:40:50,dl_dst=00:01:02:03:04:05,dl_type=0x3333
OFPT_PACKET_IN (OF1.5): cookie=0x0 total_len=14 reg0=0x1,reg4=0x2,reg8=0x3,reg12=0x5,in_port=2 (via packet_out) data_len=14 (unbuffered)
vlan_tci=0x0000,dl_src=00:10:20:30:40:50,dl_dst=00:01:02:03:04:05,dl_type=0x3333
OFPT_PACKET_IN (OF1.5): cookie=0x0 total_len=14 tun_src=1.1.1.1,tun_dst=2.2.2.2,tun_gbp_id=1,tun_gbp_flags=0x3,in_port=2 (via packet_out) data_len=14 (unbuffered)
vlan_tci=0x0000,dl_src=00:10:20:30:40:50,dl_dst=00:01:02:03:04:05,dl_type=0x3333
OFPT_PACKET_IN (OF1.5): cookie=0x0 total_len=14 tun_metadata2=0x22,tun_metadata3=0x11,in_port=2 (via packet_out) data_len=14 (unbuffered)
vlan_tci=0x0000,dl_src=00:10:20:30:40:50,dl_dst=00:01:02:03:04:05,dl_type=0x3333
OFPT_BARRIER_REPLY (OF1.5):
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif packet-out goto_table])
OVS_VSWITCHD_START
add_of_ports br0 1 2

AT_DATA([flows.txt], [dnl
table=0 dl_dst=50:54:00:00:00:0a actions=goto_table(1)
table=1 dl_dst=50:54:00:00:00:0a actions=controller
])
AT_CHECK([ovs-ofctl -O OpenFlow13 add-flows br0 flows.txt])

AT_CAPTURE_FILE([ofctl_monitor.log])
AT_CHECK([ovs-ofctl monitor br0 65534 invalid_ttl -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3; do
    ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x1234)'
done

OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6])
OVS_APP_EXIT_AND_WAIT([ovs-ofctl])
AT_CHECK([cat ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): table_id=1 cookie=0x0 total_len=14 in_port=1 (via action) data_len=14 (unbuffered)
vlan_tci=0x0000,dl_src=50:54:00:00:00:09,dl_dst=50:54:00:00:00:0a,dl_type=0x1234
dnl
NXT_PACKET_IN (xid=0x0): table_id=1 cookie=0x0 total_len=14 in_port=1 (via action) data_len=14 (unbuffered)
vlan_tci=0x0000,dl_src=50:54:00:00:00:09,dl_dst=50:54:00:00:00:0a,dl_type=0x1234
dnl
NXT_PACKET_IN (xid=0x0): table_id=1 cookie=0x0 total_len=14 in_port=1 (via action) data_len=14 (unbuffered)
vlan_tci=0x0000,dl_src=50:54:00:00:00:09,dl_dst=50:54:00:00:00:0a,dl_type=0x1234
])

AT_CHECK([ovs-appctl revalidator/purge], [0])
AT_CHECK([ovs-ofctl -O OpenFlow13 dump-flows br0 | ofctl_strip | sort], [0], [dnl
 n_packets=3, n_bytes=42, dl_dst=50:54:00:00:00:0a actions=goto_table:1
 table=1, n_packets=3, n_bytes=42, dl_dst=50:54:00:00:00:0a actions=CONTROLLER:65535
OFPST_FLOW reply (OF1.3):
])

AT_CHECK([ovs-ofctl -O OpenFlow13 dump-tables br0], [0], [dnl
OFPST_TABLE reply (OF1.3) (xid=0x2):
  table 0:
    active=1, lookup=3, matched=3

  table 1: ditto

  table 2:
    active=0, lookup=0, matched=0

  tables 3...253: ditto
])

OVS_VSWITCHD_STOP
AT_CLEANUP


AT_SETUP([ofproto-dpif packet-out table-miss (continue)])
OVS_VSWITCHD_START
add_of_ports br0 1 2

AT_CHECK([ovs-ofctl -O OpenFlow11 add-flow br0 'table=1 dl_dst=50:54:00:00:00:0a actions=controller'])
AT_CHECK([ovs-ofctl -O OpenFlow11 mod-table br0 all continue])

AT_CAPTURE_FILE([ofctl_monitor.log])
AT_CHECK([ovs-ofctl monitor br0 65534 invalid_ttl -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3; do
    ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x1234)'
done

OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6])
OVS_APP_EXIT_AND_WAIT([ovs-ofctl])
AT_CHECK([cat ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): table_id=1 cookie=0x0 total_len=14 in_port=1 (via action) data_len=14 (unbuffered)
vlan_tci=0x0000,dl_src=50:54:00:00:00:09,dl_dst=50:54:00:00:00:0a,dl_type=0x1234
dnl
NXT_PACKET_IN (xid=0x0): table_id=1 cookie=0x0 total_len=14 in_port=1 (via action) data_len=14 (unbuffered)
vlan_tci=0x0000,dl_src=50:54:00:00:00:09,dl_dst=50:54:00:00:00:0a,dl_type=0x1234
dnl
NXT_PACKET_IN (xid=0x0): table_id=1 cookie=0x0 total_len=14 in_port=1 (via action) data_len=14 (unbuffered)
vlan_tci=0x0000,dl_src=50:54:00:00:00:09,dl_dst=50:54:00:00:00:0a,dl_type=0x1234
])

AT_CHECK([ovs-appctl revalidator/purge], [0])
AT_CHECK([ovs-ofctl -O OpenFlow11 dump-flows br0 | ofctl_strip | sort], [0], [dnl
 table=1, n_packets=3, n_bytes=42, dl_dst=50:54:00:00:00:0a actions=CONTROLLER:65535
OFPST_FLOW reply (OF1.1):
])

AT_CHECK([ovs-ofctl -O OpenFlow13 dump-tables br0], [0], [dnl
OFPST_TABLE reply (OF1.3) (xid=0x2):
  table 0:
    active=0, lookup=3, matched=0

  table 1:
    active=1, lookup=3, matched=3

  table 2:
    active=0, lookup=0, matched=0

  tables 3...253: ditto
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif packet-out table meter drop])
OVS_VSWITCHD_START
add_of_ports br0 1 2

AT_CHECK([ovs-ofctl -O OpenFlow13 add-meter br0 'meter=1 pktps bands=type=drop rate=1'])
AT_CHECK([ovs-ofctl -O OpenFlow13 add-flow br0 'in_port=1 action=meter:1,output:2'])

ovs-ofctl -O OpenFlow13 packet-out br0 "in_port=1 packet=50540000000a50540000000908004500001c000000000011a4cd0a0101010a0101020001000400080000 actions=resubmit(,0)"
ovs-ofctl -O OpenFlow13 packet-out br0 "in_port=1 packet=50540000000a50540000000908004500001c000000000011a4cd0a0101010a0101020001000400080000 actions=resubmit(,0)"

# Check that vswitchd hasn't crashed by dumping the meter added above
AT_CHECK([ovs-ofctl -O OpenFlow13 dump-meters br0 | ofctl_strip], [0], [dnl
OFPST_METER_CONFIG reply (OF1.3):
meter=1 pktps bands=
type=drop rate=1
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - ICMPv6])
OVS_VSWITCHD_START
add_of_ports br0 1

AT_CAPTURE_FILE([ofctl_monitor.log])

AT_CHECK([ovs-ofctl monitor br0 65534 -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

ovs-appctl netdev-dummy/receive p1 '0060970769ea0000860580da86dd6000000000203afffe80000000000000020086fffe0580dafe80000000000000026097fffe0769ea870068bd00000000fe80000000000000026097fffe0769ea01010000860580da'

OVS_APP_EXIT_AND_WAIT([ovs-ofctl])

AT_CHECK([cat ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): cookie=0x0 total_len=86 in_port=1 (via no_match) data_len=86 (unbuffered)
icmp6,vlan_tci=0x0000,dl_src=00:00:86:05:80:da,dl_dst=00:60:97:07:69:ea,ipv6_src=fe80::200:86ff:fe05:80da,ipv6_dst=fe80::260:97ff:fe07:69ea,ipv6_label=0x00000,nw_tos=0,nw_ecn=0,nw_ttl=255,icmp_type=135,icmp_code=0,nd_target=fe80::260:97ff:fe07:69ea,nd_sll=00:00:86:05:80:da,nd_tll=00:00:00:00:00:00 icmp6_csum:68bd
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - ICMPv6 type match])
OVS_VSWITCHD_START
add_of_ports br0 1 2 3

AT_CHECK([ovs-ofctl add-flow br0 'icmp6,icmp_type=128,actions=2'])
AT_CHECK([ovs-ofctl add-flow br0 'icmp6,icmp_type=129,actions=3'])

AT_CHECK([ovs-appctl vlog/set dpif:dbg dpif_netdev:dbg])

AT_CHECK([ovs-appctl netdev-dummy/receive p1 'recirc_id(0),in_port(1),eth(src=f2:49:6e:52:49:0b,dst=02:b7:d7:17:ff:72),eth_type(0x86dd),ipv6(proto=58,frag=no),icmpv6(type=128)'])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'recirc_id(0),in_port(1),eth(src=f2:49:6e:52:49:0b,dst=02:b7:d7:17:ff:72),eth_type(0x86dd),ipv6(proto=58,frag=no),icmpv6(type=128)'])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'recirc_id(0),in_port(1),eth(src=f2:49:6e:52:49:0b,dst=02:b7:d7:17:ff:72),eth_type(0x86dd),ipv6(proto=58,frag=no),icmpv6(type=129)'])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'recirc_id(0),in_port(1),eth(src=f2:49:6e:52:49:0b,dst=02:b7:d7:17:ff:72),eth_type(0x86dd),ipv6(proto=58,frag=no),icmpv6(type=129)'])

AT_CHECK([ovs-appctl revalidator/purge], [0])

AT_CHECK([strip_ufid < ovs-vswitchd.log | filter_flow_install | strip_used], [0], [dnl
recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x86dd),ipv6(proto=58,frag=no),icmpv6(type=128), actions:2
recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x86dd),ipv6(proto=58,frag=no),icmpv6(type=129), actions:3
])

AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
 n_packets=2, n_bytes=252, icmp6,icmp_type=128 actions=output:2
 n_packets=2, n_bytes=252, icmp6,icmp_type=129 actions=output:3
NXST_FLOW reply:
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - Neighbor Discovery set-field with checksum update])
OVS_VSWITCHD_START
add_of_ports br0 1
AT_CHECK([ovs-ofctl add-flow br0 icmp6,icmpv6_type=135,action=set_field:fe80::1-\>nd_target,set_field:32:21:14:86:11:74-\>nd_sll,output:controller])

AT_CAPTURE_FILE([ofctl_monitor.log])

AT_CHECK([ovs-ofctl monitor br0 65534 -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

ovs-appctl netdev-dummy/receive p1 '0060970769ea0000860580da86dd6000000000203afffe80000000000000020086fffe0580dafe80000000000000026097fffe0769ea870068bd00000000fe80000000000000026097fffe0769ea01010000860580da'

OVS_APP_EXIT_AND_WAIT([ovs-ofctl])

AT_CHECK([cat ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): cookie=0x0 total_len=86 in_port=1 (via action) data_len=86 (unbuffered)
icmp6,vlan_tci=0x0000,dl_src=00:00:86:05:80:da,dl_dst=00:60:97:07:69:ea,ipv6_src=fe80::200:86ff:fe05:80da,ipv6_dst=fe80::260:97ff:fe07:69ea,ipv6_label=0x00000,nw_tos=0,nw_ecn=0,nw_ttl=255,icmp_type=135,icmp_code=0,nd_target=fe80::1,nd_sll=32:21:14:86:11:74,nd_tll=00:00:00:00:00:00 icmp6_csum:19d3
])

OVS_VSWITCHD_STOP
AT_CLEANUP

# Tests the exact match of CFI bit in installed datapath flows matching VLAN.
AT_SETUP([ofproto-dpif - vlan matching])
OVS_VSWITCHD_START(
  [add-port br0 p0 -- set Interface p0 type=dummy ofport_request=1])
AT_CHECK([ovs-appctl vlog/set dpif:dbg dpif_netdev:dbg])

AT_CHECK([ovs-ofctl del-flows br0])
AT_CHECK([ovs-ofctl add-flow br0 "vlan_tci=0x000a/0x0fff,action=output:local"])

AT_CHECK([ovs-appctl netdev-dummy/receive p0 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x8100),vlan(vid=10,pcp=0),encap(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))'])

OVS_WAIT_UNTIL([grep flow_add: ovs-vswitchd.log])
AT_CHECK([filter_flow_install < ovs-vswitchd.log | grep 'in_port([[1]])' | strip_xout], [0], [dnl
recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x8100),vlan(vid=10),encap(eth_type(0x0800),ipv4(frag=no)), actions: <del>
])
OVS_VSWITCHD_STOP
AT_CLEANUP

# Tests in place modification of installed datapath flows.
AT_SETUP([ofproto-dpif - in place modification])
OVS_VSWITCHD_START(
  [add-port br0 p1 -- set Interface p1 type=dummy ofport_request=1])
AT_CHECK([ovs-appctl vlog/set dpif:dbg dpif_netdev:dbg])

AT_CHECK([ovs-ofctl del-flows br0])
AT_CHECK([ovs-ofctl add-flow br0 in_port=1,actions=mod_vlan_vid:3,output:local])

ovs-appctl vlog/set PATTERN:ANY:'%c|%p|%m'

ovs-appctl time/stop

AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x1234)'])

# Wait for the flow setup to be done.
OVS_WAIT_UNTIL([grep 'flow_add:' ovs-vswitchd.log])

for i in 1 2; do
    ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x1234)'
done

AT_CHECK([ovs-appctl dpif/dump-flows br0 | strip_ufid | strip_used | sort], [0], [dnl
recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x1234), packets:2, bytes:28, used:0.0s, actions:push_vlan(vid=3,pcp=0),100
])

AT_CHECK([ovs-ofctl add-flow br0 priority=60000,in_port=1,actions=mod_vlan_vid:4,output:local])

ovs-appctl time/warp 500
ovs-appctl time/warp 500

for i in 1 2 3; do
    ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x1234)'
done

AT_CHECK([ovs-appctl dpif/dump-flows br0 | strip_ufid | strip_used | sort], [0], [dnl
recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x1234), packets:5, bytes:70, used:0.0s, actions:push_vlan(vid=4,pcp=0),100
])

AT_CHECK([grep 'modify' ovs-vswitchd.log | strip_ufid ], [0], [dnl
dpif|DBG|dummy@ovs-dummy: put[[modify]] skb_priority(0/0),skb_mark(0/0),ct_state(0/0),ct_zone(0/0),ct_mark(0/0),ct_label(0/0),recirc_id(0),dp_hash(0/0),in_port(1),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:09/00:00:00:00:00:00,dst=50:54:00:00:00:0a/00:00:00:00:00:00),eth_type(0x1234), actions:push_vlan(vid=4,pcp=0),100
])
OVS_VSWITCHD_STOP
AT_CLEANUP

# Tests in place modification of installed datapath flows with vlans.
AT_SETUP([ofproto-dpif - in place modification (vlan)])
OVS_VSWITCHD_START(
  [add-port br0 p1 -- set Interface p1 type=dummy ofport_request=1])
AT_CHECK([ovs-appctl vlog/set dpif:dbg dpif_netdev:dbg])

# Always drop misses
AT_CHECK([ovs-ofctl -O OpenFlow11 mod-table br0 all drop])
AT_CHECK([ovs-ofctl add-flow br0 in_port=1,actions=output:local])

ovs-appctl vlog/set PATTERN:ANY:'%c|%p|%m'

ovs-appctl time/stop

AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x1234)'])

# Check that a correct datapath flow is created.
OVS_WAIT_UNTIL([grep 'flow_add:' ovs-vswitchd.log])

for i in 1 2; do
    ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x1234)'
done

AT_CHECK([ovs-appctl dpif/dump-flows br0 | strip_ufid | strip_used | sort], [0], [dnl
recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x1234), packets:2, bytes:28, used:0.0s, actions:100
])

# Delete the flow.  Then check that the datapath flow is modified to
# drop the packets.  A modified flow inherits the stats, a new
# datapath flow would start from sero.
AT_CHECK([ovs-ofctl del-flows br0])

ovs-appctl time/warp 500
ovs-appctl time/warp 500

for i in 1 2 3; do
    ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x1234)'
done

AT_CHECK([ovs-appctl dpif/dump-flows br0 | strip_ufid | strip_used | sort], [0], [dnl
recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x1234), packets:5, bytes:70, used:0.0s, actions:drop
])

# Add a flow that matches the non-presence of a vlan tag, and check
# that the datapath flow is modified accordingly.
AT_CHECK([ovs-ofctl add-flow br0 in_port=1,vlan_tci=0x0000/0x1fff,actions=output:local])

ovs-appctl time/warp 500
ovs-appctl time/warp 500

for i in 1 2 3; do
    ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x1234)'
done

AT_CHECK([ovs-appctl dpif/dump-flows br0 | strip_ufid | strip_used | sort], [0], [dnl
recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x1234), packets:8, bytes:112, used:0.0s, actions:100
])

# Check that VLAN packets will not hit the same datapath megaflow.

AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x8100),vlan(vid=99,pcp=7),encap(eth_type(0x1234))'])
OVS_WAIT_UNTIL([grep 'flow_add:.*dl_vlan=99' ovs-vswitchd.log])

for i in 1 2; do
    ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x8100),vlan(vid=99,pcp=7),encap(eth_type(0x1234))'
done

AT_CHECK([ovs-appctl dpif/dump-flows br0 | strip_ufid | strip_used | sort], [0], [dnl
recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x1234), packets:8, bytes:112, used:0.0s, actions:100
recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x8100),vlan(vid=99,pcp=7/0x0),encap(eth_type(0x1234)), packets:2, bytes:36, used:0.0s, actions:drop
])

# Check that the new flow matches the CFI bit, while both vid and pcp
# are wildcarded.
AT_CHECK([grep '\(modify\)\|\(flow_add\)' ovs-vswitchd.log | strip_ufid ], [0], [dnl
dpif_netdev|DBG|flow_add: in_port=1,vlan_tci=0x0000,dl_src=50:54:00:00:00:09,dl_dst=50:54:00:00:00:0a,dl_type=0x1234, actions:100
dpif|DBG|dummy@ovs-dummy: put[[modify]] skb_priority(0/0),skb_mark(0/0),ct_state(0/0),ct_zone(0/0),ct_mark(0/0),ct_label(0/0),recirc_id(0),dp_hash(0/0),in_port(1),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:09/00:00:00:00:00:00,dst=50:54:00:00:00:0a/00:00:00:00:00:00),eth_type(0x1234), actions:drop
dpif|DBG|dummy@ovs-dummy: put[[modify]] skb_priority(0/0),skb_mark(0/0),ct_state(0/0),ct_zone(0/0),ct_mark(0/0),ct_label(0/0),recirc_id(0),dp_hash(0/0),in_port(1),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:09/00:00:00:00:00:00,dst=50:54:00:00:00:0a/00:00:00:00:00:00),eth_type(0x1234), actions:100
dpif_netdev|DBG|flow_add: in_port=1,dl_vlan=99,dl_vlan_pcp=7,vlan_tci1=0x0000,dl_src=50:54:00:00:00:09,dl_dst=50:54:00:00:00:0a,dl_type=0x1234, actions:drop
])
OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - trace (unchanged)])
OVS_VSWITCHD_START
AT_CHECK([ovs-appctl ofproto/trace br0 'in_port=1'], [0], [stdout])
AT_CHECK([grep "Final flow:" stdout], [0], [Final flow: unchanged
])
AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(100)'], [0], [stdout])
AT_CHECK([grep "Final flow:" stdout], [0], [Final flow: unchanged
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - conntrack - controller])
OVS_VSWITCHD_START

add_of_ports br0 1 2

AT_CHECK([ovs-appctl vlog/set dpif_netdev:dbg vconn:info ofproto_dpif:info])

dnl Allow new UDP connections on p1 for dst port 2, drop everything else.
AT_DATA([flows.txt], [dnl
dnl Table 0
dnl Store zone in reg4 and packet direction in reg3 (IN=1, OUT=2).
dnl
table=0,priority=100,arp,action=normal
table=0,priority=10,in_port=1,ip,action=set_field:1->reg4,set_field:1->reg3,ct(zone=NXM_NX_REG4[[0..15]],table=1)
table=0,priority=10,in_port=2,ip,action=set_field:1->reg4,set_field:2->reg3,ct(zone=NXM_NX_REG4[[0..15]],table=1)
table=0,priority=1,action=drop
dnl
dnl Pass tracked traffic through ACL, drop everything else.
dnl Non-REPLY/RELATED packets get the ACL lookup with the packet headers
dnl in the actual packet direction in reg0 (IN=1, OUT=2).  REPLY packets
dnl get the ACL lookup using the conntrack tuple and the inverted direction.
dnl RELATED packets get ACL lookup using the conntrack tuple in the direction
dnl of the parent connection, as storted in ct_mark.
dnl
dnl Incoming non-related packet in the original direction (ACL IN)
table=1 reg3=1, ip, ct_state=-rel-rpl+trk-inv action=set_field:1->reg0,resubmit(,3),goto_table:5
dnl Incoming non-related reply packet (CT ACL OUT)
table=1 reg3=1, ip, ct_state=-rel+rpl+trk-inv action=set_field:2->reg0,resubmit(,3,ct),goto_table:4
dnl Outgoing non-related packet (ACL OUT)
table=1 reg3=2, ip, ct_state=-rel-rpl+trk-inv action=set_field:2->reg0,resubmit(,3),goto_table:5
dnl Outgoing non-related reply packet (CT ACL IN)
table=1 reg3=2, ip, ct_state=-rel+rpl+trk-inv action=set_field:1->reg0,resubmit(,3,ct),goto_table:4
dnl
dnl Related packet (CT ACL in the direction of the parent connection.)
table=1 ip, ct_state=+rel+trk-inv, action=move:NXM_NX_CT_MARK[[]]->NXM_NX_REG0[[]],resubmit(,3,ct),goto_table:4
dnl Drop everything else.
table=1 priority=0, action=drop
dnl
dnl "ACL table"
dnl
dnl Stateful accept (1->reg2) all incoming (reg0=1) IP connections with
dnl UDP destination port '2'.  Store rule ID (1234) in reg1, verdict
dnl in reg2.
table=3 priority=10, reg0=1, udp, udp_dst=2 action=set_field:1234->reg1,set_field:1->reg2
dnl Stateless drop (0->reg2) everything else in both directions. (Rule ID: 1235)
table=3 priority=0, action=set_field:1235->reg1,set_field:0->reg2
dnl
dnl Re-process stateful traffic that was not accepted by a stateful rule as
dnl normal traffic in the current direction.  This should also delete the
dnl now stale conntrack state, so that new state can be created in it's place.
dnl
dnl Stateful accepts go to next table.
table=4 priority=100 reg2=1, action=goto_table:5
dnl Everything else is reprocessed disregarding the CT state, using the actual
dnl packet direction.
table=4 priority=0 action=move:NXM_NX_REG3[[]]->NXM_NX_REG0[[]],resubmit(,3),goto_table:5
dnl
dnl "ACL verdict processing table."
dnl
dnl Handle stateful (reg2=1) / stateless (reg2=2) accepts and drops (reg2=0)
dnl
dnl Drop all non-accepted packets.
table=5 reg2=0 priority=1000 action=drop
dnl Commit new non-related IP connections.
table=5 priority=10 reg2=1 ct_state=+new-rel, ip, action=ct(zone=NXM_NX_REG4[[0..15]],commit,exec(move:NXM_NX_REG3[[0..31]]->NXM_NX_CT_MARK[[0..31]],move:NXM_NX_REG1[[0..31]]->NXM_NX_CT_LABEL[[96..127]])),goto_table:6
dnl Commit new related connections in either direction, which inherit the mark
dnl (the direction of the original direction parent tuple) from the parent
dnl connection.
table=5 priority=10 reg2=1 ct_state=+new+rel, ip, action=ct(zone=NXM_NX_REG4[[0..15]],commit,exec(move:NXM_NX_REG1[[0..31]]->NXM_NX_CT_LABEL[[96..127]])),goto_table:6
dnl Forward everything else, including stateless accepts.
table=5 priority=0 action=goto_table:6
dnl
dnl "Forwarding table"
dnl
table=6 action=controller
])

AT_CHECK([ovs-ofctl add-flows br0 flows.txt])

AT_CAPTURE_FILE([ofctl_monitor.log])
AT_CHECK([ovs-ofctl monitor br0 65534 invalid_ttl -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

AT_CHECK([ovs-appctl netdev-dummy/receive p2 'in_port(2),eth(src=50:54:00:00:00:0a,dst=50:54:00:00:00:09),eth_type(0x0800),ipv4(src=10.1.1.2,dst=10.1.1.1,proto=17,tos=0,ttl=64,frag=no),udp(src=2,dst=1)'])

dnl OK, now start a new connection from port 1.
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.1.1.1,dst=10.1.1.2,proto=17,tos=0,ttl=64,frag=no),udp(src=1,dst=2)'])

dnl Now try a reply from port 2.
AT_CHECK([ovs-appctl netdev-dummy/receive p2 'in_port(2),eth(src=50:54:00:00:00:0a,dst=50:54:00:00:00:09),eth_type(0x0800),ipv4(src=10.1.1.2,dst=10.1.1.1,proto=17,tos=0,ttl=64,frag=no),udp(src=2,dst=1)'])

OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 4])
OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])

dnl Check this output. We only see the latter two packets, not the first.
AT_CHECK([cat ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): table_id=6 cookie=0x0 total_len=106 reg0=0x1,reg1=0x4d2,reg2=0x1,reg3=0x1,reg4=0x1,in_port=1 (via action) data_len=106 (unbuffered)
udp,vlan_tci=0x0000,dl_src=50:54:00:00:00:09,dl_dst=50:54:00:00:00:0a,nw_src=10.1.1.1,nw_dst=10.1.1.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=1,tp_dst=2 udp_csum:553
dnl
NXT_PACKET_IN (xid=0x0): table_id=6 cookie=0x0 total_len=106 ct_state=est|rpl|trk,ct_zone=1,ct_mark=0x1,ct_label=0x4d2000000000000000000000000,ct_nw_src=10.1.1.1,ct_nw_dst=10.1.1.2,ct_nw_proto=17,ct_tp_src=1,ct_tp_dst=2,ip,reg0=0x1,reg1=0x4d2,reg2=0x1,reg3=0x2,reg4=0x1,in_port=2 (via action) data_len=106 (unbuffered)
udp,vlan_tci=0x0000,dl_src=50:54:00:00:00:0a,dl_dst=50:54:00:00:00:09,nw_src=10.1.1.2,nw_dst=10.1.1.1,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=2,tp_dst=1 udp_csum:553
])

AT_CHECK([ovs-ofctl monitor br0 65534 invalid_ttl -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

dnl OK, now start a second connection from port 1
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.1.1.1,dst=10.1.1.2,proto=17,tos=0,ttl=64,frag=no),udp(src=3,dst=2)'])

dnl Now try a reply from port 2.
AT_CHECK([ovs-appctl netdev-dummy/receive p2 'in_port(2),eth(src=50:54:00:00:00:0a,dst=50:54:00:00:00:09),eth_type(0x0800),ipv4(src=10.1.1.2,dst=10.1.1.1,proto=17,tos=0,ttl=64,frag=no),udp(src=2,dst=3)'])


OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 4])
OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])

dnl Check this output. We should see both packets
AT_CHECK([cat ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): table_id=6 cookie=0x0 total_len=106 reg0=0x1,reg1=0x4d2,reg2=0x1,reg3=0x1,reg4=0x1,in_port=1 (via action) data_len=106 (unbuffered)
udp,vlan_tci=0x0000,dl_src=50:54:00:00:00:09,dl_dst=50:54:00:00:00:0a,nw_src=10.1.1.1,nw_dst=10.1.1.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=3,tp_dst=2 udp_csum:551
dnl
NXT_PACKET_IN (xid=0x0): table_id=6 cookie=0x0 total_len=106 ct_state=est|rpl|trk,ct_zone=1,ct_mark=0x1,ct_label=0x4d2000000000000000000000000,ct_nw_src=10.1.1.1,ct_nw_dst=10.1.1.2,ct_nw_proto=17,ct_tp_src=3,ct_tp_dst=2,ip,reg0=0x1,reg1=0x4d2,reg2=0x1,reg3=0x2,reg4=0x1,in_port=2 (via action) data_len=106 (unbuffered)
udp,vlan_tci=0x0000,dl_src=50:54:00:00:00:0a,dl_dst=50:54:00:00:00:09,nw_src=10.1.1.2,nw_dst=10.1.1.1,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=2,tp_dst=3 udp_csum:551
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - conntrack - force commit])
OVS_VSWITCHD_START

add_of_ports br0 1 2

AT_CHECK([ovs-appctl vlog/set dpif_netdev:dbg vconn:info ofproto_dpif:info])

dnl Allow new connections on p1->p2, but not on p2->p1.
AT_DATA([flows.txt], [dnl
dnl Table 0
dnl
table=0,priority=100,arp,action=normal
table=0,priority=10,in_port=1,udp,action=ct(commit),controller
table=0,priority=10,in_port=2,udp,action=ct(table=1)
table=0,priority=1,action=drop
dnl
dnl Table 1
dnl
table=1,priority=10,in_port=2,ct_state=+est,udp,action=ct(force,commit),controller
table=1,priority=1,action=drop
])

AT_CHECK([ovs-ofctl add-flows br0 flows.txt])

AT_CAPTURE_FILE([ofctl_monitor.log])
AT_CHECK([ovs-ofctl monitor br0 65534 invalid_ttl -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

AT_CHECK([ovs-appctl netdev-dummy/receive p2 'in_port(2),eth(src=50:54:00:00:00:0a,dst=50:54:00:00:00:09),eth_type(0x0800),ipv4(src=10.1.1.2,dst=10.1.1.1,proto=17,tos=0,ttl=64,frag=no),udp(src=2,dst=1)'])

dnl OK, now start a new connection from port 1.
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.1.1.1,dst=10.1.1.2,proto=17,tos=0,ttl=64,frag=no),udp(src=1,dst=2)'])

dnl Now try a reply from port 2.
AT_CHECK([ovs-appctl netdev-dummy/receive p2 'in_port(2),eth(src=50:54:00:00:00:0a,dst=50:54:00:00:00:09),eth_type(0x0800),ipv4(src=10.1.1.2,dst=10.1.1.1,proto=17,tos=0,ttl=64,frag=no),udp(src=2,dst=1)'])

OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 4])
OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])

dnl Check this output. We only see the latter two packets, not the first.
dnl Note that the first packet doesn't have the ct_state bits set. This
dnl happens because the ct_state field is available only after recirc.
AT_CHECK([cat ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): cookie=0x0 total_len=106 in_port=1 (via action) data_len=106 (unbuffered)
udp,vlan_tci=0x0000,dl_src=50:54:00:00:00:09,dl_dst=50:54:00:00:00:0a,nw_src=10.1.1.1,nw_dst=10.1.1.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=1,tp_dst=2 udp_csum:553
dnl
NXT_PACKET_IN (xid=0x0): table_id=1 cookie=0x0 total_len=106 in_port=2 (via action) data_len=106 (unbuffered)
udp,vlan_tci=0x0000,dl_src=50:54:00:00:00:0a,dl_dst=50:54:00:00:00:09,nw_src=10.1.1.2,nw_dst=10.1.1.1,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=2,tp_dst=1 udp_csum:553
])

AT_CHECK([ovs-ofctl monitor br0 65534 invalid_ttl -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

dnl OK, now start a second connection from port 1
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.1.1.1,dst=10.1.1.2,proto=17,tos=0,ttl=64,frag=no),udp(src=3,dst=4)'])

dnl Now try a reply from port 2.
AT_CHECK([ovs-appctl netdev-dummy/receive p2 'in_port(2),eth(src=50:54:00:00:00:0a,dst=50:54:00:00:00:09),eth_type(0x0800),ipv4(src=10.1.1.2,dst=10.1.1.1,proto=17,tos=0,ttl=64,frag=no),udp(src=4,dst=3)'])

OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 4])
OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])

dnl Check this output. We should see both packets
dnl Note that the first packet doesn't have the ct_state bits set. This
dnl happens because the ct_state field is available only after recirc.
AT_CHECK([cat ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): cookie=0x0 total_len=106 in_port=1 (via action) data_len=106 (unbuffered)
udp,vlan_tci=0x0000,dl_src=50:54:00:00:00:09,dl_dst=50:54:00:00:00:0a,nw_src=10.1.1.1,nw_dst=10.1.1.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=3,tp_dst=4 udp_csum:54f
dnl
NXT_PACKET_IN (xid=0x0): table_id=1 cookie=0x0 total_len=106 in_port=2 (via action) data_len=106 (unbuffered)
udp,vlan_tci=0x0000,dl_src=50:54:00:00:00:0a,dl_dst=50:54:00:00:00:09,nw_src=10.1.1.2,nw_dst=10.1.1.1,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=4,tp_dst=3 udp_csum:54f
])

dnl
dnl Check that the directionality has been changed by force commit.
dnl
AT_CHECK([ovs-appctl dpctl/dump-conntrack | sort], [], [dnl
udp,orig=(src=10.1.1.2,dst=10.1.1.1,sport=2,dport=1),reply=(src=10.1.1.1,dst=10.1.1.2,sport=1,dport=2)
udp,orig=(src=10.1.1.2,dst=10.1.1.1,sport=4,dport=3),reply=(src=10.1.1.1,dst=10.1.1.2,sport=3,dport=4)
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - conntrack - ipv6])
OVS_VSWITCHD_START

add_of_ports br0 1 2

AT_CHECK([ovs-appctl vlog/set dpif_netdev:dbg vconn:info ofproto_dpif:info])

dnl Allow new connections on p1->p2, but not on p2->p1.
AT_DATA([flows.txt], [dnl
dnl Table 0
dnl
table=0,priority=100,arp,action=normal
table=0,priority=10,in_port=1,udp6,action=ct(commit,zone=0),controller
table=0,priority=10,in_port=2,udp6,action=ct(table=1,zone=0)
table=0,priority=1,action=drop
dnl Table 1
dnl
table=1,priority=10,in_port=2,ct_state=+trk+est-new,udp6,action=controller
table=1,priority=1,action=drop
])

AT_CHECK([ovs-ofctl add-flows br0 flows.txt])

AT_CAPTURE_FILE([ofctl_monitor.log])
AT_CHECK([ovs-ofctl monitor br0 65534 invalid_ttl -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

AT_CHECK([ovs-appctl netdev-dummy/receive p2 'in_port(2),eth(src=50:54:00:00:00:0a,dst=50:54:00:00:00:09),eth_type(0x86dd),ipv6(src=2001:db8::2,dst=2001:db8::1,label=0,proto=17,tclass=0x70,hlimit=128,frag=no),udp(src=2,dst=1)'])

dnl OK, now start a new connection from port 1.
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x86dd),ipv6(src=2001:db8::1,dst=2001:db8::2,label=0,proto=17,tclass=0x70,hlimit=128,frag=no),udp(src=1,dst=2)'])

dnl Now try a reply from port 2.
AT_CHECK([ovs-appctl netdev-dummy/receive p2 'in_port(2),eth(src=50:54:00:00:00:0a,dst=50:54:00:00:00:09),eth_type(0x86dd),ipv6(src=2001:db8::2,dst=2001:db8::1,label=0,proto=17,tclass=0x70,hlimit=128,frag=no),udp(src=2,dst=1)'])

OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 4])
OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])

dnl Check this output. We only see the latter two packets, not the first.
dnl Note that the first packet doesn't have the ct_state bits set. This
dnl happens because the ct_state field is available only after recirc.
AT_CHECK([cat ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): cookie=0x0 total_len=126 in_port=1 (via action) data_len=126 (unbuffered)
udp6,vlan_tci=0x0000,dl_src=50:54:00:00:00:09,dl_dst=50:54:00:00:00:0a,ipv6_src=2001:db8::1,ipv6_dst=2001:db8::2,ipv6_label=0x00000,nw_tos=112,nw_ecn=0,nw_ttl=128,tp_src=1,tp_dst=2 udp_csum:bfe2
NXT_PACKET_IN (xid=0x0): table_id=1 cookie=0x0 total_len=126 ct_state=est|rpl|trk,ct_ipv6_src=2001:db8::1,ct_ipv6_dst=2001:db8::2,ct_nw_proto=17,ct_tp_src=1,ct_tp_dst=2,ipv6,in_port=2 (via action) data_len=126 (unbuffered)
udp6,vlan_tci=0x0000,dl_src=50:54:00:00:00:0a,dl_dst=50:54:00:00:00:09,ipv6_src=2001:db8::2,ipv6_dst=2001:db8::1,ipv6_label=0x00000,nw_tos=112,nw_ecn=0,nw_ttl=128,tp_src=2,tp_dst=1 udp_csum:bfe2
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - conntrack - output action])
OVS_VSWITCHD_START

add_of_ports br0 1 2

AT_CHECK([ovs-appctl vlog/set dpif_netdev:dbg vconn:info ofproto_dpif:info])

dnl Allow new connections on p1->p2. Allow only established connections p2->p1
AT_DATA([flows.txt], [dnl
dnl The flows are in two separate tables for two reasons:
dnl * To make the pipeline more clear.
dnl * To make megaflows more consistent (we check megaflows below).  The
dnl   unwildcarding in megaflows depends on the internal ordering of the
dnl   subtables, which are sorted using the system qsort().  qsort()
dnl   is provided by libc and may or may not be stable, so we can't rely
dnl   on that.  By having separate tables we have more control over which
dnl   subtables are visited, meaning consistent megaflows.
dnl
dnl Table 0
dnl
table=0,priority=100,arp,action=normal
table=0,priority=10,in_port=1,udp,action=ct(commit,zone=0),2
table=0,priority=10,in_port=2,udp,action=ct(table=1,zone=0)
table=0,priority=1,action=drop
dnl
dnl Table 1
dnl
table=1,priority=10,in_port=2,ct_state=+trk+est-new,udp,action=1
table=1,priority=1,action=drop
])

AT_CHECK([ovs-ofctl add-flows br0 flows.txt])


AT_CHECK([ovs-appctl netdev-dummy/receive p2 'in_port(2),eth(src=50:54:00:00:00:0a,dst=50:54:00:00:00:09),eth_type(0x0800),ipv4(src=10.1.1.2,dst=10.1.1.1,proto=17,tos=0,ttl=64,frag=no),udp(src=2,dst=1)'])

dnl OK, now start a new connection from port 1.
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.1.1.1,dst=10.1.1.2,proto=17,tos=0,ttl=64,frag=no),udp(src=1,dst=2)'])

dnl Now try a reply from port 2.
AT_CHECK([ovs-appctl netdev-dummy/receive p2 'in_port(2),eth(src=50:54:00:00:00:0a,dst=50:54:00:00:00:09),eth_type(0x0800),ipv4(src=10.1.1.2,dst=10.1.1.1,proto=17,tos=0,ttl=64,frag=no),udp(src=2,dst=1)'])

dnl OK, now start a second connection from port 1
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.1.1.1,dst=10.1.1.2,proto=17,tos=0,ttl=64,frag=no),udp(src=1,dst=2)'])

dnl Now try a reply from port 2.
AT_CHECK([ovs-appctl netdev-dummy/receive p2 'in_port(2),eth(src=50:54:00:00:00:0a,dst=50:54:00:00:00:09),eth_type(0x0800),ipv4(src=10.1.1.2,dst=10.1.1.1,proto=17,tos=0,ttl=64,frag=no),udp(src=2,dst=1)'])


AT_CHECK([cat ovs-vswitchd.log | strip_ufid | filter_flow_install], [0], [dnl
ct_state(+new-est+trk),recirc_id(0x1),in_port(2),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), actions:drop
ct_state(-new+est+trk),recirc_id(0x1),in_port(2),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(proto=17,frag=no), actions:1
recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(proto=17,frag=no), actions:ct(commit),2
recirc_id(0),in_port(2),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(proto=17,frag=no), actions:ct,recirc(0x1)
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - conntrack - expiration])
OVS_VSWITCHD_START

add_of_ports br0 1 2

AT_CHECK([ovs-appctl vlog/set dpif_netdev:dbg vconn:info ofproto_dpif:info])

dnl Allow new connections on p1->p2. Allow only established connections p2->p1
AT_DATA([flows.txt], [dnl
dnl Table 0
dnl
table=0,priority=100,arp,action=normal
table=0,priority=10,in_port=1,udp,action=ct(commit,zone=0)
table=0,priority=10,in_port=2,udp,action=ct(table=1,zone=0)
table=0,priority=1,action=drop
dnl
dnl Table 1
dnl
table=1,priority=10,in_port=2,ct_state=+trk+est-new,udp,action=controller
table=1,priority=1,action=drop
])

AT_CHECK([ovs-ofctl add-flows br0 flows.txt])

AT_CAPTURE_FILE([ofctl_monitor.log])
AT_CHECK([ovs-ofctl monitor br0 65534 invalid_ttl -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

AT_CHECK([ovs-appctl time/stop])

dnl Start a new connection from port 1.
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.1.1.1,dst=10.1.1.2,proto=17,tos=0,ttl=64,frag=no),udp(src=1,dst=2)'])

dnl Now try a reply from port 2.
AT_CHECK([ovs-appctl netdev-dummy/receive p2 'in_port(2),eth(src=50:54:00:00:00:0a,dst=50:54:00:00:00:09),eth_type(0x0800),ipv4(src=10.1.1.2,dst=10.1.1.1,proto=17,tos=0,ttl=64,frag=no),udp(src=2,dst=1)'])

ovs-appctl time/warp 100000

dnl Now try another reply from port 2.
AT_CHECK([ovs-appctl netdev-dummy/receive p2 'in_port(2),eth(src=50:54:00:00:00:0a,dst=50:54:00:00:00:09),eth_type(0x0800),ipv4(src=10.1.1.2,dst=10.1.1.1,proto=17,tos=0,ttl=64,frag=no),udp(src=2,dst=1)'])

OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 3])
OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])

dnl Check this output. Only one reply must be there
AT_CHECK([cat ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): table_id=1 cookie=0x0 total_len=106 ct_state=est|rpl|trk,ct_nw_src=10.1.1.1,ct_nw_dst=10.1.1.2,ct_nw_proto=17,ct_tp_src=1,ct_tp_dst=2,ip,in_port=2 (via action) data_len=106 (unbuffered)
udp,vlan_tci=0x0000,dl_src=50:54:00:00:00:0a,dl_dst=50:54:00:00:00:09,nw_src=10.1.1.2,nw_dst=10.1.1.1,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=2,tp_dst=1 udp_csum:553
dnl
OFPT_ECHO_REQUEST (xid=0x0): 0 bytes of payload
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - conntrack - untrackable traffic])
OVS_VSWITCHD_START

add_of_ports br0 1 2

AT_CHECK([ovs-appctl vlog/set dpif_netdev:dbg vconn:info ofproto_dpif:info])

AT_DATA([flows.txt], [dnl
ipv6,ct_state=-trk,action=ct(table=0,zone=0)
ct_state=+trk,action=controller
])

AT_CHECK([ovs-ofctl add-flows br0 flows.txt])

AT_CAPTURE_FILE([ofctl_monitor.log])
AT_CHECK([ovs-ofctl monitor br0 65534 invalid_ttl -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

AT_CHECK([ovs-appctl time/stop])

AT_CHECK([ovs-appctl netdev-dummy/receive p2 '0060970769ea0000860580da86dd6000000000203afffe80000000000000020086fffe0580dafe80000000000000026097fffe0769ea870068bd00000000fe80000000000000026097fffe0769ea01010000860580da'])

OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 1])
OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])

AT_CHECK([cat ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): cookie=0x0 total_len=86 ct_state=inv|trk,ipv6,in_port=2 (via action) data_len=86 (unbuffered)
icmp6,vlan_tci=0x0000,dl_src=00:00:86:05:80:da,dl_dst=00:60:97:07:69:ea,ipv6_src=fe80::200:86ff:fe05:80da,ipv6_dst=fe80::260:97ff:fe07:69ea,ipv6_label=0x00000,nw_tos=0,nw_ecn=0,nw_ttl=255,icmp_type=135,icmp_code=0,nd_target=fe80::260:97ff:fe07:69ea,nd_sll=00:00:86:05:80:da,nd_tll=00:00:00:00:00:00 icmp6_csum:68bd
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - conntrack - zones])
OVS_VSWITCHD_START

add_of_ports br0 1 2 3 4

AT_CHECK([ovs-appctl vlog/set dpif_netdev:dbg vconn:info ofproto_dpif:info])

dnl Allow new connections on p1->p2 or p3->p4.
dnl Allow only established connections p2->p1 and p4->p3
dnl p1,p2 and p3,p4 are on different zones
AT_DATA([flows.txt], [dnl
dnl Table 0
dnl
table=0,priority=100,arp,action=normal
table=0,priority=10,in_port=1,udp,action=ct(commit,zone=0),controller
table=0,priority=10,in_port=2,udp,action=ct(table=1,zone=0)
table=0,priority=10,in_port=3,udp,action=ct(commit,zone=1),controller
table=0,priority=10,in_port=4,udp,action=ct(table=1,zone=1)
table=0,priority=1,action=drop
dnl
dnl Table 1
dnl
table=1,priority=10,in_port=2,ct_state=+trk+est-new,udp,action=controller
table=1,priority=10,in_port=4,ct_state=+trk+est-new,udp,action=controller
table=1,priority=1,action=drop
])

AT_CHECK([ovs-ofctl add-flows br0 flows.txt])

AT_CAPTURE_FILE([ofctl_monitor.log])
AT_CHECK([ovs-ofctl monitor br0 65534 invalid_ttl -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

dnl Basic "only established" test on ports 1,2

AT_CHECK([ovs-appctl netdev-dummy/receive p2 'in_port(2),eth(src=50:54:00:00:00:0a,dst=50:54:00:00:00:09),eth_type(0x0800),ipv4(src=10.1.1.2,dst=10.1.1.1,proto=17,tos=0,ttl=64,frag=no),udp(src=2,dst=1)'])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.1.1.1,dst=10.1.1.2,proto=17,tos=0,ttl=64,frag=no),udp(src=1,dst=2)'])
AT_CHECK([ovs-appctl netdev-dummy/receive p2 'in_port(2),eth(src=50:54:00:00:00:0a,dst=50:54:00:00:00:09),eth_type(0x0800),ipv4(src=10.1.1.2,dst=10.1.1.1,proto=17,tos=0,ttl=64,frag=no),udp(src=2,dst=1)'])

dnl Now use the same 5-tuples but on ports 3,4

AT_CHECK([ovs-appctl netdev-dummy/receive p4 'in_port(4),eth(src=50:54:00:00:00:0a,dst=50:54:00:00:00:09),eth_type(0x0800),ipv4(src=10.1.1.2,dst=10.1.1.1,proto=17,tos=0,ttl=64,frag=no),udp(src=2,dst=1)'])
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.1.1.1,dst=10.1.1.2,proto=17,tos=0,ttl=64,frag=no),udp(src=1,dst=2)'])
AT_CHECK([ovs-appctl netdev-dummy/receive p4 'in_port(4),eth(src=50:54:00:00:00:0a,dst=50:54:00:00:00:09),eth_type(0x0800),ipv4(src=10.1.1.2,dst=10.1.1.1,proto=17,tos=0,ttl=64,frag=no),udp(src=2,dst=1)'])

OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 8])
OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])

dnl Check this output. We only see the latter two packets (for each zone), not the first.
AT_CHECK([cat ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): cookie=0x0 total_len=106 in_port=1 (via action) data_len=106 (unbuffered)
udp,vlan_tci=0x0000,dl_src=50:54:00:00:00:09,dl_dst=50:54:00:00:00:0a,nw_src=10.1.1.1,nw_dst=10.1.1.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=1,tp_dst=2 udp_csum:553
dnl
NXT_PACKET_IN (xid=0x0): table_id=1 cookie=0x0 total_len=106 ct_state=est|rpl|trk,ct_nw_src=10.1.1.1,ct_nw_dst=10.1.1.2,ct_nw_proto=17,ct_tp_src=1,ct_tp_dst=2,ip,in_port=2 (via action) data_len=106 (unbuffered)
udp,vlan_tci=0x0000,dl_src=50:54:00:00:00:0a,dl_dst=50:54:00:00:00:09,nw_src=10.1.1.2,nw_dst=10.1.1.1,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=2,tp_dst=1 udp_csum:553
dnl
NXT_PACKET_IN (xid=0x0): cookie=0x0 total_len=106 in_port=3 (via action) data_len=106 (unbuffered)
udp,vlan_tci=0x0000,dl_src=50:54:00:00:00:09,dl_dst=50:54:00:00:00:0a,nw_src=10.1.1.1,nw_dst=10.1.1.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=1,tp_dst=2 udp_csum:553
dnl
NXT_PACKET_IN (xid=0x0): table_id=1 cookie=0x0 total_len=106 ct_state=est|rpl|trk,ct_zone=1,ct_nw_src=10.1.1.1,ct_nw_dst=10.1.1.2,ct_nw_proto=17,ct_tp_src=1,ct_tp_dst=2,ip,in_port=4 (via action) data_len=106 (unbuffered)
udp,vlan_tci=0x0000,dl_src=50:54:00:00:00:0a,dl_dst=50:54:00:00:00:09,nw_src=10.1.1.2,nw_dst=10.1.1.1,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=2,tp_dst=1 udp_csum:553
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - conntrack - recirc,commit])
OVS_VSWITCHD_START

add_of_ports br0 1 2

AT_CHECK([ovs-appctl vlog/set dpif_netdev:dbg vconn:info ofproto_dpif:info])

dnl Allow new connections on p1->p2. Allow only established connections p2->p1
AT_DATA([flows.txt], [dnl
dnl Table 0
dnl
table=0,priority=100,arp,action=normal
table=0,priority=10,udp,action=ct(table=1,zone=0)
table=0,priority=1,action=drop
dnl
dnl Table 1
dnl
table=1,priority=10,in_port=1,ct_state=+trk+new,udp,action=ct(commit,zone=0),controller
table=1,priority=10,ct_state=+trk+est,udp,action=controller
table=1,priority=1,action=drop
])

AT_CHECK([ovs-ofctl add-flows br0 flows.txt])

AT_CAPTURE_FILE([ofctl_monitor.log])
AT_CHECK([ovs-ofctl monitor br0 65534 invalid_ttl -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

AT_CHECK([ovs-appctl netdev-dummy/receive p2 'in_port(2),eth(src=50:54:00:00:00:0a,dst=50:54:00:00:00:09),eth_type(0x0800),ipv4(src=10.1.1.2,dst=10.1.1.1,proto=17,tos=0,ttl=64,frag=no),udp(src=2,dst=1)'])

dnl OK, now start a new connection from port 1.
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.1.1.1,dst=10.1.1.2,proto=17,tos=0,ttl=64,frag=no),udp(src=1,dst=2)'])

dnl Now try a reply from port 2.
AT_CHECK([ovs-appctl netdev-dummy/receive p2 'in_port(2),eth(src=50:54:00:00:00:0a,dst=50:54:00:00:00:09),eth_type(0x0800),ipv4(src=10.1.1.2,dst=10.1.1.1,proto=17,tos=0,ttl=64,frag=no),udp(src=2,dst=1)'])

OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 4])
OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])

dnl Check this output. We only see the latter two packets, not the first.
AT_CHECK([cat ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): table_id=1 cookie=0x0 total_len=106 in_port=1 (via action) data_len=106 (unbuffered)
udp,vlan_tci=0x0000,dl_src=50:54:00:00:00:09,dl_dst=50:54:00:00:00:0a,nw_src=10.1.1.1,nw_dst=10.1.1.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=1,tp_dst=2 udp_csum:553
dnl
NXT_PACKET_IN (xid=0x0): table_id=1 cookie=0x0 total_len=106 ct_state=est|rpl|trk,ct_nw_src=10.1.1.1,ct_nw_dst=10.1.1.2,ct_nw_proto=17,ct_tp_src=1,ct_tp_dst=2,ip,in_port=2 (via action) data_len=106 (unbuffered)
udp,vlan_tci=0x0000,dl_src=50:54:00:00:00:0a,dl_dst=50:54:00:00:00:09,nw_src=10.1.1.2,nw_dst=10.1.1.1,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=2,tp_dst=1 udp_csum:553
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - conntrack - ICMP related])
OVS_VSWITCHD_START

add_of_ports br0 1 2

dnl Allow any traffic from ns0->ns1. Only allow nd, return traffic from ns1->ns0.
AT_DATA([flows.txt], [dnl
dnl Table 0
dnl
table=0,priority=100,arp,action=normal
table=0,priority=10,ip,in_port=1,udp,action=ct(commit,table=1)
table=0,priority=10,ip,in_port=2,action=ct(table=1)
table=0,priority=1,action=drop
dnl
dnl Table 1
dnl
table=1,priority=10,in_port=1,ct_state=+trk,action=controller
table=1,priority=10,in_port=2,ct_state=+trk-inv-new,action=controller
table=1,priority=1,action=drop
])

AT_CHECK([ovs-ofctl add-flows br0 flows.txt])

AT_CAPTURE_FILE([ofctl_monitor.log])
AT_CHECK([ovs-ofctl monitor br0 65534 invalid_ttl -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

dnl 1. Send an ICMP port unreach reply for port 8738, without any previous request
AT_CHECK([ovs-ofctl -O OpenFlow13 packet-out br0 2 ct\(table=1\) 'f64c473528c9c6f54ecb72db080045c0003d2e8700004001f351ac100004ac1000030303553f0000000045000021317040004011b138ac100003ac10000411112222000da5a06369616f0a'])

dnl 2. Send and UDP packet to port 5555
AT_CHECK([ovs-ofctl -O OpenFlow13 packet-out br0 1 ct\(commit,table=1\) 'c6f94ecb72dbe64c473528c9080045000021317040004011b138ac100001ac100002a28e15b3000d20966369616f0a'])

dnl 3. Send an ICMP port unreach reply for port 5555, related to the first packet
AT_CHECK([ovs-ofctl -O OpenFlow13 packet-out br0 2 ct\(table=1\) 'e64c473528c9c6f94ecb72db080045c0003d2e8700004001f355ac100002ac1000010303553f0000000045000021317040004011b138ac100001ac100002a28e15b3000d20966369616f0a'])

OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 4])
OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])

dnl Check this output. We only see the first and the last packet
AT_CHECK([cat ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): table_id=1 cookie=0x0 total_len=47 ct_state=new|trk,ct_nw_src=172.16.0.1,ct_nw_dst=172.16.0.2,ct_nw_proto=17,ct_tp_src=41614,ct_tp_dst=5555,ip,in_port=1 (via action) data_len=47 (unbuffered)
udp,vlan_tci=0x0000,dl_src=e6:4c:47:35:28:c9,dl_dst=c6:f9:4e:cb:72:db,nw_src=172.16.0.1,nw_dst=172.16.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=41614,tp_dst=5555 udp_csum:2096
dnl
NXT_PACKET_IN (xid=0x0): table_id=1 cookie=0x0 total_len=75 ct_state=rel|rpl|trk,ct_nw_src=172.16.0.1,ct_nw_dst=172.16.0.2,ct_nw_proto=17,ct_tp_src=41614,ct_tp_dst=5555,ip,in_port=2 (via action) data_len=75 (unbuffered)
icmp,vlan_tci=0x0000,dl_src=c6:f9:4e:cb:72:db,dl_dst=e6:4c:47:35:28:c9,nw_src=172.16.0.2,nw_dst=172.16.0.1,nw_tos=192,nw_ecn=0,nw_ttl=64,icmp_type=3,icmp_code=3 icmp_csum:553f
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - conntrack - ct_mark])
OVS_VSWITCHD_START

add_of_ports br0 1 2

AT_CHECK([ovs-appctl vlog/set dpif_netdev:dbg vconn:info ofproto_dpif:info])

dnl Allow new connections on p1->p2. Allow only established connections p2->p1
AT_DATA([flows.txt], [dnl
dnl Table 0
dnl
table=0,arp,action=normal
table=0,ip,in_port=1,udp,tp_src=1,action=ct(commit,exec(set_field:1->ct_mark)),controller
table=0,ip,in_port=1,udp,tp_src=3,action=ct(commit,exec(set_field:3->ct_mark)),controller
table=0,ip,in_port=1,udp,tp_src=5,action=ct(commit,exec(set_field:5->ct_mark)),controller
table=0,ip,in_port=2,actions=ct(table=1)
table=0,priority=0,action=drop
dnl
dnl Table 1
dnl
table=1,priority=100,ct_state=+trk+rpl,ct_mark=0/4,actions=controller
table=1,priority=1,action=drop
])

AT_CHECK([ovs-ofctl add-flows br0 flows.txt])

AT_CAPTURE_FILE([ofctl_monitor.log])
AT_CHECK([ovs-ofctl monitor br0 65534 invalid_ttl -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.1.1.1,dst=10.1.1.2,proto=17,tos=0,ttl=64,frag=no),udp(src=1,dst=2)'])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.1.1.1,dst=10.1.1.2,proto=17,tos=0,ttl=64,frag=no),udp(src=3,dst=4)'])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.1.1.1,dst=10.1.1.2,proto=17,tos=0,ttl=64,frag=no),udp(src=5,dst=6)'])

AT_CHECK([ovs-appctl netdev-dummy/receive p2 'in_port(2),eth(src=50:54:00:00:00:0a,dst=50:54:00:00:00:09),eth_type(0x0800),ipv4(src=10.1.1.2,dst=10.1.1.1,proto=17,tos=0,ttl=64,frag=no),udp(src=2,dst=1)'])
AT_CHECK([ovs-appctl netdev-dummy/receive p2 'in_port(2),eth(src=50:54:00:00:00:0a,dst=50:54:00:00:00:09),eth_type(0x0800),ipv4(src=10.1.1.2,dst=10.1.1.1,proto=17,tos=0,ttl=64,frag=no),udp(src=4,dst=3)'])
AT_CHECK([ovs-appctl netdev-dummy/receive p2 'in_port(2),eth(src=50:54:00:00:00:0a,dst=50:54:00:00:00:09),eth_type(0x0800),ipv4(src=10.1.1.2,dst=10.1.1.1,proto=17,tos=0,ttl=64,frag=no),udp(src=6,dst=5)'])

OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 10])
OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])

dnl Check this output.
AT_CHECK([cat ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): cookie=0x0 total_len=106 in_port=1 (via action) data_len=106 (unbuffered)
udp,vlan_tci=0x0000,dl_src=50:54:00:00:00:09,dl_dst=50:54:00:00:00:0a,nw_src=10.1.1.1,nw_dst=10.1.1.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=1,tp_dst=2 udp_csum:553
dnl
NXT_PACKET_IN (xid=0x0): cookie=0x0 total_len=106 in_port=1 (via action) data_len=106 (unbuffered)
udp,vlan_tci=0x0000,dl_src=50:54:00:00:00:09,dl_dst=50:54:00:00:00:0a,nw_src=10.1.1.1,nw_dst=10.1.1.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=3,tp_dst=4 udp_csum:54f
dnl
NXT_PACKET_IN (xid=0x0): cookie=0x0 total_len=106 in_port=1 (via action) data_len=106 (unbuffered)
udp,vlan_tci=0x0000,dl_src=50:54:00:00:00:09,dl_dst=50:54:00:00:00:0a,nw_src=10.1.1.1,nw_dst=10.1.1.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=5,tp_dst=6 udp_csum:54b
dnl
NXT_PACKET_IN (xid=0x0): table_id=1 cookie=0x0 total_len=106 ct_state=est|rpl|trk,ct_mark=0x1,ct_nw_src=10.1.1.1,ct_nw_dst=10.1.1.2,ct_nw_proto=17,ct_tp_src=1,ct_tp_dst=2,ip,in_port=2 (via action) data_len=106 (unbuffered)
udp,vlan_tci=0x0000,dl_src=50:54:00:00:00:0a,dl_dst=50:54:00:00:00:09,nw_src=10.1.1.2,nw_dst=10.1.1.1,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=2,tp_dst=1 udp_csum:553
dnl
NXT_PACKET_IN (xid=0x0): table_id=1 cookie=0x0 total_len=106 ct_state=est|rpl|trk,ct_mark=0x3,ct_nw_src=10.1.1.1,ct_nw_dst=10.1.1.2,ct_nw_proto=17,ct_tp_src=3,ct_tp_dst=4,ip,in_port=2 (via action) data_len=106 (unbuffered)
udp,vlan_tci=0x0000,dl_src=50:54:00:00:00:0a,dl_dst=50:54:00:00:00:09,nw_src=10.1.1.2,nw_dst=10.1.1.1,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=4,tp_dst=3 udp_csum:54f
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - conntrack - ct_label])
OVS_VSWITCHD_START

add_of_ports br0 1 2

AT_CHECK([ovs-appctl vlog/set dpif_netdev:dbg vconn:info ofproto_dpif:info])

dnl Allow new connections on p1->p2. Allow only established connections p2->p1
AT_DATA([flows.txt], [dnl
dnl Table 0
dnl
table=0,arp,action=normal
table=0,ip,in_port=1,udp,tp_src=1,action=ct(commit,exec(set_field:000000000000000001->ct_label))
table=0,ip,in_port=1,udp,tp_src=3,action=ct(commit,exec(set_field:000000000000000002->ct_label))
table=0,ip,in_port=2,actions=ct(table=1)
dnl
dnl Table 1
dnl
table=1,priority=10,ct_state=+trk+rpl,actions=controller
table=1,priority=1,action=drop
])

AT_CHECK([ovs-ofctl add-flows br0 flows.txt])

AT_CAPTURE_FILE([ofctl_monitor.log])
AT_CHECK([ovs-ofctl monitor br0 65534 invalid_ttl -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.1.1.1,dst=10.1.1.2,proto=17,tos=0,ttl=64,frag=no),udp(src=1,dst=2)'])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.1.1.1,dst=10.1.1.2,proto=17,tos=0,ttl=64,frag=no),udp(src=3,dst=4)'])

AT_CHECK([ovs-appctl netdev-dummy/receive p2 'in_port(2),eth(src=50:54:00:00:00:0a,dst=50:54:00:00:00:09),eth_type(0x0800),ipv4(src=10.1.1.2,dst=10.1.1.1,proto=17,tos=0,ttl=64,frag=no),udp(src=2,dst=1)'])
AT_CHECK([ovs-appctl netdev-dummy/receive p2 'in_port(2),eth(src=50:54:00:00:00:0a,dst=50:54:00:00:00:09),eth_type(0x0800),ipv4(src=10.1.1.2,dst=10.1.1.1,proto=17,tos=0,ttl=64,frag=no),udp(src=4,dst=3)'])

OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 4])
OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])

dnl Check this output.
AT_CHECK([cat ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): table_id=1 cookie=0x0 total_len=106 ct_state=est|rpl|trk,ct_label=0x1,ct_nw_src=10.1.1.1,ct_nw_dst=10.1.1.2,ct_nw_proto=17,ct_tp_src=1,ct_tp_dst=2,ip,in_port=2 (via action) data_len=106 (unbuffered)
udp,vlan_tci=0x0000,dl_src=50:54:00:00:00:0a,dl_dst=50:54:00:00:00:09,nw_src=10.1.1.2,nw_dst=10.1.1.1,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=2,tp_dst=1 udp_csum:553
dnl
NXT_PACKET_IN (xid=0x0): table_id=1 cookie=0x0 total_len=106 ct_state=est|rpl|trk,ct_label=0x2,ct_nw_src=10.1.1.1,ct_nw_dst=10.1.1.2,ct_nw_proto=17,ct_tp_src=3,ct_tp_dst=4,ip,in_port=2 (via action) data_len=106 (unbuffered)
udp,vlan_tci=0x0000,dl_src=50:54:00:00:00:0a,dl_dst=50:54:00:00:00:09,nw_src=10.1.1.2,nw_dst=10.1.1.1,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=4,tp_dst=3 udp_csum:54f
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - conntrack - ct_label datapath flow])
OVS_VSWITCHD_START

add_of_ports br0 1 2

AT_CHECK([ovs-appctl vlog/set dpif_netdev:dbg vconn:info ofproto_dpif:info])

dnl Allow new connections on p1->p2. Allow only established connections p2->p1
AT_DATA([flows.txt], [dnl
dnl The flows are in two separate tables for two reasons:
dnl * To make the pipeline more clear.
dnl * To make megaflows more consistent (we check megaflows below).  The
dnl   unwildcarding in megaflows depends on the internal ordering of the
dnl   subtables, which are sorted using the system qsort().  qsort()
dnl   is provided by libc and may or may not be stable, so we can't rely
dnl   on that.  By having separate tables we have more control over which
dnl   subtables are visited, meaning consistent megaflows.
dnl
dnl Table 0
dnl
table=0,arp,action=normal
table=0,ip,in_port=1,udp,tp_src=1,action=ct(commit,exec(set_field:1->ct_label)),2
table=0,ip,in_port=2,actions=ct(table=1)
table=0,priority=0,action=drop
dnl
dnl Table 1
dnl
table=1,priority=10,ct_state=+trk+rpl,ct_label=0x1,actions=1
table=1,priority=1,action=drop
])

AT_CHECK([ovs-ofctl add-flows br0 flows.txt])

AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.1.1.1,dst=10.1.1.2,proto=17,tos=0,ttl=64,frag=no),udp(src=1,dst=2)'])
AT_CHECK([ovs-appctl netdev-dummy/receive p2 'in_port(2),eth(src=50:54:00:00:00:0a,dst=50:54:00:00:00:09),eth_type(0x0800),ipv4(src=10.1.1.2,dst=10.1.1.1,proto=17,tos=0,ttl=64,frag=no),udp(src=2,dst=1)'])

# Give time for logs to appear.
ovs-appctl revalidator/wait

AT_CHECK([cat ovs-vswitchd.log | strip_ufid | filter_flow_install], [0], [dnl
ct_state(+rpl+trk),ct_label(0x1),recirc_id(0x1),in_port(2),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), actions:1
recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(proto=17,frag=no),udp(src=1), actions:ct(commit,label=0x1),2
recirc_id(0),in_port(2),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), actions:ct,recirc(0x1)
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - conntrack - no output])
OVS_VSWITCHD_START

add_of_ports br0 1

AT_CHECK([ovs-appctl vlog/set dpif_netdev:dbg vconn:info ofproto_dpif:info])

dnl Allow new connections on p1->p2. Allow only established connections p2->p1
AT_DATA([flows.txt], [dnl
in_port=1,udp,action=ct(commit,zone=0)
])

AT_CHECK([ovs-ofctl add-flows br0 flows.txt])

dnl Start a new connection from port 1.
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.1.1.1,dst=10.1.1.2,proto=17,tos=0,ttl=64,frag=no),udp(src=1,dst=2)'])

AT_CHECK([cat ovs-vswitchd.log | strip_ufid | filter_flow_install], [0], [dnl
recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(proto=17,frag=no), actions:ct(commit)
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - conntrack - tcp port reuse])
OVS_VSWITCHD_START

add_of_ports br0 1 2

AT_CHECK([ovs-appctl vlog/set dpif_netdev:dbg vconn:info ofproto_dpif:info])

dnl Allow new connections on p1->p2. Allow only established connections p2->p1
AT_DATA([flows.txt], [dnl
dnl Table 0
dnl
table=0,priority=100,arp,action=normal
table=0,priority=10,in_port=1,ip,action=ct(commit,table=1)
table=0,priority=10,in_port=2,ip,action=ct(table=1)
table=0,priority=1,action=drop
dnl
dnl Table 1
dnl
dnl The following two flows are separated to explicitly count the packets
dnl that create a new connection
table=1,priority=100,cookie=0x1,in_port=1,ip,ct_state=+trk+new-inv-rpl,action=2
table=1,priority=100,in_port=1,ip,ct_state=+trk-new-inv-rpl,action=2
dnl
table=1,priority=100,in_port=2,ip,ct_state=+trk+est+rpl-new-inv,action=1
table=1,ip,ct_state=+trk+inv,action=drop
])

AT_CHECK([ovs-ofctl add-flows br0 flows.txt])

AT_CHECK([ovs-appctl netdev-dummy/receive p1 '50540000000a50540000000908004500002ca4e5400040067fe20a0101010a0101020001000259b5d93f0000000060027210dd190000020405b4'])
AT_CHECK([ovs-appctl netdev-dummy/receive p2 '50540000000950540000000a08004500002c00004000400624c80a0101020a010101000200017c35468459b5d940601272101a4f0000020405b4'])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 '50540000000a505400000009080045000028a4e6400040067fe50a0101010a0101020001000259b5d9407c35468550107210320c0000'])
AT_CHECK([ovs-appctl netdev-dummy/receive p2 '50540000000950540000000a0800450000303b5f40004006e9640a0101020a010101000200017c35468559b5d9405018721074c200007061796c6f61640a'])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 '50540000000a505400000009080045000028a4e7400040067fe40a0101010a0101020001000259b5d9407c35468d5010721032040000'])
AT_CHECK([ovs-appctl netdev-dummy/receive p2 '50540000000950540000000a0800450000283b6040004006e96b0a0101020a010101000200017c35468d59b5d9405011721032030000'])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 '50540000000a505400000009080045000028a4e8400040067fe30a0101010a0101020001000259b5d9407c35468e5010721032030000'])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 '50540000000a505400000009080045000028a4e9400040067fe20a0101010a0101020001000259b5d9407c35468e5011721032020000'])
AT_CHECK([ovs-appctl netdev-dummy/receive p2 '50540000000950540000000a0800450000283b6140004006e96a0a0101020a010101000200017c35468e59b5d9415010721032020000'])

AT_CHECK([ovs-appctl revalidator/purge])
AT_CHECK([ovs-ofctl dump-flows br0 | grep cookie=0x1 | grep -o "n_packets=[[0-9]]*"], [0], [dnl
dnl Only one new connection
n_packets=1
])

AT_CHECK([ovs-appctl netdev-dummy/receive p1 '50540000000a50540000000908004500002cc0a74000400664200a0101010a010102000100025b7dbf1f0000000060027210f5710000020405b4'])
AT_CHECK([ovs-appctl netdev-dummy/receive p2 '50540000000950540000000a08004500002c00004000400624c80a0101020a010101000200017c36468f5b7dbf2060127210329b0000020405b4'])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 '50540000000a505400000009080045000028c0a84000400664230a0101010a010102000100025b7dbf207c364690501072104a580000'])
AT_CHECK([ovs-appctl netdev-dummy/receive p2 '50540000000950540000000a080045000030392840004006eb9b0a0101020a010101000200017c3646905b7dbf20501872108d0e00007061796c6f61640a'])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 '50540000000a505400000009080045000028c0a94000400664220a0101010a010102000100025b7dbf207c364698501072104a500000'])
AT_CHECK([ovs-appctl netdev-dummy/receive p2 '50540000000950540000000a080045000028392940004006eba20a0101020a010101000200017c3646985b7dbf20501172104a4f0000'])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 '50540000000a505400000009080045000028c0aa4000400664210a0101010a010102000100025b7dbf207c364699501072104a4f0000'])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 '50540000000a505400000009080045000028c0ab4000400664200a0101010a010102000100025b7dbf207c364699501172104a4e0000'])
AT_CHECK([ovs-appctl netdev-dummy/receive p2 '50540000000950540000000a080045000028392a40004006eba10a0101020a010101000200017c3646995b7dbf21501072104a4e0000'])

AT_CHECK([ovs-appctl revalidator/purge])
AT_CHECK([ovs-ofctl dump-flows br0 | grep cookie=0x1 | grep -o "n_packets=[[0-9]]*"], [0], [dnl
dnl Two new connections
n_packets=2
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - conntrack - tcp pick up])
OVS_VSWITCHD_START

add_of_ports br0 1 2

AT_CHECK([ovs-appctl vlog/set dpif_netdev:dbg vconn:info ofproto_dpif:info])

dnl Allow new connections on p1->p2. Allow only established connections p2->p1
AT_DATA([flows.txt], [dnl
dnl Table 0
dnl
table=0,priority=100,arp,action=normal
table=0,priority=10,in_port=1,tcp,action=ct(commit,table=1)
table=0,priority=10,in_port=2,tcp,action=ct(table=1)
table=0,priority=1,action=drop
dnl
dnl Table 1
dnl
table=1,priority=10,cookie=0x1,ip,ct_state=+trk+inv,action=controller
table=1,priority=1,action=drop
])

AT_CHECK([ovs-ofctl add-flows br0 flows.txt])

AT_CHECK([ovs-appctl revalidator/purge])
AT_CHECK([ovs-ofctl dump-flows br0 | grep cookie=0x1 | grep -o "n_packets=[[0-9]]*"], [0], [dnl
dnl No dropped packets
n_packets=0
])

AT_CAPTURE_FILE([ofctl_monitor.log])
AT_CHECK([ovs-ofctl monitor br0 65534 invalid_ttl -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

dnl The first two packets (SYN, SYN|ACK) are commented out.  We're making
dnl sure that the connection tracker is able to pick up already established
dnl connections that use window scaling.
dnl
dnl AT_CHECK([ovs-appctl netdev-dummy/receive p1 '50540000000950540000000a080045000030fc2540004006289e0a0101020a01010100020001396bb359000000007002008080cc0000020405b401030307'])
dnl AT_CHECK([ovs-appctl netdev-dummy/receive p2 '50540000000a50540000000908004500003000004000400624c40a0101010a010102000100028cadbdb3396bb35a70120080365a0000020405b401030307'])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 '50540000000950540000000a080045000028fc264000400628a50a0101020a01010100020001396bb35a8cadbdb45010000a629b0000'])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 '50540000000950540000000a080045000029fc274000400628a30a0101020a01010100020001396bb35a8cadbdb45018000a589200000a'])
AT_CHECK([ovs-appctl netdev-dummy/receive p2 '50540000000a505400000009080045000028f2c84000400632030a0101010a010102000100028cadbdb4396bb35b5010000a629a0000'])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 '50540000000950540000000a08004500022afc284000400626a10a0101020a01010100020001396bb35b8cadbdb45018000a941f0000 dnl
                                              666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666 dnl
                                              666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666 dnl
                                              666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666 dnl
                                              666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666 dnl
                                              666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666 dnl
                                              666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666 dnl
                                              666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666 dnl
                                              666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666 dnl
                                              666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666 dnl
                                              6666666666666666666666666666666666666666666666666666660a'])
AT_CHECK([ovs-appctl netdev-dummy/receive p2 '50540000000a505400000009080045000028f2c94000400632020a0101010a010102000100028cadbdb4396bb55d5010000a60980000'])
AT_CHECK([ovs-appctl netdev-dummy/receive p2 '50540000000a5054000000090800450001fdf2ca40004006302c0a0101010a010102000100028cadbdb4396bb55d5018000aa60c0000 dnl
                                              656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565 dnl
                                              656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565 dnl
                                              656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565 dnl
                                              656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565 dnl
                                              656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565 dnl
                                              656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565 dnl
                                              656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565 dnl
                                              656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565 dnl
                                              6565656565656565656565656565656565656565656565656565656565656565656565650a'])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 '50540000000950540000000a080045000028fc294000400628a20a0101020a01010100020001396bb55d8cadbf895010000a5ec30000'])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 '50540000000950540000000a080045000028fc2a4000400628a10a0101020a01010100020001396bb55d8cadbf895011000a5ec20000'])
AT_CHECK([ovs-appctl netdev-dummy/receive p2 '50540000000a505400000009080045000028f2cb4000400632000a0101010a010102000100028cadbf89396bb55e5010000a5ec20000'])
AT_CHECK([ovs-appctl netdev-dummy/receive p2 '50540000000a505400000009080045000028f2cc4000400631ff0a0101010a010102000100028cadbf89396bb55e5011000a5ec10000'])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 '50540000000950540000000a080045000028258e40004006ff3d0a0101020a01010100020001396bb55e8cadbf8a5010000a5ec10000'])

AT_CHECK([ovs-appctl revalidator/purge])

OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])

AT_CHECK([cat ofctl_monitor.log], [0], [dnl
])

AT_CHECK([ovs-ofctl dump-flows br0 | grep cookie=0x1 | grep -o "n_packets=[[0-9]]*"], [0], [dnl
dnl No dropped packets
n_packets=0
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - conntrack - disable tcp sequence checking])
OVS_VSWITCHD_START

add_of_ports br0 1 2

dnl Allow new connections on p1->p2. Allow only established connections p2->p1
AT_DATA([flows.txt], [dnl
dnl Table 0
dnl
table=0,priority=10,in_port=1,ip,action=ct(commit,table=1)
table=0,priority=10,in_port=2,ip,action=ct(table=1)
table=0,priority=1,action=drop
dnl
dnl Table 1
dnl
dnl The following two flows are separated to explicitly count the packets
dnl that create a new connection
table=1,priority=100,cookie=0x1,in_port=1,ip,ct_state=+trk+new-inv-rpl,action=2
table=1,priority=100,cookie=0x2,in_port=1,ip,ct_state=+trk-new-inv-rpl,action=2
dnl
table=1,priority=100,cookie=0x3,in_port=2,ip,ct_state=+trk+est+rpl-new-inv,action=1
table=1,cookie=0x4,ip,ct_state=+trk+inv,action=drop
])

AT_CHECK([ovs-ofctl add-flows br0 flows.txt])

dnl Send 9 packets; one packet will be marked invalid.
AT_CHECK([ovs-appctl netdev-dummy/receive p1 '50540000000a50540000000908004500002ca4e5400040067fe20a0101010a0101020001000259b5d93f0000000060027210dd190000020405b4'])
AT_CHECK([ovs-appctl netdev-dummy/receive p2 '50540000000950540000000a08004500002c00004000400624c80a0101020a010101000200017c35468459b5d940601272101a4f0000020405b4'])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 '50540000000a505400000009080045000028a4e6400040067fe50a0101010a0101020001000259b5d9407c35468550107210320c0000'])
AT_CHECK([ovs-appctl netdev-dummy/receive p2 '50540000000950540000000a0800450000303b5f40004006e9640a0101020a010101000200010000000000000000501872106a7300007061796c6f61640a'])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 '50540000000a505400000009080045000028a4e7400040067fe40a0101010a0101020001000259b5d9407c35468d5010721032040000'])
AT_CHECK([ovs-appctl netdev-dummy/receive p2 '50540000000950540000000a0800450000283b6040004006e96b0a0101020a010101000200017c35468d59b5d9405011721032030000'])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 '50540000000a505400000009080045000028a4e8400040067fe30a0101010a0101020001000259b5d9407c35468e5010721032030000'])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 '50540000000a505400000009080045000028a4e9400040067fe20a0101010a0101020001000259b5d9407c35468e5011721032020000'])
AT_CHECK([ovs-appctl netdev-dummy/receive p2 '50540000000950540000000a0800450000283b6140004006e96a0a0101020a010101000200017c35468e59b5d9415010721032020000'])

AT_CHECK([ovs-appctl revalidator/purge])
AT_CHECK([ovs-ofctl dump-flows br0 | grep cookie=0x1 | grep -o "n_packets=[[0-9]]*"], [0], [dnl
n_packets=1
])

AT_CHECK([ovs-ofctl dump-flows br0 | grep cookie=0x2 | grep -o "n_packets=[[0-9]]*"], [0], [dnl
n_packets=4
])

AT_CHECK([ovs-ofctl dump-flows br0 | grep cookie=0x3 | grep -o "n_packets=[[0-9]]*"], [0], [dnl
n_packets=3
])

AT_CHECK([ovs-ofctl dump-flows br0 | grep cookie=0x4 | grep -o "n_packets=[[0-9]]*"], [0], [dnl
n_packets=1
])

AT_CHECK([ovs-appctl dpctl/flush-conntrack])

AT_CHECK([ovs-appctl dpctl/ct-get-tcp-seq-chk], [], [dnl
TCP sequence checking: enabled
])

AT_CHECK([ovs-appctl dpctl/ct-disable-tcp-seq-chk], [], [dnl
disabling TCP sequence checking successful
])

AT_CHECK([ovs-appctl dpctl/ct-get-tcp-seq-chk], [], [dnl
TCP sequence checking: disabled
])

dnl Send exactly the same 9 packets to confirm no additional packets are marked invalid.
AT_CHECK([ovs-appctl netdev-dummy/receive p1 '50540000000a50540000000908004500002ca4e5400040067fe20a0101010a0101020001000259b5d93f0000000060027210dd190000020405b4'])
AT_CHECK([ovs-appctl netdev-dummy/receive p2 '50540000000950540000000a08004500002c00004000400624c80a0101020a010101000200017c35468459b5d940601272101a4f0000020405b4'])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 '50540000000a505400000009080045000028a4e6400040067fe50a0101010a0101020001000259b5d9407c35468550107210320c0000'])
AT_CHECK([ovs-appctl netdev-dummy/receive p2 '50540000000950540000000a0800450000303b5f40004006e9640a0101020a010101000200010000000000000000501872106a7300007061796c6f61640a'])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 '50540000000a505400000009080045000028a4e7400040067fe40a0101010a0101020001000259b5d9407c35468d5010721032040000'])
AT_CHECK([ovs-appctl netdev-dummy/receive p2 '50540000000950540000000a0800450000283b6040004006e96b0a0101020a010101000200017c35468d59b5d9405011721032030000'])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 '50540000000a505400000009080045000028a4e8400040067fe30a0101010a0101020001000259b5d9407c35468e5010721032030000'])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 '50540000000a505400000009080045000028a4e9400040067fe20a0101010a0101020001000259b5d9407c35468e5011721032020000'])
AT_CHECK([ovs-appctl netdev-dummy/receive p2 '50540000000950540000000a0800450000283b6140004006e96a0a0101020a010101000200017c35468e59b5d9415010721032020000'])

AT_CHECK([ovs-appctl revalidator/purge])
AT_CHECK([ovs-ofctl dump-flows br0 | grep cookie=0x1 | grep -o "n_packets=[[0-9]]*"], [0], [dnl
n_packets=2
])

AT_CHECK([ovs-ofctl dump-flows br0 | grep cookie=0x2 | grep -o "n_packets=[[0-9]]*"], [0], [dnl
n_packets=8
])

AT_CHECK([ovs-ofctl dump-flows br0 | grep cookie=0x3 | grep -o "n_packets=[[0-9]]*"], [0], [dnl
n_packets=7
])

AT_CHECK([ovs-ofctl dump-flows br0 | grep cookie=0x4 | grep -o "n_packets=[[0-9]]*"], [0], [dnl
n_packets=1
])

AT_CHECK([ovs-appctl dpctl/ct-enable-tcp-seq-chk], [], [dnl
enabling TCP sequence checking successful
])

AT_CHECK([ovs-appctl dpctl/ct-get-tcp-seq-chk], [], [dnl
TCP sequence checking: enabled
])

AT_CHECK([ovs-appctl dpctl/flush-conntrack])

dnl Send exactly the same 9 packets after disabling TCP sequence checking to
dnl confirm one more packet is marked invalid.
AT_CHECK([ovs-appctl netdev-dummy/receive p1 '50540000000a50540000000908004500002ca4e5400040067fe20a0101010a0101020001000259b5d93f0000000060027210dd190000020405b4'])
AT_CHECK([ovs-appctl netdev-dummy/receive p2 '50540000000950540000000a08004500002c00004000400624c80a0101020a010101000200017c35468459b5d940601272101a4f0000020405b4'])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 '50540000000a505400000009080045000028a4e6400040067fe50a0101010a0101020001000259b5d9407c35468550107210320c0000'])
AT_CHECK([ovs-appctl netdev-dummy/receive p2 '50540000000950540000000a0800450000303b5f40004006e9640a0101020a010101000200010000000000000000501872106a7300007061796c6f61640a'])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 '50540000000a505400000009080045000028a4e7400040067fe40a0101010a0101020001000259b5d9407c35468d5010721032040000'])
AT_CHECK([ovs-appctl netdev-dummy/receive p2 '50540000000950540000000a0800450000283b6040004006e96b0a0101020a010101000200017c35468d59b5d9405011721032030000'])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 '50540000000a505400000009080045000028a4e8400040067fe30a0101010a0101020001000259b5d9407c35468e5010721032030000'])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 '50540000000a505400000009080045000028a4e9400040067fe20a0101010a0101020001000259b5d9407c35468e5011721032020000'])
AT_CHECK([ovs-appctl netdev-dummy/receive p2 '50540000000950540000000a0800450000283b6140004006e96a0a0101020a010101000200017c35468e59b5d9415010721032020000'])

AT_CHECK([ovs-appctl revalidator/purge])
AT_CHECK([ovs-ofctl dump-flows br0 | grep cookie=0x1 | grep -o "n_packets=[[0-9]]*"], [0], [dnl
n_packets=3
])

AT_CHECK([ovs-ofctl dump-flows br0 | grep cookie=0x2 | grep -o "n_packets=[[0-9]]*"], [0], [dnl
n_packets=12
])

AT_CHECK([ovs-ofctl dump-flows br0 | grep cookie=0x3 | grep -o "n_packets=[[0-9]]*"], [0], [dnl
n_packets=10
])

AT_CHECK([ovs-ofctl dump-flows br0 | grep cookie=0x4 | grep -o "n_packets=[[0-9]]*"], [0], [dnl
n_packets=2
])

OVS_VSWITCHD_STOP
AT_CLEANUP

dnl This is a truncated version of "ofproto-dpif - conntrack - controller",
dnl with extra send-to-controller actions following ct_clear to show that
dnl the connection tracking data has been cleared.
AT_SETUP([ofproto-dpif - conntrack - ct_clear])
OVS_VSWITCHD_START

add_of_ports br0 1 2

AT_CHECK([ovs-appctl vlog/set dpif_netdev:dbg vconn:info ofproto_dpif:info])

dnl Allow new connections on p1->p2, but not on p2->p1.
AT_DATA([flows.txt], [dnl
dnl Table 0
dnl
table=0,priority=100,arp,action=normal
table=0,priority=10,in_port=1,udp,action=ct(commit,zone=0),controller,ct_clear,controller
table=0,priority=10,in_port=2,udp,action=ct(table=1,zone=0)
table=0,priority=1,action=drop
dnl
dnl Table 1
dnl
table=1,priority=10,in_port=2,ct_state=+trk+est-new,udp,action=controller,ct_clear,controller
table=1,priority=1,action=drop
])

AT_CHECK([ovs-ofctl add-flows br0 flows.txt])

AT_CAPTURE_FILE([ofctl_monitor.log])
AT_CHECK([ovs-ofctl monitor br0 65534 invalid_ttl -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

AT_CHECK([ovs-appctl netdev-dummy/receive p2 'in_port(2),eth(src=50:54:00:00:00:0a,dst=50:54:00:00:00:09),eth_type(0x0800),ipv4(src=10.1.1.2,dst=10.1.1.1,proto=17,tos=0,ttl=64,frag=no),udp(src=2,dst=1)'])

dnl OK, now start a new connection from port 1.
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.1.1.1,dst=10.1.1.2,proto=17,tos=0,ttl=64,frag=no),udp(src=1,dst=2)'])

dnl Now try a reply from port 2.
AT_CHECK([ovs-appctl netdev-dummy/receive p2 'in_port(2),eth(src=50:54:00:00:00:0a,dst=50:54:00:00:00:09),eth_type(0x0800),ipv4(src=10.1.1.2,dst=10.1.1.1,proto=17,tos=0,ttl=64,frag=no),udp(src=2,dst=1)'])

OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 8])
OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])

dnl Check this output. We only see the latter two packets, not the first.
dnl Note that the first packet doesn't have the ct_state bits set. This
dnl happens because the ct_state field is available only after recirc.
AT_CHECK([cat ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): cookie=0x0 total_len=106 in_port=1 (via action) data_len=106 (unbuffered)
udp,vlan_tci=0x0000,dl_src=50:54:00:00:00:09,dl_dst=50:54:00:00:00:0a,nw_src=10.1.1.1,nw_dst=10.1.1.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=1,tp_dst=2 udp_csum:553
dnl
NXT_PACKET_IN (xid=0x0): cookie=0x0 total_len=106 in_port=1 (via action) data_len=106 (unbuffered)
udp,vlan_tci=0x0000,dl_src=50:54:00:00:00:09,dl_dst=50:54:00:00:00:0a,nw_src=10.1.1.1,nw_dst=10.1.1.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=1,tp_dst=2 udp_csum:553
dnl
NXT_PACKET_IN (xid=0x0): table_id=1 cookie=0x0 total_len=106 ct_state=est|rpl|trk,ct_nw_src=10.1.1.1,ct_nw_dst=10.1.1.2,ct_nw_proto=17,ct_tp_src=1,ct_tp_dst=2,ip,in_port=2 (via action) data_len=106 (unbuffered)
udp,vlan_tci=0x0000,dl_src=50:54:00:00:00:0a,dl_dst=50:54:00:00:00:09,nw_src=10.1.1.2,nw_dst=10.1.1.1,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=2,tp_dst=1 udp_csum:553
dnl
NXT_PACKET_IN (xid=0x0): table_id=1 cookie=0x0 total_len=106 in_port=2 (via action) data_len=106 (unbuffered)
udp,vlan_tci=0x0000,dl_src=50:54:00:00:00:0a,dl_dst=50:54:00:00:00:09,nw_src=10.1.1.2,nw_dst=10.1.1.1,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=2,tp_dst=1 udp_csum:553
])

dnl The next test verifies that ct_clear at the datapath only gets executed
dnl if conntrack information is present.
AT_DATA([flows.txt], [dnl
table=0 in_port=1 actions=ct_clear,ct_clear,ct_clear,p2
])
AT_CHECK([ovs-ofctl del-flows br0])
AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
AT_CHECK([ovs-appctl ofproto/trace br0 'in_port=p1,dl_src=50:54:00:00:00:05,dl_dst=50:54:00:00:00:07,dl_type=0x0800,nw_src=192.168.0.1,nw_dst=192.168.0.2'], [0], [stdout])
AT_CHECK([tail -1 stdout], [0],
  [Datapath actions: 2
])
AT_DATA([flows.txt], [dnl
table=0 in_port=1 ip actions=ct_clear,ct(table=1)
table=1 in_port=1 actions=ct_clear,ct_clear,goto_table:2
table=2 in_port=1 actions=ct_clear,p2
])
AT_CHECK([ovs-ofctl del-flows br0])
AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
AT_CHECK([ovs-appctl ofproto/trace br0 'in_port=p1,dl_src=50:54:00:00:00:05,dl_dst=50:54:00:00:00:07,dl_type=0x0800,nw_src=192.168.0.1,nw_dst=192.168.0.2'], [0], [stdout])
AT_CHECK([grep Datapath stdout | sed 's/recirc(.*)/recirc(X)/'], [0],
  [Datapath actions: ct,recirc(X)
Datapath actions: ct_clear,2
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - conntrack - match masked ct fields])
OVS_VSWITCHD_START

add_of_ports br0 1 2

AT_CHECK([ovs-appctl vlog/set dpif_netdev:dbg vconn:info ofproto_dpif:info])

dnl Allow new connections on p1->p2. Allow only established connections p2->p1
AT_DATA([flows.txt], [dnl
table=0,arp,action=normal
table=0,ip,in_port=1,udp,nw_src=10.1.2.1/24,action=ct(commit)
table=0,ip,in_port=1,udp6,ipv6_dst=2001:db8::1/64,action=ct(commit)
table=0,ip,in_port=1,udp,tp_src=3/0x1,action=ct(commit)
table=0,ip,in_port=2,actions=ct(table=1)
table=0,ip6,in_port=2,actions=ct(table=1)
table=1,priority=10,udp,ct_state=+trk+rpl,ct_nw_src=10.1.2.1/24,actions=controller
table=1,priority=10,udp6,ct_state=+trk+rpl,ct_ipv6_dst=2001:db8::1/64,actions=controller
table=1,priority=10,udp,ct_state=+trk+rpl,ct_tp_src=3/0x1,actions=controller
table=1,priority=1,action=drop
])

AT_CHECK([ovs-ofctl add-flows br0 flows.txt])

AT_CAPTURE_FILE([ofctl_monitor.log])
AT_CHECK([ovs-ofctl monitor br0 65534 invalid_ttl -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])

dnl Match ct_nw_src=10.1.2.1/24
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.1.2.100,dst=10.1.2.200,proto=17,tos=0,ttl=64,frag=no),udp(src=6,dst=6)'])
AT_CHECK([ovs-appctl netdev-dummy/receive p2 'in_port(2),eth(src=50:54:00:00:00:0a,dst=50:54:00:00:00:09),eth_type(0x0800),ipv4(src=10.1.2.200,dst=10.1.2.100,proto=17,tos=0,ttl=64,frag=no),udp(src=6,dst=6)'])

dnl Match ct_ipv6_dst=2001:db8::1/64
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x86dd),ipv6(src=2001:db8::1,dst=2001:db8::2,label=0,proto=17,tclass=0x70,hlimit=128,frag=no),udp(src=1,dst=2)'])
AT_CHECK([ovs-appctl netdev-dummy/receive p2 'in_port(2),eth(src=50:54:00:00:00:0a,dst=50:54:00:00:00:09),eth_type(0x86dd),ipv6(src=2001:db8::2,dst=2001:db8::1,label=0,proto=17,tclass=0x70,hlimit=128,frag=no),udp(src=2,dst=1)'])

dnl Match ct_tp_src=3/0x1
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.1.1.1,dst=10.1.1.2,proto=17,tos=0,ttl=64,frag=no),udp(src=1,dst=2)'])
AT_CHECK([ovs-appctl netdev-dummy/receive p2 'in_port(2),eth(src=50:54:00:00:00:0a,dst=50:54:00:00:00:09),eth_type(0x0800),ipv4(src=10.1.1.2,dst=10.1.1.1,proto=17,tos=0,ttl=64,frag=no),udp(src=2,dst=1)'])

OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6])
OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])

dnl Check this output.
AT_CHECK([cat ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): table_id=1 cookie=0x0 total_len=106 ct_state=est|rpl|trk,ct_nw_src=10.1.2.100,ct_nw_dst=10.1.2.200,ct_nw_proto=17,ct_tp_src=6,ct_tp_dst=6,ip,in_port=2 (via action) data_len=106 (unbuffered)
udp,vlan_tci=0x0000,dl_src=50:54:00:00:00:0a,dl_dst=50:54:00:00:00:09,nw_src=10.1.2.200,nw_dst=10.1.2.100,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=6,tp_dst=6 udp_csum:221
dnl
NXT_PACKET_IN (xid=0x0): table_id=1 cookie=0x0 total_len=126 ct_state=est|rpl|trk,ct_ipv6_src=2001:db8::1,ct_ipv6_dst=2001:db8::2,ct_nw_proto=17,ct_tp_src=1,ct_tp_dst=2,ipv6,in_port=2 (via action) data_len=126 (unbuffered)
udp6,vlan_tci=0x0000,dl_src=50:54:00:00:00:0a,dl_dst=50:54:00:00:00:09,ipv6_src=2001:db8::2,ipv6_dst=2001:db8::1,ipv6_label=0x00000,nw_tos=112,nw_ecn=0,nw_ttl=128,tp_src=2,tp_dst=1 udp_csum:bfe2
dnl
NXT_PACKET_IN (xid=0x0): table_id=1 cookie=0x0 total_len=106 ct_state=est|rpl|trk,ct_nw_src=10.1.1.1,ct_nw_dst=10.1.1.2,ct_nw_proto=17,ct_tp_src=1,ct_tp_dst=2,ip,in_port=2 (via action) data_len=106 (unbuffered)
udp,vlan_tci=0x0000,dl_src=50:54:00:00:00:0a,dl_dst=50:54:00:00:00:09,nw_src=10.1.1.2,nw_dst=10.1.1.1,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=2,tp_dst=1 udp_csum:553
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - conntrack - ofproto/trace])
OVS_VSWITCHD_START

add_of_ports br0 1 2 3 4

AT_DATA([flows.txt], [dnl
dnl Table 0
dnl
table=0,priority=100,arp,action=normal
table=0,priority=10,udp,action=ct(table=1,zone=0)
table=0,priority=10,tcp,action=ct(table=2,zone=1)
table=0,priority=1,action=drop
dnl
dnl Table 1
dnl
table=1,priority=10,in_port=1,ct_zone=0,ct_state=+trk+new,udp,action=ct(commit,zone=0),2
table=1,priority=10,in_port=1,ct_zone=0,ct_state=+trk+est,udp,action=2
table=1,priority=10,in_port=2,ct_zone=0,ct_state=+trk+est,udp,action=1
table=1,priority=1,action=drop
dnl
dnl Table 2
dnl
table=2,priority=10,in_port=1,tcp,ct_zone=1,ct_state=+trk+new,tcp,action=ct(commit,zone=1),ct(table=3,zone=2)
table=2,priority=10,in_port=1,tcp,ct_zone=1,ct_state=+trk+est,tcp,action=ct(table=3,zone=2)
table=2,priority=1,action=drop
dnl
dnl Table 3
dnl
table=3,priority=10,in_port=1,tcp,ct_zone=2,ct_state=+trk+new,tcp,action=ct(commit,zone=2),4
table=3,priority=10,in_port=1,tcp,ct_zone=2,ct_state=+trk+est,tcp,action=3
table=2,priority=1,action=drop
])

AT_CHECK([ovs-ofctl add-flows br0 flows.txt])

AT_CHECK([ovs-appctl ofproto/trace br0 'in_port=2,udp'], [0], [stdout])
AT_CHECK([tail -1 stdout], [0],
  [Datapath actions: drop
])

AT_CHECK([ovs-appctl ofproto/trace br0 'in_port=1,udp'], [0], [stdout])
AT_CHECK([tail -1 stdout], [0],
  [Datapath actions: ct(commit),2
])

AT_CHECK([ovs-appctl ofproto/trace br0 'in_port=1,tcp'], [0], [stdout])
AT_CHECK([tail -1 stdout], [0],
  [Datapath actions: ct(commit,zone=2),4
])

AT_CHECK([ovs-appctl ofproto/trace br0 'in_port=1,tcp' --ct-next 'trk,est' --ct-next 'trk,est' ], [0], [stdout])
AT_CHECK([tail -1 stdout], [0],
  [Datapath actions: 3
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - nat - ofproto/trace])
OVS_VSWITCHD_START

add_of_ports br0 1 2 3

flow="in_port=1,udp,nw_src=1.1.1.1,nw_dst=1.1.1.2,udp_src=100,udp_dst=200"
AT_DATA([flows.txt], [dnl
table=0,priority=100,ip,nw_src=1.1.1.1,ct_state=-trk,action=ct(commit,nat(src=10.0.0.1-10.0.0.42:1000-1042),table=0)
table=0,priority=100,udp,ct_state=+trk,nw_src=10.0.0.1,nw_dst=1.1.1.2,tp_src=1000,tp_dst=200,action=ct(commit,nat(dst=20.0.0.1-20.0.0.42:2000-2042),table=0)
table=0,priority=100,udp,ct_state=+trk,nw_src=10.0.0.1,nw_dst=20.0.0.1,tp_src=1000,tp_dst=2000,action=3
table=0,priority=90,ip,ct_state=+trk,action=2
])
AT_CHECK([ovs-ofctl del-flows br0])
AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
AT_CHECK([ovs-appctl ofproto/trace br0 "$flow"], [0], [stdout])
AT_CHECK([tail -1 stdout], [0],
  [Datapath actions: 3
])

flow="in_port=1,udp6,ipv6_src=1::1,ipv6_dst=1::2,udp_src=100,udp_dst=200"
AT_DATA([flows.txt], [dnl
table=0,priority=100,ip6,ipv6_src=1::1,ct_state=-trk,action=ct(commit,nat(src=[[10::1]]-[[10::42]]:1000-1042),table=0)
table=0,priority=100,udp6,ct_state=+trk,ipv6_src=10::1,ipv6_dst=1::2,tp_src=1000,tp_dst=200,action=ct(commit,nat(dst=[[20::1]]-[[20::42]]:2000-2042),table=0)
table=0,priority=100,udp6,ct_state=+trk,ipv6_src=10::1,ipv6_dst=20::1,tp_src=1000,tp_dst=2000,action=3
table=0,priority=90,ip6,ct_state=+trk,action=2
])
AT_CHECK([ovs-ofctl del-flows br0])
AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
AT_CHECK([ovs-appctl ofproto/trace br0 "$flow"], [0], [stdout])
AT_CHECK([tail -1 stdout], [0],
  [Datapath actions: 3
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto - set mtu])
OVS_VSWITCHD_START

add_of_ports br0 1

# Check that initial MTU is 1500 for 'br0' and 'p1'.
AT_CHECK([ovs-vsctl get Interface br0 mtu], [0], [dnl
1500
])
AT_CHECK([ovs-vsctl get Interface p1 mtu], [0], [dnl
1500
])

# Request new MTU for 'p1'
AT_CHECK([ovs-vsctl set Interface p1 mtu_request=1600])

# Check that the new MTU is applied
AT_CHECK([ovs-vsctl wait-until Interface p1 mtu=1600])
# The internal port 'br0' should have the same MTU value as p1, becase it's
# the new bridge minimum.
AT_CHECK([ovs-vsctl wait-until Interface br0 mtu=1600])

AT_CHECK([ovs-vsctl del-port br0 p1])

# When 'p1' is deleted, the internal port should return to the default MTU
AT_CHECK([ovs-vsctl wait-until Interface br0 mtu=1500])

# New port with 'mtu_request' in the same transaction.
AT_CHECK([ovs-vsctl add-port br0 p2 -- set int p2 type=dummy mtu_request=1600])
AT_CHECK([ovs-vsctl wait-until Interface p2 mtu=1600])
AT_CHECK([ovs-vsctl wait-until Interface br0 mtu=1600])

# Explicitly set mtu_request on the internal member.  This should prevent
# the MTU from being overriden.
AT_CHECK([ovs-vsctl set int br0 mtu_request=1700])
AT_CHECK([ovs-vsctl wait-until Interface br0 mtu=1700])

# The new MTU on p2 should not affect br0.
AT_CHECK([ovs-vsctl set int p2 mtu_request=1400])
AT_CHECK([ovs-vsctl wait-until Interface p2 mtu=1400])
AT_CHECK([ovs-vsctl wait-until Interface br0 mtu=1700])

# Remove explicit mtu_request from br0.  Now it should track the bridge
# minimum again.
AT_CHECK([ovs-vsctl set int br0 mtu_request=[[]]])
AT_CHECK([ovs-vsctl wait-until Interface br0 mtu=1400])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto - fragment prerequisites])
OVS_VSWITCHD_START

AT_CHECK([ovs-appctl vlog/set dpif:dbg dpif_netdev:dbg])

add_of_ports br0 1

AT_DATA([flows.txt], [dnl
priority=10,in_port=1,udp,tp_src=67,tp_dst=68,action=drop
priority=1,in_port=1,udp,action=drop
])

AT_CHECK([ovs-ofctl add-flows br0 flows.txt])

AT_CHECK([ovs-vsctl set Open_vSwitch . other_config:max-idle=10000])

ovs-appctl time/stop
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'recirc_id(0),in_port(1),eth_type(0x0800),ipv4(proto=17,frag=later)'])
ovs-appctl time/warp 5000

AT_CHECK([strip_ufid < ovs-vswitchd.log | filter_flow_install | strip_used], [0], [dnl
recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(proto=17,frag=later), actions:drop
])

dnl Change the flow table.  This will trigger revalidation of all the flows.
AT_CHECK([ovs-ofctl add-flow br0 priority=5,in_port=1,action=drop])
AT_CHECK([ovs-appctl revalidator/wait], [0])

dnl We don't want revalidators to delete any flow.  If the flow has been
dnl deleted it means that there's some inconsistency with the revalidation.
AT_CHECK([grep flow_del ovs-vswitchd.log], [1])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - check_pkt_larger action])
OVS_VSWITCHD_START
add_of_ports br0 1 2 3 4

AT_DATA([flows.txt], [dnl
table=0,in_port=1 actions=check_pkt_larger(200)->NXM_NX_REG0[[0]],resubmit(,1)
table=1,in_port=1,reg0=0x1/0x1 actions=output:2,resubmit(,2)
table=1,in_port=1,actions=output:3,resubmit(,2)
table=2,in_port=1,actions=mod_dl_dst:82:82:82:82:82:82,output:4
])

AT_CHECK([ovs-ofctl --protocols=OpenFlow10 add-flows br0 flows.txt])
AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.10.10.2,dst=10.10.10.1,proto=1,tos=1,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])
AT_CHECK([tail -1 stdout], [0], [dnl
Datapath actions: check_pkt_len(size=200,gt(2,set(eth(dst=82:82:82:82:82:82)),4),le(3,set(eth(dst=82:82:82:82:82:82)),4))
])

dnl Test flow xlate check_pkt_large clone action without using datapath check_pkt_len action.
AT_CHECK([ovs-appctl dpif/set-dp-features br0 check_pkt_len false], [0], [ignore])

AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.10.10.2,dst=10.10.10.1,proto=1,tos=1,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])
AT_CHECK([tail -3 stdout], [0], [dnl
Datapath actions: 3,set(eth(dst=82:82:82:82:82:82)),4
This flow is handled by the userspace slow path because it:
  - Uses action(s) not supported by datapath.
])

dnl Enable datapath check_pkt_len action
AT_CHECK([ovs-appctl dpif/set-dp-features br0 check_pkt_len true], [0], [ignore])

ovs-ofctl del-flows br0

AT_DATA([flows.txt], [dnl
table=0,in_port=1 actions=check_pkt_larger(200)->NXM_NX_REG0[[0]],resubmit(,1)
table=1,in_port=1,priority=200,reg0=0x1/0x1 actions=output:2
])

AT_CHECK([ovs-ofctl --protocols=OpenFlow10 add-flows br0 flows.txt])
AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.10.10.2,dst=10.10.10.1,proto=1,tos=1,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])
AT_CHECK([tail -1 stdout], [0], [dnl
Datapath actions: check_pkt_len(size=200,gt(2),le(drop))
])

ovs-ofctl del-flows br0
AT_DATA([flows.txt], [dnl
table=0,in_port=1 actions=check_pkt_larger(200)->NXM_NX_REG0[[0]]
])

AT_CHECK([ovs-ofctl --protocols=OpenFlow10 add-flows br0 flows.txt])
AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.10.10.2,dst=10.10.10.1,proto=1,tos=1,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])
AT_CHECK([tail -1 stdout], [0], [dnl
Datapath actions: check_pkt_len(size=200,gt(drop),le(drop))
])

ovs-ofctl del-flows br0
AT_DATA([flows.txt], [dnl
table=0,in_port=1 actions=check_pkt_larger(200)->NXM_NX_REG0[[0]],resubmit(,1)
table=1,in_port=1,priority=200,reg0=0x1/0x1,ip actions=clone(set_field:192.168.3.3->ip_src),clone(set_field:192.168.4.4->ip_dst,output:2),clone(mod_dl_src:80:81:81:81:81:81,set_field:192.168.5.5->ip_dst,output:3),output:4
table=1,in_port=1,priority=0,ip actions=clone(set_field:192.168.3.3->ip_src),clone(set_field:192.168.4.4->ip_dst,output:2),clone(ct(commit),output:3),output:4
])

AT_CHECK([ovs-ofctl --protocols=OpenFlow10 add-flows br0 flows.txt])
AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.10.10.2,dst=10.10.10.1,proto=1,tos=1,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])
AT_CHECK([tail -1 stdout], [0], [dnl
Datapath actions: check_pkt_len(size=200,gt(set(ipv4(dst=192.168.4.4)),2,set(eth(src=80:81:81:81:81:81)),set(ipv4(dst=192.168.5.5)),3,set(eth(src=50:54:00:00:00:09)),set(ipv4(dst=10.10.10.1)),4),le(set(ipv4(dst=192.168.4.4)),2,set(ipv4(dst=10.10.10.1)),clone(ct(commit),3),4))
])

AT_DATA([flows.txt], [dnl
table=0,priority=0 actions=check_pkt_larger(200)->NXM_NX_REG0[[0]],resubmit(,1)
table=1,in_port=1,priority=200,reg0=0x1/0x1,ip actions=clone(set_field:192.168.3.3->ip_src, resubmit(,0))
table=1,in_port=1,priority=0,ip actions=clone(set_field:192.168.3.4->ip_src, resubmit(,0))
])

AT_CHECK([ovs-ofctl --protocols=OpenFlow10 add-flows br0 flows.txt])
ovs-ofctl dump-flows br0

AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.10.10.2,dst=10.10.10.1,proto=1,tos=1,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])
AT_CHECK([tail -3 stdout], [0], [dnl
Megaflow: recirc_id=0,eth,ip,reg0=0/0x1,in_port=1,nw_src=10.10.10.2,nw_frag=no
Datapath actions: drop
Translation failed (Recursion too deep), packet is dropped.
])

ovs-ofctl del-flows br0
AT_DATA([flows.txt], [dnl
table=0,priority=0 actions=check_pkt_larger(200)->NXM_NX_REG0[[0]],resubmit(,1)
table=1,ip,nw_src=192.168.3.3 actions=output:3
table=1,ip,nw_src=192.168.3.4 actions=output:4
table=1,reg0=0x1/0x1,ip actions=clone(set_field:192.168.3.3->ip_src, resubmit(,0))
table=1,ip actions=clone(set_field:192.168.3.4->ip_src, resubmit(,0))
])

AT_CHECK([ovs-ofctl --protocols=OpenFlow10 add-flows br0 flows.txt])
ovs-ofctl dump-flows br0

AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.10.10.2,dst=10.10.10.1,proto=1,tos=1,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])
AT_CHECK([tail -1 stdout], [0], [dnl
Datapath actions: check_pkt_len(size=200,gt(set(ipv4(src=192.168.3.3)),check_pkt_len(size=200,gt(3),le(3))),le(set(ipv4(src=192.168.3.4)),check_pkt_len(size=200,gt(4),le(4))))
])

ovs-ofctl del-flows br0
AT_DATA([flows.txt], [dnl
table=0,in_port=1 actions=check_pkt_larger(200)->NXM_NX_REG0[[0]],resubmit(,1)
table=1,in_port=1,reg0=0x1/0x1 actions=mod_dl_dst:82:82:82:82:82:82,controller(),resubmit(,2)
table=1,in_port=1 actions=resubmit(,2)
table=2,ip,dl_dst=82:82:82:82:82:82 actions=ct(table=3)
table=2,ip,dl_dst=50:54:00:00:00:0a actions=ct(table=3)
table=3,ip,reg0=0x1/0x1 actions=output:2
table=3,ip actions=output:4
])

AT_CHECK([ovs-ofctl --protocols=OpenFlow10 add-flows br0 flows.txt])
AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.10.10.2,dst=10.10.10.1,proto=1,tos=1,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])
AT_CHECK([cat stdout | grep Datapath -B1], [0], [dnl
Megaflow: recirc_id=0,eth,ip,in_port=1,dl_dst=50:54:00:00:00:0a,nw_frag=no
Datapath actions: check_pkt_len(size=200,gt(set(eth(dst=82:82:82:82:82:82)),userspace(pid=0,controller(reason=1,dont_send=1,continuation=0,recirc_id=1,rule_cookie=0,controller_id=0,max_len=65535)),ct,recirc(0x2)),le(ct,recirc(0x3)))
--
Megaflow: recirc_id=0x2,eth,ip,in_port=1,nw_frag=no
Datapath actions: 2
--
Megaflow: recirc_id=0x3,eth,ip,in_port=1,nw_frag=no
Datapath actions: 4
])

ovs-ofctl del-flows br0

AT_DATA([flows.txt], [dnl
table=0,in_port=1 actions=load:0x1->NXM_NX_REG1[[]],resubmit(,1),load:0x2->NXM_NX_REG1[[]],resubmit(,1),load:0x3->NXM_NX_REG1[[]],resubmit(,1)
table=1,in_port=1,reg1=0x1 actions=check_pkt_larger(200)->NXM_NX_REG0[[0]],resubmit(,4)
table=1,in_port=1,reg1=0x2 actions=output:2
table=1,in_port=1,reg1=0x3 actions=output:4
table=4,in_port=1 actions=output:3
])

AT_CHECK([ovs-ofctl --protocols=OpenFlow10 add-flows br0 flows.txt])
AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.10.10.2,dst=10.10.10.1,proto=1,tos=1,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])
AT_CHECK([cat stdout | grep Datapath -B1], [0], [dnl
Megaflow: recirc_id=0,eth,ip,in_port=1,nw_frag=no
Datapath actions: check_pkt_len(size=200,gt(3),le(3)),2,4
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - check_pkt_larger with continuation and ct])
OVS_VSWITCHD_START
add_of_ports --pcap br0 `seq 1 4`

AT_CAPTURE_FILE([ofctl_monitor0.log])
AT_CHECK([ovs-ofctl monitor br0 resume --detach --no-chdir --pidfile=ovs-ofctl0.pid 2> ofctl_monitor0.log])

AT_DATA([flows.txt], [dnl
table=0,in_port=1 actions=check_pkt_larger(150)->NXM_NX_REG0[[0]],resubmit(,1)
table=1,ip,reg0=0x1/0x1 actions=mod_dl_dst:82:82:82:82:82:82,controller(pause),resubmit(,2)
table=1,ip,reg0=0 actions=mod_dl_dst:83:83:83:83:83:83,controller(pause),resubmit(,2)
table=2,ip,dl_dst=82:82:82:82:82:82 actions=ct(table=3)
table=2,ip,dl_dst=83:83:83:83:83:83 actions=ct(table=3)
table=3,ip,reg0=0x1/0x1 actions=ct(commit),output:2
table=3,ip actions=ct(commit),output:4
])

AT_CHECK([ovs-ofctl --protocols=OpenFlow10 add-flows br0 flows.txt])

flow="in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.10.10.2,dst=10.10.10.1,proto=1,tos=1,ttl=128,frag=no),icmp(type=8,code=0)"

AT_CHECK([ovs-appctl netdev-dummy/receive p1 "$flow"], [0], [stdout])

OVS_WAIT_UNTIL([test 1 = `ovs-ofctl parse-pcap p4-tx.pcap \
| grep dl_dst=83:83:83:83:83:83 | wc -l`])
AT_CHECK([test 0 = `ovs-ofctl parse-pcap p2-tx.pcap | wc -l`])

AT_CHECK([ovs-appctl netdev-dummy/receive p1 "$flow" --len 200], [0], [stdout])

OVS_WAIT_UNTIL([test 1 = `ovs-ofctl parse-pcap p2-tx.pcap \
| grep dl_dst=82:82:82:82:82:82 | wc -l`])
AT_CHECK([test 1 = `ovs-ofctl parse-pcap p2-tx.pcap | wc -l`])

OVS_VSWITCHD_STOP
AT_CLEANUP
