]> git.proxmox.com Git - mirror_ovs.git/blame - tests/learn.at
check-kmod: Remove all OVS modules in this target.
[mirror_ovs.git] / tests / learn.at
CommitLineData
75a75043
BP
1AT_BANNER([learning action])
2
3AT_SETUP([learning action - parsing and formatting])
4AT_DATA([flows.txt], [[
5actions=learn()
35f48b8b
BP
6actions=learn(send_flow_rem)
7actions=learn(delete_learned)
8actions=learn(send_flow_rem,delete_learned)
75a75043 9actions=learn(NXM_OF_VLAN_TCI[0..11], NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[], output:NXM_OF_IN_PORT[], load:10->NXM_NX_REG0[5..10])
0e553d9c 10actions=learn(table=1,idle_timeout=10, hard_timeout=20, fin_idle_timeout=5, fin_hard_timeout=10, priority=10, cookie=0xfedcba9876543210, in_port=99,NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[],load:NXM_OF_IN_PORT[]->NXM_NX_REG1[16..31])
75a75043
BP
11]])
12AT_CHECK([ovs-ofctl parse-flows flows.txt], [0],
aa233d57 13[[usable protocols: any
27527aa0
BP
14chosen protocol: OpenFlow10-table_id
15OFPT_FLOW_MOD (xid=0x1): ADD actions=learn(table=1)
35f48b8b
BP
16OFPT_FLOW_MOD (xid=0x2): ADD actions=learn(table=1,send_flow_rem)
17OFPT_FLOW_MOD (xid=0x3): ADD actions=learn(table=1,delete_learned)
18OFPT_FLOW_MOD (xid=0x4): ADD actions=learn(table=1,send_flow_rem,delete_learned)
19OFPT_FLOW_MOD (xid=0x5): ADD actions=learn(table=1,NXM_OF_VLAN_TCI[0..11],NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[],output:NXM_OF_IN_PORT[],load:0xa->NXM_NX_REG0[5..10])
20OFPT_FLOW_MOD (xid=0x6): ADD actions=learn(table=1,idle_timeout=10,hard_timeout=20,fin_idle_timeout=5,fin_hard_timeout=10,priority=10,cookie=0xfedcba9876543210,in_port=99,NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[],load:NXM_OF_IN_PORT[]->NXM_NX_REG1[16..31])
75a75043
BP
21]])
22AT_CLEANUP
eddfcba7 23
72333065
JR
24AT_SETUP([learning action - parsing and formatting - illegal in_port_oxm])
25AT_CHECK([[ovs-ofctl parse-flow 'actions=learn(table=1, in_port_oxm=123456)']],
26 [1], [], [stderr])
27AT_CHECK([sed -e 's/.*|ofp_util|WARN|//' < stderr], [0],
28 [[port 123456 is outside the supported range 0 through ffff or 0xffffff00 through 0xffffffff
29ovs-ofctl: 123456: port value out of range for in_port_oxm
30]], [[]])
31AT_CLEANUP
32
33AT_SETUP([learning action - parsing and formatting - OXM])
34AT_DATA([flows.txt], [[
35actions=learn(output:OXM_OF_IN_PORT[])
36actions=learn(table=1, in_port=1, load:OXM_OF_IN_PORT[]->NXM_NX_REG1[], load:0xfffffffe->OXM_OF_IN_PORT[])
37]])
db0b6c29 38AT_CHECK([ovs-ofctl -O OpenFlow12 parse-flows flows.txt], [0],
aa233d57 39[[usable protocols: any
db0b6c29 40chosen protocol: OXM-OpenFlow12
0e197060
BP
41OFPT_FLOW_MOD (OF1.2) (xid=0x1): ADD actions=learn(table=1,output:OXM_OF_IN_PORT[])
42OFPT_FLOW_MOD (OF1.2) (xid=0x2): ADD actions=learn(table=1,in_port=1,load:OXM_OF_IN_PORT[]->NXM_NX_REG1[],load:0xfffffffe->OXM_OF_IN_PORT[])
72333065
JR
43]])
44AT_CLEANUP
45
eddfcba7
BP
46AT_SETUP([learning action - examples])
47AT_DATA([flows.txt], [[
48# These are the examples from nicira-ext.h.
49actions=learn(in_port=99,NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[], load:NXM_OF_IN_PORT[]->NXM_NX_REG1[16..31])
50actions=learn(NXM_OF_VLAN_TCI[0..11], NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[],output:NXM_OF_IN_PORT[])
51table=0 actions=learn(table=1,hard_timeout=10, NXM_OF_VLAN_TCI[0..11],output:NXM_OF_IN_PORT[]), resubmit(,1)
52table=1 priority=0 actions=flood
53]])
54AT_CHECK([ovs-ofctl parse-flows flows.txt], [0],
aa233d57 55[[usable protocols: OXM,OpenFlow10+table_id,NXM+table_id,OpenFlow11
27527aa0
BP
56chosen protocol: OpenFlow10+table_id
57OFPT_FLOW_MOD (xid=0x1): ADD table:255 actions=learn(table=1,in_port=99,NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[],load:NXM_OF_IN_PORT[]->NXM_NX_REG1[16..31])
58OFPT_FLOW_MOD (xid=0x2): ADD table:255 actions=learn(table=1,NXM_OF_VLAN_TCI[0..11],NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[],output:NXM_OF_IN_PORT[])
59OFPT_FLOW_MOD (xid=0x3): ADD actions=learn(table=1,hard_timeout=10,NXM_OF_VLAN_TCI[0..11],output:NXM_OF_IN_PORT[]),resubmit(,1)
60OFPT_FLOW_MOD (xid=0x4): ADD table:1 priority=0 actions=FLOOD
eddfcba7
BP
61]])
62AT_CLEANUP
75a75043
BP
63
64AT_SETUP([learning action - satisfied prerequisites])
65AT_DATA([flows.txt],
66[[actions=learn(eth_type=0x800,load:5->NXM_OF_IP_DST[])
67ip,actions=learn(load:NXM_OF_IP_DST[]->NXM_NX_REG1[])
b5e5143b 68ip,actions=learn(eth_type=0x800,OXM_OF_IPV4_DST[])
75a75043
BP
69]])
70AT_CHECK([ovs-ofctl parse-flows flows.txt], [0],
aa233d57 71[[usable protocols: any
27527aa0 72chosen protocol: OpenFlow10-table_id
f25d0cf3 73OFPT_FLOW_MOD (xid=0x1): ADD actions=learn(table=1,eth_type=0x800,load:0x5->NXM_OF_IP_DST[])
75a75043
BP
74OFPT_FLOW_MOD (xid=0x2): ADD ip actions=learn(table=1,load:NXM_OF_IP_DST[]->NXM_NX_REG1[])
75OFPT_FLOW_MOD (xid=0x3): ADD ip actions=learn(table=1,eth_type=0x800,NXM_OF_IP_DST[])
76]])
77AT_CLEANUP
78
79AT_SETUP([learning action - invalid prerequisites])
80AT_CHECK([[ovs-ofctl parse-flow 'actions=learn(load:5->NXM_OF_IP_DST[])']],
dd43a558
SH
81 [1], [], [stderr])
82AT_CHECK([sed -e 's/.*|meta_flow|WARN|//' < stderr], [0],
83 [[destination field ip_dst lacks correct prerequisites
9e404d1e 84ovs-ofctl: actions are invalid with specified match (OFPBAC_MATCH_INCONSISTENT)
dd43a558 85]], [[]])
75a75043 86AT_CHECK([[ovs-ofctl parse-flow 'actions=learn(load:NXM_OF_IP_DST[]->NXM_NX_REG1[])']],
dd43a558
SH
87 [1], [], [stderr])
88AT_CHECK([sed -e 's/.*|meta_flow|WARN|//' < stderr], [0],
89 [[source field ip_dst lacks correct prerequisites
9e404d1e 90ovs-ofctl: actions are invalid with specified match (OFPBAC_MATCH_INCONSISTENT)
75a75043
BP
91]])
92AT_CLEANUP
93
6f17821e
BP
94AT_SETUP([learning action - too-long immediate value])
95dnl 129 bits is too long.
96AT_CHECK([[ovs-ofctl parse-flow 'actions=learn(load:0x1fedbca9876543210fedbca9876543210->NXM_NX_IPV6_DST[])']],
4531547f 97 [1], [], [[ovs-ofctl: 0x1fedbca9876543210fedbca9876543210->NXM_NX_IPV6_DST[]: value does not fit into 128 bits
6f17821e
BP
98]])
99
100dnl 128 bits is merely a bad prerequisite.
101AT_CHECK([[ovs-ofctl parse-flow 'actions=learn(load:0xfedbca9876543210fedbca9876543210->NXM_NX_IPV6_DST[])']], [1], [], [stderr])
102AT_CHECK([sed -e 's/.*|meta_flow|WARN|//' < stderr], [0],
103 [[destination field ipv6_dst lacks correct prerequisites
104ovs-ofctl: actions are invalid with specified match (OFPBAC_MATCH_INCONSISTENT)
105]], [[]])
106AT_CLEANUP
107
75a75043 108AT_SETUP([learning action - standard VLAN+MAC learning])
023e1e0a 109OVS_VSWITCHD_START(
e44768b7
JP
110 [add-port br0 p1 -- set Interface p1 type=dummy ofport_request=1 -- \
111 add-port br0 p2 -- set Interface p2 type=dummy ofport_request=2 -- \
112 add-port br0 p3 -- set Interface p3 type=dummy ofport_request=3])
75a75043
BP
113# Set up flow table for VLAN+MAC learning.
114AT_DATA([flows.txt], [[
115table=0 actions=learn(table=1, hard_timeout=60, NXM_OF_VLAN_TCI[0..11], NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[], output:NXM_OF_IN_PORT[]), resubmit(,1)
116table=1 priority=0 actions=flood
117]])
118AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
119
120# Trace an ARP packet arriving on port 3, to create a MAC learning entry.
e44768b7 121flow="in_port(3),eth(src=50:54:00:00:00:05,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)"
50aa28fd 122AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow" -generate], [0], [stdout])
e44768b7
JP
123actual=`tail -1 stdout | sed 's/Datapath actions: //'`
124
125expected="1,2,100"
126AT_CHECK([ovs-dpctl normalize-actions "$flow" "$expected"], [0], [stdout])
127mv stdout expout
128AT_CHECK([ovs-dpctl normalize-actions "$flow" "$actual"], [0], [expout])
75a75043
BP
129
130# Check for the MAC learning entry.
ef0ce8ae 131AT_CHECK([ovs-ofctl dump-flows br0 table=1 | ofctl_strip | sort], [0], [dnl
b9718b7b 132 table=1, hard_timeout=60, vlan_tci=0x0000/0x0fff,dl_dst=50:54:00:00:00:05 actions=output:3
ef0ce8ae 133 table=1, priority=0 actions=FLOOD
75a75043
BP
134NXST_FLOW reply:
135])
136
137# Trace a packet arrival destined for the learned MAC.
138# (This will also learn a MAC.)
50aa28fd 139AT_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),eth_type(0x0806),arp(sip=192.168.0.2,tip=192.168.0.1,op=2,sha=50:54:00:00:00:06,tha=50:54:00:00:00:05)' -generate], [0], [stdout])
75a75043
BP
140AT_CHECK([tail -1 stdout], [0], [Datapath actions: 3
141])
142
143# Check for both MAC learning entries.
ef0ce8ae 144AT_CHECK([ovs-ofctl dump-flows br0 table=1 | ofctl_strip |sort], [0], [dnl
b9718b7b
BP
145 table=1, hard_timeout=60, vlan_tci=0x0000/0x0fff,dl_dst=50:54:00:00:00:05 actions=output:3
146 table=1, hard_timeout=60, vlan_tci=0x0000/0x0fff,dl_dst=50:54:00:00:00:06 actions=output:1
ef0ce8ae 147 table=1, priority=0 actions=FLOOD
75a75043
BP
148NXST_FLOW reply:
149])
150
151# Trace a packet arrival that updates the first learned MAC entry.
e44768b7 152flow="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.1,tip=192.168.0.2,op=1,sha=50:54:00:00:00:05,tha=00:00:00:00:00:00)"
50aa28fd 153AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow" -generate], [0], [stdout])
e44768b7
JP
154actual=`tail -1 stdout | sed 's/Datapath actions: //'`
155
156expected="1,3,100"
157AT_CHECK([ovs-dpctl normalize-actions "$flow" "$expected"], [0], [stdout])
158mv stdout expout
159AT_CHECK([ovs-dpctl normalize-actions "$flow" "$actual"], [0], [expout])
75a75043
BP
160
161# Check that the MAC learning entry was updated.
ef0ce8ae 162AT_CHECK([ovs-ofctl dump-flows br0 table=1 | ofctl_strip | sort], [0], [dnl
b9718b7b
BP
163 table=1, hard_timeout=60, vlan_tci=0x0000/0x0fff,dl_dst=50:54:00:00:00:05 actions=output:2
164 table=1, hard_timeout=60, vlan_tci=0x0000/0x0fff,dl_dst=50:54:00:00:00:06 actions=output:1
ef0ce8ae 165 table=1, priority=0 actions=FLOOD
75a75043
BP
166NXST_FLOW reply:
167])
023e1e0a 168OVS_VSWITCHD_STOP
75a75043 169AT_CLEANUP
0e553d9c 170
644e2a7c
BP
171dnl This test checks that repeated uses of a "learn" action cause the
172dnl modified time of the learned flow to advance. Otherwise, the
173dnl learned flow will expire after its hard timeout even though it's
174dnl supposed to be refreshed. (The expiration can be hard to see since
175dnl it gets re-learned again the next time a packet appears, but
176dnl sometimes the expiration can cause temporary flooding etc.)
177AT_SETUP([learning action - learn refreshes hard_age])
178OVS_VSWITCHD_START(
179 [add-port br0 p1 -- set Interface p1 type=dummy ofport_request=1 -- \
180 add-port br0 p2 -- set Interface p2 type=dummy ofport_request=2 -- \
181 add-port br0 p3 -- set Interface p3 type=dummy ofport_request=3])
182
183ovs-appctl time/stop
184
185# Set up flow table for MAC learning.
186AT_DATA([flows.txt], [[
187table=0 actions=learn(table=1, hard_timeout=10, NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[], output:NXM_OF_IN_PORT[]), resubmit(,1)
188table=1 priority=0 actions=flood
189]])
190AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
191
192# Trace an ICMP packet arriving on port 3, to create a MAC learning entry.
193flow="in_port(3),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)"
50aa28fd 194AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow" -generate], [0], [stdout])
644e2a7c
BP
195actual=`tail -1 stdout | sed 's/Datapath actions: //'`
196
197expected="1,2,100"
198AT_CHECK([ovs-dpctl normalize-actions "$flow" "$expected"], [0], [stdout])
199mv stdout expout
200AT_CHECK([ovs-dpctl normalize-actions "$flow" "$actual"], [0], [expout])
201
202# Check that the MAC learning entry appeared.
203AT_CHECK([ovs-ofctl dump-flows br0 table=1 | ofctl_strip | sort], [0], [dnl
204 table=1, hard_timeout=10, dl_dst=50:54:00:00:00:07 actions=output:3
205 table=1, priority=0 actions=FLOOD
206NXST_FLOW reply:
207])
208
209# For 25 seconds, make sure that the MAC learning entry doesn't
210# disappear as long as we refresh it every second.
211for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25; do
212 ovs-appctl time/warp 1000
50aa28fd 213 AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow" -generate], [0], [stdout])
644e2a7c
BP
214
215 # Check that the entry is there.
216 AT_CHECK([ovs-ofctl dump-flows br0 table=1], [0], [stdout])
217 AT_CHECK([ofctl_strip < stdout | sort], [0], [dnl
218 table=1, hard_timeout=10, dl_dst=50:54:00:00:00:07 actions=output:3
219 table=1, priority=0 actions=FLOOD
220NXST_FLOW reply:
221])
222
223 if test $i != 1; then
224 # Check that hard_age has appeared. We need to do this separately
225 # from the above check because ofctl_strip removes it. dump-flows
226 # only prints hard_age when it is different from the flow's duration
227 # (that is, the number of seconds from the time it was created),
228 # so we only check for it after we've refreshed the flow once.
229 AT_CHECK([grep dl_dst=50:54:00:00:00:07 stdout | grep -c hard_age],
230 [0], [1
231])
232 fi
233done
234
235# Make sure that 15 seconds without refreshing makes the flow time out.
bdba1947 236ovs-appctl time/warp 15000 5000
1ddccd4e
YT
237sleep 1
238AT_CHECK([ovs-ofctl dump-flows br0 table=1 | ofctl_strip | sort], [0], [dnl
644e2a7c
BP
239 table=1, priority=0 actions=FLOOD
240NXST_FLOW reply:
241])
242OVS_VSWITCHD_STOP
243AT_CLEANUP
244
337b9cec
BP
245AT_SETUP([learning action - TCPv4 port learning])
246OVS_VSWITCHD_START(
e44768b7
JP
247 [add-port br0 p1 -- set Interface p1 type=dummy -- \
248 add-port br0 p2 -- set Interface p2 type=dummy -- \
249 add-port br0 p3 -- set Interface p3 type=dummy])
337b9cec
BP
250# Set up flow table for TCPv4 port learning.
251AT_CHECK([[ovs-ofctl add-flow br0 'table=0 tcp actions=learn(table=1, hard_timeout=60, eth_type=0x800, nw_proto=6, NXM_OF_IP_SRC[]=NXM_OF_IP_DST[], NXM_OF_IP_DST[]=NXM_OF_IP_SRC[], NXM_OF_TCP_SRC[]=NXM_OF_TCP_DST[], NXM_OF_TCP_DST[]=NXM_OF_TCP_SRC[]), flood']])
252
253# Trace a TCPv4 packet arriving on port 3.
e44768b7 254flow="in_port(3),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:06),eth_type(0x0800),ipv4(src=192.168.0.2,dst=192.168.0.1,proto=6,tos=0,ttl=64,frag=no),tcp(src=40000,dst=80)"
50aa28fd 255AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow" -generate], [0], [stdout])
e44768b7
JP
256actual=`tail -1 stdout | sed 's/Datapath actions: //'`
257
258expected="1,2,100"
259AT_CHECK([ovs-dpctl normalize-actions "$flow" "$expected"], [0], [stdout])
260mv stdout expout
261AT_CHECK([ovs-dpctl normalize-actions "$flow" "$actual"], [0], [expout])
337b9cec
BP
262
263# Check for the learning entry.
264AT_CHECK([ovs-ofctl dump-flows br0 table=1 | ofctl_strip | sort], [0], [dnl
b9718b7b 265 table=1, hard_timeout=60, tcp,nw_src=192.168.0.1,nw_dst=192.168.0.2,tp_src=80,tp_dst=40000 actions=drop
337b9cec
BP
266NXST_FLOW reply:
267])
268OVS_VSWITCHD_STOP
269AT_CLEANUP
270
271AT_SETUP([learning action - TCPv6 port learning])
272OVS_VSWITCHD_START(
e44768b7
JP
273 [add-port br0 p1 -- set Interface p1 type=dummy -- \
274 add-port br0 p2 -- set Interface p2 type=dummy -- \
275 add-port br0 p3 -- set Interface p3 type=dummy])
337b9cec 276# Set up flow table for TCPv6 port learning.
3d792b70
BP
277# Also add a 128-bit-wide "load" action and a 128-bit literal match to check
278# that they work.
279AT_CHECK([[ovs-ofctl add-flow br0 'table=0 tcp6 actions=learn(table=1, hard_timeout=60, eth_type=0x86dd, nw_proto=6, NXM_NX_IPV6_SRC[]=NXM_NX_IPV6_DST[], ipv6_dst=2001:0db8:85a3:0000:0000:8a2e:0370:7334, NXM_OF_TCP_SRC[]=NXM_OF_TCP_DST[], NXM_OF_TCP_DST[]=NXM_OF_TCP_SRC[], load(0x20010db885a308d313198a2e03707348->NXM_NX_IPV6_DST[])), flood']])
337b9cec
BP
280
281# Trace a TCPv6 packet arriving on port 3.
e44768b7 282flow="in_port(3),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:06),eth_type(0x86dd),ipv6(src=fec0::2,dst=fec0::1,label=0,proto=6,tclass=0,hlimit=255,frag=no),tcp(src=40000,dst=80)"
50aa28fd 283AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow" -generate], [0], [stdout])
e44768b7
JP
284actual=`tail -1 stdout | sed 's/Datapath actions: //'`
285
286expected="1,2,100"
287AT_CHECK([ovs-dpctl normalize-actions "$flow" "$expected"], [0], [stdout])
288mv stdout expout
289AT_CHECK([ovs-dpctl normalize-actions "$flow" "$actual"], [0], [expout])
337b9cec
BP
290
291# Check for the learning entry.
3d792b70 292AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
b9718b7b 293 table=1, hard_timeout=60, tcp6,ipv6_src=fec0::1,ipv6_dst=2001:db8:85a3::8a2e:370:7334,tp_src=80,tp_dst=40000 actions=load:0x13198a2e03707348->NXM_NX_IPV6_DST[[0..63]],load:0x20010db885a308d3->NXM_NX_IPV6_DST[[64..127]]
3d792b70 294 tcp6 actions=learn(table=1,hard_timeout=60,eth_type=0x86dd,nw_proto=6,NXM_NX_IPV6_SRC[[]]=NXM_NX_IPV6_DST[[]],ipv6_dst=2001:db8:85a3::8a2e:370:7334,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],NXM_OF_TCP_DST[[]]=NXM_OF_TCP_SRC[[]],load:0x20010db885a308d313198a2e03707348->NXM_NX_IPV6_DST[[]]),FLOOD
337b9cec
BP
295NXST_FLOW reply:
296])
297OVS_VSWITCHD_STOP
298AT_CLEANUP
299
7cf2e080
BP
300# In this use of a learn action, the first packet in the flow creates
301# a new flow that changes the behavior of subsequent packets in the
302# flow.
303AT_SETUP([learning action - self-modifying flow])
304OVS_VSWITCHD_START
ca5792f0 305add_of_ports br0 1 2 3
7cf2e080 306
31ef9f51 307ovs-appctl time/stop
7cf2e080
BP
308# Set up flow table for TCPv4 port learning.
309AT_CHECK([[ovs-ofctl add-flow br0 'actions=load:3->NXM_NX_REG0[0..15],learn(table=0,priority=65535,NXM_OF_ETH_SRC[],NXM_OF_VLAN_TCI[0..11],output:NXM_NX_REG0[0..15]),output:2']])
310
311# Trace some packets arriving. The particular packets don't matter.
312for i in 1 2 3 4 5 6 7 8 9 10; do
313 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)'
b0ed42c8 314 ovs-appctl time/warp 10
15155807
YT
315 if [[ $i -eq 1 ]]; then
316 sleep 1
317 fi
7cf2e080
BP
318done
319
320# Check for the learning entry.
b0ed42c8 321ovs-appctl time/warp 1000
7cf2e080
BP
322AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0],
323[[ n_packets=1, n_bytes=60, actions=load:0x3->NXM_NX_REG0[0..15],learn(table=0,priority=65535,NXM_OF_ETH_SRC[],NXM_OF_VLAN_TCI[0..11],output:NXM_NX_REG0[0..15]),output:2
b0ed42c8 324 n_packets=9, n_bytes=540, priority=65535,vlan_tci=0x0000/0x0fff,dl_src=50:54:00:00:00:05 actions=output:3
7cf2e080
BP
325NXST_FLOW reply:
326]])
327
328# Check that the first packet went out port 2 and the rest out port 3.
329AT_CHECK(
8a32aaa5 330 [(ovs-ofctl dump-ports br0 2; ovs-ofctl dump-ports br0 3) | strip_xids], [0],
7cf2e080
BP
331 [OFPST_PORT reply: 1 ports
332 port 2: rx pkts=0, bytes=0, drop=0, errs=0, frame=0, over=0, crc=0
333 tx pkts=1, bytes=60, drop=0, errs=0, coll=0
334OFPST_PORT reply: 1 ports
335 port 3: rx pkts=0, bytes=0, drop=0, errs=0, frame=0, over=0, crc=0
336 tx pkts=9, bytes=540, drop=0, errs=0, coll=0
337])
619d5f98
JS
338
339OVS_VSWITCHD_STOP
340AT_CLEANUP
341
342# This test is much like the previous, but adds idle timeouts and sends
343# two different flows to the bridge. This tests that the statistics are
344# attributed correctly.
345AT_SETUP([learning action - self-modifying flow with idle_timeout])
346OVS_VSWITCHD_START
ca5792f0 347add_of_ports br0 1 2 3
619d5f98
JS
348
349ovs-appctl time/stop
350# Set up flow table for TCPv4 port learning.
351AT_CHECK([[ovs-ofctl add-flow br0 'actions=load:3->NXM_NX_REG0[0..15],learn(table=0,idle_timeout=5,priority=65535,NXM_OF_ETH_SRC[],NXM_OF_VLAN_TCI[0..11],output:NXM_NX_REG0[0..15]),output:2']])
352
353# Trace some packets arriving. The particular packets don't matter.
354for i in `seq 1 10`; do
355 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)'
356 ovs-appctl time/warp 10
357 if [[ $i -eq 1 ]]; then
358 sleep 1
359 fi
360done
361
362# Trace some packets arriving. This is is a different flow from the previous.
363# Note that we advance time by 1 second between each packet here.
364for i in `seq 1 10`; do
365 ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:06,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)'
366 ovs-appctl time/warp 1000
7f12bdcc
YT
367 # Note: netdev-dummy/receive merely queues the packet.
368 # We need to wait for other thread to process the packet
369 # and update the flow's 'used' for the packet.
370 # (i % 3 == 0) below is somehow arbitrary but chosen to ensure
371 # that we update the flow's 'used' frequently enough to prevent
372 # idle_timeout.
3ef64336 373 if [[ $i -eq 1 -o $((i % 3)) -eq 0 ]]; then
619d5f98
JS
374 sleep 1
375 fi
376done
377
4b10fd11
YT
378# Check that the first packet of each flow went out port 2 and the rest out
379# port 3.
619d5f98 380AT_CHECK(
8a32aaa5 381 [(ovs-ofctl dump-ports br0 2; ovs-ofctl dump-ports br0 3) | strip_xids], [0],
619d5f98
JS
382 [OFPST_PORT reply: 1 ports
383 port 2: rx pkts=0, bytes=0, drop=0, errs=0, frame=0, over=0, crc=0
384 tx pkts=2, bytes=120, drop=0, errs=0, coll=0
385OFPST_PORT reply: 1 ports
386 port 3: rx pkts=0, bytes=0, drop=0, errs=0, frame=0, over=0, crc=0
387 tx pkts=18, bytes=1080, drop=0, errs=0, coll=0
388])
389
390# Check for the learning entry.
391ovs-appctl time/warp 1000
392AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0],
393[[ n_packets=2, n_bytes=120, actions=load:0x3->NXM_NX_REG0[0..15],learn(table=0,idle_timeout=5,priority=65535,NXM_OF_ETH_SRC[],NXM_OF_VLAN_TCI[0..11],output:NXM_NX_REG0[0..15]),output:2
394 n_packets=9, n_bytes=540, idle_timeout=5, priority=65535,vlan_tci=0x0000/0x0fff,dl_src=50:54:00:00:00:06 actions=output:3
395NXST_FLOW reply:
396]])
397OVS_VSWITCHD_STOP
398AT_CLEANUP
399
bd2f109b 400# This test is much like the previous, but adds hard timeouts and sends
619d5f98
JS
401# two different flows to the bridge. This tests that the statistics are
402# attributed correctly.
403AT_SETUP([learning action - self-modifying flow with hard_timeout])
404OVS_VSWITCHD_START
ca5792f0 405add_of_ports br0 1 2 3
619d5f98
JS
406
407ovs-appctl time/stop
408# Set up flow table for TCPv4 port learning.
c2dc87c9 409AT_CHECK([[ovs-ofctl add-flow br0 'actions=load:3->NXM_NX_REG0[0..15],learn(table=0,hard_timeout=10,priority=65535,NXM_OF_ETH_SRC[],NXM_OF_VLAN_TCI[0..11],output:NXM_NX_REG0[0..15]),output:2']])
619d5f98
JS
410
411# Trace some packets arriving. The particular packets don't matter.
412for i in `seq 1 10`; do
413 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)'
619d5f98
JS
414 if [[ $i -eq 1 ]]; then
415 sleep 1
416 fi
c2dc87c9 417 ovs-appctl time/warp 10
619d5f98
JS
418done
419
420# Trace some packets arriving. This is is a different flow from the previous.
c2dc87c9 421# Note that we advance time by 2 second between each packet here.
619d5f98
JS
422for i in `seq 1 10`; do
423 ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:06,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)'
c2dc87c9
YT
424 # Note: hard_timeout should fire immediately after #6 packet.
425 # #7 packet re-install the flow and the following 3 packets
426 # (#8, #9, #10) use the flow.
427 # it's difficult to predict the exact timing of rule expiry
428 # because it's affected by flow dumper thread via udpif_dump_seq.
429 # hard_timeout value for this test was chosen to overcome the uncertainty.
dd7ec292
YT
430 #
431 # receive #1 learn, install flow with hard_timeout=10
432 # sleep to ensure the flow installation
433 # (warp, timeout left 8s)
434 # receive #2 the learned flow
435 # (warp, timeout left 6s)
436 # receive #3
437 # (warp, timeout left 4s)
438 # receive #4
439 # (warp, timeout left 2s)
440 # receive #5
441 # (warp, timeout left 0s)
442 # NOTE: OVS does not consider this expired yet. cf. rule_expire()
443 # receive #6
444 # (warp, timeout left -2s)
445 # sleep to ensure flow expiration
446 # receive #7 learn, install flow with hard_timeout=10
447 # sleep to ensure the flow installation
448 # (warp, timeout left 8s)
449 # receive #8
450 # (warp, timeout left 6s)
451 # receive #9
452 # (warp, timeout left 4s)
453 # receive #10
454 # (warp, timeout left 2s)
455 if [[ $i -eq 1 -o $i -eq 7 ]]; then
619d5f98
JS
456 sleep 1
457 fi
c2dc87c9 458 ovs-appctl time/warp 2000
dd7ec292
YT
459 if [[ $i -eq 6 ]]; then
460 sleep 1
461 fi
619d5f98
JS
462done
463
4b10fd11
YT
464# Check that the first packet of each flow went out port 2 and the rest out
465# port 3.
619d5f98 466AT_CHECK(
8a32aaa5 467 [(ovs-ofctl dump-ports br0 2; ovs-ofctl dump-ports br0 3) | strip_xids], [0],
619d5f98
JS
468 [OFPST_PORT reply: 1 ports
469 port 2: rx pkts=0, bytes=0, drop=0, errs=0, frame=0, over=0, crc=0
470 tx pkts=3, bytes=180, drop=0, errs=0, coll=0
471OFPST_PORT reply: 1 ports
472 port 3: rx pkts=0, bytes=0, drop=0, errs=0, frame=0, over=0, crc=0
473 tx pkts=17, bytes=1020, drop=0, errs=0, coll=0
474])
475
476# Check for the learning entry.
477ovs-appctl time/warp 1000
c2dc87c9 478sleep 1
619d5f98 479AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0],
c2dc87c9
YT
480[[ n_packets=3, n_bytes=180, actions=load:0x3->NXM_NX_REG0[0..15],learn(table=0,hard_timeout=10,priority=65535,NXM_OF_ETH_SRC[],NXM_OF_VLAN_TCI[0..11],output:NXM_NX_REG0[0..15]),output:2
481 n_packets=3, n_bytes=180, hard_timeout=10, priority=65535,vlan_tci=0x0000/0x0fff,dl_src=50:54:00:00:00:06 actions=output:3
619d5f98
JS
482NXST_FLOW reply:
483]])
7cf2e080
BP
484OVS_VSWITCHD_STOP
485AT_CLEANUP
486
0e553d9c
BP
487AT_SETUP([learning action - fin_timeout feature])
488# This is a totally artificial use of the "learn" action. The only purpose
489# is to check that specifying fin_idle_timeout or fin_hard_timeout causes
490# a corresponding fin_timeout action to end up in the learned flows.
e1b1d06a
JP
491OVS_VSWITCHD_START(
492 [add-port br0 p1 -- set Interface p1 type=dummy ofport_request=1])
0e553d9c 493AT_CHECK([[ovs-ofctl add-flow br0 'actions=learn(fin_hard_timeout=10, fin_idle_timeout=5, NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[], output:NXM_OF_IN_PORT[])']])
50aa28fd 494AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=50:54:00:00:00:05,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)' -generate], [0], [ignore])
0e553d9c
BP
495AT_CHECK([ovs-ofctl dump-flows br0 table=1 | ofctl_strip], [0],
496[NXST_FLOW reply:
497 table=1, dl_dst=50:54:00:00:00:05 actions=fin_timeout(idle_timeout=5,hard_timeout=10),output:1
498])
499OVS_VSWITCHD_STOP
500AT_CLEANUP
35f48b8b
BP
501
502AT_SETUP([learning action - delete_learned feature])
503OVS_VSWITCHD_START
504
505# Add some initial flows and check that it was successful.
506AT_DATA([flows.txt], [dnl
507 reg0=0x1 actions=learn(delete_learned,cookie=0x123)
508 reg0=0x2 actions=learn(delete_learned,cookie=0x123)
509cookie=0x123, table=1, reg0=0x3 actions=drop
510cookie=0x123, table=1, reg0=0x4 actions=drop
511cookie=0x123, table=2, reg0=0x5 actions=drop
512cookie=0x234, table=1, reg0=0x6 actions=drop
513])
514AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
515AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
516 cookie=0x123, table=1, reg0=0x3 actions=drop
517 cookie=0x123, table=1, reg0=0x4 actions=drop
518 cookie=0x123, table=2, reg0=0x5 actions=drop
519 cookie=0x234, table=1, reg0=0x6 actions=drop
520 reg0=0x1 actions=learn(table=1,delete_learned,cookie=0x123)
521 reg0=0x2 actions=learn(table=1,delete_learned,cookie=0x123)
522NXST_FLOW reply:
523])
524
525# Delete one of the learn actions. The learned flows should stay, since there
526# is another learn action with the identical target.
527AT_CHECK([ovs-ofctl del-flows br0 'table=0 reg0=1'])
528AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
529 cookie=0x123, table=1, reg0=0x3 actions=drop
530 cookie=0x123, table=1, reg0=0x4 actions=drop
531 cookie=0x123, table=2, reg0=0x5 actions=drop
532 cookie=0x234, table=1, reg0=0x6 actions=drop
533 reg0=0x2 actions=learn(table=1,delete_learned,cookie=0x123)
534NXST_FLOW reply:
535])
536
537# Change the flow with the learn action by adding a second action. The learned
538# flows should stay because the learn action is still there.
539AT_CHECK([ovs-ofctl mod-flows br0 'table=0 reg0=2 actions=output:1,learn(delete_learned,cookie=0x123)'])
540AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
541 cookie=0x123, table=1, reg0=0x3 actions=drop
542 cookie=0x123, table=1, reg0=0x4 actions=drop
543 cookie=0x123, table=2, reg0=0x5 actions=drop
544 cookie=0x234, table=1, reg0=0x6 actions=drop
545 reg0=0x2 actions=output:1,learn(table=1,delete_learned,cookie=0x123)
546NXST_FLOW reply:
547])
548
549# Change the flow with the learn action by replacing its learn action by one
550# with a different target. The (previous) learned flows disappear.
551AT_CHECK([ovs-ofctl mod-flows br0 'table=0 reg0=2 actions=learn(delete_learned,cookie=0x234)'])
552AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
553 cookie=0x123, table=2, reg0=0x5 actions=drop
554 cookie=0x234, table=1, reg0=0x6 actions=drop
555 reg0=0x2 actions=learn(table=1,delete_learned,cookie=0x234)
556NXST_FLOW reply:
557])
558
559# Use add-flow to replace the flow with the learn action by one with the
560# same learn action and an extra action. The (new) learned flow remains.
561AT_CHECK([ovs-ofctl add-flow br0 'table=0 reg0=2 actions=learn(delete_learned,cookie=0x234),output:2'])
562AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
563 cookie=0x123, table=2, reg0=0x5 actions=drop
564 cookie=0x234, table=1, reg0=0x6 actions=drop
565 reg0=0x2 actions=learn(table=1,delete_learned,cookie=0x234),output:2
566NXST_FLOW reply:
567])
568
569# Delete the flow with the learn action. The learned flow disappears too.
570AT_CHECK([ovs-ofctl del-flows br0 table=0])
571AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
572 cookie=0x123, table=2, reg0=0x5 actions=drop
573NXST_FLOW reply:
574])
575
576# Add a new set of flows to check on a corner case: the learned flows
577# contain their own learn actions which cascade to further deletions.
578# This can't happen if the learned flows were actually created by a
579# learn action, since the learn action has very restricted action
580# support, but there's no restriction that the deleted flows were
581# created by a learn action.
582AT_DATA([flows.txt], [dnl
583 reg0=0x1 actions=learn(table=1,delete_learned,cookie=0x123)
584 reg0=0x2 actions=learn(table=2,delete_learned,cookie=0x234)
585cookie=0x123, table=1, reg0=0x3 actions=learn(table=3,delete_learned,cookie=0x345)
586cookie=0x234, table=2, reg0=0x3 actions=learn(table=4,delete_learned,cookie=0x456)
587cookie=0x345, table=3, reg0=0x4 actions=learn(table=5,delete_learned,cookie=0x567)
588cookie=0x456, table=4, reg0=0x5 actions=learn(table=5,delete_learned,cookie=0x567)
589cookie=0x567, table=5, reg0=0x6 actions=drop
590cookie=0x567, table=5, reg0=0x7 actions=drop
591cookie=0x567, table=5, reg0=0x8 actions=drop
592])
593AT_CHECK([ovs-ofctl del-flows br0])
594AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
595AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
596 cookie=0x123, table=1, reg0=0x3 actions=learn(table=3,delete_learned,cookie=0x345)
597 cookie=0x234, table=2, reg0=0x3 actions=learn(table=4,delete_learned,cookie=0x456)
598 cookie=0x345, table=3, reg0=0x4 actions=learn(table=5,delete_learned,cookie=0x567)
599 cookie=0x456, table=4, reg0=0x5 actions=learn(table=5,delete_learned,cookie=0x567)
600 cookie=0x567, table=5, reg0=0x6 actions=drop
601 cookie=0x567, table=5, reg0=0x7 actions=drop
602 cookie=0x567, table=5, reg0=0x8 actions=drop
603 reg0=0x1 actions=learn(table=1,delete_learned,cookie=0x123)
604 reg0=0x2 actions=learn(table=2,delete_learned,cookie=0x234)
605NXST_FLOW reply:
606])
607
608# Deleting the flow with reg0=1 should cascade to delete a few levels
609# of learned flows, but the ones with cookie=0x567 stick around
610# because of the flow with cookie=0x456.
611AT_CHECK([ovs-ofctl del-flows br0 'table=0 reg0=1'])
612AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
613 cookie=0x234, table=2, reg0=0x3 actions=learn(table=4,delete_learned,cookie=0x456)
614 cookie=0x456, table=4, reg0=0x5 actions=learn(table=5,delete_learned,cookie=0x567)
615 cookie=0x567, table=5, reg0=0x6 actions=drop
616 cookie=0x567, table=5, reg0=0x7 actions=drop
617 cookie=0x567, table=5, reg0=0x8 actions=drop
618 reg0=0x2 actions=learn(table=2,delete_learned,cookie=0x234)
619NXST_FLOW reply:
620])
621
622# Deleting the flow with reg0=2 should cascade to delete all the rest:
623AT_CHECK([ovs-ofctl del-flows br0 'table=0 reg0=2'])
624AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
625NXST_FLOW reply:
626])
627OVS_VSWITCHD_STOP
628AT_CLEANUP