1 AT_BANNER([learning action])
3 AT_SETUP([learning action - parsing and formatting])
4 AT_DATA([flows.txt], [[
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])
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])
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
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
36 AT_SETUP([learning action - satisfied prerequisites])
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[])
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[])
51 AT_SETUP([learning action - invalid prerequisites])
52 AT_CHECK([[ovs-ofctl parse-flow 'actions=learn(load:5->NXM_OF_IP_DST[])']],
54 [[ovs-ofctl: load:5->NXM_OF_IP_DST[]: cannot specify destination field ip_dst because prerequisites are not satisfied
56 AT_CHECK([[ovs-ofctl parse-flow 'actions=learn(load:NXM_OF_IP_DST[]->NXM_NX_REG1[])']],
58 [[ovs-ofctl: load:NXM_OF_IP_DST[]->NXM_NX_REG1[]: cannot specify source field ip_dst because prerequisites are not satisfied
62 AT_SETUP([learning action - standard VLAN+MAC learning])
64 [add-port br0 p1 -- set Interface p1 type=dummy ofport_request=1 -- \
65 add-port br0 p2 -- set Interface p2 type=dummy ofport_request=2 -- \
66 add-port br0 p3 -- set Interface p3 type=dummy ofport_request=3])
67 # Set up flow table for VLAN+MAC learning.
68 AT_DATA([flows.txt], [[
69 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)
70 table=1 priority=0 actions=flood
72 AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
74 # Trace an ARP packet arriving on port 3, to create a MAC learning entry.
75 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)"
76 AT_CHECK([ovs-appctl ofproto/trace br0 "$flow" -generate], [0], [stdout])
77 actual=`tail -1 stdout | sed 's/Datapath actions: //'`
80 AT_CHECK([ovs-dpctl normalize-actions "$flow" "$expected"], [0], [stdout])
82 AT_CHECK([ovs-dpctl normalize-actions "$flow" "$actual"], [0], [expout])
84 # Check for the MAC learning entry.
85 AT_CHECK([ovs-ofctl dump-flows br0 table=1 | ofctl_strip | sort], [0], [dnl
86 table=1, hard_timeout=60, vlan_tci=0x0000/0x0fff,dl_dst=50:54:00:00:00:05 actions=output:3
87 table=1, priority=0 actions=FLOOD
91 # Trace a packet arrival destined for the learned MAC.
92 # (This will also learn a MAC.)
93 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])
94 AT_CHECK([tail -1 stdout], [0], [Datapath actions: 3
97 # Check for both MAC learning entries.
98 AT_CHECK([ovs-ofctl dump-flows br0 table=1 | ofctl_strip |sort], [0], [dnl
99 table=1, hard_timeout=60, vlan_tci=0x0000/0x0fff,dl_dst=50:54:00:00:00:05 actions=output:3
100 table=1, hard_timeout=60, vlan_tci=0x0000/0x0fff,dl_dst=50:54:00:00:00:06 actions=output:1
101 table=1, priority=0 actions=FLOOD
105 # Trace a packet arrival that updates the first learned MAC entry.
106 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)"
107 AT_CHECK([ovs-appctl ofproto/trace br0 "$flow" -generate], [0], [stdout])
108 actual=`tail -1 stdout | sed 's/Datapath actions: //'`
111 AT_CHECK([ovs-dpctl normalize-actions "$flow" "$expected"], [0], [stdout])
113 AT_CHECK([ovs-dpctl normalize-actions "$flow" "$actual"], [0], [expout])
115 # Check that the MAC learning entry was updated.
116 AT_CHECK([ovs-ofctl dump-flows br0 table=1 | ofctl_strip | sort], [0], [dnl
117 table=1, hard_timeout=60, vlan_tci=0x0000/0x0fff,dl_dst=50:54:00:00:00:05 actions=output:2
118 table=1, hard_timeout=60, vlan_tci=0x0000/0x0fff,dl_dst=50:54:00:00:00:06 actions=output:1
119 table=1, priority=0 actions=FLOOD
125 dnl This test checks that repeated uses of a "learn" action cause the
126 dnl modified time of the learned flow to advance. Otherwise, the
127 dnl learned flow will expire after its hard timeout even though it's
128 dnl supposed to be refreshed. (The expiration can be hard to see since
129 dnl it gets re-learned again the next time a packet appears, but
130 dnl sometimes the expiration can cause temporary flooding etc.)
131 AT_SETUP([learning action - learn refreshes hard_age])
133 [add-port br0 p1 -- set Interface p1 type=dummy ofport_request=1 -- \
134 add-port br0 p2 -- set Interface p2 type=dummy ofport_request=2 -- \
135 add-port br0 p3 -- set Interface p3 type=dummy ofport_request=3])
139 # Set up flow table for MAC learning.
140 AT_DATA([flows.txt], [[
141 table=0 actions=learn(table=1, hard_timeout=10, NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[], output:NXM_OF_IN_PORT[]), resubmit(,1)
142 table=1 priority=0 actions=flood
144 AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
146 # Trace an ICMP packet arriving on port 3, to create a MAC learning entry.
147 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)"
148 AT_CHECK([ovs-appctl ofproto/trace br0 "$flow" -generate], [0], [stdout])
149 actual=`tail -1 stdout | sed 's/Datapath actions: //'`
152 AT_CHECK([ovs-dpctl normalize-actions "$flow" "$expected"], [0], [stdout])
154 AT_CHECK([ovs-dpctl normalize-actions "$flow" "$actual"], [0], [expout])
156 # Check that the MAC learning entry appeared.
157 AT_CHECK([ovs-ofctl dump-flows br0 table=1 | ofctl_strip | sort], [0], [dnl
158 table=1, hard_timeout=10, dl_dst=50:54:00:00:00:07 actions=output:3
159 table=1, priority=0 actions=FLOOD
163 # For 25 seconds, make sure that the MAC learning entry doesn't
164 # disappear as long as we refresh it every second.
165 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
166 ovs-appctl time/warp 1000
167 AT_CHECK([ovs-appctl ofproto/trace br0 "$flow" -generate], [0], [stdout])
169 # Check that the entry is there.
170 AT_CHECK([ovs-ofctl dump-flows br0 table=1], [0], [stdout])
171 AT_CHECK([ofctl_strip < stdout | sort], [0], [dnl
172 table=1, hard_timeout=10, dl_dst=50:54:00:00:00:07 actions=output:3
173 table=1, priority=0 actions=FLOOD
177 if test $i != 1; then
178 # Check that hard_age has appeared. We need to do this separately
179 # from the above check because ofctl_strip removes it. dump-flows
180 # only prints hard_age when it is different from the flow's duration
181 # (that is, the number of seconds from the time it was created),
182 # so we only check for it after we've refreshed the flow once.
183 AT_CHECK([grep dl_dst=50:54:00:00:00:07 stdout | grep -c hard_age],
189 # Make sure that 15 seconds without refreshing makes the flow time out.
190 ovs-appctl time/warp 5000
191 ovs-appctl time/warp 5000
192 ovs-appctl time/warp 5000
193 AT_CHECK([ovs-ofctl dump-flows br0 table=1 | ofctl_strip | sort], [0], [dnl
194 table=1, priority=0 actions=FLOOD
200 AT_SETUP([learning action - TCPv4 port learning])
202 [add-port br0 p1 -- set Interface p1 type=dummy -- \
203 add-port br0 p2 -- set Interface p2 type=dummy -- \
204 add-port br0 p3 -- set Interface p3 type=dummy])
205 # Set up flow table for TCPv4 port learning.
206 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']])
208 # Trace a TCPv4 packet arriving on port 3.
209 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)"
210 AT_CHECK([ovs-appctl ofproto/trace br0 "$flow" -generate], [0], [stdout])
211 actual=`tail -1 stdout | sed 's/Datapath actions: //'`
214 AT_CHECK([ovs-dpctl normalize-actions "$flow" "$expected"], [0], [stdout])
216 AT_CHECK([ovs-dpctl normalize-actions "$flow" "$actual"], [0], [expout])
218 # Check for the learning entry.
219 AT_CHECK([ovs-ofctl dump-flows br0 table=1 | ofctl_strip | sort], [0], [dnl
220 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
226 AT_SETUP([learning action - TCPv6 port learning])
228 [add-port br0 p1 -- set Interface p1 type=dummy -- \
229 add-port br0 p2 -- set Interface p2 type=dummy -- \
230 add-port br0 p3 -- set Interface p3 type=dummy])
231 # Set up flow table for TCPv6 port learning.
232 # Also add a 128-bit-wide "load" action and a 128-bit literal match to check
234 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']])
236 # Trace a TCPv6 packet arriving on port 3.
237 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)"
238 AT_CHECK([ovs-appctl ofproto/trace br0 "$flow" -generate], [0], [stdout])
239 actual=`tail -1 stdout | sed 's/Datapath actions: //'`
242 AT_CHECK([ovs-dpctl normalize-actions "$flow" "$expected"], [0], [stdout])
244 AT_CHECK([ovs-dpctl normalize-actions "$flow" "$actual"], [0], [expout])
246 # Check for the learning entry.
247 AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
248 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]]
249 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
255 AT_SETUP([learning action - fin_timeout feature])
256 # This is a totally artificial use of the "learn" action. The only purpose
257 # is to check that specifying fin_idle_timeout or fin_hard_timeout causes
258 # a corresponding fin_timeout action to end up in the learned flows.
260 [add-port br0 p1 -- set Interface p1 type=dummy ofport_request=1])
261 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[])']])
262 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])
263 AT_CHECK([ovs-ofctl dump-flows br0 table=1 | ofctl_strip], [0],
265 table=1, dl_dst=50:54:00:00:00:05 actions=fin_timeout(idle_timeout=5,hard_timeout=10),output:1