]> git.proxmox.com Git - mirror_ovs.git/blame - tests/learn.at
ofp-actions: Only set defined bits when encoding "load" actions.
[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
94AT_SETUP([learning action - standard VLAN+MAC learning])
023e1e0a 95OVS_VSWITCHD_START(
e44768b7
JP
96 [add-port br0 p1 -- set Interface p1 type=dummy ofport_request=1 -- \
97 add-port br0 p2 -- set Interface p2 type=dummy ofport_request=2 -- \
98 add-port br0 p3 -- set Interface p3 type=dummy ofport_request=3])
75a75043
BP
99# Set up flow table for VLAN+MAC learning.
100AT_DATA([flows.txt], [[
101table=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)
102table=1 priority=0 actions=flood
103]])
104AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
105
106# Trace an ARP packet arriving on port 3, to create a MAC learning entry.
e44768b7 107flow="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 108AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow" -generate], [0], [stdout])
e44768b7
JP
109actual=`tail -1 stdout | sed 's/Datapath actions: //'`
110
111expected="1,2,100"
112AT_CHECK([ovs-dpctl normalize-actions "$flow" "$expected"], [0], [stdout])
113mv stdout expout
114AT_CHECK([ovs-dpctl normalize-actions "$flow" "$actual"], [0], [expout])
75a75043
BP
115
116# Check for the MAC learning entry.
ef0ce8ae 117AT_CHECK([ovs-ofctl dump-flows br0 table=1 | ofctl_strip | sort], [0], [dnl
b9718b7b 118 table=1, hard_timeout=60, vlan_tci=0x0000/0x0fff,dl_dst=50:54:00:00:00:05 actions=output:3
ef0ce8ae 119 table=1, priority=0 actions=FLOOD
75a75043
BP
120NXST_FLOW reply:
121])
122
123# Trace a packet arrival destined for the learned MAC.
124# (This will also learn a MAC.)
50aa28fd 125AT_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
126AT_CHECK([tail -1 stdout], [0], [Datapath actions: 3
127])
128
129# Check for both MAC learning entries.
ef0ce8ae 130AT_CHECK([ovs-ofctl dump-flows br0 table=1 | ofctl_strip |sort], [0], [dnl
b9718b7b
BP
131 table=1, hard_timeout=60, vlan_tci=0x0000/0x0fff,dl_dst=50:54:00:00:00:05 actions=output:3
132 table=1, hard_timeout=60, vlan_tci=0x0000/0x0fff,dl_dst=50:54:00:00:00:06 actions=output:1
ef0ce8ae 133 table=1, priority=0 actions=FLOOD
75a75043
BP
134NXST_FLOW reply:
135])
136
137# Trace a packet arrival that updates the first learned MAC entry.
e44768b7 138flow="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 139AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow" -generate], [0], [stdout])
e44768b7
JP
140actual=`tail -1 stdout | sed 's/Datapath actions: //'`
141
142expected="1,3,100"
143AT_CHECK([ovs-dpctl normalize-actions "$flow" "$expected"], [0], [stdout])
144mv stdout expout
145AT_CHECK([ovs-dpctl normalize-actions "$flow" "$actual"], [0], [expout])
75a75043
BP
146
147# Check that the MAC learning entry was updated.
ef0ce8ae 148AT_CHECK([ovs-ofctl dump-flows br0 table=1 | ofctl_strip | sort], [0], [dnl
b9718b7b
BP
149 table=1, hard_timeout=60, vlan_tci=0x0000/0x0fff,dl_dst=50:54:00:00:00:05 actions=output:2
150 table=1, hard_timeout=60, vlan_tci=0x0000/0x0fff,dl_dst=50:54:00:00:00:06 actions=output:1
ef0ce8ae 151 table=1, priority=0 actions=FLOOD
75a75043
BP
152NXST_FLOW reply:
153])
023e1e0a 154OVS_VSWITCHD_STOP
75a75043 155AT_CLEANUP
0e553d9c 156
644e2a7c
BP
157dnl This test checks that repeated uses of a "learn" action cause the
158dnl modified time of the learned flow to advance. Otherwise, the
159dnl learned flow will expire after its hard timeout even though it's
160dnl supposed to be refreshed. (The expiration can be hard to see since
161dnl it gets re-learned again the next time a packet appears, but
162dnl sometimes the expiration can cause temporary flooding etc.)
163AT_SETUP([learning action - learn refreshes hard_age])
164OVS_VSWITCHD_START(
165 [add-port br0 p1 -- set Interface p1 type=dummy ofport_request=1 -- \
166 add-port br0 p2 -- set Interface p2 type=dummy ofport_request=2 -- \
167 add-port br0 p3 -- set Interface p3 type=dummy ofport_request=3])
168
169ovs-appctl time/stop
170
171# Set up flow table for MAC learning.
172AT_DATA([flows.txt], [[
173table=0 actions=learn(table=1, hard_timeout=10, NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[], output:NXM_OF_IN_PORT[]), resubmit(,1)
174table=1 priority=0 actions=flood
175]])
176AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
177
178# Trace an ICMP packet arriving on port 3, to create a MAC learning entry.
179flow="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 180AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow" -generate], [0], [stdout])
644e2a7c
BP
181actual=`tail -1 stdout | sed 's/Datapath actions: //'`
182
183expected="1,2,100"
184AT_CHECK([ovs-dpctl normalize-actions "$flow" "$expected"], [0], [stdout])
185mv stdout expout
186AT_CHECK([ovs-dpctl normalize-actions "$flow" "$actual"], [0], [expout])
187
188# Check that the MAC learning entry appeared.
189AT_CHECK([ovs-ofctl dump-flows br0 table=1 | ofctl_strip | sort], [0], [dnl
190 table=1, hard_timeout=10, dl_dst=50:54:00:00:00:07 actions=output:3
191 table=1, priority=0 actions=FLOOD
192NXST_FLOW reply:
193])
194
195# For 25 seconds, make sure that the MAC learning entry doesn't
196# disappear as long as we refresh it every second.
197for 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
198 ovs-appctl time/warp 1000
50aa28fd 199 AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow" -generate], [0], [stdout])
644e2a7c
BP
200
201 # Check that the entry is there.
202 AT_CHECK([ovs-ofctl dump-flows br0 table=1], [0], [stdout])
203 AT_CHECK([ofctl_strip < stdout | 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 if test $i != 1; then
210 # Check that hard_age has appeared. We need to do this separately
211 # from the above check because ofctl_strip removes it. dump-flows
212 # only prints hard_age when it is different from the flow's duration
213 # (that is, the number of seconds from the time it was created),
214 # so we only check for it after we've refreshed the flow once.
215 AT_CHECK([grep dl_dst=50:54:00:00:00:07 stdout | grep -c hard_age],
216 [0], [1
217])
218 fi
219done
220
221# Make sure that 15 seconds without refreshing makes the flow time out.
bdba1947 222ovs-appctl time/warp 15000 5000
1ddccd4e
YT
223sleep 1
224AT_CHECK([ovs-ofctl dump-flows br0 table=1 | ofctl_strip | sort], [0], [dnl
644e2a7c
BP
225 table=1, priority=0 actions=FLOOD
226NXST_FLOW reply:
227])
228OVS_VSWITCHD_STOP
229AT_CLEANUP
230
337b9cec
BP
231AT_SETUP([learning action - TCPv4 port learning])
232OVS_VSWITCHD_START(
e44768b7
JP
233 [add-port br0 p1 -- set Interface p1 type=dummy -- \
234 add-port br0 p2 -- set Interface p2 type=dummy -- \
235 add-port br0 p3 -- set Interface p3 type=dummy])
337b9cec
BP
236# Set up flow table for TCPv4 port learning.
237AT_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']])
238
239# Trace a TCPv4 packet arriving on port 3.
e44768b7 240flow="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 241AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow" -generate], [0], [stdout])
e44768b7
JP
242actual=`tail -1 stdout | sed 's/Datapath actions: //'`
243
244expected="1,2,100"
245AT_CHECK([ovs-dpctl normalize-actions "$flow" "$expected"], [0], [stdout])
246mv stdout expout
247AT_CHECK([ovs-dpctl normalize-actions "$flow" "$actual"], [0], [expout])
337b9cec
BP
248
249# Check for the learning entry.
250AT_CHECK([ovs-ofctl dump-flows br0 table=1 | ofctl_strip | sort], [0], [dnl
b9718b7b 251 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
252NXST_FLOW reply:
253])
254OVS_VSWITCHD_STOP
255AT_CLEANUP
256
257AT_SETUP([learning action - TCPv6 port learning])
258OVS_VSWITCHD_START(
e44768b7
JP
259 [add-port br0 p1 -- set Interface p1 type=dummy -- \
260 add-port br0 p2 -- set Interface p2 type=dummy -- \
261 add-port br0 p3 -- set Interface p3 type=dummy])
337b9cec 262# Set up flow table for TCPv6 port learning.
3d792b70
BP
263# Also add a 128-bit-wide "load" action and a 128-bit literal match to check
264# that they work.
265AT_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
266
267# Trace a TCPv6 packet arriving on port 3.
e44768b7 268flow="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 269AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow" -generate], [0], [stdout])
e44768b7
JP
270actual=`tail -1 stdout | sed 's/Datapath actions: //'`
271
272expected="1,2,100"
273AT_CHECK([ovs-dpctl normalize-actions "$flow" "$expected"], [0], [stdout])
274mv stdout expout
275AT_CHECK([ovs-dpctl normalize-actions "$flow" "$actual"], [0], [expout])
337b9cec
BP
276
277# Check for the learning entry.
3d792b70 278AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
b9718b7b 279 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 280 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
281NXST_FLOW reply:
282])
283OVS_VSWITCHD_STOP
284AT_CLEANUP
285
7cf2e080
BP
286# In this use of a learn action, the first packet in the flow creates
287# a new flow that changes the behavior of subsequent packets in the
288# flow.
289AT_SETUP([learning action - self-modifying flow])
290OVS_VSWITCHD_START
291ADD_OF_PORTS([br0], 1, 2, 3)
292
31ef9f51 293ovs-appctl time/stop
7cf2e080
BP
294# Set up flow table for TCPv4 port learning.
295AT_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']])
296
297# Trace some packets arriving. The particular packets don't matter.
298for i in 1 2 3 4 5 6 7 8 9 10; do
299 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 300 ovs-appctl time/warp 10
15155807
YT
301 if [[ $i -eq 1 ]]; then
302 sleep 1
303 fi
7cf2e080
BP
304done
305
306# Check for the learning entry.
b0ed42c8 307ovs-appctl time/warp 1000
7cf2e080
BP
308AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0],
309[[ 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 310 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
311NXST_FLOW reply:
312]])
313
314# Check that the first packet went out port 2 and the rest out port 3.
315AT_CHECK(
316 [(ovs-ofctl dump-ports br0 2; ovs-ofctl dump-ports br0 3) | STRIP_XIDS], [0],
317 [OFPST_PORT reply: 1 ports
318 port 2: rx pkts=0, bytes=0, drop=0, errs=0, frame=0, over=0, crc=0
319 tx pkts=1, bytes=60, drop=0, errs=0, coll=0
320OFPST_PORT reply: 1 ports
321 port 3: rx pkts=0, bytes=0, drop=0, errs=0, frame=0, over=0, crc=0
322 tx pkts=9, bytes=540, drop=0, errs=0, coll=0
323])
619d5f98
JS
324
325OVS_VSWITCHD_STOP
326AT_CLEANUP
327
328# This test is much like the previous, but adds idle timeouts and sends
329# two different flows to the bridge. This tests that the statistics are
330# attributed correctly.
331AT_SETUP([learning action - self-modifying flow with idle_timeout])
332OVS_VSWITCHD_START
333ADD_OF_PORTS([br0], 1, 2, 3)
334
335ovs-appctl time/stop
336# Set up flow table for TCPv4 port learning.
337AT_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']])
338
339# Trace some packets arriving. The particular packets don't matter.
340for i in `seq 1 10`; do
341 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)'
342 ovs-appctl time/warp 10
343 if [[ $i -eq 1 ]]; then
344 sleep 1
345 fi
346done
347
348# Trace some packets arriving. This is is a different flow from the previous.
349# Note that we advance time by 1 second between each packet here.
350for i in `seq 1 10`; do
351 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)'
352 ovs-appctl time/warp 1000
7f12bdcc
YT
353 # Note: netdev-dummy/receive merely queues the packet.
354 # We need to wait for other thread to process the packet
355 # and update the flow's 'used' for the packet.
356 # (i % 3 == 0) below is somehow arbitrary but chosen to ensure
357 # that we update the flow's 'used' frequently enough to prevent
358 # idle_timeout.
3ef64336 359 if [[ $i -eq 1 -o $((i % 3)) -eq 0 ]]; then
619d5f98
JS
360 sleep 1
361 fi
362done
363
4b10fd11
YT
364# Check that the first packet of each flow went out port 2 and the rest out
365# port 3.
619d5f98
JS
366AT_CHECK(
367 [(ovs-ofctl dump-ports br0 2; ovs-ofctl dump-ports br0 3) | STRIP_XIDS], [0],
368 [OFPST_PORT reply: 1 ports
369 port 2: rx pkts=0, bytes=0, drop=0, errs=0, frame=0, over=0, crc=0
370 tx pkts=2, bytes=120, drop=0, errs=0, coll=0
371OFPST_PORT reply: 1 ports
372 port 3: rx pkts=0, bytes=0, drop=0, errs=0, frame=0, over=0, crc=0
373 tx pkts=18, bytes=1080, drop=0, errs=0, coll=0
374])
375
376# Check for the learning entry.
377ovs-appctl time/warp 1000
378AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0],
379[[ 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
380 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
381NXST_FLOW reply:
382]])
383OVS_VSWITCHD_STOP
384AT_CLEANUP
385
bd2f109b 386# This test is much like the previous, but adds hard timeouts and sends
619d5f98
JS
387# two different flows to the bridge. This tests that the statistics are
388# attributed correctly.
389AT_SETUP([learning action - self-modifying flow with hard_timeout])
390OVS_VSWITCHD_START
391ADD_OF_PORTS([br0], 1, 2, 3)
392
393ovs-appctl time/stop
394# Set up flow table for TCPv4 port learning.
c2dc87c9 395AT_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
396
397# Trace some packets arriving. The particular packets don't matter.
398for i in `seq 1 10`; do
399 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
400 if [[ $i -eq 1 ]]; then
401 sleep 1
402 fi
c2dc87c9 403 ovs-appctl time/warp 10
619d5f98
JS
404done
405
406# Trace some packets arriving. This is is a different flow from the previous.
c2dc87c9 407# Note that we advance time by 2 second between each packet here.
619d5f98
JS
408for i in `seq 1 10`; do
409 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
410 # Note: hard_timeout should fire immediately after #6 packet.
411 # #7 packet re-install the flow and the following 3 packets
412 # (#8, #9, #10) use the flow.
413 # it's difficult to predict the exact timing of rule expiry
414 # because it's affected by flow dumper thread via udpif_dump_seq.
415 # hard_timeout value for this test was chosen to overcome the uncertainty.
dd7ec292
YT
416 #
417 # receive #1 learn, install flow with hard_timeout=10
418 # sleep to ensure the flow installation
419 # (warp, timeout left 8s)
420 # receive #2 the learned flow
421 # (warp, timeout left 6s)
422 # receive #3
423 # (warp, timeout left 4s)
424 # receive #4
425 # (warp, timeout left 2s)
426 # receive #5
427 # (warp, timeout left 0s)
428 # NOTE: OVS does not consider this expired yet. cf. rule_expire()
429 # receive #6
430 # (warp, timeout left -2s)
431 # sleep to ensure flow expiration
432 # receive #7 learn, install flow with hard_timeout=10
433 # sleep to ensure the flow installation
434 # (warp, timeout left 8s)
435 # receive #8
436 # (warp, timeout left 6s)
437 # receive #9
438 # (warp, timeout left 4s)
439 # receive #10
440 # (warp, timeout left 2s)
441 if [[ $i -eq 1 -o $i -eq 7 ]]; then
619d5f98
JS
442 sleep 1
443 fi
c2dc87c9 444 ovs-appctl time/warp 2000
dd7ec292
YT
445 if [[ $i -eq 6 ]]; then
446 sleep 1
447 fi
619d5f98
JS
448done
449
4b10fd11
YT
450# Check that the first packet of each flow went out port 2 and the rest out
451# port 3.
619d5f98
JS
452AT_CHECK(
453 [(ovs-ofctl dump-ports br0 2; ovs-ofctl dump-ports br0 3) | STRIP_XIDS], [0],
454 [OFPST_PORT reply: 1 ports
455 port 2: rx pkts=0, bytes=0, drop=0, errs=0, frame=0, over=0, crc=0
456 tx pkts=3, bytes=180, drop=0, errs=0, coll=0
457OFPST_PORT reply: 1 ports
458 port 3: rx pkts=0, bytes=0, drop=0, errs=0, frame=0, over=0, crc=0
459 tx pkts=17, bytes=1020, drop=0, errs=0, coll=0
460])
461
462# Check for the learning entry.
463ovs-appctl time/warp 1000
c2dc87c9 464sleep 1
619d5f98 465AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0],
c2dc87c9
YT
466[[ 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
467 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
468NXST_FLOW reply:
469]])
7cf2e080
BP
470OVS_VSWITCHD_STOP
471AT_CLEANUP
472
0e553d9c
BP
473AT_SETUP([learning action - fin_timeout feature])
474# This is a totally artificial use of the "learn" action. The only purpose
475# is to check that specifying fin_idle_timeout or fin_hard_timeout causes
476# a corresponding fin_timeout action to end up in the learned flows.
e1b1d06a
JP
477OVS_VSWITCHD_START(
478 [add-port br0 p1 -- set Interface p1 type=dummy ofport_request=1])
0e553d9c 479AT_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 480AT_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
481AT_CHECK([ovs-ofctl dump-flows br0 table=1 | ofctl_strip], [0],
482[NXST_FLOW reply:
483 table=1, dl_dst=50:54:00:00:00:05 actions=fin_timeout(idle_timeout=5,hard_timeout=10),output:1
484])
485OVS_VSWITCHD_STOP
486AT_CLEANUP
35f48b8b
BP
487
488AT_SETUP([learning action - delete_learned feature])
489OVS_VSWITCHD_START
490
491# Add some initial flows and check that it was successful.
492AT_DATA([flows.txt], [dnl
493 reg0=0x1 actions=learn(delete_learned,cookie=0x123)
494 reg0=0x2 actions=learn(delete_learned,cookie=0x123)
495cookie=0x123, table=1, reg0=0x3 actions=drop
496cookie=0x123, table=1, reg0=0x4 actions=drop
497cookie=0x123, table=2, reg0=0x5 actions=drop
498cookie=0x234, table=1, reg0=0x6 actions=drop
499])
500AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
501AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
502 cookie=0x123, table=1, reg0=0x3 actions=drop
503 cookie=0x123, table=1, reg0=0x4 actions=drop
504 cookie=0x123, table=2, reg0=0x5 actions=drop
505 cookie=0x234, table=1, reg0=0x6 actions=drop
506 reg0=0x1 actions=learn(table=1,delete_learned,cookie=0x123)
507 reg0=0x2 actions=learn(table=1,delete_learned,cookie=0x123)
508NXST_FLOW reply:
509])
510
511# Delete one of the learn actions. The learned flows should stay, since there
512# is another learn action with the identical target.
513AT_CHECK([ovs-ofctl del-flows br0 'table=0 reg0=1'])
514AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
515 cookie=0x123, table=1, reg0=0x3 actions=drop
516 cookie=0x123, table=1, reg0=0x4 actions=drop
517 cookie=0x123, table=2, reg0=0x5 actions=drop
518 cookie=0x234, table=1, reg0=0x6 actions=drop
519 reg0=0x2 actions=learn(table=1,delete_learned,cookie=0x123)
520NXST_FLOW reply:
521])
522
523# Change the flow with the learn action by adding a second action. The learned
524# flows should stay because the learn action is still there.
525AT_CHECK([ovs-ofctl mod-flows br0 'table=0 reg0=2 actions=output:1,learn(delete_learned,cookie=0x123)'])
526AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
527 cookie=0x123, table=1, reg0=0x3 actions=drop
528 cookie=0x123, table=1, reg0=0x4 actions=drop
529 cookie=0x123, table=2, reg0=0x5 actions=drop
530 cookie=0x234, table=1, reg0=0x6 actions=drop
531 reg0=0x2 actions=output:1,learn(table=1,delete_learned,cookie=0x123)
532NXST_FLOW reply:
533])
534
535# Change the flow with the learn action by replacing its learn action by one
536# with a different target. The (previous) learned flows disappear.
537AT_CHECK([ovs-ofctl mod-flows br0 'table=0 reg0=2 actions=learn(delete_learned,cookie=0x234)'])
538AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
539 cookie=0x123, table=2, reg0=0x5 actions=drop
540 cookie=0x234, table=1, reg0=0x6 actions=drop
541 reg0=0x2 actions=learn(table=1,delete_learned,cookie=0x234)
542NXST_FLOW reply:
543])
544
545# Use add-flow to replace the flow with the learn action by one with the
546# same learn action and an extra action. The (new) learned flow remains.
547AT_CHECK([ovs-ofctl add-flow br0 'table=0 reg0=2 actions=learn(delete_learned,cookie=0x234),output:2'])
548AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
549 cookie=0x123, table=2, reg0=0x5 actions=drop
550 cookie=0x234, table=1, reg0=0x6 actions=drop
551 reg0=0x2 actions=learn(table=1,delete_learned,cookie=0x234),output:2
552NXST_FLOW reply:
553])
554
555# Delete the flow with the learn action. The learned flow disappears too.
556AT_CHECK([ovs-ofctl del-flows br0 table=0])
557AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
558 cookie=0x123, table=2, reg0=0x5 actions=drop
559NXST_FLOW reply:
560])
561
562# Add a new set of flows to check on a corner case: the learned flows
563# contain their own learn actions which cascade to further deletions.
564# This can't happen if the learned flows were actually created by a
565# learn action, since the learn action has very restricted action
566# support, but there's no restriction that the deleted flows were
567# created by a learn action.
568AT_DATA([flows.txt], [dnl
569 reg0=0x1 actions=learn(table=1,delete_learned,cookie=0x123)
570 reg0=0x2 actions=learn(table=2,delete_learned,cookie=0x234)
571cookie=0x123, table=1, reg0=0x3 actions=learn(table=3,delete_learned,cookie=0x345)
572cookie=0x234, table=2, reg0=0x3 actions=learn(table=4,delete_learned,cookie=0x456)
573cookie=0x345, table=3, reg0=0x4 actions=learn(table=5,delete_learned,cookie=0x567)
574cookie=0x456, table=4, reg0=0x5 actions=learn(table=5,delete_learned,cookie=0x567)
575cookie=0x567, table=5, reg0=0x6 actions=drop
576cookie=0x567, table=5, reg0=0x7 actions=drop
577cookie=0x567, table=5, reg0=0x8 actions=drop
578])
579AT_CHECK([ovs-ofctl del-flows br0])
580AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
581AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
582 cookie=0x123, table=1, reg0=0x3 actions=learn(table=3,delete_learned,cookie=0x345)
583 cookie=0x234, table=2, reg0=0x3 actions=learn(table=4,delete_learned,cookie=0x456)
584 cookie=0x345, table=3, reg0=0x4 actions=learn(table=5,delete_learned,cookie=0x567)
585 cookie=0x456, table=4, reg0=0x5 actions=learn(table=5,delete_learned,cookie=0x567)
586 cookie=0x567, table=5, reg0=0x6 actions=drop
587 cookie=0x567, table=5, reg0=0x7 actions=drop
588 cookie=0x567, table=5, reg0=0x8 actions=drop
589 reg0=0x1 actions=learn(table=1,delete_learned,cookie=0x123)
590 reg0=0x2 actions=learn(table=2,delete_learned,cookie=0x234)
591NXST_FLOW reply:
592])
593
594# Deleting the flow with reg0=1 should cascade to delete a few levels
595# of learned flows, but the ones with cookie=0x567 stick around
596# because of the flow with cookie=0x456.
597AT_CHECK([ovs-ofctl del-flows br0 'table=0 reg0=1'])
598AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
599 cookie=0x234, table=2, reg0=0x3 actions=learn(table=4,delete_learned,cookie=0x456)
600 cookie=0x456, table=4, reg0=0x5 actions=learn(table=5,delete_learned,cookie=0x567)
601 cookie=0x567, table=5, reg0=0x6 actions=drop
602 cookie=0x567, table=5, reg0=0x7 actions=drop
603 cookie=0x567, table=5, reg0=0x8 actions=drop
604 reg0=0x2 actions=learn(table=2,delete_learned,cookie=0x234)
605NXST_FLOW reply:
606])
607
608# Deleting the flow with reg0=2 should cascade to delete all the rest:
609AT_CHECK([ovs-ofctl del-flows br0 'table=0 reg0=2'])
610AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
611NXST_FLOW reply:
612])
613OVS_VSWITCHD_STOP
614AT_CLEANUP