+AT_CHECK([ovs-ofctl -F openflow10 dump-flows br0 | ofctl_strip], [0], [OFPST_FLOW reply:
+])
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+AT_SETUP([ofproto - set-field flow_mod commands (NXM)])
+OVS_VSWITCHD_START
+AT_CHECK([ovs-ofctl add-flow br0 ipv6,table=1,in_port=3,actions=drop])
+AT_CHECK([ovs-ofctl add-flow br0 ipv6,table=1,in_port=3,actions=set_field:fe80:0123:4567:890a:a6ba:dbff:fefe:59fa-\>ipv6_src])
+AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
+ table=1, ipv6,in_port=3 actions=load:0xa6badbfffefe59fa->NXM_NX_IPV6_SRC[[0..63]],load:0xfe8001234567890a->NXM_NX_IPV6_SRC[[64..127]]
+NXST_FLOW reply:
+])
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+AT_SETUP([ofproto - basic flow_mod commands (OpenFlow 1.2)])
+OVS_VSWITCHD_START
+AT_CHECK([ovs-ofctl -O OpenFlow12 dump-flows br0 | ofctl_strip], [0], [OFPST_FLOW reply (OF1.2):
+])
+AT_CHECK([echo 'in_port=2,actions=1' | ovs-ofctl -O OpenFlow12 add-flows br0 -])
+AT_CHECK([ovs-ofctl -O OpenFlow12 add-flow br0 in_port=1,actions=2])
+AT_CHECK([ovs-ofctl -O OpenFlow12 add-flow br0 table=1,in_port=4,actions=3])
+AT_CHECK([ovs-ofctl -O OpenFlow12 dump-flows br0 | ofctl_strip | sort], [0], [dnl
+ in_port=1 actions=output:2
+ in_port=2 actions=output:1
+ table=1, in_port=4 actions=output:3
+OFPST_FLOW reply (OF1.2):
+])
+AT_CHECK([ovs-ofctl -O OpenFlow12 del-flows br0])
+AT_CHECK([ovs-ofctl -O OpenFlow12 dump-flows br0 | ofctl_strip], [0], [OFPST_FLOW reply (OF1.2):
+])
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+AT_SETUP([ofproto - dump flows with cookie])
+OVS_VSWITCHD_START
+AT_CHECK([ovs-ofctl add-flow br0 cookie=0x1,in_port=1,actions=1])
+AT_CHECK([ovs-ofctl add-flow br0 cookie=0x2,in_port=2,actions=1])
+AT_CHECK([ovs-ofctl add-flow br0 cookie=0x3,in_port=3,actions=1])
+AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
+ cookie=0x1, in_port=1 actions=output:1
+ cookie=0x2, in_port=2 actions=output:1
+ cookie=0x3, in_port=3 actions=output:1
+NXST_FLOW reply:
+])
+AT_CHECK([ovs-ofctl dump-aggregate br0 table=0 | STRIP_XIDS], [0], [dnl
+NXST_AGGREGATE reply: packet_count=0 byte_count=0 flow_count=3
+])
+AT_CHECK([ovs-ofctl dump-flows br0 cookie=0x3/-1 | ofctl_strip | sort], [0], [dnl
+ cookie=0x3, in_port=3 actions=output:1
+NXST_FLOW reply:
+])
+AT_CHECK([ovs-ofctl dump-aggregate br0 cookie=0x3/-1 | STRIP_XIDS], [0], [dnl
+NXST_AGGREGATE reply: packet_count=0 byte_count=0 flow_count=1
+])
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+AT_SETUP([ofproto - mod flow with cookie change (OpenFlow 1.0)])
+OVS_VSWITCHD_START
+AT_CHECK([ovs-ofctl -F openflow10 add-flow br0 cookie=0x1,in_port=1,actions=1])
+AT_CHECK([ovs-ofctl -F openflow10 dump-flows br0 | ofctl_strip | sort], [0], [dnl
+ cookie=0x1, in_port=1 actions=output:1
+OFPST_FLOW reply:
+])
+
+AT_CHECK([ovs-ofctl -F openflow10 mod-flows br0 cookie=0x2,in_port=1,actions=1])
+AT_CHECK([ovs-ofctl -F openflow10 dump-flows br0 | ofctl_strip | sort], [0], [dnl
+ cookie=0x2, in_port=1 actions=output:1
+OFPST_FLOW reply:
+])
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+AT_SETUP([ofproto - mod flow with cookie change (NXM)])
+OVS_VSWITCHD_START
+AT_CHECK([ovs-ofctl -F nxm add-flow br0 cookie=0x1,in_port=1,actions=1])
+AT_CHECK([ovs-ofctl -F nxm dump-flows br0 | ofctl_strip | sort], [0], [dnl
+ cookie=0x1, in_port=1 actions=output:1
+NXST_FLOW reply:
+])
+
+AT_CHECK([ovs-ofctl -F nxm mod-flows br0 cookie=0x2,in_port=1,actions=1])
+AT_CHECK([ovs-ofctl -F nxm dump-flows br0 | ofctl_strip | sort], [0], [dnl
+ cookie=0x2, in_port=1 actions=output:1
+NXST_FLOW reply:
+])
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+dnl The OpenFlow 1.2 spec states that the cookie may not be modified
+AT_SETUP([ofproto - no mod flow with cookie change (OpenFlow1.2)])
+OVS_VSWITCHD_START
+AT_CHECK([ovs-ofctl -O OpenFlow12 add-flow br0 cookie=0x1,in_port=1,actions=1])
+AT_CHECK([ovs-ofctl -O OpenFlow12 dump-flows br0 | ofctl_strip | sort], [0], [dnl
+ cookie=0x1, in_port=1 actions=output:1
+OFPST_FLOW reply (OF1.2):
+])
+
+AT_CHECK([ovs-ofctl -O OpenFlow12 mod-flows br0 cookie=0x2,in_port=1,actions=1])
+AT_CHECK([ovs-ofctl -O OpenFlow12 dump-flows br0 | ofctl_strip | sort], [0], [dnl
+ cookie=0x1, in_port=1 actions=output:1
+OFPST_FLOW reply (OF1.2):
+])
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+AT_SETUP([ofproto - mod flows based on cookie mask (OpenFlow 1.0)])
+OVS_VSWITCHD_START
+AT_CHECK([ovs-ofctl add-flow br0 cookie=0x1,in_port=1,actions=1])
+AT_CHECK([ovs-ofctl add-flow br0 cookie=0x1,in_port=2,actions=1])
+AT_CHECK([ovs-ofctl add-flow br0 cookie=0x2,in_port=3,actions=1])
+AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
+ cookie=0x1, in_port=1 actions=output:1
+ cookie=0x1, in_port=2 actions=output:1
+ cookie=0x2, in_port=3 actions=output:1
+NXST_FLOW reply:
+])
+
+AT_CHECK([ovs-ofctl -F nxm mod-flows br0 cookie=0x1/0xff,actions=4])
+AT_CHECK([ovs-ofctl -F nxm dump-flows br0 | ofctl_strip | sort], [0], [dnl
+ cookie=0x1, in_port=1 actions=output:4
+ cookie=0x1, in_port=2 actions=output:4
+ cookie=0x2, in_port=3 actions=output:1
+NXST_FLOW reply:
+])
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+AT_SETUP([ofproto - mod flows based on cookie mask (OpenFlow 1.2)])
+OVS_VSWITCHD_START
+AT_CHECK([ovs-ofctl -O OpenFlow12 add-flow br0 cookie=0x1,in_port=1,actions=1])
+AT_CHECK([ovs-ofctl -O OpenFlow12 add-flow br0 cookie=0x1,in_port=2,actions=1])
+AT_CHECK([ovs-ofctl -O OpenFlow12 add-flow br0 cookie=0x2,in_port=3,actions=1])
+AT_CHECK([ovs-ofctl -O OpenFlow12 dump-flows br0 | ofctl_strip | sort], [0], [dnl
+ cookie=0x1, in_port=1 actions=output:1
+ cookie=0x1, in_port=2 actions=output:1
+ cookie=0x2, in_port=3 actions=output:1
+OFPST_FLOW reply (OF1.2):
+])
+
+AT_CHECK([ovs-ofctl -O OpenFlow12 mod-flows br0 cookie=0x1/0xff,actions=4])
+AT_CHECK([ovs-ofctl -O OpenFlow12 dump-flows br0 | ofctl_strip | sort], [0], [dnl
+ cookie=0x1, in_port=1 actions=output:4
+ cookie=0x1, in_port=2 actions=output:4
+ cookie=0x2, in_port=3 actions=output:1
+OFPST_FLOW reply (OF1.2):
+])
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+dnl The OpenFlow 1.2 spec states that the cookie may not be modified
+AT_SETUP([ofproto - mod flows based on cookie mask with cookie change])
+OVS_VSWITCHD_START
+AT_CHECK([ovs-ofctl add-flow br0 cookie=0x1,in_port=1,actions=1])
+AT_CHECK([ovs-ofctl add-flow br0 cookie=0x1,in_port=2,actions=1])
+AT_CHECK([ovs-ofctl add-flow br0 cookie=0x2,in_port=3,actions=1])
+AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
+ cookie=0x1, in_port=1 actions=output:1
+ cookie=0x1, in_port=2 actions=output:1
+ cookie=0x2, in_port=3 actions=output:1
+NXST_FLOW reply:
+])
+
+AT_CHECK([ovs-ofctl -F nxm mod-flows br0 cookie=1/-1,cookie=4,actions=4])
+AT_CHECK([ovs-ofctl -F nxm dump-flows br0 | ofctl_strip | sort], [0], [dnl
+ cookie=0x2, in_port=3 actions=output:1
+ cookie=0x4, in_port=1 actions=output:4
+ cookie=0x4, in_port=2 actions=output:4
+NXST_FLOW reply:
+])
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+AT_SETUP([ofproto - mod flow with cookie miss (mask==0)])
+OVS_VSWITCHD_START
+AT_CHECK([ovs-ofctl -F nxm mod-flows br0 in_port=1,actions=1])
+AT_CHECK([ovs-ofctl -F nxm dump-flows br0 | ofctl_strip | sort], [0], [dnl
+ in_port=1 actions=output:1
+NXST_FLOW reply:
+])
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+AT_SETUP([ofproto - mod flow with cookie miss (mask!=0)])
+OVS_VSWITCHD_START
+AT_CHECK([ovs-ofctl -F nxm mod-flows br0 cookie=1/1,in_port=1,actions=1])
+AT_CHECK([ovs-ofctl -F nxm dump-flows br0 | ofctl_strip | sort], [0], [dnl
+NXST_FLOW reply:
+])
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+AT_SETUP([ofproto - del flows with cookies])
+OVS_VSWITCHD_START
+AT_CHECK([ovs-ofctl add-flow br0 cookie=0x1,in_port=1,actions=1])
+AT_CHECK([ovs-ofctl add-flow br0 cookie=0x2,in_port=2,actions=1])
+AT_CHECK([ovs-ofctl add-flow br0 cookie=0x3,in_port=3,actions=1])
+AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
+ cookie=0x1, in_port=1 actions=output:1
+ cookie=0x2, in_port=2 actions=output:1
+ cookie=0x3, in_port=3 actions=output:1
+NXST_FLOW reply:
+])
+
+AT_CHECK([ovs-ofctl del-flows br0])
+AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
+NXST_FLOW reply:
+])
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+AT_SETUP([ofproto - del flows based on cookie])
+OVS_VSWITCHD_START
+AT_CHECK([ovs-ofctl add-flow br0 cookie=0x1,in_port=1,actions=1])
+AT_CHECK([ovs-ofctl add-flow br0 cookie=0x2,in_port=2,actions=1])
+AT_CHECK([ovs-ofctl add-flow br0 cookie=0x3,in_port=3,actions=1])
+AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
+ cookie=0x1, in_port=1 actions=output:1
+ cookie=0x2, in_port=2 actions=output:1
+ cookie=0x3, in_port=3 actions=output:1
+NXST_FLOW reply:
+])
+
+AT_CHECK([ovs-ofctl del-flows br0 cookie=0x3/-1])
+AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
+ cookie=0x1, in_port=1 actions=output:1
+ cookie=0x2, in_port=2 actions=output:1
+NXST_FLOW reply:
+])
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+AT_SETUP([ofproto - del flows based on cookie mask])
+OVS_VSWITCHD_START
+AT_CHECK([ovs-ofctl add-flow br0 cookie=0x1,in_port=1,actions=1])
+AT_CHECK([ovs-ofctl add-flow br0 cookie=0x2,in_port=2,actions=1])
+AT_CHECK([ovs-ofctl add-flow br0 cookie=0x3,in_port=3,actions=1])
+AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
+ cookie=0x1, in_port=1 actions=output:1
+ cookie=0x2, in_port=2 actions=output:1
+ cookie=0x3, in_port=3 actions=output:1
+NXST_FLOW reply:
+])
+AT_CHECK([ovs-ofctl del-flows br0 cookie=0x3/0x1])
+AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
+ cookie=0x2, in_port=2 actions=output:1
+NXST_FLOW reply:
+])
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+AT_SETUP([ofproto - del flows based on table id (NXM)])
+OVS_VSWITCHD_START
+AT_CHECK([ovs-ofctl add-flow br0 cookie=0x1,in_port=1,actions=1])
+AT_CHECK([ovs-ofctl add-flow br0 cookie=0x2,in_port=2,table=1,actions=1])
+AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
+ cookie=0x1, in_port=1 actions=output:1
+ cookie=0x2, table=1, in_port=2 actions=output:1
+NXST_FLOW reply:
+])
+AT_CHECK([ovs-ofctl del-flows br0 table=0])
+AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
+ cookie=0x2, table=1, in_port=2 actions=output:1
+NXST_FLOW reply:
+])
+AT_CHECK([ovs-ofctl del-flows br0 table=1])
+AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
+NXST_FLOW reply:
+])
+AT_CHECK([ovs-ofctl add-flow br0 cookie=0x1,in_port=1,actions=1])
+AT_CHECK([ovs-ofctl add-flow br0 cookie=0x2,in_port=2,table=1,actions=1])
+AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
+ cookie=0x1, in_port=1 actions=output:1
+ cookie=0x2, table=1, in_port=2 actions=output:1
+NXST_FLOW reply:
+])
+AT_CHECK([ovs-ofctl del-flows br0])
+AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
+NXST_FLOW reply:
+])
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+AT_SETUP([ofproto - del flows based on table id (OpenFlow 1.2)])
+OVS_VSWITCHD_START
+AT_CHECK([ovs-ofctl -O OpenFlow12 add-flow br0 cookie=0x1,in_port=1,actions=1])
+AT_CHECK([ovs-ofctl -O OpenFlow12 add-flow br0 cookie=0x2,in_port=2,table=1,actions=1])
+AT_CHECK([ovs-ofctl -O OpenFlow12 dump-flows br0 | ofctl_strip | sort], [0], [dnl
+ cookie=0x1, in_port=1 actions=output:1
+ cookie=0x2, table=1, in_port=2 actions=output:1
+OFPST_FLOW reply (OF1.2):
+])
+AT_CHECK([ovs-ofctl -O OpenFlow12 del-flows br0 table=0])
+AT_CHECK([ovs-ofctl -O OpenFlow12 dump-flows br0 | ofctl_strip | sort], [0], [dnl
+ cookie=0x2, table=1, in_port=2 actions=output:1
+OFPST_FLOW reply (OF1.2):
+])
+AT_CHECK([ovs-ofctl -O OpenFlow12 del-flows br0 table=1])
+AT_CHECK([ovs-ofctl -O OpenFlow12 dump-flows br0 | ofctl_strip | sort], [0], [dnl
+OFPST_FLOW reply (OF1.2):
+])
+AT_CHECK([ovs-ofctl -O OpenFlow12 add-flow br0 cookie=0x1,in_port=1,actions=1])
+AT_CHECK([ovs-ofctl -O OpenFlow12 add-flow br0 cookie=0x2,in_port=2,table=1,actions=1])
+AT_CHECK([ovs-ofctl -O OpenFlow12 dump-flows br0 | ofctl_strip | sort], [0], [dnl
+ cookie=0x1, in_port=1 actions=output:1
+ cookie=0x2, table=1, in_port=2 actions=output:1
+OFPST_FLOW reply (OF1.2):
+])
+AT_CHECK([ovs-ofctl -O OpenFlow12 del-flows br0])
+AT_CHECK([ovs-ofctl -O OpenFlow12 dump-flows br0 | ofctl_strip | sort], [0], [dnl
+OFPST_FLOW reply (OF1.2):
+])
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+AT_SETUP([ofproto - flow table configuration (OpenFlow 1.0)])
+OVS_VSWITCHD_START
+# Check the default configuration.
+(echo "OFPST_TABLE reply (xid=0x2): 254 tables
+ 0: classifier: wild=0x3fffff, max=1000000, active=0
+ lookup=0, matched=0"
+ x=1
+ while test $x -lt 254; do
+ printf " %d: %-8s: wild=0x3fffff, max=1000000, active=0
+ lookup=0, matched=0
+" $x table$x
+ x=`expr $x + 1`
+ done) > expout
+AT_CHECK([ovs-ofctl dump-tables br0], [0], [expout])
+# Change the configuration.
+AT_CHECK(
+ [ovs-vsctl \
+ -- --id=@t0 create Flow_Table name=main \
+ -- --id=@t1 create Flow_Table flow-limit=1024 \
+ -- set bridge br0 'flow_tables={1=@t1,0=@t0}' \
+ | perl $srcdir/uuidfilt.pl],
+ [0], [<0>
+<1>
+])
+# Check that the configuration was updated.
+mv expout orig-expout
+(echo "OFPST_TABLE reply (xid=0x2): 254 tables
+ 0: main : wild=0x3fffff, max=1000000, active=0
+ lookup=0, matched=0
+ 1: table1 : wild=0x3fffff, max= 1024, active=0
+ lookup=0, matched=0"
+ tail -n +6 orig-expout) > expout
+AT_CHECK([ovs-ofctl dump-tables br0], [0], [expout])
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+AT_SETUP([ofproto - flow table configuration (OpenFlow 1.2)])
+OVS_VSWITCHD_START
+# Check the default configuration.
+(mid="wild=0xffffffffff, max=1000000,"
+ tail="
+ lookup=0, matched=0
+ match=0xffffffffff, instructions=0x00000007, config=0x00000003
+ write_actions=0x00000000, apply_actions=0x00000000
+ write_setfields=0x000000ffffffffff
+ apply_setfields=0x000000ffffffffff
+ metadata_match=0xffffffffffffffff
+ metadata_write=0xffffffffffffffff"
+ echo "OFPST_TABLE reply (OF1.2) (xid=0x2): 254 tables
+ 0: classifier: $mid active=0$tail"
+ x=1
+ while test $x -lt 254; do
+ printf " %d: %-8s: $mid active=0$tail
+" $x table$x
+ x=`expr $x + 1`
+ done) > expout
+AT_CHECK([ovs-ofctl -O OpenFlow12 dump-tables br0], [0], [expout])
+# Change the configuration.
+AT_CHECK(
+ [ovs-vsctl \
+ -- --id=@t0 create Flow_Table name=main \
+ -- --id=@t1 create Flow_Table flow-limit=1024 \
+ -- set bridge br0 'flow_tables={1=@t1,0=@t0}' \
+ | perl $srcdir/uuidfilt.pl],
+ [0], [<0>
+<1>
+])
+# Check that the configuration was updated.
+mv expout orig-expout
+(echo "OFPST_TABLE reply (OF1.2) (xid=0x2): 254 tables
+ 0: main : wild=0xffffffffff, max=1000000, active=0"
+ tail -n +3 orig-expout | head -7
+ echo " 1: table1 : wild=0xffffffffff, max= 1024, active=0"
+ tail -n +11 orig-expout) > expout
+AT_CHECK([ovs-ofctl -O OpenFlow12 dump-tables br0], [0], [expout])
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+AT_SETUP([ofproto - hard limits on flow table size (OpenFLow 1.0)])
+OVS_VSWITCHD_START
+# Configure a maximum of 4 flows.
+AT_CHECK(
+ [ovs-vsctl \
+ -- --id=@t0 create Flow_Table flow-limit=4 \
+ -- set bridge br0 flow_tables:0=@t0 \
+ | perl $srcdir/uuidfilt.pl],
+ [0], [<0>
+])
+# Add 4 flows.
+for in_port in 1 2 3 4; do
+ ovs-ofctl add-flow br0 in_port=$in_port,actions=drop
+done
+AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
+ in_port=1 actions=drop
+ in_port=2 actions=drop
+ in_port=3 actions=drop
+ in_port=4 actions=drop
+NXST_FLOW reply:
+])
+# Adding another flow will be refused.
+AT_CHECK([ovs-ofctl add-flow br0 in_port=5,actions=drop], [1], [], [stderr])
+AT_CHECK([head -n 1 stderr | ofctl_strip], [0],
+ [OFPT_ERROR: OFPFMFC_TABLE_FULL
+])
+# Also a mod-flow that would add a flow will be refused.
+AT_CHECK([ovs-ofctl mod-flows br0 in_port=5,actions=drop], [1], [], [stderr])
+AT_CHECK([head -n 1 stderr | ofctl_strip], [0],
+ [OFPT_ERROR: OFPFMFC_TABLE_FULL
+])
+# Replacing or modifying an existing flow is allowed.
+AT_CHECK([ovs-ofctl add-flow br0 in_port=4,actions=normal])
+AT_CHECK([ovs-ofctl mod-flows br0 in_port=3,actions=output:1])
+AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
+ in_port=1 actions=drop
+ in_port=2 actions=drop
+ in_port=3 actions=output:1
+ in_port=4 actions=NORMAL
+NXST_FLOW reply:
+])
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+AT_SETUP([ofproto - hard limits on flow table size (OpenFLow 1.2)])
+OVS_VSWITCHD_START
+# Configure a maximum of 4 flows.
+AT_CHECK(
+ [ovs-vsctl \
+ -- --id=@t0 create Flow_Table flow-limit=4 \
+ -- set bridge br0 flow_tables:0=@t0 \
+ | perl $srcdir/uuidfilt.pl],
+ [0], [<0>
+])
+# Add 4 flows.
+for in_port in 1 2 3 4; do
+ ovs-ofctl -O OpenFlow12 add-flow br0 in_port=$in_port,actions=drop
+done
+AT_CHECK([ovs-ofctl -O OpenFlow12 dump-flows br0 | ofctl_strip | sort], [0], [dnl
+ in_port=1 actions=drop
+ in_port=2 actions=drop
+ in_port=3 actions=drop
+ in_port=4 actions=drop
+OFPST_FLOW reply (OF1.2):
+])
+# Adding another flow will be refused.
+AT_CHECK([ovs-ofctl -O OpenFlow12 add-flow br0 in_port=5,actions=drop], [1], [], [stderr])
+AT_CHECK([head -n 1 stderr | ofctl_strip], [0],
+ [OFPT_ERROR (OF1.2): OFPFMFC_TABLE_FULL
+])
+# Replacing or modifying an existing flow is allowed.
+AT_CHECK([ovs-ofctl -O OpenFlow12 add-flow br0 in_port=4,actions=normal])
+AT_CHECK([ovs-ofctl -O OpenFlow12 mod-flows br0 in_port=3,actions=output:1])
+AT_CHECK([ovs-ofctl -O OpenFlow12 dump-flows br0 | ofctl_strip | sort], [0], [dnl
+ in_port=1 actions=drop
+ in_port=2 actions=drop
+ in_port=3 actions=output:1
+ in_port=4 actions=NORMAL
+OFPST_FLOW reply (OF1.2):
+])
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+AT_SETUP([ofproto - eviction upon table overflow (OpenFlow 1.0)])
+OVS_VSWITCHD_START
+# Configure a maximum of 4 flows.
+AT_CHECK(
+ [ovs-vsctl \
+ -- --id=@t0 create Flow_Table flow-limit=4 overflow-policy=evict \
+ -- set bridge br0 flow_tables:0=@t0 \
+ | perl $srcdir/uuidfilt.pl],
+ [0], [<0>
+])
+# Add 4 flows.
+for in_port in 4 3 2 1; do
+ ovs-ofctl add-flow br0 idle_timeout=${in_port}0,in_port=$in_port,actions=drop
+done
+AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
+ idle_timeout=10, in_port=1 actions=drop
+ idle_timeout=20, in_port=2 actions=drop
+ idle_timeout=30, in_port=3 actions=drop
+ idle_timeout=40, in_port=4 actions=drop
+NXST_FLOW reply:
+])
+# Adding another flow will cause the one that expires soonest to be evicted.
+AT_CHECK([ovs-ofctl add-flow br0 in_port=5,actions=drop])
+AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
+ idle_timeout=20, in_port=2 actions=drop
+ idle_timeout=30, in_port=3 actions=drop
+ idle_timeout=40, in_port=4 actions=drop
+ in_port=5 actions=drop
+NXST_FLOW reply:
+])
+# A mod-flow that adds a flow also causes eviction, but replacing or
+# modifying an existing flow doesn't.
+AT_CHECK([ovs-ofctl mod-flows br0 in_port=6,actions=drop])
+AT_CHECK([ovs-ofctl add-flow br0 in_port=4,actions=normal])
+AT_CHECK([ovs-ofctl mod-flows br0 in_port=3,actions=output:1])
+AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
+ idle_timeout=30, in_port=3 actions=output:1
+ in_port=4 actions=NORMAL
+ in_port=5 actions=drop
+ in_port=6 actions=drop
+NXST_FLOW reply:
+])
+# Flows with no timeouts at all cannot be evicted.
+AT_CHECK([ovs-ofctl add-flow br0 in_port=7,actions=normal])
+AT_CHECK([ovs-ofctl add-flow br0 in_port=8,actions=drop], [1], [], [stderr])
+AT_CHECK([head -n 1 stderr | ofctl_strip], [0],
+ [OFPT_ERROR: OFPFMFC_TABLE_FULL
+])
+AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
+ in_port=4 actions=NORMAL
+ in_port=5 actions=drop
+ in_port=6 actions=drop
+ in_port=7 actions=NORMAL
+NXST_FLOW reply:
+])
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+AT_SETUP([ofproto - eviction upon table overflow (OpenFlow 1.2)])
+OVS_VSWITCHD_START
+# Configure a maximum of 4 flows.
+AT_CHECK(
+ [ovs-vsctl \
+ -- --id=@t0 create Flow_Table flow-limit=4 overflow-policy=evict \
+ -- set bridge br0 flow_tables:0=@t0 \
+ | perl $srcdir/uuidfilt.pl],
+ [0], [<0>
+])
+# Add 4 flows.
+for in_port in 4 3 2 1; do
+ ovs-ofctl -O OpenFlow12 add-flow br0 idle_timeout=${in_port}0,in_port=$in_port,actions=drop
+done
+AT_CHECK([ovs-ofctl -O OpenFlow12 dump-flows br0 | ofctl_strip | sort], [0], [dnl
+ idle_timeout=10, in_port=1 actions=drop
+ idle_timeout=20, in_port=2 actions=drop
+ idle_timeout=30, in_port=3 actions=drop
+ idle_timeout=40, in_port=4 actions=drop
+OFPST_FLOW reply (OF1.2):
+])
+# Adding another flow will cause the one that expires soonest to be evicted.
+AT_CHECK([ovs-ofctl -O OpenFlow12 add-flow br0 in_port=5,actions=drop])
+AT_CHECK([ovs-ofctl -O OpenFlow12 dump-flows br0 | ofctl_strip | sort], [0], [dnl
+ idle_timeout=20, in_port=2 actions=drop
+ idle_timeout=30, in_port=3 actions=drop
+ idle_timeout=40, in_port=4 actions=drop
+ in_port=5 actions=drop
+OFPST_FLOW reply (OF1.2):
+])
+# In Open Flow 1.2 a mod-flow does not ever add a flow and thus
+# has no effect on eviction
+AT_CHECK([ovs-ofctl -O OpenFlow12 mod-flows br0 in_port=6,actions=drop])
+AT_CHECK([ovs-ofctl -O OpenFlow12 add-flow br0 in_port=4,actions=normal])
+AT_CHECK([ovs-ofctl -O OpenFlow12 mod-flows br0 in_port=3,actions=output:1])
+AT_CHECK([ovs-ofctl -O OpenFlow12 dump-flows br0 | ofctl_strip | sort], [0], [dnl
+ idle_timeout=20, in_port=2 actions=drop
+ idle_timeout=30, in_port=3 actions=output:1
+ in_port=4 actions=NORMAL
+ in_port=5 actions=drop
+OFPST_FLOW reply (OF1.2):
+])
+# Flows with no timeouts at all cannot be evicted.
+AT_CHECK([ovs-ofctl -O OpenFlow12 add-flow br0 in_port=6,actions=drop])
+AT_CHECK([ovs-ofctl -O OpenFlow12 add-flow br0 in_port=7,actions=normal])
+AT_CHECK([ovs-ofctl -O OpenFlow12 add-flow br0 in_port=8,actions=drop], [1], [], [stderr])
+AT_CHECK([head -n 1 stderr | ofctl_strip], [0],
+ [OFPT_ERROR (OF1.2): OFPFMFC_TABLE_FULL
+])
+AT_CHECK([ovs-ofctl -O OpenFlow12 dump-flows br0 | ofctl_strip | sort], [0], [dnl
+ in_port=4 actions=NORMAL
+ in_port=5 actions=drop
+ in_port=6 actions=drop
+ in_port=7 actions=NORMAL
+OFPST_FLOW reply (OF1.2):
+])
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+AT_SETUP([ofproto - eviction upon table overflow, with fairness (OpenFlow 1.0)])
+OVS_VSWITCHD_START
+# Configure a maximum of 4 flows.
+AT_CHECK(
+ [ovs-vsctl \
+ -- --id=@t0 create Flow_Table name=evict flow-limit=4 \
+ overflow-policy=evict \
+ groups='"NXM_OF_IN_PORT[[]]"' \
+ -- set bridge br0 flow_tables:0=@t0 \
+ | perl $srcdir/uuidfilt.pl],
+ [0], [<0>
+])
+# Add 4 flows.
+ovs-ofctl add-flows br0 - <<EOF
+idle_timeout=10 in_port=2 dl_src=00:44:55:66:77:88 actions=drop
+idle_timeout=20 in_port=1 dl_src=00:11:22:33:44:55 actions=drop
+idle_timeout=30 in_port=1 dl_src=00:22:33:44:55:66 actions=drop
+idle_timeout=40 in_port=1 dl_src=00:33:44:55:66:77 actions=drop
+EOF
+AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
+ idle_timeout=10, in_port=2,dl_src=00:44:55:66:77:88 actions=drop
+ idle_timeout=20, in_port=1,dl_src=00:11:22:33:44:55 actions=drop
+ idle_timeout=30, in_port=1,dl_src=00:22:33:44:55:66 actions=drop
+ idle_timeout=40, in_port=1,dl_src=00:33:44:55:66:77 actions=drop
+NXST_FLOW reply:
+])
+# Adding another flow will cause the one that expires soonest within
+# the largest group (those with in_port=1) to be evicted. In this
+# case this is not the same as the one that expires soonest overall
+# (which is what makes the test interesting):
+AT_CHECK([ovs-ofctl add-flow br0 in_port=2,dl_src=00:55:66:77:88:99,actions=drop])
+AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
+ idle_timeout=10, in_port=2,dl_src=00:44:55:66:77:88 actions=drop
+ idle_timeout=30, in_port=1,dl_src=00:22:33:44:55:66 actions=drop
+ idle_timeout=40, in_port=1,dl_src=00:33:44:55:66:77 actions=drop
+ in_port=2,dl_src=00:55:66:77:88:99 actions=drop
+NXST_FLOW reply:
+])
+# Enlarge the flow limit, change the eviction policy back to strictly
+# based on expiration, and and add some flows.
+AT_CHECK([ovs-vsctl set Flow_Table evict groups='[[]]' flow-limit=7])
+ovs-ofctl add-flows br0 - <<EOF
+idle_timeout=50 in_port=2 dl_src=00:66:77:88:99:aa actions=drop
+idle_timeout=60 in_port=2 dl_src=00:77:88:99:aa:bb actions=drop
+idle_timeout=70 in_port=2 dl_src=00:88:99:aa:bb:cc actions=drop
+EOF
+AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
+ idle_timeout=10, in_port=2,dl_src=00:44:55:66:77:88 actions=drop
+ idle_timeout=30, in_port=1,dl_src=00:22:33:44:55:66 actions=drop
+ idle_timeout=40, in_port=1,dl_src=00:33:44:55:66:77 actions=drop
+ idle_timeout=50, in_port=2,dl_src=00:66:77:88:99:aa actions=drop
+ idle_timeout=60, in_port=2,dl_src=00:77:88:99:aa:bb actions=drop
+ idle_timeout=70, in_port=2,dl_src=00:88:99:aa:bb:cc actions=drop
+ in_port=2,dl_src=00:55:66:77:88:99 actions=drop
+NXST_FLOW reply:
+])
+# Adding another flow will cause the one that expires soonest overall
+# to be evicted.
+AT_CHECK([ovs-ofctl add-flow br0 'idle_timeout=80 in_port=2 dl_src=00:99:aa:bb:cc:dd actions=drop'])
+AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
+ idle_timeout=30, in_port=1,dl_src=00:22:33:44:55:66 actions=drop
+ idle_timeout=40, in_port=1,dl_src=00:33:44:55:66:77 actions=drop
+ idle_timeout=50, in_port=2,dl_src=00:66:77:88:99:aa actions=drop
+ idle_timeout=60, in_port=2,dl_src=00:77:88:99:aa:bb actions=drop
+ idle_timeout=70, in_port=2,dl_src=00:88:99:aa:bb:cc actions=drop
+ idle_timeout=80, in_port=2,dl_src=00:99:aa:bb:cc:dd actions=drop
+ in_port=2,dl_src=00:55:66:77:88:99 actions=drop
+NXST_FLOW reply:
+])
+# Reducing the flow limit also causes the flows that expire soonest
+# overall to be evicted.
+AT_CHECK([ovs-vsctl set Flow_Table evict flow-limit=4])
+AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
+ idle_timeout=60, in_port=2,dl_src=00:77:88:99:aa:bb actions=drop
+ idle_timeout=70, in_port=2,dl_src=00:88:99:aa:bb:cc actions=drop
+ idle_timeout=80, in_port=2,dl_src=00:99:aa:bb:cc:dd actions=drop
+ in_port=2,dl_src=00:55:66:77:88:99 actions=drop
+NXST_FLOW reply:
+])
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+AT_SETUP([ofproto - eviction upon table overflow, with fairness (OpenFlow 1.2)])
+OVS_VSWITCHD_START
+# Configure a maximum of 4 flows.
+AT_CHECK(
+ [ovs-vsctl \
+ -- --id=@t0 create Flow_Table name=evict flow-limit=4 \
+ overflow-policy=evict \
+ groups='"NXM_OF_IN_PORT[[]]"' \
+ -- set bridge br0 flow_tables:0=@t0 \
+ | perl $srcdir/uuidfilt.pl],
+ [0], [<0>
+])
+# Add 4 flows.
+ovs-ofctl -O OpenFlow12 add-flows br0 - <<EOF
+idle_timeout=10 in_port=2 dl_src=00:44:55:66:77:88 actions=drop
+idle_timeout=20 in_port=1 dl_src=00:11:22:33:44:55 actions=drop
+idle_timeout=30 in_port=1 dl_src=00:22:33:44:55:66 actions=drop
+idle_timeout=40 in_port=1 dl_src=00:33:44:55:66:77 actions=drop
+EOF
+AT_CHECK([ovs-ofctl -O OpenFlow12 dump-flows br0 | ofctl_strip | sort], [0], [dnl
+ idle_timeout=10, in_port=2,dl_src=00:44:55:66:77:88 actions=drop
+ idle_timeout=20, in_port=1,dl_src=00:11:22:33:44:55 actions=drop
+ idle_timeout=30, in_port=1,dl_src=00:22:33:44:55:66 actions=drop
+ idle_timeout=40, in_port=1,dl_src=00:33:44:55:66:77 actions=drop
+OFPST_FLOW reply (OF1.2):