Do not perform validation in learn_parse();
[sliver-openvswitch.git] / tests / learn.at
1 AT_BANNER([learning action])
2
3 AT_SETUP([learning action - parsing and formatting])
4 AT_DATA([flows.txt], [[
5 actions=learn()
6 actions=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])
7 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])
8 ]])
9 AT_CHECK([ovs-ofctl parse-flows flows.txt], [0],
10 [[usable protocols: any
11 chosen protocol: OpenFlow10-table_id
12 OFPT_FLOW_MOD (xid=0x1): ADD actions=learn(table=1)
13 OFPT_FLOW_MOD (xid=0x2): 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])
14 OFPT_FLOW_MOD (xid=0x3): 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])
15 ]])
16 AT_CLEANUP
17
18 AT_SETUP([learning action - examples])
19 AT_DATA([flows.txt], [[
20 # These are the examples from nicira-ext.h.
21 actions=learn(in_port=99,NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[], load:NXM_OF_IN_PORT[]->NXM_NX_REG1[16..31])
22 actions=learn(NXM_OF_VLAN_TCI[0..11], NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[],output:NXM_OF_IN_PORT[])
23 table=0 actions=learn(table=1,hard_timeout=10, NXM_OF_VLAN_TCI[0..11],output:NXM_OF_IN_PORT[]), resubmit(,1)
24 table=1 priority=0 actions=flood
25 ]])
26 AT_CHECK([ovs-ofctl parse-flows flows.txt], [0],
27 [[usable protocols: OXM,OpenFlow10+table_id,NXM+table_id
28 chosen protocol: OpenFlow10+table_id
29 OFPT_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])
30 OFPT_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[])
31 OFPT_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)
32 OFPT_FLOW_MOD (xid=0x4): ADD table:1 priority=0 actions=FLOOD
33 ]])
34 AT_CLEANUP
35
36 AT_SETUP([learning action - satisfied prerequisites])
37 AT_DATA([flows.txt],
38 [[actions=learn(eth_type=0x800,load:5->NXM_OF_IP_DST[])
39 ip,actions=learn(load:NXM_OF_IP_DST[]->NXM_NX_REG1[])
40 ip,actions=learn(eth_type=0x800,OXM_OF_IPV4_DST[])
41 ]])
42 AT_CHECK([ovs-ofctl parse-flows flows.txt], [0],
43 [[usable protocols: any
44 chosen protocol: OpenFlow10-table_id
45 OFPT_FLOW_MOD (xid=0x1): ADD actions=learn(table=1,eth_type=0x800,load:0x5->NXM_OF_IP_DST[])
46 OFPT_FLOW_MOD (xid=0x2): ADD ip actions=learn(table=1,load:NXM_OF_IP_DST[]->NXM_NX_REG1[])
47 OFPT_FLOW_MOD (xid=0x3): ADD ip actions=learn(table=1,eth_type=0x800,NXM_OF_IP_DST[])
48 ]])
49 AT_CLEANUP
50
51 AT_SETUP([learning action - invalid prerequisites])
52 AT_CHECK([[ovs-ofctl parse-flow 'actions=learn(load:5->NXM_OF_IP_DST[])']],
53   [1], [], [stderr])
54 AT_CHECK([sed -e 's/.*|meta_flow|WARN|//' < stderr], [0],
55   [[destination field ip_dst lacks correct prerequisites
56 ]], [[]])
57 AT_CHECK([[ovs-ofctl parse-flow 'actions=learn(load:NXM_OF_IP_DST[]->NXM_NX_REG1[])']],
58   [1], [], [stderr])
59 AT_CHECK([sed -e 's/.*|meta_flow|WARN|//' < stderr], [0],
60   [[source field ip_dst lacks correct prerequisites
61 ]])
62 AT_CLEANUP
63
64 AT_SETUP([learning action - standard VLAN+MAC learning])
65 OVS_VSWITCHD_START(
66   [add-port br0 p1 -- set Interface p1 type=dummy ofport_request=1 -- \
67    add-port br0 p2 -- set Interface p2 type=dummy ofport_request=2 -- \
68    add-port br0 p3 -- set Interface p3 type=dummy ofport_request=3])
69 # Set up flow table for VLAN+MAC learning.
70 AT_DATA([flows.txt], [[
71 table=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)
72 table=1 priority=0 actions=flood
73 ]])
74 AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
75
76 # Trace an ARP packet arriving on port 3, to create a MAC learning entry.
77 flow="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)"
78 AT_CHECK([ovs-appctl ofproto/trace br0 "$flow" -generate], [0], [stdout])
79 actual=`tail -1 stdout | sed 's/Datapath actions: //'`
80
81 expected="1,2,100"
82 AT_CHECK([ovs-dpctl normalize-actions "$flow" "$expected"], [0], [stdout])
83 mv stdout expout
84 AT_CHECK([ovs-dpctl normalize-actions "$flow" "$actual"], [0], [expout])
85
86 # Check for the MAC learning entry.
87 AT_CHECK([ovs-ofctl dump-flows br0 table=1 | ofctl_strip | sort], [0], [dnl
88  table=1, hard_timeout=60, vlan_tci=0x0000/0x0fff,dl_dst=50:54:00:00:00:05 actions=output:3
89  table=1, priority=0 actions=FLOOD
90 NXST_FLOW reply:
91 ])
92
93 # Trace a packet arrival destined for the learned MAC.
94 # (This will also learn a MAC.)
95 AT_CHECK([ovs-appctl ofproto/trace br0 '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])
96 AT_CHECK([tail -1 stdout], [0], [Datapath actions: 3
97 ])
98
99 # Check for both MAC learning entries.
100 AT_CHECK([ovs-ofctl dump-flows br0 table=1 | ofctl_strip |sort], [0], [dnl
101  table=1, hard_timeout=60, vlan_tci=0x0000/0x0fff,dl_dst=50:54:00:00:00:05 actions=output:3
102  table=1, hard_timeout=60, vlan_tci=0x0000/0x0fff,dl_dst=50:54:00:00:00:06 actions=output:1
103  table=1, priority=0 actions=FLOOD
104 NXST_FLOW reply:
105 ])
106
107 # Trace a packet arrival that updates the first learned MAC entry.
108 flow="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)"
109 AT_CHECK([ovs-appctl ofproto/trace br0 "$flow" -generate], [0], [stdout])
110 actual=`tail -1 stdout | sed 's/Datapath actions: //'`
111
112 expected="1,3,100"
113 AT_CHECK([ovs-dpctl normalize-actions "$flow" "$expected"], [0], [stdout])
114 mv stdout expout
115 AT_CHECK([ovs-dpctl normalize-actions "$flow" "$actual"], [0], [expout])
116
117 # Check that the MAC learning entry was updated.
118 AT_CHECK([ovs-ofctl dump-flows br0 table=1 | ofctl_strip | sort], [0], [dnl
119  table=1, hard_timeout=60, vlan_tci=0x0000/0x0fff,dl_dst=50:54:00:00:00:05 actions=output:2
120  table=1, hard_timeout=60, vlan_tci=0x0000/0x0fff,dl_dst=50:54:00:00:00:06 actions=output:1
121  table=1, priority=0 actions=FLOOD
122 NXST_FLOW reply:
123 ])
124 OVS_VSWITCHD_STOP
125 AT_CLEANUP
126
127 dnl This test checks that repeated uses of a "learn" action cause the
128 dnl modified time of the learned flow to advance.  Otherwise, the
129 dnl learned flow will expire after its hard timeout even though it's
130 dnl supposed to be refreshed.  (The expiration can be hard to see since
131 dnl it gets re-learned again the next time a packet appears, but
132 dnl sometimes the expiration can cause temporary flooding etc.)
133 AT_SETUP([learning action - learn refreshes hard_age])
134 OVS_VSWITCHD_START(
135   [add-port br0 p1 -- set Interface p1 type=dummy ofport_request=1 -- \
136    add-port br0 p2 -- set Interface p2 type=dummy ofport_request=2 -- \
137    add-port br0 p3 -- set Interface p3 type=dummy ofport_request=3])
138
139 ovs-appctl time/stop
140
141 # Set up flow table for MAC learning.
142 AT_DATA([flows.txt], [[
143 table=0 actions=learn(table=1, hard_timeout=10, NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[], output:NXM_OF_IN_PORT[]), resubmit(,1)
144 table=1 priority=0 actions=flood
145 ]])
146 AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
147
148 # Trace an ICMP packet arriving on port 3, to create a MAC learning entry.
149 flow="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)"
150 AT_CHECK([ovs-appctl ofproto/trace br0 "$flow" -generate], [0], [stdout])
151 actual=`tail -1 stdout | sed 's/Datapath actions: //'`
152
153 expected="1,2,100"
154 AT_CHECK([ovs-dpctl normalize-actions "$flow" "$expected"], [0], [stdout])
155 mv stdout expout
156 AT_CHECK([ovs-dpctl normalize-actions "$flow" "$actual"], [0], [expout])
157
158 # Check that the MAC learning entry appeared.
159 AT_CHECK([ovs-ofctl dump-flows br0 table=1 | ofctl_strip | sort], [0], [dnl
160  table=1, hard_timeout=10, dl_dst=50:54:00:00:00:07 actions=output:3
161  table=1, priority=0 actions=FLOOD
162 NXST_FLOW reply:
163 ])
164
165 # For 25 seconds, make sure that the MAC learning entry doesn't
166 # disappear as long as we refresh it every second.
167 for 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
168     ovs-appctl time/warp 1000
169     AT_CHECK([ovs-appctl ofproto/trace br0 "$flow" -generate], [0], [stdout])
170
171     # Check that the entry is there.
172     AT_CHECK([ovs-ofctl dump-flows br0 table=1], [0], [stdout])
173     AT_CHECK([ofctl_strip < stdout | sort], [0], [dnl
174  table=1, hard_timeout=10, dl_dst=50:54:00:00:00:07 actions=output:3
175  table=1, priority=0 actions=FLOOD
176 NXST_FLOW reply:
177 ])
178
179     if test $i != 1; then
180         # Check that hard_age has appeared.  We need to do this separately
181         # from the above check because ofctl_strip removes it.  dump-flows
182         # only prints hard_age when it is different from the flow's duration
183         # (that is, the number of seconds from the time it was created),
184         # so we only check for it after we've refreshed the flow once.
185         AT_CHECK([grep dl_dst=50:54:00:00:00:07 stdout | grep -c hard_age],
186                  [0], [1
187 ])
188     fi
189 done
190
191 # Make sure that 15 seconds without refreshing makes the flow time out.
192 ovs-appctl time/warp 5000
193 ovs-appctl time/warp 5000
194 ovs-appctl time/warp 5000
195     AT_CHECK([ovs-ofctl dump-flows br0 table=1 | ofctl_strip | sort], [0], [dnl
196  table=1, priority=0 actions=FLOOD
197 NXST_FLOW reply:
198 ])
199 OVS_VSWITCHD_STOP
200 AT_CLEANUP
201
202 AT_SETUP([learning action - TCPv4 port learning])
203 OVS_VSWITCHD_START(
204   [add-port br0 p1 -- set Interface p1 type=dummy -- \
205    add-port br0 p2 -- set Interface p2 type=dummy -- \
206    add-port br0 p3 -- set Interface p3 type=dummy])
207 # Set up flow table for TCPv4 port learning.
208 AT_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']])
209
210 # Trace a TCPv4 packet arriving on port 3.
211 flow="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)"
212 AT_CHECK([ovs-appctl ofproto/trace br0 "$flow" -generate], [0], [stdout])
213 actual=`tail -1 stdout | sed 's/Datapath actions: //'`
214
215 expected="1,2,100"
216 AT_CHECK([ovs-dpctl normalize-actions "$flow" "$expected"], [0], [stdout])
217 mv stdout expout
218 AT_CHECK([ovs-dpctl normalize-actions "$flow" "$actual"], [0], [expout])
219
220 # Check for the learning entry.
221 AT_CHECK([ovs-ofctl dump-flows br0 table=1 | ofctl_strip | sort], [0], [dnl
222  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
223 NXST_FLOW reply:
224 ])
225 OVS_VSWITCHD_STOP
226 AT_CLEANUP
227
228 AT_SETUP([learning action - TCPv6 port learning])
229 OVS_VSWITCHD_START(
230   [add-port br0 p1 -- set Interface p1 type=dummy -- \
231    add-port br0 p2 -- set Interface p2 type=dummy -- \
232    add-port br0 p3 -- set Interface p3 type=dummy])
233 # Set up flow table for TCPv6 port learning.
234 # Also add a 128-bit-wide "load" action and a 128-bit literal match to check
235 # that they work.
236 AT_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']])
237
238 # Trace a TCPv6 packet arriving on port 3.
239 flow="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)"
240 AT_CHECK([ovs-appctl ofproto/trace br0 "$flow" -generate], [0], [stdout])
241 actual=`tail -1 stdout | sed 's/Datapath actions: //'`
242
243 expected="1,2,100"
244 AT_CHECK([ovs-dpctl normalize-actions "$flow" "$expected"], [0], [stdout])
245 mv stdout expout
246 AT_CHECK([ovs-dpctl normalize-actions "$flow" "$actual"], [0], [expout])
247
248 # Check for the learning entry.
249 AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
250  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]]
251  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
252 NXST_FLOW reply:
253 ])
254 OVS_VSWITCHD_STOP
255 AT_CLEANUP
256
257 # In this use of a learn action, the first packet in the flow creates
258 # a new flow that changes the behavior of subsequent packets in the
259 # flow.
260 AT_SETUP([learning action - self-modifying flow])
261 OVS_VSWITCHD_START
262 ADD_OF_PORTS([br0], 1, 2, 3)
263
264 # Set up flow table for TCPv4 port learning.
265 AT_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']])
266
267 # Trace some packets arriving.  The particular packets don't matter.
268 for i in 1 2 3 4 5 6 7 8 9 10; do
269     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)'
270 done
271
272 # Check for the learning entry.
273 AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0],
274 [[ 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
275  priority=65535,vlan_tci=0x0000/0x0fff,dl_src=50:54:00:00:00:05 actions=output:3
276 NXST_FLOW reply:
277 ]])
278
279 # Check that the first packet went out port 2 and the rest out port 3.
280 AT_CHECK(
281   [(ovs-ofctl dump-ports br0 2; ovs-ofctl dump-ports br0 3) | STRIP_XIDS], [0],
282   [OFPST_PORT reply: 1 ports
283   port  2: rx pkts=0, bytes=0, drop=0, errs=0, frame=0, over=0, crc=0
284            tx pkts=1, bytes=60, drop=0, errs=0, coll=0
285 OFPST_PORT reply: 1 ports
286   port  3: rx pkts=0, bytes=0, drop=0, errs=0, frame=0, over=0, crc=0
287            tx pkts=9, bytes=540, drop=0, errs=0, coll=0
288 ])
289 OVS_VSWITCHD_STOP
290 AT_CLEANUP
291
292 AT_SETUP([learning action - fin_timeout feature])
293 # This is a totally artificial use of the "learn" action.  The only purpose
294 # is to check that specifying fin_idle_timeout or fin_hard_timeout causes
295 # a corresponding fin_timeout action to end up in the learned flows.
296 OVS_VSWITCHD_START(
297     [add-port br0 p1 -- set Interface p1 type=dummy ofport_request=1])
298 AT_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[])']])
299 AT_CHECK([ovs-appctl ofproto/trace br0 '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])
300 AT_CHECK([ovs-ofctl dump-flows br0 table=1 | ofctl_strip], [0],
301 [NXST_FLOW reply:
302  table=1, dl_dst=50:54:00:00:00:05 actions=fin_timeout(idle_timeout=5,hard_timeout=10),output:1
303 ])
304 OVS_VSWITCHD_STOP
305 AT_CLEANUP