1 # OVN_CHECK_PACKETS([PCAP], [EXPECTED])
3 # This compares packets read from PCAP, in pcap format, to those read
4 # from EXPECTED, which is a text file containing packets as hex
5 # strings, one per line. If PCAP contains fewer packets than
6 # EXPECTED, it waits up to 10 seconds for more packets to appear.
8 # The implementation is an m4 macro that is mostly implemented in
9 # terms of a shell function. This reduces the size of the generated
10 # testsuite file since the shell function is only emitted once even
11 # when this macro is invoked many times.
12 m4_divert_text([PREPARE_TESTS],
13 [ovn_check_packets__ () {
15 echo "checking packets in $1 against $2:"
17 rcv_text=`echo "$rcv_pcap.packets" | sed 's/\.pcap//'`
19 exp_n=`wc -l < "$exp_text"`
21 [$PYTHON "$top_srcdir/utilities/ovs-pcap.in" $rcv_pcap > $rcv_text
22 rcv_n=`wc -l < "$rcv_text"`
23 echo "rcv_n=$rcv_n exp_n=$exp_n"
24 test $rcv_n -ge $exp_n])
25 sort $exp_text > expout
28 m4_define([OVN_CHECK_PACKETS],
29 [ovn_check_packets__ "$1" "$2"
30 AT_CHECK([sort $rcv_text], [0], [expout])])
32 AT_BANNER([OVN components])
34 AT_SETUP([ovn -- lexer])
35 dnl For lines without =>, input and expected output are identical.
36 dnl For lines with =>, input precedes => and expected output follows =>.
37 AT_DATA([test-cases.txt], [dnl
38 foo bar baz quuxquuxquux _abcd_ a.b.c.d a123_.456
39 "abc\u0020def" => "abc def"
40 " => error("Input ends inside quoted string.")dnl "
42 $foo $bar $baz $quuxquuxquux $_abcd_ $a.b.c.d $a123_.456
43 $1 => error("`$' must be followed by a valid identifier.") 1
48 a/*/b => a error("`/*' without matching `*/'.")
50 a/b => a error("`/' is only valid as part of `//' or `/*'.") b
52 0 1 12345 18446744073709551615
53 18446744073709551616 => error("Decimal constants must be less than 2**64.")
54 9999999999999999999999 => error("Decimal constants must be less than 2**64.")
55 01 => error("Decimal constants must not have leading zeros.")
59 1/0 => error("Value contains unmasked 1-bits.")
63 1/ => error("Integer constant expected.")
65 1/0x123 => error("Value and mask have incompatible formats.")
72 0XFEDCBA9876543210 => 0xfedcba9876543210
73 0xfedcba9876543210fedcba9876543210
74 0x0000fedcba9876543210fedcba9876543210 => 0xfedcba9876543210fedcba9876543210
75 0x => error("Hex digits expected following 0x.")
76 0X => error("Hex digits expected following 0X.")
79 0x1/0x0 => error("Value contains unmasked 1-bits.")
81 0x. => error("Invalid syntax in hexadecimal constant.")
83 192.168.128.1 1.2.3.4 255.255.255.255 0.0.0.0
84 256.1.2.3 => error("Invalid numeric constant.")
86 192.168.0.0/255.255.0.0 => 192.168.0.0/16
87 192.168.0.0/255.255.255.0 => 192.168.0.0/24
88 192.168.0.0/255.255.0.255
89 192.168.0.0/255.0.0.0 => error("Value contains unmasked 1-bits.")
91 192.168.0.0/255.255.255.255 => 192.168.0.0/32
92 1.2.3.4:5 => 1.2.3.4 : 5
96 ff00::1234 => ff00::1234
97 2001:db8:85a3::8a2e:370:7334
98 2001:db8:85a3:0:0:8a2e:370:7334 => 2001:db8:85a3::8a2e:370:7334
99 2001:0db8:85a3:0000:0000:8a2e:0370:7334 => 2001:db8:85a3::8a2e:370:7334
101 ::ffff:c000:0280 => ::ffff:192.0.2.128
103 ::1/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff => ::1/128
106 ff00::/ff00:: => ff00::/8
109 01:23:45:67:AB:CD => 01:23:45:67:ab:cd
111 FE:DC:ba:98:76:54 => fe:dc:ba:98:76:54
112 01:00:00:00:00:00/01:00:00:00:00:00
113 ff:ff:ff:ff:ff:ff/ff:ff:ff:ff:ff:ff
114 fe:ff:ff:ff:ff:ff/ff:ff:ff:ff:ff:ff
115 ff:ff:ff:ff:ff:ff/fe:ff:ff:ff:ff:ff => error("Value contains unmasked 1-bits.")
116 fe:x => error("Invalid numeric constant.")
117 00:01:02:03:04:x => error("Invalid numeric constant.")
119 # Test that operators are tokenized as expected, even without white space.
120 (){}[[]]==!=<<=>>=!&&||..,;=<->--: => ( ) { } [[ ]] == != < <= > >= ! && || .. , ; = <-> -- :
121 & => error("`&' is only valid as part of `&&'.")
122 | => error("`|' is only valid as part of `||'.")
123 - => error("`-' is only valid as part of `--'.")
125 ^ => error("Invalid character `^' in input.")
127 AT_CAPTURE_FILE([input.txt])
128 sed 's/ =>.*//' test-cases.txt > input.txt
129 sed 's/.* => //' test-cases.txt > expout
130 AT_CHECK([ovstest test-ovn lex < input.txt], [0], [expout])
133 dnl The OVN expression parser needs to know what fields overlap with one
134 dnl another. This test therefore verifies that all the smaller registers
135 dnl are defined as terms of subfields of the larger ones.
137 dnl When we add or remove registers this test needs to be updated, of course.
138 AT_SETUP([ovn -- registers])
139 AT_CHECK([ovstest test-ovn dump-symtab | grep reg | sort], [0],
140 [[reg0 = xxreg0[96..127]
141 reg1 = xxreg0[64..95]
142 reg2 = xxreg0[32..63]
144 reg4 = xxreg1[96..127]
145 reg5 = xxreg1[64..95]
146 reg6 = xxreg1[32..63]
150 xreg0 = xxreg0[64..127]
151 xreg1 = xxreg0[0..63]
152 xreg2 = xxreg1[64..127]
153 xreg3 = xxreg1[0..63]
154 xreg4 = OXM_OF_PKT_REG4
155 xxreg0 = NXM_NX_XXREG0
156 xxreg1 = NXM_NX_XXREG1
160 dnl Check that the OVN conntrack field definitions are correct.
161 AT_SETUP([ovn -- conntrack fields])
162 AT_CHECK([ovstest test-ovn dump-symtab | grep ^ct | sort], [0],
163 [[ct.dnat = ct_state[7]
169 ct.snat = ct_state[6]
171 ct_label = NXM_NX_CT_LABEL
172 ct_label.blocked = ct_label[0]
173 ct_mark = NXM_NX_CT_MARK
174 ct_state = NXM_NX_CT_STATE
178 AT_SETUP([ovn -- composition])
179 AT_CHECK([ovstest test-ovn composition 2], [0], [ignore])
182 AT_SETUP([ovn -- expression parser])
183 dnl For lines without =>, input and expected output are identical.
184 dnl For lines with =>, input precedes => and expected output follows =>.
185 AT_DATA([test-cases.txt], [[
187 eth.type==0x800 => eth.type == 0x800
188 eth.type[0..15] == 0x800 => eth.type == 0x800
191 vlan.present == 1 => vlan.present
192 !(vlan.present == 0) => vlan.present
193 !(vlan.present != 1) => vlan.present
195 vlan.present == 0 => !vlan.present
196 vlan.present != 1 => !vlan.present
197 !(vlan.present == 1) => !vlan.present
198 !(vlan.present != 0) => !vlan.present
201 eth.dst[0] == 1 => eth.dst[0]
202 eth.dst[0] != 0 => eth.dst[0]
203 !(eth.dst[0] == 0) => eth.dst[0]
204 !(eth.dst[0] != 1) => eth.dst[0]
207 eth.dst[0] == 0 => !eth.dst[0]
208 eth.dst[0] != 1 => !eth.dst[0]
209 !(eth.dst[0] == 1) => !eth.dst[0]
210 !(eth.dst[0] != 0) => !eth.dst[0]
212 vlan.tci[12..15] == 0x3
213 vlan.tci == 0x3000/0xf000 => vlan.tci[12..15] == 0x3
214 vlan.tci[12..15] != 0x3
215 vlan.tci != 0x3000/0xf000 => vlan.tci[12..15] != 0x3
217 !vlan.pcp => vlan.pcp == 0
218 !(vlan.pcp) => vlan.pcp == 0
225 !(vlan.pcp != 0x4) => vlan.pcp == 0x4
226 !(vlan.pcp == 0x4) => vlan.pcp != 0x4
227 !(vlan.pcp <= 0x4) => vlan.pcp > 0x4
228 !(vlan.pcp < 0x4) => vlan.pcp >= 0x4
229 !(vlan.pcp >= 0x4) => vlan.pcp < 0x4
230 !(vlan.pcp > 0x4) => vlan.pcp <= 0x4
231 0x4 == vlan.pcp => vlan.pcp == 0x4
232 0x4 != vlan.pcp => vlan.pcp != 0x4
233 0x4 < vlan.pcp => vlan.pcp > 0x4
234 0x4 <= vlan.pcp => vlan.pcp >= 0x4
235 0x4 > vlan.pcp => vlan.pcp < 0x4
236 0x4 >= vlan.pcp => vlan.pcp <= 0x4
237 !(0x4 != vlan.pcp) => vlan.pcp == 0x4
238 !(0x4 == vlan.pcp) => vlan.pcp != 0x4
239 !(0x4 >= vlan.pcp) => vlan.pcp > 0x4
240 !(0x4 > vlan.pcp) => vlan.pcp >= 0x4
241 !(0x4 <= vlan.pcp) => vlan.pcp < 0x4
242 !(0x4 < vlan.pcp) => vlan.pcp <= 0x4
244 1 < vlan.pcp < 4 => vlan.pcp > 0x1 && vlan.pcp < 0x4
245 1 <= vlan.pcp <= 4 => vlan.pcp >= 0x1 && vlan.pcp <= 0x4
246 1 < vlan.pcp <= 4 => vlan.pcp > 0x1 && vlan.pcp <= 0x4
247 1 <= vlan.pcp < 4 => vlan.pcp >= 0x1 && vlan.pcp < 0x4
248 1 <= vlan.pcp <= 4 => vlan.pcp >= 0x1 && vlan.pcp <= 0x4
249 4 > vlan.pcp > 1 => vlan.pcp < 0x4 && vlan.pcp > 0x1
250 4 >= vlan.pcp > 1 => vlan.pcp <= 0x4 && vlan.pcp > 0x1
251 4 > vlan.pcp >= 1 => vlan.pcp < 0x4 && vlan.pcp >= 0x1
252 4 >= vlan.pcp >= 1 => vlan.pcp <= 0x4 && vlan.pcp >= 0x1
253 !(1 < vlan.pcp < 4) => vlan.pcp <= 0x1 || vlan.pcp >= 0x4
254 !(1 <= vlan.pcp <= 4) => vlan.pcp < 0x1 || vlan.pcp > 0x4
255 !(1 < vlan.pcp <= 4) => vlan.pcp <= 0x1 || vlan.pcp > 0x4
256 !(1 <= vlan.pcp < 4) => vlan.pcp < 0x1 || vlan.pcp >= 0x4
257 !(1 <= vlan.pcp <= 4) => vlan.pcp < 0x1 || vlan.pcp > 0x4
258 !(4 > vlan.pcp > 1) => vlan.pcp >= 0x4 || vlan.pcp <= 0x1
259 !(4 >= vlan.pcp > 1) => vlan.pcp > 0x4 || vlan.pcp <= 0x1
260 !(4 > vlan.pcp >= 1) => vlan.pcp >= 0x4 || vlan.pcp < 0x1
261 !(4 >= vlan.pcp >= 1) => vlan.pcp > 0x4 || vlan.pcp < 0x1
263 vlan.pcp == {1, 2, 3, 4} => vlan.pcp == 0x1 || vlan.pcp == 0x2 || vlan.pcp == 0x3 || vlan.pcp == 0x4
264 vlan.pcp == 1 || ((vlan.pcp == 2 || vlan.pcp == 3) || vlan.pcp == 4) => vlan.pcp == 0x1 || vlan.pcp == 0x2 || vlan.pcp == 0x3 || vlan.pcp == 0x4
266 vlan.pcp != {1, 2, 3, 4} => vlan.pcp != 0x1 && vlan.pcp != 0x2 && vlan.pcp != 0x3 && vlan.pcp != 0x4
267 vlan.pcp == 1 && ((vlan.pcp == 2 && vlan.pcp == 3) && vlan.pcp == 4) => vlan.pcp == 0x1 && vlan.pcp == 0x2 && vlan.pcp == 0x3 && vlan.pcp == 0x4
269 vlan.pcp == 1 && !((vlan.pcp == 2 && vlan.pcp == 3) && vlan.pcp == 4) => vlan.pcp == 0x1 && (vlan.pcp != 0x2 || vlan.pcp != 0x3 || vlan.pcp != 0x4)
270 vlan.pcp == 1 && (!(vlan.pcp == 2 && vlan.pcp == 3) && vlan.pcp == 4) => vlan.pcp == 0x1 && (vlan.pcp != 0x2 || vlan.pcp != 0x3) && vlan.pcp == 0x4
271 vlan.pcp == 1 && !(!(vlan.pcp == 2 && vlan.pcp == 3) && vlan.pcp == 4) => vlan.pcp == 0x1 && ((vlan.pcp == 0x2 && vlan.pcp == 0x3) || vlan.pcp != 0x4)
273 ip4.src == {10.0.0.0/8, 192.168.0.0/16, 172.16.20.0/24, 8.8.8.8} => ip4.src[24..31] == 0xa || ip4.src[16..31] == 0xc0a8 || ip4.src[8..31] == 0xac1014 || ip4.src == 0x8080808
274 ip6.src == ::1 => ip6.src == 0x1
276 ip4.src == 1.2.3.4 => ip4.src == 0x1020304
277 ip4.src == ::1.2.3.4/::ffff:ffff => ip4.src == 0x1020304
278 ip6.src == ::1 => ip6.src == 0x1
286 !(inport != "eth0") => inport == "eth0"
288 (((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((0))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) => 0
290 ip4.src == "eth0" => Integer field ip4.src is not compatible with string constant.
291 inport == 1 => String field inport is not compatible with integer constant.
292 ip4.src = 1.2.3.4 => Syntax error at `=' expecting relational operator.
294 ip4.src > {1, 2, 3} => Only == and != operators may be used with value sets.
295 eth.type > 0x800 => Only == and != operators may be used with nominal field eth.type.
296 vlan.present > 0 => Only == and != operators may be used with Boolean field vlan.present.
298 inport != "eth0" => Nominal field inport may only be tested for equality (taking enclosing `!' operators into account).
299 !(inport == "eth0") => Nominal field inport may only be tested for equality (taking enclosing `!' operators into account).
300 eth.type != 0x800 => Nominal field eth.type may only be tested for equality (taking enclosing `!' operators into account).
301 !(eth.type == 0x800) => Nominal field eth.type may only be tested for equality (taking enclosing `!' operators into account).
302 inport = "eth0" => Syntax error at `=' expecting relational operator.
304 123 == 123 => Syntax error at `123' expecting field name.
306 $name => Syntax error at `$name' expecting address set name.
307 @name => Syntax error at `@name' expecting port group name.
309 123 == xyzzy => Syntax error at `xyzzy' expecting field name.
310 xyzzy == 1 => Syntax error at `xyzzy' expecting field name.
312 inport[1] == 1 => Cannot select subfield of string field inport.
314 eth.type[] == 1 => Syntax error at `@:>@' expecting small integer.
315 eth.type[::1] == 1 => Syntax error at `::1' expecting small integer.
316 eth.type[18446744073709551615] == 1 => Syntax error at `18446744073709551615' expecting small integer.
318 eth.type[5!] => Syntax error at `!' expecting `@:>@'.
320 eth.type[5..1] => Invalid bit range 5 to 1.
322 eth.type[12..16] => Cannot select bits 12 to 16 of 16-bit field eth.type.
324 eth.type[10] == 1 => Cannot select subfield of nominal field eth.type.
326 eth.type => Explicit `!= 0' is required for inequality test of multibit field against 0.
328 !(!(vlan.pcp)) => Explicit `!= 0' is required for inequality test of multibit field against 0.
330 123 => Syntax error at end of input expecting relational operator.
332 123 x => Syntax error at `x' expecting relational operator.
334 {1, "eth0"} => Syntax error at `"eth0"' expecting integer.
336 eth.type == xyzzy => Syntax error at `xyzzy' expecting constant.
338 (1 x) => Syntax error at `x' expecting `)'.
340 !0x800 != eth.type => Missing parentheses around operand of !.
342 eth.type == 0x800 || eth.type == 0x86dd && ip.proto == 17 => && and || must be parenthesized when used together.
344 eth.dst == {} => Syntax error at `}' expecting constant.
346 eth.src > 00:00:00:00:11:11/00:00:00:00:ff:ff => Only == and != operators may be used with masked constants. Consider using subfields instead (e.g. eth.src[0..15] > 0x1111 in place of eth.src > 00:00:00:00:11:11/00:00:00:00:ff:ff).
348 ip4.src == ::1 => 128-bit constant is not compatible with 32-bit field ip4.src.
350 1 == eth.type == 2 => Range expressions must have the form `x < field < y' or `x > field > y', with each `<' optionally replaced by `<=' or `>' by `>=').
352 eth.dst[40] x => Syntax error at `x' expecting end of input.
354 ip4.src == {1.2.3.4, $set1, $unknownset} => Syntax error at `$unknownset' expecting address set name.
355 eth.src == {$set3, badmac, 00:00:00:00:00:01} => Syntax error at `badmac' expecting constant.
357 ((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((())))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) => Parentheses nested too deeply.
359 ct_label > $set4 => Only == and != operators may be used to compare a field against an empty value set.
361 sed 's/ =>.*//' test-cases.txt > input.txt
362 sed 's/.* => //' test-cases.txt > expout
363 AT_CHECK([ovstest test-ovn parse-expr < input.txt], [0], [expout])
366 AT_SETUP([ovn -- expression annotation])
367 dnl Input precedes =>, expected output follows =>.
368 dnl Empty lines and lines starting with # are ignored.
369 AT_DATA([test-cases.txt], [[
370 ip4.src == 1.2.3.4 => ip4.src == 0x1020304 && eth.type == 0x800
371 ip4.src != 1.2.3.4 => ip4.src != 0x1020304 && eth.type == 0x800
372 ip.proto == 123 => ip.proto == 0x7b && (eth.type == 0x800 || eth.type == 0x86dd)
373 ip.proto == {123, 234} => (ip.proto == 0x7b || ip.proto == 0xea) && (eth.type == 0x800 || eth.type == 0x86dd)
374 ip4.src == 1.2.3.4 && ip4.dst == 5.6.7.8 => ip4.src == 0x1020304 && eth.type == 0x800 && ip4.dst == 0x5060708 && eth.type == 0x800
376 # Nested expressions over a single symbol should be annotated with symbol's
377 # prerequisites only once, at the top level.
378 tcp.dst == 1 || (tcp.dst >= 2 && tcp.dst <= 3) => (tcp.dst == 0x1 || (tcp.dst >= 0x2 && tcp.dst <= 0x3)) && ip.proto == 0x6 && (eth.type == 0x800 || eth.type == 0x86dd)
380 ip => eth.type == 0x800 || eth.type == 0x86dd
381 ip == 1 => eth.type == 0x800 || eth.type == 0x86dd
382 ip[0] == 1 => eth.type == 0x800 || eth.type == 0x86dd
383 ip > 0 => Only == and != operators may be used with nominal field ip.
384 !ip => Nominal predicate ip may only be tested positively, e.g. `ip' or `ip == 1' but not `!ip' or `ip == 0'.
385 ip == 0 => Nominal predicate ip may only be tested positively, e.g. `ip' or `ip == 1' but not `!ip' or `ip == 0'.
387 vlan.present => vlan.tci[12]
388 !vlan.present => !vlan.tci[12]
390 !vlan.pcp => vlan.tci[13..15] == 0 && vlan.tci[12]
391 vlan.pcp == 1 && vlan.vid == 2 => vlan.tci[13..15] == 0x1 && vlan.tci[12] && vlan.tci[0..11] == 0x2 && vlan.tci[12]
392 !reg0 && !reg1 && !reg2 && !reg3 => xxreg0[96..127] == 0 && xxreg0[64..95] == 0 && xxreg0[32..63] == 0 && xxreg0[0..31] == 0
394 ip.first_frag => ip.frag[0] && (eth.type == 0x800 || eth.type == 0x86dd) && (!ip.frag[1] || (eth.type != 0x800 && eth.type != 0x86dd))
395 !ip.first_frag => !ip.frag[0] || (eth.type != 0x800 && eth.type != 0x86dd) || (ip.frag[1] && (eth.type == 0x800 || eth.type == 0x86dd))
396 ip.later_frag => ip.frag[1] && (eth.type == 0x800 || eth.type == 0x86dd)
398 bad_prereq != 0 => Error parsing expression `xyzzy' encountered as prerequisite or predicate of initial expression: Syntax error at `xyzzy' expecting field name.
399 self_recurse != 0 => Error parsing expression `self_recurse != 0' encountered as prerequisite or predicate of initial expression: Recursive expansion of symbol `self_recurse'.
400 mutual_recurse_1 != 0 => Error parsing expression `mutual_recurse_2 != 0' encountered as prerequisite or predicate of initial expression: Error parsing expression `mutual_recurse_1 != 0' encountered as prerequisite or predicate of initial expression: Recursive expansion of symbol `mutual_recurse_1'.
401 mutual_recurse_2 != 0 => Error parsing expression `mutual_recurse_1 != 0' encountered as prerequisite or predicate of initial expression: Error parsing expression `mutual_recurse_2 != 0' encountered as prerequisite or predicate of initial expression: Recursive expansion of symbol `mutual_recurse_2'.
403 sed 's/ =>.*//' test-cases.txt > input.txt
404 sed 's/.* => //' test-cases.txt > expout
405 AT_CHECK([ovstest test-ovn annotate-expr < input.txt], [0], [expout])
408 AT_SETUP([ovn -- 1-term expression conversion])
409 AT_CHECK([ovstest test-ovn exhaustive --operation=convert 1], [0],
410 [Tested converting all 1-terminal expressions with 2 numeric vars (each 3 bits) in terms of operators == != < <= > >= and 2 string vars.
414 AT_SETUP([ovn -- 2-term expression conversion])
415 AT_CHECK([ovstest test-ovn exhaustive --operation=convert 2], [0],
416 [Tested converting 578 expressions of 2 terminals with 2 numeric vars (each 3 bits) in terms of operators == != < <= > >= and 2 string vars.
420 AT_SETUP([ovn -- 3-term expression conversion])
421 AT_CHECK([ovstest test-ovn exhaustive --operation=convert --bits=2 3], [0],
422 [Tested converting 67410 expressions of 3 terminals with 2 numeric vars (each 2 bits) in terms of operators == != < <= > >= and 2 string vars.
426 AT_SETUP([ovn -- 3-term numeric expression simplification])
427 AT_CHECK([ovstest test-ovn exhaustive --operation=simplify --nvars=2 --svars=0 3], [0],
428 [Tested simplifying 490770 expressions of 3 terminals with 2 numeric vars (each 3 bits) in terms of operators == != < <= > >=.
432 AT_SETUP([ovn -- 4-term string expression simplification])
433 AT_CHECK([ovstest test-ovn exhaustive --operation=simplify --nvars=0 --svars=4 4], [0],
434 [Tested simplifying 21978 expressions of 4 terminals with 4 string vars.
438 AT_SETUP([ovn -- 3-term mixed expression simplification])
439 AT_CHECK([ovstest test-ovn exhaustive --operation=simplify --nvars=1 --svars=1 3], [0],
440 [Tested simplifying 127890 expressions of 3 terminals with 1 numeric vars (each 3 bits) in terms of operators == != < <= > >= and 1 string vars.
444 AT_SETUP([ovn -- simplification special cases])
446 echo "$1" | ovstest test-ovn simplify-expr
448 AT_CHECK([simplify 'eth.dst == 0/0'], [0], [1
450 AT_CHECK([simplify 'eth.dst != 0/0'], [0], [0
452 AT_CHECK([simplify 'tcp.dst >= 0'], [0],
453 [ip.proto == 0x6 && (eth.type == 0x800 || eth.type == 0x86dd)
455 AT_CHECK([simplify 'tcp.dst <= 65535'], [0],
456 [ip.proto == 0x6 && (eth.type == 0x800 || eth.type == 0x86dd)
458 AT_CHECK([simplify 'tcp.dst > 0'], [0],
459 [[(tcp.dst[0] || tcp.dst[1] || tcp.dst[2] || tcp.dst[3] || tcp.dst[4] || tcp.dst[5] || tcp.dst[6] || tcp.dst[7] || tcp.dst[8] || tcp.dst[9] || tcp.dst[10] || tcp.dst[11] || tcp.dst[12] || tcp.dst[13] || tcp.dst[14] || tcp.dst[15]) && ip.proto == 0x6 && (eth.type == 0x800 || eth.type == 0x86dd)
461 AT_CHECK([simplify 'tcp.dst < 65535'], [0],
462 [[(!tcp.dst[0] || !tcp.dst[1] || !tcp.dst[2] || !tcp.dst[3] || !tcp.dst[4] || !tcp.dst[5] || !tcp.dst[6] || !tcp.dst[7] || !tcp.dst[8] || !tcp.dst[9] || !tcp.dst[10] || !tcp.dst[11] || !tcp.dst[12] || !tcp.dst[13] || !tcp.dst[14] || !tcp.dst[15]) && ip.proto == 0x6 && (eth.type == 0x800 || eth.type == 0x86dd)
466 AT_SETUP([ovn -- is_chassis_resident simplification])
468 echo "$1" | ovstest test-ovn simplify-expr
470 AT_CHECK([simplify 'is_chassis_resident("eth1")'], [0], [1
472 AT_CHECK([simplify 'is_chassis_resident("eth2")'], [0], [0
474 AT_CHECK([simplify '!is_chassis_resident("eth1")'], [0], [0
476 AT_CHECK([simplify '!is_chassis_resident("eth2")'], [0], [1
480 AT_SETUP([ovn -- 4-term numeric expression normalization])
481 AT_CHECK([ovstest test-ovn exhaustive --operation=normalize --nvars=3 --svars=0 --bits=1 4], [0],
482 [Tested normalizing 1874026 expressions of 4 terminals with 3 numeric vars (each 1 bits) in terms of operators == != < <= > >=.
486 AT_SETUP([ovn -- 4-term string expression normalization])
487 AT_CHECK([ovstest test-ovn exhaustive --operation=normalize --nvars=0 --svars=3 --bits=1 4], [0],
488 [Tested normalizing 11242 expressions of 4 terminals with 3 string vars.
492 AT_SETUP([ovn -- 4-term mixed expression normalization])
493 AT_CHECK([ovstest test-ovn exhaustive --operation=normalize --nvars=1 --bits=1 --svars=2 4], [0],
494 [Tested normalizing 175978 expressions of 4 terminals with 1 numeric vars (each 1 bits) in terms of operators == != < <= > >= and 2 string vars.
498 AT_SETUP([ovn -- 5-term numeric expression normalization])
499 AT_CHECK([ovstest test-ovn exhaustive --operation=normalize --nvars=3 --svars=0 --bits=1 --relops='==' 5], [0],
500 [Tested normalizing 1317600 expressions of 5 terminals with 3 numeric vars (each 1 bits) in terms of operators ==.
504 AT_SETUP([ovn -- 5-term string expression normalization])
505 AT_CHECK([ovstest test-ovn exhaustive --operation=normalize --nvars=0 --svars=3 --bits=1 --relops='==' 5], [0],
506 [Tested normalizing 368550 expressions of 5 terminals with 3 string vars.
510 AT_SETUP([ovn -- 5-term mixed expression normalization])
511 AT_CHECK([ovstest test-ovn exhaustive --operation=normalize --nvars=1 --svars=1 --bits=1 --relops='==' 5], [0],
512 [Tested normalizing 216000 expressions of 5 terminals with 1 numeric vars (each 1 bits) in terms of operators == and 1 string vars.
516 AT_SETUP([ovn -- 4-term numeric expressions to flows])
517 AT_KEYWORDS([expression])
518 AT_CHECK([ovstest test-ovn exhaustive --operation=flow --nvars=2 --svars=0 --bits=2 --relops='==' 4], [0],
519 [Tested converting to flows 175978 expressions of 4 terminals with 2 numeric vars (each 2 bits) in terms of operators ==.
523 AT_SETUP([ovn -- 4-term string expressions to flows])
524 AT_KEYWORDS([expression])
525 AT_CHECK([ovstest test-ovn exhaustive --operation=flow --nvars=0 --svars=4 4], [0],
526 [Tested converting to flows 21978 expressions of 4 terminals with 4 string vars.
530 AT_SETUP([ovn -- 4-term mixed expressions to flows])
531 AT_KEYWORDS([expression])
532 AT_CHECK([ovstest test-ovn exhaustive --operation=flow --nvars=1 --bits=2 --svars=1 --relops='==' 4], [0],
533 [Tested converting to flows 48312 expressions of 4 terminals with 1 numeric vars (each 2 bits) in terms of operators == and 1 string vars.
537 AT_SETUP([ovn -- 3-term numeric expressions to flows])
538 AT_KEYWORDS([expression])
539 AT_CHECK([ovstest test-ovn exhaustive --operation=flow --nvars=3 --svars=0 --bits=3 --relops='==' 3], [0],
540 [Tested converting to flows 41328 expressions of 3 terminals with 3 numeric vars (each 3 bits) in terms of operators ==.
544 AT_SETUP([ovn -- converting expressions to flows -- string fields])
545 AT_KEYWORDS([expression])
547 echo "$1" | ovstest test-ovn expr-to-flows | sort
549 AT_CHECK([expr_to_flow 'inport == "eth0"'], [0], [reg14=0x5
551 AT_CHECK([expr_to_flow 'inport == "eth1"'], [0], [reg14=0x6
553 AT_CHECK([expr_to_flow 'inport == "eth2"'], [0], [(no flows)
555 AT_CHECK([expr_to_flow 'inport == "eth0" && ip'], [0], [dnl
559 AT_CHECK([expr_to_flow 'inport == "eth1" && ip'], [0], [dnl
563 AT_CHECK([expr_to_flow 'inport == "eth2" && ip'], [0], [(no flows)
565 AT_CHECK([expr_to_flow 'inport == {"eth0", "eth1", "eth2", "LOCAL"}'], [0],
570 AT_CHECK([expr_to_flow 'inport == {"eth0", "eth1", "eth2"} && ip'], [0], [dnl
576 AT_CHECK([expr_to_flow 'inport == "eth0" && inport == "eth1"'], [0], [dnl
581 AT_SETUP([ovn -- converting expressions to flows -- address sets])
582 AT_KEYWORDS([expression])
584 echo "$1" | ovstest test-ovn expr-to-flows | sort
586 AT_CHECK([expr_to_flow 'ip4.src == {10.0.0.1, 10.0.0.2, 10.0.0.3}'], [0], [dnl
591 AT_CHECK([expr_to_flow 'ip4.src == $set1'], [0], [dnl
596 AT_CHECK([expr_to_flow 'ip4.src == {1.2.3.4, $set1}'], [0], [dnl
602 AT_CHECK([expr_to_flow 'ip4.src == {1.2.0.0/20, 5.5.5.0/24, $set1}'], [0], [dnl
609 AT_CHECK([expr_to_flow 'ip6.src == {::1, ::2, ::3}'], [0], [dnl
614 AT_CHECK([expr_to_flow 'ip6.src == {::1, $set2, ::4}'], [0], [dnl
620 AT_CHECK([expr_to_flow 'eth.src == {00:00:00:00:00:01, 00:00:00:00:00:02, 00:00:00:00:00:03}'], [0], [dnl
621 dl_src=00:00:00:00:00:01
622 dl_src=00:00:00:00:00:02
623 dl_src=00:00:00:00:00:03
625 AT_CHECK([expr_to_flow 'eth.src == {$set3}'], [0], [dnl
626 dl_src=00:00:00:00:00:01
627 dl_src=00:00:00:00:00:02
628 dl_src=00:00:00:00:00:03
630 AT_CHECK([expr_to_flow 'eth.src == {00:00:00:00:00:01, $set3, ba:be:be:ef:de:ad, $set3}'], [0], [dnl
631 dl_src=00:00:00:00:00:01
632 dl_src=00:00:00:00:00:02
633 dl_src=00:00:00:00:00:03
634 dl_src=ba:be:be:ef:de:ad
636 AT_CHECK([expr_to_flow 'ip4.src == {$set4}'], [0], [dnl
639 AT_CHECK([expr_to_flow 'ip4.src == {1.2.3.4, $set4}'], [0], [dnl
642 AT_CHECK([expr_to_flow 'ip4.src == 1.2.3.4 || ip4.src == {$set4}'], [0], [dnl
645 AT_CHECK([expr_to_flow 'ip4.src != {$set4}'], [0], [dnl
648 AT_CHECK([expr_to_flow 'ip4.src != {1.0.0.0/8, $set4}'], [0], [dnl
649 ip,nw_src=0.0.0.0/1.0.0.0
650 ip,nw_src=128.0.0.0/1
651 ip,nw_src=16.0.0.0/16.0.0.0
652 ip,nw_src=2.0.0.0/2.0.0.0
653 ip,nw_src=32.0.0.0/32.0.0.0
654 ip,nw_src=4.0.0.0/4.0.0.0
655 ip,nw_src=64.0.0.0/64.0.0.0
656 ip,nw_src=8.0.0.0/8.0.0.0
658 AT_CHECK([expr_to_flow 'ip4.src != 1.0.0.0/8 && ip4.src != {$set4}'], [0], [dnl
659 ip,nw_src=0.0.0.0/1.0.0.0
660 ip,nw_src=128.0.0.0/1
661 ip,nw_src=16.0.0.0/16.0.0.0
662 ip,nw_src=2.0.0.0/2.0.0.0
663 ip,nw_src=32.0.0.0/32.0.0.0
664 ip,nw_src=4.0.0.0/4.0.0.0
665 ip,nw_src=64.0.0.0/64.0.0.0
666 ip,nw_src=8.0.0.0/8.0.0.0
670 AT_SETUP([ovn -- converting expressions to flows -- port groups])
671 AT_KEYWORDS([expression])
673 echo "$1" | ovstest test-ovn expr-to-flows | sort
675 AT_CHECK([expr_to_flow 'outport == @pg1'], [0], [dnl
680 AT_CHECK([expr_to_flow 'outport == {@pg_empty}'], [0], [dnl
683 AT_CHECK([expr_to_flow 'outport == {"lsp1", @pg_empty}'], [0], [dnl
688 AT_SETUP([ovn -- converting expressions to flows -- conjunction])
689 AT_KEYWORDS([conjunction])
691 echo "$1" | ovstest test-ovn expr-to-flows | sort
694 lflow="ip4.src == {10.0.0.1, 10.0.0.2, 10.0.0.3} && \
695 ip4.dst == {20.0.0.1, 20.0.0.2, 20.0.0.3}"
696 AT_CHECK([expr_to_flow "$lflow"], [0], [dnl
698 ip,nw_dst=20.0.0.1: conjunction(1, 0/2)
699 ip,nw_dst=20.0.0.2: conjunction(1, 0/2)
700 ip,nw_dst=20.0.0.3: conjunction(1, 0/2)
701 ip,nw_src=10.0.0.1: conjunction(1, 1/2)
702 ip,nw_src=10.0.0.2: conjunction(1, 1/2)
703 ip,nw_src=10.0.0.3: conjunction(1, 1/2)
706 lflow="ip && (!ct.est || (ct.est && ct_label.blocked == 1))"
707 AT_CHECK([expr_to_flow "$lflow"], [0], [dnl
708 ct_state=+est+trk,ct_label=0x1/0x1,ip
709 ct_state=+est+trk,ct_label=0x1/0x1,ipv6
711 ct_state=-est+trk,ipv6
714 lflow="ip4.src == {10.0.0.1, 10.0.0.2, 10.0.0.3} && \
715 ip4.dst == {20.0.0.1, 20.0.0.2}"
716 AT_CHECK([expr_to_flow "$lflow"], [0], [dnl
718 ip,nw_dst=20.0.0.1: conjunction(1, 0/2)
719 ip,nw_dst=20.0.0.2: conjunction(1, 0/2)
720 ip,nw_src=10.0.0.1: conjunction(1, 1/2)
721 ip,nw_src=10.0.0.2: conjunction(1, 1/2)
722 ip,nw_src=10.0.0.3: conjunction(1, 1/2)
725 lflow="ip4 && ip4.src == {10.0.0.1, 10.0.0.2, 10.0.0.3} && \
726 ip4.dst == {20.0.0.1, 20.0.0.2, 20.0.0.3} && \
727 tcp.dst >= 1000 && tcp.dst <= 1010"
729 AT_CHECK([expr_to_flow "$lflow"], [0], [dnl
731 tcp,nw_dst=20.0.0.1: conjunction(1, 0/3)
732 tcp,nw_dst=20.0.0.2: conjunction(1, 0/3)
733 tcp,nw_dst=20.0.0.3: conjunction(1, 0/3)
734 tcp,nw_src=10.0.0.1: conjunction(1, 1/3)
735 tcp,nw_src=10.0.0.2: conjunction(1, 1/3)
736 tcp,nw_src=10.0.0.3: conjunction(1, 1/3)
737 tcp,tp_dst=0x3ea/0xfffe: conjunction(1, 2/3)
738 tcp,tp_dst=0x3ec/0xfffc: conjunction(1, 2/3)
739 tcp,tp_dst=0x3f0/0xfffe: conjunction(1, 2/3)
740 tcp,tp_dst=1000: conjunction(1, 2/3)
741 tcp,tp_dst=1001: conjunction(1, 2/3)
742 tcp,tp_dst=1010: conjunction(1, 2/3)
745 lflow="ip4 && ip4.src == {10.0.0.4, 10.0.0.5, 10.0.0.6} && \
746 ((ip4.dst == {20.0.0.4, 20.0.0.7, 20.0.0.8} && tcp.dst >= 1000 && \
747 tcp.dst <= 2000 && tcp.src >=1000 && tcp.src <= 2000) \
748 || ip4.dst == 20.0.0.5 || ip4.dst == 20.0.0.6)"
750 AT_CHECK([expr_to_flow "$lflow"], [0], [dnl
752 ip,nw_src=10.0.0.4,nw_dst=20.0.0.5
753 ip,nw_src=10.0.0.4,nw_dst=20.0.0.6
754 ip,nw_src=10.0.0.5,nw_dst=20.0.0.5
755 ip,nw_src=10.0.0.5,nw_dst=20.0.0.6
756 ip,nw_src=10.0.0.6,nw_dst=20.0.0.5
757 ip,nw_src=10.0.0.6,nw_dst=20.0.0.6
758 tcp,nw_dst=20.0.0.4: conjunction(1, 0/4)
759 tcp,nw_dst=20.0.0.7: conjunction(1, 0/4)
760 tcp,nw_dst=20.0.0.8: conjunction(1, 0/4)
761 tcp,nw_src=10.0.0.4: conjunction(1, 1/4)
762 tcp,nw_src=10.0.0.5: conjunction(1, 1/4)
763 tcp,nw_src=10.0.0.6: conjunction(1, 1/4)
764 tcp,tp_dst=0x3ea/0xfffe: conjunction(1, 2/4)
765 tcp,tp_dst=0x3ec/0xfffc: conjunction(1, 2/4)
766 tcp,tp_dst=0x3f0/0xfff0: conjunction(1, 2/4)
767 tcp,tp_dst=0x400/0xfe00: conjunction(1, 2/4)
768 tcp,tp_dst=0x600/0xff00: conjunction(1, 2/4)
769 tcp,tp_dst=0x700/0xff80: conjunction(1, 2/4)
770 tcp,tp_dst=0x780/0xffc0: conjunction(1, 2/4)
771 tcp,tp_dst=0x7c0/0xfff0: conjunction(1, 2/4)
772 tcp,tp_dst=1000: conjunction(1, 2/4)
773 tcp,tp_dst=1001: conjunction(1, 2/4)
774 tcp,tp_dst=2000: conjunction(1, 2/4)
775 tcp,tp_src=0x3ea/0xfffe: conjunction(1, 3/4)
776 tcp,tp_src=0x3ec/0xfffc: conjunction(1, 3/4)
777 tcp,tp_src=0x3f0/0xfff0: conjunction(1, 3/4)
778 tcp,tp_src=0x400/0xfe00: conjunction(1, 3/4)
779 tcp,tp_src=0x600/0xff00: conjunction(1, 3/4)
780 tcp,tp_src=0x700/0xff80: conjunction(1, 3/4)
781 tcp,tp_src=0x780/0xffc0: conjunction(1, 3/4)
782 tcp,tp_src=0x7c0/0xfff0: conjunction(1, 3/4)
783 tcp,tp_src=1000: conjunction(1, 3/4)
784 tcp,tp_src=1001: conjunction(1, 3/4)
785 tcp,tp_src=2000: conjunction(1, 3/4)
789 AT_SETUP([ovn -- action parsing])
790 dnl Unindented text is input (a set of OVN logical actions).
791 dnl Indented text is expected output.
792 AT_DATA([test-cases.txt],
797 Syntax error at `next' expecting end of input.
799 Syntax error at `drop' expecting action.
803 encodes as resubmit(,64)
807 encodes as resubmit(,19)
810 encodes as resubmit(,19)
812 encodes as resubmit(,8)
814 encodes as resubmit(,31)
817 Syntax error at `)' expecting "pipeline" or "table".
819 Syntax error at `;' expecting `)'.
821 "next" action cannot advance beyond table 23.
825 encodes as resubmit(,19)
826 next(pipeline=ingress);
828 encodes as resubmit(,19)
829 next(table=11, pipeline=ingress);
831 encodes as resubmit(,19)
832 next(pipeline=ingress, table=11);
834 encodes as resubmit(,19)
836 next(pipeline=egress);
837 "next" action cannot advance from ingress to egress pipeline (use "output" action instead)
841 encodes as resubmit(,18)
843 # Loading a constant value.
845 formats as tcp.dst = 80;
846 encodes as set_field:80->tcp_dst
847 has prereqs ip.proto == 0x6 && (eth.type == 0x800 || eth.type == 0x86dd)
849 encodes as set_field:01:00:00:00:00:00/01:00:00:00:00:00->eth_dst
851 encodes as set_field:0x4000/0xe000->vlan_tci
852 has prereqs vlan.tci[12]
853 vlan.tci[13..15] = 2;
854 encodes as set_field:0x4000/0xe000->vlan_tci
856 encodes as set_field:0->reg14
858 formats as ip.ttl = 4;
859 encodes as set_field:4->nw_ttl
860 has prereqs eth.type == 0x800 || eth.type == 0x86dd
861 outport="eth0"; next; outport="LOCAL"; next;
862 formats as outport = "eth0"; next; outport = "LOCAL"; next;
863 encodes as set_field:0x5->reg15,resubmit(,19),set_field:0xfffe->reg15,resubmit(,19)
866 Cannot select subfield of string field inport.
868 Cannot select subfield of nominal field ip.proto.
870 Syntax error at `==' expecting `=' or `<->'.
872 Predicate symbol ip used where lvalue required.
874 Field ip.proto is not modifiable.
876 Syntax error at `{' expecting constant.
878 Syntax error at `{' expecting constant.
880 Error parsing expression `xyzzy' encountered as prerequisite or predicate of initial expression: Syntax error at `xyzzy' expecting field name.
882 Error parsing expression `self_recurse != 0' encountered as prerequisite or predicate of initial expression: Error parsing expression `self_recurse != 0' encountered as prerequisite or predicate of initial expression: Recursive expansion of symbol `self_recurse'.
884 Predicate symbol vlan.present used where lvalue required.
886 # Moving one field into another.
888 formats as reg0 = reg1;
889 encodes as move:NXM_NX_XXREG0[64..95]->NXM_NX_XXREG0[96..127]
890 vlan.pcp = reg0[0..2];
891 encodes as move:NXM_NX_XXREG0[96..98]->NXM_OF_VLAN_TCI[13..15]
892 has prereqs vlan.tci[12]
893 reg0[10] = vlan.pcp[1];
894 encodes as move:NXM_OF_VLAN_TCI[14]->NXM_NX_XXREG0[106]
895 has prereqs vlan.tci[12]
897 encodes as move:NXM_NX_REG14[]->NXM_NX_REG15[]
899 reg0[0] = vlan.present;
900 Predicate symbol vlan.present used where lvalue required.
902 Can't assign 11-bit value to 32-bit destination.
904 Can't assign integer field (reg0) to string field (inport).
906 String fields inport and big_string are incompatible for assignment.
907 ip.proto = reg0[0..7];
908 Field ip.proto is not modifiable.
912 encodes as push:NXM_NX_XXREG0[64..95],push:NXM_NX_XXREG0[96..127],pop:NXM_NX_XXREG0[64..95],pop:NXM_NX_XXREG0[96..127]
913 vlan.pcp <-> reg0[0..2];
914 encodes as push:NXM_NX_XXREG0[96..98],push:NXM_OF_VLAN_TCI[13..15],pop:NXM_NX_XXREG0[96..98],pop:NXM_OF_VLAN_TCI[13..15]
915 has prereqs vlan.tci[12]
916 reg0[10] <-> vlan.pcp[1];
917 encodes as push:NXM_OF_VLAN_TCI[14],push:NXM_NX_XXREG0[106],pop:NXM_OF_VLAN_TCI[14],pop:NXM_NX_XXREG0[106]
918 has prereqs vlan.tci[12]
920 encodes as push:NXM_NX_REG14[],push:NXM_NX_REG15[],pop:NXM_NX_REG14[],pop:NXM_NX_REG15[]
922 reg0[0] <-> vlan.present;
923 Predicate symbol vlan.present used where lvalue required.
924 reg0 <-> reg1[0..10];
925 Can't exchange 32-bit field with 11-bit field.
927 Can't exchange string field (inport) with integer field (reg0).
928 inport <-> big_string;
929 String fields inport and big_string are incompatible for exchange.
930 ip.proto <-> reg0[0..7];
931 Field ip.proto is not modifiable.
932 reg0[0..7] <-> ip.proto;
933 Field ip.proto is not modifiable.
940 Syntax error at end of input expecting `--'.
944 encodes as ct(table=19,zone=NXM_NX_REG13[0..15],nat)
948 encodes as ct(table=19,zone=NXM_NX_REG13[0..15],nat)
950 ct_lb(192.168.1.2:80, 192.168.1.3:80);
953 ct_lb(192.168.1.2, 192.168.1.3, );
954 formats as ct_lb(192.168.1.2, 192.168.1.3);
957 ct_lb(fd0f::2, fd0f::3, );
958 formats as ct_lb(fd0f::2, fd0f::3);
963 Syntax error at `)' expecting port number.
964 ct_lb(192.168.1.2:123456);
965 Syntax error at `123456' expecting port number.
967 Syntax error at `foo' expecting IP address.
968 ct_lb([192.168.1.2]);
969 Syntax error at `192.168.1.2' expecting IPv6 address.
973 encodes as ct(table=19,zone=NXM_NX_REG13[0..15])
978 encodes as ct(commit,zone=NXM_NX_REG13[0..15])
981 formats as ct_commit;
982 encodes as ct(commit,zone=NXM_NX_REG13[0..15])
984 ct_commit(ct_mark=1);
985 formats as ct_commit(ct_mark=0x1);
986 encodes as ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x1->ct_mark))
988 ct_commit(ct_mark=1/1);
989 formats as ct_commit(ct_mark=0x1/0x1);
990 encodes as ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x1/0x1->ct_mark))
992 ct_commit(ct_label=1);
993 formats as ct_commit(ct_label=0x1);
994 encodes as ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x1->ct_label))
996 ct_commit(ct_label=1/1);
997 formats as ct_commit(ct_label=0x1/0x1);
998 encodes as ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x1/0x1->ct_label))
1000 ct_commit(ct_mark=1, ct_label=2);
1001 formats as ct_commit(ct_mark=0x1, ct_label=0x2);
1002 encodes as ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x1->ct_mark,set_field:0x2->ct_label))
1005 ct_commit(ct_label=0x01020304050607080910111213141516);
1006 formats as ct_commit(ct_label=0x1020304050607080910111213141516);
1007 encodes as ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x1020304050607080910111213141516->ct_label))
1009 ct_commit(ct_label=0x181716151413121110090807060504030201);
1010 formats as ct_commit(ct_label=0x16151413121110090807060504030201);
1011 encodes as ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x16151413121110090807060504030201->ct_label))
1013 ct_commit(ct_label=0x1000000000000000000000000000000/0x1000000000000000000000000000000);
1014 encodes as ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x1000000000000000000000000000000/0x1000000000000000000000000000000->ct_label))
1016 ct_commit(ct_label=18446744073709551615);
1017 formats as ct_commit(ct_label=0xffffffffffffffff);
1018 encodes as ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0xffffffffffffffff->ct_label))
1020 ct_commit(ct_label=18446744073709551616);
1021 Decimal constants must be less than 2**64.
1025 encodes as ct(table=19,zone=NXM_NX_REG11[0..15],nat)
1027 ct_dnat(192.168.1.2);
1028 encodes as ct(commit,table=19,zone=NXM_NX_REG11[0..15],nat(dst=192.168.1.2))
1031 ct_dnat(192.168.1.2, 192.168.1.3);
1032 Syntax error at `,' expecting `)'.
1034 Syntax error at `foo' expecting IPv4 address.
1036 Syntax error at `foo' expecting IPv4 address.
1038 Syntax error at `)' expecting IPv4 address.
1042 encodes as ct(table=19,zone=NXM_NX_REG12[0..15],nat)
1044 ct_snat(192.168.1.2);
1045 encodes as ct(commit,table=19,zone=NXM_NX_REG12[0..15],nat(src=192.168.1.2))
1048 ct_snat(192.168.1.2, 192.168.1.3);
1049 Syntax error at `,' expecting `)'.
1051 Syntax error at `foo' expecting IPv4 address.
1053 Syntax error at `foo' expecting IPv4 address.
1055 Syntax error at `)' expecting IPv4 address.
1062 clone { ip4.dst = 255.255.255.255; output; }; next;
1063 encodes as clone(set_field:255.255.255.255->ip_dst,resubmit(,64)),resubmit(,19)
1064 has prereqs eth.type == 0x800
1067 arp { eth.dst = ff:ff:ff:ff:ff:ff; output; }; output;
1068 encodes as controller(userdata=00.00.00.00.00.00.00.00.00.19.00.10.80.00.06.06.ff.ff.ff.ff.ff.ff.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00),resubmit(,64)
1071 formats as arp { drop; };
1072 encodes as controller(userdata=00.00.00.00.00.00.00.00)
1076 get_arp(outport, ip4.dst);
1077 encodes as push:NXM_NX_REG0[],push:NXM_OF_IP_DST[],pop:NXM_NX_REG0[],set_field:00:00:00:00:00:00->eth_dst,resubmit(,65),pop:NXM_NX_REG0[]
1078 has prereqs eth.type == 0x800
1079 get_arp(inport, reg0);
1080 encodes as push:NXM_NX_REG15[],push:NXM_NX_REG0[],push:NXM_NX_XXREG0[96..127],push:NXM_NX_REG14[],pop:NXM_NX_REG15[],pop:NXM_NX_REG0[],set_field:00:00:00:00:00:00->eth_dst,resubmit(,65),pop:NXM_NX_REG0[],pop:NXM_NX_REG15[]
1083 Syntax error at `;' expecting `('.
1085 Syntax error at `)' expecting field name.
1087 Syntax error at `)' expecting `,'.
1088 get_arp(inport ip4.dst);
1089 Syntax error at `ip4.dst' expecting `,'.
1090 get_arp(inport, ip4.dst;
1091 Syntax error at `;' expecting `)'.
1092 get_arp(inport, eth.dst);
1093 Cannot use 48-bit field eth.dst[0..47] where 32-bit field is required.
1094 get_arp(inport, outport);
1095 Cannot use string field outport where numeric field is required.
1096 get_arp(reg0, ip4.dst);
1097 Cannot use numeric field reg0 where string field is required.
1100 put_arp(inport, arp.spa, arp.sha);
1101 encodes as push:NXM_NX_REG0[],push:NXM_OF_ETH_SRC[],push:NXM_NX_ARP_SHA[],push:NXM_OF_ARP_SPA[],pop:NXM_NX_REG0[],pop:NXM_OF_ETH_SRC[],controller(userdata=00.00.00.01.00.00.00.00),pop:NXM_OF_ETH_SRC[],pop:NXM_NX_REG0[]
1102 has prereqs eth.type == 0x806 && eth.type == 0x806
1105 reg1[0] = put_dhcp_opts(offerip = 1.2.3.4, router = 10.0.0.1);
1106 encodes as controller(userdata=00.00.00.02.00.00.00.00.00.01.de.10.00.00.00.40.01.02.03.04.03.04.0a.00.00.01,pause)
1107 reg2[5] = put_dhcp_opts(offerip=10.0.0.4,router=10.0.0.1,netmask=255.255.254.0,mtu=1400,domain="ovn.org",wpad="https://example.org",bootfile_name="https://127.0.0.1/boot.ipxe",path_prefix="/tftpboot");
1108 formats as reg2[5] = put_dhcp_opts(offerip = 10.0.0.4, router = 10.0.0.1, netmask = 255.255.254.0, mtu = 1400, domain = "ovn.org", wpad = "https://example.org", bootfile_name = "https://127.0.0.1/boot.ipxe", path_prefix = "/tftpboot");
1109 encodes as controller(userdata=00.00.00.02.00.00.00.00.00.01.de.10.00.00.00.25.0a.00.00.04.03.04.0a.00.00.01.01.04.ff.ff.fe.00.1a.02.05.78.0f.07.6f.76.6e.2e.6f.72.67.fc.13.68.74.74.70.73.3a.2f.2f.65.78.61.6d.70.6c.65.2e.6f.72.67.43.1b.68.74.74.70.73.3a.2f.2f.31.32.37.2e.30.2e.30.2e.31.2f.62.6f.6f.74.2e.69.70.78.65.d2.09.2f.74.66.74.70.62.6f.6f.74,pause)
1110 reg0[15] = put_dhcp_opts(offerip=10.0.0.4,router=10.0.0.1,netmask=255.255.255.0,mtu=1400,ip_forward_enable=1,default_ttl=121,dns_server={8.8.8.8,7.7.7.7},classless_static_route={30.0.0.0/24,10.0.0.4,40.0.0.0/16,10.0.0.6,0.0.0.0/0,10.0.0.1},ethernet_encap=1,router_discovery=0,tftp_server_address={10.0.0.4,10.0.0.5});
1111 formats as reg0[15] = put_dhcp_opts(offerip = 10.0.0.4, router = 10.0.0.1, netmask = 255.255.255.0, mtu = 1400, ip_forward_enable = 1, default_ttl = 121, dns_server = {8.8.8.8, 7.7.7.7}, classless_static_route = {30.0.0.0/24, 10.0.0.4, 40.0.0.0/16, 10.0.0.6, 0.0.0.0/0, 10.0.0.1}, ethernet_encap = 1, router_discovery = 0, tftp_server_address = {10.0.0.4, 10.0.0.5});
1112 encodes as controller(userdata=00.00.00.02.00.00.00.00.00.01.de.10.00.00.00.6f.0a.00.00.04.03.04.0a.00.00.01.01.04.ff.ff.ff.00.1a.02.05.78.13.01.01.17.01.79.06.08.08.08.08.08.07.07.07.07.79.14.18.1e.00.00.0a.00.00.04.10.28.00.0a.00.00.06.00.0a.00.00.01.24.01.01.1f.01.00.96.08.0a.00.00.04.0a.00.00.05,pause)
1114 reg1[0..1] = put_dhcp_opts(offerip = 1.2.3.4, router = 10.0.0.1);
1115 Cannot use 2-bit field reg1[0..1] where 1-bit field is required.
1116 reg1[0] = put_dhcp_opts();
1117 put_dhcp_opts requires offerip to be specified.
1118 reg1[0] = put_dhcp_opts(x = 1.2.3.4, router = 10.0.0.1);
1119 Syntax error at `x' expecting DHCPv4 option name.
1120 reg1[0] = put_dhcp_opts(router = 10.0.0.1);
1121 put_dhcp_opts requires offerip to be specified.
1122 reg1[0] = put_dhcp_opts(offerip=1.2.3.4, "hi");
1123 Syntax error at `"hi"'.
1124 reg1[0] = put_dhcp_opts(offerip=1.2.3.4, xyzzy);
1125 Syntax error at `xyzzy' expecting DHCPv4 option name.
1126 reg1[0] = put_dhcp_opts(offerip="xyzzy");
1127 DHCPv4 option offerip requires numeric value.
1128 reg1[0] = put_dhcp_opts(offerip=1.2.3.4, domain=1.2.3.4);
1129 DHCPv4 option domain requires string value.
1132 nd_ns { nd.target = xxreg0; output; };
1133 encodes as controller(userdata=00.00.00.09.00.00.00.00.ff.ff.00.18.00.00.23.20.00.06.00.80.00.00.00.00.00.01.de.10.00.01.2e.10.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00)
1137 formats as nd_ns { drop; };
1138 encodes as controller(userdata=00.00.00.09.00.00.00.00)
1142 nd_na { eth.src = 12:34:56:78:9a:bc; nd.tll = 12:34:56:78:9a:bc; outport = inport; inport = ""; /* Allow sending out inport. */ output; };
1143 formats as nd_na { eth.src = 12:34:56:78:9a:bc; nd.tll = 12:34:56:78:9a:bc; outport = inport; inport = ""; output; };
1144 encodes as controller(userdata=00.00.00.03.00.00.00.00.00.19.00.10.80.00.08.06.12.34.56.78.9a.bc.00.00.00.19.00.10.80.00.42.06.12.34.56.78.9a.bc.00.00.ff.ff.00.18.00.00.23.20.00.06.00.20.00.00.00.00.00.01.1c.04.00.01.1e.04.00.19.00.10.00.01.1c.04.00.00.00.00.00.00.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00)
1147 nd_na_router { eth.src = 12:34:56:78:9a:bc; nd.tll = 12:34:56:78:9a:bc; outport = inport; inport = ""; /* Allow sending out inport. */ output; };
1148 formats as nd_na_router { eth.src = 12:34:56:78:9a:bc; nd.tll = 12:34:56:78:9a:bc; outport = inport; inport = ""; output; };
1149 encodes as controller(userdata=00.00.00.0c.00.00.00.00.00.19.00.10.80.00.08.06.12.34.56.78.9a.bc.00.00.00.19.00.10.80.00.42.06.12.34.56.78.9a.bc.00.00.ff.ff.00.18.00.00.23.20.00.06.00.20.00.00.00.00.00.01.1c.04.00.01.1e.04.00.19.00.10.00.01.1c.04.00.00.00.00.00.00.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00)
1153 get_nd(outport, ip6.dst);
1154 encodes as push:NXM_NX_XXREG0[],push:NXM_NX_IPV6_DST[],pop:NXM_NX_XXREG0[],set_field:00:00:00:00:00:00->eth_dst,resubmit(,65),pop:NXM_NX_XXREG0[]
1155 has prereqs eth.type == 0x86dd
1156 get_nd(inport, xxreg0);
1157 encodes as push:NXM_NX_REG15[],push:NXM_NX_REG14[],pop:NXM_NX_REG15[],set_field:00:00:00:00:00:00->eth_dst,resubmit(,65),pop:NXM_NX_REG15[]
1159 Syntax error at `;' expecting `('.
1161 Syntax error at `)' expecting field name.
1163 Syntax error at `)' expecting `,'.
1164 get_nd(inport ip6.dst);
1165 Syntax error at `ip6.dst' expecting `,'.
1166 get_nd(inport, ip6.dst;
1167 Syntax error at `;' expecting `)'.
1168 get_nd(inport, eth.dst);
1169 Cannot use 48-bit field eth.dst[0..47] where 128-bit field is required.
1170 get_nd(inport, outport);
1171 Cannot use string field outport where numeric field is required.
1172 get_nd(xxreg0, ip6.dst);
1173 Cannot use numeric field xxreg0 where string field is required.
1176 put_nd(inport, nd.target, nd.sll);
1177 encodes as push:NXM_NX_XXREG0[],push:NXM_OF_ETH_SRC[],push:NXM_NX_ND_SLL[],push:NXM_NX_ND_TARGET[],pop:NXM_NX_XXREG0[],pop:NXM_OF_ETH_SRC[],controller(userdata=00.00.00.04.00.00.00.00),pop:NXM_OF_ETH_SRC[],pop:NXM_NX_XXREG0[]
1178 has prereqs (icmp6.type == 0x87 || icmp6.type == 0x88) && eth.type == 0x86dd && ip.proto == 0x3a && (eth.type == 0x800 || eth.type == 0x86dd) && icmp6.code == 0 && eth.type == 0x86dd && ip.proto == 0x3a && (eth.type == 0x800 || eth.type == 0x86dd) && ip.ttl == 0xff && (eth.type == 0x800 || eth.type == 0x86dd) && icmp6.type == 0x87 && eth.type == 0x86dd && ip.proto == 0x3a && (eth.type == 0x800 || eth.type == 0x86dd) && icmp6.code == 0 && eth.type == 0x86dd && ip.proto == 0x3a && (eth.type == 0x800 || eth.type == 0x86dd) && ip.ttl == 0xff && (eth.type == 0x800 || eth.type == 0x86dd)
1181 reg1[0] = put_dhcpv6_opts(ia_addr = ae70::4, server_id = 00:00:00:00:10:02);
1182 encodes as controller(userdata=00.00.00.05.00.00.00.00.00.01.de.10.00.00.00.40.00.05.00.10.ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.04.00.02.00.06.00.00.00.00.10.02,pause)
1183 reg1[0] = put_dhcpv6_opts();
1184 encodes as controller(userdata=00.00.00.05.00.00.00.00.00.01.de.10.00.00.00.40,pause)
1185 reg1[0] = put_dhcpv6_opts(dns_server={ae70::1,ae70::2});
1186 formats as reg1[0] = put_dhcpv6_opts(dns_server = {ae70::1, ae70::2});
1187 encodes as controller(userdata=00.00.00.05.00.00.00.00.00.01.de.10.00.00.00.40.00.17.00.20.ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.01.ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.02,pause)
1188 reg1[0] = put_dhcpv6_opts(server_id=12:34:56:78:9a:bc, dns_server={ae70::1,ae89::2});
1189 formats as reg1[0] = put_dhcpv6_opts(server_id = 12:34:56:78:9a:bc, dns_server = {ae70::1, ae89::2});
1190 encodes as controller(userdata=00.00.00.05.00.00.00.00.00.01.de.10.00.00.00.40.00.02.00.06.12.34.56.78.9a.bc.00.17.00.20.ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.01.ae.89.00.00.00.00.00.00.00.00.00.00.00.00.00.02,pause)
1191 reg1[0] = put_dhcpv6_opts(domain_search = "ovn.org");
1192 encodes as controller(userdata=00.00.00.05.00.00.00.00.00.01.de.10.00.00.00.40.00.18.00.07.6f.76.6e.2e.6f.72.67,pause)
1193 reg1[0] = put_dhcpv6_opts(x = 1.2.3.4);
1194 Syntax error at `x' expecting DHCPv6 option name.
1195 reg1[0] = put_dhcpv6_opts(ia_addr=ae70::4, "hi");
1196 Syntax error at `"hi"'.
1197 reg1[0] = put_dhcpv6_opts(ia_addr=ae70::4, xyzzy);
1198 Syntax error at `xyzzy' expecting DHCPv6 option name.
1199 reg1[0] = put_dhcpv6_opts(ia_addr="ae70::4");
1200 DHCPv6 option ia_addr requires numeric value.
1201 reg1[0] = put_dhcpv6_opts(ia_addr=ae70::4, domain_search=ae70::1);
1202 DHCPv6 option domain_search requires string value.
1206 encodes as set_queue:0
1208 encodes as set_queue:61440
1210 Queue ID 65535 for set_queue is not in valid range 0 to 61440.
1213 reg1[0] = dns_lookup();
1214 encodes as controller(userdata=00.00.00.06.00.00.00.00.00.01.de.10.00.00.00.40,pause)
1216 reg1[0] = dns_lookup("foo");
1217 dns_lookup doesn't take any parameters
1221 Rate 0 for set_meter is not in valid.
1224 set_meter(100, 1000);
1226 set_meter(100, 1000, );
1227 Syntax error at `,' expecting `)'.
1228 set_meter(4294967295, 4294967295);
1232 log(verdict=allow, severity=warning);
1233 encodes as controller(userdata=00.00.00.07.00.00.00.00.00.04)
1234 log(name="test1", verdict=drop, severity=info);
1235 encodes as controller(userdata=00.00.00.07.00.00.00.00.01.06.74.65.73.74.31)
1236 log(verdict=drop, severity=info, meter="meter1");
1237 encodes as controller(userdata=00.00.00.07.00.00.00.00.01.06,meter_id=4)
1238 log(name="test1", verdict=drop, severity=info, meter="meter1");
1239 encodes as controller(userdata=00.00.00.07.00.00.00.00.01.06.74.65.73.74.31,meter_id=4)
1241 formats as log(verdict=drop, severity=info);
1242 encodes as controller(userdata=00.00.00.07.00.00.00.00.01.06)
1243 log(verdict=bad_verdict, severity=info);
1244 Syntax error at `bad_verdict' unknown verdict.
1245 log(verdict=drop, severity=bad_severity);
1246 Syntax error at `bad_severity' unknown severity.
1247 log(severity=notice);
1248 Syntax error at `;' expecting verdict.
1251 reg1[0] = put_nd_ra_opts(addr_mode = "slaac", mtu = 1500, prefix = aef0::/64, slla = ae:01:02:03:04:05);
1252 encodes as controller(userdata=00.00.00.08.00.00.00.00.00.01.de.10.00.00.00.40.86.00.00.00.ff.00.ff.ff.00.00.00.00.00.00.00.00.05.01.00.00.00.00.05.dc.03.04.40.c0.ff.ff.ff.ff.ff.ff.ff.ff.00.00.00.00.ae.f0.00.00.00.00.00.00.00.00.00.00.00.00.00.00.01.01.ae.01.02.03.04.05,pause)
1254 reg1[0] = put_nd_ra_opts(addr_mode = "dhcpv6_stateful", slla = ae:01:02:03:04:10, mtu = 1450);
1255 encodes as controller(userdata=00.00.00.08.00.00.00.00.00.01.de.10.00.00.00.40.86.00.00.00.ff.80.ff.ff.00.00.00.00.00.00.00.00.01.01.ae.01.02.03.04.10.05.01.00.00.00.00.05.aa,pause)
1257 reg1[0] = put_nd_ra_opts(addr_mode = "dhcpv6_stateless", slla = ae:01:02:03:04:06, prefix = aef0::/64);
1258 encodes as controller(userdata=00.00.00.08.00.00.00.00.00.01.de.10.00.00.00.40.86.00.00.00.ff.40.ff.ff.00.00.00.00.00.00.00.00.01.01.ae.01.02.03.04.06.03.04.40.c0.ff.ff.ff.ff.ff.ff.ff.ff.00.00.00.00.ae.f0.00.00.00.00.00.00.00.00.00.00.00.00.00.00,pause)
1260 reg1[0] = put_nd_ra_opts(addr_mode = "slaac", mtu = 1500, prefix = aef0::/64);
1261 slla option not present
1262 reg1[0] = put_nd_ra_opts(addr_mode = "dhcpv6_stateful", mtu = 1450, prefix = aef0::/64, prefix = bef0::/64, slla = ae:01:02:03:04:10);
1263 encodes as controller(userdata=00.00.00.08.00.00.00.00.00.01.de.10.00.00.00.40.86.00.00.00.ff.80.ff.ff.00.00.00.00.00.00.00.00.05.01.00.00.00.00.05.aa.03.04.40.80.ff.ff.ff.ff.ff.ff.ff.ff.00.00.00.00.ae.f0.00.00.00.00.00.00.00.00.00.00.00.00.00.00.03.04.40.80.ff.ff.ff.ff.ff.ff.ff.ff.00.00.00.00.be.f0.00.00.00.00.00.00.00.00.00.00.00.00.00.00.01.01.ae.01.02.03.04.10,pause)
1265 reg1[0] = put_nd_ra_opts(addr_mode = "dhcpv6_stateful", mtu = 1450, prefix = aef0::/64, prefix = bef0::/64, slla = ae:01:02:03:04:10);
1266 encodes as controller(userdata=00.00.00.08.00.00.00.00.00.01.de.10.00.00.00.40.86.00.00.00.ff.80.ff.ff.00.00.00.00.00.00.00.00.05.01.00.00.00.00.05.aa.03.04.40.80.ff.ff.ff.ff.ff.ff.ff.ff.00.00.00.00.ae.f0.00.00.00.00.00.00.00.00.00.00.00.00.00.00.03.04.40.80.ff.ff.ff.ff.ff.ff.ff.ff.00.00.00.00.be.f0.00.00.00.00.00.00.00.00.00.00.00.00.00.00.01.01.ae.01.02.03.04.10,pause)
1268 reg1[0] = put_nd_ra_opts(addr_mode = "slaac", slla = ae:01:02:03:04:10);
1269 prefix option needs to be set when address mode is slaac/dhcpv6_stateless.
1270 reg1[0] = put_nd_ra_opts(addr_mode = "dhcpv6_stateless", slla = ae:01:02:03:04:10);
1271 prefix option needs to be set when address mode is slaac/dhcpv6_stateless.
1272 reg1[0] = put_nd_ra_opts(addr_mode = dhcpv6_stateless, prefix = aef0::/64, slla = ae:01:02:03:04:10);
1273 Syntax error at `dhcpv6_stateless' expecting constant.
1274 reg1[0] = put_nd_ra_opts(addr_mode = "slaac", mtu = 1500, prefix = aef0::, slla = ae:01:02:03:04:10);
1275 Invalid value for "prefix" option
1276 reg1[0] = put_nd_ra_opts(addr_mode = "foo", mtu = 1500, slla = ae:01:02:03:04:10);
1277 Invalid value for "addr_mode" option
1278 reg1[0] = put_nd_ra_opts(addr_mode = "slaac", mtu = "1500", slla = ae:01:02:03:04:10);
1279 IPv6 ND RA option mtu requires numeric value.
1280 reg1[0] = put_nd_ra_opts(addr_mode = "slaac", mtu = 10.0.0.4, slla = ae:01:02:03:04:10);
1281 Invalid value for "mtu" option
1284 icmp4 { eth.dst = ff:ff:ff:ff:ff:ff; output; }; output;
1285 encodes as controller(userdata=00.00.00.0a.00.00.00.00.00.19.00.10.80.00.06.06.ff.ff.ff.ff.ff.ff.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00),resubmit(,64)
1289 formats as icmp4 { drop; };
1290 encodes as controller(userdata=00.00.00.0a.00.00.00.00)
1293 # icmp4 with icmp4.frag_mtu
1294 icmp4 { eth.dst = ff:ff:ff:ff:ff:ff; icmp4.frag_mtu = 1500; output; }; output;
1295 encodes as controller(userdata=00.00.00.0a.00.00.00.00.00.19.00.10.80.00.06.06.ff.ff.ff.ff.ff.ff.00.00.ff.ff.00.28.00.00.23.20.00.25.00.00.00.00.00.00.00.03.00.0e.00.00.00.0d.00.00.00.00.05.dc.00.00.00.04.00.04.00.00.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00),resubmit(,64)
1299 icmp4_error { eth.dst = ff:ff:ff:ff:ff:ff; output; }; output;
1300 encodes as controller(userdata=00.00.00.0e.00.00.00.00.00.19.00.10.80.00.06.06.ff.ff.ff.ff.ff.ff.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00),resubmit(,64)
1304 formats as icmp4_error { drop; };
1305 encodes as controller(userdata=00.00.00.0e.00.00.00.00)
1308 # icmp4_error with icmp4.frag_mtu
1309 icmp4_error { eth.dst = ff:ff:ff:ff:ff:ff; icmp4.frag_mtu = 1500; output; }; output;
1310 encodes as controller(userdata=00.00.00.0e.00.00.00.00.00.19.00.10.80.00.06.06.ff.ff.ff.ff.ff.ff.00.00.ff.ff.00.28.00.00.23.20.00.25.00.00.00.00.00.00.00.03.00.0e.00.00.00.0d.00.00.00.00.05.dc.00.00.00.04.00.04.00.00.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00),resubmit(,64)
1313 icmp4.frag_mtu = 1500;
1314 encodes as controller(userdata=00.00.00.0d.00.00.00.00.05.dc,pause)
1317 icmp6 { eth.dst = ff:ff:ff:ff:ff:ff; output; }; output;
1318 encodes as controller(userdata=00.00.00.0a.00.00.00.00.00.19.00.10.80.00.06.06.ff.ff.ff.ff.ff.ff.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00),resubmit(,64)
1322 formats as icmp6 { drop; };
1323 encodes as controller(userdata=00.00.00.0a.00.00.00.00)
1327 tcp_reset { eth.dst = ff:ff:ff:ff:ff:ff; output; }; output;
1328 encodes as controller(userdata=00.00.00.0b.00.00.00.00.00.19.00.10.80.00.06.06.ff.ff.ff.ff.ff.ff.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00),resubmit(,64)
1332 formats as tcp_reset { drop; };
1333 encodes as controller(userdata=00.00.00.0b.00.00.00.00)
1336 # Contradictionary prerequisites (allowed but not useful):
1337 ip4.src = ip6.src[0..31];
1338 encodes as move:NXM_NX_IPV6_SRC[0..31]->NXM_OF_IP_SRC[]
1339 has prereqs eth.type == 0x800 && eth.type == 0x86dd
1340 ip4.src <-> ip6.src[0..31];
1341 encodes as push:NXM_NX_IPV6_SRC[0..31],push:NXM_OF_IP_SRC[],pop:NXM_NX_IPV6_SRC[0..31],pop:NXM_OF_IP_SRC[]
1342 has prereqs eth.type == 0x800 && eth.type == 0x86dd
1345 reg0[0] = check_pkt_larger(1500);
1346 encodes as check_pkt_larger(1500)->NXM_NX_XXREG0[96]
1348 reg0 = check_pkt_larger(1500);
1349 Cannot use 32-bit field reg0[0..31] where 1-bit field is required.
1351 reg0 = check_pkt_larger(foo);
1352 Cannot use 32-bit field reg0[0..31] where 1-bit field is required.
1354 reg0[0] = check_pkt_larger(foo);
1355 Syntax error at `foo' expecting `;'.
1357 # Miscellaneous negative tests.
1359 Syntax error at `;'.
1361 Syntax error at `xyzzy' expecting action.
1363 Syntax error at `123'.
1365 Syntax error at `xyzzy' expecting action.
1367 Syntax error at end of input expecting `;'.
1369 sed '/^[[ ]]/d' test-cases.txt > input.txt
1370 cp test-cases.txt expout
1371 AT_CHECK([ovstest test-ovn parse-actions < input.txt], [0], [expout])
1374 AT_BANNER([OVN end-to-end tests])
1376 # 3 hypervisors, one logical switch, 3 logical ports per hypervisor
1377 AT_SETUP([ovn -- 3 HVs, 1 LS, 3 lports/HV])
1378 AT_KEYWORDS([ovnarp])
1379 AT_SKIP_IF([test $HAVE_PYTHON = no])
1382 # Create hypervisors hv[123].
1383 # Add vif1[123] to hv1, vif2[123] to hv2, vif3[123] to hv3.
1384 # Add all of the vifs to a single logical switch lsw0.
1385 # Turn on port security on all the vifs except vif[123]1.
1386 # Make vif13, vif2[23], vif3[123] destinations for unknown MACs.
1387 # Add some ACLs for Ethertypes 1234, 1235, 1236.
1388 ovn-nbctl ls-add lsw0
1393 ovs-vsctl add-br br-phys
1394 ovn_attach n1 br-phys 192.168.0.$i
1397 ovs-vsctl add-port br-int vif$i$j -- set Interface vif$i$j external-ids:iface-id=lp$i$j options:tx_pcap=hv$i/vif$i$j-tx.pcap options:rxq_pcap=hv$i/vif$i$j-rx.pcap ofport-request=$i$j
1398 ovn-nbctl lsp-add lsw0 lp$i$j
1399 if test $j = 1; then
1400 ovn-nbctl lsp-set-addresses lp$i$j "f0:00:00:00:00:$i$j 192.168.0.$i$j" unknown
1402 if test $j = 3; then
1403 ip_addrs="192.168.0.$i$j fe80::ea2a:eaff:fe28:$i$j/64 192.169.0.$i$j"
1405 ip_addrs="192.168.0.$i$j"
1407 ovn-nbctl lsp-set-addresses lp$i$j "f0:00:00:00:00:$i$j $ip_addrs"
1408 ovn-nbctl lsp-set-port-security lp$i$j f0:00:00:00:00:$i$j
1412 ovn-nbctl acl-add lsw0 from-lport 1000 'eth.type == 0x1234' drop
1413 ovn-nbctl acl-add lsw0 from-lport 1000 'eth.type == 0x1235 && inport == "lp11"' drop
1414 ovn-nbctl acl-add lsw0 to-lport 1000 'eth.type == 0x1236 && outport == "lp33"' drop
1415 ovn-nbctl create Address_Set name=set1 addresses=\"f0:00:00:00:00:11\",\"f0:00:00:00:00:21\",\"f0:00:00:00:00:31\"
1416 ovn-nbctl acl-add lsw0 to-lport 1000 'eth.type == 0x1237 && eth.src == $set1 && outport == "lp33"' drop
1419 ovn-nbctl lsp-list lsw0 | grep $1 | awk '{ print $1 }'
1422 ovn-nbctl create Port_Group name=pg1 ports=`get_lsp_uuid lp22`,`get_lsp_uuid lp33`
1423 ovn-nbctl acl-add lsw0 to-lport 1000 'eth.type == 0x1238 && outport == @pg1' drop
1425 # Pre-populate the hypervisors' ARP tables so that we don't lose any
1426 # packets for ARP resolution (native tunneling doesn't queue packets
1427 # for ARP resolution).
1430 # Allow some time for ovn-northd and ovn-controller to catch up.
1431 # XXX This should be more systematic.
1434 # Make sure there is no attempt to adding duplicated flows by ovn-controller
1435 AT_FAIL_IF([test -n "`grep duplicate hv1/ovn-controller.log`"])
1436 AT_FAIL_IF([test -n "`grep duplicate hv2/ovn-controller.log`"])
1437 AT_FAIL_IF([test -n "`grep duplicate hv3/ovn-controller.log`"])
1439 # Given the name of a logical port, prints the name of the hypervisor
1440 # on which it is located.
1445 # test_packet INPORT DST SRC ETHTYPE OUTPORT...
1447 # This shell function causes a packet to be received on INPORT. The packet's
1448 # content has Ethernet destination DST and source SRC (each exactly 12 hex
1449 # digits) and Ethernet type ETHTYPE (4 hex digits). The OUTPORTs (zero or
1450 # more) list the VIFs on which the packet should be received. INPORT and the
1451 # OUTPORTs are specified as logical switch port numbers, e.g. 11 for vif11.
1458 local inport=$1 packet=$2$3$4; shift; shift; shift; shift
1459 hv=`vif_to_hv $inport`
1461 as $hv ovs-appctl netdev-dummy/receive $vif $packet
1463 echo $packet >> $outport.expected
1467 # test_arp INPORT SHA SPA TPA [REPLY_HA]
1469 # Causes a packet to be received on INPORT. The packet is an ARP
1470 # request with SHA, SPA, and TPA as specified. If REPLY_HA is provided, then
1471 # it should be the hardware address of the target to expect to receive in an
1472 # ARP reply; otherwise no reply is expected.
1474 # INPORT is an logical switch port number, e.g. 11 for vif11.
1475 # SHA and REPLY_HA are each 12 hex digits.
1476 # SPA and TPA are each 8 hex digits.
1478 local inport=$1 sha=$2 spa=$3 tpa=$4 reply_ha=$5
1479 local request=ffffffffffff${sha}08060001080006040001${sha}${spa}ffffffffffff${tpa}
1480 hv=`vif_to_hv $inport`
1481 as $hv ovs-appctl netdev-dummy/receive vif$inport $request
1483 if test X$reply_ha = X; then
1484 # Expect to receive the broadcast ARP on the other logical switch ports
1485 # if no reply is expected.
1489 if test $i$j != $inport; then
1490 echo $request >> $i$j.expected
1495 # Expect to receive the reply, if any.
1496 local reply=${sha}${reply_ha}08060001080006040002${reply_ha}${tpa}${sha}${spa}
1497 echo $reply >> $inport.expected
1502 printf "%02x%02x%02x%02x" "$@"
1505 # Send packets between all pairs of source and destination ports:
1507 # 1. Unicast packets are delivered to exactly one logical switch port
1508 # (except that packets destined to their input ports are dropped).
1510 # 2. Broadcast and multicast are delivered to all logical switch ports
1511 # except the input port.
1513 # 3. When port security is turned on, the switch drops packets from the wrong
1516 # 4. The switch drops all packets with a VLAN tag.
1518 # 5. The switch drops all packets with a multicast source address. (This only
1519 # affects behavior when port security is turned off, since otherwise port
1520 # security would drop the packet anyway.)
1522 # 6. The switch delivers packets with an unknown destination to logical
1523 # switch ports with "unknown" among their MAC addresses (and port
1524 # security disabled).
1526 # 7. The switch drops unicast packets that violate an ACL.
1528 # 8. The switch drops multicast and broadcast packets that violate an ACL.
1530 # 9. OVN generates responses to ARP requests for known IPs, except for
1531 # requests from a port for the port's own IP.
1533 # 10. No response to ARP requests for unknown IPs.
1546 if test $d != $s; then unicast=$d; else unicast=; fi
1547 test_packet $s f000000000$d f000000000$s $s$d $unicast #1
1549 if test $d != $s && test $js = 1; then
1554 test_packet $s f000000000$d f00000000055 55$d $impersonate #3
1556 if test $d != $s && test $s != 11; then acl2=$d; else acl2=; fi
1557 if test $d != $s && test $d != 33; then acl3=$d; else acl3=; fi
1558 if test $d = $s || (test $js = 1 && test $d = 33); then
1559 # Source of 11, 21, or 31 and dest of 33 should be dropped
1560 # due to the 4th ACL that uses address_set(set1).
1565 if test $d = $s || test $d = 22 || test $d = 33; then
1566 # dest of 22 and 33 should be dropped
1567 # due to the 5th ACL that uses port_group(pg1).
1572 test_packet $s f000000000$d f000000000$s 1234 #7, acl1
1573 test_packet $s f000000000$d f000000000$s 1235 $acl2 #7, acl2
1574 test_packet $s f000000000$d f000000000$s 1236 $acl3 #7, acl3
1575 test_packet $s f000000000$d f000000000$s 1237 $acl4 #7, acl4
1576 test_packet $s f000000000$d f000000000$s 1238 $acl5 #7, acl5
1578 test_packet $s f000000000$d f00000000055 810000091234 #4
1579 test_packet $s f000000000$d 0100000000$s $s$d #5
1581 if test $d != $s && test $jd = 1; then
1582 unknown="$unknown $d"
1584 bcast="$bcast $unicast"
1585 bacl2="$bacl2 $acl2"
1586 bacl3="$bacl3 $acl3"
1588 sip=`ip_to_hex 192 168 0 $is$js`
1589 tip=`ip_to_hex 192 168 0 $id$jd`
1590 tip_unknown=`ip_to_hex 11 11 11 11`
1591 if test $d != $s; then
1592 reply_ha=f000000000$d
1596 test_arp $s f000000000$s $sip $tip $reply_ha #9
1597 test_arp $s f000000000$s $sip $tip_unknown #10
1599 if test $jd = 3; then
1600 # lsp[123]3 has an additional ip 192.169.0.[123]3.
1601 tip=`ip_to_hex 192 169 0 $id$jd`
1602 test_arp $s f000000000$s $sip $tip $reply_ha #9
1607 # Broadcast and multicast.
1608 test_packet $s ffffffffffff f000000000$s ${s}ff $bcast #2
1609 test_packet $s 010000000000 f000000000$s ${s}ff $bcast #2
1610 if test $js = 1; then
1611 bcast_impersonate=$bcast
1615 test_packet $s 010000000000 f00000000044 44ff $bcast_impersonate #3
1617 test_packet $s f0000000ffff f000000000$s ${s}66 $unknown #6
1619 test_packet $s ffffffffffff f000000000$s 1234 #8, acl1
1620 test_packet $s ffffffffffff f000000000$s 1235 $bacl2 #8, acl2
1621 test_packet $s ffffffffffff f000000000$s 1236 $bacl3 #8, acl3
1622 test_packet $s 010000000000 f000000000$s 1234 #8, acl1
1623 test_packet $s 010000000000 f000000000$s 1235 $bacl2 #8, acl2
1624 test_packet $s 010000000000 f000000000$s 1236 $bacl3 #8, acl3
1628 # set address for lp13 with invalid characters.
1629 # lp13 should be configured with only 192.168.0.13.
1630 ovn-nbctl lsp-set-addresses lp13 "f0:00:00:00:00:13 192.168.0.13 invalid 192.169.0.13"
1632 # Allow some time for ovn-northd and ovn-controller to catch up.
1633 # XXX This should be more systematic.
1636 sip=`ip_to_hex 192 168 0 11`
1637 tip=`ip_to_hex 192 168 0 13`
1638 test_arp 11 f00000000011 $sip $tip f00000000013
1640 tip=`ip_to_hex 192 169 0 13`
1641 #arp request for 192.169.0.13 should be flooded
1642 test_arp 11 f00000000011 $sip $tip
1644 # dump information and flows with counters
1645 ovn-sbctl dump-flows -- list multicast_group
1647 echo "------ hv1 dump ------"
1648 as hv1 ovs-vsctl show
1649 as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-int
1651 echo "------ hv2 dump ------"
1652 as hv2 ovs-vsctl show
1653 as hv2 ovs-ofctl -O OpenFlow13 dump-flows br-int
1655 echo "------ hv3 dump ------"
1656 as hv3 ovs-vsctl show
1657 as hv3 ovs-ofctl -O OpenFlow13 dump-flows br-int
1659 # Now check the packets actually received against the ones expected.
1662 OVN_CHECK_PACKETS([hv$i/vif$i$j-tx.pcap], [$i$j.expected])
1666 OVN_CLEANUP([hv1],[hv2],[hv3])
1670 # 2 hypervisors, one logical switch, 2 logical ports per hypervisor
1671 # logical ports bound to chassis encap-ip.
1672 AT_SETUP([ovn -- 2 HVs, 1 LS, 2 lports/HV])
1673 AT_KEYWORDS([ovnarp])
1674 AT_SKIP_IF([test $HAVE_PYTHON = no])
1677 # Create hypervisors hv[12].
1678 # Add vif1[12] to hv1, vif2[12] to hv2
1679 ovn-nbctl ls-add lsw0
1684 ovs-vsctl add-br br-phys
1685 ovn_attach n1 br-phys 192.168.0.$i
1688 ovs-vsctl add-port br-int vif$i$j -- set Interface vif$i$j external-ids:iface-id=lp$i$j options:tx_pcap=hv$i/vif$i$j-tx.pcap options:rxq_pcap=hv$i/vif$i$j-rx.pcap ofport-request=$i$j
1689 ovn-nbctl lsp-add lsw0 lp$i$j
1690 ip_addrs="192.168.0.$i$j"
1691 ovn-nbctl lsp-set-addresses lp$i$j "f0:00:00:00:00:$i$j $ip_addrs"
1692 ovn-nbctl --wait=hv lsp-set-port-security lp$i$j f0:00:00:00:00:$i$j
1697 ovn-nbctl lsp-list lsw0 | grep $1 | awk '{ print $1 }'
1700 # XXX-Check how to pass lp$i1 in AT_CHECK_UNQUOTED, for now just do it
1704 AT_CHECK_UNQUOTED([ovn-sbctl --column encap list port_binding lp11], [0], [dnl
1707 AT_CHECK_UNQUOTED([ovn-sbctl --column encap list port_binding lp12], [0], [dnl
1712 AT_CHECK_UNQUOTED([ovn-sbctl --column encap list port_binding lp21], [0], [dnl
1715 AT_CHECK_UNQUOTED([ovn-sbctl --column encap list port_binding lp22], [0], [dnl
1719 # Bind the ports to the encap-ip
1723 ovs-vsctl set Interface vif$i$j external-ids:encap-ip=192.168.0.$i
1729 # dump port bindings; since we have vxlan and geneve tunnels, we expect the
1730 # ports to be bound to geneve tunnels.
1733 encap_rec=`ovn-sbctl --data=bare --no-heading --column _uuid find encap chassis_name=hv1 type=geneve ip=192.168.0.1`
1735 AT_CHECK_UNQUOTED([ovn-sbctl --column encap list port_binding lp11], [0], [dnl
1736 encap : ${encap_rec}
1739 AT_CHECK_UNQUOTED([ovn-sbctl --column encap list port_binding lp12], [0], [dnl
1740 encap : ${encap_rec}
1744 encap_rec=`ovn-sbctl --data=bare --no-heading --column _uuid find encap chassis_name=hv2 type=geneve ip=192.168.0.2`
1746 AT_CHECK_UNQUOTED([ovn-sbctl --column encap list port_binding lp21], [0], [dnl
1747 encap : ${encap_rec}
1750 AT_CHECK_UNQUOTED([ovn-sbctl --column encap list port_binding lp22], [0], [dnl
1751 encap : ${encap_rec}
1754 # Pre-populate the hypervisors' ARP tables so that we don't lose any
1755 # packets for ARP resolution (native tunneling doesn't queue packets
1756 # for ARP resolution).
1759 # Allow some time for ovn-northd and ovn-controller to catch up.
1760 # XXX This should be more systematic.
1763 # Make sure there is no attempt to adding duplicated flows by ovn-controller
1764 AT_FAIL_IF([test -n "`grep duplicate hv1/ovn-controller.log`"])
1765 AT_FAIL_IF([test -n "`grep duplicate hv2/ovn-controller.log`"])
1766 AT_FAIL_IF([test -n "`grep duplicate hv3/ovn-controller.log`"])
1768 # Given the name of a logical port, prints the name of the hypervisor
1769 # on which it is located.
1774 # test_packet INPORT DST SRC ETHTYPE OUTPORT...
1776 # This shell function causes a packet to be received on INPORT. The packet's
1777 # content has Ethernet destination DST and source SRC (each exactly 12 hex
1778 # digits) and Ethernet type ETHTYPE (4 hex digits). The OUTPORTs (zero or
1779 # more) list the VIFs on which the packet should be received. INPORT and the
1780 # OUTPORTs are specified as logical switch port numbers, e.g. 11 for vif11.
1787 local inport=$1 packet=$2$3$4; shift; shift; shift; shift
1788 hv=`vif_to_hv $inport`
1790 as $hv ovs-appctl netdev-dummy/receive $vif $packet
1792 echo $packet >> $outport.expected
1797 printf "%02x%02x%02x%02x" "$@"
1800 # Send packets between all pairs of source and destination ports:
1802 # 1. Unicast packets are delivered to exactly one logical switch port
1803 # (except that packets destined to their input ports are dropped).
1816 if test $d != $s; then unicast=$d; else unicast=; fi
1817 test_packet $s f000000000$d f000000000$s $s$d $unicast #1
1824 # dump information and flows with counters
1825 ovn-sbctl dump-flows -- list multicast_group
1827 echo "------ hv1 dump ------"
1828 as hv1 ovs-vsctl show
1829 as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-int
1831 echo "------ hv2 dump ------"
1832 as hv2 ovs-vsctl show
1833 as hv2 ovs-ofctl -O OpenFlow13 dump-flows br-int
1835 echo "------ hv3 dump ------"
1836 as hv3 ovs-vsctl show
1837 as hv3 ovs-ofctl -O OpenFlow13 dump-flows br-int
1839 # Now check the packets actually received against the ones expected.
1842 OVN_CHECK_PACKETS([hv$i/vif$i$j-tx.pcap], [$i$j.expected])
1846 OVN_CLEANUP([hv1],[hv2])
1850 AT_SETUP([ovn -- trace 1 LS, 3 LSPs])
1851 AT_SKIP_IF([test $HAVE_PYTHON = no])
1854 # Create a logical switch and some logical ports.
1855 # Turn on port security on all lports except ls1.
1856 # Make ls1 a destination for unknown MACs.
1857 # Add some ACLs for Ethertypes 1234, 1235, 1236.
1858 ovn-nbctl ls-add lsw0
1859 ovn-sbctl chassis-add hv0 geneve 127.0.0.1
1861 ovn-nbctl lsp-add lsw0 lp$i
1863 ovn-nbctl --wait=sb sync
1865 ovn-sbctl lsp-bind lp$i hv0
1866 if test $i = 1; then
1867 ovn-nbctl lsp-set-addresses lp$i "f0:00:00:00:00:0$i 192.168.0.$i" unknown
1869 if test $i = 3; then
1870 ip_addrs="192.168.0.$i fe80::ea2a:eaff:fe28:$i/64 192.169.0.$i"
1872 ip_addrs="192.168.0.$i"
1874 ovn-nbctl lsp-set-addresses lp$i "f0:00:00:00:00:0$i $ip_addrs"
1875 ovn-nbctl lsp-set-port-security lp$i f0:00:00:00:00:0$i
1878 ovn-nbctl acl-add lsw0 from-lport 1000 'eth.type == 0x1234' drop
1879 ovn-nbctl acl-add lsw0 from-lport 1000 'eth.type == 0x1235 && inport == "lp1"' drop
1880 ovn-nbctl acl-add lsw0 to-lport 1000 'eth.type == 0x1236 && outport == "lp3"' drop
1881 ovn-nbctl create Address_Set name=set1 addresses=\"f0:00:00:00:00:01\",\"f0:00:00:00:00:02\"
1882 ovn-nbctl acl-add lsw0 to-lport 1000 'eth.type == 0x1237 && eth.src == $set1 && outport == "lp3"' drop
1884 ovn-nbctl --wait=sb sync
1885 on_exit 'kill `cat ovn-trace.pid`'
1886 ovn-trace --detach --pidfile --no-chdir
1888 # test_packet INPORT DST SRC [-vlan] [-eth TYPE] OUTPORT...
1890 # This shell function causes a packet to be received on INPORT. The packet's
1891 # content has Ethernet destination DST and source SRC (each exactly 12 hex
1892 # digits) and Ethernet type ETHTYPE (4 hex digits). The OUTPORTs (zero or
1893 # more) list the VIFs on which the packet should be received. INPORT and the
1894 # OUTPORTs are specified as logical switch port numbers, e.g. 11 for vif11.
1896 local inport=$1 eth_dst=$2 eth_src=$3; shift; shift; shift
1897 uflow="inport==\"lp$inport\" && eth.dst==$eth_dst && eth.src==$eth_src"
1900 -vlan) uflow="$uflow && vlan.vid == 1234"; shift ;; # (
1901 -eth) uflow="$uflow && eth.type == 0x$2"; shift; shift ;; # (
1906 echo "output(\"lp$outport\");"
1909 AT_CAPTURE_FILE([trace])
1910 AT_CHECK([ovs-appctl -t ovn-trace trace --all lsw0 "$uflow" | tee trace | sed '1,/Minimal trace/d'], [0], [expout])
1913 # test_arp INPORT SHA SPA TPA [REPLY_HA]
1915 # Causes a packet to be received on INPORT. The packet is an ARP
1916 # request with SHA, SPA, and TPA as specified. If REPLY_HA is provided, then
1917 # it should be the hardware address of the target to expect to receive in an
1918 # ARP reply; otherwise no reply is expected.
1920 # INPORT is an logical switch port number, e.g. 11 for vif11.
1921 # SHA and REPLY_HA are each 12 hex digits.
1922 # SPA and TPA are each 8 hex digits.
1924 local inport=$1 sha=$2 spa=$3 tpa=$4 reply_ha=$5
1926 local request="inport == \"lp$inport\"
1927 && eth.dst == ff:ff:ff:ff:ff:ff && eth.src == $sha
1928 && arp.op == 1 && arp.sha == $sha && arp.spa == $spa
1929 && arp.tha == ff:ff:ff:ff:ff:ff && arp.tpa == $tpa"
1931 if test -z "$reply_ha"; then
1935 if test $i != $inport; then
1936 reply="${reply}output(\"lp$i\");
1943 eth.src = $reply_ha;
1946 arp.sha = $reply_ha;
1949 output(\"lp$inport\");
1953 AT_CAPTURE_FILE([trace])
1954 AT_CHECK_UNQUOTED([ovs-appctl -t ovn-trace trace --all lsw0 "$request" | tee trace | sed '1,/Minimal trace/d'], [0], [$reply])
1957 # Send packets between all pairs of source and destination ports:
1959 # 1. Unicast packets are delivered to exactly one logical switch port
1960 # (except that packets destined to their input ports are dropped).
1962 # 2. Broadcast and multicast are delivered to all logical switch ports
1963 # except the input port.
1965 # 3. When port security is turned on, the switch drops packets from the wrong
1968 # 4. The switch drops all packets with a VLAN tag.
1970 # 5. The switch drops all packets with a multicast source address. (This only
1971 # affects behavior when port security is turned off, since otherwise port
1972 # security would drop the packet anyway.)
1974 # 6. The switch delivers packets with an unknown destination to logical
1975 # switch ports with "unknown" among their MAC addresses (and port
1976 # security disabled).
1978 # 7. The switch drops unicast packets that violate an ACL.
1980 # 8. The switch drops multicast and broadcast packets that violate an ACL.
1982 # 9. OVN generates responses to ARP requests for known IPs, except for
1983 # requests from a port for the port's own IP.
1985 # 10. No response to ARP requests for unknown IPs.
1995 if test $d != $s; then unicast=$d; else unicast=; fi
1996 test_packet $s f0:00:00:00:00:0$d f0:00:00:00:00:0$s $unicast #1
1998 if test $d != $s && test $s = 1; then
2003 test_packet $s f0:00:00:00:00:0$d f0:00:00:00:00:55 $impersonate #3
2005 if test $d != $s && test $s != 1; then acl2=$d; else acl2=; fi
2006 if test $d != $s && test $d != 3; then acl3=$d; else acl3=; fi
2007 if test $d = $s || ( (test $s = 1 || test $s = 2) && test $d = 3); then
2008 # Source of 1 or 2 and dest of 3 should be dropped
2009 # due to the 4th ACL that uses address_set(set1).
2016 test_packet $s f0:00:00:00:00:0$d f0:00:00:00:00:0$s -eth 1234
2017 test_packet $s f0:00:00:00:00:0$d f0:00:00:00:00:0$s -eth 1235 $acl2
2018 test_packet $s f0:00:00:00:00:0$d f0:00:00:00:00:0$s -eth 1236 $acl3
2019 test_packet $s f0:00:00:00:00:0$d f0:00:00:00:00:0$s -eth 1237 $acl4
2021 test_packet $s f0:00:00:00:00:0$d f0:00:00:00:00:55 -vlan #4
2022 test_packet $s f0:00:00:00:00:0$d 01:00:00:00:00:0$s #5
2024 if test $d != $s && test $d = 1; then
2025 unknown="$unknown $d"
2027 bcast="$bcast $unicast"
2028 bacl2="$bacl2 $acl2"
2029 bacl3="$bacl3 $acl3"
2033 tip_unknown=11.11.11.11
2034 if test $d != $s; then reply_ha=f0:00:00:00:00:0$d; else reply_ha=; fi
2035 test_arp $s f0:00:00:00:00:0$s $sip $tip $reply_ha #9
2036 test_arp $s f0:00:00:00:00:0$s $sip $tip_unknown #10
2038 if test $d = 3; then
2039 # lp3 has an additional ip 192.169.0.[123]3.
2041 test_arp $s f0:00:00:00:00:0$s $sip $tip $reply_ha #9
2045 # Broadcast and multicast.
2046 test_packet $s ff:ff:ff:ff:ff:ff f0:00:00:00:00:0$s $bcast #2
2047 test_packet $s 01:00:00:00:00:00 f0:00:00:00:00:0$s $bcast #2
2048 if test $s = 1; then
2049 bcast_impersonate=$bcast
2053 test_packet $s 01:00:00:00:00:00 f0:00:00:00:00:44 $bcast_impersonate #3
2055 test_packet $s f0:00:00:00:ff:ff f0:00:00:00:00:0$s $unknown #6
2058 test_packet $s ff:ff:ff:ff:ff:ff f0:00:00:00:00:0$s -eth 1234
2059 test_packet $s ff:ff:ff:ff:ff:ff f0:00:00:00:00:0$s -eth 1235 $bacl2
2060 test_packet $s ff:ff:ff:ff:ff:ff f0:00:00:00:00:0$s -eth 1236 $bacl3
2063 test_packet $s 01:00:00:00:00:00 f0:00:00:00:00:0$s -eth 1234
2064 test_packet $s 01:00:00:00:00:00 f0:00:00:00:00:0$s -eth 1235 $bacl2
2065 test_packet $s 01:00:00:00:00:00 f0:00:00:00:00:0$s -eth 1236 $bacl3
2070 # 2 hypervisors, 4 logical ports per HV
2071 # 2 locally attached networks (one flat, one vlan tagged over same device)
2072 # 2 ports per HV on each network
2073 AT_SETUP([ovn -- 2 HVs, 4 lports/HV, localnet ports])
2074 AT_SKIP_IF([test $HAVE_PYTHON = no])
2077 # In this test cases we create 3 switches, all connected to same
2078 # physical network (through br-phys on each HV). Each switch has
2079 # VIF ports across 2 HVs. Each HV has 5 VIF ports. The first digit
2080 # of VIF port name indicates the hypervisor it is bound to, e.g.
2081 # lp23 means VIF 3 on hv2.
2083 # Each switch's VLAN tag and their logical switch ports are:
2086 # - ports: lp11, lp12, lp21, lp22
2089 # - tagged with VLAN 101
2090 # - ports: lp13, lp14, lp23, lp24
2093 # - ports: lp15, lp25
2095 # Note: a localnet port is created for each switch to connect to
2100 ovn-nbctl ls-add $ls_name
2102 if test $i -eq 2; then
2103 ovn-nbctl lsp-add $ls_name $ln_port_name "" 101
2105 ovn-nbctl lsp-add $ls_name $ln_port_name
2107 ovn-nbctl lsp-set-addresses $ln_port_name unknown
2108 ovn-nbctl lsp-set-type $ln_port_name localnet
2109 ovn-nbctl lsp-set-options $ln_port_name network_name=phys
2114 # Prints the name of the logical switch that contains LSP.
2117 lp?[[12]]) echo ls1 ;; dnl (
2118 lp?[[34]]) echo ls2 ;; dnl (
2119 lp?5) echo ls3 ;; dnl (
2120 *) AT_FAIL_IF([:]) ;;
2128 ovs-vsctl add-br br-phys
2129 ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
2130 ovn_attach n1 br-phys 192.168.0.$i
2132 for j in 1 2 3 4 5; do
2133 ovs-vsctl add-port br-int vif$i$j -- \
2134 set Interface vif$i$j external-ids:iface-id=lp$i$j \
2135 options:tx_pcap=hv$i/vif$i$j-tx.pcap \
2136 options:rxq_pcap=hv$i/vif$i$j-rx.pcap \
2140 ls_name=$(lsp_to_ls $lsp_name)
2142 ovn-nbctl lsp-add $ls_name $lsp_name
2143 ovn-nbctl lsp-set-addresses $lsp_name f0:00:00:00:00:$i$j
2144 ovn-nbctl lsp-set-port-security $lsp_name f0:00:00:00:00:$i$j
2146 OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up $lsp_name` = xup])
2149 ovn-nbctl --wait=sb sync
2150 ovn-sbctl dump-flows
2154 # XXX This is now the 3rd copy of these functions in this file ...
2156 # Given the name of a logical port, prints the name of the hypervisor
2157 # on which it is located.
2162 # test_packet INPORT DST SRC ETHTYPE EOUT LOUT
2164 # This shell function causes a packet to be received on INPORT. The packet's
2165 # content has Ethernet destination DST and source SRC (each exactly 12 hex
2166 # digits) and Ethernet type ETHTYPE (4 hex digits). INPORT is specified as
2167 # logical switch port numbers, e.g. 11 for vif11.
2169 # EOUT is the end-to-end output port, that is, where the packet will end up
2170 # after possibly bouncing through one or more localnet ports. LOUT is the
2171 # logical output port, which might be a localnet port, as seen by ovn-trace
2172 # (which doesn't know what localnet ports are connected to and therefore can't
2173 # figure out the end-to-end answer).
2175 for j in 1 2 3 4 5; do
2180 local inport=$1 dst=$2 src=$3 eth=$4 eout=$5 lout=$6
2183 # First try tracing the packet.
2184 uflow="inport==\"lp$inport\" && eth.dst==$dst && eth.src==$src && eth.type==0x$eth"
2185 if test $lout != drop; then
2186 echo "output(\"$lout\");"
2188 AT_CAPTURE_FILE([trace])
2189 AT_CHECK([ovn-trace --all $(lsp_to_ls lp$inport) "$uflow" | tee trace | sed '1,/Minimal trace/d'], [0], [expout])
2191 # Then actually send a packet, for an end-to-end test.
2192 local packet=$(echo $dst$src | sed 's/://g')${eth}
2193 hv=`vif_to_hv $inport`
2195 as $hv ovs-appctl netdev-dummy/receive $vif $packet
2196 if test $eout != drop; then
2197 echo $packet >> ${eout#lp}.expected
2201 # lp11 and lp21 are on the same network (phys, untagged)
2202 # and on different hypervisors
2203 test_packet 11 f0:00:00:00:00:21 f0:00:00:00:00:11 1121 lp21 lp21
2204 test_packet 21 f0:00:00:00:00:11 f0:00:00:00:00:21 2111 lp11 lp11
2206 # lp11 and lp12 are on the same network (phys, untagged)
2207 # and on the same hypervisor
2208 test_packet 11 f0:00:00:00:00:12 f0:00:00:00:00:11 1112 lp12 lp12
2209 test_packet 12 f0:00:00:00:00:11 f0:00:00:00:00:12 1211 lp11 lp11
2211 # lp13 and lp23 are on the same network (phys, VLAN 101)
2212 # and on different hypervisors
2213 test_packet 13 f0:00:00:00:00:23 f0:00:00:00:00:13 1323 lp23 lp23
2214 test_packet 23 f0:00:00:00:00:13 f0:00:00:00:00:23 2313 lp13 lp13
2216 # lp13 and lp14 are on the same network (phys, VLAN 101)
2217 # and on the same hypervisor
2218 test_packet 13 f0:00:00:00:00:14 f0:00:00:00:00:13 1314 lp14 lp14
2219 test_packet 14 f0:00:00:00:00:13 f0:00:00:00:00:14 1413 lp13 lp13
2221 # lp11 and lp15 are on the same network (phys, untagged),
2222 # same hypervisor, and on different switches
2223 test_packet 11 f0:00:00:00:00:15 f0:00:00:00:00:11 1115 lp15 ln1
2224 test_packet 15 f0:00:00:00:00:11 f0:00:00:00:00:15 1511 lp11 ln3
2226 # lp11 and lp25 are on the same network (phys, untagged),
2227 # different hypervisors, and on different switches
2228 test_packet 11 f0:00:00:00:00:25 f0:00:00:00:00:11 1125 lp25 ln1
2229 test_packet 25 f0:00:00:00:00:11 f0:00:00:00:00:25 2511 lp11 ln3
2231 # Ports that should not be able to communicate
2232 test_packet 11 f0:00:00:00:00:13 f0:00:00:00:00:11 1113 drop ln1
2233 test_packet 11 f0:00:00:00:00:23 f0:00:00:00:00:11 1123 drop ln1
2234 test_packet 21 f0:00:00:00:00:13 f0:00:00:00:00:21 2113 drop ln1
2235 test_packet 21 f0:00:00:00:00:23 f0:00:00:00:00:21 2123 drop ln1
2236 test_packet 13 f0:00:00:00:00:11 f0:00:00:00:00:13 1311 drop ln2
2237 test_packet 13 f0:00:00:00:00:21 f0:00:00:00:00:13 1321 drop ln2
2238 test_packet 23 f0:00:00:00:00:11 f0:00:00:00:00:23 2311 drop ln2
2239 test_packet 23 f0:00:00:00:00:21 f0:00:00:00:00:23 2321 drop ln2
2241 # Dump a bunch of info helpful for debugging if there's a failure.
2243 echo "------ OVN dump ------"
2247 echo "------ hv1 dump ------"
2248 as hv1 ovs-vsctl show
2249 as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-int
2251 echo "------ hv2 dump ------"
2252 as hv2 ovs-vsctl show
2253 as hv2 ovs-ofctl -O OpenFlow13 dump-flows br-int
2255 # Now check the packets actually received against the ones expected.
2257 for j in 1 2 3 4 5; do
2258 OVN_CHECK_PACKETS([hv$i/vif$i$j-tx.pcap], [$i$j.expected])
2262 OVN_CLEANUP([hv1],[hv2])
2266 AT_SETUP([ovn -- vtep: 3 HVs, 1 VIFs/HV, 1 GW, 1 LS])
2268 AT_SKIP_IF([test $HAVE_PYTHON = no])
2271 # Configure the Northbound database
2272 ovn-nbctl ls-add lsw0
2274 ovn-nbctl lsp-add lsw0 lp1
2275 ovn-nbctl lsp-set-addresses lp1 f0:00:00:00:00:01
2277 ovn-nbctl lsp-add lsw0 lp2
2278 ovn-nbctl lsp-set-addresses lp2 f0:00:00:00:00:02
2280 ovn-nbctl lsp-add lsw0 lp-vtep
2281 ovn-nbctl lsp-set-type lp-vtep vtep
2282 ovn-nbctl lsp-set-options lp-vtep vtep-physical-switch=br-vtep vtep-logical-switch=lsw0
2283 ovn-nbctl lsp-set-addresses lp-vtep unknown
2285 # lpr, lr and lrp1 are used for the ARP request handling test only.
2286 ovn-nbctl lsp-add lsw0 lpr
2288 ovn-nbctl lrp-add lr lrp1 f0:00:00:00:00:f1 192.168.1.1/24
2289 ovn-nbctl set Logical_Switch_Port lpr type=router \
2290 options:router-port=lrp1 \
2291 addresses='"f0:00:00:00:00:f1 192.168.1.1"'
2294 net_add n1 # Network to connect hv1, hv2, and vtep
2295 net_add n2 # Network to connect vtep and hv3
2297 # Create hypervisor hv1 connected to n1
2300 ovs-vsctl add-br br-phys
2301 ovn_attach n1 br-phys 192.168.0.1
2302 ovs-vsctl add-port br-int vif1 -- set Interface vif1 external-ids:iface-id=lp1 options:tx_pcap=hv1/vif1-tx.pcap options:rxq_pcap=hv1/vif1-rx.pcap ofport-request=1
2304 # Create hypervisor hv2 connected to n1
2307 ovs-vsctl add-br br-phys
2308 ovn_attach n1 br-phys 192.168.0.2
2309 ovs-vsctl add-port br-int vif2 -- set Interface vif2 external-ids:iface-id=lp2 options:tx_pcap=hv2/vif2-tx.pcap options:rxq_pcap=hv2/vif2-rx.pcap ofport-request=1
2312 # Start the vtep emulator with a leg in both networks
2316 ovsdb-tool create "$ovs_base"/vtep/vtep.db "$abs_top_srcdir"/vtep/vtep.ovsschema || return 1
2317 ovs-appctl -t ovsdb-server ovsdb-server/add-db "$ovs_base"/vtep/vtep.db
2319 ovs-vsctl add-br br-phys
2320 net_attach n1 br-phys
2322 mac=`ovs-vsctl get Interface br-phys mac_in_use | sed s/\"//g`
2323 arp_table="$arp_table $sandbox,br-phys,192.168.0.3,$mac"
2324 ovs-appctl netdev-dummy/ip4addr br-phys 192.168.0.3/24 >/dev/null || return 1
2325 ovs-appctl ovs/route/add 192.168.0.3/24 br-phys >/dev/null || return 1
2327 ovs-vsctl add-br br-vtep
2328 net_attach n2 br-vtep
2330 vtep-ctl add-ps br-vtep
2331 vtep-ctl set Physical_Switch br-vtep tunnel_ips=192.168.0.3
2332 vtep-ctl add-ls lsw0
2334 start_daemon ovs-vtep br-vtep
2335 start_daemon ovn-controller-vtep --vtep-db=unix:"$ovs_base"/vtep/db.sock --ovnsb-db=unix:"$ovs_base"/ovn-sb/ovn-sb.sock
2337 OVS_WAIT_UNTIL([vtep-ctl bind-ls br-vtep br-vtep_n2 0 lsw0])
2339 OVS_WAIT_UNTIL([test -n "`as vtep vtep-ctl get-replication-mode lsw0 |
2341 # It takes more time for the update to be processed by ovs-vtep.
2344 # Add hv3 on the other side of the vtep
2347 ovs-vsctl add-br br-phys
2348 net_attach n2 br-phys
2350 ovs-vsctl add-port br-phys vif3 -- set Interface vif3 options:tx_pcap=hv3/vif3-tx.pcap options:rxq_pcap=hv3/vif3-rx.pcap ofport-request=1
2352 # Pre-populate the hypervisors' ARP tables so that we don't lose any
2353 # packets for ARP resolution (native tunneling doesn't queue packets
2354 # for ARP resolution).
2357 # Allow some time for ovn-northd and ovn-controller to catch up.
2358 # XXX This should be more systematic.
2361 # test_packet INPORT DST SRC ETHTYPE OUTPORT...
2363 # This shell function causes a packet to be received on INPORT. The packet's
2364 # content has Ethernet destination DST and source SRC (each exactly 12 hex
2365 # digits) and Ethernet type ETHTYPE (4 hex digits). The OUTPORTs (zero or
2366 # more) list the VIFs on which the packet should be received. INPORT and the
2367 # OUTPORTs are specified as logical switch port numbers, e.g. 1 for vif1.
2372 local inport=$1 packet=$2$3$4; shift; shift; shift; shift
2373 #hv=hv`echo $inport | sed 's/^\(.\).*/\1/'`
2376 as $hv ovs-appctl netdev-dummy/receive $vif $packet
2378 echo $packet >> $outport.expected
2382 # Send packets between all pairs of source and destination ports:
2384 # 1. Unicast packets are delivered to exactly one logical switch port
2385 # (except that packets destined to their input ports are dropped).
2387 # 2. Broadcast and multicast are delivered to all logical switch ports
2388 # except the input port.
2390 # 3. The switch delivers packets with an unknown destination to logical
2391 # switch ports with "unknown" among their MAC addresses (and port
2392 # security disabled).
2397 if test $d != $s; then unicast=$d; else unicast=; fi
2398 test_packet $s f0000000000$d f0000000000$s 00$s$d $unicast #1
2400 # The vtep (vif3) is the only one configured for "unknown"
2401 if test $d != $s && test $d = 3; then
2402 unknown="$unknown $d"
2404 bcast="$bcast $unicast"
2407 # Broadcast and multicast.
2408 test_packet $s ffffffffffff f0000000000$s 0${s}ff $bcast #2
2409 test_packet $s 010000000000 f0000000000$s 0${s}ff $bcast #2
2411 test_packet $s f0000000ffff f0000000000$s 0${s}66 $unknown #3
2414 # ARP request should not be responded to by logical switch router
2415 # type arp responder on HV1 and HV2 and should reach directly to
2418 printf "%02x%02x%02x%02x" "$@"
2421 spa=`ip_to_hex 192 168 1 2`
2422 tpa=`ip_to_hex 192 168 1 1`
2423 request=ffffffffffff${sha}08060001080006040001${sha}${spa}ffffffffffff${tpa}
2424 as hv3 ovs-appctl netdev-dummy/receive vif3 $request
2425 echo $request >> 1.expected
2426 echo $request >> 2.expected
2428 # dump information with counters
2429 echo "------ OVN dump ------"
2433 echo "---------SB dump-----"
2434 ovn-sbctl list datapath_binding
2435 echo "---------------------"
2436 ovn-sbctl list port_binding
2437 echo "---------------------"
2438 ovn-sbctl dump-flows
2440 echo "------ hv1 dump ------"
2441 as hv1 ovs-vsctl show
2442 as hv1 ovs-ofctl -O OpenFlow13 show br-int
2443 as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-int
2445 echo "------ hv2 dump ------"
2446 as hv2 ovs-vsctl show
2447 as hv2 ovs-ofctl -O OpenFlow13 show br-int
2448 as hv2 ovs-ofctl -O OpenFlow13 dump-flows br-int
2450 echo "------ hv3 dump ------"
2451 as hv3 ovs-vsctl show
2452 # note: hv3 has no logical port bind, thus it should not have br-int
2453 AT_CHECK([as hv3 ovs-ofctl -O OpenFlow13 show br-int], [1], [],
2454 [ovs-ofctl: br-int is not a bridge or a socket
2457 # Now check the packets actually received against the ones expected.
2459 OVN_CHECK_PACKETS([hv$i/vif$i-tx.pcap], [$i.expected])
2462 # Gracefully terminate daemons
2463 OVN_CLEANUP([hv1],[hv2],[vtep])
2464 OVN_CLEANUP_VSWITCH([hv3])
2468 # Similar test to "hardware GW"
2469 AT_SETUP([ovn -- 3 HVs, 1 VIFs/HV, 1 software GW, 1 LS])
2470 AT_SKIP_IF([test $HAVE_PYTHON = no])
2473 # Configure the Northbound database
2474 ovn-nbctl ls-add lsw0
2476 ovn-nbctl lsp-add lsw0 lp1
2477 ovn-nbctl lsp-set-addresses lp1 f0:00:00:00:00:01
2479 ovn-nbctl lsp-add lsw0 lp2
2480 ovn-nbctl lsp-set-addresses lp2 f0:00:00:00:00:02
2482 ovn-nbctl lsp-add lsw0 lp-gw
2483 ovn-nbctl lsp-set-type lp-gw l2gateway
2484 ovn-nbctl lsp-set-options lp-gw network_name=physnet1 l2gateway-chassis=hv_gw
2485 ovn-nbctl lsp-set-addresses lp-gw unknown
2487 net_add n1 # Network to connect hv1, hv2, and gw
2488 net_add n2 # Network to connect gw and hv3
2490 # Create hypervisor hv1 connected to n1
2493 ovs-vsctl add-br br-phys
2494 ovn_attach n1 br-phys 192.168.0.1
2495 ovs-vsctl add-port br-int vif1 -- set Interface vif1 external-ids:iface-id=lp1 options:tx_pcap=hv1/vif1-tx.pcap options:rxq_pcap=hv1/vif1-rx.pcap ofport-request=1
2497 # Create hypervisor hv2 connected to n1
2500 ovs-vsctl add-br br-phys
2501 ovn_attach n1 br-phys 192.168.0.2
2502 ovs-vsctl add-port br-int vif2 -- set Interface vif2 external-ids:iface-id=lp2 options:tx_pcap=hv2/vif2-tx.pcap options:rxq_pcap=hv2/vif2-rx.pcap ofport-request=1
2504 # Create hypervisor hv_gw connected to n1 and n2
2505 # connect br-phys bridge to n1; connect hv-gw bridge to n2
2508 ovs-vsctl add-br br-phys
2509 ovn_attach n1 br-phys 192.168.0.3
2510 ovs-vsctl add-br br-phys2
2511 net_attach n2 br-phys2
2512 ovs-vsctl set open . external_ids:ovn-bridge-mappings="physnet1:br-phys2"
2514 # Add hv3 on the other side of the GW
2517 ovs-vsctl add-br br-phys
2518 net_attach n2 br-phys
2519 ovs-vsctl add-port br-phys vif3 -- set Interface vif3 options:tx_pcap=hv3/vif3-tx.pcap options:rxq_pcap=hv3/vif3-rx.pcap ofport-request=1
2522 # Pre-populate the hypervisors' ARP tables so that we don't lose any
2523 # packets for ARP resolution (native tunneling doesn't queue packets
2524 # for ARP resolution).
2527 # Allow some time for ovn-northd and ovn-controller to catch up.
2528 # XXX This should be more systematic.
2531 # test_packet INPORT DST SRC ETHTYPE OUTPORT...
2533 # This shell function causes a packet to be received on INPORT. The packet's
2534 # content has Ethernet destination DST and source SRC (each exactly 12 hex
2535 # digits) and Ethernet type ETHTYPE (4 hex digits). The OUTPORTs (zero or
2536 # more) list the VIFs on which the packet should be received. INPORT and the
2537 # OUTPORTs are specified as lport numbers, e.g. 1 for vif1.
2542 local inport=$1 packet=$2$3$4; shift; shift; shift; shift
2543 #hv=hv`echo $inport | sed 's/^\(.\).*/\1/'`
2546 as $hv ovs-appctl netdev-dummy/receive $vif $packet
2548 echo $packet >> $outport.expected
2552 # Send packets between all pairs of source and destination ports:
2554 # 1. Unicast packets are delivered to exactly one lport (except that packets
2555 # destined to their input ports are dropped).
2557 # 2. Broadcast and multicast are delivered to all lports except the input port.
2559 # 3. The lswitch delivers packets with an unknown destination to lports with
2560 # "unknown" among their MAC addresses (and port security disabled).
2565 if test $d != $s; then unicast=$d; else unicast=; fi
2566 test_packet $s f0000000000$d f0000000000$s 00$s$d $unicast #1
2568 # The vtep (vif3) is the only one configured for "unknown"
2569 if test $d != $s && test $d = 3; then
2570 unknown="$unknown $d"
2572 bcast="$bcast $unicast"
2575 test_packet $s ffffffffffff f0000000000$s 0${s}ff $bcast #2
2576 test_packet $s 010000000000 f0000000000$s 0${s}ff $bcast #3
2577 test_packet $s f0000000ffff f0000000000$s 0${s}66 $unknown #4
2580 echo "------ ovn-nbctl show ------"
2582 echo "------ ovn-sbctl show ------"
2585 echo "------ hv1 ------"
2586 as hv1 ovs-vsctl show
2587 echo "------ hv1 br-int ------"
2588 as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-int
2589 echo "------ hv1 br-phys ------"
2590 as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-phys
2592 echo "------ hv2 ------"
2593 as hv2 ovs-vsctl show
2594 echo "------ hv2 br-int ------"
2595 as hv2 ovs-ofctl -O OpenFlow13 dump-flows br-int
2596 echo "------ hv2 br-phys ------"
2597 as hv2 ovs-ofctl -O OpenFlow13 dump-flows br-phys
2599 echo "------ hv_gw ------"
2600 as hv_gw ovs-vsctl show
2601 echo "------ hv_gw br-phys ------"
2602 as hv_gw ovs-ofctl -O OpenFlow13 dump-flows br-phys
2603 echo "------ hv_gw br-phys2 ------"
2604 as hv_gw ovs-ofctl -O OpenFlow13 dump-flows br-phys2
2606 echo "------ hv3 ------"
2607 as hv3 ovs-vsctl show
2608 echo "------ hv3 br-phys ------"
2609 as hv3 ovs-ofctl -O OpenFlow13 dump-flows br-phys
2611 # Now check the packets actually received against the ones expected.
2613 OVN_CHECK_PACKETS([hv$i/vif$i-tx.pcap], [$i.expected])
2617 # 3 hypervisors, 3 logical switches with 3 logical ports each, 1 logical router
2618 AT_SETUP([ovn -- 3 HVs, 3 LS, 3 lports/LS, 1 LR])
2619 AT_SKIP_IF([test $HAVE_PYTHON = no])
2624 # Three logical switches ls1, ls2, ls3.
2625 # One logical router lr0 connected to ls[123],
2626 # with nine subnets, three per logical switch:
2628 # lrp11 on ls1 for subnet 192.168.11.0/24
2629 # lrp12 on ls1 for subnet 192.168.12.0/24
2630 # lrp13 on ls1 for subnet 192.168.13.0/24
2632 # lrp33 on ls3 for subnet 192.168.33.0/24
2634 # 27 VIFs, 9 per LS, 3 per subnet: lp[123][123][123], where the first two
2635 # digits are the subnet and the last digit distinguishes the VIF.
2637 ovn-nbctl ls-add ls$i
2640 # Add "unknown" to MAC addresses for lp?11, so packets for
2641 # MAC-IP bindings discovered via ARP later have somewhere to go.
2642 if test $j$k = 11; then unknown=unknown; else unknown=; fi
2645 -- lsp-add ls$i lp$i$j$k \
2646 -- lsp-set-addresses lp$i$j$k \
2647 "f0:00:00:00:0$i:$j$k 192.168.$i$j.$k" $unknown
2652 ovn-nbctl lr-add lr0
2655 ovn-nbctl lrp-add lr0 lrp$i$j 00:00:00:00:ff:$i$j 192.168.$i$j.254/24
2657 -- lsp-add ls$i lrp$i$j-attachment \
2658 -- set Logical_Switch_Port lrp$i$j-attachment type=router \
2659 options:router-port=lrp$i$j \
2660 addresses='"00:00:00:00:ff:'$i$j'"'
2664 ovn-nbctl set Logical_Switch_Port lrp33-attachment \
2665 addresses='"00:00:00:00:ff:33 192.168.33.254"'
2669 # Three hypervisors hv[123].
2670 # lp?1[123] spread across hv[123]: lp?11 on hv1, lp?12 on hv2, lp?13 on hv3.
2671 # lp?2[123] spread across hv[23]: lp?21 and lp?22 on hv2, lp?23 on hv3.
2672 # lp?3[123] all on hv3.
2675 # Given the name of a logical port, prints the name of the hypervisor
2676 # on which it is located.
2679 ?11) echo 1 ;; dnl (
2680 ?12 | ?21 | ?22) echo 2 ;; dnl (
2681 ?13 | ?23 | ?3?) echo 3 ;;
2685 # Given the name of a logical port, prints the name of its logical router
2686 # port, e.g. "vif_to_lrp 123" yields 12.
2691 # Given the name of a logical port, prints the name of its logical
2692 # switch, e.g. "vif_to_ls 123" yields 1.
2701 ovs-vsctl add-br br-phys
2702 ovn_attach n1 br-phys 192.168.0.$i
2707 hv=`vif_to_hv $i$j$k`
2708 as hv$hv ovs-vsctl \
2709 -- add-port br-int vif$i$j$k \
2710 -- set Interface vif$i$j$k \
2711 external-ids:iface-id=lp$i$j$k \
2712 options:tx_pcap=hv$hv/vif$i$j$k-tx.pcap \
2713 options:rxq_pcap=hv$hv/vif$i$j$k-rx.pcap \
2714 ofport-request=$i$j$k
2719 # Pre-populate the hypervisors' ARP tables so that we don't lose any
2720 # packets for ARP resolution (native tunneling doesn't queue packets
2721 # for ARP resolution).
2724 # Allow some time for ovn-northd and ovn-controller to catch up.
2725 # XXX This should be more systematic.
2728 # test_ip INPORT SRC_MAC DST_MAC SRC_IP DST_IP OUTPORT...
2730 # This shell function causes a packet to be received on INPORT. The packet's
2731 # content has Ethernet destination DST and source SRC (each exactly 12 hex
2732 # digits) and Ethernet type ETHTYPE (4 hex digits). The OUTPORTs (zero or
2733 # more) list the VIFs on which the packet should be received. INPORT and the
2734 # OUTPORTs are specified as logical switch port numbers, e.g. 123 for vif123.
2743 # This packet has bad checksums but logical L3 routing doesn't check.
2744 local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
2745 local packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
2746 shift; shift; shift; shift; shift
2747 hv=hv`vif_to_hv $inport`
2748 as $hv ovs-appctl netdev-dummy/receive vif$inport $packet
2749 #as $hv ovs-appctl ofproto/trace br-int in_port=$inport $packet
2750 in_ls=`vif_to_ls $inport`
2751 in_lrp=`vif_to_lrp $inport`
2753 out_ls=`vif_to_ls $outport`
2754 if test $in_ls = $out_ls; then
2755 # Ports on the same logical switch receive exactly the same packet.
2758 # Routing decrements TTL and updates source and dest MAC
2760 out_lrp=`vif_to_lrp $outport`
2761 echo f00000000${outport}00000000ff${out_lrp}08004500001c00000000"3f1101"00${src_ip}${dst_ip}0035111100080000
2762 fi >> $outport.expected
2766 # test_arp INPORT SHA SPA TPA [REPLY_HA]
2768 # Causes a packet to be received on INPORT. The packet is an ARP
2769 # request with SHA, SPA, and TPA as specified. If REPLY_HA is provided, then
2770 # it should be the hardware address of the target to expect to receive in an
2771 # ARP reply; otherwise no reply is expected.
2773 # INPORT is an logical switch port number, e.g. 11 for vif11.
2774 # SHA and REPLY_HA are each 12 hex digits.
2775 # SPA and TPA are each 8 hex digits.
2777 local inport=$1 sha=$2 spa=$3 tpa=$4 reply_ha=$5
2778 local request=ffffffffffff${sha}08060001080006040001${sha}${spa}ffffffffffff${tpa}
2779 hv=hv`vif_to_hv $inport`
2780 as $hv ovs-appctl netdev-dummy/receive vif$inport $request
2781 as $hv ovs-appctl ofproto/trace br-int in_port=$inport $request
2783 # Expect to receive the broadcast ARP on the other logical switch ports if
2784 # IP address is not configured to the switch patch port.
2785 local i=`vif_to_ls $inport`
2789 # 192.168.33.254 is configured to the switch patch port for lrp33,
2790 # so no ARP flooding expected for it.
2791 if test $i$j$k != $inport && test $tpa != `ip_to_hex 192 168 33 254`; then
2792 echo $request >> $i$j$k.expected
2797 # Expect to receive the reply, if any.
2798 if test X$reply_ha != X; then
2799 lrp=`vif_to_lrp $inport`
2800 local reply=${sha}00000000ff${lrp}08060001080006040002${reply_ha}${tpa}${sha}${spa}
2801 echo $reply >> $inport.expected
2805 as hv1 ovs-vsctl --columns=name,ofport list interface
2806 as hv1 ovn-sbctl list port_binding
2807 as hv1 ovn-sbctl list datapath_binding
2808 as hv1 ovn-sbctl dump-flows
2809 as hv1 ovs-ofctl dump-flows br-int
2811 # Send IP packets between all pairs of source and destination ports:
2813 # 1. Unicast IP packets are delivered to exactly one logical switch port
2814 # (except that packets destined to their input ports are dropped).
2816 # 2. Broadcast IP packets are delivered to all logical switch ports
2817 # except the input port.
2819 printf "%02x%02x%02x%02x" "$@"
2827 sip=`ip_to_hex 192 168 $is$js $ks`
2832 dip=`ip_to_hex 192 168 $id$jd $kd`
2833 if test $is = $id; then dmac=f00000000$d; else dmac=00000000ff$is$js; fi
2834 if test $d != $s; then unicast=$d; else unicast=; fi
2836 test_ip $s $smac $dmac $sip $dip $unicast #1
2838 if test $id = $is && test $d != $s; then bcast="$bcast $d"; fi
2842 test_ip $s $smac ffffffffffff $sip ffffffff $bcast #2
2847 : > mac_bindings.expected
2849 # 3. Send an IP packet from every logical port to every other subnet,
2850 # to an IP address that does not have a static IP-MAC binding.
2851 # This should generate a broadcast ARP request for the destination
2852 # IP address in the destination subnet.
2853 # Moreover generate an ARP reply for each of the IP addresses ARPed
2859 sip=`ip_to_hex 192 168 $is$js $ks`
2862 if test $is$js = $id$jd; then
2867 dmac=00000000ff$is$js
2868 # Calculate a 4th octet for the destination that is
2869 # unique per $s, avoids the .1 .2 .3 and .254 IP addresses
2870 # that have static MAC bindings, and fits in the range
2872 o4=`expr $is '*' 9 + $js '*' 3 + $ks + 10`
2873 dip=`ip_to_hex 192 168 $id$jd $o4`
2874 test_ip $s $smac $dmac $sip $dip
2876 # Every LP on the destination subnet's lswitch should
2877 # receive the ARP request.
2878 lrmac=00000000ff$id$jd
2879 lrip=`ip_to_hex 192 168 $id$jd 254`
2880 arp=ffffffffffff${lrmac}08060001080006040001${lrmac}${lrip}000000000000${dip}
2881 for jd2 in 1 2 3; do
2883 echo $arp >> $id$jd2$kd.expected
2888 rmac=00000000ff$id$jd
2889 echo ${hmac}${rmac}08004500001c00000000"3f1101"00${sip}${dip}0035111100080000 >> ${id}11.expected
2891 host_mac=8000000000$o4
2892 lrmac=00000000ff$id$jd
2894 arp_reply=${lrmac}${host_mac}08060001080006040002${host_mac}${dip}${lrmac}${lrip}
2896 hv=hv`vif_to_hv ${id}${jd}1`
2897 as $hv ovs-appctl netdev-dummy/receive vif${id}${jd}1 $arp_reply
2899 host_ip_pretty=192.168.$id$jd.$o4
2900 host_mac_pretty=80:00:00:00:00:$o4
2901 echo lrp$id$jd,$host_ip_pretty,$host_mac_pretty >> mac_bindings.expected
2908 # Test router replies to ARP requests from all source ports:
2910 # 4. Router replies to query for its MAC address from port's own IP address.
2912 # 5. Router replies to query for its MAC address from any random IP address
2915 # 6. No reply to query for IP address other than router IP.
2917 # 7. No reply to query from another subnet.
2921 smac=f00000000$i$j$k # Source MAC
2922 sip=`ip_to_hex 192 168 $i$j $k` # Source IP
2923 rip=`ip_to_hex 192 168 $i$j 254` # Router IP
2924 rmac=00000000ff$i$j # Router MAC
2925 otherip=`ip_to_hex 192 168 $i$j 55` # Some other IP in subnet
2926 externalip=`ip_to_hex 1 2 3 4` # Some other IP not in subnet
2928 test_arp $i$j$k $smac $sip $rip $rmac #4
2929 test_arp $i$j$k $smac $otherip $rip $rmac #5
2930 test_arp $i$j$k $smac $sip $otherip #6
2932 # When rip is 192.168.33.254, ARP request from externalip won't be
2933 # filtered, because 192.168.33.254 is configured to switch peer port
2936 if test $i = 3 && test $j = 3; then
2939 test_arp $i$j$k $smac $externalip $rip $lrp33_rsp #7
2941 # MAC binding should be learned from ARP request.
2942 host_mac_pretty=f0:00:00:00:0$i:$j$k
2944 host_ip_pretty=192.168.$i$j.$k
2945 echo lrp$i$j,$host_ip_pretty,$host_mac_pretty >> mac_bindings.expected
2947 # mac_binding is learned and overwritten so only the last one remains.
2948 if test $k = 3; then
2949 # lrp33 will not learn from ARP request, because 192.168.33.254 is
2950 # configured to switch peer port for lrp33.
2951 if test $i != 3 || test $j != 3; then
2952 host_ip_pretty=192.168.$i$j.55
2953 echo lrp$i$j,$host_ip_pretty,$host_mac_pretty >> mac_bindings.expected
2962 # Allow some time for packet forwarding.
2963 # XXX This can be improved.
2966 # 8. Send an IP packet from every logical port to every other subnet. These
2967 # are the same packets already sent as #3, but now the destinations' IP-MAC
2968 # bindings have been discovered via ARP, so instead of provoking an ARP
2969 # request, these packets now get routed to their destinations (which don't
2970 # have static MAC bindings, so they go to the port we've designated as
2971 # accepting "unknown" MACs.)
2977 sip=`ip_to_hex 192 168 $is$js $ks`
2980 if test $is$js = $id$jd; then
2985 dmac=00000000ff$is$js
2986 # Calculate a 4th octet for the destination that is
2987 # unique per $s, avoids the .1 .2 .3 and .254 IP addresses
2988 # that have static MAC bindings, and fits in the range
2990 o4=`expr $is '*' 9 + $js '*' 3 + $ks + 10`
2991 dip=`ip_to_hex 192 168 $id$jd $o4`
2992 test_ip $s $smac $dmac $sip $dip
2994 # Expect the packet egress.
2995 host_mac=8000000000$o4
2998 echo ${host_mac}00000000ff${out_lrp}08004500001c00000000"3f1101"00${sip}${dip}0035111100080000 >> $outport.expected
3005 ovn-sbctl -f csv -d bare --no-heading \
3006 -- --columns=logical_port,ip,mac list mac_binding > mac_bindings
3008 # Now check the packets actually received against the ones expected.
3012 OVN_CHECK_PACKETS([hv`vif_to_hv $i$j$k`/vif$i$j$k-tx.pcap],
3018 # Check the MAC bindings against those expected.
3019 AT_CHECK_UNQUOTED([sort < mac_bindings], [0], [`sort < mac_bindings.expected`
3022 # Gracefully terminate daemons
3023 OVN_CLEANUP([hv1], [hv2], [hv3])
3027 AT_SETUP([ovn -- IP relocation using GARP request])
3028 AT_SKIP_IF([test $HAVE_PYTHON = no])
3033 # Two logical switches ls1, ls2.
3034 # One logical router lr0 connected to ls[12],
3035 # with 2 subnets, 1 per logical switch:
3037 # lrp1 on ls1 for subnet 192.168.1.1/24
3038 # lrp2 on ls2 for subnet 192.168.2.1/24
3040 # 4 VIFs, 2 per LS lp[12][12], first digit being LS.
3041 # VIFs' fixed IP addresses are 192.168.[12].1[12].
3043 # There is a secondary IP 192.168.1.100 that is unknown in NB and learned
3044 # through ARP only, and it can move between lp11 and lp12.
3046 ovn-nbctl lr-add lr0
3048 ovn-nbctl ls-add ls$i
3049 ovn-nbctl lrp-add lr0 lrp$i 00:00:00:00:ff:0$i 192.168.$i.1/24
3051 -- lsp-add ls$i lrp$i-attachment \
3052 -- set Logical_Switch_Port lrp$i-attachment type=router \
3053 options:router-port=lrp$i \
3057 -- lsp-add ls$i lp$i$j \
3058 -- lsp-set-addresses lp$i$j \
3059 "f0:00:00:00:00:$i$j 192.168.$i.1$j"
3064 # 2 hypervisors hv[12], lp?1 on hv1, lp?2 on hv2.
3066 # Given the name of a logical port, prints the name of the hypervisor
3067 # on which it is located, e.g. "vif_to_hv 12" yields 2.
3072 # Given the name of a logical port, prints the name of its logical router
3073 # port, e.g. "vif_to_lrp 12" yields 1.
3078 # Given the name of a logical port, prints the name of its logical
3079 # switch, e.g. "vif_to_ls 12" yields 1.
3088 ovs-vsctl add-br br-phys
3089 ovn_attach n1 br-phys 192.168.0.$i
3094 as hv$hv ovs-vsctl \
3095 -- add-port br-int vif$i$j \
3096 -- set Interface vif$i$j \
3097 external-ids:iface-id=lp$i$j \
3098 options:tx_pcap=hv$hv/vif$i$j-tx.pcap \
3099 options:rxq_pcap=hv$hv/vif$i$j-rx.pcap \
3104 # Pre-populate the hypervisors' ARP tables so that we don't lose any
3105 # packets for ARP resolution (native tunneling doesn't queue packets
3106 # for ARP resolution).
3109 # Allow some time for ovn-northd and ovn-controller to catch up.
3110 # XXX This should be more systematic.
3113 # test_ip INPORT SRC_MAC DST_MAC SRC_IP DST_IP OUTPORT...
3115 # This shell function causes a packet to be received on INPORT. The packet's
3116 # content has Ethernet destination DST and source SRC (each exactly 12 hex
3117 # digits) and Ethernet type ETHTYPE (4 hex digits). The OUTPORTs (zero or
3118 # more) list the VIFs on which the packet should be received. INPORT and the
3119 # OUTPORTs are specified as logical switch port numbers, e.g. 12 for vif12.
3126 # This packet has bad checksums but logical L3 routing doesn't check.
3127 local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
3128 local packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
3129 shift; shift; shift; shift; shift
3130 hv=hv`vif_to_hv $inport`
3131 as $hv ovs-appctl netdev-dummy/receive vif$inport $packet
3132 in_ls=`vif_to_ls $inport`
3133 in_lrp=`vif_to_lrp $inport`
3135 out_ls=`vif_to_ls $outport`
3136 if test $in_ls = $out_ls; then
3137 # Ports on the same logical switch receive exactly the same packet.
3140 # Routing decrements TTL and updates source and dest MAC
3142 out_lrp=`vif_to_lrp $outport`
3143 echo f000000000${outport}00000000ff0${out_lrp}08004500001c00000000"3f1101"00${src_ip}${dst_ip}0035111100080000
3144 fi >> $outport.expected
3148 # test_arp INPORT SHA SPA TPA [REPLY_HA]
3150 # Causes a packet to be received on INPORT. The packet is an ARP
3151 # request with SHA, SPA, and TPA as specified. If REPLY_HA is provided, then
3152 # it should be the hardware address of the target to expect to receive in an
3153 # ARP reply; otherwise no reply is expected.
3155 # INPORT is an logical switch port number, e.g. 11 for vif11.
3156 # SHA and REPLY_HA are each 12 hex digits.
3157 # SPA and TPA are each 8 hex digits.
3159 local inport=$1 sha=$2 spa=$3 tpa=$4 reply_ha=$5
3160 local request=ffffffffffff${sha}08060001080006040001${sha}${spa}ffffffffffff${tpa}
3161 hv=hv`vif_to_hv $inport`
3162 as $hv ovs-appctl netdev-dummy/receive vif$inport $request
3164 # Expect to receive the broadcast ARP on the other logical switch ports if
3165 # IP address is not configured to the switch patch port.
3166 local i=`vif_to_ls $inport`
3169 if test $i$j != $inport; then
3170 echo $request >> $i$j$k.expected
3174 # Expect to receive the reply, if any.
3175 if test X$reply_ha != X; then
3176 lrp=`vif_to_lrp $inport`
3177 local reply=${sha}00000000ff0${lrp}08060001080006040002${reply_ha}${tpa}${sha}${spa}
3178 echo $reply >> $inport.expected
3183 printf "%02x%02x%02x%02x" "$@"
3186 # lp11 send GARP request to announce ownership of 192.168.1.100.
3189 spa=`ip_to_hex 192 168 1 100`
3191 test_arp 11 $sha $spa $tpa
3192 OVS_WAIT_UNTIL([test `ovn-sbctl find mac_binding ip="192.168.1.100" | wc -l` -gt 0])
3193 ovn-nbctl --wait=hv sync
3195 # Send an IP packet from lp21 to 192.168.1.100, which should go to lp11.
3199 sip=`ip_to_hex 192 168 2 11`
3200 dip=`ip_to_hex 192 168 1 100`
3201 test_ip 21 $smac $dmac $sip $dip 11
3203 # lp12 send GARP request to announce ownership of 192.168.1.100.
3206 test_arp 12 $sha $spa $tpa
3207 OVS_WAIT_UNTIL([ovn-sbctl find mac_binding ip="192.168.1.100" | grep f0:00:00:00:00:12])
3208 ovn-nbctl --wait=hv sync
3209 # give to the hv the time to send queued ip packets
3212 # Send an IP packet from lp21 to 192.168.1.100, which should go to lp12.
3214 test_ip 21 $smac $dmac $sip $dip 12
3216 # Now check the packets actually received against the ones expected.
3219 OVN_CHECK_PACKETS([hv`vif_to_hv $i$j`/vif$i$j-tx.pcap],
3224 # Gracefully terminate daemons
3225 OVN_CLEANUP([hv1], [hv2])
3229 # 3 hypervisors, one logical switch, 3 logical ports per hypervisor
3230 AT_SETUP([ovn -- portsecurity : 3 HVs, 1 LS, 3 lports/HV])
3231 AT_SKIP_IF([test $HAVE_PYTHON = no])
3234 # Create hypervisors hv[123].
3235 # Add vif1[123] to hv1, vif2[123] to hv2, vif3[123] to hv3.
3236 # Add all of the vifs to a single logical switch lsw0.
3237 # Turn off port security on vifs vif[123]1
3238 # Turn on l2 port security on vifs vif[123]2
3239 # Turn of l2 and l3 port security on vifs vif[123]3
3240 # Make vif13, vif2[23], vif3[123] destinations for unknown MACs.
3241 ovn-nbctl ls-add lsw0
3246 ovs-vsctl add-br br-phys
3247 ovn_attach n1 br-phys 192.168.0.$i
3250 ovs-vsctl add-port br-int vif$i$j -- set Interface vif$i$j external-ids:iface-id=lp$i$j options:tx_pcap=hv$i/vif$i$j-tx.pcap options:rxq_pcap=hv$i/vif$i$j-rx.pcap ofport-request=$i$j
3251 ovn-nbctl lsp-add lsw0 lp$i$j
3252 if test $j = 1; then
3253 ovn-nbctl lsp-set-addresses lp$i$j "f0:00:00:00:00:$i$j 192.168.0.$i$j" unknown
3254 elif test $j = 2; then
3255 ovn-nbctl lsp-set-addresses lp$i$j "f0:00:00:00:00:$i$j 192.168.0.$i$j"
3256 ovn-nbctl lsp-set-port-security lp$i$j f0:00:00:00:00:$i$j
3258 extra_addr="f0:00:00:00:0$i:$i$j fe80::ea2a:eaff:fe28:$i$j"
3259 ovn-nbctl lsp-set-addresses lp$i$j "f0:00:00:00:00:$i$j 192.168.0.$i$j" "$extra_addr"
3260 ovn-nbctl lsp-set-port-security lp$i$j "f0:00:00:00:00:$i$j 192.168.0.$i$j" "$extra_addr"
3265 # Pre-populate the hypervisors' ARP tables so that we don't lose any
3266 # packets for ARP resolution (native tunneling doesn't queue packets
3267 # for ARP resolution).
3270 # Allow some time for ovn-northd and ovn-controller to catch up.
3271 # XXX This should be more systematic.
3274 # Given the name of a logical port, prints the name of the hypervisor
3275 # on which it is located.
3286 # test_ip INPORT SRC_MAC DST_MAC SRC_IP DST_IP OUTPORT...
3288 # This shell function causes an ip packet to be received on INPORT.
3289 # The packet's content has Ethernet destination DST and source SRC
3290 # (each exactly 12 hex digits) and Ethernet type ETHTYPE (4 hex digits).
3291 # The OUTPORTs (zero or more) list the VIFs on which the packet should
3292 # be received. INPORT and the OUTPORTs are specified as logical switch
3293 # port numbers, e.g. 11 for vif11.
3295 # This packet has bad checksums but logical L3 routing doesn't check.
3296 local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
3297 local packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
3298 shift; shift; shift; shift; shift
3299 hv=`vif_to_hv $inport`
3300 as $hv ovs-appctl netdev-dummy/receive vif$inport $packet
3301 #as $hv ovs-appctl ofproto/trace br-int in_port=$inport $packet
3303 echo $packet >> $outport.expected
3307 # test_arp INPORT SHA SPA TPA DROP [REPLY_HA]
3309 # Causes a packet to be received on INPORT. The packet is an ARP
3310 # request with SHA, SPA, and TPA as specified. If REPLY_HA is provided, then
3311 # it should be the hardware address of the target to expect to receive in an
3312 # ARP reply; otherwise no reply is expected.
3314 # INPORT is an logical switch port number, e.g. 11 for vif11.
3315 # SHA and REPLY_HA are each 12 hex digits.
3316 # SPA and TPA are each 8 hex digits.
3318 local inport=$1 smac=$2 sha=$3 spa=$4 tpa=$5 drop=$6 reply_ha=$7
3319 local request=ffffffffffff${smac}08060001080006040001${sha}${spa}ffffffffffff${tpa}
3320 hv=`vif_to_hv $inport`
3321 as $hv ovs-appctl netdev-dummy/receive vif$inport $request
3322 #as $hv ovs-appctl ofproto/trace br-int in_port=$inport $request
3323 if test $drop != 1; then
3324 if test X$reply_ha = X; then
3325 # Expect to receive the broadcast ARP on the other logical switch ports
3326 # if no reply is expected.
3330 if test $i$j != $inport; then
3331 echo $request >> $i$j.expected
3336 # Expect to receive the reply, if any.
3337 local reply=${smac}${reply_ha}08060001080006040002${reply_ha}${tpa}${sha}${spa}
3338 echo $reply >> $inport.expected
3343 # test_ipv6 INPORT SRC_MAC DST_MAC SRC_IP DST_IP OUTPORT...
3344 # This function is similar to test_ip() except that it sends
3347 local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
3348 local packet=${dst_mac}${src_mac}86dd6000000000083aff${src_ip}${dst_ip}0000000000000000
3349 shift; shift; shift; shift; shift
3350 hv=`vif_to_hv $inport`
3351 as $hv ovs-appctl netdev-dummy/receive vif$inport $packet
3352 #as $hv ovs-appctl ofproto/trace br-int in_port=$inport $packet
3354 echo $packet >> $outport.expected
3358 # test_icmpv6 INPORT SRC_MAC DST_MAC SRC_IP DST_IP ICMP_TYPE OUTPORT...
3359 # This function is similar to test_ipv6() except it specifies the ICMPv6 type
3360 # of the test packet
3362 local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5 icmp_type=$6
3363 local packet=${dst_mac}${src_mac}86dd6000000000083aff${src_ip}${dst_ip}${icmp_type}00000000000000
3364 shift; shift; shift; shift; shift; shift
3365 hv=`vif_to_hv $inport`
3366 as $hv ovs-appctl netdev-dummy/receive vif$inport $packet
3367 #as $hv ovs-appctl ofproto/trace br-int in_port=$inport $packet
3369 echo $packet >> $outport.expected
3374 printf "%02x%02x%02x%02x" "$@"
3378 sip=`ip_to_hex 192 168 0 12`
3379 tip=`ip_to_hex 192 168 0 13`
3380 # the arp packet should be allowed even if lp[123]1 is
3381 # not configured with mac f00000000023 and ip 192.168.0.12
3383 test_arp ${i}1 f00000000023 f00000000023 $sip $tip 0 f00000000013
3385 if test $i != $j; then
3386 test_ip ${i}1 f000000000${i}1 f000000000${j}1 $sip $tip ${j}1
3392 sip=`ip_to_hex 192 168 0 12`
3393 tip=`ip_to_hex 192 168 0 13`
3395 # arp packet should be allowed since lp22 is configured with
3397 test_arp 22 f00000000022 f00000000022 $sip $tip 0 f00000000013
3399 # arp packet should not be allowed since lp32 is not configured with
3401 test_arp 32 f00000000021 f00000000021 $sip $tip 1
3403 # arp packet with sha set to f00000000021 should not be allowed
3405 test_arp 12 f00000000012 f00000000021 $sip $tip 1
3407 # ip packets should be allowed and received since lp[123]2 do not
3408 # have l3 port security
3409 sip=`ip_to_hex 192 168 0 55`
3410 tip=`ip_to_hex 192 168 0 66`
3413 if test $i != $j; then
3414 test_ip ${i}2 f000000000${i}2 f000000000${j}2 $sip $tip ${j}2
3419 # ipv6 packets should be received by lp[123]2
3420 # lp[123]1 can send ipv6 traffic as there is no port security
3421 sip=fe800000000000000000000000000000
3422 tip=ff020000000000000000000000000000
3425 test_ipv6 ${i}1 f000000000${i}1 f000000000${i}2 $sip $tip ${i}2
3429 # l2 and l3 port security
3430 sip=`ip_to_hex 192 168 0 13`
3431 tip=`ip_to_hex 192 168 0 22`
3432 # arp packet should be allowed since lp13 is configured with
3433 # f00000000013 and 192.168.0.13
3434 test_arp 13 f00000000013 f00000000013 $sip $tip 0 f00000000022
3436 # the arp packet should be dropped because lp23 is not configured
3437 # with mac f00000000022
3438 sip=`ip_to_hex 192 168 0 13`
3439 tip=`ip_to_hex 192 168 0 22`
3440 test_arp 23 f00000000022 f00000000022 $sip $tip 1
3442 # the arp packet should be dropped because lp33 is not configured
3443 # with ip 192.168.0.55
3444 spa=`ip_to_hex 192 168 0 55`
3445 tpa=`ip_to_hex 192 168 0 22`
3446 test_arp 33 f00000000031 f00000000031 $spa $tpa 1
3448 # ip packets should not be received by lp[123]3 since
3449 # l3 port security is enabled
3450 sip=`ip_to_hex 192 168 0 55`
3451 tip=`ip_to_hex 192 168 0 66`
3454 test_ip ${i}2 f000000000${i}2 f000000000${j}3 $sip $tip
3458 # ipv6 packets should be dropped for lp[123]3 since
3459 # it is configured with only ipv4 address
3460 sip=fe800000000000000000000000000000
3461 tip=ff020000000000000000000000000000
3464 test_ipv6 ${i}3 f000000000${i}3 f00000000022 $sip $tip
3467 # ipv6 packets should not be received by lp[123]3 with mac f000000000$[123]3
3468 # lp[123]1 can send ipv6 traffic as there is no port security
3470 test_ipv6 ${i}1 f000000000${i}1 f000000000${i}3 $sip $tip
3473 # lp13 has extra port security with mac f0000000113 and ipv6 addr
3474 # fe80::ea2a:eaff:fe28:0012
3476 # ipv4 packet should be dropped for lp13 with mac f0000000113
3477 sip=`ip_to_hex 192 168 0 13`
3478 tip=`ip_to_hex 192 168 0 23`
3479 test_ip 13 f00000000113 f00000000023 $sip $tip
3481 # ipv6 packet should be received by lp[123]3 with mac f00000000${i}${i}3
3482 # and ip6.dst as fe80::ea2a:eaff:fe28:0${i}${i}3.
3483 # lp11 can send ipv6 traffic as there is no port security
3484 sip=ee800000000000000000000000000000
3486 tip=fe80000000000000ea2aeafffe2800${i}3
3487 test_ipv6 11 f00000000011 f00000000${i}${i}3 $sip $tip ${i}3
3491 # ipv6 packet should not be received by lp33 with mac f0000000333
3492 # and ip6.dst as fe80::ea2a:eaff:fe28:0023 as it is
3493 # configured with fe80::ea2a:eaff:fe28:0033
3494 # lp11 can send ipv6 traffic as there is no port security
3496 sip=ee800000000000000000000000000000
3497 tip=fe80000000000000ea2aeafffe280023
3498 test_ipv6 11 f00000000011 f00000000333 $sip $tip
3500 # ipv6 packet should be allowed for lp[123]3 with mac f0000000${i}${i}3
3501 # and ip6.src fe80::ea2a:eaff:fe28:0${i}${i}3 and ip6.src ::.
3502 # and should be dropped for any other ip6.src
3503 # lp21 can receive ipv6 traffic as there is no port security
3505 tip=ee800000000000000000000000000000
3507 sip=fe80000000000000ea2aeafffe2800${i}3
3508 test_ipv6 ${i}3 f00000000${i}${i}3 f00000000021 $sip $tip 21
3510 # Test ICMPv6 MLD reports (v1 and v2) and NS for DAD
3511 sip=00000000000000000000000000000000
3512 test_icmpv6 ${i}3 f00000000${i}${i}3 f00000000021 $sip ff020000000000000000000000160000 83 21
3513 test_icmpv6 ${i}3 f00000000${i}${i}3 f00000000021 $sip ff020000000000000000000000160000 8f 21
3514 test_icmpv6 ${i}3 f00000000${i}${i}3 f00000000021 $sip ff0200000000000000ea2aeafffe2800 87 21
3515 # Traffic to non-multicast traffic should be dropped
3516 test_icmpv6 ${i}3 f00000000${i}${i}3 f00000000021 $sip $tip 83
3517 # Traffic of other ICMPv6 types should be dropped
3518 test_icmpv6 ${i}3 f00000000${i}${i}3 f00000000021 $sip ff020000000000000000000000160000 80
3521 sip=ae80000000000000ea2aeafffe2800aa
3522 test_ipv6 ${i}3 f00000000${i}${i}3 f00000000021 $sip $tip
3525 # configure lsp13 to send and received IPv4 packets with an address range
3526 ovn-nbctl lsp-set-port-security lp13 "f0:00:00:00:00:13 192.168.0.13 20.0.0.4/24 10.0.0.0/24"
3530 sip=`ip_to_hex 10 0 0 13`
3531 tip=`ip_to_hex 192 168 0 22`
3532 # arp packet with inner ip 10.0.0.13 should be allowed for lsp13
3533 test_arp 13 f00000000013 f00000000013 $sip $tip 0 f00000000022
3535 sip=`ip_to_hex 10 0 0 14`
3536 tip=`ip_to_hex 192 168 0 23`
3537 # IPv4 packet from lsp13 with src ip 10.0.0.14 destined to lsp23
3538 # with dst ip 192.168.0.23 should be allowed
3539 test_ip 13 f00000000013 f00000000023 $sip $tip 23
3541 sip=`ip_to_hex 192 168 0 33`
3542 tip=`ip_to_hex 10 0 0 15`
3543 # IPv4 packet from lsp33 with src ip 192.168.0.33 destined to lsp13
3544 # with dst ip 10.0.0.15 should be received by lsp13
3545 test_ip 33 f00000000033 f00000000013 $sip $tip 13
3547 sip=`ip_to_hex 192 168 0 33`
3548 tip=`ip_to_hex 20 0 0 4`
3549 # IPv4 packet from lsp33 with src ip 192.168.0.33 destined to lsp13
3550 # with dst ip 20.0.0.4 should be received by lsp13
3551 test_ip 33 f00000000033 f00000000013 $sip $tip 13
3553 sip=`ip_to_hex 192 168 0 33`
3554 tip=`ip_to_hex 20 0 0 5`
3555 # IPv4 packet from lsp33 with src ip 192.168.0.33 destined to lsp13
3556 # with dst ip 20.0.0.5 should not be received by lsp13
3557 test_ip 33 f00000000033 f00000000013 $sip $tip
3559 sip=`ip_to_hex 192 168 0 33`
3560 tip=`ip_to_hex 20 0 0 255`
3561 # IPv4 packet from lsp33 with src ip 192.168.0.33 destined to lsp13
3562 # with dst ip 20.0.0.255 should be received by lsp13
3563 test_ip 33 f00000000033 f00000000013 $sip $tip 13
3565 sip=`ip_to_hex 192 168 0 33`
3566 tip=`ip_to_hex 192 168 0 255`
3567 # IPv4 packet from lsp33 with src ip 192.168.0.33 destined to lsp13
3568 # with dst ip 192.168.0.255 should not be received by lsp13
3569 test_ip 33 f00000000033 f00000000013 $sip $tip
3571 sip=`ip_to_hex 192 168 0 33`
3572 tip=`ip_to_hex 224 0 0 4`
3573 # IPv4 packet from lsp33 with src ip 192.168.0.33 destined to lsp13
3574 # with dst ip 224.0.0.4 should be received by lsp13
3575 test_ip 33 f00000000033 f00000000013 $sip $tip 13
3577 #dump information including flow counters
3579 ovn-sbctl dump-flows -- list multicast_group
3581 echo "------ hv1 dump ------"
3582 as hv1 ovs-vsctl show
3583 as hv1 ovs-ofctl -O OpenFlow13 show br-int
3584 as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-int
3586 echo "------ hv2 dump ------"
3587 as hv2 ovs-vsctl show
3588 as hv2 ovs-ofctl -O OpenFlow13 show br-int
3589 as hv2 ovs-ofctl -O OpenFlow13 dump-flows br-int
3591 echo "------ hv3 dump ------"
3592 as hv3 ovs-vsctl show
3593 as hv3 ovs-ofctl -O OpenFlow13 show br-int
3594 as hv3 ovs-ofctl -O OpenFlow13 dump-flows br-int
3596 # Now check the packets actually received against the ones expected.
3599 OVN_CHECK_PACKETS([hv$i/vif$i$j-tx.pcap], [$i$j.expected])
3603 OVN_CLEANUP([hv1],[hv2],[hv3])
3607 AT_SETUP([ovn -- 2 HVs, 2 LS, 1 lport/LS, 2 peer LRs])
3608 AT_SKIP_IF([test $HAVE_PYTHON = no])
3612 # Two LRs - R1 and R2 that are connected to each other as peers in 20.0.0.0/24
3613 # network. R1 has a switchs ls1 (191.168.1.0/24) connected to it.
3614 # R2 has ls2 (172.16.1.0/24) connected to it.
3616 ls1_lp1_mac="f0:00:00:01:02:03"
3617 rp_ls1_mac="00:00:00:01:02:03"
3618 rp_ls2_mac="00:00:00:01:02:04"
3619 ls2_lp1_mac="f0:00:00:01:02:04"
3621 ls1_lp1_ip="192.168.1.2"
3622 ls2_lp1_ip="172.16.1.2"
3627 ovn-nbctl ls-add ls1
3628 ovn-nbctl ls-add ls2
3631 ovn-nbctl lrp-add R1 ls1 $rp_ls1_mac 192.168.1.1/24
3633 ovn-nbctl lsp-add ls1 rp-ls1 -- set Logical_Switch_Port rp-ls1 type=router \
3634 options:router-port=ls1 addresses=\"$rp_ls1_mac\"
3637 ovn-nbctl lrp-add R2 ls2 $rp_ls2_mac 172.16.1.1/24
3639 ovn-nbctl lsp-add ls2 rp-ls2 -- set Logical_Switch_Port rp-ls2 type=router \
3640 options:router-port=ls2 addresses=\"$rp_ls2_mac\"
3643 ovn-nbctl lrp-add R1 R1_R2 00:00:00:02:03:04 20.0.0.1/24 peer=R2_R1
3644 ovn-nbctl lrp-add R2 R2_R1 00:00:00:02:03:05 20.0.0.2/24 peer=R1_R2
3646 ovn-nbctl lr-route-add R1 "0.0.0.0/0" 20.0.0.2
3647 ovn-nbctl lr-route-add R2 "0.0.0.0/0" 20.0.0.1
3649 # Create logical port ls1-lp1 in ls1
3650 ovn-nbctl lsp-add ls1 ls1-lp1 \
3651 -- lsp-set-addresses ls1-lp1 "$ls1_lp1_mac $ls1_lp1_ip"
3653 # Create logical port ls2-lp1 in ls2
3654 ovn-nbctl lsp-add ls2 ls2-lp1 \
3655 -- lsp-set-addresses ls2-lp1 "$ls2_lp1_mac $ls2_lp1_ip"
3657 # Create two hypervisor and create OVS ports corresponding to logical ports.
3662 ovs-vsctl add-br br-phys
3663 ovn_attach n1 br-phys 192.168.0.1
3664 ovs-vsctl -- add-port br-int hv1-vif1 -- \
3665 set interface hv1-vif1 external-ids:iface-id=ls1-lp1 \
3666 options:tx_pcap=hv1/vif1-tx.pcap \
3667 options:rxq_pcap=hv1/vif1-rx.pcap \
3672 ovs-vsctl add-br br-phys
3673 ovn_attach n1 br-phys 192.168.0.2
3674 ovs-vsctl -- add-port br-int hv2-vif1 -- \
3675 set interface hv2-vif1 external-ids:iface-id=ls2-lp1 \
3676 options:tx_pcap=hv2/vif1-tx.pcap \
3677 options:rxq_pcap=hv2/vif1-rx.pcap \
3681 # Pre-populate the hypervisors' ARP tables so that we don't lose any
3682 # packets for ARP resolution (native tunneling doesn't queue packets
3683 # for ARP resolution).
3686 # Allow some time for ovn-northd and ovn-controller to catch up.
3687 # XXX This should be more systematic.
3691 packet="inport==\"ls1-lp1\" && eth.src==$ls1_lp1_mac && eth.dst==$rp_ls1_mac &&
3692 ip4 && ip.ttl==64 && ip4.src==$ls1_lp1_ip && ip4.dst==$ls2_lp1_ip &&
3693 udp && udp.src==53 && udp.dst==4369"
3694 as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"
3697 echo "---------NB dump-----"
3699 echo "---------------------"
3700 ovn-nbctl list logical_router
3701 echo "---------------------"
3702 ovn-nbctl list logical_router_port
3703 echo "---------------------"
3705 echo "---------SB dump-----"
3706 ovn-sbctl list datapath_binding
3707 echo "---------------------"
3708 ovn-sbctl list port_binding
3709 echo "---------------------"
3711 echo "------ hv1 dump ----------"
3712 as hv1 ovs-ofctl show br-int
3713 as hv1 ovs-ofctl dump-flows br-int
3714 echo "------ hv2 dump ----------"
3715 as hv2 ovs-ofctl show br-int
3716 as hv2 ovs-ofctl dump-flows br-int
3719 # The TTL should be decremented by 2.
3720 packet="eth.src==$rp_ls2_mac && eth.dst==$ls2_lp1_mac &&
3721 ip4 && ip.ttl==62 && ip4.src==$ls1_lp1_ip && ip4.dst==$ls2_lp1_ip &&
3722 udp && udp.src==53 && udp.dst==4369"
3723 echo $packet | ovstest test-ovn expr-to-packets > expected
3725 OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
3727 AT_CHECK([ovn-sbctl dump-flows | grep lr_in_arp_resolve | \
3728 grep "reg0 == 172.16.1.2" | wc -l], [0], [1
3731 # Disable the ls2-lp1 port.
3732 ovn-nbctl --wait=hv set logical_switch_port ls2-lp1 enabled=false
3734 AT_CHECK([ovn-sbctl dump-flows | grep lr_in_arp_resolve | \
3735 grep "reg0 == 172.16.1.2" | wc -l], [0], [0
3738 # Generate the packet destined for ls2-lp1 and it should not be delivered.
3740 packet="inport==\"ls1-lp1\" && eth.src==$ls1_lp1_mac && eth.dst==$rp_ls1_mac &&
3741 ip4 && ip.ttl==64 && ip4.src==$ls1_lp1_ip && ip4.dst==$ls2_lp1_ip &&
3742 udp && udp.src==53 && udp.dst==4369"
3744 as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"
3745 # The 2nd packet sent shound not be received.
3746 OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
3748 OVN_CLEANUP([hv1],[hv2])
3753 AT_SETUP([ovn -- 1 HV, 1 LS, 2 lport/LS, 1 LR])
3754 AT_KEYWORDS([router-admin-state])
3755 AT_SKIP_IF([test $HAVE_PYTHON = no])
3759 # One LR - R1 has switch ls1 with two subnets attached to it (191.168.1.0/24
3760 # and 172.16.1.0/24) connected to it.
3764 ovn-nbctl ls-add ls1
3767 ovn-nbctl lrp-add R1 ls1 00:00:00:01:02:03 192.168.1.1/24 172.16.1.1/24
3768 ovn-nbctl lsp-add ls1 rp-ls1 -- set Logical_Switch_Port rp-ls1 type=router \
3769 options:router-port=ls1 addresses=\"00:00:00:01:02:03\"
3771 # Create logical port ls1-lp1 in ls1
3772 ovn-nbctl lsp-add ls1 ls1-lp1 \
3773 -- lsp-set-addresses ls1-lp1 "f0:00:00:01:02:03 192.168.1.2"
3775 # Create logical port ls1-lp2 in ls1
3776 ovn-nbctl lsp-add ls1 ls1-lp2 \
3777 -- lsp-set-addresses ls1-lp2 "f0:00:00:01:02:04 172.16.1.2"
3779 # Create one hypervisor and create OVS ports corresponding to logical ports.
3784 ovs-vsctl add-br br-phys
3785 ovn_attach n1 br-phys 192.168.0.1
3786 ovs-vsctl -- add-port br-int vif1 -- \
3787 set interface vif1 external-ids:iface-id=ls1-lp1 \
3788 options:tx_pcap=hv1/vif1-tx.pcap \
3789 options:rxq_pcap=hv1/vif1-rx.pcap \
3792 ovs-vsctl -- add-port br-int vif2 -- \
3793 set interface vif2 external-ids:iface-id=ls1-lp2 \
3794 options:tx_pcap=hv1/vif2-tx.pcap \
3795 options:rxq_pcap=hv1/vif2-rx.pcap \
3799 # Allow some time for ovn-northd and ovn-controller to catch up.
3800 # XXX This should be more systematic.
3803 # Send ip packets between the two ports.
3805 printf "%02x%02x%02x%02x" "$@"
3809 src_mac="f00000010203"
3810 dst_mac="000000010203"
3811 src_ip=`ip_to_hex 192 168 1 2`
3812 dst_ip=`ip_to_hex 172 16 1 2`
3813 packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
3814 as hv1 ovs-appctl netdev-dummy/receive vif1 $packet
3817 echo "---------NB dump-----"
3819 echo "---------------------"
3820 ovn-nbctl list logical_router
3821 echo "---------------------"
3822 ovn-nbctl list logical_router_port
3823 echo "---------------------"
3825 echo "---------SB dump-----"
3826 ovn-sbctl list datapath_binding
3827 echo "---------------------"
3828 ovn-sbctl list logical_flow
3829 echo "---------------------"
3831 echo "------ hv1 dump ----------"
3832 as hv1 ovs-ofctl dump-flows br-int
3836 ovn-nbctl set Logical_Router R1 enabled=false
3838 # Allow some time for ovn-northd and ovn-controller to catch up.
3839 # XXX This should be more systematic.
3842 echo "---------SB dump-----"
3843 ovn-sbctl list datapath_binding
3844 echo "---------------------"
3845 ovn-sbctl list logical_flow
3846 echo "---------------------"
3848 echo "------ hv1 dump ----------"
3849 as hv1 ovs-ofctl dump-flows br-int
3851 as hv1 ovs-appctl netdev-dummy/receive vif1 $packet
3854 expect_src_mac="000000010203"
3855 expect_dst_mac="f00000010204"
3856 echo "${expect_dst_mac}${expect_src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000" > expected
3858 OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [expected])
3865 AT_SETUP([ovn -- 1 HV, 2 LSs, 1 lport/LS, 1 LR])
3866 AT_KEYWORDS([router-admin-state])
3867 AT_SKIP_IF([test $HAVE_PYTHON = no])
3871 # One LR - R1 has switch ls1 (191.168.1.0/24) connected to it,
3872 # and has switch ls2 (172.16.1.0/24) connected to it.
3876 ovn-nbctl ls-add ls1
3877 ovn-nbctl ls-add ls2
3880 ovn-nbctl lrp-add R1 ls1 00:00:00:01:02:03 192.168.1.1/24
3881 ovn-nbctl lsp-add ls1 rp-ls1 -- set Logical_Switch_Port rp-ls1 type=router \
3882 options:router-port=ls1 addresses=\"00:00:00:01:02:03\"
3885 ovn-nbctl lrp-add R1 ls2 00:00:00:01:02:04 172.16.1.1/24
3886 ovn-nbctl lsp-add ls2 rp-ls2 -- set Logical_Switch_Port rp-ls2 type=router \
3887 options:router-port=ls2 addresses=\"00:00:00:01:02:04\"
3889 # Create logical port ls1-lp1 in ls1
3890 ovn-nbctl lsp-add ls1 ls1-lp1 \
3891 -- lsp-set-addresses ls1-lp1 "f0:00:00:01:02:03 192.168.1.2"
3893 # Create logical port ls2-lp1 in ls2
3894 ovn-nbctl lsp-add ls2 ls2-lp1 \
3895 -- lsp-set-addresses ls2-lp1 "f0:00:00:01:02:04 172.16.1.2"
3897 # Create one hypervisor and create OVS ports corresponding to logical ports.
3902 ovs-vsctl add-br br-phys
3903 ovn_attach n1 br-phys 192.168.0.1
3904 ovs-vsctl -- add-port br-int vif1 -- \
3905 set interface vif1 external-ids:iface-id=ls1-lp1 \
3906 options:tx_pcap=hv1/vif1-tx.pcap \
3907 options:rxq_pcap=hv1/vif1-rx.pcap \
3910 ovs-vsctl -- add-port br-int vif2 -- \
3911 set interface vif2 external-ids:iface-id=ls2-lp1 \
3912 options:tx_pcap=hv1/vif2-tx.pcap \
3913 options:rxq_pcap=hv1/vif2-rx.pcap \
3917 # Allow some time for ovn-northd and ovn-controller to catch up.
3918 # XXX This should be more systematic.
3921 # Send ip packets between the two ports.
3923 printf "%02x%02x%02x%02x" "$@"
3927 src_mac="f00000010203"
3928 dst_mac="000000010203"
3929 src_ip=`ip_to_hex 192 168 1 2`
3930 dst_ip=`ip_to_hex 172 16 1 2`
3931 packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
3932 as hv1 ovs-appctl netdev-dummy/receive vif1 $packet
3935 echo "---------NB dump-----"
3937 echo "---------------------"
3938 ovn-nbctl list logical_router
3939 echo "---------------------"
3940 ovn-nbctl list logical_router_port
3941 echo "---------------------"
3943 echo "---------SB dump-----"
3944 ovn-sbctl list datapath_binding
3945 echo "---------------------"
3946 ovn-sbctl list logical_flow
3947 echo "---------------------"
3949 echo "------ hv1 dump ----------"
3950 as hv1 ovs-ofctl dump-flows br-int
3953 ovn-nbctl set Logical_Router R1 enabled=false
3955 echo "---------SB dump-----"
3956 ovn-sbctl list datapath_binding
3957 echo "---------------------"
3958 ovn-sbctl list logical_flow
3959 echo "---------------------"
3961 echo "------ hv1 dump ----------"
3962 as hv1 ovs-ofctl dump-flows br-int
3964 # Allow some time for the disabling of logical router R1 to propagate.
3965 # XXX This should be more systematic.
3968 as hv1 ovs-appctl netdev-dummy/receive vif1 $packet
3971 expect_src_mac="000000010204"
3972 expect_dst_mac="f00000010204"
3973 echo "${expect_dst_mac}${expect_src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000" > expected
3975 OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [expected])
3981 AT_SETUP([ovn -- 2 HVs, 3 LS, 1 lport/LS, 2 peer LRs, static routes])
3982 AT_SKIP_IF([test $HAVE_PYTHON = no])
3986 # Two LRs - R1 and R2 that are connected to each other as peers in 20.0.0.0/24
3987 # network. R1 has switchess foo (192.168.1.0/24)
3989 # R2 has alice (172.16.1.0/24) and bob (172.16.2.0/24) connected to it.
3994 ovn-nbctl ls-add foo
3995 ovn-nbctl ls-add alice
3996 ovn-nbctl ls-add bob
3999 ovn-nbctl lrp-add R1 foo 00:00:00:01:02:03 192.168.1.1/24
4000 ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo type=router \
4001 options:router-port=foo addresses=\"00:00:00:01:02:03\"
4003 # Connect alice to R2
4004 ovn-nbctl lrp-add R2 alice 00:00:00:01:02:04 172.16.1.1/24
4005 ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port rp-alice \
4006 type=router options:router-port=alice addresses=\"00:00:00:01:02:04\"
4009 ovn-nbctl lrp-add R2 bob 00:00:00:01:02:05 172.16.2.1/24
4010 ovn-nbctl lsp-add bob rp-bob -- set Logical_Switch_Port rp-bob type=router \
4011 options:router-port=bob addresses=\"00:00:00:01:02:05\"
4014 ovn-nbctl lrp-add R1 R1_R2 00:00:00:02:03:04 20.0.0.1/24 peer=R2_R1
4015 ovn-nbctl lrp-add R2 R2_R1 00:00:00:02:03:05 20.0.0.2/24 peer=R1_R2
4017 #install static routes
4018 ovn-nbctl lr-route-add R1 172.16.1.0/24 20.0.0.2
4019 ovn-nbctl lr-route-add R2 172.16.2.0/24 20.0.0.2 R1_R2
4020 ovn-nbctl lr-route-add R2 192.168.1.0/24 20.0.0.1
4022 # Create logical port foo1 in foo
4023 ovn-nbctl lsp-add foo foo1 \
4024 -- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
4026 # Create logical port alice1 in alice
4027 ovn-nbctl lsp-add alice alice1 \
4028 -- lsp-set-addresses alice1 "f0:00:00:01:02:04 172.16.1.2"
4030 # Create logical port bob1 in bob
4031 ovn-nbctl lsp-add bob bob1 \
4032 -- lsp-set-addresses bob1 "f0:00:00:01:02:05 172.16.2.2"
4034 # Create two hypervisor and create OVS ports corresponding to logical ports.
4039 ovs-vsctl add-br br-phys
4040 ovn_attach n1 br-phys 192.168.0.1
4041 ovs-vsctl -- add-port br-int hv1-vif1 -- \
4042 set interface hv1-vif1 external-ids:iface-id=foo1 \
4043 options:tx_pcap=hv1/vif1-tx.pcap \
4044 options:rxq_pcap=hv1/vif1-rx.pcap \
4047 ovs-vsctl -- add-port br-int hv1-vif2 -- \
4048 set interface hv1-vif2 external-ids:iface-id=alice1 \
4049 options:tx_pcap=hv1/vif2-tx.pcap \
4050 options:rxq_pcap=hv1/vif2-rx.pcap \
4055 ovs-vsctl add-br br-phys
4056 ovn_attach n1 br-phys 192.168.0.2
4057 ovs-vsctl -- add-port br-int hv2-vif1 -- \
4058 set interface hv2-vif1 external-ids:iface-id=bob1 \
4059 options:tx_pcap=hv2/vif1-tx.pcap \
4060 options:rxq_pcap=hv2/vif1-rx.pcap \
4064 # Pre-populate the hypervisors' ARP tables so that we don't lose any
4065 # packets for ARP resolution (native tunneling doesn't queue packets
4066 # for ARP resolution).
4069 # Allow some time for ovn-northd and ovn-controller to catch up.
4070 # XXX This should be more systematic.
4074 printf "%02x%02x%02x%02x" "$@"
4077 # Send ip packets between foo1 and alice1
4078 src_mac="f00000010203"
4079 dst_mac="000000010203"
4080 src_ip=`ip_to_hex 192 168 1 2`
4081 dst_ip=`ip_to_hex 172 16 1 2`
4082 packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
4083 as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
4085 # Send ip packets between foo1 and bob1
4086 src_mac="f00000010203"
4087 dst_mac="000000010203"
4088 src_ip=`ip_to_hex 192 168 1 2`
4089 dst_ip=`ip_to_hex 172 16 2 2`
4090 packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
4091 as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
4093 echo "---------NB dump-----"
4095 echo "---------------------"
4096 ovn-nbctl list logical_router
4097 echo "---------------------"
4098 ovn-nbctl list logical_router_port
4099 echo "---------------------"
4101 echo "---------SB dump-----"
4102 ovn-sbctl list datapath_binding
4103 echo "---------------------"
4104 ovn-sbctl list port_binding
4105 echo "---------------------"
4107 echo "------ hv1 dump ----------"
4108 as hv1 ovs-ofctl dump-flows br-int
4109 echo "------ hv2 dump ----------"
4110 as hv2 ovs-ofctl dump-flows br-int
4112 # Packet to Expect at bob1
4113 src_mac="000000010205"
4114 dst_mac="f00000010205"
4115 src_ip=`ip_to_hex 192 168 1 2`
4116 dst_ip=`ip_to_hex 172 16 2 2`
4117 echo "${dst_mac}${src_mac}08004500001c000000003e110200${src_ip}${dst_ip}0035111100080000" > expected
4119 OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
4121 # Packet to Expect at alice1
4122 src_mac="000000010204"
4123 dst_mac="f00000010204"
4124 src_ip=`ip_to_hex 192 168 1 2`
4125 dst_ip=`ip_to_hex 172 16 1 2`
4126 echo "${dst_mac}${src_mac}08004500001c000000003e110200${src_ip}${dst_ip}0035111100080000" > expected
4128 OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [expected])
4130 OVN_CLEANUP([hv1],[hv2])
4134 AT_SETUP([ovn -- send gratuitous arp on localnet])
4135 AT_SKIP_IF([test $HAVE_PYTHON = no])
4137 ovn-nbctl ls-add lsw0
4145 ovn_attach n1 br-phys 192.168.0.1
4147 AT_CHECK([ovs-vsctl set Open_vSwitch . external-ids:ovn-bridge-mappings=physnet1:br-eth0])
4148 AT_CHECK([ovs-vsctl add-port br-eth0 snoopvif -- set Interface snoopvif options:tx_pcap=hv/snoopvif-tx.pcap options:rxq_pcap=hv/snoopvif-rx.pcap])
4151 AT_CHECK([ovn-nbctl lsp-add lsw0 localvif1])
4152 AT_CHECK([ovn-nbctl lsp-set-addresses localvif1 "f0:00:00:00:00:01 192.168.1.2"])
4153 AT_CHECK([ovn-nbctl lsp-set-port-security localvif1 "f0:00:00:00:00:01"])
4155 # Create a localnet port.
4156 AT_CHECK([ovn-nbctl lsp-add lsw0 ln_port])
4157 AT_CHECK([ovn-nbctl lsp-set-addresses ln_port unknown])
4158 AT_CHECK([ovn-nbctl lsp-set-type ln_port localnet])
4159 AT_CHECK([ovn-nbctl lsp-set-options ln_port network_name=physnet1])
4161 AT_CHECK([ovs-vsctl add-port br-int localvif1 -- set Interface localvif1 external_ids:iface-id=localvif1])
4163 # Wait for packet to be received.
4164 echo "fffffffffffff0000000000108060001080006040001f00000000001c0a80102000000000000c0a80102" > expected
4165 OVN_CHECK_PACKETS([hv/snoopvif-tx.pcap], [expected])
4167 # Check GARP packet when restart openflow connection.
4169 OVS_APP_EXIT_AND_WAIT([ovs-vswitchd])
4171 OVS_WAIT_UNTIL([grep -c "waiting 4 seconds before reconnect" hv/ovn-controller.log])
4174 start_daemon ovs-vswitchd --enable-dummy=system -vvconn -vofproto_dpif -vunixctl
4176 # Wait for packet to be received.
4177 echo "fffffffffffff0000000000108060001080006040001f00000000001c0a80102000000000000c0a80102" > expected
4178 OVN_CHECK_PACKETS([hv/snoopvif-tx.pcap], [expected])
4180 # Delete the localnet ports.
4181 AT_CHECK([ovs-vsctl del-port localvif1])
4182 AT_CHECK([ovn-nbctl lsp-del ln_port])
4188 AT_SETUP([ovn -- 2 HVs, 3 LRs connected via LS, static routes])
4189 AT_SKIP_IF([test $HAVE_PYTHON = no])
4193 # Three LRs - R1, R2 and R3 that are connected to each other via LS "join"
4194 # in 20.0.0.0/24 network. R1 has switchess foo (192.168.1.0/24)
4195 # connected to it. R2 has alice (172.16.1.0/24) and R3 has bob (10.32.1.0/24)
4202 ovn-nbctl ls-add foo
4203 ovn-nbctl ls-add alice
4204 ovn-nbctl ls-add bob
4205 ovn-nbctl ls-add join
4208 ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
4209 ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo type=router \
4210 options:router-port=foo addresses=\"00:00:01:01:02:03\"
4212 # Connect alice to R2
4213 ovn-nbctl lrp-add R2 alice 00:00:02:01:02:03 172.16.1.1/24
4214 ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port rp-alice \
4215 type=router options:router-port=alice addresses=\"00:00:02:01:02:03\"
4218 ovn-nbctl lrp-add R3 bob 00:00:03:01:02:03 10.32.1.1/24
4219 ovn-nbctl lsp-add bob rp-bob -- set Logical_Switch_Port rp-bob \
4220 type=router options:router-port=bob addresses=\"00:00:03:01:02:03\"
4222 # Connect R1 to join
4223 ovn-nbctl lrp-add R1 R1_join 00:00:04:01:02:03 20.0.0.1/24
4224 ovn-nbctl lsp-add join r1-join -- set Logical_Switch_Port r1-join \
4225 type=router options:router-port=R1_join addresses='"00:00:04:01:02:03"'
4227 # Connect R2 to join
4228 ovn-nbctl lrp-add R2 R2_join 00:00:04:01:02:04 20.0.0.2/24
4229 ovn-nbctl lsp-add join r2-join -- set Logical_Switch_Port r2-join \
4230 type=router options:router-port=R2_join addresses='"00:00:04:01:02:04"'
4232 # Connect R3 to join
4233 ovn-nbctl lrp-add R3 R3_join 00:00:04:01:02:05 20.0.0.3/24
4234 ovn-nbctl lsp-add join r3-join -- set Logical_Switch_Port r3-join \
4235 type=router options:router-port=R3_join addresses='"00:00:04:01:02:05"'
4237 #install static routes
4238 ovn-nbctl lr-route-add R1 172.16.1.0/24 20.0.0.2
4239 ovn-nbctl lr-route-add R1 10.32.1.0/24 20.0.0.3
4241 ovn-nbctl lr-route-add R2 192.168.1.0/24 20.0.0.1
4242 ovn-nbctl lr-route-add R2 10.32.1.0/24 20.0.0.3
4244 ovn-nbctl lr-route-add R3 192.168.1.0/24 20.0.0.1
4245 ovn-nbctl lr-route-add R3 172.16.1.0/24 20.0.0.2
4247 # Create logical port foo1 in foo
4248 ovn-nbctl lsp-add foo foo1 \
4249 -- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
4251 # Create logical port alice1 in alice
4252 ovn-nbctl lsp-add alice alice1 \
4253 -- lsp-set-addresses alice1 "f0:00:00:01:02:04 172.16.1.2"
4255 # Create logical port bob1 in bob
4256 ovn-nbctl lsp-add bob bob1 \
4257 -- lsp-set-addresses bob1 "f0:00:00:01:02:05 10.32.1.2"
4259 # Create two hypervisor and create OVS ports corresponding to logical ports.
4264 ovs-vsctl add-br br-phys
4265 ovn_attach n1 br-phys 192.168.0.1
4266 ovs-vsctl -- add-port br-int hv1-vif1 -- \
4267 set interface hv1-vif1 external-ids:iface-id=foo1 \
4268 options:tx_pcap=hv1/vif1-tx.pcap \
4269 options:rxq_pcap=hv1/vif1-rx.pcap \
4272 ovs-vsctl -- add-port br-int hv1-vif2 -- \
4273 set interface hv1-vif2 external-ids:iface-id=alice1 \
4274 options:tx_pcap=hv1/vif2-tx.pcap \
4275 options:rxq_pcap=hv1/vif2-rx.pcap \
4280 ovs-vsctl add-br br-phys
4281 ovn_attach n1 br-phys 192.168.0.2
4282 ovs-vsctl -- add-port br-int hv2-vif1 -- \
4283 set interface hv2-vif1 external-ids:iface-id=bob1 \
4284 options:tx_pcap=hv2/vif1-tx.pcap \
4285 options:rxq_pcap=hv2/vif1-rx.pcap \
4289 # Pre-populate the hypervisors' ARP tables so that we don't lose any
4290 # packets for ARP resolution (native tunneling doesn't queue packets
4291 # for ARP resolution).
4294 # Allow some time for ovn-northd and ovn-controller to catch up.
4295 # XXX This should be more systematic.
4299 printf "%02x%02x%02x%02x" "$@"
4302 # Send ip packets between foo1 and alice1
4303 src_mac="f00000010203"
4304 dst_mac="000001010203"
4305 src_ip=`ip_to_hex 192 168 1 2`
4306 dst_ip=`ip_to_hex 172 16 1 2`
4307 packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
4308 as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
4309 as hv1 ovs-appctl ofproto/trace br-int in_port=1 $packet
4311 # Send ip packets between foo1 and bob1
4312 src_mac="f00000010203"
4313 dst_mac="000001010203"
4314 src_ip=`ip_to_hex 192 168 1 2`
4315 dst_ip=`ip_to_hex 10 32 1 2`
4316 packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
4317 as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
4319 echo "---------NB dump-----"
4321 echo "---------------------"
4322 ovn-nbctl list logical_router
4323 echo "---------------------"
4324 ovn-nbctl list logical_router_port
4325 echo "---------------------"
4327 echo "---------SB dump-----"
4328 ovn-sbctl list datapath_binding
4329 echo "---------------------"
4330 ovn-sbctl list port_binding
4331 echo "---------------------"
4332 ovn-sbctl dump-flows
4333 echo "---------------------"
4335 echo "------ hv1 dump ----------"
4336 as hv1 ovs-ofctl show br-int
4337 as hv1 ovs-ofctl dump-flows br-int
4338 echo "------ hv2 dump ----------"
4339 as hv2 ovs-ofctl show br-int
4340 as hv2 ovs-ofctl dump-flows br-int
4341 echo "----------------------------"
4343 # Packet to Expect at bob1
4344 src_mac="000003010203"
4345 dst_mac="f00000010205"
4346 src_ip=`ip_to_hex 192 168 1 2`
4347 dst_ip=`ip_to_hex 10 32 1 2`
4348 echo "${dst_mac}${src_mac}08004500001c000000003e110200${src_ip}${dst_ip}0035111100080000" > expected
4350 OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
4352 # Packet to Expect at alice1
4353 src_mac="000002010203"
4354 dst_mac="f00000010204"
4355 src_ip=`ip_to_hex 192 168 1 2`
4356 dst_ip=`ip_to_hex 172 16 1 2`
4357 echo "${dst_mac}${src_mac}08004500001c000000003e110200${src_ip}${dst_ip}0035111100080000" > expected
4359 OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [expected])
4361 OVN_CLEANUP([hv1],[hv2])
4365 AT_SETUP([ovn -- dhcpv4 : 1 HV, 2 LS, 2 LSPs/LS])
4366 AT_SKIP_IF([test $HAVE_PYTHON = no])
4369 ovn-nbctl ls-add ls1
4371 ovn-nbctl lsp-add ls1 ls1-lp1 \
4372 -- lsp-set-addresses ls1-lp1 "f0:00:00:00:00:01 10.0.0.4"
4374 ovn-nbctl lsp-set-port-security ls1-lp1 "f0:00:00:00:00:01 10.0.0.4"
4376 ovn-nbctl lsp-add ls1 ls1-lp2 \
4377 -- lsp-set-addresses ls1-lp2 "f0:00:00:00:00:02 10.0.0.6 20.0.0.4"
4379 ovn-nbctl lsp-set-port-security ls1-lp2 "f0:00:00:00:00:02 10.0.0.6 20.0.0.4"
4381 ovn-nbctl ls-add ls2
4382 ovn-nbctl lsp-add ls2 ls2-lp1 \
4383 -- lsp-set-addresses ls2-lp1 "f0:00:00:00:00:03 30.0.0.6 40.0.0.4"
4384 ovn-nbctl lsp-set-port-security ls2-lp1 "f0:00:00:00:00:03 30.0.0.6 40.0.0.4"
4385 ovn-nbctl lsp-add ls2 ls2-lp2 \
4386 -- lsp-set-addresses ls2-lp2 "f0:00:00:00:00:04 30.0.0.7"
4387 ovn-nbctl lsp-set-port-security ls2-lp2 "f0:00:00:00:00:04 30.0.0.7"
4389 d1="$(ovn-nbctl create DHCP_Options cidr=10.0.0.0/24 \
4390 options="\"server_id\"=\"10.0.0.1\" \"server_mac\"=\"ff:10:00:00:00:01\" \
4391 \"lease_time\"=\"3600\" \"router\"=\"10.0.0.1\"")"
4393 ovn-nbctl lsp-set-dhcpv4-options ls1-lp1 ${d1}
4394 ovn-nbctl lsp-set-dhcpv4-options ls1-lp2 ${d1}
4396 d2="$(ovn-nbctl create DHCP_Options cidr=30.0.0.0/24 \
4397 options="\"server_id\"=\"30.0.0.1\" \"server_mac\"=\"ff:10:00:00:00:02\" \
4398 \"lease_time\"=\"3600\"")"
4400 ovn-nbctl lsp-set-dhcpv4-options ls2-lp2 ${d2}
4406 ovs-vsctl add-br br-phys
4407 ovn_attach n1 br-phys 192.168.0.1
4408 ovs-vsctl -- add-port br-int hv1-vif1 -- \
4409 set interface hv1-vif1 external-ids:iface-id=ls1-lp1 \
4410 options:tx_pcap=hv1/vif1-tx.pcap \
4411 options:rxq_pcap=hv1/vif1-rx.pcap \
4414 ovs-vsctl -- add-port br-int hv1-vif2 -- \
4415 set interface hv1-vif2 external-ids:iface-id=ls1-lp2 \
4416 options:tx_pcap=hv1/vif2-tx.pcap \
4417 options:rxq_pcap=hv1/vif2-rx.pcap \
4420 ovs-vsctl -- add-port br-int hv1-vif3 -- \
4421 set interface hv1-vif3 external-ids:iface-id=ls2-lp1 \
4422 options:tx_pcap=hv1/vif3-tx.pcap \
4423 options:rxq_pcap=hv1/vif3-rx.pcap \
4426 ovs-vsctl -- add-port br-int hv1-vif4 -- \
4427 set interface hv1-vif4 external-ids:iface-id=ls2-lp2 \
4428 options:tx_pcap=hv1/vif4-tx.pcap \
4429 options:rxq_pcap=hv1/vif4-rx.pcap \
4436 as hv1 ovs-vsctl show
4438 # This shell function sends a DHCP request packet
4439 # test_dhcp INPORT SRC_MAC DHCP_TYPE OFFER_IP REQUEST_IP ...
4441 local inport=$1 src_mac=$2 dhcp_type=$3 ciaddr=$4 offer_ip=$5 request_ip=$6 use_ip=$7
4442 shift; shift; shift; shift; shift; shift; shift;
4443 if test $use_ip != 0; then
4448 src_ip=`ip_to_hex 0 0 0 0`
4449 dst_ip=`ip_to_hex 255 255 255 255`
4451 if test $request_ip != 0; then
4458 local request=ffffffffffff${src_mac}08004510${ip_len}0000000080110000${src_ip}${dst_ip}
4459 # udp header and dhcp header
4460 request=${request}00440043${udp_len}0000
4461 request=${request}010106006359aa7600000000${ciaddr}000000000000000000000000${src_mac}
4462 # client hardware padding
4463 request=${request}00000000000000000000
4465 request=${request}0000000000000000000000000000000000000000000000000000000000000000
4466 request=${request}0000000000000000000000000000000000000000000000000000000000000000
4468 request=${request}0000000000000000000000000000000000000000000000000000000000000000
4469 request=${request}0000000000000000000000000000000000000000000000000000000000000000
4470 request=${request}0000000000000000000000000000000000000000000000000000000000000000
4471 request=${request}0000000000000000000000000000000000000000000000000000000000000000
4473 request=${request}63825363
4475 request=${request}3501${dhcp_type}
4476 # dhcp unknown option
4477 request=${request}d70701020304050607
4479 request=${request}00
4480 if test $request_ip != 0; then
4482 request=${request}3204${request_ip}
4485 request=${request}ff
4487 for port in $inport "$@"; do
4490 if test $offer_ip != 0; then
4491 local srv_mac=$1 srv_ip=$2 dhcp_reply_type=$3 expected_dhcp_opts=$4
4492 # total IP length will be the IP length of the request packet
4493 # (which is 272 in our case) + 8 (padding bytes) + (expected_dhcp_opts / 2)
4494 ip_len=`expr 280 + ${#expected_dhcp_opts} / 2`
4495 udp_len=`expr $ip_len - 20`
4496 ip_len=$(printf "%x" $ip_len)
4497 udp_len=$(printf "%x" $udp_len)
4498 # $ip_len var will be in 3 digits i.e 134. So adding a '0' before $ip_len
4499 local reply=${src_mac}${srv_mac}080045100${ip_len}000000008011XXXX${srv_ip}${offer_ip}
4500 # udp header and dhcp header.
4501 # $udp_len var will be in 3 digits. So adding a '0' before $udp_len
4502 reply=${reply}004300440${udp_len}0000020106006359aa7600000000${ciaddr}
4503 # your ip address; 0 for NAK
4504 if test $dhcp_reply_type = 06; then
4505 reply=${reply}00000000
4507 reply=${reply}${offer_ip}
4509 # next server ip address, relay agent ip address, client mac address
4510 reply=${reply}0000000000000000${src_mac}
4511 # client hardware padding
4512 reply=${reply}00000000000000000000
4514 reply=${reply}0000000000000000000000000000000000000000000000000000000000000000
4515 reply=${reply}0000000000000000000000000000000000000000000000000000000000000000
4517 reply=${reply}0000000000000000000000000000000000000000000000000000000000000000
4518 reply=${reply}0000000000000000000000000000000000000000000000000000000000000000
4519 reply=${reply}0000000000000000000000000000000000000000000000000000000000000000
4520 reply=${reply}0000000000000000000000000000000000000000000000000000000000000000
4522 reply=${reply}63825363
4523 reply=${reply}3501${dhcp_reply_type}${expected_dhcp_opts}00000000ff00000000
4524 echo $reply >> $inport.expected
4527 echo $request >> $outport.expected
4530 as hv1 ovs-appctl netdev-dummy/receive hv1-vif$inport $request
4536 ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \
4537 options:rxq_pcap=dummy-rx.pcap
4538 rm -f ${pcap_file}*.pcap
4539 ovs-vsctl -- set Interface $iface options:tx_pcap=${pcap_file}-tx.pcap \
4540 options:rxq_pcap=${pcap_file}-rx.pcap
4544 printf "%02x%02x%02x%02x" "$@"
4547 AT_CAPTURE_FILE([ofctl_monitor0.log])
4548 as hv1 ovs-ofctl monitor br-int resume --detach --no-chdir \
4549 --pidfile=ovs-ofctl0.pid 2> ofctl_monitor0.log
4551 echo "---------NB dump-----"
4553 echo "---------------------"
4554 echo "---------SB dump-----"
4555 ovn-sbctl list datapath_binding
4556 echo "---------------------"
4557 ovn-sbctl list logical_flow
4558 echo "---------------------"
4560 echo "---------------------"
4561 ovn-sbctl dump-flows
4562 echo "---------------------"
4564 echo "------ hv1 dump ----------"
4565 as hv1 ovs-ofctl dump-flows br-int
4567 # Send DHCPDISCOVER.
4568 offer_ip=`ip_to_hex 10 0 0 4`
4569 server_ip=`ip_to_hex 10 0 0 1`
4570 ciaddr=`ip_to_hex 0 0 0 0`
4572 expected_dhcp_opts=330400000e100104ffffff0003040a00000136040a000001
4573 test_dhcp 1 f00000000001 01 $ciaddr $offer_ip $request_ip 0 ff1000000001 $server_ip 02 $expected_dhcp_opts
4575 # NXT_RESUMEs should be 1.
4576 OVS_WAIT_UNTIL([test 1 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
4578 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif1-tx.pcap > 1.packets
4579 cat 1.expected | cut -c -48 > expout
4580 AT_CHECK([cat 1.packets | cut -c -48], [0], [expout])
4581 # Skipping the IPv4 checksum.
4582 cat 1.expected | cut -c 53- > expout
4583 AT_CHECK([cat 1.packets | cut -c 53-], [0], [expout])
4585 # ovs-ofctl also resumes the packets and this causes other ports to receive
4586 # the DHCP request packet. So reset the pcap files so that its easier to test.
4587 reset_pcap_file hv1-vif1 hv1/vif1
4588 reset_pcap_file hv1-vif2 hv1/vif2
4592 # Send DHCPREQUEST in the SELECTING/INIT-REBOOT state with the offered IP
4593 # address in the Requested IP Address option.
4594 offer_ip=`ip_to_hex 10 0 0 6`
4595 server_ip=`ip_to_hex 10 0 0 1`
4596 ciaddr=`ip_to_hex 0 0 0 0`
4597 request_ip=$offer_ip
4598 expected_dhcp_opts=330400000e100104ffffff0003040a00000136040a000001
4599 test_dhcp 2 f00000000002 03 $ciaddr $offer_ip $request_ip 0 ff1000000001 $server_ip 05 $expected_dhcp_opts
4601 # NXT_RESUMEs should be 2.
4602 OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
4604 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets
4605 cat 2.expected | cut -c -48 > expout
4606 AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
4607 # Skipping the IPv4 checksum.
4608 cat 2.expected | cut -c 53- > expout
4609 AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
4611 reset_pcap_file hv1-vif1 hv1/vif1
4612 reset_pcap_file hv1-vif2 hv1/vif2
4616 # Send DHCPREQUEST in the SELECTING/INIT-REBOOT state with a mismatched IP in
4617 # the Requested IP Address option, expect a DHCPNAK.
4618 offer_ip=`ip_to_hex 10 0 0 6`
4619 server_ip=`ip_to_hex 10 0 0 1`
4620 ciaddr=`ip_to_hex 0 0 0 0`
4621 request_ip=`ip_to_hex 10 0 0 7`
4622 expected_dhcp_opts=""
4623 test_dhcp 2 f00000000002 03 $ciaddr $offer_ip $request_ip 0 ff1000000001 $server_ip 06 $expected_dhcp_opts
4625 # NXT_RESUMEs should be 3.
4626 OVS_WAIT_UNTIL([test 3 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
4628 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets
4629 cat 2.expected | cut -c -48 > expout
4630 AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
4631 # Skipping the IPv4 checksum.
4632 cat 2.expected | cut -c 53- > expout
4633 AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
4635 reset_pcap_file hv1-vif1 hv1/vif1
4636 reset_pcap_file hv1-vif2 hv1/vif2
4640 # Send Invalid DHCPv4 packet on ls1-lp2. It should be received by ovn-controller
4641 # but should be resumed without the reply.
4642 # ls1-lp1 (vif1-tx.pcap) should receive the DHCPv4 request packet twice,
4643 # one from ovn-controller and the other from "ovs-ofctl resume."
4644 ciaddr=`ip_to_hex 0 0 0 0`
4647 test_dhcp 2 f00000000002 08 $ciaddr $offer_ip $request_ip 0 1 1
4649 # NXT_RESUMEs should be 4.
4650 OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
4652 # vif1-tx.pcap should have received the DHCPv4 (invalid) request packet
4653 OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [1.expected])
4655 reset_pcap_file hv1-vif1 hv1/vif1
4656 reset_pcap_file hv1-vif2 hv1/vif2
4660 # Send DHCPv4 packet on ls2-lp1. It doesn't have any DHCPv4 options defined.
4661 # ls2-lp2 (vif4-tx.pcap) should receive the DHCPv4 request packet once.
4663 ciaddr=`ip_to_hex 0 0 0 0`
4664 test_dhcp 3 f00000000003 01 $ciaddr 0 0 4 0
4666 # Send DHCPv4 packet on ls2-lp2. "router" DHCPv4 option is not defined for
4668 ciaddr=`ip_to_hex 0 0 0 0`
4669 test_dhcp 4 f00000000004 01 $ciaddr 0 0 3 0
4671 # NXT_RESUMEs should be 4.
4672 OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
4674 #OVN_CHECK_PACKETS([hv1/vif3-tx.pcap], [3.expected])
4675 #OVN_CHECK_PACKETS([hv1/vif4-tx.pcap], [4.expected])
4677 # Send DHCPREQUEST in the RENEWING/REBINDING state with ip4.src set to 10.0.0.6
4678 # and ip4.dst set to 10.0.0.1.
4679 offer_ip=`ip_to_hex 10 0 0 6`
4680 server_ip=`ip_to_hex 10 0 0 1`
4685 expected_dhcp_opts=330400000e100104ffffff0003040a00000136040a000001
4686 test_dhcp 2 f00000000002 03 $ciaddr $offer_ip $request_ip 1 $src_ip $dst_ip ff1000000001 $server_ip 05 $expected_dhcp_opts
4688 # NXT_RESUMEs should be 5.
4689 OVS_WAIT_UNTIL([test 5 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
4691 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets
4692 cat 2.expected | cut -c -48 > expout
4693 AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
4694 # Skipping the IPv4 checksum.
4695 cat 2.expected | cut -c 53- > expout
4696 AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
4698 reset_pcap_file hv1-vif1 hv1/vif1
4699 reset_pcap_file hv1-vif2 hv1/vif2
4703 # Send DHCPREQUEST in the RENEWING/REBINDING state with ip4.src set to 10.0.0.6
4704 # and ip4.dst set to 255.255.255.255.
4705 offer_ip=`ip_to_hex 10 0 0 6`
4706 server_ip=`ip_to_hex 10 0 0 1`
4710 dst_ip=`ip_to_hex 255 255 255 255`
4711 expected_dhcp_opts=330400000e100104ffffff0003040a00000136040a000001
4712 test_dhcp 2 f00000000002 03 $ciaddr $offer_ip $request_ip 1 $src_ip $dst_ip ff1000000001 $server_ip 05 $expected_dhcp_opts
4714 # NXT_RESUMEs should be 6.
4715 OVS_WAIT_UNTIL([test 6 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
4717 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets
4718 cat 2.expected | cut -c -48 > expout
4719 AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
4720 # Skipping the IPv4 checksum.
4721 cat 2.expected | cut -c 53- > expout
4722 AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
4724 reset_pcap_file hv1-vif1 hv1/vif1
4725 reset_pcap_file hv1-vif2 hv1/vif2
4729 # Send DHCPREQUEST in the RENEWING/REBINDING state with a mismatched IP in the
4730 # ciaddr, expect a DHCPNAK.
4731 offer_ip=`ip_to_hex 10 0 0 6`
4732 server_ip=`ip_to_hex 10 0 0 1`
4733 ciaddr=`ip_to_hex 10 0 0 7`
4736 dst_ip=`ip_to_hex 255 255 255 255`
4737 expected_dhcp_opts=""
4738 test_dhcp 2 f00000000002 03 $ciaddr $offer_ip $request_ip 1 $src_ip $dst_ip ff1000000001 $server_ip 06 $expected_dhcp_opts
4740 # NXT_RESUMEs should be 7.
4741 OVS_WAIT_UNTIL([test 7 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
4743 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets
4744 cat 2.expected | cut -c -48 > expout
4745 AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
4746 # Skipping the IPv4 checksum.
4747 cat 2.expected | cut -c 53- > expout
4748 AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
4750 reset_pcap_file hv1-vif1 hv1/vif1
4751 reset_pcap_file hv1-vif2 hv1/vif2
4755 # Send DHCPREQUEST in the RENEWING/REBINDING state without a specifyied ciaddr,
4757 offer_ip=`ip_to_hex 10 0 0 6`
4758 server_ip=`ip_to_hex 10 0 0 1`
4759 ciaddr=`ip_to_hex 0 0 0 0`
4762 dst_ip=`ip_to_hex 255 255 255 255`
4763 expected_dhcp_opts=""
4764 test_dhcp 2 f00000000002 03 $ciaddr $offer_ip $request_ip 1 $src_ip $dst_ip ff1000000001 $server_ip 06 $expected_dhcp_opts
4766 # NXT_RESUMEs should be 8.
4767 OVS_WAIT_UNTIL([test 8 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
4769 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets
4770 cat 2.expected | cut -c -48 > expout
4771 AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
4772 # Skipping the IPv4 checksum.
4773 cat 2.expected | cut -c 53- > expout
4774 AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
4776 reset_pcap_file hv1-vif1 hv1/vif1
4777 reset_pcap_file hv1-vif2 hv1/vif2
4781 # Send DHCPREQUEST with ip4.src set to 10.0.0.6 and ip4.dst set to 10.0.0.4.
4782 # The packet should not be received by ovn-controller.
4783 ciaddr=`ip_to_hex 0 0 0 0`
4784 src_ip=`ip_to_hex 10 0 0 6`
4785 dst_ip=`ip_to_hex 10 0 0 4`
4786 test_dhcp 2 f00000000002 03 $ciaddr 0 0 1 $src_ip $dst_ip 1
4788 # NXT_RESUMEs should be 8.
4789 OVS_WAIT_UNTIL([test 8 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
4791 # vif1-tx.pcap should have received the DHCPv4 request packet
4792 OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [1.expected])
4798 AT_SETUP([ovn -- dhcpv6 : 1 HV, 2 LS, 5 LSPs])
4799 AT_SKIP_IF([test $HAVE_PYTHON = no])
4802 ovn-nbctl ls-add ls1
4803 ovn-nbctl lsp-add ls1 ls1-lp1 \
4804 -- lsp-set-addresses ls1-lp1 "f0:00:00:00:00:01 10.0.0.4 ae70::4"
4806 ovn-nbctl lsp-set-port-security ls1-lp1 "f0:00:00:00:00:01 10.0.0.4 ae70::4"
4808 ovn-nbctl lsp-add ls1 ls1-lp2 \
4809 -- lsp-set-addresses ls1-lp2 "f0:00:00:00:00:02 ae70::5"
4811 ovn-nbctl lsp-set-port-security ls1-lp2 "f0:00:00:00:00:02 ae70::5"
4813 ovn-nbctl lsp-add ls1 ls1-lp3 \
4814 -- lsp-set-addresses ls1-lp3 "f0:00:00:00:00:22 ae70::22"
4816 ovn-nbctl lsp-set-port-security ls1-lp3 "f0:00:00:00:00:22 ae70::22"
4818 d1="$(ovn-nbctl create DHCP_Options cidr="ae70\:\:/64" \
4819 options="\"server_id\"=\"00:00:00:10:00:01\"")"
4821 ovn-nbctl lsp-set-dhcpv6-options ls1-lp1 ${d1}
4822 ovn-nbctl lsp-set-dhcpv6-options ls1-lp2 ${d1}
4824 d2="$(ovn-nbctl create DHCP_Options cidr="ae70\:\:/64" \
4825 options="\"dhcpv6_stateless\"=\"true\" \"server_id\"=\"00:00:00:10:00:01\"")"
4827 ovn-nbctl lsp-set-dhcpv6-options ls1-lp3 ${d2}
4829 ovn-nbctl ls-add ls2
4830 ovn-nbctl lsp-add ls2 ls2-lp1 \
4831 -- lsp-set-addresses ls2-lp1 "f0:00:00:00:00:03 be70::3"
4832 ovn-nbctl lsp-set-port-security ls2-lp1 "f0:00:00:00:00:03 be70::3"
4833 ovn-nbctl lsp-add ls2 ls2-lp2 \
4834 -- lsp-set-addresses ls2-lp2 "f0:00:00:00:00:04 be70::4"
4835 ovn-nbctl lsp-set-port-security ls2-lp2 "f0:00:00:00:00:04 be70::4"
4841 ovs-vsctl add-br br-phys
4842 ovn_attach n1 br-phys 192.168.0.1
4843 ovs-vsctl -- add-port br-int hv1-vif1 -- \
4844 set interface hv1-vif1 external-ids:iface-id=ls1-lp1 \
4845 options:tx_pcap=hv1/vif1-tx.pcap \
4846 options:rxq_pcap=hv1/vif1-rx.pcap \
4849 ovs-vsctl -- add-port br-int hv1-vif2 -- \
4850 set interface hv1-vif2 external-ids:iface-id=ls1-lp2 \
4851 options:tx_pcap=hv1/vif2-tx.pcap \
4852 options:rxq_pcap=hv1/vif2-rx.pcap \
4855 ovs-vsctl -- add-port br-int hv1-vif3 -- \
4856 set interface hv1-vif3 external-ids:iface-id=ls2-lp1 \
4857 options:tx_pcap=hv1/vif3-tx.pcap \
4858 options:rxq_pcap=hv1/vif3-rx.pcap \
4861 ovs-vsctl -- add-port br-int hv1-vif4 -- \
4862 set interface hv1-vif4 external-ids:iface-id=ls2-lp2 \
4863 options:tx_pcap=hv1/vif4-tx.pcap \
4864 options:rxq_pcap=hv1/vif4-rx.pcap \
4867 ovs-vsctl -- add-port br-int hv1-vif5 -- \
4868 set interface hv1-vif5 external-ids:iface-id=ls1-lp3 \
4869 options:tx_pcap=hv1/vif5-tx.pcap \
4870 options:rxq_pcap=hv1/vif5-rx.pcap \
4878 sed 's/\(00\)\{1,\}$//'
4881 # This shell function sends a DHCPv6 request packet
4882 # test_dhcpv6 INPORT SRC_MAC SRC_LLA DHCPv6_MSG_TYPE OFFER_IP OUTPORT...
4883 # The OUTPORTs (zero or more) list the VIFs on which the original DHCPv6
4884 # packet should be received twice (one from ovn-controller and the other
4885 # from the "ovs-ofctl monitor br-int resume"
4887 local inport=$1 src_mac=$2 src_lla=$3 msg_code=$4 offer_ip=$5
4888 if test $msg_code != 0b; then
4893 local request=ffffffffffff${src_mac}86dd0000000000${req_len}1101${src_lla}
4895 request=${request}ff020000000000000000000000010002
4896 # udp header and dhcpv6 header
4897 request=${request}0222022300${req_len}ffff${msg_code}010203
4899 request=${request}0001000a00030001${src_mac}
4900 # Add IA-NA (Identity Association for Non Temporary Address) if msg_code
4901 # is not 11 (information request packet)
4902 if test $msg_code != 0b; then
4903 request=${request}0003000c0102030400000e1000001518
4905 shift; shift; shift; shift; shift;
4906 if test $offer_ip != 0; then
4907 local server_mac=000000100001
4908 local server_lla=fe80000000000000020000fffe100001
4910 if test $msg_code = 01; then
4914 if test $offer_ip = 1; then
4917 local reply=${src_mac}${server_mac}86dd0000000000${msg_len}1101${server_lla}${src_lla}
4918 # udp header and dhcpv6 header
4919 reply=${reply}0223022200${msg_len}ffff${reply_code}010203
4921 reply=${reply}0001000a00030001${src_mac}
4923 if test $offer_ip != 1; then
4924 reply=${reply}0003002801020304ffffffffffffffff00050018${offer_ip}ffffffffffffffff
4927 reply=${reply}0002000a00030001${server_mac}
4928 echo $reply | trim_zeros >> $inport.expected
4931 echo $request | trim_zeros >> $outport.expected
4935 as hv1 ovs-appctl netdev-dummy/receive hv1-vif$inport $request
4941 ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \
4942 options:rxq_pcap=dummy-rx.pcap
4943 rm -f ${pcap_file}*.pcap
4944 ovs-vsctl -- set Interface $iface options:tx_pcap=${pcap_file}-tx.pcap \
4945 options:rxq_pcap=${pcap_file}-rx.pcap
4948 AT_CAPTURE_FILE([ofctl_monitor0.log])
4949 as hv1 ovs-ofctl monitor br-int resume --detach --no-chdir \
4950 --pidfile=ovs-ofctl0.pid 2> ofctl_monitor0.log
4952 echo "---------NB dump-----"
4954 echo "---------------------"
4955 echo "---------SB dump-----"
4956 ovn-sbctl list datapath_binding
4957 echo "---------------------"
4958 ovn-sbctl list logical_flow
4959 echo "---------------------"
4961 echo "---------------------"
4962 ovn-sbctl dump-flows
4963 echo "---------------------"
4965 echo "------ hv1 dump ----------"
4966 as hv1 ovs-ofctl dump-flows br-int
4968 src_mac=f00000000001
4969 src_lla=fe80000000000000f20000fffe000001
4970 offer_ip=ae700000000000000000000000000004
4971 test_dhcpv6 1 $src_mac $src_lla 01 $offer_ip
4973 # NXT_RESUMEs should be 1.
4974 OVS_WAIT_UNTIL([test 1 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
4976 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif1-tx.pcap | trim_zeros > 1.packets
4977 # cat 1.expected | trim_zeros > expout
4978 cat 1.expected | cut -c -120 > expout
4979 AT_CHECK([cat 1.packets | cut -c -120], [0], [expout])
4980 # Skipping the UDP checksum
4981 cat 1.expected | cut -c 125- > expout
4982 AT_CHECK([cat 1.packets | cut -c 125-], [0], [expout])
4986 # Send invalid packet on ls1-lp2. ovn-controller should resume the packet
4987 # without any modifications and the packet should be received by ls1-lp1.
4988 # ls1-lp1 will receive the packet twice, one from the ovn-controller after the
4989 # resume and the other from ovs-ofctl monitor resume.
4991 reset_pcap_file hv1-vif1 hv1/vif1
4992 reset_pcap_file hv1-vif2 hv1/vif2
4994 src_mac=f00000000002
4995 src_lla=fe80000000000000f20000fffe000002
4996 offer_ip=ae700000000000000000000000000005
4997 # Set invalid msg_type
4999 test_dhcpv6 2 $src_mac $src_lla 10 0 1 1
5001 # NXT_RESUMEs should be 2.
5002 OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
5004 # vif2-tx.pcap should not have received the DHCPv6 reply packet
5006 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap | trim_zeros > 2.packets
5007 AT_CHECK([cat 2.packets], [0], [])
5009 # vif1-tx.pcap should have received the DHCPv6 (invalid) request packet
5010 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif1-tx.pcap | trim_zeros > 1.packets
5011 cat 1.expected > expout
5012 AT_CHECK([cat 1.packets], [0], [expout])
5014 # Send DHCPv6 packet on ls2-lp1. native DHCPv6 is disabled on this port.
5015 # There should be no DHCPv6 reply from ovn-controller and the request packet
5016 # should be received by ls2-lp2.
5018 src_mac=f00000000003
5019 src_lla=fe80000000000000f20000fffe000003
5020 test_dhcpv6 3 $src_mac $src_lla 01 0 4
5022 # NXT_RESUMEs should be 2 only.
5023 OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
5025 # vif3-tx.pcap should not have received the DHCPv6 reply packet
5026 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif3-tx.pcap | trim_zeros > 3.packets
5027 AT_CHECK([cat 3.packets], [0], [])
5029 # vif4-tx.pcap should have received the DHCPv6 request packet
5030 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif4-tx.pcap | trim_zeros > 4.packets
5031 cat 4.expected > expout
5032 AT_CHECK([cat 4.packets], [0], [expout])
5034 # Send DHCPv6 packet on ls1-lp3. native DHCPv6 works as stateless mode for this port.
5035 # The DHCPv6 reply shouldn't contain offer_ip.
5036 src_mac=f00000000022
5037 src_lla=fe80000000000000f20000fffe000022
5038 reset_pcap_file hv1-vif5 hv1/vif5
5039 test_dhcpv6 5 $src_mac $src_lla 01 1 5
5041 # NXT_RESUMEs should be 3.
5042 OVS_WAIT_UNTIL([test 3 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
5044 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif5-tx.pcap | trim_zeros > 5.packets
5045 # Skipping the UDP checksum
5046 cat 5.expected | cut -c 1-120,125- > expout
5047 AT_CHECK([cat 5.packets | cut -c 1-120,125- ], [0], [expout])
5049 # Send DHCPv6 information request (code 11) on ls1-lp3. The DHCPv6 reply
5050 # shouldn't contain offer_ip
5051 src_mac=f00000000022
5052 src_lla=fe80000000000000f20000fffe000022
5053 reset_pcap_file hv1-vif5 hv1/vif5
5055 test_dhcpv6 5 $src_mac $src_lla 0b 1 5
5057 # NXT_RESUMEs should be 4.
5058 OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
5060 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif5-tx.pcap |
5061 trim_zeros > 5.packets
5062 # Skipping the UDP checksum
5063 cat 5.expected | cut -c 1-120,125- > expout
5064 AT_CHECK([cat 5.packets | cut -c 1-120,125- ], [0], [expout])
5070 AT_SETUP([ovn -- 2 HVs, 2 LRs connected via LS, gateway router])
5071 AT_SKIP_IF([test $HAVE_PYTHON = no])
5075 # Two LRs - R1 and R2 that are connected to each other via LS "join"
5076 # in 20.0.0.0/24 network. R1 has switchess foo (192.168.1.0/24)
5077 # connected to it. R2 has alice (172.16.1.0/24) connected to it.
5078 # R2 is a gateway router.
5082 # Create two hypervisor and create OVS ports corresponding to logical ports.
5087 ovs-vsctl add-br br-phys
5088 ovn_attach n1 br-phys 192.168.0.1
5089 ovs-vsctl -- add-port br-int hv1-vif1 -- \
5090 set interface hv1-vif1 external-ids:iface-id=foo1 \
5091 options:tx_pcap=hv1/vif1-tx.pcap \
5092 options:rxq_pcap=hv1/vif1-rx.pcap \
5098 ovs-vsctl add-br br-phys
5099 ovn_attach n1 br-phys 192.168.0.2
5100 ovs-vsctl -- add-port br-int hv2-vif1 -- \
5101 set interface hv2-vif1 external-ids:iface-id=alice1 \
5102 options:tx_pcap=hv2/vif1-tx.pcap \
5103 options:rxq_pcap=hv2/vif1-rx.pcap \
5106 # Pre-populate the hypervisors' ARP tables so that we don't lose any
5107 # packets for ARP resolution (native tunneling doesn't queue packets
5108 # for ARP resolution).
5111 ovn-nbctl create Logical_Router name=R1
5112 ovn-nbctl create Logical_Router name=R2 options:chassis="hv2"
5114 ovn-nbctl ls-add foo
5115 ovn-nbctl ls-add alice
5116 ovn-nbctl ls-add join
5119 ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
5120 ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
5121 type=router options:router-port=foo addresses=\"00:00:01:01:02:03\"
5123 # Connect alice to R2
5124 ovn-nbctl lrp-add R2 alice 00:00:02:01:02:03 172.16.1.1/24
5125 ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port rp-alice \
5126 type=router options:router-port=alice addresses=\"00:00:02:01:02:03\"
5128 # Connect R1 to join
5129 ovn-nbctl lrp-add R1 R1_join 00:00:04:01:02:03 20.0.0.1/24
5130 ovn-nbctl lsp-add join r1-join -- set Logical_Switch_Port r1-join \
5131 type=router options:router-port=R1_join addresses='"00:00:04:01:02:03"'
5133 # Connect R2 to join
5134 ovn-nbctl lrp-add R2 R2_join 00:00:04:01:02:04 20.0.0.2/24
5135 ovn-nbctl lsp-add join r2-join -- set Logical_Switch_Port r2-join \
5136 type=router options:router-port=R2_join addresses='"00:00:04:01:02:04"'
5139 #install static routes
5140 ovn-nbctl -- --id=@lrt create Logical_Router_Static_Route \
5141 ip_prefix=172.16.1.0/24 nexthop=20.0.0.2 -- add Logical_Router \
5142 R1 static_routes @lrt
5144 ovn-nbctl -- --id=@lrt create Logical_Router_Static_Route \
5145 ip_prefix=192.168.1.0/24 nexthop=20.0.0.1 -- add Logical_Router \
5146 R2 static_routes @lrt
5148 # Create logical port foo1 in foo
5149 ovn-nbctl lsp-add foo foo1 \
5150 -- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
5152 # Create logical port alice1 in alice
5153 ovn-nbctl lsp-add alice alice1 \
5154 -- lsp-set-addresses alice1 "f0:00:00:01:02:04 172.16.1.2"
5157 # Allow some time for ovn-northd and ovn-controller to catch up.
5158 # XXX This should be more systematic.
5162 printf "%02x%02x%02x%02x" "$@"
5165 # Send ip packets between foo1 and alice1
5166 src_mac="f00000010203"
5167 dst_mac="000001010203"
5168 src_ip=`ip_to_hex 192 168 1 2`
5169 dst_ip=`ip_to_hex 172 16 1 2`
5170 packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
5172 echo "---------NB dump-----"
5174 echo "---------------------"
5175 ovn-nbctl list logical_router
5176 echo "---------------------"
5177 ovn-nbctl list logical_router_port
5178 echo "---------------------"
5180 echo "---------SB dump-----"
5181 ovn-sbctl list datapath_binding
5182 echo "---------------------"
5183 ovn-sbctl list port_binding
5184 echo "---------------------"
5185 ovn-sbctl dump-flows
5186 echo "---------------------"
5187 ovn-sbctl list chassis
5188 ovn-sbctl list encap
5189 echo "---------------------"
5191 # Packet to Expect at alice1
5192 src_mac="000002010203"
5193 dst_mac="f00000010204"
5194 src_ip=`ip_to_hex 192 168 1 2`
5195 dst_ip=`ip_to_hex 172 16 1 2`
5196 expected=${dst_mac}${src_mac}08004500001c000000003e110200${src_ip}${dst_ip}0035111100080000
5199 as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
5200 as hv1 ovs-appctl ofproto/trace br-int in_port=1 $packet
5202 echo "------ hv1 dump after packet 1 ----------"
5203 as hv1 ovs-ofctl show br-int
5204 as hv1 ovs-ofctl dump-flows br-int
5205 echo "------ hv2 dump after packet 1 ----------"
5206 as hv2 ovs-ofctl show br-int
5207 as hv2 ovs-ofctl dump-flows br-int
5208 echo "----------------------------"
5210 echo $expected > expected
5211 OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
5213 # Delete the router and re-create it. Things should work as before.
5215 ovn-nbctl create Logical_Router name=R2 options:chassis="hv2"
5216 # Connect alice to R2
5217 ovn-nbctl lrp-add R2 alice 00:00:02:01:02:03 172.16.1.1/24
5218 # Connect R2 to join
5219 ovn-nbctl lrp-add R2 R2_join 00:00:04:01:02:04 20.0.0.2/24
5221 ovn-nbctl -- --id=@lrt create Logical_Router_Static_Route \
5222 ip_prefix=192.168.1.0/24 nexthop=20.0.0.1 -- add Logical_Router \
5223 R2 static_routes @lrt
5225 # Wait for ovn-controller to catch up.
5228 # Send the packet again.
5229 as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
5231 echo "------ hv1 dump after packet 2 ----------"
5232 as hv1 ovs-ofctl show br-int
5233 as hv1 ovs-ofctl dump-flows br-int
5234 echo "------ hv2 dump after packet 2 ----------"
5235 as hv2 ovs-ofctl show br-int
5236 as hv2 ovs-ofctl dump-flows br-int
5237 echo "----------------------------"
5239 echo $expected >> expected
5240 OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
5242 OVN_CLEANUP([hv1],[hv2])
5246 AT_SETUP([ovn -- icmp_reply: 1 HVs, 2 LSs, 1 lport/LS, 1 LR])
5247 AT_KEYWORDS([router-icmp-reply])
5248 AT_SKIP_IF([test $HAVE_PYTHON = no])
5252 # One LR - R1 has switch ls1 (191.168.1.0/24) connected to it,
5253 # and has switch ls2 (172.16.1.0/24) connected to it.
5257 ovn-nbctl ls-add ls1
5258 ovn-nbctl ls-add ls2
5261 ovn-nbctl lrp-add R1 ls1 00:00:00:01:02:f1 192.168.1.1/24
5262 ovn-nbctl lsp-add ls1 rp-ls1 -- set Logical_Switch_Port rp-ls1 \
5263 type=router options:router-port=ls1 addresses=\"00:00:00:01:02:f1\"
5266 ovn-nbctl lrp-add R1 ls2 00:00:00:01:02:f2 172.16.1.1/24
5267 ovn-nbctl lsp-add ls2 rp-ls2 -- set Logical_Switch_Port rp-ls2 \
5268 type=router options:router-port=ls2 addresses=\"00:00:00:01:02:f2\"
5270 # Create logical port ls1-lp1 in ls1
5271 ovn-nbctl lsp-add ls1 ls1-lp1 \
5272 -- lsp-set-addresses ls1-lp1 "00:00:00:01:02:03 192.168.1.2"
5274 # Create logical port ls2-lp1 in ls2
5275 ovn-nbctl lsp-add ls2 ls2-lp1 \
5276 -- lsp-set-addresses ls2-lp1 "00:00:00:01:02:04 172.16.1.2"
5278 # Create one hypervisor and create OVS ports corresponding to logical ports.
5283 ovs-vsctl add-br br-phys
5284 ovn_attach n1 br-phys 192.168.0.1
5285 ovs-vsctl -- add-port br-int vif1 -- \
5286 set interface vif1 external-ids:iface-id=ls1-lp1 \
5287 options:tx_pcap=hv1/vif1-tx.pcap \
5288 options:rxq_pcap=hv1/vif1-rx.pcap \
5291 ovs-vsctl -- add-port br-int vif2 -- \
5292 set interface vif2 external-ids:iface-id=ls2-lp1 \
5293 options:tx_pcap=hv1/vif2-tx.pcap \
5294 options:rxq_pcap=hv1/vif2-rx.pcap \
5298 # Allow some time for ovn-northd and ovn-controller to catch up.
5299 # XXX This should be more systematic.
5304 printf "%02x%02x%02x%02x" "$@"
5309 # test_ipv4_icmp_request INPORT ETH_SRC ETH_DST IPV4_SRC IPV4_DST IP_CHKSUM ICMP_CHKSUM [EXP_IP_CHKSUM EXP_ICMP_CHKSUM]
5311 # Causes a packet to be received on INPORT. The packet is an ICMPv4
5312 # request with ETH_SRC, ETH_DST, IPV4_SRC, IPV4_DST, IP_CHSUM and
5313 # ICMP_CHKSUM as specified. If EXP_IP_CHKSUM and EXP_ICMP_CHKSUM are
5314 # provided, then it should be the ip and icmp checksums of the packet
5315 # responded; otherwise, no reply is expected.
5316 # In the absence of an ip checksum calculation helpers, this relies
5317 # on the caller to provide the checksums for the ip and icmp headers.
5318 # XXX This should be more systematic.
5320 # INPORT is an lport number, e.g. 11 for vif11.
5321 # ETH_SRC and ETH_DST are each 12 hex digits.
5322 # IPV4_SRC and IPV4_DST are each 8 hex digits.
5323 # IP_CHSUM and ICMP_CHKSUM are each 4 hex digits.
5324 # EXP_IP_CHSUM and EXP_ICMP_CHKSUM are each 4 hex digits.
5325 test_ipv4_icmp_request() {
5326 local inport=$1 eth_src=$2 eth_dst=$3 ipv4_src=$4 ipv4_dst=$5 ip_chksum=$6 icmp_chksum=$7
5327 local exp_ip_chksum=$8 exp_icmp_chksum=$9
5328 shift; shift; shift; shift; shift; shift; shift
5331 # Use ttl to exercise section 4.2.2.9 of RFC1812
5335 local icmp_data=$(seq 1 56 | xargs printf "%02x")
5336 local icmp_type_code_request=0800
5337 local icmp_payload=${icmp_type_code_request}${icmp_chksum}${icmp_id}${icmp_seq}${icmp_data}
5338 local packet=${eth_dst}${eth_src}08004500005400004000${ip_ttl}01${ip_chksum}${ipv4_src}${ipv4_dst}${icmp_payload}
5340 as hv1 ovs-appctl netdev-dummy/receive vif$inport $packet
5341 if test X$exp_icmp_chksum != X; then
5342 # Expect to receive the reply, if any. In same port where packet was sent.
5343 # Note: src and dst fields are expected to be reversed.
5344 local icmp_type_code_response=0000
5345 local reply_icmp_ttl=fe
5346 local reply_icmp_payload=${icmp_type_code_response}${exp_icmp_chksum}${icmp_id}${icmp_seq}${icmp_data}
5347 local reply=${eth_src}${eth_dst}08004500005400004000${reply_icmp_ttl}01${exp_ip_chksum}${ipv4_dst}${ipv4_src}${reply_icmp_payload}
5348 echo $reply >> vif$inport.expected
5352 # Send ping packet to router's ip addresses, from each of the 2 logical ports.
5353 rtr_l1_ip=$(ip_to_hex 192 168 1 1)
5354 rtr_l2_ip=$(ip_to_hex 172 16 1 1)
5355 l1_ip=$(ip_to_hex 192 168 1 2)
5356 l2_ip=$(ip_to_hex 172 16 1 2)
5358 # Ping router ip address that is on same subnet as the logical port
5359 test_ipv4_icmp_request 1 000000010203 0000000102f1 $l1_ip $rtr_l1_ip 0000 8510 02ff 8d10
5360 test_ipv4_icmp_request 2 000000010204 0000000102f2 $l2_ip $rtr_l2_ip 0000 8510 02ff 8d10
5362 # Ping router ip address that is on the other side of the logical ports
5363 test_ipv4_icmp_request 1 000000010203 0000000102f1 $l1_ip $rtr_l2_ip 0000 8510 02ff 8d10
5364 test_ipv4_icmp_request 2 000000010204 0000000102f2 $l2_ip $rtr_l1_ip 0000 8510 02ff 8d10
5367 echo "---------NB dump-----"
5369 echo "---------------------"
5370 ovn-nbctl list logical_router
5371 echo "---------------------"
5372 ovn-nbctl list logical_router_port
5373 echo "---------------------"
5375 echo "---------SB dump-----"
5376 ovn-sbctl list datapath_binding
5377 echo "---------------------"
5378 ovn-sbctl list logical_flow
5379 echo "---------------------"
5381 echo "------ hv1 dump ----------"
5382 as hv1 ovs-ofctl dump-flows br-int
5384 # Now check the packets actually received against the ones expected.
5385 for inport in 1 2; do
5386 OVN_CHECK_PACKETS([hv1/vif${inport}-tx.pcap], [vif$inport.expected])
5392 AT_SETUP([ovn -- policy-based routing: 1 HVs, 2 LSs, 1 lport/LS, 1 LR])
5393 AT_KEYWORDS([policy-based-routing])
5394 AT_SKIP_IF([test $HAVE_PYTHON = no])
5398 # One LR - R1 has switch ls1 (191.168.1.0/24) connected to it,
5399 # and has switch ls2 (172.16.1.0/24) connected to it.
5403 ovn-nbctl ls-add ls1
5404 ovn-nbctl ls-add ls2
5405 ovn-nbctl ls-add ls3
5408 ovn-nbctl lrp-add R1 ls1 00:00:00:01:02:f1 192.168.1.1/24
5409 ovn-nbctl lsp-add ls1 rp-ls1 -- set Logical_Switch_Port rp-ls1 \
5410 type=router options:router-port=ls1 addresses=\"00:00:00:01:02:f1\"
5413 ovn-nbctl lrp-add R1 ls2 00:00:00:01:02:f2 172.16.1.1/24
5414 ovn-nbctl lsp-add ls2 rp-ls2 -- set Logical_Switch_Port rp-ls2 \
5415 type=router options:router-port=ls2 addresses=\"00:00:00:01:02:f2\"
5418 ovn-nbctl lrp-add R1 ls3 00:00:00:01:02:f3 20.20.1.1/24
5419 ovn-nbctl lsp-add ls3 rp-ls3 -- set Logical_Switch_Port rp-ls3 \
5420 type=router options:router-port=ls3 addresses=\"00:00:00:01:02:f3\"
5422 # Create logical port ls1-lp1 in ls1
5423 ovn-nbctl lsp-add ls1 ls1-lp1 \
5424 -- lsp-set-addresses ls1-lp1 "00:00:00:01:02:03 192.168.1.2"
5426 # Create logical port ls2-lp1 in ls2
5427 ovn-nbctl lsp-add ls2 ls2-lp1 \
5428 -- lsp-set-addresses ls2-lp1 "00:00:00:01:02:04 172.16.1.2"
5430 # Create logical port ls3-lp1 in ls3
5431 ovn-nbctl lsp-add ls3 ls3-lp1 \
5432 -- lsp-set-addresses ls3-lp1 "00:00:00:01:02:05 20.20.1.2"
5434 # Create one hypervisor and create OVS ports corresponding to logical ports.
5439 ovs-vsctl add-br br-phys
5440 ovn_attach n1 br-phys 192.168.0.1
5442 ovs-vsctl -- add-port br-int vif1 -- \
5443 set interface vif1 external-ids:iface-id=ls1-lp1 \
5444 options:tx_pcap=pbr-hv/vif1-tx.pcap \
5445 options:rxq_pcap=pbr-hv/vif1-rx.pcap \
5448 ovs-vsctl -- add-port br-int vif2 -- \
5449 set interface vif2 external-ids:iface-id=ls2-lp1 \
5450 options:tx_pcap=pbr-hv/vif2-tx.pcap \
5451 options:rxq_pcap=pbr-hv/vif2-rx.pcap \
5454 ovs-vsctl -- add-port br-int vif3 -- \
5455 set interface vif3 external-ids:iface-id=ls3-lp1 \
5456 options:tx_pcap=pbr-hv/vif3-tx.pcap \
5457 options:rxq_pcap=pbr-hv/vif3-rx.pcap \
5460 # Allow some time for ovn-northd and ovn-controller to catch up.
5461 # XXX This should be more systematic.
5464 ls1_ro_mac=00:00:00:01:02:f1
5465 ls1_ro_ip=192.168.1.1
5467 ls2_ro_mac=00:00:00:01:02:f2
5468 ls2_ro_ip=172.16.1.1
5470 ls3_ro_mac=00:00:00:01:02:f3
5472 ls1_p1_mac=00:00:00:01:02:03
5473 ls1_p1_ip=192.168.1.2
5475 ls2_p1_mac=00:00:00:01:02:04
5476 ls2_p1_ip=172.16.1.2
5478 ls3_p1_mac=00:00:00:01:02:05
5480 # Create a drop policy
5481 ovn-nbctl lr-policy-add R1 10 "ip4.src==192.168.1.0/24 && ip4.dst==172.16.1.0/24" drop
5483 # Check logical flow
5484 AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | grep "192.168.1.0" | wc -l], [0], [dnl
5489 packet="inport==\"ls1-lp1\" && eth.src==$ls1_p1_mac && eth.dst==$ls1_ro_mac &&
5490 ip4 && ip.ttl==64 && ip4.src==$ls1_p1_ip && ip4.dst==$ls2_p1_ip &&
5491 udp && udp.src==53 && udp.dst==4369"
5493 as pbr-hv ovs-appctl -t ovn-controller inject-pkt "$packet"
5495 # Check if packet hit the drop policy
5496 AT_CHECK([ovs-ofctl dump-flows br-int | \
5497 grep "nw_src=192.168.1.0/24,nw_dst=172.16.1.0/24 actions=drop" | \
5498 grep "priority=10" | \
5499 grep "n_packets=1" | wc -l], [0], [dnl
5503 # Expected to drop the packet.
5504 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" pbr-hv/vif2-tx.pcap > vif2.packets
5505 rcvd_packet=`cat vif2.packets`
5506 AT_FAIL_IF([rcvd_packet = ""])
5508 # Override drop policy with allow
5509 ovn-nbctl lr-policy-add R1 20 "ip4.src==192.168.1.0/24 && ip4.dst==172.16.1.0/24" allow
5511 # Check logical flow
5512 AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | grep "192.168.1.0" | wc -l], [0], [dnl
5517 packet="inport==\"ls1-lp1\" && eth.src==$ls1_p1_mac && eth.dst==$ls1_ro_mac &&
5518 ip4 && ip.ttl==64 && ip4.src==$ls1_p1_ip && ip4.dst==$ls2_p1_ip &&
5519 udp && udp.src==53 && udp.dst==4369"
5520 as pbr-hv ovs-appctl -t ovn-controller inject-pkt "$packet"
5522 # Check if packet hit the allow policy
5523 AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | \
5524 grep "192.168.1.0" | \
5525 grep "priority=20" | wc -l], [0], [dnl
5529 # Expected packet has TTL decreased by 1
5530 expected="eth.src==$ls2_ro_mac && eth.dst==$ls2_p1_mac &&
5531 ip4 && ip.ttl==63 && ip4.src==$ls1_p1_ip && ip4.dst==$ls2_p1_ip &&
5532 udp && udp.src==53 && udp.dst==4369"
5533 echo $expected | ovstest test-ovn expr-to-packets > expected
5535 OVN_CHECK_PACKETS([pbr-hv/vif2-tx.pcap], [expected])
5537 # Override allow policy with reroute
5538 ovn-nbctl lr-policy-add R1 30 "ip4.src==192.168.1.0/24 && ip4.dst==172.16.1.0/24" reroute 20.20.1.2
5540 # Check logical flow
5541 AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | \
5542 grep "192.168.1.0" | \
5543 grep "priority=30" | wc -l], [0], [dnl
5548 packet="inport==\"ls1-lp1\" && eth.src==$ls1_p1_mac && eth.dst==$ls1_ro_mac &&
5549 ip4 && ip.ttl==64 && ip4.src==$ls1_p1_ip && ip4.dst==$ls2_p1_ip &&
5550 udp && udp.src==53 && udp.dst==4369"
5551 as pbr-hv ovs-appctl -t ovn-controller inject-pkt "$packet"
5553 echo "southbound flows"
5555 ovn-sbctl dump-flows | grep lr_in_policy
5557 ovs-ofctl dump-flows br-int
5558 # Check if packet hit the allow policy
5559 AT_CHECK([ovs-ofctl dump-flows br-int | \
5560 grep "nw_src=192.168.1.0/24,nw_dst=172.16.1.0/24" | \
5561 grep "priority=30" | \
5562 grep "n_packets=1" | wc -l], [0], [dnl
5565 echo "packet hit reroute policy"
5567 # Expected packet has TTL decreased by 1
5568 expected="eth.src==$ls3_ro_mac && eth.dst==$ls3_p1_mac &&
5569 ip4 && ip.ttl==63 && ip4.src==$ls1_p1_ip && ip4.dst==$ls2_p1_ip &&
5570 udp && udp.src==53 && udp.dst==4369"
5571 echo $expected | ovstest test-ovn expr-to-packets > 3.expected
5573 OVN_CHECK_PACKETS([pbr-hv/vif3-tx.pcap], [3.expected])
5575 OVN_CLEANUP([pbr-hv])
5578 AT_SETUP([ovn -- policy-based routing IPv6: 1 HVs, 3 LSs, 1 lport/LS, 1 LR])
5579 AT_KEYWORDS([policy-based-routing])
5580 AT_SKIP_IF([test $HAVE_PYTHON = no])
5584 # One LR - R1 has switch ls1 (191.168.1.0/24) connected to it,
5585 # and has switch ls2 (172.16.1.0/24) connected to it.
5589 ovn-nbctl ls-add ls1
5590 ovn-nbctl ls-add ls2
5591 ovn-nbctl ls-add ls3
5594 ovn-nbctl lrp-add R1 ls1 00:00:00:01:02:f1 2001::1/64
5595 ovn-nbctl lsp-add ls1 rp-ls1 -- set Logical_Switch_Port rp-ls1 \
5596 type=router options:router-port=ls1 addresses=\"00:00:00:01:02:f1\"
5599 ovn-nbctl lrp-add R1 ls2 00:00:00:01:02:f2 2002::1/64
5600 ovn-nbctl lsp-add ls2 rp-ls2 -- set Logical_Switch_Port rp-ls2 \
5601 type=router options:router-port=ls2 addresses=\"00:00:00:01:02:f2\"
5604 ovn-nbctl lrp-add R1 ls3 00:00:00:01:02:f3 2003::1/64
5605 ovn-nbctl lsp-add ls3 rp-ls3 -- set Logical_Switch_Port rp-ls3 \
5606 type=router options:router-port=ls3 addresses=\"00:00:00:01:02:f3\"
5608 # Create logical port ls1-lp1 in ls1
5609 ovn-nbctl lsp-add ls1 ls1-lp1 \
5610 -- lsp-set-addresses ls1-lp1 "00:00:00:01:02:03 2001::2"
5612 # Create logical port ls2-lp1 in ls2
5613 ovn-nbctl lsp-add ls2 ls2-lp1 \
5614 -- lsp-set-addresses ls2-lp1 "00:00:00:01:02:04 2002::2"
5616 # Create logical port ls3-lp1 in ls3
5617 ovn-nbctl lsp-add ls3 ls3-lp1 \
5618 -- lsp-set-addresses ls3-lp1 "00:00:00:01:02:05 2003::2"
5620 # Create one hypervisor and create OVS ports corresponding to logical ports.
5625 ovs-vsctl add-br br-phys
5626 ovn_attach n1 br-phys 192.168.0.1
5628 ovs-vsctl -- add-port br-int vif1 -- \
5629 set interface vif1 external-ids:iface-id=ls1-lp1 \
5630 options:tx_pcap=pbr-hv/vif1-tx.pcap \
5631 options:rxq_pcap=pbr-hv/vif1-rx.pcap \
5634 ovs-vsctl -- add-port br-int vif2 -- \
5635 set interface vif2 external-ids:iface-id=ls2-lp1 \
5636 options:tx_pcap=pbr-hv/vif2-tx.pcap \
5637 options:rxq_pcap=pbr-hv/vif2-rx.pcap \
5640 ovs-vsctl -- add-port br-int vif3 -- \
5641 set interface vif3 external-ids:iface-id=ls3-lp1 \
5642 options:tx_pcap=pbr-hv/vif3-tx.pcap \
5643 options:rxq_pcap=pbr-hv/vif3-rx.pcap \
5646 # Allow some time for ovn-northd and ovn-controller to catch up.
5647 # XXX This should be more systematic.
5650 ls1_ro_mac=00:00:00:01:02:f1
5653 ls2_ro_mac=00:00:00:01:02:f2
5656 ls3_ro_mac=00:00:00:01:02:f3
5658 ls1_p1_mac=00:00:00:01:02:03
5661 ls2_p1_mac=00:00:00:01:02:04
5664 ls3_p1_mac=00:00:00:01:02:05
5666 # Create a drop policy
5667 ovn-nbctl lr-policy-add R1 10 "ip6.src==2001::/64 && ip6.dst==2002::/64" drop
5669 # Check logical flow
5670 AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | grep "2001" | wc -l], [0], [dnl
5675 packet="inport==\"ls1-lp1\" && eth.src==$ls1_p1_mac && eth.dst==$ls1_ro_mac &&
5676 ip6 && ip.ttl==64 && ip6.src==$ls1_p1_ip && ip6.dst==$ls2_p1_ip &&
5677 udp && udp.src==53 && udp.dst==4369"
5679 as pbr-hv ovs-appctl -t ovn-controller inject-pkt "$packet"
5681 # Check if packet hit the drop policy
5682 AT_CHECK([ovs-ofctl dump-flows br-int | \
5683 grep "ipv6_src=2001::/64,ipv6_dst=2002::/64 actions=drop" | \
5684 grep "priority=10" | \
5685 grep "n_packets=1" | wc -l], [0], [dnl
5689 # Expected to drop the packet.
5690 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" pbr-hv/vif2-tx.pcap > vif2.packets
5691 rcvd_packet=`cat vif2.packets`
5692 AT_FAIL_IF([rcvd_packet = ""])
5694 # Override drop policy with allow
5695 ovn-nbctl lr-policy-add R1 20 "ip6.src==2001::/64 && ip6.dst==2002::/64" allow
5697 # Check logical flow
5698 AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | grep "2001" | wc -l], [0], [dnl
5703 packet="inport==\"ls1-lp1\" && eth.src==$ls1_p1_mac && eth.dst==$ls1_ro_mac &&
5704 ip6 && ip.ttl==64 && ip6.src==$ls1_p1_ip && ip6.dst==$ls2_p1_ip &&
5705 udp && udp.src==53 && udp.dst==4369"
5706 as pbr-hv ovs-appctl -t ovn-controller inject-pkt "$packet"
5708 # Check if packet hit the allow policy
5709 AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | \
5711 grep "priority=20" | wc -l], [0], [dnl
5715 # Expected packet has TTL decreased by 1
5716 expected="eth.src==$ls2_ro_mac && eth.dst==$ls2_p1_mac &&
5717 ip6 && ip.ttl==63 && ip6.src==$ls1_p1_ip && ip6.dst==$ls2_p1_ip &&
5718 udp && udp.src==53 && udp.dst==4369"
5719 echo $expected | ovstest test-ovn expr-to-packets > expected
5721 OVN_CHECK_PACKETS([pbr-hv/vif2-tx.pcap], [expected])
5723 # Override allow policy with reroute
5724 ovn-nbctl lr-policy-add R1 30 "ip6.src==2001::/64 && ip6.dst==2002::/64" reroute 2003::2
5726 # Check logical flow
5727 AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | \
5729 grep "priority=30" | wc -l], [0], [dnl
5734 packet="inport==\"ls1-lp1\" && eth.src==$ls1_p1_mac && eth.dst==$ls1_ro_mac &&
5735 ip6 && ip.ttl==64 && ip6.src==$ls1_p1_ip && ip6.dst==$ls2_p1_ip &&
5736 udp && udp.src==53 && udp.dst==4369"
5737 as pbr-hv ovs-appctl -t ovn-controller inject-pkt "$packet"
5739 echo "southbound flows"
5741 ovn-sbctl dump-flows | grep lr_in_policy
5743 ovs-ofctl dump-flows br-int
5744 # Check if packet hit the allow policy
5745 AT_CHECK([ovs-ofctl dump-flows br-int | \
5746 grep "ipv6_src=2001::/64,ipv6_dst=2002::/64" | \
5747 grep "priority=30" | \
5748 grep "n_packets=1" | wc -l], [0], [dnl
5751 echo "packet hit reroute policy"
5753 # Expected packet has TTL decreased by 1
5754 expected="eth.src==$ls3_ro_mac && eth.dst==$ls3_p1_mac &&
5755 ip6 && ip.ttl==63 && ip6.src==$ls1_p1_ip && ip6.dst==$ls2_p1_ip &&
5756 udp && udp.src==53 && udp.dst==4369"
5757 echo $expected | ovstest test-ovn expr-to-packets > 3.expected
5759 OVN_CHECK_PACKETS([pbr-hv/vif3-tx.pcap], [3.expected])
5761 OVN_CLEANUP([pbr-hv])
5764 # 1 hypervisor, 1 port
5765 # make sure that the port state is properly set to up and back down
5766 # when created and deleted.
5767 AT_SETUP([ovn -- port state up and down])
5770 ovn-nbctl ls-add ls1
5771 ovn-nbctl lsp-add ls1 lp1
5772 ovn-nbctl lsp-set-addresses lp1 unknown
5776 as hv1 ovs-vsctl add-br br-phys
5777 as hv1 ovn_attach n1 br-phys 192.168.0.1
5779 as hv1 ovs-vsctl add-port br-int vif1 -- set Interface vif1 external-ids:iface-id=lp1
5780 OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up lp1` = xup])
5782 as hv1 ovs-vsctl del-port br-int vif1
5783 OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up lp1` = xdown])
5789 # 1 hypervisor, 1 port
5790 # make sure that the OF rules created to support a datapath are added/cleared
5791 # when logical switch is created and removed.
5792 AT_SETUP([ovn -- datapath rules added/removed])
5793 AT_KEYWORDS([cleanup])
5798 as hv1 ovs-vsctl add-br br-phys
5799 as hv1 ovn_attach n1 br-phys 192.168.0.1
5801 # This shell function checks if OF rules in br-int have clauses
5802 # related to OVN datapaths. The caller determines if it should find
5803 # a match in the output, or not.
5805 # EXPECT_DATAPATH param determines whether flows that refer to
5806 # datapath to should be present or not. 0 means
5807 # they should not be.
5808 # STAGE_INFO param is a simple string to help identify the stage
5809 # in the test when this function was invoked.
5810 test_datapath_in_of_rules() {
5811 local expect_datapath=$1 stage_info=$2
5812 echo "------ ovn-nbctl show ${stage_info} ------"
5814 echo "------ ovn-sbctl show ${stage_info} ------"
5816 echo "------ OF rules ${stage_info} ------"
5817 AT_CHECK([ovs-ofctl dump-flows br-int], [0], [stdout])
5818 # if there is a datapath mentioned in the output, check for the
5819 # magic keyword that represents one, based on the exit status of
5821 if test $expect_datapath != 0; then
5822 AT_CHECK([grep -q -i 'metadata=' stdout], [0], [ignore-nolog])
5824 AT_CHECK([grep -q -i 'metadata=' stdout], [1], [ignore-nolog])
5828 test_datapath_in_of_rules 0 "before ls+port create"
5830 ovn-nbctl ls-add ls1
5831 ovn-nbctl lsp-add ls1 lp1
5832 ovn-nbctl lsp-set-addresses lp1 unknown
5834 as hv1 ovs-vsctl add-port br-int vif1 -- set Interface vif1 external-ids:iface-id=lp1
5835 OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up lp1` = xup])
5837 test_datapath_in_of_rules 1 "after port is bound"
5839 as hv1 ovs-vsctl del-port br-int vif1
5840 OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up lp1` = xdown])
5842 ovn-nbctl lsp-set-addresses lp1
5843 ovn-nbctl lsp-del lp1
5844 ovn-nbctl ls-del ls1
5846 # wait for earlier changes to take effect
5847 AT_CHECK([ovn-nbctl --timeout=3 --wait=sb sync], [0], [ignore])
5849 # ensure OF rules are no longer present. There used to be a bug here.
5850 test_datapath_in_of_rules 0 "after lport+ls removal"
5856 AT_SETUP([ovn -- nd_na ])
5857 AT_SKIP_IF([test $HAVE_PYTHON = no])
5860 #TODO: since patch port for IPv6 logical router port is not ready not,
5861 # so we are not going to test vifs on different lswitches cases. Try
5862 # to update for that once relevant stuff implemented.
5864 # In this test cases we create 1 lswitch, it has 2 VIF ports attached
5865 # with. NS packet we test, from one VIF for another VIF, will be replied
5866 # by local ovn-controller, but not by target VIF.
5868 # Create hypervisors and logical switch lsw0.
5869 ovn-nbctl ls-add lsw0
5873 ovs-vsctl add-br br-phys
5874 ovn_attach n1 br-phys 192.168.0.2
5876 # Add vif1 to hv1 and lsw0, turn on l2 port security on vif1.
5877 ovs-vsctl add-port br-int vif1 -- set Interface vif1 external-ids:iface-id=lp1 options:tx_pcap=hv1/vif1-tx.pcap options:rxq_pcap=hv1/vif1-rx.pcap ofport-request=1
5878 ovn-nbctl lsp-add lsw0 lp1
5879 ovn-nbctl lsp-set-addresses lp1 "fa:16:3e:94:05:98 192.168.0.3 fd81:ce49:a948:0:f816:3eff:fe94:598"
5880 ovn-nbctl lsp-set-port-security lp1 "fa:16:3e:94:05:98 192.168.0.3 fd81:ce49:a948:0:f816:3eff:fe94:598"
5882 # Add vif2 to hv1 and lsw0, turn on l2 port security on vif2.
5883 ovs-vsctl add-port br-int vif2 -- set Interface vif2 external-ids:iface-id=lp2 options:tx_pcap=hv1/vif2-tx.pcap options:rxq_pcap=hv1/vif2-rx.pcap ofport-request=2
5884 ovn-nbctl lsp-add lsw0 lp2
5885 ovn-nbctl lsp-set-addresses lp2 "fa:16:3e:a1:f9:ae 192.168.0.4 fd81:ce49:a948:0:f816:3eff:fea1:f9ae"
5886 ovn-nbctl lsp-set-port-security lp2 "fa:16:3e:a1:f9:ae 192.168.0.4 fd81:ce49:a948:0:f816:3eff:fea1:f9ae"
5888 # Add ACL rule for ICMPv6 on lsw0
5889 ovn-nbctl acl-add lsw0 from-lport 1002 'ip6 && icmp6' allow-related
5890 ovn-nbctl acl-add lsw0 to-lport 1002 'outport == "lp1" && ip6 && icmp6' allow-related
5891 ovn-nbctl acl-add lsw0 to-lport 1002 'outport == "lp2" && ip6 && icmp6' allow-related
5893 # Allow some time for ovn-northd and ovn-controller to catch up.
5894 # XXX This should be more systematic.
5897 # Given the name of a logical port, prints the name of the hypervisor
5898 # on which it is located.
5906 # Complete Neighbor Solicitation packet and Neighbor Advertisement packet
5907 # vif1 -> NS -> vif2. vif1 <- NA <- ovn-controller.
5908 # vif2 will not receive NS packet, since ovn-controller will reply for it.
5909 ns_packet=3333ffa1f9aefa163e94059886dd6000000000203afffd81ce49a9480000f8163efffe940598fd81ce49a9480000f8163efffea1f9ae8700e01160000000fd81ce49a9480000f8163efffea1f9ae0101fa163e940598
5910 na_packet=fa163e940598fa163ea1f9ae86dd6000000000203afffd81ce49a9480000f8163efffea1f9aefd81ce49a9480000f8163efffe9405988800e9ed60000000fd81ce49a9480000f8163efffea1f9ae0201fa163ea1f9ae
5912 as hv1 ovs-appctl netdev-dummy/receive vif1 $ns_packet
5913 echo $na_packet >> 1.expected
5915 echo "------ hv1 dump ------"
5916 as hv1 ovs-vsctl show
5917 as hv1 ovs-ofctl -O OpenFlow13 show br-int
5918 as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-int
5921 OVN_CHECK_PACKETS([hv1/vif$i-tx.pcap], [$i.expected])
5928 AT_SETUP([ovn -- address sets modification/removal smoke test])
5935 ovs-vsctl add-br br-phys
5936 ovn_attach n1 br-phys 192.168.0.1
5938 row=`ovn-nbctl create Address_Set name=set1 addresses=\"1.1.1.1\"`
5939 ovn-nbctl set Address_Set $row name=set1 addresses=\"1.1.1.1,1.1.1.2\"
5940 ovn-nbctl destroy Address_Set $row
5944 # A bug previously existed in the address set support code
5945 # that caused ovn-controller to crash after an address set
5946 # was updated and then removed. This test case ensures
5947 # that ovn-controller is at least still running after
5948 # creating, updating, and deleting an address set.
5949 AT_CHECK([ovs-appctl -t ovn-controller version], [0], [ignore])
5955 AT_SETUP([ovn -- ipam])
5956 AT_SKIP_IF([test $HAVE_PYTHON = no])
5959 # Add a port to a switch that does not have a subnet set, then set the
5960 # subnet which should result in an address being allocated for the port.
5961 ovn-nbctl --wait=hv set NB_Global . options:mac_prefix="0a:00:00:00:00:00"
5962 ovn-nbctl ls-add sw0
5963 ovn-nbctl lsp-add sw0 p0 -- lsp-set-addresses p0 dynamic
5964 ovn-nbctl --wait=sb add Logical-Switch sw0 other_config subnet=192.168.1.0/24
5965 AT_CHECK([ovn-nbctl get Logical-Switch-Port p0 dynamic_addresses], [0],
5966 ["0a:00:00:a8:01:03 192.168.1.2"
5969 # Add 9 more ports to sw0, addresses should all be unique.
5970 for n in `seq 1 9`; do
5971 ovn-nbctl --wait=sb lsp-add sw0 "p$n" -- lsp-set-addresses "p$n" dynamic
5973 AT_CHECK([ovn-nbctl get Logical-Switch-Port p1 dynamic_addresses], [0],
5974 ["0a:00:00:a8:01:04 192.168.1.3"
5976 AT_CHECK([ovn-nbctl get Logical-Switch-Port p2 dynamic_addresses], [0],
5977 ["0a:00:00:a8:01:05 192.168.1.4"
5979 AT_CHECK([ovn-nbctl get Logical-Switch-Port p3 dynamic_addresses], [0],
5980 ["0a:00:00:a8:01:06 192.168.1.5"
5982 AT_CHECK([ovn-nbctl get Logical-Switch-Port p4 dynamic_addresses], [0],
5983 ["0a:00:00:a8:01:07 192.168.1.6"
5985 AT_CHECK([ovn-nbctl get Logical-Switch-Port p5 dynamic_addresses], [0],
5986 ["0a:00:00:a8:01:08 192.168.1.7"
5988 AT_CHECK([ovn-nbctl get Logical-Switch-Port p6 dynamic_addresses], [0],
5989 ["0a:00:00:a8:01:09 192.168.1.8"
5991 AT_CHECK([ovn-nbctl get Logical-Switch-Port p7 dynamic_addresses], [0],
5992 ["0a:00:00:a8:01:0a 192.168.1.9"
5994 AT_CHECK([ovn-nbctl get Logical-Switch-Port p8 dynamic_addresses], [0],
5995 ["0a:00:00:a8:01:0b 192.168.1.10"
5997 AT_CHECK([ovn-nbctl get Logical-Switch-Port p9 dynamic_addresses], [0],
5998 ["0a:00:00:a8:01:0c 192.168.1.11"
6001 # Trying similar tests with a second switch. MAC addresses should be unique
6002 # across both switches but IP's only need to be unique within the same switch.
6003 ovn-nbctl ls-add sw1
6004 ovn-nbctl lsp-add sw1 p10 -- lsp-set-addresses p10 dynamic
6005 ovn-nbctl --wait=sb add Logical-Switch sw1 other_config subnet=192.168.1.0/24
6006 AT_CHECK([ovn-nbctl get Logical-Switch-Port p10 dynamic_addresses], [0],
6007 ["0a:00:00:a8:01:0d 192.168.1.2"
6010 for n in `seq 11 19`; do
6011 ovn-nbctl --wait=sb lsp-add sw1 "p$n" -- lsp-set-addresses "p$n" dynamic
6013 AT_CHECK([ovn-nbctl get Logical-Switch-Port p11 dynamic_addresses], [0],
6014 ["0a:00:00:a8:01:0e 192.168.1.3"
6016 AT_CHECK([ovn-nbctl get Logical-Switch-Port p12 dynamic_addresses], [0],
6017 ["0a:00:00:a8:01:0f 192.168.1.4"
6019 AT_CHECK([ovn-nbctl get Logical-Switch-Port p13 dynamic_addresses], [0],
6020 ["0a:00:00:a8:01:10 192.168.1.5"
6022 AT_CHECK([ovn-nbctl get Logical-Switch-Port p14 dynamic_addresses], [0],
6023 ["0a:00:00:a8:01:11 192.168.1.6"
6025 AT_CHECK([ovn-nbctl get Logical-Switch-Port p15 dynamic_addresses], [0],
6026 ["0a:00:00:a8:01:12 192.168.1.7"
6028 AT_CHECK([ovn-nbctl get Logical-Switch-Port p16 dynamic_addresses], [0],
6029 ["0a:00:00:a8:01:13 192.168.1.8"
6031 AT_CHECK([ovn-nbctl get Logical-Switch-Port p17 dynamic_addresses], [0],
6032 ["0a:00:00:a8:01:14 192.168.1.9"
6034 AT_CHECK([ovn-nbctl get Logical-Switch-Port p18 dynamic_addresses], [0],
6035 ["0a:00:00:a8:01:15 192.168.1.10"
6037 AT_CHECK([ovn-nbctl get Logical-Switch-Port p19 dynamic_addresses], [0],
6038 ["0a:00:00:a8:01:16 192.168.1.11"
6041 # Change a port's address to test for multiple ip's for a single address entry
6042 # and addresses set by the user.
6043 ovn-nbctl lsp-set-addresses p0 "0a:00:00:a8:01:17 192.168.1.2 192.168.1.12 192.168.1.14"
6044 ovn-nbctl --wait=sb lsp-add sw0 p20 -- lsp-set-addresses p20 dynamic
6045 AT_CHECK([ovn-nbctl get Logical-Switch-Port p20 dynamic_addresses], [0],
6046 ["0a:00:00:a8:01:18 192.168.1.13"
6049 # Test for logical router port address management.
6050 ovn-nbctl create Logical_Router name=R1
6051 ovn-nbctl -- --id=@lrp create Logical_Router_port name=sw0 \
6052 network="192.168.1.1/24" mac=\"0a:00:00:a8:01:19\" \
6053 -- add Logical_Router R1 ports @lrp -- lsp-add sw0 rp-sw0 \
6054 -- set Logical_Switch_Port rp-sw0 type=router options:router-port=sw0
6055 ovn-nbctl --wait=sb lsp-add sw0 p21 -- lsp-set-addresses p21 dynamic
6056 AT_CHECK([ovn-nbctl get Logical-Switch-Port p21 dynamic_addresses], [0],
6057 ["0a:00:00:a8:01:1a 192.168.1.15"
6060 # Test for address reuse after logical port is deleted.
6061 ovn-nbctl lsp-del p0
6062 ovn-nbctl --wait=sb lsp-add sw0 p23 -- lsp-set-addresses p23 dynamic
6063 AT_CHECK([ovn-nbctl get Logical-Switch-Port p23 dynamic_addresses], [0],
6064 ["0a:00:00:a8:01:03 192.168.1.2"
6067 # Test for multiple addresses to one logical port.
6068 ovn-nbctl lsp-add sw0 p25 -- lsp-set-addresses p25 \
6069 "0a:00:00:a8:01:1b 192.168.1.12" "0a:00:00:a8:01:1c 192.168.1.14"
6070 ovn-nbctl --wait=sb lsp-add sw0 p26 -- lsp-set-addresses p26 dynamic
6071 AT_CHECK([ovn-nbctl get Logical-Switch-Port p26 dynamic_addresses], [0],
6072 ["0a:00:00:a8:01:17 192.168.1.16"
6075 # Test for exhausting subnet address space.
6076 ovn-nbctl ls-add sw2 -- add Logical-Switch sw2 other_config subnet=172.16.1.0/30
6077 ovn-nbctl --wait=sb lsp-add sw2 p27 -- lsp-set-addresses p27 dynamic
6078 AT_CHECK([ovn-nbctl get Logical-Switch-Port p27 dynamic_addresses], [0],
6079 ["0a:00:00:10:01:03 172.16.1.2"
6082 ovn-nbctl --wait=sb lsp-add sw2 p28 -- lsp-set-addresses p28 dynamic
6083 AT_CHECK([ovn-nbctl get Logical-Switch-Port p28 dynamic_addresses], [0],
6084 ["0a:00:00:00:00:01"
6087 # Test that address management does not add duplicate MAC for lsp/lrp peers.
6088 ovn-nbctl create Logical_Router name=R2
6089 ovn-nbctl ls-add sw3
6090 ovn-nbctl lsp-add sw3 p29 -- lsp-set-addresses p29 \
6092 ovn-nbctl -- --id=@lrp create Logical_Router_port name=sw3 \
6093 network="192.168.2.1/24" mac=\"0a:00:00:a8:01:18\" \
6094 -- add Logical_Router R2 ports @lrp -- lsp-add sw3 rp-sw3 \
6095 -- set Logical_Switch_Port rp-sw3 type=router options:router-port=sw3
6096 ovn-nbctl --wait=sb lsp-add sw0 p30 -- lsp-set-addresses p30 dynamic
6097 AT_CHECK([ovn-nbctl get Logical-Switch-Port p30 dynamic_addresses], [0],
6098 ["0a:00:00:a8:01:1d 192.168.1.17"
6101 # Test static MAC address with dynamically allocated IP
6102 ovn-nbctl --wait=sb lsp-add sw0 p31 -- lsp-set-addresses p31 \
6103 "fe:dc:ba:98:76:54 dynamic"
6104 AT_CHECK([ovn-nbctl get Logical-Switch-Port p31 dynamic_addresses], [0],
6105 ["fe:dc:ba:98:76:54 192.168.1.18"
6108 # Update the static MAC address with dynamically allocated IP and check
6109 # if the MAC address is updated in 'Logical_Switch_Port.dynamic_adddresses'
6110 ovn-nbctl --wait=sb lsp-set-addresses p31 "fe:dc:ba:98:76:55 dynamic"
6112 AT_CHECK([ovn-nbctl get Logical-Switch-Port p31 dynamic_addresses], [0],
6113 ["fe:dc:ba:98:76:55 192.168.1.18"
6116 ovn-nbctl --wait=sb lsp-set-addresses p31 "dynamic"
6117 AT_CHECK([ovn-nbctl get Logical-Switch-Port p31 dynamic_addresses], [0],
6118 ["0a:00:00:a8:01:1e 192.168.1.18"
6121 ovn-nbctl --wait=sb lsp-set-addresses p31 "fe:dc:ba:98:76:56 dynamic"
6122 AT_CHECK([ovn-nbctl get Logical-Switch-Port p31 dynamic_addresses], [0],
6123 ["fe:dc:ba:98:76:56 192.168.1.18"
6127 # Test the exclude_ips from the IPAM list
6128 ovn-nbctl --wait=sb set logical_switch sw0 \
6129 other_config:exclude_ips="192.168.1.19 192.168.1.21 192.168.1.23..192.168.1.50"
6131 ovn-nbctl --wait=sb lsp-add sw0 p32 -- lsp-set-addresses p32 \
6133 # 192.168.1.20 should be assigned as 192.168.1.19 is excluded.
6134 AT_CHECK([ovn-nbctl get Logical-Switch-Port p32 dynamic_addresses], [0],
6135 ["0a:00:00:a8:01:1e 192.168.1.20"
6138 ovn-nbctl --wait=sb lsp-add sw0 p33 -- lsp-set-addresses p33 \
6140 # 192.168.1.22 should be assigned as 192.168.1.21 is excluded.
6141 AT_CHECK([ovn-nbctl get Logical-Switch-Port p33 dynamic_addresses], [0],
6142 ["0a:00:00:a8:01:1f 192.168.1.22"
6145 ovn-nbctl --wait=sb lsp-add sw0 p34 -- lsp-set-addresses p34 \
6147 # 192.168.1.51 should be assigned as 192.168.1.23-192.168.1.50 is excluded.
6148 AT_CHECK([ovn-nbctl get Logical-Switch-Port p34 dynamic_addresses], [0],
6149 ["0a:00:00:a8:01:34 192.168.1.51"
6152 # Now clear the exclude_ips list. 192.168.1.19 should be assigned.
6153 ovn-nbctl --wait=sb set Logical-switch sw0 other_config:exclude_ips="invalid"
6154 ovn-nbctl --wait=sb lsp-add sw0 p35 -- lsp-set-addresses p35 \
6156 AT_CHECK([ovn-nbctl get Logical-Switch-Port p35 dynamic_addresses], [0],
6157 ["0a:00:00:a8:01:20 192.168.1.19"
6160 # Set invalid data in exclude_ips list. It should be ignored.
6161 ovn-nbctl --wait=sb set Logical-switch sw0 other_config:exclude_ips="182.168.1.30"
6162 ovn-nbctl --wait=sb lsp-add sw0 p36 -- lsp-set-addresses p36 \
6164 # 192.168.1.21 should be assigned as that's the next free one.
6165 AT_CHECK([ovn-nbctl get Logical-Switch-Port p36 dynamic_addresses], [0],
6166 ["0a:00:00:a8:01:21 192.168.1.21"
6169 # Clear the dynamic addresses assignment request.
6170 ovn-nbctl --wait=sb clear logical_switch_port p36 addresses
6171 AT_CHECK([ovn-nbctl get Logical-Switch-Port p36 dynamic_addresses], [0],
6176 ovn-nbctl --wait=sb set Logical-switch sw0 other_config:ipv6_prefix="aef0::"
6177 ovn-nbctl --wait=sb lsp-add sw0 p37 -- lsp-set-addresses p37 \
6180 # With prefix aef0 and mac 0a:00:00:00:00:26, the dynamic IPv6 should be
6181 # - aef0::800:ff:fe00:26 (EUI64)
6182 AT_CHECK([ovn-nbctl get Logical-Switch-Port p37 dynamic_addresses], [0],
6183 ["0a:00:00:a8:01:21 192.168.1.21 aef0::800:ff:fea8:121"
6186 ovn-nbctl --wait=sb ls-add sw4
6187 ovn-nbctl --wait=sb set Logical-switch sw4 other_config:ipv6_prefix="bef0::" \
6188 -- set Logical-switch sw4 other_config:subnet=192.168.2.0/30
6189 ovn-nbctl --wait=sb lsp-add sw4 p38 -- lsp-set-addresses p38 \
6192 AT_CHECK([ovn-nbctl get Logical-Switch-Port p38 dynamic_addresses], [0],
6193 ["0a:00:00:a8:02:03 192.168.2.2 bef0::800:ff:fea8:203"
6196 ovn-nbctl --wait=sb lsp-add sw4 p39 -- lsp-set-addresses p39 \
6197 "f0:00:00:00:10:12 dynamic"
6199 AT_CHECK([ovn-nbctl get Logical-Switch-Port p39 dynamic_addresses], [0],
6200 ["f0:00:00:00:10:12 bef0::f200:ff:fe00:1012"
6203 # Test the case where IPv4 addresses are exhausted and IPv6 prefix is set
6204 # p40 should not have an IPv4 address since the pool is exhausted
6205 ovn-nbctl --wait=sb lsp-add sw4 p40 -- lsp-set-addresses p40 \
6207 AT_CHECK([ovn-nbctl get Logical-Switch-Port p40 dynamic_addresses], [0],
6208 ["0a:00:00:00:00:02 bef0::800:ff:fe00:2"
6211 # Test dynamic changes on switch ports.
6213 ovn-nbctl --wait=sb ls-add sw5
6214 ovn-nbctl --wait=sb lsp-add sw5 p41 -- lsp-set-addresses p41 \
6216 # p41 will start with nothing
6217 AT_CHECK([ovn-nbctl get Logical-Switch-Port p41 dynamic_addresses], [0],
6221 # Set a subnet. Now p41 should have an ipv4 address, too
6222 ovn-nbctl --wait=sb add Logical-Switch sw5 other_config subnet=192.168.1.0/24
6223 AT_CHECK([ovn-nbctl get Logical-Switch-Port p41 dynamic_addresses], [0],
6224 ["0a:00:00:a8:01:22 192.168.1.2"
6227 # Clear the other_config. The IPv4 address should be gone
6228 ovn-nbctl --wait=sb clear Logical-Switch sw5 other_config
6229 AT_CHECK([ovn-nbctl get Logical-Switch-Port p41 dynamic_addresses], [0],
6233 # Set an IPv6 prefix. Now p41 should have an IPv6 address.
6234 ovn-nbctl --wait=sb set Logical-Switch sw5 other_config:ipv6_prefix="aef0::"
6235 AT_CHECK([ovn-nbctl get Logical-Switch-Port p41 dynamic_addresses], [0],
6236 ["0a:00:00:00:00:03 aef0::800:ff:fe00:3"
6239 # Change the MAC address to a static one. The IPv6 address should update.
6240 ovn-nbctl --wait=sb lsp-set-addresses p41 "f0:00:00:00:10:2b dynamic"
6241 AT_CHECK([ovn-nbctl get Logical-Switch-Port p41 dynamic_addresses], [0],
6242 ["f0:00:00:00:10:2b aef0::f200:ff:fe00:102b"
6245 # Change the IPv6 prefix. The IPv6 address should update.
6246 ovn-nbctl --wait=sb set Logical-Switch sw5 other_config:ipv6_prefix="bef0::"
6247 AT_CHECK([ovn-nbctl get Logical-Switch-Port p41 dynamic_addresses], [0],
6248 ["f0:00:00:00:10:2b bef0::f200:ff:fe00:102b"
6251 # Clear the other_config. The IPv6 address should be gone
6252 ovn-nbctl --wait=sb clear Logical-Switch sw5 other_config
6253 AT_CHECK([ovn-nbctl get Logical-Switch-Port p41 dynamic_addresses], [0],
6257 # Set the subnet again. Now p41 should get the IPv4 address again.
6258 ovn-nbctl --wait=sb add Logical-Switch sw5 other_config subnet=192.168.1.0/24
6259 AT_CHECK([ovn-nbctl get Logical-Switch-Port p41 dynamic_addresses], [0],
6260 ["f0:00:00:00:10:2b 192.168.1.2"
6263 # Add an excluded IP address that conflicts with p41. p41 should update.
6264 ovn-nbctl --wait=sb add Logical-Switch sw5 other_config \
6265 exclude_ips="192.168.1.2"
6266 AT_CHECK([ovn-nbctl get Logical-Switch-Port p41 dynamic_addresses], [0],
6267 ["f0:00:00:00:10:2b 192.168.1.3"
6270 # Add static ip address
6271 ovn-nbctl --wait=sb lsp-set-addresses p41 "dynamic 192.168.1.100"
6272 ovn-nbctl list Logical-Switch-Port p41
6273 ovn-nbctl --wait=sb lsp-add sw5 p42 -- lsp-set-addresses p42 \
6274 "dynamic 192.168.1.101"
6275 AT_CHECK([ovn-nbctl get Logical-Switch-Port p41 dynamic_addresses], [0],
6276 ["0a:00:00:a8:01:65 192.168.1.100"
6278 AT_CHECK([ovn-nbctl get Logical-Switch-Port p42 dynamic_addresses], [0],
6279 ["0a:00:00:a8:01:66 192.168.1.101"
6282 # define a mac address prefix
6283 ovn-nbctl ls-add sw6
6284 ovn-nbctl --wait=hv set NB_Global . options:mac_prefix="00:11:22:33:44:55"
6285 ovn-nbctl --wait=sb set Logical-Switch sw6 other_config:subnet=192.168.100.0/24
6286 for n in $(seq 1 3); do
6287 ovn-nbctl --wait=sb lsp-add sw6 "p5$n" -- lsp-set-addresses "p5$n" dynamic
6289 AT_CHECK([ovn-nbctl get Logical-Switch-Port p51 dynamic_addresses], [0],
6290 ["00:11:22:a8:64:03 192.168.100.2"
6292 AT_CHECK([ovn-nbctl get Logical-Switch-Port p52 dynamic_addresses], [0],
6293 ["00:11:22:a8:64:04 192.168.100.3"
6295 AT_CHECK([ovn-nbctl get Logical-Switch-Port p53 dynamic_addresses], [0],
6296 ["00:11:22:a8:64:05 192.168.100.4"
6299 # verify configuration order does not break IPAM/MACAM
6300 ovn-nbctl ls-add sw7
6301 for n in $(seq 1 3); do
6302 ovn-nbctl --wait=sb lsp-add sw7 "p7$n" -- lsp-set-addresses "p7$n" dynamic
6304 ovn-nbctl --wait=sb set Logical-Switch sw7 other_config:ipv6_prefix="bef0::"
6305 p71_addr=$(ovn-nbctl get Logical-Switch-Port p71 dynamic_addresses)
6306 p72_addr=$(ovn-nbctl get Logical-Switch-Port p72 dynamic_addresses)
6307 p73_addr=$(ovn-nbctl get Logical-Switch-Port p73 dynamic_addresses)
6308 AT_CHECK([test "$p71_addr" != "$p72_addr"], [0], [])
6309 AT_CHECK([test "$p71_addr" != "$p73_addr"], [0], [])
6310 AT_CHECK([test "$p72_addr" != "$p73_addr"], [0], [])
6312 # request to assign mac only
6314 ovn-nbctl ls-add sw8
6315 ovn-nbctl --wait=sb set Logical-Switch sw8 other_config:mac_only=true
6316 for n in $(seq 1 3); do
6317 ovn-nbctl --wait=sb lsp-add sw8 "p8$n" -- lsp-set-addresses "p8$n" dynamic
6319 AT_CHECK([ovn-nbctl get Logical-Switch-Port p81 dynamic_addresses], [0],
6320 ["00:11:22:00:00:06"
6322 AT_CHECK([ovn-nbctl get Logical-Switch-Port p82 dynamic_addresses], [0],
6323 ["00:11:22:00:00:07"
6325 AT_CHECK([ovn-nbctl get Logical-Switch-Port p83 dynamic_addresses], [0],
6326 ["00:11:22:00:00:08"
6329 # clear mac_prefix and check it is allocated in a random manner
6330 ovn-nbctl --wait=hv remove NB_Global . options mac_prefix
6331 ovn-nbctl ls-add sw9
6332 ovn-nbctl --wait=sb set Logical-Switch sw9 other_config:mac_only=true
6333 ovn-nbctl --wait=sb lsp-add sw9 p91 -- lsp-set-addresses p91 dynamic
6335 mac_prefix=$(ovn-nbctl --wait=sb get NB_Global . options:mac_prefix | tr -d \")
6336 port_addr=$(ovn-nbctl get Logical-Switch-Port p91 dynamic_addresses | tr -d \")
6337 AT_CHECK([test "$port_addr" = "${mac_prefix}:00:00:09"], [0], [])
6339 ovn-nbctl --wait=hv set NB_Global . options:mac_prefix="00:11:22"
6340 ovn-nbctl ls-add sw10
6341 ovn-nbctl --wait=sb set Logical-Switch sw10 other_config:ipv6_prefix="ae01::"
6342 ovn-nbctl --wait=sb lsp-add sw10 p101 -- lsp-set-addresses p101 "dynamic ae01::1"
6343 AT_CHECK([ovn-nbctl get Logical-Switch-Port p101 dynamic_addresses], [0],
6344 ["00:11:22:00:00:0a ae01::1"
6347 ovn-nbctl --wait=sb set Logical-Switch sw10 other_config:subnet=192.168.110.0/24
6348 ovn-nbctl --wait=sb lsp-add sw10 p102 -- lsp-set-addresses p102 "dynamic 192.168.110.10 ae01::2"
6349 AT_CHECK([ovn-nbctl get Logical-Switch-Port p102 dynamic_addresses], [0],
6350 ["00:11:22:a8:6e:0b 192.168.110.10 ae01::2"
6354 OVS_APP_EXIT_AND_WAIT([ovsdb-server])
6357 OVS_APP_EXIT_AND_WAIT([ovsdb-server])
6360 OVS_APP_EXIT_AND_WAIT([ovn-northd])
6363 OVS_APP_EXIT_AND_WAIT([ovn-northd])
6367 AT_SETUP([ovn -- ipam connectivity])
6368 AT_SKIP_IF([test $HAVE_PYTHON = no])
6373 # Test for a ping using dynamically allocated addresses.
6374 ovn-nbctl --wait=hv set NB_Global . options:mac_prefix="0a:00:00:00:00:00"
6375 ovn-nbctl ls-add foo -- add Logical_Switch foo other_config subnet=192.168.1.0/24
6376 ovn-nbctl ls-add alice -- add Logical_Switch alice other_config subnet=192.168.2.0/24
6379 ovn-nbctl lrp-add R1 foo 00:00:00:01:02:03 192.168.1.1/24
6380 ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo type=router \
6381 options:router-port=foo \
6382 -- lsp-set-addresses rp-foo router
6384 # Connect alice to R1
6385 ovn-nbctl lrp-add R1 alice 00:00:00:01:02:04 192.168.2.1/24
6386 ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port rp-alice type=router \
6387 options:router-port=alice addresses=\"00:00:00:01:02:04\"
6389 # Create logical port foo1 in foo
6390 ovn-nbctl --wait=sb lsp-add foo foo1 \
6391 -- lsp-set-addresses foo1 "dynamic"
6392 AT_CHECK([ovn-nbctl --timeout=10 wait-until Logical-Switch-Port foo1 dynamic_addresses='"0a:00:00:a8:01:03 192.168.1.2"'], [0])
6394 # Create logical port alice1 in alice
6395 ovn-nbctl --wait=sb lsp-add alice alice1 \
6396 -- lsp-set-addresses alice1 "dynamic"
6397 AT_CHECK([ovn-nbctl --timeout=10 wait-until Logical-Switch-Port alice1 dynamic_addresses='"0a:00:00:a8:02:03 192.168.2.2"'])
6399 # Create logical port foo2 in foo
6400 ovn-nbctl --wait=sb lsp-add foo foo2 \
6401 -- lsp-set-addresses foo2 "dynamic"
6402 AT_CHECK([ovn-nbctl --timeout=10 wait-until Logical-Switch-Port foo2 dynamic_addresses='"0a:00:00:a8:01:04 192.168.1.3"'])
6404 # Create a hypervisor and create OVS ports corresponding to logical ports.
6409 ovs-vsctl add-br br-phys
6410 ovn_attach n1 br-phys 192.168.0.1
6411 ovs-vsctl -- add-port br-int hv1-vif1 -- \
6412 set interface hv1-vif1 external-ids:iface-id=foo1 \
6413 options:tx_pcap=hv1/vif1-tx.pcap \
6414 options:rxq_pcap=hv1/vif1-rx.pcap \
6417 ovs-vsctl -- add-port br-int hv1-vif2 -- \
6418 set interface hv1-vif2 external-ids:iface-id=foo2 \
6419 options:tx_pcap=hv1/vif2-tx.pcap \
6420 options:rxq_pcap=hv1/vif2-rx.pcap \
6423 ovs-vsctl -- add-port br-int hv1-vif3 -- \
6424 set interface hv1-vif3 external-ids:iface-id=alice1 \
6425 options:tx_pcap=hv1/vif3-tx.pcap \
6426 options:rxq_pcap=hv1/vif3-rx.pcap \
6429 # Allow some time for ovn-northd and ovn-controller to catch up.
6430 # XXX This should be more systematic.
6434 printf "%02x%02x%02x%02x" "$@"
6437 # Send ip packets between foo1 and foo2
6438 src_mac="0a0000a80103"
6439 dst_mac="0a0000a80104"
6440 src_ip=`ip_to_hex 192 168 1 2`
6441 dst_ip=`ip_to_hex 192 168 1 3`
6442 packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
6443 as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
6445 # Send ip packets between foo1 and alice1
6446 src_mac="0a0000a80103"
6447 dst_mac="000000010203"
6448 src_ip=`ip_to_hex 192 168 1 2`
6449 dst_ip=`ip_to_hex 192 168 2 2`
6450 packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
6451 as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
6453 echo "---------NB dump-----"
6455 echo "---------------------"
6456 ovn-nbctl list logical_router
6457 echo "---------------------"
6458 ovn-nbctl list logical_router_port
6459 echo "---------------------"
6461 echo "---------SB dump-----"
6462 ovn-sbctl list datapath_binding
6463 echo "---------------------"
6464 ovn-sbctl list port_binding
6465 echo "---------------------"
6467 echo "------ hv1 dump ----------"
6468 as hv1 ovs-ofctl dump-flows br-int
6470 # Packet to Expect at foo2
6471 src_mac="0a0000a80103"
6472 dst_mac="0a0000a80104"
6473 src_ip=`ip_to_hex 192 168 1 2`
6474 dst_ip=`ip_to_hex 192 168 1 3`
6475 expected=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
6477 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > received1.packets
6478 echo $expected > expout
6479 AT_CHECK([cat received1.packets], [0], [expout])
6481 # Packet to Expect at alice1
6482 src_mac="000000010204"
6483 dst_mac="0a0000a80203"
6484 src_ip=`ip_to_hex 192 168 1 2`
6485 dst_ip=`ip_to_hex 192 168 2 2`
6486 expected=${dst_mac}${src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000
6488 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif3-tx.pcap > received2.packets
6489 echo $expected > expout
6490 AT_CHECK([cat received2.packets], [0], [expout])
6496 AT_SETUP([ovn -- ovs-vswitchd restart])
6497 AT_KEYWORDS([vswitchd])
6498 AT_SKIP_IF([test $HAVE_PYTHON = no])
6501 ovn-nbctl ls-add ls1
6503 ovn-nbctl lsp-add ls1 ls1-lp1 \
6504 -- lsp-set-addresses ls1-lp1 "f0:00:00:00:00:01 10.0.0.4"
6506 ovn-nbctl lsp-set-port-security ls1-lp1 "f0:00:00:00:00:01 10.0.0.4"
6512 ovs-vsctl add-br br-phys
6513 ovn_attach n1 br-phys 192.168.0.1
6514 ovs-vsctl -- add-port br-int hv1-vif1 -- \
6515 set interface hv1-vif1 external-ids:iface-id=ls1-lp1 \
6516 options:tx_pcap=hv1/vif1-tx.pcap \
6517 options:rxq_pcap=hv1/vif1-rx.pcap \
6523 as hv1 ovs-vsctl show
6525 echo "---------------------"
6526 ovn-sbctl dump-flows
6527 echo "---------------------"
6529 echo "------ hv1 dump ----------"
6530 as hv1 ovs-ofctl dump-flows br-int
6531 total_flows=`as hv1 ovs-ofctl dump-flows br-int | wc -l`
6533 echo "Total flows before vswitchd restart = " $total_flows
6535 # Code taken from ovs-save utility
6537 echo "ovs-ofctl add-flows br-int - << EOF" > restore_flows.sh
6538 as hv1 ovs-ofctl dump-flows "br-int" | sed -e '/NXST_FLOW/d' \
6539 -e 's/\(idle\|hard\)_age=[^,]*,//g' >> restore_flows.sh
6540 echo "EOF" >> restore_flows.sh
6543 restart_vswitchd () {
6546 if test $restore_flows = true; then
6551 OVS_APP_EXIT_AND_WAIT([ovs-vswitchd])
6553 if test $restore_flows = true; then
6555 ovs-vsctl --no-wait set open_vswitch . other_config:flow-restore-wait="true"
6559 start_daemon ovs-vswitchd --enable-dummy=system -vvconn -vofproto_dpif -vunixctl
6560 ovs-ofctl dump-flows br-int
6562 if test $restore_flows = true; then
6563 sh ./restore_flows.sh
6564 echo "Flows after restore"
6566 ovs-ofctl dump-flows br-int
6567 ovs-vsctl --no-wait --if-exists remove open_vswitch . other_config \
6568 flow-restore-wait="true"
6572 # Save the flows, restart vswitchd and restore the flows
6573 restart_vswitchd true
6575 total_flows_after_restart=`as hv1 ovs-ofctl dump-flows br-int | wc -l`
6576 echo "Total flows after vswitchd restart = " $total_flows_after_restart
6577 test "${total_flows}" = "${total_flows_after_restart}"
6580 # Restart vswitchd without restoring
6581 restart_vswitchd false
6583 total_flows_after_restart=`as hv1 ovs-ofctl dump-flows br-int | wc -l`
6584 echo "Total flows after vswitchd restart = " $total_flows_after_restart
6585 test "${total_flows}" = "${total_flows_after_restart}"
6591 AT_SETUP([ovn -- send arp for nexthop])
6592 AT_SKIP_IF([test $HAVE_PYTHON = no])
6595 # Topology: Two LSs - ls1 and ls2 are connected via router r0
6597 # Create logical switches
6598 ovn-nbctl ls-add ls1
6599 ovn-nbctl ls-add ls2
6602 ovn-nbctl create Logical_Router name=lr0
6604 # Add router ls1p1 port to gateway router
6605 ovn-nbctl lrp-add lr0 lrp-ls1lp1 f0:00:00:00:00:01 192.168.0.1/24
6606 ovn-nbctl lsp-add ls1 ls1lp1 -- set Logical_Switch_Port ls1lp1 \
6607 type=router options:router-port=lrp-ls1lp1 \
6608 addresses='"f0:00:00:00:00:01 192.168.0.1"'
6610 # Add router ls2p2 port to gateway router
6611 ovn-nbctl lrp-add lr0 lrp-ls2lp1 f0:00:00:00:00:02 192.168.1.1/24
6612 ovn-nbctl lsp-add ls2 ls2lp1 -- set Logical_Switch_Port ls2lp1 \
6613 type=router options:router-port=lrp-ls2lp1 \
6614 addresses='"f0:00:00:00:00:02 192.168.1.1"'
6616 # Set default gateway (nexthop) to 192.168.1.254
6617 ovn-nbctl lr-route-add lr0 "0.0.0.0/0" 192.168.1.254 lrp-ls2lp1
6619 # Create logical port ls1lp2 in ls1
6620 ovn-nbctl lsp-add ls1 ls1lp2 \
6621 -- lsp-set-addresses ls1lp2 "f0:00:00:00:00:03 192.168.0.2"
6623 # Create logical port ls2lp2 in ls2
6624 ovn-nbctl lsp-add ls2 ls2lp2 \
6625 -- lsp-set-addresses ls2lp2 "f0:00:00:00:00:04 192.168.1.10"
6630 ovs-vsctl add-br br-phys
6631 ovn_attach n1 br-phys 192.168.0.1
6632 ovs-vsctl -- add-port br-int hv1-ls1lp2 -- \
6633 set interface hv1-ls1lp2 external-ids:iface-id=ls1lp2 \
6634 options:tx_pcap=hv1/ls1lp2-tx.pcap \
6635 options:rxq_pcap=hv1/ls1lp2-rx.pcap \
6637 ovs-vsctl -- add-port br-int hv1-ls2lp2 -- \
6638 set interface hv1-ls2lp2 external-ids:iface-id=ls2lp2 \
6639 options:tx_pcap=hv1/ls2lp2-tx.pcap \
6640 options:rxq_pcap=hv1/ls2lp2-rx.pcap \
6643 # Allow some time for ovn-northd and ovn-controller to catch up.
6644 # XXX This should be more systematic.
6647 echo "---------NB dump-----"
6649 echo "---------------------"
6650 ovn-nbctl list logical_router
6651 echo "---------------------"
6652 ovn-nbctl list logical_router_port
6653 echo "---------------------"
6655 echo "---------SB dump-----"
6656 ovn-sbctl list datapath_binding
6657 echo "---------------------"
6658 ovn-sbctl list port_binding
6659 echo "---------------------"
6660 ovn-sbctl dump-flows
6661 echo "---------------------"
6662 ovn-sbctl list chassis
6663 ovn-sbctl list encap
6664 echo "---------------------"
6666 echo "------Flows dump-----"
6668 ovs-ofctl dump-flows
6669 echo "---------------------"
6672 printf "%02x%02x%02x%02x" "$@"
6675 src_mac="f00000000003"
6676 dst_mac="f00000000001"
6677 src_ip=`ip_to_hex 192 168 0 2`
6678 dst_ip=`ip_to_hex 8 8 8 8`
6679 packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
6681 # Send IP packet destined to 8.8.8.8 from lsp1lp2
6682 as hv1 ovs-appctl netdev-dummy/receive hv1-ls1lp2 $packet
6685 sed 's/\(00\)\{1,\}$//'
6688 # ARP packet should be received with Target IP Address set to 192.168.1.254 and
6691 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/ls2lp2-tx.pcap | trim_zeros > packets
6692 expected="fffffffffffff0000000000208060001080006040001f00000000002c0a80101000000000000c0a801fe"
6693 echo $expected > expout
6694 AT_CHECK([cat packets], [0], [expout])
6701 AT_SETUP([ovn -- send gratuitous arp for nat ips in localnet])
6702 AT_SKIP_IF([test $HAVE_PYTHON = no])
6704 # Create logical switch
6705 ovn-nbctl ls-add ls0
6706 # Create gateway router
6707 ovn-nbctl create Logical_Router name=lr0 options:chassis=hv1
6708 # Add router port to gateway router
6709 ovn-nbctl lrp-add lr0 lrp0 f0:00:00:00:00:01 192.168.0.1/24
6710 ovn-nbctl lsp-add ls0 lrp0-rp -- set Logical_Switch_Port lrp0-rp \
6711 type=router options:router-port=lrp0 addresses='"f0:00:00:00:00:01"'
6712 # Add nat-address option
6713 ovn-nbctl lsp-set-options lrp0-rp router-port=lrp0 nat-addresses="f0:00:00:00:00:01 192.168.0.2"
6722 ovn_attach n1 br-phys 192.168.0.1
6724 AT_CHECK([ovs-vsctl set Open_vSwitch . external-ids:ovn-bridge-mappings=physnet1:br-eth0])
6725 AT_CHECK([ovs-vsctl add-port br-eth0 snoopvif -- set Interface snoopvif options:tx_pcap=hv1/snoopvif-tx.pcap options:rxq_pcap=hv1/snoopvif-rx.pcap])
6727 # Create a localnet port.
6728 AT_CHECK([ovn-nbctl lsp-add ls0 ln_port])
6729 AT_CHECK([ovn-nbctl lsp-set-addresses ln_port unknown])
6730 AT_CHECK([ovn-nbctl lsp-set-type ln_port localnet])
6731 AT_CHECK([ovn-nbctl lsp-set-options ln_port network_name=physnet1])
6734 # Wait for packet to be received.
6735 OVS_WAIT_UNTIL([test `wc -c < "hv1/snoopvif-tx.pcap"` -ge 50])
6737 sed 's/\(00\)\{1,\}$//'
6739 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/snoopvif-tx.pcap | trim_zeros > packets
6740 expected="fffffffffffff0000000000108060001080006040001f00000000001c0a80002000000000000c0a80002"
6741 echo $expected > expout
6742 AT_CHECK([sort packets], [0], [expout])
6749 AT_SETUP([ovn -- send gratuitous arp with nat-addresses router in localnet])
6750 AT_SKIP_IF([test $HAVE_PYTHON = no])
6752 # Create logical switch
6753 ovn-nbctl ls-add ls0
6754 # Create gateway router
6755 ovn-nbctl create Logical_Router name=lr0 options:chassis=hv1
6756 # Add router port to gateway router
6757 ovn-nbctl lrp-add lr0 lrp0 f0:00:00:00:00:01 192.168.0.1/24
6758 ovn-nbctl lsp-add ls0 lrp0-rp -- set Logical_Switch_Port lrp0-rp \
6759 type=router options:router-port=lrp0 addresses='"f0:00:00:00:00:01"'
6760 # Add nat-address option
6761 ovn-nbctl lsp-set-options lrp0-rp router-port=lrp0 nat-addresses="router"
6763 AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 192.168.0.1 10.0.0.0/24])
6764 AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 192.168.0.2 10.0.0.1])
6765 # Add load balancers
6766 AT_CHECK([ovn-nbctl lb-add lb0 192.168.0.3:80 10.0.0.2:80,10.0.0.3:80])
6767 AT_CHECK([ovn-nbctl lr-lb-add lr0 lb0])
6768 AT_CHECK([ovn-nbctl lb-add lb1 192.168.0.3:8080 10.0.0.2:8080,10.0.0.3:8080])
6769 AT_CHECK([ovn-nbctl lr-lb-add lr0 lb1])
6778 ovn_attach n1 br-phys 192.168.0.1
6780 AT_CHECK([ovs-vsctl set Open_vSwitch . external-ids:ovn-bridge-mappings=physnet1:br-eth0])
6781 AT_CHECK([ovs-vsctl add-port br-eth0 snoopvif -- set Interface snoopvif options:tx_pcap=hv1/snoopvif-tx.pcap options:rxq_pcap=hv1/snoopvif-rx.pcap])
6783 # Create a localnet port.
6784 AT_CHECK([ovn-nbctl lsp-add ls0 ln_port])
6785 AT_CHECK([ovn-nbctl lsp-set-addresses ln_port unknown])
6786 AT_CHECK([ovn-nbctl lsp-set-type ln_port localnet])
6787 AT_CHECK([ovn-nbctl lsp-set-options ln_port network_name=physnet1])
6790 # Wait for packet to be received.
6791 OVS_WAIT_UNTIL([test `wc -c < "hv1/snoopvif-tx.pcap"` -ge 50])
6793 sed 's/\(00\)\{1,\}$//'
6795 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/snoopvif-tx.pcap | trim_zeros > packets
6796 expected="fffffffffffff0000000000108060001080006040001f00000000001c0a80001000000000000c0a80001"
6797 echo $expected > expout
6798 expected="fffffffffffff0000000000108060001080006040001f00000000001c0a80002000000000000c0a80002"
6799 echo $expected >> expout
6800 expected="fffffffffffff0000000000108060001080006040001f00000000001c0a80003000000000000c0a80003"
6801 echo $expected >> expout
6802 AT_CHECK([sort packets], [0], [expout])
6809 AT_SETUP([ovn -- delete mac bindings])
6814 ovs-vsctl -- add-br br-phys
6815 ovn_attach n1 br-phys 192.168.0.1
6816 # Create logical switch ls0
6817 ovn-nbctl ls-add ls0
6818 # Create ports lp0, lp1 in ls0
6819 ovn-nbctl lsp-add ls0 lp0
6820 ovn-nbctl lsp-add ls0 lp1
6821 ovn-nbctl lsp-set-addresses lp0 "f0:00:00:00:00:01 192.168.0.1"
6822 ovn-nbctl lsp-set-addresses lp1 "f0:00:00:00:00:02 192.168.0.2"
6823 dp_uuid=`ovn-sbctl find datapath | grep uuid | cut -f2 -d ":" | cut -f2 -d " "`
6824 ovn-sbctl create MAC_Binding ip=10.0.0.1 datapath=$dp_uuid logical_port=lp0 mac="mac1"
6825 ovn-sbctl create MAC_Binding ip=10.0.0.1 datapath=$dp_uuid logical_port=lp1 mac="mac2"
6826 ovn-sbctl find MAC_Binding
6827 # Delete port lp0 and check that its MAC_Binding is deleted.
6828 ovn-nbctl lsp-del lp0
6829 ovn-sbctl find MAC_Binding
6830 OVS_WAIT_UNTIL([test `ovn-sbctl find MAC_Binding logical_port=lp0 | wc -l` = 0])
6831 # Delete logical switch ls0 and check that its MAC_Binding is deleted.
6832 ovn-nbctl ls-del ls0
6833 ovn-sbctl find MAC_Binding
6834 OVS_WAIT_UNTIL([test `ovn-sbctl find MAC_Binding | wc -l` = 0])
6840 AT_SETUP([ovn -- conntrack zone allocation])
6841 AT_SKIP_IF([test $HAVE_PYTHON = no])
6845 # 2 logical switches "foo" (192.168.1.0/24) and "bar" (172.16.1.0/24)
6846 # connected to a router R1.
6847 # foo has foo1 to act as a client.
6848 # bar has bar1, bar2, bar3 to act as servers.
6854 ovs-vsctl add-br br-phys
6855 ovn_attach n1 br-phys 192.168.0.1
6856 for i in foo1 bar1 bar2 bar3; do
6857 ovs-vsctl -- add-port br-int $i -- \
6858 set interface $i external-ids:iface-id=$i \
6859 options:tx_pcap=hv1/$i-tx.pcap \
6860 options:rxq_pcap=hv1/$i-rx.pcap
6863 ovn-nbctl create Logical_Router name=R1
6864 ovn-nbctl ls-add foo
6865 ovn-nbctl ls-add bar
6868 ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
6869 ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
6870 type=router options:router-port=foo addresses=\"00:00:01:01:02:03\"
6873 ovn-nbctl lrp-add R1 bar 00:00:01:01:02:04 172.16.1.1/24
6874 ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar \
6875 type=router options:router-port=bar addresses=\"00:00:01:01:02:04\"
6877 # Create logical port foo1 in foo
6878 ovn-nbctl lsp-add foo foo1 \
6879 -- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
6881 # Create logical port bar1, bar2 and bar3 in bar
6882 for i in `seq 1 3`; do
6884 ovn-nbctl lsp-add bar bar$i \
6885 -- lsp-set-addresses bar$i "f0:00:0a:01:02:$i 172.16.1.$ip"
6888 OVS_WAIT_UNTIL([test `ovs-ofctl dump-flows br-int table=0 | grep REG13 | wc -l` -eq 4])
6894 AT_SETUP([ovn -- tag allocation])
6897 AT_CHECK([ovn-nbctl ls-add ls0])
6898 AT_CHECK([ovn-nbctl lsp-add ls0 parent1])
6899 AT_CHECK([ovn-nbctl lsp-add ls0 parent2])
6900 AT_CHECK([ovn-nbctl ls-add ls1])
6902 dnl When a tag is provided, no allocation is done
6903 AT_CHECK([ovn-nbctl --wait=sb lsp-add ls1 c0 parent1 3])
6904 AT_CHECK([ovn-nbctl lsp-get-tag c0], [0], [3
6906 dnl The same 'tag' gets created in southbound database.
6907 AT_CHECK([ovn-sbctl --data=bare --no-heading --columns=tag find port_binding \
6908 logical_port="c0"], [0], [3
6911 dnl Allocate tags and see it getting created in both NB and SB
6912 AT_CHECK([ovn-nbctl --wait=sb lsp-add ls1 c1 parent1 0])
6913 AT_CHECK([ovn-nbctl lsp-get-tag c1], [0], [1
6915 AT_CHECK([ovn-sbctl --data=bare --no-heading --columns=tag find port_binding \
6916 logical_port="c1"], [0], [1
6919 AT_CHECK([ovn-nbctl --wait=sb lsp-add ls1 c2 parent1 0])
6920 AT_CHECK([ovn-nbctl lsp-get-tag c2], [0], [2
6922 AT_CHECK([ovn-sbctl --data=bare --no-heading --columns=tag find port_binding \
6923 logical_port="c2"], [0], [2
6925 AT_CHECK([ovn-nbctl --wait=sb lsp-add ls1 c3 parent1 0])
6926 AT_CHECK([ovn-nbctl lsp-get-tag c3], [0], [4
6928 AT_CHECK([ovn-sbctl --data=bare --no-heading --columns=tag find port_binding \
6929 logical_port="c3"], [0], [4
6932 dnl A different parent.
6933 AT_CHECK([ovn-nbctl --wait=sb lsp-add ls1 c4 parent2 0])
6934 AT_CHECK([ovn-nbctl lsp-get-tag c4], [0], [1
6936 AT_CHECK([ovn-sbctl --data=bare --no-heading --columns=tag find port_binding \
6937 logical_port="c4"], [0], [1
6940 AT_CHECK([ovn-nbctl --wait=sb lsp-add ls1 c5 parent2 0])
6941 AT_CHECK([ovn-nbctl lsp-get-tag c5], [0], [2
6943 AT_CHECK([ovn-sbctl --data=bare --no-heading --columns=tag find port_binding \
6944 logical_port="c5"], [0], [2
6947 dnl Delete a logical port and create a new one.
6948 AT_CHECK([ovn-nbctl --wait=sb lsp-del c1])
6949 AT_CHECK([ovn-nbctl --wait=sb lsp-add ls1 c6 parent1 0])
6950 AT_CHECK([ovn-nbctl lsp-get-tag c6], [0], [1
6952 AT_CHECK([ovn-sbctl --data=bare --no-heading --columns=tag find port_binding \
6953 logical_port="c6"], [0], [1
6956 dnl Restart northd to see that the same allocation remains.
6958 OVS_APP_EXIT_AND_WAIT([ovn-northd])
6959 start_daemon ovn-northd \
6960 --ovnnb-db=unix:"$ovs_base"/ovn-nb/ovn-nb.sock \
6961 --ovnsb-db=unix:"$ovs_base"/ovn-sb/ovn-sb.sock
6963 dnl Create a switch to make sure that ovn-northd has run through the main loop.
6964 AT_CHECK([ovn-nbctl --wait=sb ls-add ls-dummy])
6965 AT_CHECK([ovn-nbctl lsp-get-tag c0], [0], [3
6967 AT_CHECK([ovn-nbctl lsp-get-tag c6], [0], [1
6969 AT_CHECK([ovn-nbctl lsp-get-tag c2], [0], [2
6971 AT_CHECK([ovn-nbctl lsp-get-tag c3], [0], [4
6973 AT_CHECK([ovn-nbctl lsp-get-tag c4], [0], [1
6975 AT_CHECK([ovn-nbctl lsp-get-tag c5], [0], [2
6978 dnl Create a switch port with a tag that has already been allocated.
6979 dnl It should go through fine with a duplicate tag.
6980 AT_CHECK([ovn-nbctl --wait=sb lsp-add ls1 c7 parent2 2])
6981 AT_CHECK([ovn-nbctl lsp-get-tag c7], [0], [2
6983 AT_CHECK([ovn-sbctl --data=bare --no-heading --columns=tag find port_binding \
6984 logical_port="c7"], [0], [2
6986 AT_CHECK([ovn-nbctl lsp-get-tag c5], [0], [2
6989 AT_CHECK([ovn-nbctl ls-add ls2])
6990 dnl When there is no parent_name provided (for say, 'localnet'), 'tag_request'
6991 dnl gets copied to 'tag'
6992 AT_CHECK([ovn-nbctl --wait=sb lsp-add ls2 local0 "" 25])
6993 AT_CHECK([ovn-nbctl lsp-get-tag local0], [0], [25
6995 dnl The same 'tag' gets created in southbound database.
6996 AT_CHECK([ovn-sbctl --data=bare --no-heading --columns=tag find port_binding \
6997 logical_port="local0"], [0], [25
6999 dnl If 'tag_request' is 0 for localnet, nothing gets written to 'tag'
7000 AT_CHECK([ovn-nbctl --wait=sb lsp-add ls2 local1 "" 0])
7001 AT_CHECK([ovn-nbctl lsp-get-tag local1])
7002 dnl change the tag_request.
7003 AT_CHECK([ovn-nbctl --wait=sb set logical_switch_port local1 tag_request=50])
7004 AT_CHECK([ovn-nbctl lsp-get-tag local1], [0], [50
7009 AT_SETUP([ovn -- lsp deletion and broadcast-flow deletion on localnet])
7011 ovn-nbctl ls-add lsw0
7016 ovs-vsctl add-br br-phys
7017 ovn_attach n1 br-phys 192.168.0.$i
7018 ovs-vsctl add-br br-eth0
7019 AT_CHECK([ovs-vsctl set Open_vSwitch . external-ids:ovn-bridge-mappings=physnet1:br-eth0])
7022 # Create a localnet port.
7023 AT_CHECK([ovn-nbctl lsp-add lsw0 ln_port])
7024 AT_CHECK([ovn-nbctl lsp-set-addresses ln_port unknown])
7025 AT_CHECK([ovn-nbctl lsp-set-type ln_port localnet])
7026 AT_CHECK([ovn-nbctl lsp-set-options ln_port network_name=physnet1])
7030 AT_CHECK([ovn-nbctl lsp-add lsw0 localvif1])
7031 AT_CHECK([ovn-nbctl lsp-set-addresses localvif1 "f0:00:00:00:00:01 192.168.1.1"])
7032 AT_CHECK([ovn-nbctl lsp-set-port-security localvif1 "f0:00:00:00:00:01"])
7033 AT_CHECK([ovn-nbctl lsp-add lsw0 localvif2])
7034 AT_CHECK([ovn-nbctl lsp-set-addresses localvif2 "f0:00:00:00:00:02 192.168.1.2"])
7035 AT_CHECK([ovn-nbctl lsp-set-port-security localvif2 "f0:00:00:00:00:02"])
7036 AT_CHECK([ovn-nbctl lsp-add lsw0 localvif3])
7037 AT_CHECK([ovn-nbctl lsp-set-addresses localvif3 "f0:00:00:00:00:03 192.168.1.3"])
7038 AT_CHECK([ovn-nbctl lsp-set-port-security localvif3 "f0:00:00:00:00:03"])
7040 # Bind the localvif1 to hv1.
7042 AT_CHECK([ovs-vsctl add-port br-int localvif1 -- set Interface localvif1 external_ids:iface-id=localvif1])
7044 # On hv1, check that there are no flows outputting bcast to tunnel
7045 OVS_WAIT_UNTIL([test `ovs-ofctl dump-flows br-int table=32 | ofctl_strip | grep output | wc -l` -eq 0])
7047 # On hv2, check that no flow outputs bcast to tunnel to hv1.
7049 OVS_WAIT_UNTIL([test `ovs-ofctl dump-flows br-int table=32 | ofctl_strip | grep output | wc -l` -eq 0])
7051 # Now bind vif2 on hv2.
7052 AT_CHECK([ovs-vsctl add-port br-int localvif2 -- set Interface localvif2 external_ids:iface-id=localvif2])
7054 # At this point, the broadcast flow on vif2 should be deleted.
7055 # because, there is now a localnet vif bound (table=32 programming logic)
7056 OVS_WAIT_UNTIL([test `ovs-ofctl dump-flows br-int table=32 | ofctl_strip | grep output | wc -l` -eq 0])
7058 # Verify that the local net patch port exists on hv2.
7059 OVS_WAIT_UNTIL([test `ovs-vsctl show | grep "Port patch-br-int-to-ln_port" | wc -l` -eq 1])
7061 # Now bind vif3 on hv2.
7062 AT_CHECK([ovs-vsctl add-port br-int localvif3 -- set Interface localvif3 external_ids:iface-id=localvif3])
7064 # Verify that the local net patch port still exists on hv2
7065 OVS_WAIT_UNTIL([test `ovs-vsctl show | grep "Port patch-br-int-to-ln_port" | wc -l` -eq 1])
7068 AT_CHECK([ovn-nbctl lsp-del localvif2])
7070 # Verify that the local net patch port still exists on hv2,
7071 # because, localvif3 is still bound.
7072 OVS_WAIT_UNTIL([test `ovs-vsctl show | grep "Port patch-br-int-to-ln_port" | wc -l` -eq 1])
7074 OVN_CLEANUP([hv1],[hv2])
7079 AT_SETUP([ovn -- ACL logging])
7087 ovs-vsctl add-br br-phys
7088 ovn_attach n1 br-phys 192.168.0.1
7089 for i in lp1 lp2; do
7090 ovs-vsctl -- add-port br-int $i -- \
7091 set interface $i external-ids:iface-id=$i \
7092 options:tx_pcap=hv/$i-tx.pcap \
7093 options:rxq_pcap=hv/$i-rx.pcap
7096 lp1_mac="f0:00:00:00:00:01"
7097 lp1_ip="192.168.1.2"
7099 lp2_mac="f0:00:00:00:00:02"
7100 lp2_ip="192.168.1.3"
7102 ovn-nbctl ls-add lsw0
7103 ovn-nbctl --wait=sb lsp-add lsw0 lp1
7104 ovn-nbctl --wait=sb lsp-add lsw0 lp2
7105 ovn-nbctl lsp-set-addresses lp1 $lp1_mac
7106 ovn-nbctl lsp-set-addresses lp2 $lp2_mac
7107 ovn-nbctl --wait=sb sync
7109 ovn-nbctl acl-add lsw0 to-lport 1000 'tcp.dst==80' drop
7110 ovn-nbctl --log --severity=alert --name=drop-flow acl-add lsw0 to-lport 1000 'tcp.dst==81' drop
7112 ovn-nbctl acl-add lsw0 to-lport 1000 'tcp.dst==82' allow
7113 ovn-nbctl --log --severity=info --name=allow-flow acl-add lsw0 to-lport 1000 'tcp.dst==83' allow
7115 ovn-nbctl acl-add lsw0 to-lport 1000 'tcp.dst==84' allow-related
7116 ovn-nbctl --log acl-add lsw0 to-lport 1000 'tcp.dst==85' allow-related
7118 ovn-nbctl acl-add lsw0 to-lport 1000 'tcp.dst==86' reject
7119 ovn-nbctl --wait=hv --log --severity=alert --name=reject-flow acl-add lsw0 to-lport 1000 'tcp.dst==87' reject
7121 ovn-sbctl dump-flows
7124 # Send packet that should be dropped without logging.
7125 packet="inport==\"lp1\" && eth.src==$lp1_mac && eth.dst==$lp2_mac &&
7126 ip4 && ip.ttl==64 && ip4.src==$lp1_ip && ip4.dst==$lp2_ip &&
7127 tcp && tcp.flags==2 && tcp.src==4360 && tcp.dst==80"
7128 as hv ovs-appctl -t ovn-controller inject-pkt "$packet"
7130 # Send packet that should be dropped with logging.
7131 packet="inport==\"lp1\" && eth.src==$lp1_mac && eth.dst==$lp2_mac &&
7132 ip4 && ip.ttl==64 && ip4.src==$lp1_ip && ip4.dst==$lp2_ip &&
7133 tcp && tcp.flags==2 && tcp.src==4361 && tcp.dst==81"
7134 as hv ovs-appctl -t ovn-controller inject-pkt "$packet"
7136 # Send packet that should be allowed without logging.
7137 packet="inport==\"lp1\" && eth.src==$lp1_mac && eth.dst==$lp2_mac &&
7138 ip4 && ip.ttl==64 && ip4.src==$lp1_ip && ip4.dst==$lp2_ip &&
7139 tcp && tcp.flags==2 && tcp.src==4362 && tcp.dst==82"
7140 as hv ovs-appctl -t ovn-controller inject-pkt "$packet"
7142 # Send packet that should be allowed with logging.
7143 packet="inport==\"lp1\" && eth.src==$lp1_mac && eth.dst==$lp2_mac &&
7144 ip4 && ip.ttl==64 && ip4.src==$lp1_ip && ip4.dst==$lp2_ip &&
7145 tcp && tcp.flags==2 && tcp.src==4363 && tcp.dst==83"
7146 as hv ovs-appctl -t ovn-controller inject-pkt "$packet"
7148 # Send packet that should allow related flows without logging.
7149 packet="inport==\"lp1\" && eth.src==$lp1_mac && eth.dst==$lp2_mac &&
7150 ip4 && ip.ttl==64 && ip4.src==$lp1_ip && ip4.dst==$lp2_ip &&
7151 tcp && tcp.flags==2 && tcp.src==4364 && tcp.dst==84"
7152 as hv ovs-appctl -t ovn-controller inject-pkt "$packet"
7154 # Send packet that should allow related flows with logging.
7155 packet="inport==\"lp1\" && eth.src==$lp1_mac && eth.dst==$lp2_mac &&
7156 ip4 && ip.ttl==64 && ip4.src==$lp1_ip && ip4.dst==$lp2_ip &&
7157 tcp && tcp.flags==2 && tcp.src==4365 && tcp.dst==85"
7158 as hv ovs-appctl -t ovn-controller inject-pkt "$packet"
7160 # Send packet that should be rejected without logging.
7161 packet="inport==\"lp1\" && eth.src==$lp1_mac && eth.dst==$lp2_mac &&
7162 ip4 && ip.ttl==64 && ip4.src==$lp1_ip && ip4.dst==$lp2_ip &&
7163 tcp && tcp.flags==2 && tcp.src==4366 && tcp.dst==86"
7164 as hv ovs-appctl -t ovn-controller inject-pkt "$packet"
7166 # Send packet that should be rejected with logging.
7167 packet="inport==\"lp1\" && eth.src==$lp1_mac && eth.dst==$lp2_mac &&
7168 ip4 && ip.ttl==64 && ip4.src==$lp1_ip && ip4.dst==$lp2_ip &&
7169 tcp && tcp.flags==2 && tcp.src==4367 && tcp.dst==87"
7170 as hv ovs-appctl -t ovn-controller inject-pkt "$packet"
7172 OVS_WAIT_UNTIL([ test 4 = $(grep -c 'acl_log' hv/ovn-controller.log) ])
7174 AT_CHECK([grep 'acl_log' hv/ovn-controller.log | sed 's/.*name=/name=/'], [0], [dnl
7175 name="drop-flow", verdict=drop, severity=alert: tcp,vlan_tci=0x0000,dl_src=f0:00:00:00:00:01,dl_dst=f0:00:00:00:00:02,nw_src=192.168.1.2,nw_dst=192.168.1.3,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=4361,tp_dst=81,tcp_flags=syn
7176 name="allow-flow", verdict=allow, severity=info: tcp,vlan_tci=0x0000,dl_src=f0:00:00:00:00:01,dl_dst=f0:00:00:00:00:02,nw_src=192.168.1.2,nw_dst=192.168.1.3,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=4363,tp_dst=83,tcp_flags=syn
7177 name="<unnamed>", verdict=allow, severity=info: tcp,vlan_tci=0x0000,dl_src=f0:00:00:00:00:01,dl_dst=f0:00:00:00:00:02,nw_src=192.168.1.2,nw_dst=192.168.1.3,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=4365,tp_dst=85,tcp_flags=syn
7178 name="reject-flow", verdict=reject, severity=alert: tcp,vlan_tci=0x0000,dl_src=f0:00:00:00:00:01,dl_dst=f0:00:00:00:00:02,nw_src=192.168.1.2,nw_dst=192.168.1.3,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=4367,tp_dst=87,tcp_flags=syn
7185 AT_SETUP([ovn -- ACL rate-limited logging])
7193 ovs-vsctl add-br br-phys
7194 ovn_attach n1 br-phys 192.168.0.1
7195 for i in lp1 lp2; do
7196 ovs-vsctl -- add-port br-int $i -- \
7197 set interface $i external-ids:iface-id=$i \
7198 options:tx_pcap=hv/$i-tx.pcap \
7199 options:rxq_pcap=hv/$i-rx.pcap
7202 lp1_mac="f0:00:00:00:00:01"
7203 lp1_ip="192.168.1.2"
7205 lp2_mac="f0:00:00:00:00:02"
7206 lp2_ip="192.168.1.3"
7208 ovn-nbctl ls-add lsw0
7209 ovn-nbctl --wait=sb lsp-add lsw0 lp1
7210 ovn-nbctl --wait=sb lsp-add lsw0 lp2
7211 ovn-nbctl lsp-set-addresses lp1 $lp1_mac
7212 ovn-nbctl lsp-set-addresses lp2 $lp2_mac
7213 ovn-nbctl --wait=sb sync
7216 # Add an ACL that rate-limits logs at 10 per second.
7217 ovn-nbctl meter-add http-rl1 drop 10 pktps
7218 ovn-nbctl --log --severity=alert --meter=http-rl1 --name=http-acl1 acl-add lsw0 to-lport 1000 'tcp.dst==80' drop
7220 # Add an ACL that rate-limits logs at 5 per second.
7221 ovn-nbctl meter-add http-rl2 drop 5 pktps
7222 ovn-nbctl --log --severity=alert --meter=http-rl2 --name=http-acl2 acl-add lsw0 to-lport 1000 'tcp.dst==81' allow
7224 # Add an ACL that doesn't rate-limit logs.
7225 ovn-nbctl --log --severity=alert --name=http-acl3 acl-add lsw0 to-lport 1000 'tcp.dst==82' drop
7226 ovn-nbctl --wait=hv sync
7228 # For each ACL, send 100 packets.
7229 for i in `seq 1 100`; do
7230 ovs-appctl netdev-dummy/receive lp1 'in_port(1),eth(src=f0:00:00:00:00:01,dst=f0:00:00:00:00:02),eth_type(0x0800),ipv4(src=192.168.1.2,dst=192.168.1.3,proto=6,tos=0,ttl=64,frag=no),tcp(src=7777,dst=80)'
7232 ovs-appctl netdev-dummy/receive lp1 'in_port(1),eth(src=f0:00:00:00:00:01,dst=f0:00:00:00:00:02),eth_type(0x0800),ipv4(src=192.168.1.2,dst=192.168.1.3,proto=6,tos=0,ttl=64,frag=no),tcp(src=7777,dst=81)'
7234 ovs-appctl netdev-dummy/receive lp1 'in_port(1),eth(src=f0:00:00:00:00:01,dst=f0:00:00:00:00:02),eth_type(0x0800),ipv4(src=192.168.1.2,dst=192.168.1.3,proto=6,tos=0,ttl=64,frag=no),tcp(src=7777,dst=82)'
7237 # The rate at which packets are sent is highly system-dependent, so we
7238 # can't count on precise drop counts. To work around that, we just
7239 # check that exactly 100 "http-acl3" actions were logged and that there
7240 # were more "http-acl1" actions than "http-acl2" ones.
7241 OVS_WAIT_UNTIL([ test 100 = $(grep -c 'http-acl3' hv/ovn-controller.log) ])
7243 # On particularly slow or overloaded systems, the transmission rate may
7244 # be lower than the configured meter rate. To prevent false test
7245 # failures, we check the duration count of the meter, and if it's
7246 # greater than nine seconds, just skip the test.
7247 d_secs=$(as hv ovs-ofctl -O OpenFlow13 meter-stats br-int | grep "meter:1" | sed 's/.* duration:\([[0-9]]\{1,\}\)\.[[0-9]]\+s .*/\1/')
7249 echo "Meter duration: $d_secs"
7250 AT_SKIP_IF([test $d_secs -gt 9])
7252 # Print some information that may help debugging.
7253 as hv ovs-appctl -t ovn-controller meter-table-list
7254 as hv ovs-ofctl -O OpenFlow13 meter-stats br-int
7256 n_acl1=$(grep -c 'http-acl1' hv/ovn-controller.log)
7257 n_acl2=$(grep -c 'http-acl2' hv/ovn-controller.log)
7258 n_acl3=$(grep -c 'http-acl3' hv/ovn-controller.log)
7260 AT_CHECK([ test $n_acl3 -gt $n_acl1 ], [0], [])
7261 AT_CHECK([ test $n_acl1 -gt $n_acl2 ], [0], [])
7267 AT_SETUP([ovn -- DSCP marking and meter check])
7271 ovn-nbctl ls-add lsw0
7272 ovn-nbctl --wait=sb lsp-add lsw0 lp1
7273 ovn-nbctl --wait=sb lsp-add lsw0 lp2
7274 ovn-nbctl --wait=sb lsp-add lsw0 lp3
7275 ovn-nbctl lsp-set-addresses lp1 f0:00:00:00:00:01
7276 ovn-nbctl lsp-set-addresses lp2 f0:00:00:00:00:02
7277 ovn-nbctl lsp-set-addresses lp3 f0:00:00:00:00:03
7278 ovn-nbctl lsp-set-port-security lp1 f0:00:00:00:00:01
7279 ovn-nbctl lsp-set-port-security lp2 f0:00:00:00:00:02
7280 ovn-nbctl --wait=sb sync
7284 ovs-vsctl add-br br-phys
7285 ovn_attach n1 br-phys 192.168.0.1
7286 ovs-vsctl add-port br-int vif1 -- set Interface vif1 external-ids:iface-id=lp1 options:tx_pcap=vif1-tx.pcap options:rxq_pcap=vif1-rx.pcap ofport-request=1
7287 ovs-vsctl add-port br-int vif2 -- set Interface vif2 external-ids:iface-id=lp2 options:tx_pcap=vif2-tx.pcap options:rxq_pcap=vif2-rx.pcap ofport-request=2
7289 AT_CAPTURE_FILE([trace])
7291 ovn-trace --all "$@" | tee trace | sed '1,/Minimal trace/d'
7294 # Extracts nw_tos from the final flow from ofproto/trace output and prints
7295 # it on stdout. Prints "none" if no nw_tos was included.
7296 get_final_nw_tos() {
7297 if flow=$(grep '^Final flow:' stdout); then :; else
7298 # The output didn't have a final flow.
7302 tos=$(echo "$flow" | sed -n 's/.*nw_tos=\([[0-9]]\{1,\}\).*/\1/p')
7311 # Checks that a packet from 1.1.1.1 to 1.1.1.2 gets its DSCP set to TOS.
7313 # First check with ovn-trace for logical flows.
7314 echo "checking for tos $1"
7315 (if test $1 != 0; then echo "ip.dscp = $1;"; fi;
7316 echo 'output("lp2");') > expout
7317 AT_CHECK_UNQUOTED([ovn_trace lsw0 'inport == "lp1" && eth.src == f0:00:00:00:00:01 && eth.dst == f0:00:00:00:00:02 && ip4.src == 1.1.1.1 && ip4.dst == 1.1.1.2'], [0], [expout])
7319 # Then re-check with ofproto/trace for a physical packet.
7320 AT_CHECK([ovs-appctl ofproto/trace br-int 'in_port=1,dl_src=f0:00:00:00:00:01,dl_dst=f0:00:00:00:00:02,dl_type=0x800,nw_src=1.1.1.1,nw_dst=1.1.1.2'], [0], [stdout-nolog])
7321 AT_CHECK_UNQUOTED([get_final_nw_tos], [0], [`expr $1 \* 4`
7326 AT_CHECK([ovn_trace lsw0 'inport == "lp1" && eth.src == f0:00:00:00:00:01 && eth.dst == f0:00:00:00:00:02'], [0], [output("lp2");
7328 AT_CHECK([ovs-appctl ofproto/trace br-int 'in_port=1,dl_src=f0:00:00:00:00:01,dl_dst=f0:00:00:00:00:02'], [0], [stdout-nolog])
7329 AT_CHECK([get_final_nw_tos], [0], [none
7332 # check at L3 without dscp marking
7335 # Mark DSCP with a valid value
7336 qos_id=$(ovn-nbctl --wait=hv -- --id=@lp1-qos create QoS priority=100 action=dscp=48 match="inport\=\=\"lp1\"\ &&\ is_chassis_resident(\"lp1\")" direction="from-lport" -- set Logical_Switch lsw0 qos_rules=@lp1-qos)
7337 AT_CHECK([as hv ovn-nbctl qos-list lsw0 | wc -l], [0], [1
7341 # check at hv without qos meter
7342 AT_CHECK([as hv ovs-ofctl dump-flows br-int -O OpenFlow13 | grep meter | wc -l], [0], [0
7345 # Update the meter rate
7346 ovn-nbctl --wait=hv set QoS $qos_id bandwidth=rate=100
7348 # check at hv with a qos meter table
7349 AT_CHECK([as hv ovs-ofctl dump-meters br-int -O OpenFlow13 | grep rate=100 | wc -l], [0], [1
7351 AT_CHECK([as hv ovs-ofctl dump-flows br-int -O OpenFlow13 | grep meter | wc -l], [0], [1
7354 # Update the DSCP marking
7355 ovn-nbctl --wait=hv set QoS $qos_id action=dscp=63
7358 # Update the meter rate
7359 ovn-nbctl --wait=hv set QoS $qos_id bandwidth=rate=4294967295,burst=4294967295
7361 # check at hv with a qos meter table
7362 AT_CHECK([as hv ovs-ofctl dump-meters br-int -O OpenFlow13 | grep burst_size=4294967295 | wc -l], [0], [1
7364 AT_CHECK([as hv ovs-ofctl dump-flows br-int -O OpenFlow13 | grep meter | wc -l], [0], [1
7367 ovn-nbctl --wait=hv set QoS $qos_id match="outport\=\=\"lp2\"" direction="to-lport"
7370 # Disable DSCP marking
7371 ovn-nbctl --wait=hv qos-del lsw0
7372 AT_CHECK([as hv ovn-nbctl qos-list lsw0 | wc -l], [0], [0
7376 # check at hv without qos meter
7377 AT_CHECK([as hv ovs-ofctl dump-flows br-int -O OpenFlow13 | grep meter | wc -l], [0], [0
7380 # check meter with chassis not resident
7381 ovn-nbctl qos-add lsw0 to-lport 1001 'inport=="lp3" && is_chassis_resident("lp3")' rate=11123 burst=111230
7382 AT_CHECK([as hv ovn-nbctl qos-list lsw0 | wc -l], [0], [1
7385 # check no meter table
7386 AT_CHECK([as hv ovs-ofctl dump-flows br-int -O OpenFlow13 | grep meter | wc -l], [0], [0
7388 AT_CHECK([as hv ovs-ofctl dump-meters br-int -O OpenFlow13 | grep rate=11123 | wc -l], [0], [0
7394 AT_SETUP([ovn -- read-only sb db:ptcp access])
7395 AT_SKIP_IF([test $HAVE_PYTHON = no])
7398 ovsdb-tool create ovn-sb.db "$abs_top_srcdir"/ovn/ovn-sb.ovsschema
7400 # Add read-only remote to sb ovsdb-server
7402 [ovsdb-tool transact ovn-sb.db \
7403 ['["OVN_Southbound",
7405 "table": "SB_Global",
7407 "connections": ["set", [["named-uuid", "xyz"]]]}},
7409 "table": "Connection",
7411 "row": {"target": "ptcp:0:127.0.0.1",
7412 "read_only": true}}]']], [0], [ignore], [ignore])
7414 start_daemon ovsdb-server --remote=punix:ovn-sb.sock --remote=db:OVN_Southbound,SB_Global,connections ovn-sb.db
7416 PARSE_LISTENING_PORT([ovsdb-server.log], [TCP_PORT])
7418 # read-only accesses should succeed
7419 AT_CHECK([ovn-sbctl --db=tcp:127.0.0.1:$TCP_PORT list SB_Global], [0], [stdout], [ignore])
7420 AT_CHECK([ovn-sbctl --db=tcp:127.0.0.1:$TCP_PORT list Connection], [0], [stdout], [ignore])
7422 # write access should fail
7423 AT_CHECK([ovn-sbctl --db=tcp:127.0.0.1:$TCP_PORT chassis-add ch vxlan 1.2.4.8], [1], [ignore],
7424 [ovn-sbctl: transaction error: {"details":"insert operation not allowed when database server is in read only mode","error":"not allowed"}
7427 OVS_APP_EXIT_AND_WAIT([ovsdb-server])
7430 AT_SETUP([ovn -- read-only sb db:pssl access])
7431 AT_SKIP_IF([test $HAVE_PYTHON = no])
7432 AT_SKIP_IF([test "$HAVE_OPENSSL" = no])
7433 PKIDIR="$(cd $abs_top_builddir/tests && pwd)"
7434 AT_SKIP_IF([expr "$PKIDIR" : ".*[ '\"
7438 ovsdb-tool create ovn-sb.db "$abs_top_srcdir"/ovn/ovn-sb.ovsschema
7440 # Add read-only remote to sb ovsdb-server
7442 [ovsdb-tool transact ovn-sb.db \
7443 ['["OVN_Southbound",
7445 "table": "SB_Global",
7447 "connections": ["set", [["named-uuid", "xyz"]]]}},
7449 "table": "Connection",
7451 "row": {"target": "pssl:0:127.0.0.1",
7452 "read_only": true}}]']], [0], [ignore], [ignore])
7454 start_daemon ovsdb-server --remote=punix:ovn-sb.sock \
7455 --remote=db:OVN_Southbound,SB_Global,connections \
7456 --private-key="$PKIDIR/testpki-privkey2.pem" \
7457 --certificate="$PKIDIR/testpki-cert2.pem" \
7458 --ca-cert="$PKIDIR/testpki-cacert.pem" \
7461 PARSE_LISTENING_PORT([ovsdb-server.log], [TCP_PORT])
7463 # read-only accesses should succeed
7464 AT_CHECK([ovn-sbctl --db=ssl:127.0.0.1:$TCP_PORT \
7465 --private-key=$PKIDIR/testpki-privkey.pem \
7466 --certificate=$PKIDIR/testpki-cert.pem \
7467 --ca-cert=$PKIDIR/testpki-cacert.pem \
7468 list SB_Global], [0], [stdout], [ignore])
7469 AT_CHECK([ovn-sbctl --db=ssl:127.0.0.1:$TCP_PORT \
7470 --private-key=$PKIDIR/testpki-privkey.pem \
7471 --certificate=$PKIDIR/testpki-cert.pem \
7472 --ca-cert=$PKIDIR/testpki-cacert.pem \
7473 list Connection], [0], [stdout], [ignore])
7475 # write access should fail
7476 AT_CHECK([ovn-sbctl --db=ssl:127.0.0.1:$TCP_PORT \
7477 --private-key=$PKIDIR/testpki-privkey.pem \
7478 --certificate=$PKIDIR/testpki-cert.pem \
7479 --ca-cert=$PKIDIR/testpki-cacert.pem \
7480 chassis-add ch vxlan 1.2.4.8], [1], [ignore],
7481 [ovn-sbctl: transaction error: {"details":"insert operation not allowed when database server is in read only mode","error":"not allowed"}
7484 OVS_APP_EXIT_AND_WAIT([ovsdb-server])
7487 AT_SETUP([ovn -- nb connection/ssl commands])
7488 AT_SKIP_IF([test $HAVE_PYTHON = no])
7489 AT_SKIP_IF([test "$HAVE_OPENSSL" = no])
7490 PKIDIR="$(cd $abs_top_builddir/tests && pwd)"
7491 AT_SKIP_IF([expr "$PKIDIR" : ".*[ '\"
7495 ovsdb-tool create ovn-nb.db "$abs_top_srcdir"/ovn/ovn-nb.ovsschema
7497 # Start nb db server using db connection/ssl entries (unpopulated initially)
7498 start_daemon ovsdb-server --remote=punix:ovnnb_db.sock \
7499 --remote=db:OVN_Northbound,NB_Global,connections \
7500 --private-key=db:OVN_Northbound,SSL,private_key \
7501 --certificate=db:OVN_Northbound,SSL,certificate \
7502 --ca-cert=db:OVN_Northbound,SSL,ca_cert \
7505 # Populate SSL configuration entries in nb db
7507 [ovn-nbctl set-ssl $PKIDIR/testpki-privkey.pem \
7508 $PKIDIR/testpki-cert.pem \
7509 $PKIDIR/testpki-cacert.pem], [0], [stdout], [ignore])
7511 # Populate a passive SSL connection in nb db
7512 AT_CHECK([ovn-nbctl set-connection pssl:0:127.0.0.1], [0], [stdout], [ignore])
7514 PARSE_LISTENING_PORT([ovsdb-server.log], [TCP_PORT])
7516 # Verify SSL connetivity to nb db server
7517 AT_CHECK([ovn-nbctl --db=ssl:127.0.0.1:$TCP_PORT \
7518 --private-key=$PKIDIR/testpki-privkey.pem \
7519 --certificate=$PKIDIR/testpki-cert.pem \
7520 --ca-cert=$PKIDIR/testpki-cacert.pem \
7522 [0], [stdout], [ignore])
7523 AT_CHECK([ovn-nbctl --db=ssl:127.0.0.1:$TCP_PORT \
7524 --private-key=$PKIDIR/testpki-privkey.pem \
7525 --certificate=$PKIDIR/testpki-cert.pem \
7526 --ca-cert=$PKIDIR/testpki-cacert.pem \
7528 [0], [stdout], [ignore])
7529 AT_CHECK([ovn-nbctl --db=ssl:127.0.0.1:$TCP_PORT \
7530 --private-key=$PKIDIR/testpki-privkey.pem \
7531 --certificate=$PKIDIR/testpki-cert.pem \
7532 --ca-cert=$PKIDIR/testpki-cacert.pem \
7534 [0], [stdout], [ignore])
7536 OVS_APP_EXIT_AND_WAIT([ovsdb-server])
7539 AT_SETUP([ovn -- sb connection/ssl commands])
7540 AT_SKIP_IF([test $HAVE_PYTHON = no])
7541 AT_SKIP_IF([test "$HAVE_OPENSSL" = no])
7542 PKIDIR="$(cd $abs_top_builddir/tests && pwd)"
7543 AT_SKIP_IF([expr "$PKIDIR" : ".*[ '\"
7547 ovsdb-tool create ovn-sb.db "$abs_top_srcdir"/ovn/ovn-sb.ovsschema
7549 # Start sb db server using db connection/ssl entries (unpopulated initially)
7550 start_daemon ovsdb-server --remote=punix:ovnsb_db.sock \
7551 --remote=db:OVN_Southbound,SB_Global,connections \
7552 --private-key=db:OVN_Southbound,SSL,private_key \
7553 --certificate=db:OVN_Southbound,SSL,certificate \
7554 --ca-cert=db:OVN_Southbound,SSL,ca_cert \
7557 # Populate SSL configuration entries in sb db
7559 [ovn-sbctl set-ssl $PKIDIR/testpki-privkey.pem \
7560 $PKIDIR/testpki-cert.pem \
7561 $PKIDIR/testpki-cacert.pem], [0], [stdout], [ignore])
7563 # Populate a passive SSL connection in sb db
7564 AT_CHECK([ovn-sbctl set-connection pssl:0:127.0.0.1], [0], [stdout], [ignore])
7566 PARSE_LISTENING_PORT([ovsdb-server.log], [TCP_PORT])
7568 # Verify SSL connetivity to sb db server
7569 AT_CHECK([ovn-sbctl --db=ssl:127.0.0.1:$TCP_PORT \
7570 --private-key=$PKIDIR/testpki-privkey.pem \
7571 --certificate=$PKIDIR/testpki-cert.pem \
7572 --ca-cert=$PKIDIR/testpki-cacert.pem \
7574 [0], [stdout], [ignore])
7575 AT_CHECK([ovn-sbctl --db=ssl:127.0.0.1:$TCP_PORT \
7576 --private-key=$PKIDIR/testpki-privkey.pem \
7577 --certificate=$PKIDIR/testpki-cert.pem \
7578 --ca-cert=$PKIDIR/testpki-cacert.pem \
7580 [0], [stdout], [ignore])
7581 AT_CHECK([ovn-sbctl --db=ssl:127.0.0.1:$TCP_PORT \
7582 --private-key=$PKIDIR/testpki-privkey.pem \
7583 --certificate=$PKIDIR/testpki-cert.pem \
7584 --ca-cert=$PKIDIR/testpki-cacert.pem \
7586 [0], [stdout], [ignore])
7588 OVS_APP_EXIT_AND_WAIT([ovsdb-server])
7591 AT_SETUP([ovn -- nested containers])
7595 # 2 HVs. HV1 has 2 VMs - "VM1" and "bar3". HV2 has 1 VM - "VM2"
7598 # 3 Logical switches - "mgmt" (172.16.1.0/24), "foo" (192.168.1.0/24)
7599 # and "bar" (192.168.2.0/24). They are all connected to router R1.
7602 ovn-nbctl ls-add mgmt
7603 ovn-nbctl ls-add foo
7604 ovn-nbctl ls-add bar
7606 # Connect mgmt to R1
7607 ovn-nbctl lrp-add R1 mgmt 00:00:00:01:02:02 172.16.1.1/24
7608 ovn-nbctl lsp-add mgmt rp-mgmt -- set Logical_Switch_Port rp-mgmt type=router \
7609 options:router-port=mgmt addresses=\"00:00:00:01:02:02\"
7612 ovn-nbctl lrp-add R1 foo 00:00:00:01:02:03 192.168.1.1/24
7613 ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo type=router \
7614 options:router-port=foo addresses=\"00:00:00:01:02:03\"
7617 ovn-nbctl lrp-add R1 bar 00:00:00:01:02:04 192.168.2.1/24
7618 ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar type=router \
7619 options:router-port=bar addresses=\"00:00:00:01:02:04\"
7621 # "mgmt" has VM1 and VM2 connected
7622 ovn-nbctl lsp-add mgmt vm1 \
7623 -- lsp-set-addresses vm1 "f0:00:00:01:02:03 172.16.1.2"
7625 ovn-nbctl lsp-add mgmt vm2 \
7626 -- lsp-set-addresses vm2 "f0:00:00:01:02:04 172.16.1.3"
7628 # "foo1" and "foo2" are containers belonging to switch "foo"
7629 # "foo1" has "VM1" as parent_port and "foo2" has "VM2" as parent_port.
7630 ovn-nbctl lsp-add foo foo1 vm1 1 \
7631 -- lsp-set-addresses foo1 "f0:00:00:01:02:05 192.168.1.2"
7633 ovn-nbctl lsp-add foo foo2 vm2 2 \
7634 -- lsp-set-addresses foo2 "f0:00:00:01:02:06 192.168.1.3"
7636 # "bar1" and "bar2" are containers belonging to switch "bar"
7637 # "bar1" has "VM1" as parent_port and "bar2" has "VM2" as parent_port.
7638 ovn-nbctl lsp-add bar bar1 vm1 2 \
7639 -- lsp-set-addresses bar1 "f0:00:00:01:02:07 192.168.2.2"
7641 ovn-nbctl lsp-add bar bar2 vm2 1 \
7642 -- lsp-set-addresses bar2 "f0:00:00:01:02:08 192.168.2.3"
7644 # bar3 is a standalone VM belonging to switch "bar"
7645 ovn-nbctl lsp-add bar bar3 \
7646 -- lsp-set-addresses bar3 "f0:00:00:01:02:09 192.168.2.4"
7648 # Create two hypervisor and create OVS ports corresponding to logical ports.
7653 ovs-vsctl add-br br-phys
7654 ovn_attach n1 br-phys 192.168.0.1
7655 ovs-vsctl -- add-port br-int vm1 -- \
7656 set interface vm1 external-ids:iface-id=vm1 \
7657 options:tx_pcap=hv1/vm1-tx.pcap \
7658 options:rxq_pcap=hv1/vm1-rx.pcap \
7661 ovs-vsctl -- add-port br-int bar3 -- \
7662 set interface bar3 external-ids:iface-id=bar3 \
7663 options:tx_pcap=hv1/bar3-tx.pcap \
7664 options:rxq_pcap=hv1/bar3-rx.pcap \
7669 ovs-vsctl add-br br-phys
7670 ovn_attach n1 br-phys 192.168.0.2
7671 ovs-vsctl -- add-port br-int vm2 -- \
7672 set interface vm2 external-ids:iface-id=vm2 \
7673 options:tx_pcap=hv2/vm2-tx.pcap \
7674 options:rxq_pcap=hv2/vm2-rx.pcap \
7677 # Pre-populate the hypervisors' ARP tables so that we don't lose any
7678 # packets for ARP resolution (native tunneling doesn't queue packets
7679 # for ARP resolution).
7682 # Allow some time for ovn-northd and ovn-controller to catch up.
7683 # XXX This should be more systematic.
7687 printf "%02x%02x%02x%02x" "$@"
7690 # Send ip packets between foo1 and foo2 (same switch, different HVs and
7691 # different VLAN tags).
7692 src_mac="f00000010205"
7693 dst_mac="f00000010206"
7694 src_ip=`ip_to_hex 192 168 1 2`
7695 dst_ip=`ip_to_hex 192 168 1 3`
7696 packet=${dst_mac}${src_mac}8100000108004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
7697 as hv1 ovs-appctl netdev-dummy/receive vm1 $packet
7699 # expected packet at foo2
7700 packet=${dst_mac}${src_mac}8100000208004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
7701 echo $packet > expected
7702 OVN_CHECK_PACKETS([hv2/vm2-tx.pcap], [expected])
7704 # Send ip packets between foo1 and bar2 (different switch, different HV)
7705 src_mac="f00000010205"
7706 dst_mac="000000010203"
7707 src_ip=`ip_to_hex 192 168 1 2`
7708 dst_ip=`ip_to_hex 192 168 2 3`
7709 packet=${dst_mac}${src_mac}8100000108004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
7710 as hv1 ovs-appctl netdev-dummy/receive vm1 $packet
7712 # expected packet at bar2
7713 src_mac="000000010204"
7714 dst_mac="f00000010208"
7715 packet=${dst_mac}${src_mac}8100000108004500001c000000003f110100${src_ip}${dst_ip}0035111100080000
7716 echo $packet >> expected
7717 OVN_CHECK_PACKETS([hv2/vm2-tx.pcap], [expected])
7719 # Send ip packets between foo1 and bar1
7720 # (different switch, loopback to same vm but different tag)
7721 src_mac="f00000010205"
7722 dst_mac="000000010203"
7723 src_ip=`ip_to_hex 192 168 1 2`
7724 dst_ip=`ip_to_hex 192 168 2 2`
7725 packet=${dst_mac}${src_mac}8100000108004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
7726 as hv1 ovs-appctl netdev-dummy/receive vm1 $packet
7728 # expected packet at bar1
7729 src_mac="000000010204"
7730 dst_mac="f00000010207"
7731 packet=${dst_mac}${src_mac}8100000208004500001c000000003f110100${src_ip}${dst_ip}0035111100080000
7732 echo $packet > expected1
7733 OVN_CHECK_PACKETS([hv1/vm1-tx.pcap], [expected1])
7735 # Send ip packets between bar1 and bar3
7736 # (same switch. But one is container and another is a standalone VM)
7737 src_mac="f00000010207"
7738 dst_mac="f00000010209"
7739 src_ip=`ip_to_hex 192 168 2 2`
7740 dst_ip=`ip_to_hex 192 168 2 3`
7741 packet=${dst_mac}${src_mac}8100000208004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
7742 as hv1 ovs-appctl netdev-dummy/receive vm1 $packet
7744 # expected packet at bar3
7745 packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
7746 echo $packet > expected
7747 OVN_CHECK_PACKETS([hv1/bar3-tx.pcap], [expected])
7749 # Send ip packets between foo1 and vm1.
7750 (different switch, container to the VM hosting it.)
7751 src_mac="f00000010205"
7752 dst_mac="000000010203"
7753 src_ip=`ip_to_hex 192 168 1 2`
7754 dst_ip=`ip_to_hex 172 16 1 2`
7755 packet=${dst_mac}${src_mac}8100000108004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
7756 as hv1 ovs-appctl netdev-dummy/receive vm1 $packet
7758 # expected packet at vm1
7759 src_mac="000000010202"
7760 dst_mac="f00000010203"
7761 packet=${dst_mac}${src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000
7762 echo $packet >> expected1
7763 OVN_CHECK_PACKETS([hv1/vm1-tx.pcap], [expected1])
7765 # Send packets from vm1 to bar1.
7766 (different switch, A hosting VM to a container inside it)
7767 src_mac="f00000010203"
7768 dst_mac="000000010202"
7769 src_ip=`ip_to_hex 172 16 1 2`
7770 dst_ip=`ip_to_hex 192 168 2 2`
7771 packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
7772 as hv1 ovs-appctl netdev-dummy/receive vm1 $packet
7774 # expected packet at vm1
7775 src_mac="000000010204"
7776 dst_mac="f00000010207"
7777 packet=${dst_mac}${src_mac}8100000208004500001c000000003f110100${src_ip}${dst_ip}0035111100080000
7778 echo $packet >> expected1
7779 OVN_CHECK_PACKETS([hv1/vm1-tx.pcap], [expected1])
7781 # Send broadcast packet from foo1. foo1 should not receive the same packet.
7782 src_mac="f00000010205"
7783 dst_mac="ffffffffffff"
7784 src_ip=`ip_to_hex 192 168 1 2`
7785 dst_ip=`ip_to_hex 255 255 255 255`
7786 packet=${dst_mac}${src_mac}8100000108004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
7787 as hv1 ovs-appctl netdev-dummy/receive vm1 $packet
7789 # expected packet at VM1
7790 OVN_CHECK_PACKETS([hv1/vm1-tx.pcap], [expected1])
7792 OVN_CLEANUP([hv1],[hv2])
7796 AT_SETUP([ovn -- 3 HVs, 3 LRs connected via LS, source IP based routes])
7797 AT_SKIP_IF([test $HAVE_PYTHON = no])
7801 # Three LRs - R1, R2 and R3 that are connected to each other via LS "join"
7802 # in 20.0.0.0/24 network. R1 has switchess foo (192.168.1.0/24) and bar
7803 # (192.168.2.0/24) connected to it.
7805 # R2 and R3 are gateway routers.
7806 # R2 has alice (172.16.1.0/24) and R3 has bob (172.16.1.0/24)
7807 # connected to it. Note how both alice and bob have the same subnet behind it.
7808 # We are trying to simulate external network via those 2 switches. In real
7809 # world the switch ports of these switches will have addresses set as "unknown"
7810 # to make them learning switches. Or those switches will be "localnet" ones.
7812 # Create three hypervisors and create OVS ports corresponding to logical ports.
7817 ovs-vsctl add-br br-phys
7818 ovn_attach n1 br-phys 192.168.0.1
7819 ovs-vsctl -- add-port br-int hv1-vif1 -- \
7820 set interface hv1-vif1 external-ids:iface-id=foo1 \
7821 options:tx_pcap=hv1/vif1-tx.pcap \
7822 options:rxq_pcap=hv1/vif1-rx.pcap \
7825 ovs-vsctl -- add-port br-int hv1-vif2 -- \
7826 set interface hv1-vif2 external-ids:iface-id=bar1 \
7827 options:tx_pcap=hv1/vif2-tx.pcap \
7828 options:rxq_pcap=hv1/vif2-rx.pcap \
7833 ovs-vsctl add-br br-phys
7834 ovn_attach n1 br-phys 192.168.0.2
7835 ovs-vsctl -- add-port br-int hv2-vif1 -- \
7836 set interface hv2-vif1 external-ids:iface-id=alice1 \
7837 options:tx_pcap=hv2/vif1-tx.pcap \
7838 options:rxq_pcap=hv2/vif1-rx.pcap \
7843 ovs-vsctl add-br br-phys
7844 ovn_attach n1 br-phys 192.168.0.3
7845 ovs-vsctl -- add-port br-int hv3-vif1 -- \
7846 set interface hv3-vif1 external-ids:iface-id=bob1 \
7847 options:tx_pcap=hv3/vif1-tx.pcap \
7848 options:rxq_pcap=hv3/vif1-rx.pcap \
7852 ovn-nbctl create Logical_Router name=R1
7853 ovn-nbctl create Logical_Router name=R2 options:chassis="hv2"
7854 ovn-nbctl create Logical_Router name=R3 options:chassis="hv3"
7856 ovn-nbctl ls-add foo
7857 ovn-nbctl ls-add bar
7858 ovn-nbctl ls-add alice
7859 ovn-nbctl ls-add bob
7860 ovn-nbctl ls-add join
7863 ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
7864 ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo type=router \
7865 options:router-port=foo addresses=\"00:00:01:01:02:03\"
7868 ovn-nbctl lrp-add R1 bar 00:00:01:01:02:04 192.168.2.1/24
7869 ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar type=router \
7870 options:router-port=bar addresses=\"00:00:01:01:02:04\"
7872 # Connect alice to R2
7873 ovn-nbctl lrp-add R2 alice 00:00:02:01:02:03 172.16.1.1/24
7874 ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port rp-alice \
7875 type=router options:router-port=alice addresses=\"00:00:02:01:02:03\"
7878 ovn-nbctl lrp-add R3 bob 00:00:03:01:02:03 172.16.1.2/24
7879 ovn-nbctl lsp-add bob rp-bob -- set Logical_Switch_Port rp-bob \
7880 type=router options:router-port=bob addresses=\"00:00:03:01:02:03\"
7882 # Connect R1 to join
7883 ovn-nbctl lrp-add R1 R1_join 00:00:04:01:02:03 20.0.0.1/24
7884 ovn-nbctl lsp-add join r1-join -- set Logical_Switch_Port r1-join \
7885 type=router options:router-port=R1_join addresses='"00:00:04:01:02:03"'
7887 # Connect R2 to join
7888 ovn-nbctl lrp-add R2 R2_join 00:00:04:01:02:04 20.0.0.2/24
7889 ovn-nbctl lsp-add join r2-join -- set Logical_Switch_Port r2-join \
7890 type=router options:router-port=R2_join addresses='"00:00:04:01:02:04"'
7892 # Connect R3 to join
7893 ovn-nbctl lrp-add R3 R3_join 00:00:04:01:02:05 20.0.0.3/24
7894 ovn-nbctl lsp-add join r3-join -- set Logical_Switch_Port r3-join \
7895 type=router options:router-port=R3_join addresses='"00:00:04:01:02:05"'
7897 # Install static routes with source ip address as the policy for routing.
7898 # We want traffic from 'foo' to go via R2 and traffic of 'bar' to go via R3.
7899 ovn-nbctl --policy="src-ip" lr-route-add R1 192.168.1.0/24 20.0.0.2
7900 ovn-nbctl --policy="src-ip" lr-route-add R1 192.168.2.0/24 20.0.0.3
7902 # Install static routes with destination ip address as the policy for routing.
7903 ovn-nbctl lr-route-add R2 192.168.0.0/16 20.0.0.1
7905 ovn-nbctl lr-route-add R3 192.168.0.0/16 20.0.0.1
7907 # Create logical port foo1 in foo
7908 ovn-nbctl lsp-add foo foo1 \
7909 -- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
7911 # Create logical port bar1 in bar
7912 ovn-nbctl lsp-add bar bar1 \
7913 -- lsp-set-addresses bar1 "f0:00:00:01:02:04 192.168.2.2"
7915 # Create logical port alice1 in alice
7916 ovn-nbctl lsp-add alice alice1 \
7917 -- lsp-set-addresses alice1 "f0:00:00:01:02:05 172.16.1.3"
7919 # Create logical port bob1 in bob
7920 ovn-nbctl lsp-add bob bob1 \
7921 -- lsp-set-addresses bob1 "f0:00:00:01:02:06 172.16.1.4"
7923 # Pre-populate the hypervisors' ARP tables so that we don't lose any
7924 # packets for ARP resolution (native tunneling doesn't queue packets
7925 # for ARP resolution).
7928 # Allow some time for ovn-northd and ovn-controller to catch up.
7929 # XXX This should be more systematic.
7933 printf "%02x%02x%02x%02x" "$@"
7936 sed 's/\(00\)\{1,\}$//'
7939 # Send ip packets between foo1 and bar1
7940 # (East-west traffic should flow normally)
7941 src_mac="f00000010203"
7942 dst_mac="000001010203"
7943 src_ip=`ip_to_hex 192 168 1 2`
7944 dst_ip=`ip_to_hex 192 168 2 2`
7945 packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
7946 as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
7948 # Send ip packets between foo1 and alice1
7949 src_mac="f00000010203"
7950 dst_mac="000001010203"
7951 src_ip=`ip_to_hex 192 168 1 2`
7952 dst_ip=`ip_to_hex 172 16 1 3`
7953 packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
7954 as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
7955 as hv1 ovs-appctl ofproto/trace br-int in_port=1 $packet
7957 # Send ip packets between bar1 and bob1
7958 src_mac="f00000010204"
7959 dst_mac="000001010204"
7960 src_ip=`ip_to_hex 192 168 2 2`
7961 dst_ip=`ip_to_hex 172 16 1 4`
7962 packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
7963 as hv1 ovs-appctl netdev-dummy/receive hv1-vif2 $packet
7964 #as hv1 ovs-appctl ofproto/trace br-int in_port=2 $packet
7966 # Packet to expect at bar1
7967 src_mac="000001010204"
7968 dst_mac="f00000010204"
7969 src_ip=`ip_to_hex 192 168 1 2`
7970 dst_ip=`ip_to_hex 192 168 2 2`
7971 expected=${dst_mac}${src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000
7972 echo $expected > expected
7973 OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [expected])
7975 # Packet to Expect at alice1
7976 src_mac="000002010203"
7977 dst_mac="f00000010205"
7978 src_ip=`ip_to_hex 192 168 1 2`
7979 dst_ip=`ip_to_hex 172 16 1 3`
7980 expected=${dst_mac}${src_mac}08004500001c000000003e110200${src_ip}${dst_ip}0035111100080000
7981 echo $expected > expected
7982 OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
7984 # Packet to Expect at bob1
7985 src_mac="000003010203"
7986 dst_mac="f00000010206"
7987 src_ip=`ip_to_hex 192 168 2 2`
7988 dst_ip=`ip_to_hex 172 16 1 4`
7989 expected=${dst_mac}${src_mac}08004500001c000000003e110200${src_ip}${dst_ip}0035111100080000
7990 echo $expected > expected
7991 OVN_CHECK_PACKETS([hv3/vif1-tx.pcap], [expected])
7993 OVN_CLEANUP([hv1],[hv2],[hv3])
7997 AT_SETUP([ovn -- dns lookup : 1 HV, 2 LS, 2 LSPs/LS])
7998 AT_SKIP_IF([test $HAVE_PYTHON = no])
8001 ovn-nbctl ls-add ls1
8003 ovn-nbctl lsp-add ls1 ls1-lp1 \
8004 -- lsp-set-addresses ls1-lp1 "f0:00:00:00:00:01 10.0.0.4 aef0::4"
8006 ovn-nbctl lsp-set-port-security ls1-lp1 "f0:00:00:00:00:01 10.0.0.4 aef0::4"
8008 ovn-nbctl lsp-add ls1 ls1-lp2 \
8009 -- lsp-set-addresses ls1-lp2 "f0:00:00:00:00:02 10.0.0.6 20.0.0.4"
8011 ovn-nbctl lsp-set-port-security ls1-lp2 "f0:00:00:00:00:02 10.0.0.6 20.0.0.4"
8013 DNS1=`ovn-nbctl create DNS records={}`
8014 DNS2=`ovn-nbctl create DNS records={}`
8016 ovn-nbctl set DNS $DNS1 records:vm1.ovn.org="10.0.0.4 aef0::4"
8017 ovn-nbctl set DNS $DNS1 records:vm2.ovn.org="10.0.0.6 20.0.0.4"
8018 ovn-nbctl set DNS $DNS2 records:vm3.ovn.org="40.0.0.4"
8020 ovn-nbctl set Logical_switch ls1 dns_records="$DNS1"
8026 ovs-vsctl add-br br-phys
8027 ovn_attach n1 br-phys 192.168.0.1
8028 ovs-vsctl -- add-port br-int hv1-vif1 -- \
8029 set interface hv1-vif1 external-ids:iface-id=ls1-lp1 \
8030 options:tx_pcap=hv1/vif1-tx.pcap \
8031 options:rxq_pcap=hv1/vif1-rx.pcap \
8034 ovs-vsctl -- add-port br-int hv1-vif2 -- \
8035 set interface hv1-vif2 external-ids:iface-id=ls1-lp2 \
8036 options:tx_pcap=hv1/vif2-tx.pcap \
8037 options:rxq_pcap=hv1/vif2-rx.pcap \
8042 as hv1 ovs-vsctl show
8044 echo "*************************"
8046 echo "*************************"
8049 printf "%02x%02x%02x%02x" "$@"
8055 ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \
8056 options:rxq_pcap=dummy-rx.pcap
8057 rm -f ${pcap_file}*.pcap
8058 ovs-vsctl -- set Interface $iface options:tx_pcap=${pcap_file}-tx.pcap \
8059 options:rxq_pcap=${pcap_file}-rx.pcap
8062 # set_dns_params host_name
8063 # Sets the dns_req_data and dns_resp_data
8072 query_name=03766d31036f766e036f726700
8073 # IPv4 address - 10.0.0.4
8074 expected_dns_answer=${query_name}00010001${ttl}00040a000004
8078 query_name=03766d32036f766e036f726700
8079 # IPv4 address - 10.0.0.6
8080 expected_dns_answer=${query_name}00010001${ttl}00040a000006
8081 # IPv4 address - 20.0.0.4
8082 expected_dns_answer=${expected_dns_answer}${query_name}00010001${ttl}000414000004
8087 query_name=03766d33036f766e036f726700
8088 # IPv4 address - 40.0.0.4
8089 expected_dns_answer=${query_name}00010001${ttl}000428000004
8093 query_name=03766d31036f766e036f726700
8094 # IPv6 address - aef0::4
8096 expected_dns_answer=${query_name}${type}0001${ttl}0010aef00000000000000000000000000004
8100 query_name=03766d31036f766e036f726700
8103 # IPv4 address - 10.0.0.4
8104 # IPv6 address - aef0::4
8105 expected_dns_answer=${query_name}00010001${ttl}00040a000004
8106 expected_dns_answer=${expected_dns_answer}${query_name}001c0001${ttl}0010
8107 expected_dns_answer=${expected_dns_answer}aef00000000000000000000000000004
8111 query_name=03766d31036f766e036f726700
8112 # IPv6 address - aef0::4
8120 local dns_req_header=010201200001000000000000
8121 local dns_resp_header=010281200001${an_count}00000000
8122 dns_req_data=${dns_req_header}${query_name}${type}0001
8123 dns_resp_data=${dns_resp_header}${query_name}${type}0001${expected_dns_answer}
8126 # This shell function sends a DNS request packet
8127 # test_dns INPORT SRC_MAC DST_MAC SRC_IP DST_IP DNS_QUERY EXPEC
8129 local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5 dns_reply=$6
8130 local dns_query_data=$7
8131 shift; shift; shift; shift; shift; shift; shift;
8132 # Packet size => IPv4 header (20) + UDP header (8) +
8133 # DNS data (header + query)
8134 ip_len=`expr 28 + ${#dns_query_data} / 2`
8135 udp_len=`expr $ip_len - 20`
8136 ip_len=$(printf "%x" $ip_len)
8137 udp_len=$(printf "%x" $udp_len)
8138 local request=${dst_mac}${src_mac}0800450000${ip_len}0000000080110000
8139 request=${request}${src_ip}${dst_ip}9234003500${udp_len}0000
8141 request=${request}${dns_query_data}
8143 if test $dns_reply != 0; then
8145 ip_len=`expr 28 + ${#dns_reply} / 2`
8146 udp_len=`expr $ip_len - 20`
8147 ip_len=$(printf "%x" $ip_len)
8148 udp_len=$(printf "%x" $udp_len)
8149 local reply=${src_mac}${dst_mac}0800450000${ip_len}0000000080110000
8150 reply=${reply}${dst_ip}${src_ip}0035923400${udp_len}0000${dns_reply}
8151 echo $reply >> $inport.expected
8154 echo $request >> $outport.expected
8157 as hv1 ovs-appctl netdev-dummy/receive hv1-vif$inport $request
8161 local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5 dns_reply=$6
8162 local dns_query_data=$7
8163 shift; shift; shift; shift; shift; shift; shift;
8164 # Packet size => UDP header (8) +
8165 # DNS data (header + query)
8166 ip_len=`expr 8 + ${#dns_query_data} / 2`
8168 ip_len=$(printf "%x" $ip_len)
8169 udp_len=$(printf "%x" $udp_len)
8170 local request=${dst_mac}${src_mac}86dd6000000000${ip_len}11ff${src_ip}${dst_ip}
8171 request=${request}9234003500${udp_len}0000
8173 request=${request}${dns_query_data}
8175 if test $dns_reply != 0; then
8177 ip_len=`expr 8 + ${#dns_reply} / 2`
8179 ip_len=$(printf "%x" $ip_len)
8180 udp_len=$(printf "%x" $udp_len)
8181 local reply=${src_mac}${dst_mac}86dd6000000000${ip_len}11ff${dst_ip}${src_ip}
8182 reply=${reply}0035923400${udp_len}0000${dns_reply}
8183 echo $reply >> $inport.expected
8186 echo $request >> $outport.expected
8189 as hv1 ovs-appctl netdev-dummy/receive hv1-vif$inport $request
8192 AT_CAPTURE_FILE([ofctl_monitor0.log])
8193 as hv1 ovs-ofctl monitor br-int resume --detach --no-chdir \
8194 --pidfile=ovs-ofctl0.pid 2> ofctl_monitor0.log
8197 src_ip=`ip_to_hex 10 0 0 4`
8198 dst_ip=`ip_to_hex 10 0 0 1`
8200 test_dns 1 f00000000001 f000000000f0 $src_ip $dst_ip $dns_reply $dns_req_data $dns_resp_data
8202 # NXT_RESUMEs should be 1.
8203 OVS_WAIT_UNTIL([test 1 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
8205 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif1-tx.pcap > 1.packets
8206 cat 1.expected | cut -c -48 > expout
8207 AT_CHECK([cat 1.packets | cut -c -48], [0], [expout])
8208 # Skipping the IPv4 checksum.
8209 cat 1.expected | cut -c 53- > expout
8210 AT_CHECK([cat 1.packets | cut -c 53-], [0], [expout])
8212 reset_pcap_file hv1-vif1 hv1/vif1
8213 reset_pcap_file hv1-vif2 hv1/vif2
8218 src_ip=`ip_to_hex 10 0 0 6`
8219 dst_ip=`ip_to_hex 10 0 0 1`
8221 test_dns 2 f00000000002 f000000000f0 $src_ip $dst_ip $dns_reply $dns_req_data $dns_resp_data
8223 # NXT_RESUMEs should be 2.
8224 OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
8226 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets
8227 cat 2.expected | cut -c -48 > expout
8228 AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
8229 # Skipping the IPv4 checksum.
8230 cat 2.expected | cut -c 53- > expout
8231 AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
8233 reset_pcap_file hv1-vif1 hv1/vif1
8234 reset_pcap_file hv1-vif2 hv1/vif2
8238 # Clear the query name options for ls1-lp2
8239 ovn-nbctl --wait=hv remove DNS $DNS1 records vm2.ovn.org
8242 src_ip=`ip_to_hex 10 0 0 4`
8243 dst_ip=`ip_to_hex 10 0 0 1`
8245 test_dns 1 f00000000001 f00000000002 $src_ip $dst_ip $dns_reply $dns_req_data
8247 # NXT_RESUMEs should be 3.
8248 OVS_WAIT_UNTIL([test 3 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
8250 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif1-tx.pcap > 1.packets
8251 AT_CHECK([cat 1.packets], [0], [])
8253 reset_pcap_file hv1-vif1 hv1/vif1
8254 reset_pcap_file hv1-vif2 hv1/vif2
8258 # Clear the query name for ls1-lp1
8259 # Since ls1 has no query names configued,
8260 # ovn-northd should not add the DNS flows.
8261 ovn-nbctl --wait=hv remove DNS $DNS1 records vm1.ovn.org
8264 src_ip=`ip_to_hex 10 0 0 6`
8265 dst_ip=`ip_to_hex 10 0 0 1`
8267 test_dns 2 f00000000002 f000000000f0 $src_ip $dst_ip $dns_reply $dns_req_data
8269 # NXT_RESUMEs should be 3 only.
8270 OVS_WAIT_UNTIL([test 3 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
8272 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets
8273 AT_CHECK([cat 2.packets], [0], [])
8275 reset_pcap_file hv1-vif1 hv1/vif1
8276 reset_pcap_file hv1-vif2 hv1/vif2
8280 # Test IPv6 (AAAA records) using IPv4 packet.
8281 # Add back the DNS options for ls1-lp1.
8282 ovn-nbctl --wait=hv set DNS $DNS1 records:vm1.ovn.org="10.0.0.4 aef0::4"
8284 set_dns_params vm1_ipv6_only
8285 src_ip=`ip_to_hex 10 0 0 6`
8286 dst_ip=`ip_to_hex 10 0 0 1`
8288 test_dns 2 f00000000002 f000000000f0 $src_ip $dst_ip $dns_reply $dns_req_data $dns_resp_data
8290 # NXT_RESUMEs should be 4.
8291 OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
8293 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets
8294 cat 2.expected | cut -c -48 > expout
8295 AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
8296 # Skipping the IPv4 checksum.
8297 cat 2.expected | cut -c 53- > expout
8298 AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
8300 reset_pcap_file hv1-vif1 hv1/vif1
8301 reset_pcap_file hv1-vif2 hv1/vif2
8305 # Test both IPv4 (A) and IPv6 (AAAA records) using IPv4 packet.
8306 set_dns_params vm1_ipv4_v6
8307 src_ip=`ip_to_hex 10 0 0 6`
8308 dst_ip=`ip_to_hex 10 0 0 1`
8310 test_dns 2 f00000000002 f000000000f0 $src_ip $dst_ip $dns_reply $dns_req_data $dns_resp_data
8312 # NXT_RESUMEs should be 5.
8313 OVS_WAIT_UNTIL([test 5 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
8315 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets
8316 cat 2.expected | cut -c -48 > expout
8317 AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
8318 # Skipping the IPv4 checksum.
8319 cat 2.expected | cut -c 53- > expout
8320 AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
8322 reset_pcap_file hv1-vif1 hv1/vif1
8323 reset_pcap_file hv1-vif2 hv1/vif2
8328 set_dns_params vm1_invalid_type
8329 src_ip=`ip_to_hex 10 0 0 6`
8330 dst_ip=`ip_to_hex 10 0 0 1`
8332 test_dns 2 f00000000002 f000000000f0 $src_ip $dst_ip $dns_reply $dns_req_data
8334 # NXT_RESUMEs should be 6.
8335 OVS_WAIT_UNTIL([test 6 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
8337 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets
8338 AT_CHECK([cat 2.packets], [0], [])
8340 reset_pcap_file hv1-vif1 hv1/vif1
8341 reset_pcap_file hv1-vif2 hv1/vif2
8345 # Incomplete DNS packet.
8346 set_dns_params vm1_incomplete
8347 src_ip=`ip_to_hex 10 0 0 6`
8348 dst_ip=`ip_to_hex 10 0 0 1`
8350 test_dns 2 f00000000002 f000000000f0 $src_ip $dst_ip $dns_reply $dns_req_data
8352 # NXT_RESUMEs should be 7.
8353 OVS_WAIT_UNTIL([test 7 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
8355 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets
8356 AT_CHECK([cat 2.packets], [0], [])
8358 reset_pcap_file hv1-vif1 hv1/vif1
8359 reset_pcap_file hv1-vif2 hv1/vif2
8363 # Add one more DNS record to the ls1.
8364 ovn-nbctl --wait=hv set Logical_switch ls1 dns_records="$DNS1 $DNS2"
8367 src_ip=`ip_to_hex 10 0 0 4`
8368 dst_ip=`ip_to_hex 10 0 0 1`
8370 test_dns 1 f00000000001 f000000000f0 $src_ip $dst_ip $dns_reply $dns_req_data $dns_resp_data
8372 # NXT_RESUMEs should be 8.
8373 OVS_WAIT_UNTIL([test 8 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
8375 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif1-tx.pcap > 1.packets
8376 cat 1.expected | cut -c -48 > expout
8377 AT_CHECK([cat 1.packets | cut -c -48], [0], [expout])
8378 # Skipping the IPv4 checksum.
8379 cat 1.expected | cut -c 53- > expout
8380 AT_CHECK([cat 1.packets | cut -c 53-], [0], [expout])
8382 reset_pcap_file hv1-vif1 hv1/vif1
8383 reset_pcap_file hv1-vif2 hv1/vif2
8387 # Try DNS query over IPv6
8389 src_ip=aef00000000000000000000000000004
8390 dst_ip=aef00000000000000000000000000001
8392 test_dns6 1 f00000000001 f000000000f0 $src_ip $dst_ip $dns_reply $dns_req_data $dns_resp_data
8394 # NXT_RESUMEs should be 9.
8395 OVS_WAIT_UNTIL([test 9 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
8397 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif1-tx.pcap > 1.packets
8398 # Skipping the UDP checksum.
8399 cat 1.expected | cut -c 1-120,125- > expout
8400 AT_CHECK([cat 1.packets | cut -c 1-120,125-], [0], [expout])
8402 reset_pcap_file hv1-vif1 hv1/vif1
8403 reset_pcap_file hv1-vif2 hv1/vif2
8411 AT_SETUP([ovn -- 4 HV, 1 LS, 1 LR, packet test with HA distributed router gateway port])
8412 AT_SKIP_IF([test $HAVE_PYTHON = no])
8419 ovs-vsctl add-br br-phys
8420 ovn_attach n1 br-phys 192.168.0.1
8421 ovs-vsctl -- add-port br-int hv1-vif1 -- \
8422 set interface hv1-vif1 external-ids:iface-id=foo1 \
8423 options:tx_pcap=hv1/vif1-tx.pcap \
8424 options:rxq_pcap=hv1/vif1-rx.pcap \
8429 ovs-vsctl add-br br-phys
8430 ovn_attach n1 br-phys 192.168.0.2
8434 ovs-vsctl add-br br-phys
8435 ovn_attach n1 br-phys 192.168.0.4
8439 ovs-vsctl add-br br-phys
8440 ovn_attach n1 br-phys 192.168.0.3
8441 ovs-vsctl -- add-port br-int ext1-vif1 -- \
8442 set interface ext1-vif1 external-ids:iface-id=outside1 \
8443 options:tx_pcap=ext1/vif1-tx.pcap \
8444 options:rxq_pcap=ext1/vif1-rx.pcap \
8447 # Pre-populate the hypervisors' ARP tables so that we don't lose any
8448 # packets for ARP resolution (native tunneling doesn't queue packets
8449 # for ARP resolution).
8452 ovn-nbctl create Logical_Router name=R1
8454 ovn-nbctl ls-add foo
8455 ovn-nbctl ls-add alice
8456 ovn-nbctl ls-add outside
8459 ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
8460 ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
8461 type=router options:router-port=foo \
8462 -- lsp-set-addresses rp-foo router
8464 # Connect alice to R1 as distributed router gateway port on gw1
8465 ovn-nbctl lrp-add R1 alice 00:00:02:01:02:03 172.16.1.1/24
8468 --id=@gc0 create Gateway_Chassis name=alice_gw1 \
8471 --id=@gc1 create Gateway_Chassis name=alice_gw2 \
8474 set Logical_Router_Port alice 'gateway_chassis=[@gc0,@gc1]'
8476 ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port rp-alice \
8477 type=router options:router-port=alice \
8478 -- lsp-set-addresses rp-alice router
8480 # Create logical port foo1 in foo
8481 ovn-nbctl lsp-add foo foo1 \
8482 -- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
8484 # Create logical port outside1 in outside
8485 ovn-nbctl lsp-add outside outside1 \
8486 -- lsp-set-addresses outside1 "f0:00:00:01:02:04 172.16.1.3"
8488 # Create localnet port in alice
8489 ovn-nbctl lsp-add alice ln-alice
8490 ovn-nbctl lsp-set-addresses ln-alice unknown
8491 ovn-nbctl lsp-set-type ln-alice localnet
8492 ovn-nbctl lsp-set-options ln-alice network_name=phys
8494 # Create localnet port in outside
8495 ovn-nbctl lsp-add outside ln-outside
8496 ovn-nbctl lsp-set-addresses ln-outside unknown
8497 ovn-nbctl lsp-set-type ln-outside localnet
8498 ovn-nbctl lsp-set-options ln-outside network_name=phys
8500 # Create bridge-mappings on gw1, gw2 and ext1, hv1 doesn't need
8501 # mapping to the external network, is the one generating packets
8502 as gw1 ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
8503 as gw2 ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
8504 as ext1 ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
8506 AT_CHECK([ovn-nbctl --timeout=3 --wait=sb sync], [0], [ignore])
8508 # Allow some time for ovn-northd and ovn-controller to catch up.
8509 # XXX This should be more systematic.
8513 printf "%02x%02x%02x%02x" "$@"
8519 ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \
8520 options:rxq_pcap=dummy-rx.pcap
8521 rm -f ${pcap_file}*.pcap
8522 ovs-vsctl -- set Interface $iface options:tx_pcap=${pcap_file}-tx.pcap \
8523 options:rxq_pcap=${pcap_file}-rx.pcap
8530 local backup_vswitchd_dead=$3
8532 # Send ip packet between foo1 and outside1
8533 src_mac="f00000010203" # foo1 mac
8534 dst_mac="000001010203" # rp-foo mac (internal router leg)
8535 src_ip=`ip_to_hex 192 168 1 2`
8536 dst_ip=`ip_to_hex 172 16 1 3`
8537 packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
8539 # ARP request packet to expect at outside1
8540 #arp_request=ffffffffffff${src_mac}08060001080006040001${src_mac}${src_ip}000000000000${dst_ip}
8542 as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
8544 # Send ARP reply from outside1 back to the router
8545 # XXX: note, we could avoid this if we plug this port into a netns
8546 # and setup the IP address into the port, so the kernel would simply reply
8547 src_mac="000002010203"
8548 reply_mac="f00000010204"
8549 dst_ip=`ip_to_hex 172 16 1 3`
8550 src_ip=`ip_to_hex 172 16 1 1`
8551 arp_reply=${src_mac}${reply_mac}08060001080006040002${reply_mac}${dst_ip}${src_mac}${src_ip}
8553 as ext1 ovs-appctl netdev-dummy/receive ext1-vif1 $arp_reply
8556 test `as $active_gw ovs-ofctl dump-flows br-int | grep table=66 | \
8557 grep actions=mod_dl_dst:f0:00:00:01:02:04 | wc -l` -eq 1
8560 # Packet to Expect at ext1 chassis, outside1 port
8561 src_mac="000002010203"
8562 dst_mac="f00000010204"
8563 src_ip=`ip_to_hex 192 168 1 2`
8564 dst_ip=`ip_to_hex 172 16 1 3`
8565 expected=${dst_mac}${src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000
8566 echo $expected > ext1-vif1.expected
8568 as $active_gw reset_pcap_file br-phys_n1 $active_gw/br-phys_n1
8570 if test $backup_vswitchd_dead != 1; then
8571 # Reset the file only if vswitchd in backup gw is alive
8572 as $backup_gw reset_pcap_file br-phys_n1 $backup_gw/br-phys_n1
8574 as ext1 reset_pcap_file ext1-vif1 ext1/vif1
8576 # Resend packet from foo1 to outside1
8577 as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
8581 OVN_CHECK_PACKETS([ext1/vif1-tx.pcap], [ext1-vif1.expected])
8582 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" $active_gw/br-phys_n1-tx.pcap > packets
8583 AT_CHECK([grep $expected packets | sort], [0], [expout])
8584 if test $backup_vswitchd_dead != 1; then
8585 # Check for backup gw only if vswitchd is alive
8586 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" $backup_gw/br-phys_n1-tx.pcap > packets
8587 AT_CHECK([grep $expected packets | sort], [0], [])
8591 test_ip_packet gw1 gw2 0
8593 ovn-nbctl --timeout=3 --wait=hv \
8594 --id=@gc0 create Gateway_Chassis name=alice_gw1 \
8597 --id=@gc1 create Gateway_Chassis name=alice_gw2 \
8600 set Logical_Router_Port alice 'gateway_chassis=[@gc0,@gc1]'
8602 test_ip_packet gw2 gw1 0
8604 # Get the claim count of both gw1 and gw2.
8605 gw1_claim_ct=`grep "cr-alice: Claiming" gw1/ovn-controller.log | wc -l`
8606 gw2_claim_ct=`grep "cr-alice: Claiming" gw2/ovn-controller.log | wc -l`
8608 # Stop ovs-vswitchd in gw2. gw1 should claim the gateway port.
8610 OVS_APP_EXIT_AND_WAIT([ovs-vswitchd])
8612 # gw1 should claim the cr-alice and the claim count of gw1 should be
8614 gw1_claim_ct=$((gw1_claim_ct+1))
8616 OVS_WAIT_UNTIL([test $gw1_claim_ct = `cat gw1/ovn-controller.log \
8617 | grep -c "cr-alice: Claiming"`])
8619 AT_CHECK([test $gw2_claim_ct = `cat gw2/ovn-controller.log | \
8620 grep -c "cr-alice: Claiming"`])
8622 test_ip_packet gw1 gw2 1
8625 OVS_APP_EXIT_AND_WAIT([ovn-controller])
8626 OVS_APP_EXIT_AND_WAIT([ovsdb-server])
8628 OVN_CLEANUP([hv1],[gw1],[ext1])
8632 AT_SETUP([ovn -- 4 HV, 3 LS, 2 LR, packet test with HA distributed router gateway port])
8633 AT_SKIP_IF([test $HAVE_PYTHON = no])
8640 ovs-vsctl add-br br-phys
8641 ovn_attach n1 br-phys 192.168.0.1
8642 ovs-vsctl -- add-port br-int hv1-vif1 -- \
8643 set interface hv1-vif1 external-ids:iface-id=foo1 \
8644 options:tx_pcap=hv1/vif1-tx.pcap \
8645 options:rxq_pcap=hv1/vif1-rx.pcap \
8650 ovs-vsctl add-br br-phys
8651 ovn_attach n1 br-phys 192.168.0.2
8655 ovs-vsctl add-br br-phys
8656 ovn_attach n1 br-phys 192.168.0.4
8660 ovs-vsctl add-br br-phys
8661 ovn_attach n1 br-phys 192.168.0.3
8662 ovs-vsctl -- add-port br-int ext1-vif1 -- \
8663 set interface ext1-vif1 external-ids:iface-id=outside1 \
8664 options:tx_pcap=ext1/vif1-tx.pcap \
8665 options:rxq_pcap=ext1/vif1-rx.pcap \
8668 # Pre-populate the hypervisors' ARP tables so that we don't lose any
8669 # packets for ARP resolution (native tunneling doesn't queue packets
8670 # for ARP resolution).
8673 ovn-nbctl create Logical_Router name=R0
8674 ovn-nbctl create Logical_Router name=R1
8676 ovn-nbctl ls-add foo
8677 ovn-nbctl ls-add join
8678 ovn-nbctl ls-add alice
8679 ovn-nbctl ls-add outside
8682 ovn-nbctl lrp-add R0 R0-foo 00:00:01:01:02:03 192.168.1.1/24
8683 ovn-nbctl lsp-add foo foo-R0 -- set Logical_Switch_Port foo-R0 \
8684 type=router options:router-port=R0-foo \
8685 -- lsp-set-addresses foo-R0 router
8688 ovn-nbctl lrp-add R0 R0-join 00:00:0d:01:02:03 100.60.1.1/24
8689 ovn-nbctl lsp-add join join-R0 -- set Logical_Switch_Port join-R0 \
8690 type=router options:router-port=R0-join \
8691 -- lsp-set-addresses join-R0 router
8694 ovn-nbctl lrp-add R1 R1-join 00:00:0e:01:02:03 100.60.1.2/24
8695 ovn-nbctl lsp-add join join-R1 -- set Logical_Switch_Port join-R1 \
8696 type=router options:router-port=R1-join \
8697 -- lsp-set-addresses join-R1 router
8700 ovn-nbctl lr-route-add R0 0.0.0.0/0 100.60.1.2
8701 ovn-nbctl lr-route-add R1 192.168.0.0/16 100.60.1.1
8703 # Connect alice to R1 as distributed router gateway port on gw1
8704 ovn-nbctl lrp-add R1 alice 00:00:02:01:02:03 172.16.1.1/24
8707 --id=@gc0 create Gateway_Chassis name=alice_gw1 \
8710 --id=@gc1 create Gateway_Chassis name=alice_gw2 \
8713 set Logical_Router_Port alice 'gateway_chassis=[@gc0,@gc1]'
8715 ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port rp-alice \
8716 type=router options:router-port=alice \
8717 -- lsp-set-addresses rp-alice router
8719 # Create logical port foo1 in foo
8720 ovn-nbctl lsp-add foo foo1 \
8721 -- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
8723 # Create logical port outside1 in outside
8724 ovn-nbctl lsp-add outside outside1 \
8725 -- lsp-set-addresses outside1 "f0:00:00:01:02:04 172.16.1.3"
8727 # Create localnet port in alice
8728 ovn-nbctl lsp-add alice ln-alice
8729 ovn-nbctl lsp-set-addresses ln-alice unknown
8730 ovn-nbctl lsp-set-type ln-alice localnet
8731 ovn-nbctl lsp-set-options ln-alice network_name=phys
8733 # Create localnet port in outside
8734 ovn-nbctl lsp-add outside ln-outside
8735 ovn-nbctl lsp-set-addresses ln-outside unknown
8736 ovn-nbctl lsp-set-type ln-outside localnet
8737 ovn-nbctl lsp-set-options ln-outside network_name=phys
8739 # Create bridge-mappings on gw1, gw2 and ext1, hv1 doesn't need
8740 # mapping to the external network, is the one generating packets
8741 as gw1 ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
8742 as gw2 ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
8743 as ext1 ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
8745 AT_CHECK([ovn-nbctl --timeout=3 --wait=sb sync], [0], [ignore])
8747 # hv1 should be in 'ref_chassis' of the ha_chasssi_group as logical
8748 # switch 'foo' can reach the router 'R1' (which has gw router port)
8749 # via foo1 -> foo -> R0 -> join -> R1
8750 hv1_ch_uuid=`ovn-sbctl --bare --columns _uuid find chassis name="hv1"`
8752 [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find ha_chassis_group | sort`
8754 ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
8755 test "$hv1_ch_uuid" = "$ref_ch_list"])
8757 # Allow some time for ovn-northd and ovn-controller to catch up.
8758 # XXX This should be more systematic.
8762 printf "%02x%02x%02x%02x" "$@"
8768 ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \
8769 options:rxq_pcap=dummy-rx.pcap
8770 rm -f ${pcap_file}*.pcap
8771 ovs-vsctl -- set Interface $iface options:tx_pcap=${pcap_file}-tx.pcap \
8772 options:rxq_pcap=${pcap_file}-rx.pcap
8780 # Send ip packet between foo1 and outside1
8781 src_mac="f00000010203" # foo1 mac
8782 dst_mac="000001010203" # foo-R0 mac (internal router leg)
8783 src_ip=`ip_to_hex 192 168 1 2`
8784 dst_ip=`ip_to_hex 172 16 1 3`
8785 packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
8787 # ARP request packet to expect at outside1
8788 #arp_request=ffffffffffff${src_mac}08060001080006040001${src_mac}${src_ip}000000000000${dst_ip}
8790 as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
8792 # Send ARP reply from outside1 back to the router
8793 # XXX: note, we could avoid this if we plug this port into a netns
8794 # and setup the IP address into the port, so the kernel would simply reply
8795 src_mac="000002010203"
8796 reply_mac="f00000010204"
8797 dst_ip=`ip_to_hex 172 16 1 3`
8798 src_ip=`ip_to_hex 172 16 1 1`
8799 arp_reply=${src_mac}${reply_mac}08060001080006040002${reply_mac}${dst_ip}${src_mac}${src_ip}
8801 as ext1 ovs-appctl netdev-dummy/receive ext1-vif1 $arp_reply
8804 test `as $active_gw ovs-ofctl dump-flows br-int | grep table=66 | \
8805 grep actions=mod_dl_dst:f0:00:00:01:02:04 | wc -l` -eq 1
8808 # Packet to Expect at ext1 chassis, outside1 port
8809 src_mac="000002010203"
8810 dst_mac="f00000010204"
8811 src_ip=`ip_to_hex 192 168 1 2`
8812 dst_ip=`ip_to_hex 172 16 1 3`
8813 expected=${dst_mac}${src_mac}08004500001c000000003e110200${src_ip}${dst_ip}0035111100080000
8814 echo $expected > ext1-vif1.expected
8816 as $active_gw reset_pcap_file br-phys_n1 $active_gw/br-phys_n1
8817 as $backup_gw reset_pcap_file br-phys_n1 $backup_gw/br-phys_n1
8818 as ext1 reset_pcap_file ext1-vif1 ext1/vif1
8820 # Resend packet from foo1 to outside1
8821 as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
8825 OVN_CHECK_PACKETS([ext1/vif1-tx.pcap], [ext1-vif1.expected])
8826 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" $active_gw/br-phys_n1-tx.pcap > packets
8827 AT_CHECK([grep $expected packets | sort], [0], [expout])
8828 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" $backup_gw/br-phys_n1-tx.pcap > packets
8829 AT_CHECK([grep $expected packets | sort], [0], [])
8832 test_ip_packet gw1 gw2
8834 ovn-nbctl --timeout=3 --wait=hv \
8835 --id=@gc0 create Gateway_Chassis name=alice_gw1 \
8838 --id=@gc1 create Gateway_Chassis name=alice_gw2 \
8841 set Logical_Router_Port alice 'gateway_chassis=[@gc0,@gc1]'
8843 test_ip_packet gw2 gw1
8845 OVN_CLEANUP([hv1],[gw1],[gw2],[ext1])
8848 AT_SETUP([ovn -- 1 LR with distributed router gateway port])
8849 AT_SKIP_IF([test $HAVE_PYTHON = no])
8853 # One LR R1 that has switches foo (192.168.1.0/24) and
8854 # alice (172.16.1.0/24) connected to it. The logical port
8855 # between R1 and alice has a "redirect-chassis" specified,
8856 # i.e. it is the distributed router gateway port.
8857 # Switch alice also has a localnet port defined.
8858 # An additional switch outside has a localnet port and the
8859 # same subnet as alice (172.16.1.0/24).
8862 # Three hypervisors hv[123].
8863 # hv1 hosts vif foo1.
8864 # hv2 is the "redirect-chassis" that hosts the distributed
8865 # router gateway port.
8866 # hv3 hosts vif outside1.
8867 # In order to show that connectivity works only through hv2,
8868 # an initial round of tests is run without any bridge-mapping
8869 # defined for the localnet on hv2. These tests are expected
8871 # Subsequent tests are run after defining the bridge-mapping
8872 # for the localnet on hv2. These tests are expected to succeed.
8874 # Create three hypervisors and create OVS ports corresponding
8880 ovs-vsctl add-br br-phys
8881 ovn_attach n1 br-phys 192.168.0.1
8882 ovs-vsctl -- add-port br-int hv1-vif1 -- \
8883 set interface hv1-vif1 external-ids:iface-id=foo1 \
8884 options:tx_pcap=hv1/vif1-tx.pcap \
8885 options:rxq_pcap=hv1/vif1-rx.pcap \
8890 ovs-vsctl add-br br-phys
8891 ovn_attach n1 br-phys 192.168.0.2
8895 ovs-vsctl add-br br-phys
8896 ovn_attach n1 br-phys 192.168.0.3
8897 ovs-vsctl -- add-port br-int hv3-vif1 -- \
8898 set interface hv3-vif1 external-ids:iface-id=outside1 \
8899 options:tx_pcap=hv3/vif1-tx.pcap \
8900 options:rxq_pcap=hv3/vif1-rx.pcap \
8903 # Pre-populate the hypervisors' ARP tables so that we don't lose any
8904 # packets for ARP resolution (native tunneling doesn't queue packets
8905 # for ARP resolution).
8908 ovn-nbctl create Logical_Router name=R1
8910 ovn-nbctl ls-add foo
8911 ovn-nbctl ls-add alice
8912 ovn-nbctl ls-add outside
8915 ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
8916 ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
8917 type=router options:router-port=foo \
8918 -- lsp-set-addresses rp-foo router
8920 # Connect alice to R1 as distributed router gateway port on hv2
8921 ovn-nbctl lrp-add R1 alice 00:00:02:01:02:03 172.16.1.1/24 \
8922 -- set Logical_Router_Port alice options:redirect-chassis="hv2"
8923 ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port rp-alice \
8924 type=router options:router-port=alice \
8925 -- lsp-set-addresses rp-alice router
8927 # Create logical port foo1 in foo
8928 ovn-nbctl lsp-add foo foo1 \
8929 -- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
8931 # Create logical port outside1 in outside
8932 ovn-nbctl lsp-add outside outside1 \
8933 -- lsp-set-addresses outside1 "f0:00:00:01:02:04 172.16.1.3"
8935 # Create localnet port in alice
8936 ovn-nbctl lsp-add alice ln-alice
8937 ovn-nbctl lsp-set-addresses ln-alice unknown
8938 ovn-nbctl lsp-set-type ln-alice localnet
8939 ovn-nbctl lsp-set-options ln-alice network_name=phys
8941 # Create localnet port in outside
8942 ovn-nbctl lsp-add outside ln-outside
8943 ovn-nbctl lsp-set-addresses ln-outside unknown
8944 ovn-nbctl lsp-set-type ln-outside localnet
8945 ovn-nbctl lsp-set-options ln-outside network_name=phys
8947 # Create bridge-mappings on hv1 and hv3, leaving hv2 for later
8948 as hv1 ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
8949 as hv3 ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
8952 # Allow some time for ovn-northd and ovn-controller to catch up.
8953 # XXX This should be more systematic.
8956 echo "---------NB dump-----"
8958 echo "---------------------"
8959 ovn-nbctl list logical_router
8960 echo "---------------------"
8961 ovn-nbctl list logical_router_port
8962 echo "---------------------"
8964 echo "---------SB dump-----"
8965 ovn-sbctl list datapath_binding
8966 echo "---------------------"
8967 ovn-sbctl list port_binding
8968 echo "---------------------"
8969 ovn-sbctl dump-flows
8970 echo "---------------------"
8971 ovn-sbctl list chassis
8972 ovn-sbctl list encap
8973 echo "------ Gateway_Chassis dump (SBDB) -------"
8974 ovn-sbctl list Gateway_Chassis
8975 echo "------ Port_Binding chassisredirect -------"
8976 ovn-sbctl find Port_Binding type=chassisredirect
8977 echo "-------------------------------------------"
8979 echo "------ hv1 dump ----------"
8980 as hv1 ovs-ofctl show br-int
8981 as hv1 ovs-ofctl dump-flows br-int
8982 echo "------ hv2 dump ----------"
8983 as hv2 ovs-ofctl show br-int
8984 as hv2 ovs-ofctl dump-flows br-int
8985 echo "------ hv3 dump ----------"
8986 as hv3 ovs-ofctl show br-int
8987 as hv3 ovs-ofctl dump-flows br-int
8988 echo "--------------------------"
8991 # Check that redirect mapping is programmed only on hv2
8992 AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=33 | grep =0x3,metadata=0x1 | wc -l], [0], [0
8994 AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=33 | grep =0x3,metadata=0x1 | grep load:0x2- | wc -l], [0], [1
8996 # Check that hv1 sends chassisredirect port traffic to hv2
8997 AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=32 | grep =0x3,metadata=0x1 | grep output | wc -l], [0], [1
8999 AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=32 | grep =0x3,metadata=0x1 | wc -l], [0], [0
9001 # Check that arp reply on distributed gateway port is only programmed on hv2
9002 AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep arp | grep load:0x2- | grep =0x2,metadata=0x1 | wc -l], [0], [0
9004 AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep arp | grep load:0x2- | grep =0x2,metadata=0x1 | wc -l], [0], [1
9009 printf "%02x%02x%02x%02x" "$@"
9013 : > hv2-vif1.expected
9014 : > hv3-vif1.expected
9016 # test_arp INPORT SHA SPA TPA [REPLY_HA]
9018 # Causes a packet to be received on INPORT. The packet is an ARP
9019 # request with SHA, SPA, and TPA as specified. If REPLY_HA is provided, then
9020 # it should be the hardware address of the target to expect to receive in an
9021 # ARP reply; otherwise no reply is expected.
9023 # INPORT is an logical switch port number, e.g. 11 for vif11.
9024 # SHA and REPLY_HA are each 12 hex digits.
9025 # SPA and TPA are each 8 hex digits.
9027 local hv=$1 inport=$2 sha=$3 spa=$4 tpa=$5 reply_ha=$6
9028 local request=ffffffffffff${sha}08060001080006040001${sha}${spa}ffffffffffff${tpa}
9029 as hv$hv ovs-appctl netdev-dummy/receive hv${hv}-vif$inport $request
9031 if test X$reply_ha != X; then
9032 # Expect to receive the reply, if any.
9033 local reply=${sha}${reply_ha}08060001080006040002${reply_ha}${tpa}${sha}${spa}
9034 echo $reply >> hv${hv}-vif$inport.expected
9038 rtr_ip=$(ip_to_hex 172 16 1 1)
9039 foo_ip=$(ip_to_hex 192 168 1 2)
9040 outside_ip=$(ip_to_hex 172 16 1 3)
9046 # ARP for router IP address from outside1, no response expected
9047 test_arp 3 1 f00000010204 $outside_ip $rtr_ip
9049 # Now check the packets actually received against the ones expected.
9050 OVN_CHECK_PACKETS([hv3/vif1-tx.pcap], [hv3-vif1.expected])
9052 # Send ip packet between foo1 and outside1
9053 src_mac="f00000010203"
9054 dst_mac="000001010203"
9055 src_ip=`ip_to_hex 192 168 1 2`
9056 dst_ip=`ip_to_hex 172 16 1 3`
9057 packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
9059 # Now check the packets actually received against the ones expected.
9060 OVN_CHECK_PACKETS([hv3/vif1-tx.pcap], [hv3-vif1.expected])
9062 # Now add bridge-mappings on hv2, which should make everything work
9063 as hv2 ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
9065 # Allow some time for ovn-northd and ovn-controller to catch up.
9066 # XXX This should be more systematic.
9069 # ARP for router IP address from outside1
9070 test_arp 3 1 f00000010204 $outside_ip $rtr_ip 000002010203
9072 # Now check the packets actually received against the ones expected.
9073 OVN_CHECK_PACKETS([hv3/vif1-tx.pcap], [hv3-vif1.expected])
9075 # Send ip packet between foo1 and outside1
9076 src_mac="f00000010203"
9077 dst_mac="000001010203"
9078 src_ip=`ip_to_hex 192 168 1 2`
9079 dst_ip=`ip_to_hex 172 16 1 3`
9080 packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
9082 # Packet to Expect at outside1
9083 src_mac="000002010203"
9084 dst_mac="f00000010204"
9085 expected=${dst_mac}${src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000
9087 as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
9089 echo "------ hv1 dump ----------"
9090 as hv1 ovs-ofctl show br-int
9091 as hv1 ovs-ofctl dump-flows br-int
9092 echo "------ hv2 dump ----------"
9093 as hv2 ovs-ofctl show br-int
9094 as hv2 ovs-ofctl dump-flows br-int
9095 echo "------ hv3 dump ----------"
9096 as hv3 ovs-ofctl show br-int
9097 as hv3 ovs-ofctl dump-flows br-int
9098 echo "----------------------------"
9100 echo $expected >> hv3-vif1.expected
9101 OVN_CHECK_PACKETS([hv3/vif1-tx.pcap], [hv3-vif1.expected])
9103 #Check ovn-trace over "chassisredirect" port
9104 AT_CAPTURE_FILE([trace])
9106 ovn-trace --all "$@" | tee trace | sed '1,/Minimal trace/d'
9109 echo 'ip.ttl--;' > expout
9110 echo 'eth.src = 00:00:02:01:02:03;' >> expout
9111 echo 'eth.dst = f0:00:00:01:02:04;' >> expout
9112 echo 'output("ln-alice");' >> expout
9113 AT_CHECK_UNQUOTED([ovn_trace foo 'inport == "foo1" && eth.src == f0:00:00:01:02:03 && eth.dst == 00:00:01:01:02:03 && ip4.src == 192.168.1.2 && ip4.dst == 172.16.1.3 && ip.ttl == 0xff'], [0], [expout])
9115 # Create logical port alice1 in alice on hv1
9116 as hv1 ovs-vsctl -- add-port br-int hv1-vif2 -- \
9117 set interface hv1-vif2 external-ids:iface-id=alice1 \
9118 options:tx_pcap=hv1/vif2-tx.pcap \
9119 options:rxq_pcap=hv1/vif2-rx.pcap \
9122 ovn-nbctl lsp-add alice alice1 \
9123 -- lsp-set-addresses alice1 "f0:00:00:01:02:05 172.16.1.4"
9125 # Create logical port foo2 in foo on hv2
9126 as hv2 ovs-vsctl -- add-port br-int hv2-vif1 -- \
9127 set interface hv2-vif1 external-ids:iface-id=foo2 \
9128 options:tx_pcap=hv2/vif1-tx.pcap \
9129 options:rxq_pcap=hv2/vif1-rx.pcap \
9132 ovn-nbctl lsp-add foo foo2 \
9133 -- lsp-set-addresses foo2 "f0:00:00:01:02:06 192.168.1.3"
9135 # Allow some time for ovn-northd and ovn-controller to catch up.
9136 # XXX This should be more systematic.
9139 : > hv1-vif2.expected
9141 # Send ip packet between alice1 and foo2
9142 src_mac="f00000010205"
9143 dst_mac="000002010203"
9144 src_ip=`ip_to_hex 172 16 1 4`
9145 dst_ip=`ip_to_hex 192 168 1 3`
9146 packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
9148 as hv1 ovs-appctl netdev-dummy/receive hv1-vif2 $packet
9150 # Packet to Expect at foo2
9151 src_mac="000001010203"
9152 dst_mac="f00000010206"
9153 src_ip=`ip_to_hex 172 16 1 4`
9154 dst_ip=`ip_to_hex 192 168 1 3`
9155 expected=${dst_mac}${src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000
9157 echo $expected >> hv2-vif1.expected
9158 OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [hv2-vif1.expected])
9160 AT_CHECK([ovn-sbctl --bare --columns _uuid find Port_Binding logical_port=cr-alice | wc -l], [0], [1
9163 ovn-nbctl --timeout=3 --wait=sb remove Logical_Router_Port alice options redirect-chassis
9165 AT_CHECK([ovn-sbctl find Port_Binding logical_port=cr-alice | wc -l], [0], [0
9168 OVN_CLEANUP([hv1],[hv2],[hv3])
9172 AT_SETUP([ovn -- send gratuitous arp for NAT rules on distributed router])
9173 AT_SKIP_IF([test $HAVE_PYTHON = no])
9175 # Create logical switches
9176 ovn-nbctl ls-add ls0
9177 ovn-nbctl ls-add ls1
9178 # Create distributed router
9179 ovn-nbctl create Logical_Router name=lr0
9180 # Add distributed gateway port to distributed router
9181 ovn-nbctl lrp-add lr0 lrp0 f0:00:00:00:00:01 192.168.0.1/24 \
9182 -- set Logical_Router_Port lrp0 options:redirect-chassis="hv2"
9183 ovn-nbctl lsp-add ls0 lrp0-rp -- set Logical_Switch_Port lrp0-rp \
9184 type=router options:router-port=lrp0 addresses="router"
9185 # Add router port to ls1
9186 ovn-nbctl lrp-add lr0 lrp1 f0:00:00:00:00:02 10.0.0.1/24
9187 ovn-nbctl lsp-add ls1 lrp1-rp -- set Logical_Switch_Port lrp1-rp \
9188 type=router options:router-port=lrp1 addresses="router"
9189 # Add logical ports for NAT rules
9190 ovn-nbctl lsp-add ls1 foo1 \
9191 -- lsp-set-addresses foo1 "00:00:00:00:00:03 10.0.0.3"
9192 ovn-nbctl lsp-add ls1 foo2 \
9193 -- lsp-set-addresses foo2 "00:00:00:00:00:04 10.0.0.4"
9194 # Add nat-addresses option
9195 ovn-nbctl lsp-set-options lrp0-rp router-port=lrp0 nat-addresses="router"
9197 AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 192.168.0.1 10.0.0.0/24])
9198 AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 192.168.0.2 10.0.0.2])
9199 AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 192.168.0.3 10.0.0.3 foo1 f0:00:00:00:00:03])
9200 AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 192.168.0.4 10.0.0.4 foo2 f0:00:00:00:00:04])
9205 ovs-vsctl add-br br-phys
9206 ovn_attach n1 br-phys 192.168.0.1
9208 AT_CHECK([ovs-vsctl set Open_vSwitch . external-ids:ovn-bridge-mappings=physnet1:br-phys])
9209 AT_CHECK([ovs-vsctl add-port br-phys snoopvif -- set Interface snoopvif options:tx_pcap=hv1/snoopvif-tx.pcap options:rxq_pcap=hv1/snoopvif-rx.pcap])
9213 ovs-vsctl add-br br-phys
9214 ovn_attach n1 br-phys 192.168.0.2
9215 # Initially test with no bridge-mapping on hv2, expect to receive no packets
9219 ovs-vsctl add-br br-phys
9220 ovn_attach n1 br-phys 192.168.0.3
9221 # Initially test with no bridge-mapping on hv3
9223 # Create a localnet port.
9224 AT_CHECK([ovn-nbctl lsp-add ls0 ln_port])
9225 AT_CHECK([ovn-nbctl lsp-set-addresses ln_port unknown])
9226 AT_CHECK([ovn-nbctl lsp-set-type ln_port localnet])
9227 AT_CHECK([ovn-nbctl lsp-set-options ln_port network_name=physnet1])
9229 # Allow some time for ovn-northd and ovn-controller to catch up.
9230 # XXX This should be more systematic.
9233 # Expect no packets when hv2 bridge-mapping is not present
9235 OVN_CHECK_PACKETS([hv1/snoopvif-tx.pcap], [packets])
9237 # Add bridge-mapping on hv2
9238 AT_CHECK([as hv2 ovs-vsctl set Open_vSwitch . external-ids:ovn-bridge-mappings=physnet1:br-phys])
9240 # Wait for packets to be received.
9241 OVS_WAIT_UNTIL([test `wc -c < "hv1/snoopvif-tx.pcap"` -ge 100])
9243 sed 's/\(00\)\{1,\}$//'
9245 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/snoopvif-tx.pcap | trim_zeros > packets
9246 expected="fffffffffffff0000000000108060001080006040001f00000000001c0a80001000000000000c0a80001"
9247 echo $expected > expout
9248 expected="fffffffffffff0000000000108060001080006040001f00000000001c0a80002000000000000c0a80002"
9249 echo $expected >> expout
9250 AT_CHECK([sort packets], [0], [expout])
9253 # Temporarily remove nat-addresses option to avoid race conditions
9254 # due to GARP backoff
9255 ovn-nbctl lsp-set-options lrp0-rp router-port=lrp0 nat-addresses=""
9260 ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \
9261 options:rxq_pcap=dummy-rx.pcap
9262 rm -f ${pcap_file}*.pcap
9263 ovs-vsctl -- set Interface $iface options:tx_pcap=${pcap_file}-tx.pcap \
9264 options:rxq_pcap=${pcap_file}-rx.pcap
9267 as hv1 reset_pcap_file snoopvif hv1/snoopvif
9269 # Add OVS ports for foo1 and foo2 on hv3
9270 ovs-vsctl -- add-port br-int hv3-vif1 -- \
9271 set interface hv3-vif1 external-ids:iface-id=foo1 \
9273 ovs-vsctl -- add-port br-int hv3-vif2 -- \
9274 set interface hv3-vif2 external-ids:iface-id=foo2 \
9277 # Add bridge-mapping on hv3
9278 AT_CHECK([as hv3 ovs-vsctl set Open_vSwitch . external-ids:ovn-bridge-mappings=physnet1:br-phys])
9280 # Re-add nat-addresses option
9281 ovn-nbctl lsp-set-options lrp0-rp router-port=lrp0 nat-addresses="router"
9283 # Wait for packets to be received.
9284 OVS_WAIT_UNTIL([test `wc -c < "hv1/snoopvif-tx.pcap"` -ge 250])
9286 sed 's/\(00\)\{1,\}$//'
9289 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/snoopvif-tx.pcap | trim_zeros > packets
9290 expected="fffffffffffff0000000000308060001080006040001f00000000003c0a80003000000000000c0a80003"
9291 echo $expected >> expout
9292 expected="fffffffffffff0000000000408060001080006040001f00000000004c0a80004000000000000c0a80004"
9293 echo $expected >> expout
9294 AT_CHECK([sort packets], [0], [expout])
9297 OVN_CLEANUP([hv1],[hv2],[hv3])
9301 # VLAN traffic for external network redirected through distributed router
9302 # gateway port should use vlans(i.e input network vlan tag) across hypervisors
9303 # instead of tunneling.
9304 AT_SETUP([ovn -- vlan traffic for external network with distributed router gateway port])
9305 AT_SKIP_IF([test $HAVE_PYTHON = no])
9309 # # One LR R1 that has switches foo (192.168.1.0/24) and
9310 # # alice (172.16.1.0/24) connected to it. The logical port
9311 # # between R1 and alice has a "redirect-chassis" specified,
9312 # # i.e. it is the distributed router gateway port(172.16.1.6).
9313 # # Switch alice also has a localnet port defined.
9314 # # An additional switch outside has the same subnet as alice
9315 # # (172.16.1.0/24), a localnet port and nexthop port(172.16.1.1)
9316 # # which will receive the packet destined for external network
9317 # # (i.e 8.8.8.8 as destination ip).
9320 # # Three hypervisors hv[123].
9321 # # hv1 hosts vif foo1.
9322 # # hv2 is the "redirect-chassis" that hosts the distributed router gateway port.
9323 # # hv3 hosts nexthop port vif outside1.
9324 # # All other tests connect hypervisors to network n1 through br-phys for tunneling.
9325 # # But in this test, hv1 won't connect to n1(and no br-phys in hv1), and
9326 # # in order to show vlans(instead of tunneling) used between hv1 and hv2,
9327 # # a new network n2 created and hv1 and hv2 connected to this network through br-ex.
9328 # # hv2 and hv3 are still connected to n1 network through br-phys.
9331 # We are not calling ovn_attach for hv1, to avoid adding br-phys.
9332 # Tunneling won't work in hv1 as ovn-encap-ip is not added to any bridge in hv1
9336 -- set Open_vSwitch . external-ids:system-id=hv1 \
9337 -- set Open_vSwitch . external-ids:ovn-remote=unix:$ovs_base/ovn-sb/ovn-sb.sock \
9338 -- set Open_vSwitch . external-ids:ovn-encap-type=geneve,vxlan \
9339 -- set Open_vSwitch . external-ids:ovn-encap-ip=192.168.0.1 \
9341 -- set bridge br-int fail-mode=secure other-config:disable-in-band=true \
9342 -- set Open_vSwitch . external-ids:ovn-bridge-mappings=public:br-ex
9344 start_daemon ovn-controller
9345 ovs-vsctl -- add-port br-int hv1-vif1 -- \
9346 set interface hv1-vif1 external-ids:iface-id=foo1 \
9351 ovs-vsctl add-br br-phys
9352 ovn_attach n1 br-phys 192.168.0.2
9353 ovs-vsctl set Open_vSwitch . external-ids:ovn-bridge-mappings="public:br-ex,phys:br-phys"
9357 ovs-vsctl add-br br-phys
9358 ovn_attach n1 br-phys 192.168.0.3
9359 ovs-vsctl -- add-port br-int hv3-vif1 -- \
9360 set interface hv3-vif1 external-ids:iface-id=outside1 \
9361 options:tx_pcap=hv3/vif1-tx.pcap \
9362 options:rxq_pcap=hv3/vif1-rx.pcap \
9364 ovs-vsctl set Open_vSwitch . external-ids:ovn-bridge-mappings="phys:br-phys"
9366 # Create network n2 for vlan connectivity between hv1 and hv2
9370 ovs-vsctl add-br br-ex
9374 ovs-vsctl add-br br-ex
9379 ovn-nbctl create Logical_Router name=R1
9381 ovn-nbctl ls-add foo
9382 ovn-nbctl ls-add alice
9383 ovn-nbctl ls-add outside
9386 ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
9387 ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
9388 type=router options:router-port=foo \
9389 -- lsp-set-addresses rp-foo router
9391 # Connect alice to R1 as distributed router gateway port (172.16.1.6) on hv2
9392 ovn-nbctl lrp-add R1 alice 00:00:02:01:02:03 172.16.1.6/24 \
9393 -- set Logical_Router_Port alice options:redirect-chassis="hv2"
9394 ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port rp-alice \
9395 type=router options:router-port=alice \
9396 -- lsp-set-addresses rp-alice router \
9398 # Create logical port foo1 in foo
9399 ovn-nbctl lsp-add foo foo1 \
9400 -- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
9402 # Create logical port outside1 in outside, which is a nexthop address
9404 ovn-nbctl lsp-add outside outside1 \
9405 -- lsp-set-addresses outside1 "f0:00:00:01:02:04 172.16.1.1"
9407 # Set default gateway (nexthop) to 172.16.1.1
9408 ovn-nbctl lr-route-add R1 "0.0.0.0/0" 172.16.1.1 alice
9409 AT_CHECK([ovn-nbctl lr-nat-add R1 snat 172.16.1.6 192.168.1.1/24])
9410 ovn-nbctl set Logical_Switch_Port rp-alice options:nat-addresses=router
9412 ovn-nbctl lsp-add foo ln-foo
9413 ovn-nbctl lsp-set-addresses ln-foo unknown
9414 ovn-nbctl lsp-set-options ln-foo network_name=public
9415 ovn-nbctl lsp-set-type ln-foo localnet
9416 AT_CHECK([ovn-nbctl set Logical_Switch_Port ln-foo tag=2])
9418 # Create localnet port in alice
9419 ovn-nbctl lsp-add alice ln-alice
9420 ovn-nbctl lsp-set-addresses ln-alice unknown
9421 ovn-nbctl lsp-set-type ln-alice localnet
9422 ovn-nbctl lsp-set-options ln-alice network_name=phys
9424 # Create localnet port in outside
9425 ovn-nbctl lsp-add outside ln-outside
9426 ovn-nbctl lsp-set-addresses ln-outside unknown
9427 ovn-nbctl lsp-set-type ln-outside localnet
9428 ovn-nbctl lsp-set-options ln-outside network_name=phys
9430 # Allow some time for ovn-northd and ovn-controller to catch up.
9431 # XXX This should be more systematic.
9432 ovn-nbctl --wait=hv --timeout=3 sync
9434 # Check that there is a logical flow in logical switch foo's pipeline
9435 # to set the outport to rp-foo (which is expected).
9436 OVS_WAIT_UNTIL([test 1 = `ovn-sbctl dump-flows foo | grep ls_in_l2_lkup | \
9437 grep rp-foo | grep -v is_chassis_resident | wc -l`])
9439 # Set the option 'reside-on-redirect-chassis' for foo
9440 ovn-nbctl set logical_router_port foo options:reside-on-redirect-chassis=true
9441 # Check that there is a logical flow in logical switch foo's pipeline
9442 # to set the outport to rp-foo with the condition is_chassis_redirect.
9443 ovn-sbctl dump-flows foo
9444 OVS_WAIT_UNTIL([test 1 = `ovn-sbctl dump-flows foo | grep ls_in_l2_lkup | \
9445 grep rp-foo | grep is_chassis_resident | wc -l`])
9447 echo "---------NB dump-----"
9449 echo "---------------------"
9450 ovn-nbctl list logical_router
9451 echo "---------------------"
9453 echo "---------------------"
9454 ovn-nbctl list logical_router_port
9455 echo "---------------------"
9457 echo "---------SB dump-----"
9458 ovn-sbctl list datapath_binding
9459 echo "---------------------"
9460 ovn-sbctl list port_binding
9461 echo "---------------------"
9462 ovn-sbctl dump-flows
9463 echo "---------------------"
9464 ovn-sbctl list chassis
9465 echo "---------------------"
9467 for chassis in hv1 hv2 hv3; do
9469 echo "------ $chassis dump ----------"
9470 ovs-vsctl show br-int
9471 ovs-ofctl show br-int
9472 ovs-ofctl dump-flows br-int
9473 echo "--------------------------"
9477 printf "%02x%02x%02x%02x" "$@"
9480 foo1_ip=$(ip_to_hex 192 168 1 2)
9481 gw_ip=$(ip_to_hex 172 16 1 6)
9482 dst_ip=$(ip_to_hex 8 8 8 8)
9483 nexthop_ip=$(ip_to_hex 172 16 1 1)
9485 foo1_mac="f00000010203"
9486 foo_mac="000001010203"
9487 gw_mac="000002010203"
9488 nexthop_mac="f00000010204"
9490 # Send ip packet from foo1 to 8.8.8.8
9491 src_mac="f00000010203"
9492 dst_mac="000001010203"
9493 packet=${foo_mac}${foo1_mac}08004500001c0000000040110000${foo1_ip}${dst_ip}0035111100080000
9495 # Wait for GARPs announcing gw IP to arrive
9497 test `as hv2 ovs-ofctl dump-flows br-int | grep table=66 | \
9498 grep actions=mod_dl_dst:f0:00:00:01:02:04 | wc -l` -eq 1
9501 # VLAN tagged packet with router port(192.168.1.1) MAC as destination MAC
9502 # is expected on bridge connecting hv1 and hv2
9503 expected=${foo_mac}${foo1_mac}8100000208004500001c0000000040110000${foo1_ip}${dst_ip}0035111100080000
9504 echo $expected > hv1-br-ex_n2.expected
9506 # Packet to Expect at outside1 i.e nexthop(172.16.1.1) port.
9507 # As connection tracking not enabled for this test, snat can't be done on the packet.
9508 # We still see foo1 as the source ip address. But source mac(gateway MAC) and
9509 # dest mac(nexthop mac) are properly configured.
9510 expected=${nexthop_mac}${gw_mac}08004500001c000000003f110100${foo1_ip}${dst_ip}0035111100080000
9511 echo $expected > hv3-vif1.expected
9516 ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \
9517 options:rxq_pcap=dummy-rx.pcap
9518 rm -f ${pcap_file}*.pcap
9519 ovs-vsctl -- set Interface $iface options:tx_pcap=${pcap_file}-tx.pcap \
9520 options:rxq_pcap=${pcap_file}-rx.pcap
9523 as hv1 reset_pcap_file br-ex_n2 hv1/br-ex_n2
9524 as hv3 reset_pcap_file hv3-vif1 hv3/vif1
9526 # Take note of how many packets arrived on the VLAN switch before generating
9528 n_packets=`as hv1 ovs-ofctl dump-flows br-int table=65 | grep "priority=100,reg15=0x1,metadata=0x2" | grep actions=clone | sed 's/.*n_packets=\([[0-9]]*\),.*/\1/'`
9529 as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
9532 # On hv1, the packet should not go from vlan switch pipleline to router
9534 as hv1 ovs-ofctl dump-flows br-int
9535 AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=65 | grep "priority=100,reg15=0x1,metadata=0x2" \
9536 | grep actions=clone | grep -v n_packets=$n_packets | wc -l], [0], [[0
9539 # On hv1, table 32 check that no packet goes via the tunnel port
9540 AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=32 \
9541 | grep "NXM_NX_TUN_ID" | grep -v n_packets=0 | wc -l], [0], [[0
9545 grep "1010203f00000010203"
9548 # Check vlan tagged packet on the bridge connecting hv1 and hv2 with the
9550 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/br-ex_n2-tx.pcap | ip_packet | uniq > hv1-br-ex_n2
9551 cat hv1-br-ex_n2.expected > expout
9552 AT_CHECK([sort hv1-br-ex_n2], [0], [expout])
9554 # Check expected packet on nexthop interface
9555 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv3/vif1-tx.pcap | grep ${foo1_ip}${dst_ip} | uniq > hv3-vif1
9556 cat hv3-vif1.expected > expout
9557 AT_CHECK([sort hv3-vif1], [0], [expout])
9559 OVN_CLEANUP([hv1],[hv2],[hv3])
9562 AT_SETUP([ovn -- IPv6 ND Router Solicitation responder])
9563 AT_KEYWORDS([ovn-nd_ra])
9564 AT_SKIP_IF([test $HAVE_PYTHON = no])
9567 # In this test case we create 1 lswitch with 3 VIF ports attached,
9568 # and a lrouter connected to the lswitch.
9569 # We generate the Router solicitation packet and verify the Router Advertisement
9570 # reply packet from the ovn-controller.
9572 # Create hypervisor and logical switch lsw0, logical router lr0, attach lsw0
9573 # onto lr0, set Logical_Router_Port.ipv6_ra_configs:address_mode column to
9574 # 'slaac' to allow lrp0 send RA for SLAAC mode.
9575 ovn-nbctl ls-add lsw0
9576 ovn-nbctl lr-add lr0
9577 ovn-nbctl lrp-add lr0 lrp0 fa:16:3e:00:00:01 fdad:1234:5678::1/64
9578 ovn-nbctl set Logical_Router_Port lrp0 ipv6_ra_configs:address_mode="slaac"
9580 -- lsp-add lsw0 lsp0 \
9581 -- set Logical_Switch_Port lsp0 type=router \
9582 options:router-port=lrp0 \
9583 addresses='"fa:16:3e:00:00:01 fdad:1234:5678::1"'
9587 ovs-vsctl add-br br-phys
9588 ovn_attach n1 br-phys 192.168.0.2
9590 ovn-nbctl lsp-add lsw0 lp1
9591 ovn-nbctl lsp-set-addresses lp1 "fa:16:3e:00:00:02 10.0.0.12 fdad:1234:5678:0:f816:3eff:fe:2"
9592 ovn-nbctl lsp-set-port-security lp1 "fa:16:3e:00:00:02 10.0.0.12 fdad:1234:5678:0:f816:3eff:fe:2"
9594 ovn-nbctl lsp-add lsw0 lp2
9595 ovn-nbctl lsp-set-addresses lp2 "fa:16:3e:00:00:03 10.0.0.13 fdad:1234:5678:0:f816:3eff:fe:3"
9596 ovn-nbctl lsp-set-port-security lp2 "fa:16:3e:00:00:03 10.0.0.13 fdad:1234:5678:0:f816:3eff:fe:3"
9598 ovn-nbctl lsp-add lsw0 lp3
9599 ovn-nbctl lsp-set-addresses lp3 "fa:16:3e:00:00:04 10.0.0.14 fdad:1234:5678:0:f816:3eff:fe:4"
9600 ovn-nbctl lsp-set-port-security lp3 "fa:16:3e:00:00:04 10.0.0.14 fdad:1234:5678:0:f816:3eff:fe:4"
9602 # Add ACL rule for ICMPv6 on lsw0
9603 ovn-nbctl acl-add lsw0 from-lport 1002 'ip6 && icmp6' allow-related
9604 ovn-nbctl acl-add lsw0 to-lport 1002 'outport == "lp1" && ip6 && icmp6' allow-related
9605 ovn-nbctl acl-add lsw0 to-lport 1002 'outport == "lp2" && ip6 && icmp6' allow-related
9606 ovn-nbctl acl-add lsw0 to-lport 1002 'outport == "lp3" && ip6 && icmp6' allow-related
9608 ovs-vsctl -- add-port br-int hv1-vif1 -- \
9609 set interface hv1-vif1 external-ids:iface-id=lp1 \
9610 options:tx_pcap=hv1/vif1-tx.pcap \
9611 options:rxq_pcap=hv1/vif1-rx.pcap \
9614 ovs-vsctl -- add-port br-int hv1-vif2 -- \
9615 set interface hv1-vif2 external-ids:iface-id=lp2 \
9616 options:tx_pcap=hv1/vif2-tx.pcap \
9617 options:rxq_pcap=hv1/vif2-rx.pcap \
9620 ovs-vsctl -- add-port br-int hv1-vif3 -- \
9621 set interface hv1-vif3 external-ids:iface-id=lp3 \
9622 options:tx_pcap=hv1/vif3-tx.pcap \
9623 options:rxq_pcap=hv1/vif3-rx.pcap \
9626 # Allow some time for ovn-northd and ovn-controller to catch up.
9627 # XXX This should be more systematic.
9633 ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \
9634 options:rxq_pcap=dummy-rx.pcap
9635 rm -f ${pcap_file}*.pcap
9636 ovs-vsctl -- set Interface $iface options:tx_pcap=${pcap_file}-tx.pcap \
9637 options:rxq_pcap=${pcap_file}-rx.pcap
9640 # Make sure that ovn-controller has installed the corresponding OF Flow.
9641 OVS_WAIT_UNTIL([test 1 = `as hv1 ovs-ofctl dump-flows br-int | grep -c "ipv6_dst=ff02::2,nw_ttl=255,icmp_type=133,icmp_code=0"`])
9643 # This shell function sends a Router Solicitation packet.
9644 # test_ipv6_ra INPORT SRC_MAC SRC_LLA ADDR_MODE MTU RA_PREFIX_OPT
9646 local inport=$1 src_mac=$2 src_lla=$3 addr_mode=$4 mtu=$5 prefix_opt=$6
9647 local request=333300000002${src_mac}86dd6000000000103aff${src_lla}ff02000000000000000000000000000285000efc000000000101${src_mac}
9651 if test $mtu != 0; then
9653 mtu_opt=05010000${mtu}
9656 if test ${#prefix_opt} != 0; then
9657 prefix_opt=${prefix_opt}fdad1234567800000000000000000000
9658 len=`expr $len + ${#prefix_opt} / 2`
9661 len=$(printf "%x" $len)
9662 local lrp_mac=fa163e000001
9663 local lrp_lla=fe80000000000000f8163efffe000001
9664 local reply=${src_mac}${lrp_mac}86dd6000000000${len}3aff${lrp_lla}${src_lla}8600XXXXff${addr_mode}ffff00000000000000000101${lrp_mac}${mtu_opt}${prefix_opt}
9665 echo $reply >> $inport.expected
9667 as hv1 ovs-appctl netdev-dummy/receive hv1-vif${inport} $request
9670 AT_CAPTURE_FILE([ofctl_monitor0.log])
9671 as hv1 ovs-ofctl monitor br-int resume --detach --no-chdir \
9672 --pidfile=ovs-ofctl0.pid 2> ofctl_monitor0.log
9674 # MTU is not set and the address mode is set to slaac
9676 default_prefix_option_config=030440c0ffffffffffffffff00000000
9677 src_mac=fa163e000002
9678 src_lla=fe80000000000000f8163efffe000002
9679 test_ipv6_ra 1 $src_mac $src_lla $addr_mode 0 $default_prefix_option_config
9681 # NXT_RESUME should be 1.
9682 OVS_WAIT_UNTIL([test 1 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
9684 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif1-tx.pcap > 1.packets
9686 cat 1.expected | cut -c -112 > expout
9687 AT_CHECK([cat 1.packets | cut -c -112], [0], [expout])
9689 # Skipping the ICMPv6 checksum.
9690 cat 1.expected | cut -c 117- > expout
9691 AT_CHECK([cat 1.packets | cut -c 117-], [0], [expout])
9694 reset_pcap_file hv1-vif1 hv1/vif1
9695 reset_pcap_file hv1-vif2 hv1/vif2
9696 reset_pcap_file hv1-vif3 hv1/vif3
9698 # Set the MTU to 1500
9699 ovn-nbctl --wait=hv set Logical_Router_Port lrp0 ipv6_ra_configs:mtu=1500
9701 # Make sure that ovn-controller has installed the corresponding OF Flow.
9702 OVS_WAIT_UNTIL([test 1 = `as hv1 ovs-ofctl dump-flows br-int | grep -c "ipv6_dst=ff02::2,nw_ttl=255,icmp_type=133,icmp_code=0"`])
9705 default_prefix_option_config=030440c0ffffffffffffffff00000000
9706 src_mac=fa163e000003
9707 src_lla=fe80000000000000f8163efffe000003
9710 test_ipv6_ra 2 $src_mac $src_lla $addr_mode $mtu $default_prefix_option_config
9712 # NXT_RESUME should be 2.
9713 OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
9715 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets
9717 cat 2.expected | cut -c -112 > expout
9718 AT_CHECK([cat 2.packets | cut -c -112], [0], [expout])
9720 # Skipping the ICMPv6 checksum.
9721 cat 2.expected | cut -c 117- > expout
9722 AT_CHECK([cat 2.packets | cut -c 117-], [0], [expout])
9725 reset_pcap_file hv1-vif1 hv1/vif1
9726 reset_pcap_file hv1-vif2 hv1/vif2
9727 reset_pcap_file hv1-vif3 hv1/vif3
9729 # Set the address mode to dhcpv6_stateful
9730 ovn-nbctl --wait=hv set Logical_Router_Port lrp0 ipv6_ra_configs:address_mode=dhcpv6_stateful
9731 # Make sure that ovn-controller has installed the corresponding OF Flow.
9732 OVS_WAIT_UNTIL([test 1 = `as hv1 ovs-ofctl dump-flows br-int | grep -c "ipv6_dst=ff02::2,nw_ttl=255,icmp_type=133,icmp_code=0"`])
9735 default_prefix_option_config=03044080ffffffffffffffff00000000
9736 src_mac=fa163e000004
9737 src_lla=fe80000000000000f8163efffe000004
9740 test_ipv6_ra 3 $src_mac $src_lla $addr_mode $mtu $default_prefix_option_config
9742 # NXT_RESUME should be 3.
9743 OVS_WAIT_UNTIL([test 3 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
9745 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif3-tx.pcap > 3.packets
9747 cat 3.expected | cut -c -112 > expout
9748 AT_CHECK([cat 3.packets | cut -c -112], [0], [expout])
9750 # Skipping the ICMPv6 checksum.
9751 cat 3.expected | cut -c 117- > expout
9752 AT_CHECK([cat 3.packets | cut -c 117-], [0], [expout])
9755 reset_pcap_file hv1-vif1 hv1/vif1
9756 reset_pcap_file hv1-vif2 hv1/vif2
9757 reset_pcap_file hv1-vif3 hv1/vif3
9759 # Set the address mode to dhcpv6_stateless
9760 ovn-nbctl --wait=hv set Logical_Router_Port lrp0 ipv6_ra_configs:address_mode=dhcpv6_stateless
9761 # Make sure that ovn-controller has installed the corresponding OF Flow.
9762 OVS_WAIT_UNTIL([test 1 = `as hv1 ovs-ofctl dump-flows br-int | grep -c "ipv6_dst=ff02::2,nw_ttl=255,icmp_type=133,icmp_code=0"`])
9765 default_prefix_option_config=030440c0ffffffffffffffff00000000
9766 src_mac=fa163e000002
9767 src_lla=fe80000000000000f8163efffe000002
9770 test_ipv6_ra 1 $src_mac $src_lla $addr_mode $mtu $default_prefix_option_config
9772 # NXT_RESUME should be 4.
9773 OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
9775 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif1-tx.pcap > 1.packets
9777 cat 1.expected | cut -c -112 > expout
9778 AT_CHECK([cat 1.packets | cut -c -112], [0], [expout])
9780 # Skipping the ICMPv6 checksum.
9781 cat 1.expected | cut -c 117- > expout
9782 AT_CHECK([cat 1.packets | cut -c 117-], [0], [expout])
9785 reset_pcap_file hv1-vif1 hv1/vif1
9786 reset_pcap_file hv1-vif2 hv1/vif2
9787 reset_pcap_file hv1-vif3 hv1/vif3
9789 # Set the address mode to invalid.
9790 ovn-nbctl --wait=hv set Logical_Router_Port lrp0 ipv6_ra_configs:address_mode=invalid
9791 # Make sure that ovn-controller has not installed any OF Flow for IPv6 ND RA.
9792 OVS_WAIT_UNTIL([test 0 = `as hv1 ovs-ofctl dump-flows br-int | grep -c "ipv6_dst=ff02::2,nw_ttl=255,icmp_type=133,icmp_code=0"`])
9795 default_prefix_option_config=""
9796 src_mac=fa163e000002
9797 src_lla=fe80000000000000f8163efffe000002
9800 test_ipv6_ra 1 $src_mac $src_lla $addr_mode $mtu $default_prefix_option_config
9802 # NXT_RESUME should be 4 only.
9803 OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
9805 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif1-tx.pcap > 1.packets
9806 AT_CHECK([cat 1.packets], [0], [])
9811 AT_SETUP([ovn -- /32 router IP address])
9812 AT_SKIP_IF([test $HAVE_PYTHON = no])
9816 # 2 LS 'foo' and 'alice' connected via router R1.
9817 # R1 connects to 'alice' with a /32 IP address. We use static routes and
9818 # nexthop to push traffic to a logical port in switch 'alice'
9822 ovn-nbctl ls-add foo
9823 ovn-nbctl ls-add alice
9826 ovn-nbctl lrp-add R1 foo 00:00:00:01:02:03 192.168.1.1/24
9827 ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo type=router \
9828 options:router-port=foo addresses=\"00:00:00:01:02:03\"
9830 # Connect alice to R1.
9831 ovn-nbctl lrp-add R1 alice 00:00:00:01:02:04 172.16.1.1/32
9832 ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port rp-alice \
9833 type=router options:router-port=alice addresses=\"00:00:00:01:02:04\"
9835 # Create logical port foo1 in foo
9836 ovn-nbctl lsp-add foo foo1 \
9837 -- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
9839 # Create logical port alice1 in alice
9840 ovn-nbctl lsp-add alice alice1 \
9841 -- lsp-set-addresses alice1 "f0:00:00:01:02:04 10.0.0.2"
9843 #install default route in R1 to use alice1's IP address as nexthop
9844 ovn-nbctl lr-route-add R1 0.0.0.0/0 10.0.0.2 alice
9846 # Create two hypervisor and create OVS ports corresponding to logical ports.
9851 ovs-vsctl add-br br-phys
9852 ovn_attach n1 br-phys 192.168.0.1
9853 ovs-vsctl -- add-port br-int hv1-vif1 -- \
9854 set interface hv1-vif1 external-ids:iface-id=foo1 \
9855 options:tx_pcap=hv1/vif1-tx.pcap \
9856 options:rxq_pcap=hv1/vif1-rx.pcap \
9861 ovs-vsctl add-br br-phys
9862 ovn_attach n1 br-phys 192.168.0.2
9863 ovs-vsctl -- add-port br-int hv2-vif1 -- \
9864 set interface hv2-vif1 external-ids:iface-id=alice1 \
9865 options:tx_pcap=hv2/vif1-tx.pcap \
9866 options:rxq_pcap=hv2/vif1-rx.pcap \
9870 # Pre-populate the hypervisors' ARP tables so that we don't lose any
9871 # packets for ARP resolution (native tunneling doesn't queue packets
9872 # for ARP resolution).
9875 # Allow some time for ovn-northd and ovn-controller to catch up.
9876 # XXX This should be more systematic.
9880 printf "%02x%02x%02x%02x" "$@"
9883 # Send ip packets between foo1 and alice1
9884 src_mac="f00000010203"
9885 dst_mac="000000010203"
9886 src_ip=`ip_to_hex 192 168 1 2`
9887 dst_ip=`ip_to_hex 10 0 0 2`
9888 packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
9890 # Send the first packet to trigger a ARP response and population of
9891 # mac_bindings table.
9892 as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
9893 OVS_WAIT_UNTIL([test `ovn-sbctl find mac_binding ip="10.0.0.2" | wc -l` -gt 0])
9894 ovn-nbctl --wait=hv sync
9896 # Packet to Expect at 'alice1'
9897 src_mac="000000010204"
9898 dst_mac="f00000010204"
9899 src_ip=`ip_to_hex 192 168 1 2`
9900 dst_ip=`ip_to_hex 10 0 0 2`
9901 echo "${dst_mac}${src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000" > expected
9903 OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
9905 OVN_CLEANUP([hv1],[hv2])
9909 AT_SETUP([ovn -- 2 HVs, 1 lport/HV, localport ports])
9910 AT_SKIP_IF([test $HAVE_PYTHON = no])
9913 ovn-nbctl ls-add ls1
9915 # Add localport to the switch
9916 ovn-nbctl lsp-add ls1 lp01
9917 ovn-nbctl lsp-set-addresses lp01 f0:00:00:00:00:01
9918 ovn-nbctl lsp-set-type lp01 localport
9925 ovs-vsctl add-br br-phys
9926 ovn_attach n1 br-phys 192.168.0.$i
9927 ovs-vsctl add-port br-int vif01 -- \
9928 set Interface vif01 external-ids:iface-id=lp01 \
9929 options:tx_pcap=hv${i}/vif01-tx.pcap \
9930 options:rxq_pcap=hv${i}/vif01-rx.pcap \
9931 ofport-request=${i}0
9933 ovs-vsctl add-port br-int vif${i}1 -- \
9934 set Interface vif${i}1 external-ids:iface-id=lp${i}1 \
9935 options:tx_pcap=hv${i}/vif${i}1-tx.pcap \
9936 options:rxq_pcap=hv${i}/vif${i}1-rx.pcap \
9937 ofport-request=${i}1
9939 ovn-nbctl lsp-add ls1 lp${i}1
9940 ovn-nbctl lsp-set-addresses lp${i}1 f0:00:00:00:00:${i}1
9941 ovn-nbctl lsp-set-port-security lp${i}1 f0:00:00:00:00:${i}1
9943 OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up lp${i}1` = xup])
9946 ovn-nbctl --wait=sb sync
9947 ovn-sbctl dump-flows
9951 # Given the name of a logical port, prints the name of the hypervisor
9952 # on which it is located.
9957 # test_packet INPORT DST SRC ETHTYPE EOUT LOUT DEFHV
9959 # This shell function causes a packet to be received on INPORT. The packet's
9960 # content has Ethernet destination DST and source SRC (each exactly 12 hex
9961 # digits) and Ethernet type ETHTYPE (4 hex digits). INPORT is specified as
9962 # logical switch port numbers, e.g. 11 for vif11.
9964 # EOUT is the end-to-end output port, that is, where the packet will end up
9965 # after possibly bouncing through one or more localnet ports. LOUT is the
9966 # logical output port, which might be a localnet port, as seen by ovn-trace
9967 # (which doesn't know what localnet ports are connected to and therefore can't
9968 # figure out the end-to-end answer).
9970 # DEFHV is the default hypervisor from where the packet is going to be sent
9971 # if the source port is a localport.
9978 local inport=$1 dst=$2 src=$3 eth=$4 eout=$5 lout=$6 defhv=$7
9981 # First try tracing the packet.
9982 uflow="inport==\"lp$inport\" && eth.dst==$dst && eth.src==$src && eth.type==0x$eth"
9983 if test $lout != drop; then
9984 echo "output(\"$lout\");"
9986 AT_CAPTURE_FILE([trace])
9987 AT_CHECK([ovn-trace --all ls1 "$uflow" | tee trace | sed '1,/Minimal trace/d'], [0], [expout])
9989 # Then actually send a packet, for an end-to-end test.
9990 local packet=$(echo $dst$src | sed 's/://g')${eth}
9991 hv=`vif_to_hv $inport`
9992 # If hypervisor 0 (localport) use the defhv parameter
9993 if test $hv = hv0; then
9997 as $hv ovs-appctl netdev-dummy/receive $vif $packet
9998 if test $eout != drop; then
9999 echo $packet >> ${eout#lp}.expected
10004 # lp11 and lp21 are on different hypervisors
10005 test_packet 11 f0:00:00:00:00:21 f0:00:00:00:00:11 1121 lp21 lp21
10006 test_packet 21 f0:00:00:00:00:11 f0:00:00:00:00:21 2111 lp11 lp11
10008 # Both VIFs should be able to reach the localport on their own HV
10009 test_packet 11 f0:00:00:00:00:01 f0:00:00:00:00:11 1101 lp01 lp01
10010 test_packet 21 f0:00:00:00:00:01 f0:00:00:00:00:21 2101 lp01 lp01
10012 # Packet sent from localport on same hv should reach the vif
10013 test_packet 01 f0:00:00:00:00:11 f0:00:00:00:00:01 0111 lp11 lp11 hv1
10014 test_packet 01 f0:00:00:00:00:21 f0:00:00:00:00:01 0121 lp21 lp21 hv2
10016 # Packet sent from localport on different hv should be dropped
10017 test_packet 01 f0:00:00:00:00:21 f0:00:00:00:00:01 0121 drop lp21 hv1
10018 test_packet 01 f0:00:00:00:00:11 f0:00:00:00:00:01 0111 drop lp11 hv2
10020 # Now check the packets actually received against the ones expected.
10023 OVN_CHECK_PACKETS([hv$i/vif$i$j-tx.pcap], [$i$j.expected])
10027 OVN_CLEANUP([hv1],[hv2])
10031 AT_SETUP([ovn -- 1 LR with HA distributed router gateway port])
10032 AT_SKIP_IF([test $HAVE_PYTHON = no])
10037 # create gateways with external network connectivity
10042 ovs-vsctl add-br br-phys
10043 ovn_attach n1 br-phys 192.168.0.$i
10044 ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
10047 ovn-nbctl ls-add inside
10048 ovn-nbctl ls-add outside
10050 # create hypervisors with a vif port each to an internal network
10055 ovs-vsctl add-br br-phys
10056 ovn_attach n1 br-phys 192.168.0.1$i
10057 ovs-vsctl -- add-port br-int hv$i-vif1 -- \
10058 set interface hv$i-vif1 external-ids:iface-id=inside$i \
10059 options:tx_pcap=hv$i/vif1-tx.pcap \
10060 options:rxq_pcap=hv$i/vif1-rx.pcap \
10063 ovn-nbctl lsp-add inside inside$i \
10064 -- lsp-set-addresses inside$i "f0:00:00:01:22:$i 192.168.1.10$i"
10070 ovn-nbctl create Logical_Router name=R1
10072 # Connect inside to R1
10073 ovn-nbctl lrp-add R1 inside 00:00:01:01:02:03 192.168.1.1/24
10074 ovn-nbctl lsp-add inside rp-inside -- set Logical_Switch_Port rp-inside \
10075 type=router options:router-port=inside \
10076 -- lsp-set-addresses rp-inside router
10078 # Connect outside to R1 as distributed router gateway port on gw1+gw2
10079 ovn-nbctl lrp-add R1 outside 00:00:02:01:02:04 192.168.0.101/24
10081 ovn-nbctl --id=@gc0 create Gateway_Chassis \
10082 name=outside_gw1 chassis_name=gw1 priority=20 -- \
10083 --id=@gc1 create Gateway_Chassis \
10084 name=outside_gw2 chassis_name=gw2 priority=10 -- \
10085 set Logical_Router_Port outside 'gateway_chassis=[@gc0,@gc1]'
10087 ovn-nbctl lsp-add outside rp-outside -- set Logical_Switch_Port rp-outside \
10088 type=router options:router-port=outside \
10089 -- lsp-set-addresses rp-outside router
10091 # Create localnet port in outside
10092 ovn-nbctl lsp-add outside ln-outside
10093 ovn-nbctl lsp-set-addresses ln-outside unknown
10094 ovn-nbctl lsp-set-type ln-outside localnet
10095 ovn-nbctl lsp-set-options ln-outside network_name=phys
10097 # Allow some time for ovn-northd and ovn-controller to catch up.
10098 # XXX This should be more systematic.
10099 ovn-nbctl --wait=hv --timeout=3 sync
10101 echo "---------NB dump-----"
10103 echo "---------------------"
10104 ovn-nbctl list logical_router
10105 echo "---------------------"
10106 ovn-nbctl list logical_router_port
10107 echo "---------------------"
10109 echo "---------SB dump-----"
10110 ovn-sbctl list datapath_binding
10111 echo "---------------------"
10112 ovn-sbctl list port_binding
10113 echo "---------------------"
10114 ovn-sbctl dump-flows
10115 echo "---------------------"
10116 ovn-sbctl list chassis
10117 ovn-sbctl list encap
10118 echo "---------------------"
10119 echo "------ Gateway_Chassis dump (SBDB) -------"
10120 ovn-sbctl list Gateway_Chassis
10121 echo "------ Port_Binding chassisredirect -------"
10122 ovn-sbctl find Port_Binding type=chassisredirect
10123 echo "-------------------------------------------"
10125 # There should be one ha_chassis_group with the name "outside"
10126 ha_chassi_grp_name=`ovn-sbctl --bare --columns name find \
10127 ha_chassis_group name="outside"`
10129 AT_CHECK([test $ha_chassi_grp_name = outside])
10131 # There should be 2 ha_chassis rows in SB DB.
10132 AT_CHECK([ovn-sbctl list ha_chassis | grep chassis | \
10133 grep -v chassis-name | awk '{print $3}' \
10134 | grep '-' | wc -l ], [0], [2
10137 ha_ch=`ovn-sbctl --bare --columns ha_chassis find ha_chassis_group`
10139 ha_ch=`echo $ha_ch | sed 's/ //g'`
10142 for i in `ovn-sbctl --bare --columns _uuid list ha_chassis | sort`
10144 ha_ch_list="$ha_ch_list $i"
10148 ha_ch_list=`echo $ha_ch_list | sed 's/ //g'`
10150 AT_CHECK([test "$ha_ch_list" = "$ha_ch"])
10152 for chassis in gw1 gw2 hv1 hv2; do
10154 echo "------ $chassis dump ----------"
10155 ovs-ofctl show br-int
10156 ovs-ofctl dump-flows br-int
10157 echo "--------------------------"
10160 for chassis in gw1 gw2 hv1 hv2; do
10162 echo "------ $chassis dump (BFD)----"
10163 echo "BFD (from $chassis):"
10164 # dump BFD config and status to the other chassis
10165 for chassis2 in gw1 gw2 hv1 hv2; do
10166 if [[ "$chassis" != "$chassis2" ]]; then
10167 echo " -> $chassis2:"
10168 echo " $(ovs-vsctl --bare --columns bfd,bfd_status find Interface name=ovn-$chassis2-0)"
10171 echo "--------------------------"
10177 hv1_gw1_ofport=$(as hv1 ovs-vsctl --bare --columns ofport find Interface name=ovn-gw1-0)
10178 hv1_gw2_ofport=$(as hv1 ovs-vsctl --bare --columns ofport find Interface name=ovn-gw2-0)
10179 hv2_gw1_ofport=$(as hv2 ovs-vsctl --bare --columns ofport find Interface name=ovn-gw1-0)
10180 hv2_gw2_ofport=$(as hv2 ovs-vsctl --bare --columns ofport find Interface name=ovn-gw2-0)
10182 echo $hv1_gw1_ofport
10183 echo $hv1_gw2_ofport
10184 echo $hv2_gw1_ofport
10185 echo $hv2_gw2_ofport
10188 as hv1 ovs-ofctl dump-flows br-int table=32
10191 as hv2 ovs-ofctl dump-flows br-int table=32
10193 gw1_chassis=$(ovn-sbctl --bare --columns=_uuid find Chassis name=gw1)
10194 gw2_chassis=$(ovn-sbctl --bare --columns=_uuid find Chassis name=gw2)
10196 OVS_WAIT_UNTIL([as hv1 ovs-ofctl dump-flows br-int table=32 | \
10197 grep active_backup | grep slaves:$hv1_gw1_ofport,$hv1_gw2_ofport \
10201 OVS_WAIT_UNTIL([as hv2 ovs-ofctl dump-flows br-int table=32 | \
10202 grep active_backup | grep slaves:$hv2_gw1_ofport,$hv2_gw2_ofport \
10206 # make sure that flows for handling the outside router port reside on gw1
10207 OVS_WAIT_UNTIL([as gw1 ovs-ofctl dump-flows br-int table=25 | \
10208 grep 00:00:02:01:02:04 | wc -l], [0], [[1
10210 OVS_WAIT_UNTIL([as gw2 ovs-ofctl dump-flows br-int table=25 | \
10211 grep 00:00:02:01:02:04 | wc -l], [0], [[0
10214 # make sure ARP responder flows for outside router port reside on gw1 too
10215 OVS_WAIT_UNTIL([as gw1 ovs-ofctl dump-flows br-int table=9 | \
10216 grep arp_tpa=192.168.0.101 | wc -l], [0], [[1
10218 OVS_WAIT_UNTIL([as gw2 ovs-ofctl dump-flows br-int table=9 | grep arp_tpa=192.168.0.101 | wc -l], [0], [[0
10221 # check that the chassis redirect port has been claimed by the gw1 chassis
10222 OVS_WAIT_UNTIL([ovn-sbctl --columns chassis --bare find Port_Binding \
10223 logical_port=cr-outside | grep $gw1_chassis | wc -l], [0],[[1
10226 hv1_ch_uuid=`ovn-sbctl --bare --columns _uuid find chassis name="hv1"`
10227 hv2_ch_uuid=`ovn-sbctl --bare --columns _uuid find chassis name="hv2"`
10230 for i in `ovn-sbctl --bare --columns _uuid list chassis | sort`
10232 if test $i = $hv1_ch_uuid; then
10233 exp_ref_ch_list="${exp_ref_ch_list}$i"
10234 elif test $i = $hv2_ch_uuid; then
10235 exp_ref_ch_list="${exp_ref_ch_list}$i"
10240 [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find ha_chassis_group | sort`
10242 ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
10243 test "$exp_ref_ch_list" = "$ref_ch_list"])
10246 # at this point, we invert the priority of the gw chassis between gw1 and gw2
10248 ovn-nbctl --id=@gc0 create Gateway_Chassis \
10249 name=outside_gw1 chassis_name=gw1 priority=10 -- \
10250 --id=@gc1 create Gateway_Chassis \
10251 name=outside_gw2 chassis_name=gw2 priority=20 -- \
10252 set Logical_Router_Port outside 'gateway_chassis=[@gc0,@gc1]'
10255 # XXX: Let the change propagate down to the ovn-controllers
10256 ovn-nbctl --wait=hv --timeout=3 sync
10258 # we make sure that the hypervisors noticed, and inverted the slave ports
10259 OVS_WAIT_UNTIL([as hv1 ovs-ofctl dump-flows br-int table=32 | \
10260 grep active_backup | grep slaves:$hv1_gw2_ofport,$hv1_gw1_ofport \
10264 OVS_WAIT_UNTIL([as hv2 ovs-ofctl dump-flows br-int table=32 | \
10265 grep active_backup | grep slaves:$hv2_gw2_ofport,$hv2_gw1_ofport \
10269 # check that the chassis redirect port has been reclaimed by the gw2 chassis
10270 OVS_WAIT_UNTIL([ovn-sbctl --columns chassis --bare find Port_Binding \
10271 logical_port=cr-outside | grep $gw2_chassis | wc -l], [0],[[1
10274 # check BFD enablement on tunnel ports from gw1 #########
10276 for chassis in gw2 hv1 hv2; do
10277 echo "checking gw1 -> $chassis"
10278 AT_CHECK([ovs-vsctl --bare --columns bfd find Interface name=ovn-$chassis-0],[0],
10284 # check BFD enablement on tunnel ports from gw2 ##########
10286 for chassis in gw1 hv1 hv2; do
10287 echo "checking gw2 -> $chassis"
10288 AT_CHECK([ovs-vsctl --bare --columns bfd find Interface name=ovn-$chassis-0],[0],
10293 # check BFD enablement on tunnel ports from hv1 ###########
10295 for chassis in gw1 gw2; do
10296 echo "checking hv1 -> $chassis"
10297 AT_CHECK([ovs-vsctl --bare --columns bfd find Interface name=ovn-$chassis-0],[0],
10301 # make sure BFD is not enabled to hv2, we don't need it
10302 AT_CHECK([ovs-vsctl --bare --columns bfd find Interface name=ovn-hv2-0],[0],
10307 # check BFD enablement on tunnel ports from hv2 ##########
10309 for chassis in gw1 gw2; do
10310 echo "checking hv2 -> $chassis"
10311 AT_CHECK([ovs-vsctl --bare --columns bfd find Interface name=ovn-$chassis-0],[0],
10315 # make sure BFD is not enabled to hv1, we don't need it
10316 AT_CHECK([ovs-vsctl --bare --columns bfd find Interface name=ovn-hv1-0],[0],
10320 # make sure that flows for handling the outside router port reside on gw2 now
10321 OVS_WAIT_UNTIL([as gw2 ovs-ofctl dump-flows br-int table=25 | \
10322 grep 00:00:02:01:02:04 | wc -l], [0], [[1
10324 OVS_WAIT_UNTIL([as gw1 ovs-ofctl dump-flows br-int table=25 | \
10325 grep 00:00:02:01:02:04 | wc -l], [0], [[0
10328 # disconnect GW2 from the network, GW1 should take over
10330 port=${sandbox}_br-phys
10331 as main ovs-vsctl del-port n1 $port
10335 # make sure that flows for handling the outside router port reside on gw2 now
10336 OVS_WAIT_UNTIL([as gw1 ovs-ofctl dump-flows br-int table=25 | \
10337 grep 00:00:02:01:02:04 | wc -l], [0], [[1
10339 OVS_WAIT_UNTIL([as gw2 ovs-ofctl dump-flows br-int table=25 | \
10340 grep 00:00:02:01:02:04 | wc -l], [0], [[0
10343 # check that the chassis redirect port has been reclaimed by the gw1 chassis
10344 OVS_WAIT_UNTIL([ovn-sbctl --columns chassis --bare find Port_Binding \
10345 logical_port=cr-outside | grep $gw1_chassis | wc -l], [0],[[1
10348 ovn-nbctl --wait=hv set NB_Global . options:"bfd-min-rx"=2000
10350 for chassis in gw1 hv1 hv2; do
10351 echo "checking gw2 -> $chassis"
10353 bfd_cfg=$(ovs-vsctl --bare --columns bfd find Interface name=ovn-$chassis-0)
10354 test "$bfd_cfg" = "enable=true min_rx=2000"
10357 ovn-nbctl --wait=hv set NB_Global . options:"bfd-min-tx"=1500
10358 for chassis in gw1 hv1 hv2; do
10359 echo "checking gw2 -> $chassis"
10361 bfd_cfg=$(ovs-vsctl --bare --columns bfd find Interface name=ovn-$chassis-0)
10362 test "$bfd_cfg" = "enable=true min_rx=2000 min_tx=1500"
10365 ovn-nbctl remove NB_Global . options "bfd-min-rx"
10366 ovn-nbctl --wait=hv set NB_Global . options:"bfd-mult"=5
10367 for chassis in gw1 hv1 hv2; do
10368 echo "checking gw2 -> $chassis"
10370 bfd_cfg=$(ovs-vsctl --bare --columns bfd find Interface name=ovn-$chassis-0)
10371 test "$bfd_cfg" = "enable=true min_tx=1500 mult=5"
10375 # Delete the inside1 vif. The ref_chassis in ha_chassis_group shouldn't have
10376 # reference to hv1.
10377 as hv1 ovs-vsctl del-port hv1-vif1
10380 [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find ha_chassis_group | sort`
10382 ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
10383 test "$hv2_ch_uuid" = "$ref_ch_list"])
10385 # Delete the inside2 vif.
10388 echo "Deleting hv2-vif1"
10389 as hv2 ovs-vsctl del-port hv2-vif1
10391 # ref_chassis of ha_chassis_group should be empty
10393 [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find ha_chassis_group | sort`
10395 ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
10397 test "$exp_ref_ch_list" = "$ref_ch_list"])
10399 # Delete the Gateway_Chassis for lrp - outside
10400 ovn-nbctl clear Logical_Router_Port outside gateway_chassis
10402 # There shoud be no ha_chassis_group rows in SB DB.
10403 OVS_WAIT_UNTIL([test 0 = `ovn-sbctl list ha_chassis_group | wc -l`])
10404 OVS_WAIT_UNTIL([test 0 = `ovn-sbctl list ha_chassis | wc -l`])
10406 ovn-nbctl remove NB_Global . options "bfd-min-rx"
10407 ovn-nbctl remove NB_Global . options "bfd-min-tx"
10408 ovn-nbctl remove NB_Global . options "bfd-mult"
10410 # Now test with HA chassis group instead of Gateway chassis in NB DB
10411 ovn-nbctl --wait=sb ha-chassis-group-add hagrp1
10413 ovn-nbctl list ha_chassis_group
10414 ovn-nbctl --bare --columns _uuid find ha_chassis_group name=hagrp1
10415 hagrp1_uuid=`ovn-nbctl --bare --columns _uuid find ha_chassis_group name=hagrp1`
10416 ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 gw1 30
10417 ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 gw2 20
10419 # ovn-northd should not create HA chassis group and HA chassis rows
10420 # unless the HA chassis group in OVN NB DB is associated to
10421 # a logical router port.
10422 OVS_WAIT_UNTIL([test 0 = `ovn-sbctl list ha_chassis | wc -l`])
10424 # Associate hagrp1 to outside logical router port
10425 ovn-nbctl set Logical_Router_Port outside ha_chassis_group=$hagrp1_uuid
10427 OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns _uuid \
10428 find ha_chassis_group | wc -l`])
10430 OVS_WAIT_UNTIL([test 2 = `ovn-sbctl list ha_chassis | grep chassis | \
10431 grep -v chassis-name | wc -l`])
10433 OVS_WAIT_UNTIL([as hv1 ovs-ofctl dump-flows br-int table=32 | \
10434 grep active_backup | grep slaves:$hv1_gw1_ofport,$hv1_gw2_ofport \
10438 OVS_WAIT_UNTIL([as hv2 ovs-ofctl dump-flows br-int table=32 | \
10439 grep active_backup | grep slaves:$hv2_gw1_ofport,$hv2_gw2_ofport \
10443 # make sure that flows for handling the outside router port reside on gw1
10444 OVS_WAIT_UNTIL([as gw1 ovs-ofctl dump-flows br-int table=24 | \
10445 grep 00:00:02:01:02:04 | wc -l], [0], [[1
10447 OVS_WAIT_UNTIL([as gw2 ovs-ofctl dump-flows br-int table=24 | \
10448 grep 00:00:02:01:02:04 | wc -l], [0], [[0
10451 # make sure ARP responder flows for outside router port reside on gw1 too
10452 OVS_WAIT_UNTIL([as gw1 ovs-ofctl dump-flows br-int table=9 | \
10453 grep arp_tpa=192.168.0.101 | wc -l], [0], [[1
10455 OVS_WAIT_UNTIL([as gw2 ovs-ofctl dump-flows br-int table=9 | grep arp_tpa=192.168.0.101 | wc -l], [0], [[0
10458 # check that the chassis redirect port has been claimed by the gw1 chassis
10459 OVS_WAIT_UNTIL([ovn-sbctl --columns chassis --bare find Port_Binding \
10460 logical_port=cr-outside | grep $gw1_chassis | wc -l], [0],[[1
10463 # Re add the ovs ports.
10466 ovs-vsctl -- add-port br-int hv$i-vif1 -- \
10467 set interface hv$i-vif1 external-ids:iface-id=inside$i \
10468 options:tx_pcap=hv$i/vif1-tx.pcap \
10469 options:rxq_pcap=hv$i/vif1-rx.pcap \
10473 hv1_ch_uuid=`ovn-sbctl --bare --columns _uuid find chassis name="hv1"`
10474 hv2_ch_uuid=`ovn-sbctl --bare --columns _uuid find chassis name="hv2"`
10477 for i in `ovn-sbctl --bare --columns _uuid list chassis | sort`
10479 if test $i = $hv1_ch_uuid; then
10480 exp_ref_ch_list="${exp_ref_ch_list}$i"
10481 elif test $i = $hv2_ch_uuid; then
10482 exp_ref_ch_list="${exp_ref_ch_list}$i"
10487 [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find ha_chassis_group | sort`
10489 ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
10490 test "$exp_ref_ch_list" = "$ref_ch_list"])
10492 # Increase the priority of gw2
10493 ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 gw2 40
10495 OVS_WAIT_UNTIL([as hv1 ovs-ofctl dump-flows br-int table=32 | \
10496 grep active_backup | grep slaves:$hv1_gw2_ofport,$hv1_gw1_ofport \
10500 OVS_WAIT_UNTIL([as hv2 ovs-ofctl dump-flows br-int table=32 | \
10501 grep active_backup | grep slaves:$hv2_gw2_ofport,$hv2_gw1_ofport \
10505 # check that the chassis redirect port has been reclaimed by the gw2 chassis
10506 OVS_WAIT_UNTIL([ovn-sbctl --columns chassis --bare find Port_Binding \
10507 logical_port=cr-outside | grep $gw2_chassis | wc -l], [0],[[1
10510 # check BFD enablement on tunnel ports from gw1 #########
10512 for chassis in gw2 hv1 hv2; do
10513 echo "checking gw1 -> $chassis"
10514 AT_CHECK([ovs-vsctl --bare --columns bfd find Interface name=ovn-$chassis-0],[0],
10519 # check BFD enablement on tunnel ports from gw2 ##########
10521 for chassis in gw1 hv1 hv2; do
10522 echo "checking gw2 -> $chassis"
10523 AT_CHECK([ovs-vsctl --bare --columns bfd find Interface name=ovn-$chassis-0],[0],
10528 # check BFD enablement on tunnel ports from hv1 ###########
10530 for chassis in gw1 gw2; do
10531 echo "checking hv1 -> $chassis"
10532 AT_CHECK([ovs-vsctl --bare --columns bfd find Interface name=ovn-$chassis-0],[0],
10536 # make sure BFD is not enabled to hv2, we don't need it
10537 AT_CHECK([ovs-vsctl --bare --columns bfd find Interface name=ovn-hv2-0],[0],
10541 # check BFD enablement on tunnel ports from hv2 ##########
10543 for chassis in gw1 gw2; do
10544 echo "checking hv2 -> $chassis"
10545 AT_CHECK([ovs-vsctl --bare --columns bfd find Interface name=ovn-$chassis-0],[0],
10549 # make sure BFD is not enabled to hv1, we don't need it
10550 AT_CHECK([ovs-vsctl --bare --columns bfd find Interface name=ovn-hv1-0],[0],
10554 # make sure that flows for handling the outside router port reside on gw2 now
10555 OVS_WAIT_UNTIL([as gw2 ovs-ofctl dump-flows br-int table=24 | \
10556 grep 00:00:02:01:02:04 | wc -l], [0], [[1
10558 OVS_WAIT_UNTIL([as gw1 ovs-ofctl dump-flows br-int table=24 | \
10559 grep 00:00:02:01:02:04 | wc -l], [0], [[0
10562 # disconnect GW2 from the network, GW1 should take over
10564 port=${sandbox}_br-phys
10565 as main ovs-vsctl del-port n1 $port
10569 # make sure that flows for handling the outside router port reside on gw2 now
10570 OVS_WAIT_UNTIL([as gw1 ovs-ofctl dump-flows br-int table=24 | \
10571 grep 00:00:02:01:02:04 | wc -l], [0], [[1
10573 OVS_WAIT_UNTIL([as gw2 ovs-ofctl dump-flows br-int table=24 | \
10574 grep 00:00:02:01:02:04 | wc -l], [0], [[0
10577 # check that the chassis redirect port has been reclaimed by the gw1 chassis
10578 OVS_WAIT_UNTIL([ovn-sbctl --columns chassis --bare find Port_Binding \
10579 logical_port=cr-outside | grep $gw1_chassis | wc -l], [0],[[1
10582 OVN_CLEANUP([gw1],[gw2],[hv1],[hv2])
10586 AT_SETUP([ovn -- send gratuitous ARP for NAT rules on HA distributed router])
10587 AT_SKIP_IF([test $HAVE_PYTHON = no])
10589 ovn-nbctl ls-add ls0
10590 ovn-nbctl ls-add ls1
10591 ovn-nbctl create Logical_Router name=lr0
10592 ovn-nbctl lrp-add lr0 lrp0 f0:00:00:00:00:01 192.168.0.100/24
10594 ovn-nbctl --id=@gc0 create Gateway_Chassis \
10595 name=outside_gw1 chassis_name=hv2 priority=10 -- \
10596 --id=@gc1 create Gateway_Chassis \
10597 name=outside_gw2 chassis_name=hv3 priority=1 -- \
10598 set Logical_Router_Port lrp0 'gateway_chassis=[@gc0,@gc1]'
10600 ovn-nbctl lsp-add ls0 lrp0-rp -- set Logical_Switch_Port lrp0-rp \
10601 type=router options:router-port=lrp0 addresses="router"
10602 ovn-nbctl lrp-add lr0 lrp1 f0:00:00:00:00:02 10.0.0.1/24
10603 ovn-nbctl lsp-add ls1 lrp1-rp -- set Logical_Switch_Port lrp1-rp \
10604 type=router options:router-port=lrp1 addresses="router"
10607 AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 192.168.0.100 10.0.0.0/24])
10612 ovs-vsctl add-br br-phys
10613 ovn_attach n1 br-phys 192.168.0.1
10614 AT_CHECK([ovs-vsctl set Open_vSwitch . external-ids:ovn-bridge-mappings=physnet1:br-phys])
10615 AT_CHECK([ovs-vsctl add-port br-phys snoopvif -- set Interface snoopvif options:tx_pcap=hv1/snoopvif-tx.pcap options:rxq_pcap=hv1/snoopvif-rx.pcap])
10619 ovs-vsctl add-br br-phys
10620 ovn_attach n1 br-phys 192.168.0.2
10621 AT_CHECK([as hv2 ovs-vsctl set Open_vSwitch . external-ids:ovn-bridge-mappings=physnet1:br-phys])
10625 ovs-vsctl add-br br-phys
10626 ovn_attach n1 br-phys 192.168.0.3
10627 AT_CHECK([as hv3 ovs-vsctl set Open_vSwitch . external-ids:ovn-bridge-mappings=physnet1:br-phys])
10629 # Create a localnet port.
10630 AT_CHECK([ovn-nbctl lsp-add ls0 ln_port])
10631 AT_CHECK([ovn-nbctl lsp-set-addresses ln_port unknown])
10632 AT_CHECK([ovn-nbctl lsp-set-type ln_port localnet])
10633 AT_CHECK([ovn-nbctl lsp-set-options ln_port network_name=physnet1])
10635 # wait for earlier changes to take effect
10636 AT_CHECK([ovn-nbctl --timeout=3 --wait=hv sync], [0], [ignore])
10638 reset_pcap_file() {
10641 ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \
10642 options:rxq_pcap=dummy-rx.pcap
10643 rm -f ${pcap_file}*.pcap
10644 ovs-vsctl -- set Interface $iface options:tx_pcap=${pcap_file}-tx.pcap \
10645 options:rxq_pcap=${pcap_file}-rx.pcap
10648 as hv1 reset_pcap_file snoopvif hv1/snoopvif
10649 as hv2 reset_pcap_file br-phys_n1 hv2/br-phys_n1
10650 as hv3 reset_pcap_file br-phys_n1 hv3/br-phys_n1
10651 # add nat-addresses option
10652 ovn-nbctl --wait=hv lsp-set-options lrp0-rp router-port=lrp0 nat-addresses="router"
10654 # Wait for packets to be received through hv2.
10655 OVS_WAIT_UNTIL([test `wc -c < "hv1/snoopvif-tx.pcap"` -ge 100])
10657 sed 's/\(00\)\{1,\}$//'
10660 only_broadcast_from_lrp1() {
10661 grep "fffffffffffff00000000001"
10664 garp="fffffffffffff0000000000108060001080006040001f00000000001c0a80064000000000000c0a80064"
10665 echo $garp > expout
10667 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/snoopvif-tx.pcap | trim_zeros | only_broadcast_from_lrp1 | uniq > hv1_snoop_tx
10668 echo "packets on hv1-snoopvif:"
10670 AT_CHECK([sort hv1_snoop_tx], [0], [expout])
10671 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv2/br-phys_n1-tx.pcap | trim_zeros | only_broadcast_from_lrp1 | uniq > hv2_br_phys_tx
10672 echo "packets on hv2 br-phys tx"
10674 AT_CHECK([grep $garp hv2_br_phys_tx | sort], [0], [expout])
10675 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv3/br-phys_n1-tx.pcap | trim_zeros | only_broadcast_from_lrp1 | uniq > hv3_br_phys_tx
10676 echo "packets on hv3 br-phys tx"
10678 AT_CHECK([grep $garp hv3_br_phys_tx | sort], [0], [])
10681 # at this point, we invert the priority of the gw chassis between hv2 and hv3
10683 ovn-nbctl --wait=hv \
10684 --id=@gc0 create Gateway_Chassis \
10685 name=outside_gw1 chassis_name=hv2 priority=1 -- \
10686 --id=@gc1 create Gateway_Chassis \
10687 name=outside_gw2 chassis_name=hv3 priority=10 -- \
10688 set Logical_Router_Port lrp0 'gateway_chassis=[@gc0,@gc1]'
10691 as hv1 reset_pcap_file snoopvif hv1/snoopvif
10692 as hv2 reset_pcap_file br-phys_n1 hv2/br-phys_n1
10693 as hv3 reset_pcap_file br-phys_n1 hv3/br-phys_n1
10695 # Wait for packets to be received.
10696 OVS_WAIT_UNTIL([test `wc -c < "hv1/snoopvif-tx.pcap"` -ge 100])
10698 sed 's/\(00\)\{1,\}$//'
10701 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/snoopvif-tx.pcap | trim_zeros | only_broadcast_from_lrp1 | uniq > hv1_snoopvif_tx
10702 AT_CHECK([sort hv1_snoopvif_tx], [0], [expout])
10703 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv3/br-phys_n1-tx.pcap | trim_zeros | only_broadcast_from_lrp1 | uniq > hv3_br_phys_tx
10704 AT_CHECK([grep $garp hv3_br_phys_tx | sort], [0], [expout])
10705 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv2/br-phys_n1-tx.pcap | trim_zeros | only_broadcast_from_lrp1 | uniq > hv2_br_phys_tx
10706 AT_CHECK([grep $garp hv2_br_phys_tx | sort], [0], [])
10708 # change localnet port tag.
10709 AT_CHECK([ovn-nbctl set Logical_Switch_Port ln_port tag=2014])
10711 # wait for earlier changes to take effect
10712 AT_CHECK([ovn-nbctl --timeout=3 --wait=hv sync], [0], [ignore])
10714 # update nat-addresses option
10715 ovn-nbctl --wait=hv lsp-set-options lrp0-rp router-port=lrp0
10716 ovn-nbctl --wait=hv lsp-set-options lrp0-rp router-port=lrp0 nat-addresses="router"
10718 as hv1 reset_pcap_file snoopvif hv1/snoopvif
10719 as hv2 reset_pcap_file br-phys_n1 hv2/br-phys_n1
10720 as hv3 reset_pcap_file br-phys_n1 hv3/br-phys_n1
10722 # Wait for packets to be received.
10723 OVS_WAIT_UNTIL([test `wc -c < "hv1/snoopvif-tx.pcap"` -ge 100])
10725 sed 's/\(00\)\{1,\}$//'
10728 garp="fffffffffffff00000000001810007de08060001080006040001f00000000001c0a80064000000000000c0a80064"
10729 echo $garp > expout
10731 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/snoopvif-tx.pcap | trim_zeros | only_broadcast_from_lrp1 | uniq > hv1_snoopvif_tx
10732 AT_CHECK([sort hv1_snoopvif_tx], [0], [expout])
10733 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv3/br-phys_n1-tx.pcap | trim_zeros | only_broadcast_from_lrp1 | uniq > hv3_br_phys_tx
10734 AT_CHECK([grep $garp hv3_br_phys_tx | sort], [0], [expout])
10735 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv2/br-phys_n1-tx.pcap | trim_zeros | only_broadcast_from_lrp1 | uniq > hv2_br_phys_tx
10736 AT_CHECK([grep $garp hv2_br_phys_tx | sort], [0], [])
10738 OVN_CLEANUP([hv1],[hv2],[hv3])
10742 AT_SETUP([ovn -- ensure one gw controller restart in HA doesn't bounce the master])
10743 AT_SKIP_IF([test $HAVE_PYTHON = no])
10748 # create two gateways with external network connectivity
10752 ovs-vsctl add-br br-phys
10753 ovn_attach n1 br-phys 192.168.0.$i
10754 ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
10757 ovn-nbctl ls-add inside
10758 ovn-nbctl ls-add outside
10760 # create one hypervisors with a vif port the internal network
10763 ovs-vsctl add-br br-phys
10764 ovn_attach n1 br-phys 192.168.0.11
10765 ovs-vsctl -- add-port br-int hv1-vif1 -- \
10766 set interface hv1-vif1 external-ids:iface-id=inside1 \
10767 options:tx_pcap=hv1/vif1-tx.pcap \
10768 options:rxq_pcap=hv1/vif1-rx.pcap \
10771 ovn-nbctl lsp-add inside inside1 \
10772 -- lsp-set-addresses inside1 "f0:00:00:01:22:01 192.168.1.101"
10777 ovn-nbctl create Logical_Router name=R1
10779 # Connect inside to R1
10780 ovn-nbctl lrp-add R1 inside 00:00:01:01:02:03 192.168.1.1/24
10781 ovn-nbctl lsp-add inside rp-inside -- set Logical_Switch_Port rp-inside \
10782 type=router options:router-port=inside \
10783 -- lsp-set-addresses rp-inside router
10785 # Connect outside to R1 as distributed router gateway port on gw1+gw2
10786 ovn-nbctl lrp-add R1 outside 00:00:02:01:02:04 192.168.0.101/24
10788 ovn-nbctl --id=@gc0 create Gateway_Chassis \
10789 name=outside_gw1 chassis_name=gw1 priority=20 -- \
10790 --id=@gc1 create Gateway_Chassis \
10791 name=outside_gw2 chassis_name=gw2 priority=10 -- \
10792 set Logical_Router_Port outside 'gateway_chassis=[@gc0,@gc1]'
10794 ovn-nbctl lsp-add outside rp-outside -- set Logical_Switch_Port rp-outside \
10795 type=router options:router-port=outside \
10796 -- lsp-set-addresses rp-outside router
10798 # Create localnet port in outside
10799 ovn-nbctl lsp-add outside ln-outside
10800 ovn-nbctl lsp-set-addresses ln-outside unknown
10801 ovn-nbctl lsp-set-type ln-outside localnet
10802 ovn-nbctl lsp-set-options ln-outside network_name=phys
10804 # Allow some time for ovn-northd and ovn-controller to catch up.
10805 ovn-nbctl --wait=hv --timeout=3 sync
10807 # currently when ovn-controller is restarted, the old entry is deleted
10808 # and a new one is created, which leaves the Gateway_Chassis with
10809 # an empty chassis for a while. NOTE: restarting ovn-controller in tests
10810 # doesn't have the same effect because "name" is conserved, and the
10811 # Chassis entry is not replaced.
10813 > gw1/ovn-controller.log
10815 gw2_chassis=$(ovn-sbctl --bare --columns=_uuid find Chassis name=gw2)
10816 ovn-sbctl destroy Chassis $gw2_chassis
10818 OVS_WAIT_UNTIL([test 0 = `grep -c "Releasing lport" gw1/ovn-controller.log`])
10820 OVN_CLEANUP([gw1],[gw2],[hv1])
10824 AT_SETUP([ovn -- IPv6 Neighbor Solicitation for unknown MAC])
10825 AT_KEYWORDS([ovn-nd_ns for unknown mac])
10826 AT_SKIP_IF([test $HAVE_PYTHON = no])
10829 ovn-nbctl ls-add sw0_ip6
10830 ovn-nbctl lsp-add sw0_ip6 sw0_ip6-port1
10831 ovn-nbctl lsp-set-addresses sw0_ip6-port1 \
10832 "50:64:00:00:00:02 aef0::5264:00ff:fe00:0002"
10834 ovn-nbctl lsp-set-port-security sw0_ip6-port1 \
10835 "50:64:00:00:00:02 aef0::5264:00ff:fe00:0002"
10837 ovn-nbctl lr-add lr0_ip6
10838 ovn-nbctl lrp-add lr0_ip6 lrp0_ip6 00:00:00:00:af:01 aef0:0:0:0:0:0:0:0/64
10839 ovn-nbctl lsp-add sw0_ip6 lrp0_ip6-attachment
10840 ovn-nbctl lsp-set-type lrp0_ip6-attachment router
10841 ovn-nbctl lsp-set-addresses lrp0_ip6-attachment router
10842 ovn-nbctl lsp-set-options lrp0_ip6-attachment router-port=lrp0_ip6
10843 ovn-nbctl set logical_router_port lrp0_ip6 ipv6_ra_configs:address_mode=slaac
10845 ovn-nbctl ls-add public
10846 ovn-nbctl lsp-add public ln-public
10847 ovn-nbctl lsp-set-addresses ln-public unknown
10848 ovn-nbctl lsp-set-type ln-public localnet
10849 ovn-nbctl lsp-set-options ln-public network_name=phys
10851 ovn-nbctl lrp-add lr0_ip6 ip6_public 00:00:02:01:02:04 \
10852 2001:db8:1:0:200:02ff:fe01:0204/64 \
10853 -- set Logical_Router_port ip6_public options:redirect-chassis="hv1"
10855 #install static route
10856 ovn-nbctl -- --id=@lrt create Logical_Router_Static_Route \
10857 ip_prefix="\:\:/0" nexthop="2001\:db8\:1\:0\:200\:02ff\:fe01\:1305" \
10858 -- add Logical_Router lr0_ip6 static_routes @lrt
10860 ovn-nbctl lsp-add public rp-ip6_public -- set Logical_Switch_Port \
10861 rp-ip6_public type=router options:router-port=ip6_public \
10862 -- lsp-set-addresses rp-ip6_public router
10867 ovs-vsctl add-br br-phys
10868 ovn_attach n1 br-phys 192.168.0.2
10870 ovs-vsctl -- add-port br-int hv1-vif1 -- \
10871 set interface hv1-vif1 external-ids:iface-id=sw0_ip6-port1 \
10872 options:tx_pcap=hv1/vif1-tx.pcap \
10873 options:rxq_pcap=hv1/vif1-rx.pcap \
10875 ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
10877 OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw0_ip6-port1` = xup])
10879 # There should be 2 Neighbor Advertisement flows for the router port
10880 # aef0:: ip address in logical switch pipeline with action nd_na_router.
10881 AT_CHECK([ovn-sbctl dump-flows sw0_ip6 | grep ls_in_arp_rsp | \
10882 grep "nd_na_router" | wc -l], [0], [2
10885 # There should be 4 Neighbor Advertisement flows with action nd_na_router
10886 # in the router pipeline for the router lr0_ip6.
10887 AT_CHECK([ovn-sbctl dump-flows lr0_ip6 | grep nd_na_router | \
10891 cr_uuid=`ovn-sbctl find port_binding logical_port=cr-ip6_public | grep _uuid | cut -f2 -d ":"`
10893 # There is only one chassis.
10894 chassis_uuid=`ovn-sbctl list chassis | grep _uuid | cut -f2 -d ":"`
10895 OVS_WAIT_UNTIL([test $chassis_uuid = `ovn-sbctl get port_binding $cr_uuid chassis`])
10898 sed 's/\(00\)\{1,\}$//'
10901 reset_pcap_file() {
10904 ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \
10905 options:rxq_pcap=dummy-rx.pcap
10906 rm -f ${pcap_file}*.pcap
10907 ovs-vsctl -- set Interface $iface options:tx_pcap=${pcap_file}-tx.pcap \
10908 options:rxq_pcap=${pcap_file}-rx.pcap
10911 # Test the IPv6 Neighbor Solicitation (NS) - nd_ns action for unknown MAC
10912 # addresses. ovn-controller should generate an IPv6 NS request for IPv6
10913 # packets whose MAC is unknown (in the ARP_REQUEST router pipeline stage.
10914 # test_ipv6 INPORT SRC_MAC DST_MAC SRC_IP DST_IP OUTPORT...
10915 # This function sends ipv6 packet
10917 local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
10918 local dst_mcast_mac=$6 mcast_node_ip=$7 nd_target=$8
10920 local packet=${dst_mac}${src_mac}86dd6000000000083aff${src_ip}${dst_ip}
10921 packet=${packet}8000000000000000
10923 src_mac=000002010204
10924 expected_packet=${dst_mcast_mac}${src_mac}86dd6000000000203aff${src_ip}
10925 expected_packet=${expected_packet}${mcast_node_ip}8700XXXX00000000
10926 expected_packet=${expected_packet}${nd_target}0101${src_mac}
10928 as hv1 ovs-appctl netdev-dummy/receive hv1-vif${inport} $packet
10929 rm -f ipv6_ns.expected
10930 echo $expected_packet >> ipv6_ns.expected
10933 src_mac=506400000002
10934 dst_mac=00000000af01
10935 src_ip=aef0000000000000526400fffe000002
10936 dst_ip=20010db800010000020002fffe010205
10937 dst_mcast_mac=3333ff010205
10938 mcast_node_ip=ff0200000000000000000001ff010205
10939 nd_target=20010db800010000020002fffe010205
10940 # Send an IPv6 packet. Generated IPv6 Neighbor solicitation packet
10941 # should be received by the ports attached to br-phys.
10942 test_ipv6 1 $src_mac $dst_mac $src_ip $dst_ip $dst_mcast_mac \
10943 $mcast_node_ip $nd_target
10945 OVS_WAIT_WHILE([test 24 = $(wc -c hv1/br-phys_n1-tx.pcap | cut -d " " -f1)])
10946 OVS_WAIT_WHILE([test 24 = $(wc -c hv1/br-phys-tx.pcap | cut -d " " -f1)])
10948 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/br-phys_n1-tx.pcap | \
10949 trim_zeros > 1.packets
10950 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/br-phys-tx.pcap | \
10951 trim_zeros > 2.packets
10953 cat ipv6_ns.expected | cut -c -112 > expout
10954 AT_CHECK([cat 1.packets | cut -c -112], [0], [expout])
10955 AT_CHECK([cat 2.packets | cut -c -112], [0], [expout])
10957 # Skipping the ICMPv6 checksum
10958 cat ipv6_ns.expected | cut -c 117- > expout
10959 AT_CHECK([cat 1.packets | cut -c 117-], [0], [expout])
10960 AT_CHECK([cat 2.packets | cut -c 117-], [0], [expout])
10962 # Now send a packet with destination ip other than
10963 # 2001:db8:1:0:200:02ff:fe01:0204/64 prefix.
10964 reset_pcap_file br-phys_n1 hv1/br-phys_n1
10965 reset_pcap_file br-phys hv1/br-phys
10967 src_mac=506400000002
10968 dst_mac=00000000af01
10969 src_ip=aef0000000000000526400fffe000002
10970 dst_ip=20020ab8000100000200020000020306
10971 # multicast mac of the nexthop IP - 2001:db8:1:0:200:02ff:fe01:1305
10972 dst_mcast_mac=3333ff011305
10973 mcast_node_ip=ff0200000000000000000001ff011305
10974 nd_target=20010db800010000020002fffe011305
10975 test_ipv6 1 $src_mac $dst_mac $src_ip $dst_ip $dst_mcast_mac \
10976 $mcast_node_ip $nd_target
10978 OVS_WAIT_WHILE([test 24 = $(wc -c hv1/br-phys_n1-tx.pcap | cut -d " " -f1)])
10979 OVS_WAIT_WHILE([test 24 = $(wc -c hv1/br-phys-tx.pcap | cut -d " " -f1)])
10981 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/br-phys_n1-tx.pcap | \
10982 trim_zeros > 1.packets
10983 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/br-phys-tx.pcap | \
10984 trim_zeros > 2.packets
10986 cat ipv6_ns.expected | cut -c -112 > expout
10987 AT_CHECK([cat 1.packets | cut -c -112], [0], [expout])
10988 AT_CHECK([cat 2.packets | cut -c -112], [0], [expout])
10990 # Skipping the ICMPv6 checksum
10991 cat ipv6_ns.expected | cut -c 117- > expout
10992 AT_CHECK([cat 1.packets | cut -c 117-], [0], [expout])
10993 AT_CHECK([cat 2.packets | cut -c 117-], [0], [expout])
10999 AT_SETUP([ovn -- options:requested-chassis for logical port])
11004 ovn-nbctl ls-add ls0
11005 ovn-nbctl lsp-add ls0 lsp0
11007 # create two hypervisors, each with one vif port
11010 ovs-vsctl add-br br-phys
11011 ovn_attach n1 br-phys 192.168.0.11
11012 ovs-vsctl -- add-port br-int hv1-vif0 -- \
11013 set Interface hv1-vif0 ofport-request=1
11017 ovs-vsctl add-br br-phys
11018 ovn_attach n1 br-phys 192.168.0.12
11019 ovs-vsctl -- add-port br-int hv2-vif0 -- \
11020 set Interface hv2-vif0 ofport-request=1
11022 # Allow only chassis hv1 to bind logical port lsp0.
11023 ovn-nbctl lsp-set-options lsp0 requested-chassis=hv1
11025 # Allow some time for ovn-northd and ovn-controller to catch up.
11026 ovn-nbctl --wait=hv --timeout=3 sync
11028 # Retrieve hv1 and hv2 chassis UUIDs from southbound database
11029 ovn-sbctl wait-until chassis hv1
11030 ovn-sbctl wait-until chassis hv2
11031 hv1_uuid=$(ovn-sbctl --bare --columns _uuid find chassis name=hv1)
11032 hv2_uuid=$(ovn-sbctl --bare --columns _uuid find chassis name=hv2)
11034 # (1) Chassis hv2 should not bind lsp0 when requested-chassis is hv1.
11035 echo "verifying that hv2 does not bind lsp0 when hv2 physical/logical mapping is added"
11037 ovs-vsctl set interface hv2-vif0 external-ids:iface-id=lsp0
11039 OVS_WAIT_UNTIL([test 1 = $(grep -c "Not claiming lport lsp0" hv2/ovn-controller.log)])
11040 AT_CHECK([test x$(ovn-sbctl --bare --columns chassis find port_binding logical_port=lsp0) = x], [0], [])
11042 # (2) Chassis hv2 should not add flows in OFTABLE_PHY_TO_LOG and OFTABLE_LOG_TO_PHY tables.
11043 AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=0 | grep in_port=1], [1], [])
11044 AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=65 | grep output], [1], [])
11046 # (3) Chassis hv1 should bind lsp0 when physical to logical mapping exists on hv1.
11047 echo "verifying that hv1 binds lsp0 when hv1 physical/logical mapping is added"
11049 ovs-vsctl set interface hv1-vif0 external-ids:iface-id=lsp0
11051 OVS_WAIT_UNTIL([test 1 = $(grep -c "Claiming lport lsp0" hv1/ovn-controller.log)])
11052 AT_CHECK([test x$(ovn-sbctl --bare --columns chassis find port_binding logical_port=lsp0) = x"$hv1_uuid"], [0], [])
11054 # (4) Chassis hv1 should add flows in OFTABLE_PHY_TO_LOG and OFTABLE_LOG_TO_PHY tables.
11055 as hv1 ovs-ofctl dump-flows br-int
11056 AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=0 | grep in_port=1], [0], [ignore])
11057 AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=65 | grep actions=output:1], [0], [ignore])
11059 # (5) Chassis hv1 should release lsp0 binding and chassis hv2 should bind lsp0 when
11060 # the requested chassis for lsp0 is changed from hv1 to hv2.
11061 echo "verifying that lsp0 binding moves when requested-chassis is changed"
11063 ovn-nbctl lsp-set-options lsp0 requested-chassis=hv2
11064 OVS_WAIT_UNTIL([test 1 = $(grep -c "Releasing lport lsp0 from this chassis" hv1/ovn-controller.log)])
11065 OVS_WAIT_UNTIL([test x$(ovn-sbctl --bare --columns chassis find port_binding logical_port=lsp0) = x"$hv2_uuid"])
11067 # (6) Chassis hv2 should add flows and hv1 should not.
11068 AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=0 | grep in_port=1], [0], [ignore])
11069 AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=65 | grep actions=output:1], [0], [ignore])
11071 AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=0 | grep in_port=1], [1], [])
11072 AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=65 | grep output], [1], [])
11074 OVN_CLEANUP([hv1],[hv2])
11078 AT_SETUP([ovn -- options:requested-chassis with hostname])
11082 ovn-nbctl ls-add ls0
11083 ovn-nbctl lsp-add ls0 lsp0
11088 ovs-vsctl add-br br-phys
11089 ovn_attach n1 br-phys 192.168.0.11
11090 ovs-vsctl -- add-port br-int hv1-vif0 -- set Interface hv1-vif0 ofport-request=1
11092 ovn-sbctl wait-until chassis hv1
11093 hv1_hostname=$(ovn-sbctl --bare --columns hostname find Chassis name=hv1)
11094 echo "hv1_hostname=${hv1_hostname}"
11095 ovn-nbctl --wait=hv --timeout=3 lsp-set-options lsp0 requested-chassis=${hv1_hostname}
11096 as hv1 ovs-vsctl set interface hv1-vif0 external-ids:iface-id=lsp0
11098 hv1_uuid=$(ovn-sbctl --bare --columns _uuid find Chassis name=hv1)
11099 echo "hv1_uuid=${hv1_uuid}"
11100 OVS_WAIT_UNTIL([test 1 = $(grep -c "Claiming lport lsp0" hv1/ovn-controller.log)])
11101 AT_CHECK([test x$(ovn-sbctl --bare --columns chassis find port_binding logical_port=lsp0) = x"$hv1_uuid"], [0], [])
11102 AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=0 | grep in_port=1], [0], [ignore])
11103 AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=65 | grep actions=output:1], [0], [ignore])
11105 ovn-nbctl --wait=hv --timeout=3 lsp-set-options lsp0 requested-chassis=non-existant-chassis
11106 OVS_WAIT_UNTIL([test 1 = $(grep -c "Releasing lport lsp0 from this chassis" hv1/ovn-controller.log)])
11107 ovn-nbctl --wait=hv --timeout=3 sync
11108 AT_CHECK([test x$(ovn-sbctl --bare --columns chassis find port_binding logical_port=lsp0) = x], [0], [])
11109 AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=0 | grep in_port=1], [1], [])
11110 AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=65 | grep output], [1], [])
11116 AT_SETUP([ovn -- IPv6 periodic RA])
11119 # This test sets up two hypervisors.
11120 # hv1 and hv2 run ovn-controllers, and
11121 # each has a VIF connected to the same
11122 # logical switch in OVN. The logical
11123 # switch is connected to a logical
11124 # router port that is configured to send
11125 # periodic router advertisements.
11127 # The reason for having two ovn-controller
11128 # hypervisors is to ensure that the
11129 # periodic RAs being sent by each ovn-controller
11130 # are kept to their local hypervisors. If the
11131 # packets are not kept local, then each port
11132 # will receive too many RAs.
11138 ovs-vsctl add-br br-phys
11139 ovn_attach n1 br-phys 192.168.0.2
11141 ovs-vsctl add-br br-phys
11142 ovn_attach n1 br-phys 192.168.0.3
11144 ovn-nbctl lr-add ro
11145 ovn-nbctl lrp-add ro ro-sw 00:00:00:00:00:01 aef0:0:0:0:0:0:0:1/64
11147 ovn-nbctl ls-add sw
11148 ovn-nbctl lsp-add sw sw-ro
11149 ovn-nbctl lsp-set-type sw-ro router
11150 ovn-nbctl lsp-set-options sw-ro router-port=ro-sw
11151 ovn-nbctl lsp-set-addresses sw-ro 00:00:00:00:00:01
11152 ovn-nbctl lsp-add sw sw-p1
11153 ovn-nbctl lsp-set-addresses sw-p1 "00:00:00:00:00:02 aef0::200:ff:fe00:2"
11154 ovn-nbctl lsp-add sw sw-p2
11155 ovn-nbctl lsp-set-addresses sw-p2 "00:00:00:00:00:03 aef0::200:ff:fe00:3"
11157 ovn-nbctl set Logical_Router_Port ro-sw ipv6_ra_configs:send_periodic=true
11158 ovn-nbctl set Logical_Router_Port ro-sw ipv6_ra_configs:address_mode=slaac
11159 ovn-nbctl set Logical_Router_Port ro-sw ipv6_ra_configs:max_interval=4
11160 ovn-nbctl set Logical_Router_Port ro-sw ipv6_ra_configs:min_interval=3
11164 ovs-vsctl -- add-port br-int hv$i-vif1 -- \
11165 set interface hv$i-vif1 external-ids:iface-id=sw-p$i \
11166 options:tx_pcap=hv$i/vif1-tx.pcap \
11167 options:rxq_pcap=hv$i/vif1-rx.pcap \
11171 OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw-p1` = xup])
11172 OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw-p2` = xup])
11174 reset_pcap_file() {
11177 ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \
11178 options:rxq_pcap=dummy-rx.pcap
11179 rm -f ${pcap_file}*.pcap
11180 ovs-vsctl -- set Interface $iface options:tx_pcap=${pcap_file}-tx.pcap \
11181 options:rxq_pcap=${pcap_file}-rx.pcap
11185 construct_expected_ra() {
11186 local src_mac=000000000001
11187 local dst_mac=333300000001
11188 local src_addr=fe80000000000000020000fffe000001
11189 local dst_addr=ff020000000000000000000000000001
11193 local ra_prefix_la=$3
11195 local slla=0101${src_mac}
11197 if test $mtu != 0; then
11198 mtu_opt=05010000${mtu}
11203 while [[ $# -gt 0 ]] ; do
11206 prefix=${prefix}0304${size}${ra_prefix_la}ffffffffffffffff00000000${net}
11210 local ra=ff${ra_mo}ffff0000000000000000${slla}${mtu_opt}${prefix}
11211 local icmp=8600XXXX${ra}
11213 local ip_len=$(expr ${#icmp} / 2)
11214 ip_len=$(echo "$ip_len" | awk '{printf "%0.4x\n", $0}')
11216 local ip=60000000${ip_len}3aff${src_addr}${dst_addr}${icmp}
11217 local eth=${dst_mac}${src_mac}86dd${ip}
11218 local packet=${eth}
11219 echo $packet >> expected
11223 construct_expected_ra $@
11225 for i in hv1 hv2 ; do
11226 OVS_WAIT_WHILE([test 24 = $(wc -c $i/vif1-tx.pcap | cut -d " " -f1)])
11228 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" $i/vif1-tx.pcap > packets
11230 cat expected | cut -c -112 > expout
11231 AT_CHECK([cat packets | cut -c -112], [0], [expout])
11233 # Skip ICMPv6 checksum.
11234 cat expected | cut -c 117- > expout
11235 AT_CHECK([cat packets | cut -c 117-], [0], [expout])
11238 as $i reset_pcap_file $i-vif1 $i/vif1
11244 # Baseline test with no MTU
11245 ra_test 0 00 c0 40 aef00000000000000000000000000000
11247 # Now make sure an MTU option makes it
11248 ovn-nbctl --wait=hv set Logical_Router_Port ro-sw ipv6_ra_configs:mtu=1500
11249 ra_test 000005dc 00 c0 40 aef00000000000000000000000000000
11251 # Now test for multiple network prefixes
11252 ovn-nbctl --wait=hv set Logical_Router_port ro-sw networks='aef0\:\:1/64 fd0f\:\:1/48'
11253 ra_test 000005dc 00 c0 40 aef00000000000000000000000000000 30 fd0f0000000000000000000000000000
11255 # Test a different address mode now
11256 ovn-nbctl --wait=hv set Logical_Router_Port ro-sw ipv6_ra_configs:address_mode=dhcpv6_stateful
11257 ra_test 000005dc 80 80 40 aef00000000000000000000000000000 30 fd0f0000000000000000000000000000
11259 # And the other address mode
11260 ovn-nbctl --wait=hv set Logical_Router_Port ro-sw ipv6_ra_configs:address_mode=dhcpv6_stateless
11261 ra_test 000005dc 40 c0 40 aef00000000000000000000000000000 30 fd0f0000000000000000000000000000
11263 OVN_CLEANUP([hv1],[hv2])
11266 AT_SETUP([ovn -- ACL reject rule test])
11267 AT_KEYWORDS([acl-reject])
11268 AT_SKIP_IF([test $HAVE_PYTHON = no])
11271 # test_ip_packet INPORT HV ETH_SRC ETH_DST IPV4_SRC IPV4_DST IP_CHKSUM EXP_IP_CHKSUM EXP_ICMP_CHKSUM
11273 # Causes a packet to be received on INPORT of the hypervisor HV. The packet is an IPv4 packet with
11274 # ETH_SRC, ETH_DST, IPV4_SRC, IPV4_DST, IP_CHKSUM as specified.
11275 # EXP_IP_CHKSUM and EXP_ICMP_CHKSUM are the ip and icmp checksums of the icmp destination
11276 # unreachable frame generated from ACL rule hit
11278 # INPORT is a lport number, e.g. 11 for vif11.
11279 # HV is a hypervisor number
11280 # ETH_SRC and ETH_DST are each 12 hex digits.
11281 # IPV4_SRC and IPV4_DST are each 8 hex digits.
11282 # IP_CHKSUM, EXP_IP_CHSUM and EXP_ICMP_CHKSUM are each 4 hex digits
11284 local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv4_src=$5 ipv4_dst=$6 ip_chksum=$7
11285 local exp_ip_chksum=$8 exp_icmp_chksum=$9
11289 local packet=${eth_dst}${eth_src}08004500001400004000${ip_ttl}01${ip_chksum}${ipv4_src}${ipv4_dst}
11291 local reply_icmp_ttl=ff
11292 local icmp_type_code_response=0301
11293 local icmp_data=00000000
11294 local reply_icmp_payload=${icmp_type_code_response}${exp_icmp_chksum}${icmp_data}
11295 local reply=${eth_src}${eth_dst}08004500001c00004000${reply_icmp_ttl}01${exp_ip_chksum}${ipv4_dst}${ipv4_src}${reply_icmp_payload}
11296 echo $reply >> vif$inport.expected
11298 as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
11301 # test_ipv6_packet INPORT HV ETH_SRC ETH_DST IPV4_SRC IPV4_DST EXP_ICMP_CHKSUM
11303 # Causes a packet to be received on INPORT of the hypervisor HV. The packet is an IPv6 packet with
11304 # ETH_SRC, ETH_DST, IPV6_SRC, IPV6_DST as specified.
11305 # EXP_ICMP_CHKSUM is the icmp6 checksums of the icmp6 destination unreachable frame generated from ACL rule hit
11306 test_ipv6_packet() {
11307 local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv6_src=$5 ipv6_dst=$6 exp_icmp_chksum=$7
11310 local ip6_hdr=6000000000083aff${ipv6_src}${ipv6_dst}
11311 local packet=${eth_dst}${eth_src}86dd${ip6_hdr}0000000000000000
11313 local reply=${eth_src}${eth_dst}86dd6000000000303aff${ipv6_dst}${ipv6_src}0101${exp_icmp_chksum}00000000${ip6_hdr}
11314 echo $reply >> vif$inport.expected
11316 as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
11319 # test_tcp_syn_packet INPORT HV ETH_SRC ETH_DST IPV4_SRC IPV4_DST IP_CHKSUM TCP_SPORT TCP_DPORT TCP_CHKSUM EXP_IP_CHKSUM EXP_TCP_RST_CHKSUM
11321 # Causes a packet to be received on INPORT of the hypervisor HV. The packet is an TCP syn segment with
11322 # ETH_SRC, ETH_DST, IPV4_SRC, IPV4_DST, IP_CHKSUM, TCP_SPORT, TCP_DPORT, TCP_CHKSUM as specified.
11323 # EXP_IP_CHKSUM and EXP_TCP_RST_CHKSUM are the ip and tcp checksums of the tcp reset segment generated from ACL rule hit
11325 # INPORT is an lport number, e.g. 11 for vif11.
11326 # HV is an hypervisor number
11327 # ETH_SRC and ETH_DST are each 12 hex digits.
11328 # IPV4_SRC and IPV4_DST are each 8 hex digits.
11329 # TCP_SPORT and TCP_DPORT are 4 hex digits.
11330 # IP_CHKSUM, TCP_CHKSUM, EXP_IP_CHSUM and EXP_TCP_RST_CHKSUM are each 4 hex digits
11331 test_tcp_syn_packet() {
11332 local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv4_src=$5 ipv4_dst=$6 ip_chksum=$7
11333 local tcp_sport=$8 tcp_dport=$9 tcp_chksum=${10}
11334 local exp_ip_chksum=${11} exp_tcp_rst_chksum=${12}
11338 local packet=${eth_dst}${eth_src}08004500002800004000${ip_ttl}06${ip_chksum}${ipv4_src}${ipv4_dst}${tcp_sport}${tcp_dport}000000010000000050027210${tcp_chksum}0000
11340 local tcp_rst_ttl=ff
11341 local reply=${eth_src}${eth_dst}08004500002800004000${tcp_rst_ttl}06${exp_ip_chksum}${ipv4_dst}${ipv4_src}${tcp_dport}${tcp_sport}000000000000000150040000${exp_tcp_rst_chksum}0000
11342 echo $reply >> vif$inport.expected
11344 as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
11347 # Create hypervisors hv[123].
11348 # Add vif1[123] to hv1, vif2[123] to hv2, vif3[123] to hv3.
11349 # Add all of the vifs to a single logical switch sw0.
11352 ovn-nbctl ls-add sw0
11356 ovs-vsctl add-br br-phys
11357 ovn_attach n1 br-phys 192.168.0.$i
11360 ovn-nbctl lsp-add sw0 sw0-p$i$j -- \
11361 lsp-set-addresses sw0-p$i$j "00:00:00:00:00:$i$j 192.168.1.$i$j"
11363 ovs-vsctl -- add-port br-int vif$i$j -- \
11364 set interface vif$i$j \
11365 external-ids:iface-id=sw0-p$i$j \
11366 options:tx_pcap=hv$i/vif$i$j-tx.pcap \
11367 options:rxq_pcap=hv$i/vif$i$j-rx.pcap \
11368 ofport-request=$i$j
11373 # allow some time for ovn-northd and ovn-controller to catch up.
11377 printf "%02x%02x%02x%02x" "$@"
11381 : > vif${i}1.expected
11384 ovn-nbctl --log acl-add sw0 to-lport 1000 "outport == \"sw0-p12\"" reject
11385 ovn-nbctl --log acl-add sw0 from-lport 1000 "inport == \"sw0-p11\"" reject
11386 ovn-nbctl --log acl-add sw0 from-lport 1000 "inport == \"sw0-p21\"" reject
11388 # Allow some time for ovn-northd and ovn-controller to catch up.
11389 ovn-nbctl --timeout=3 --wait=hv sync
11391 test_ip_packet 11 1 000000000011 000000000021 $(ip_to_hex 192 168 1 11) $(ip_to_hex 192 168 1 21) 0000 7d8d fcfe
11392 test_ip_packet 21 2 000000000021 000000000011 $(ip_to_hex 192 168 1 21) $(ip_to_hex 192 168 1 11) 0000 7d8d fcfe
11393 test_ip_packet 31 3 000000000031 000000000012 $(ip_to_hex 192 168 1 31) $(ip_to_hex 192 168 1 12) 0000 7d82 fcfe
11395 test_ipv6_packet 11 1 000000000011 000000000021 fe80000000000000020001fffe000001 fe80000000000000020001fffe000002 6183
11397 test_tcp_syn_packet 11 1 000000000011 000000000021 $(ip_to_hex 192 168 1 11) $(ip_to_hex 192 168 1 21) 0000 8b40 3039 0000 7d8d 4486
11398 test_tcp_syn_packet 21 2 000000000021 000000000011 $(ip_to_hex 192 168 1 21) $(ip_to_hex 192 168 1 11) 0000 8b40 3039 0000 7d8d 4486
11399 test_tcp_syn_packet 31 3 000000000031 000000000012 $(ip_to_hex 192 168 1 31) $(ip_to_hex 192 168 1 12) 0000 8b40 3039 0000 7d82 4486
11402 OVN_CHECK_PACKETS([hv$i/vif${i}1-tx.pcap], [vif${i}1.expected])
11405 OVN_CLEANUP([hv1], [hv2], [hv3])
11408 AT_SETUP([ovn -- Port Groups])
11409 AT_KEYWORDS([ovnpg])
11410 AT_SKIP_IF([test $HAVE_PYTHON = no])
11415 # Three logical switches ls1, ls2, ls3.
11416 # One logical router lr0 connected to ls[123],
11417 # with nine subnets, three per logical switch:
11419 # lrp11 on ls1 for subnet 192.168.11.0/24
11420 # lrp12 on ls1 for subnet 192.168.12.0/24
11421 # lrp13 on ls1 for subnet 192.168.13.0/24
11423 # lrp33 on ls3 for subnet 192.168.33.0/24
11425 # 27 VIFs, 9 per LS, 3 per subnet: lp[123][123][123], where the first two
11426 # digits are the subnet and the last digit distinguishes the VIF.
11428 # This test will create two port groups and uses them in ACL.
11431 ovn-nbctl lsp-list ls${1%??} | grep lp$1 | awk '{ print $1 }'
11437 ovn-nbctl ls-add ls$i
11441 -- lsp-add ls$i lp$i$j$k \
11442 -- lsp-set-addresses lp$i$j$k \
11443 "f0:00:00:00:0$i:$j$k 192.168.$i$j.$k"
11444 # logical ports lp[12]?1 belongs to port group pg1
11445 if test $i != 3 && test $k == 1; then
11446 pg1_ports="$pg1_ports `get_lsp_uuid $i$j$k`"
11448 # logical ports lp[23]?2 belongs to port group pg2
11449 if test $i != 1 && test $k == 2; then
11450 pg2_ports="$pg2_ports `get_lsp_uuid $i$j$k`"
11456 ovn-nbctl lr-add lr0
11459 ovn-nbctl lrp-add lr0 lrp$i$j 00:00:00:00:ff:$i$j 192.168.$i$j.254/24
11461 -- lsp-add ls$i lrp$i$j-attachment \
11462 -- set Logical_Switch_Port lrp$i$j-attachment type=router \
11463 options:router-port=lrp$i$j \
11464 addresses='"00:00:00:00:ff:'$i$j'"'
11468 ovn-nbctl create Port_Group name=pg1 ports="$pg1_ports"
11469 ovn-nbctl create Port_Group name=pg2 ports="$pg2_ports"
11471 # create ACLs on all lswitches to drop traffic from pg2 to pg1
11472 ovn-nbctl acl-add ls1 to-lport 1001 'outport == @pg1 && ip4.src == $pg2_ip4' drop
11473 ovn-nbctl acl-add ls2 to-lport 1001 'outport == @pg1 && ip4.src == $pg2_ip4' drop
11474 ovn-nbctl acl-add ls3 to-lport 1001 'outport == @pg1 && ip4.src == $pg2_ip4' drop
11476 # Physical network:
11478 # Three hypervisors hv[123].
11479 # lp?1[123] spread across hv[123]: lp?11 on hv1, lp?12 on hv2, lp?13 on hv3.
11480 # lp?2[123] spread across hv[23]: lp?21 and lp?22 on hv2, lp?23 on hv3.
11481 # lp?3[123] all on hv3.
11483 # Given the name of a logical port, prints the name of the hypervisor
11484 # on which it is located.
11487 ?11) echo 1 ;; dnl (
11488 ?12 | ?21 | ?22) echo 2 ;; dnl (
11489 ?13 | ?23 | ?3?) echo 3 ;;
11493 # Given the name of a logical port, prints the name of its logical router
11494 # port, e.g. "vif_to_lrp 123" yields 12.
11499 # Given the name of a logical port, prints the name of its logical
11500 # switch, e.g. "vif_to_ls 123" yields 1.
11509 ovs-vsctl add-br br-phys
11510 ovn_attach n1 br-phys 192.168.0.$i
11515 hv=`vif_to_hv $i$j$k`
11516 as hv$hv ovs-vsctl \
11517 -- add-port br-int vif$i$j$k \
11518 -- set Interface vif$i$j$k \
11519 external-ids:iface-id=lp$i$j$k \
11520 options:tx_pcap=hv$hv/vif$i$j$k-tx.pcap \
11521 options:rxq_pcap=hv$hv/vif$i$j$k-rx.pcap \
11522 ofport-request=$i$j$k
11527 # Pre-populate the hypervisors' ARP tables so that we don't lose any
11528 # packets for ARP resolution (native tunneling doesn't queue packets
11529 # for ARP resolution).
11532 # Allow some time for ovn-northd and ovn-controller to catch up.
11533 # XXX This should be more systematic.
11536 # test_ip INPORT SRC_MAC DST_MAC SRC_IP DST_IP OUTPORT...
11538 # This shell function causes a packet to be received on INPORT. The packet's
11539 # content has Ethernet destination DST and source SRC (each exactly 12 hex
11540 # digits) and Ethernet type ETHTYPE (4 hex digits). The OUTPORTs (zero or
11541 # more) list the VIFs on which the packet should be received. INPORT and the
11542 # OUTPORTs are specified as logical switch port numbers, e.g. 123 for vif123.
11546 : > $i$j$k.expected
11551 # This packet has bad checksums but logical L3 routing doesn't check.
11552 local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
11553 local packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
11554 shift; shift; shift; shift; shift
11555 hv=hv`vif_to_hv $inport`
11556 as $hv ovs-appctl netdev-dummy/receive vif$inport $packet
11557 #as $hv ovs-appctl ofproto/trace br-int in_port=$inport $packet
11558 in_ls=`vif_to_ls $inport`
11559 in_lrp=`vif_to_lrp $inport`
11561 out_ls=`vif_to_ls $outport`
11562 if test $in_ls = $out_ls; then
11563 # Ports on the same logical switch receive exactly the same packet.
11566 # Routing decrements TTL and updates source and dest MAC
11568 out_lrp=`vif_to_lrp $outport`
11569 echo f00000000${outport}00000000ff${out_lrp}08004500001c00000000"3f1101"00${src_ip}${dst_ip}0035111100080000
11570 fi >> $outport.expected
11574 as hv1 ovs-vsctl --columns=name,ofport list interface
11575 as hv1 ovn-sbctl list port_binding
11576 as hv1 ovn-sbctl list datapath_binding
11577 as hv1 ovn-sbctl list port_group
11578 as hv1 ovn-sbctl list address_set
11579 as hv1 ovn-sbctl dump-flows
11580 as hv1 ovs-ofctl dump-flows br-int
11582 # Send IP packets between all pairs of source and destination ports,
11583 # packets matches ACL (pg2 to pg1) should be dropped
11585 printf "%02x%02x%02x%02x" "$@"
11587 for is in 1 2 3; do
11588 for js in 1 2 3; do
11589 for ks in 1 2 3; do
11593 sip=`ip_to_hex 192 168 $is$js $ks`
11594 for id in 1 2 3; do
11595 for jd in 1 2 3; do
11596 for kd in 1 2 3; do
11598 dip=`ip_to_hex 192 168 $id$jd $kd`
11599 if test $is = $id; then dmac=f00000000$d; else dmac=00000000ff$is$js; fi
11600 if test $d != $s; then unicast=$d; else unicast=; fi
11602 # packets matches ACL should be dropped
11603 if test $id != 3 && test $kd == 1; then
11604 if test $is != 1 && test $ks == 2; then
11608 test_ip $s $smac $dmac $sip $dip $unicast #1
11616 # Allow some time for packet forwarding.
11617 # XXX This can be improved.
11620 # Now check the packets actually received against the ones expected.
11624 OVN_CHECK_PACKETS([hv`vif_to_hv $i$j$k`/vif$i$j$k-tx.pcap],
11630 # Gracefully terminate daemons
11631 OVN_CLEANUP([hv1], [hv2], [hv3])
11634 AT_SETUP([ovn -- ACLs on Port Groups])
11635 AT_KEYWORDS([ovnpg_acl])
11636 AT_SKIP_IF([test $HAVE_PYTHON = no])
11641 # Three logical switches ls1, ls2, ls3.
11642 # One logical router lr0 connected to ls[123],
11643 # with nine subnets, three per logical switch:
11645 # lrp11 on ls1 for subnet 192.168.11.0/24
11646 # lrp12 on ls1 for subnet 192.168.12.0/24
11647 # lrp13 on ls1 for subnet 192.168.13.0/24
11649 # lrp33 on ls3 for subnet 192.168.33.0/24
11651 # 27 VIFs, 9 per LS, 3 per subnet: lp[123][123][123], where the first two
11652 # digits are the subnet and the last digit distinguishes the VIF.
11654 # This test will create two port groups and ACLs will be applied on them.
11657 ovn-nbctl lsp-list ls${1%??} | grep lp$1 | awk '{ print $1 }'
11663 ovn-nbctl ls-add ls$i
11667 -- lsp-add ls$i lp$i$j$k \
11668 -- lsp-set-addresses lp$i$j$k \
11669 "f0:00:00:00:0$i:$j$k 192.168.$i$j.$k"
11670 # logical ports lp[12]?1 belongs to port group pg1
11671 if test $i != 3 && test $k == 1; then
11672 pg1_ports="$pg1_ports `get_lsp_uuid $i$j$k`"
11674 # logical ports lp[23]?2 belongs to port group pg2
11675 if test $i != 1 && test $k == 2; then
11676 pg2_ports="$pg2_ports `get_lsp_uuid $i$j$k`"
11682 ovn-nbctl lr-add lr0
11685 ovn-nbctl lrp-add lr0 lrp$i$j 00:00:00:00:ff:$i$j 192.168.$i$j.254/24
11687 -- lsp-add ls$i lrp$i$j-attachment \
11688 -- set Logical_Switch_Port lrp$i$j-attachment type=router \
11689 options:router-port=lrp$i$j \
11690 addresses='"00:00:00:00:ff:'$i$j'"'
11694 ovn-nbctl create Port_Group name=pg1 ports="$pg1_ports"
11695 ovn-nbctl create Port_Group name=pg2 ports="$pg2_ports"
11697 # create ACLs on pg1 to drop traffic from pg2 to pg1
11698 ovn-nbctl acl-add pg1 to-lport 1001 'outport == @pg1' drop
11699 ovn-nbctl --type=port-group acl-add pg1 to-lport 1002 \
11700 'outport == @pg1 && ip4.src == $pg2_ip4' allow-related
11702 # Physical network:
11704 # Three hypervisors hv[123].
11705 # lp?1[123] spread across hv[123]: lp?11 on hv1, lp?12 on hv2, lp?13 on hv3.
11706 # lp?2[123] spread across hv[23]: lp?21 and lp?22 on hv2, lp?23 on hv3.
11707 # lp?3[123] all on hv3.
11709 # Given the name of a logical port, prints the name of the hypervisor
11710 # on which it is located.
11713 ?11) echo 1 ;; dnl (
11714 ?12 | ?21 | ?22) echo 2 ;; dnl (
11715 ?13 | ?23 | ?3?) echo 3 ;;
11719 # Given the name of a logical port, prints the name of its logical router
11720 # port, e.g. "vif_to_lrp 123" yields 12.
11725 # Given the name of a logical port, prints the name of its logical
11726 # switch, e.g. "vif_to_ls 123" yields 1.
11735 ovs-vsctl add-br br-phys
11736 ovn_attach n1 br-phys 192.168.0.$i
11741 hv=`vif_to_hv $i$j$k`
11742 as hv$hv ovs-vsctl \
11743 -- add-port br-int vif$i$j$k \
11744 -- set Interface vif$i$j$k \
11745 external-ids:iface-id=lp$i$j$k \
11746 options:tx_pcap=hv$hv/vif$i$j$k-tx.pcap \
11747 options:rxq_pcap=hv$hv/vif$i$j$k-rx.pcap \
11748 ofport-request=$i$j$k
11753 # Pre-populate the hypervisors' ARP tables so that we don't lose any
11754 # packets for ARP resolution (native tunneling doesn't queue packets
11755 # for ARP resolution).
11758 # Allow some time for ovn-northd and ovn-controller to catch up.
11759 # XXX This should be more systematic.
11763 echo f0:00:00:00:0${1:0:1}:${1:1:2}
11767 echo 00:00:00:00:ff:$1
11770 # test_icmp INPORT SRC_MAC DST_MAC SRC_IP DST_IP ICMP_TYPE OUTPORT...
11772 # This shell function causes a ICMP packet to be received on INPORT.
11773 # The OUTPORTs (zero or more) list the VIFs on which the packet should
11774 # be received. INPORT and the OUTPORTs are specified as logical switch
11775 # port numbers, e.g. 123 for vif123.
11779 : > $i$j$k.expected
11785 local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5 icmp_type=$6
11786 local packet="inport==\"lp$inport\" && eth.src==$src_mac &&
11787 eth.dst==$dst_mac && ip.ttl==64 && ip4.src==$src_ip
11788 && ip4.dst==$dst_ip && icmp4.type==$icmp_type &&
11790 shift; shift; shift; shift; shift; shift
11791 hv=hv`vif_to_hv $inport`
11792 as $hv ovs-appctl -t ovn-controller inject-pkt "$packet"
11793 in_ls=`vif_to_ls $inport`
11794 in_lrp=`vif_to_lrp $inport`
11796 out_ls=`vif_to_ls $outport`
11797 if test $in_ls = $out_ls; then
11798 # Ports on the same logical switch receive exactly the same packet.
11799 echo $packet | ovstest test-ovn expr-to-packets
11801 # Routing decrements TTL and updates source and dest MAC
11803 out_lrp=`vif_to_lrp $outport`
11804 exp_smac=`lrp_to_mac $out_lrp`
11805 exp_dmac=`lsp_to_mac $outport`
11806 exp_packet="eth.src==$exp_smac && eth.dst==$exp_dmac &&
11807 ip.ttl==63 && ip4.src==$src_ip && ip4.dst==$dst_ip &&
11808 icmp4.type==$icmp_type && icmp4.code==0"
11809 echo $exp_packet | ovstest test-ovn expr-to-packets
11811 fi >> $outport.expected
11815 as hv1 ovs-vsctl --columns=name,ofport list interface
11816 as hv1 ovn-sbctl list port_binding
11817 as hv1 ovn-sbctl list datapath_binding
11818 as hv1 ovn-sbctl list port_group
11819 as hv1 ovn-sbctl list address_set
11820 as hv1 ovn-sbctl dump-flows
11821 as hv1 ovs-ofctl dump-flows br-int
11823 # Send IP packets between all pairs of source and destination ports,
11824 # packets matches ACL1 but not ACL2 should be dropped
11826 printf "%02x%02x%02x%02x" "$@"
11828 for is in 1 2 3; do
11829 for js in 1 2 3; do
11830 for ks in 1 2 3; do
11833 slsp_mac=`lsp_to_mac $s`
11834 slrp_mac=`lrp_to_mac $is$js`
11835 sip=192.168.$is$js.$ks
11836 for id in 1 2 3; do
11837 for jd in 1 2 3; do
11838 for kd in 1 2 3; do
11840 dlsp_mac=`lsp_to_mac $d`
11841 dlrp_mac=`lrp_to_mac $id$jd`
11842 dip=192.168.$id$jd.$kd
11843 if test $is = $id; then dmac=$dlsp_mac; else dmac=$slrp_mac; fi
11844 if test $d != $s; then unicast=$d; else unicast=; fi
11846 # packets matches ACL1 but not ACL2 should be dropped
11847 if test $id != 3 && test $kd == 1; then
11848 if test $is == 1 || test $ks != 2; then
11852 # icmp request (type = 8)
11853 test_icmp $s $slsp_mac $dmac $sip $dip 8 $unicast
11855 # if packets are not dropped, test the return traffic (icmp echo)
11856 # to make sure stateful works, too.
11857 if test x$unicast != x; then
11858 if test $is = $id; then dmac=$slsp_mac; else dmac=$dlrp_mac; fi
11859 # icmp echo (type = 0)
11860 test_icmp $unicast $dlsp_mac $dmac $dip $sip 0 $s
11869 # Allow some time for packet forwarding.
11870 # XXX This can be improved.
11873 # Now check the packets actually received against the ones expected.
11877 OVN_CHECK_PACKETS([hv`vif_to_hv $i$j$k`/vif$i$j$k-tx.pcap],
11883 # Gracefully terminate daemons
11884 OVN_CLEANUP([hv1], [hv2], [hv3])
11887 AT_SETUP([ovn -- Address Set generation from Port Groups (static addressing)])
11890 ovn-nbctl ls-add ls1
11892 ovn-nbctl lsp-add ls1 lp1
11893 ovn-nbctl lsp-add ls1 lp2
11894 ovn-nbctl lsp-add ls1 lp3
11896 ovn-nbctl lsp-set-addresses lp1 "02:00:00:00:00:01 10.0.0.1 2001:db8::1"
11897 ovn-nbctl lsp-set-addresses lp2 "02:00:00:00:00:02 10.0.0.2 2001:db8::2"
11898 ovn-nbctl lsp-set-addresses lp3 "02:00:00:00:00:03 10.0.0.3 2001:db8::3"
11900 ovn-nbctl create Port_Group name=pg1
11901 ovn-nbctl create Port_Group name=pg2
11903 ovn-nbctl --id=@p get Logical_Switch_Port lp1 -- add Port_Group pg1 ports @p
11904 ovn-nbctl --id=@p get Logical_Switch_Port lp2 -- add Port_Group pg1 ports @p
11905 ovn-nbctl --id=@p get Logical_Switch_Port lp2 -- add Port_Group pg2 ports @p
11906 ovn-nbctl --id=@p get Logical_Switch_Port lp3 -- add Port_Group pg2 ports @p
11908 ovn-nbctl --wait=sb sync
11910 dnl Check if port group address sets were populated with ports' addresses
11911 AT_CHECK([ovn-sbctl get Address_Set pg1_ip4 addresses],
11912 [0], [[["10.0.0.1", "10.0.0.2"]]
11914 AT_CHECK([ovn-sbctl get Address_Set pg2_ip4 addresses],
11915 [0], [[["10.0.0.2", "10.0.0.3"]]
11917 AT_CHECK([ovn-sbctl get Address_Set pg1_ip6 addresses],
11918 [0], [[["2001:db8::1", "2001:db8::2"]]
11920 AT_CHECK([ovn-sbctl get Address_Set pg2_ip6 addresses],
11921 [0], [[["2001:db8::2", "2001:db8::3"]]
11924 ovn-nbctl --wait=sb lsp-set-addresses lp1 \
11925 "02:00:00:00:00:01 10.0.0.11 2001:db8::11"
11927 dnl Check if updated address got propagated to the port group address sets
11928 AT_CHECK([ovn-sbctl get Address_Set pg1_ip4 addresses],
11929 [0], [[["10.0.0.11", "10.0.0.2"]]
11931 AT_CHECK([ovn-sbctl get Address_Set pg1_ip6 addresses],
11932 [0], [[["2001:db8::11", "2001:db8::2"]]
11937 AT_SETUP([ovn -- Address Set generation from Port Groups (dynamic addressing)])
11940 ovn-nbctl ls-add ls1
11941 ovn-nbctl ls-add ls2
11942 ovn-nbctl ls-add ls3
11944 ovn-nbctl set Logical_Switch ls1 \
11945 other_config:subnet=10.1.0.0/24 other_config:ipv6_prefix="2001:db8:1::"
11946 ovn-nbctl set Logical_Switch ls2 \
11947 other_config:subnet=10.2.0.0/24 other_config:ipv6_prefix="2001:db8:2::"
11948 ovn-nbctl set Logical_Switch ls3 \
11949 other_config:subnet=10.3.0.0/24 other_config:ipv6_prefix="2001:db8:3::"
11951 ovn-nbctl lsp-add ls1 lp1
11952 ovn-nbctl lsp-add ls2 lp2
11953 ovn-nbctl lsp-add ls3 lp3
11955 ovn-nbctl lsp-set-addresses lp1 "02:00:00:00:00:01 dynamic"
11956 ovn-nbctl lsp-set-addresses lp2 "02:00:00:00:00:02 dynamic"
11957 ovn-nbctl lsp-set-addresses lp3 "02:00:00:00:00:03 dynamic"
11959 ovn-nbctl create Port_Group name=pg1
11960 ovn-nbctl create Port_Group name=pg2
11962 ovn-nbctl --id=@p get Logical_Switch_Port lp1 -- add Port_Group pg1 ports @p
11963 ovn-nbctl --id=@p get Logical_Switch_Port lp2 -- add Port_Group pg1 ports @p
11964 ovn-nbctl --id=@p get Logical_Switch_Port lp2 -- add Port_Group pg2 ports @p
11965 ovn-nbctl --id=@p get Logical_Switch_Port lp3 -- add Port_Group pg2 ports @p
11967 ovn-nbctl --wait=sb sync
11969 dnl Check if port group address sets were populated with ports' addresses
11970 AT_CHECK([ovn-sbctl get Address_Set pg1_ip4 addresses],
11971 [0], [[["10.1.0.2", "10.2.0.2"]]
11973 AT_CHECK([ovn-sbctl get Address_Set pg2_ip4 addresses],
11974 [0], [[["10.2.0.2", "10.3.0.2"]]
11976 AT_CHECK([ovn-sbctl get Address_Set pg1_ip6 addresses],
11977 [0], [[["2001:db8:1::ff:fe00:1", "2001:db8:2::ff:fe00:2"]]
11979 AT_CHECK([ovn-sbctl get Address_Set pg2_ip6 addresses],
11980 [0], [[["2001:db8:2::ff:fe00:2", "2001:db8:3::ff:fe00:3"]]
11983 ovn-nbctl --wait=sb set Logical_Switch ls1 \
11984 other_config:subnet=10.11.0.0/24 other_config:ipv6_prefix="2001:db8:11::"
11986 dnl Check if updated address got propagated to the port group address sets
11987 AT_CHECK([ovn-sbctl get Address_Set pg1_ip4 addresses],
11988 [0], [[["10.11.0.2", "10.2.0.2"]]
11990 AT_CHECK([ovn-sbctl get Address_Set pg1_ip6 addresses],
11991 [0], [[["2001:db8:11::ff:fe00:1", "2001:db8:2::ff:fe00:2"]]
11996 AT_SETUP([ovn -- ACL conjunction])
11999 ovn-nbctl ls-add ls1
12001 ovn-nbctl lsp-add ls1 ls1-lp1 \
12002 -- lsp-set-addresses ls1-lp1 "f0:00:00:00:00:01 10.0.0.4"
12004 ovn-nbctl lsp-set-port-security ls1-lp1 "f0:00:00:00:00:01 10.0.0.4"
12006 ovn-nbctl lsp-add ls1 ls1-lp2 \
12007 -- lsp-set-addresses ls1-lp2 "f0:00:00:00:00:02 10.0.0.6"
12009 ovn-nbctl lsp-set-port-security ls1-lp2 "f0:00:00:00:00:02 10.0.0.6"
12015 ovs-vsctl add-br br-phys
12016 ovn_attach n1 br-phys 192.168.0.1
12017 ovs-vsctl -- add-port br-int hv1-vif1 -- \
12018 set interface hv1-vif1 external-ids:iface-id=ls1-lp1 \
12019 options:tx_pcap=hv1/vif1-tx.pcap \
12020 options:rxq_pcap=hv1/vif1-rx.pcap \
12023 ovs-vsctl -- add-port br-int hv1-vif2 -- \
12024 set interface hv1-vif2 external-ids:iface-id=ls1-lp2 \
12025 options:tx_pcap=hv1/vif2-tx.pcap \
12026 options:rxq_pcap=hv1/vif2-rx.pcap \
12029 ovn-nbctl create Address_Set name=set1 \
12030 addresses=\"10.0.0.4\",\"10.0.0.5\",\"10.0.0.6\"
12031 ovn-nbctl create Address_Set name=set2 \
12032 addresses=\"10.0.0.7\",\"10.0.0.8\",\"10.0.0.9\"
12033 ovn-nbctl acl-add ls1 to-lport 1002 \
12034 'ip4 && ip4.src == $set1 && ip4.dst == $set1' allow
12035 ovn-nbctl acl-add ls1 to-lport 1001 \
12036 'ip4 && ip4.src == $set1 && ip4.dst == $set2' drop
12038 # test_ip INPORT SRC_MAC DST_MAC SRC_IP DST_IP OUTPORT...
12040 # This shell function causes an ip packet to be received on INPORT.
12041 # The packet's content has Ethernet destination DST and source SRC
12042 # (each exactly 12 hex digits) and Ethernet type ETHTYPE (4 hex digits).
12043 # The OUTPORTs (zero or more) list the VIFs on which the packet should
12044 # be received. INPORT and the OUTPORTs are specified as logical switch
12045 # port numbers, e.g. 11 for vif11.
12047 # This packet has bad checksums but logical L3 routing doesn't check.
12048 local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
12049 local packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}\
12050 ${dst_ip}0035111100080000
12051 shift; shift; shift; shift; shift
12052 as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
12054 echo $packet >> $outport.expected
12059 printf "%02x%02x%02x%02x" "$@"
12062 reset_pcap_file() {
12065 ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \
12066 options:rxq_pcap=dummy-rx.pcap
12067 rm -f ${pcap_file}*.pcap
12068 ovs-vsctl -- set Interface $iface options:tx_pcap=${pcap_file}-tx.pcap \
12069 options:rxq_pcap=${pcap_file}-rx.pcap
12073 sip=`ip_to_hex 10 0 0 4`
12074 dip=`ip_to_hex 10 0 0 6`
12076 test_ip 1 f00000000001 f00000000002 $sip $dip 2
12078 cat 2.expected > expout
12079 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets
12080 AT_CHECK([cat 2.packets], [0], [expout])
12082 # There should be total of 12 flows present with conjunction action and 2 flows
12083 # with conj match. Eg.
12084 # table=44, priority=2002,conj_id=2,metadata=0x1 actions=resubmit(,45)
12085 # table=44, priority=2001,conj_id=3,metadata=0x1 actions=drop
12086 # priority=2002,ip,metadata=0x1,nw_dst=10.0.0.6 actions=conjunction(2,2/2)
12087 # priority=2002,ip,metadata=0x1,nw_dst=10.0.0.4 actions=conjunction(2,2/2)
12088 # priority=2002,ip,metadata=0x1,nw_dst=10.0.0.5 actions=conjunction(2,2/2)
12089 # priority=2001,ip,metadata=0x1,nw_dst=10.0.0.7 actions=conjunction(3,2/2)
12090 # priority=2001,ip,metadata=0x1,nw_dst=10.0.0.9 actions=conjunction(3,2/2)
12091 # priority=2001,ip,metadata=0x1,nw_dst=10.0.0.8 actions=conjunction(3,2/2)
12092 # priority=2002,ip,metadata=0x1,nw_src=10.0.0.6 actions=conjunction(2,1/2)
12093 # priority=2002,ip,metadata=0x1,nw_src=10.0.0.4 actions=conjunction(2,1/2)
12094 # priority=2002,ip,metadata=0x1,nw_src=10.0.0.5 actions=conjunction(2,1/2)
12095 # priority=2001,ip,metadata=0x1,nw_src=10.0.0.6 actions=conjunction(3,1/2)
12096 # priority=2001,ip,metadata=0x1,nw_src=10.0.0.4 actions=conjunction(3,1/2)
12097 # priority=2001,ip,metadata=0x1,nw_src=10.0.0.5 actions=conjunction(3,1/2)
12099 OVS_WAIT_UNTIL([test 12 = `as hv1 ovs-ofctl dump-flows br-int | \
12100 grep conjunction | wc -l`])
12101 OVS_WAIT_UNTIL([test 2 = `as hv1 ovs-ofctl dump-flows br-int | \
12102 grep conj_id | wc -l`])
12104 as hv1 ovs-ofctl dump-flows br-int
12106 # Set the ip address for ls1-lp2 from set2 so that the drop ACL flow is hit.
12107 ovn-nbctl lsp-set-addresses ls1-lp2 "f0:00:00:00:00:02 10.0.0.7 20.0.0.4"
12108 ovn-nbctl lsp-set-port-security ls1-lp2 "f0:00:00:00:00:02 10.0.0.7 20.0.0.4"
12110 reset_pcap_file hv1-vif2 hv1/vif2
12114 sip=`ip_to_hex 10 0 0 4`
12115 dip=`ip_to_hex 10 0 0 7`
12117 test_ip 1 f00000000001 f00000000002 $sip $dip
12118 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets
12119 AT_CHECK([cat 2.packets], [0], [])
12123 AT_SETUP([ovn -- TTL exceeded])
12124 AT_KEYWORDS([ttl-exceeded])
12125 AT_SKIP_IF([test $HAVE_PYTHON = no])
12128 # test_ip_packet INPORT HV ETH_SRC ETH_DST IPV4_SRC IPV4_DST IPV4_ROUTER IP_CHKSUM EXP_IP_CHKSUM EXP_ICMP_CHKSUM
12130 # Causes a packet to be received on INPORT of the hypervisor HV. The packet is an IPv4 packet with
12131 # ETH_SRC, ETH_DST, IPV4_SRC, IPV4_DST, IP_CHKSUM as specified and TTL set to 1.
12132 # EXP_IP_CHKSUM and EXP_ICMP_CHKSUM are the ip and icmp checksums of the icmp time exceeded frame
12133 # generated by OVN logical router
12135 # INPORT is a lport number, e.g. 11 for vif11.
12136 # HV is a hypervisor number
12137 # ETH_SRC and ETH_DST are each 12 hex digits.
12138 # IPV4_SRC, IPV4_DST and IPV4_ROUTER are each 8 hex digits.
12139 # IP_CHKSUM, EXP_IP_CHSUM and EXP_ICMP_CHKSUM are each 4 hex digits
12141 local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv4_src=$5 ipv4_dst=$6 ip_router=$7 ip_chksum=$8
12142 local exp_ip_chksum=$9 exp_icmp_chksum=${10}
12146 local packet=${eth_dst}${eth_src}08004500001400004000${ip_ttl}01${ip_chksum}${ipv4_src}${ipv4_dst}
12148 local reply_icmp_ttl=fe
12149 local icmp_type_code_response=0b00
12150 local icmp_data=00000000
12151 local reply_icmp_payload=${icmp_type_code_response}${exp_icmp_chksum}${icmp_data}
12152 local reply=${eth_src}${eth_dst}08004500001c00004000${reply_icmp_ttl}01${exp_ip_chksum}${ip_router}${ipv4_src}${reply_icmp_payload}
12153 echo $reply >> vif$inport.expected
12155 as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
12158 # test_ip6_packet INPORT HV ETH_SRC ETH_DST IPV6_SRC IPV6_DST IPV6_ROUTER EXP_ICMP_CHKSUM
12160 # Causes a packet to be received on INPORT of the hypervisor HV. The packet is an IPv6
12161 # packet with ETH_SRC, ETH_DST, IPV6_SRC and IPV6_DST as specified.
12162 # IPV6_ROUTER and EXP_ICMP_CHKSUM are the source IP and checksum of the icmpv6 ttl exceeded
12163 # packet sent by OVN logical router
12164 test_ip6_packet() {
12165 local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv6_src=$5 ipv6_dst=$6 ipv6_router=$7 exp_icmp_chksum=$8
12168 local ip6_hdr=6000000000151101${ipv6_src}${ipv6_dst}
12169 local packet=${eth_dst}${eth_src}86dd${ip6_hdr}dbb8303900155bac6b646f65206676676e6d66720a
12171 local reply=${eth_src}${eth_dst}86dd6000000000303afe${ipv6_router}${ipv6_src}0300${exp_icmp_chksum}00000000${ip6_hdr}
12172 echo $reply >> vif$inport.expected
12174 as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
12178 printf "%02x%02x%02x%02x" "$@"
12183 ovn-nbctl ls-add sw$i
12187 ovs-vsctl add-br br-phys
12188 ovn_attach n$i br-phys 192.168.$i.1
12190 ovn-nbctl lsp-add sw$i sw$i-p${i}0 -- \
12191 lsp-set-addresses sw$i-p${i}0 "00:00:00:00:00:0$i 192.168.$i.1 2001:db8:$i::11"
12193 ovs-vsctl -- add-port br-int vif$i -- \
12194 set interface vif$i \
12195 external-ids:iface-id=sw$i-p${i}0 \
12196 options:tx_pcap=hv$i/vif$i-tx.pcap \
12197 options:rxq_pcap=hv$i/vif$i-rx.pcap \
12201 ovn-nbctl lr-add lr0
12203 ovn-nbctl lrp-add lr0 lrp$i 00:00:00:00:ff:0$i 192.168.$i.254/24 2001:db8:$i::1/64
12204 ovn-nbctl -- lsp-add sw$i lrp$i-attachment \
12205 -- set Logical_Switch_Port lrp$i-attachment type=router \
12206 options:router-port=lrp$i addresses='"00:00:00:00:ff:0'$i' 192.168.'$i'.254 2001:db8:'$i'::1"'
12210 # allow some time for ovn-northd and ovn-controller to catch up.
12211 ovn-nbctl --wait=hv sync
12213 test_ip_packet 1 1 000000000001 00000000ff01 $(ip_to_hex 192 168 1 1) $(ip_to_hex 192 168 2 1) $(ip_to_hex 192 168 1 254) 0000 7dae f4ff
12214 test_ip6_packet 1 1 000000000001 00000000ff01 20010db8000100000000000000000011 20010db8000200000000000000000011 20010db8000100000000000000000001 d461
12215 OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [vif1.expected])
12217 OVN_CLEANUP([hv1], [hv2])
12220 AT_SETUP([ovn -- router port unreachable])
12221 AT_KEYWORDS([router-port-unreachable])
12222 AT_SKIP_IF([test $HAVE_PYTHON = no])
12225 # test_ip_packet INPORT HV ETH_SRC ETH_DST IPV4_SRC IPV4_ROUTER L4_PROTCOL IP_CHKSUM EXP_IP_CHKSUM EXP_ICMP_CHKSUM EXP_ICMP_CODE
12227 # Causes a packet to be received on INPORT of the hypervisor HV. The packet is an IPv4 packet with
12228 # ETH_SRC, ETH_DST, IPV4_SRC, IPV4_ROUTER, L4_PROTCOL, IP_CHKSUM as specified.
12229 # EXP_IP_CHKSUM and EXP_ICMP_CHKSUM are the ip and icmp checksums of the icmp frame generated by OVN logical router
12230 # EXP_ICMP_CODE are code and type of the icmp frame generated by OVN logical router
12232 # INPORT is a lport number, e.g. 11 for vif11.
12233 # HV is a hypervisor number
12234 # ETH_SRC and ETH_DST are each 12 hex digits.
12235 # IPV4_SRC and IPV4_ROUTER are each 8 hex digits.
12236 # IP_CHKSUM, EXP_IP_CHSUM and EXP_ICMP_CHKSUM are each 4 hex digits
12238 local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv4_src=$5 ip_router=$6 l4_proto=$7 ip_chksum=$8
12239 local exp_ip_chksum=$9 exp_icmp_chksum=${10} exp_icmp_code=${11}
12243 local packet=${eth_dst}${eth_src}08004500001400004000${ip_ttl}${l4_proto}${ip_chksum}${ipv4_src}${ip_router}
12245 local reply_icmp_ttl=fe
12246 local icmp_data=00000000
12247 local reply_icmp_payload=${exp_icmp_code}${exp_icmp_chksum}${icmp_data}
12248 local reply=${eth_src}${eth_dst}08004500001c00004000${reply_icmp_ttl}01${exp_ip_chksum}${ip_router}${ipv4_src}${reply_icmp_payload}
12249 echo $reply >> vif$inport.expected
12251 as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
12254 # test_tcp_syn_packet INPORT HV ETH_SRC ETH_DST IPV4_SRC IPV4_ROUTER IP_CHKSUM TCP_SPORT TCP_DPORT TCP_CHKSUM EXP_IP_CHKSUM EXP_TCP_RST_CHKSUM
12256 # Causes a packet to be received on INPORT of the hypervisor HV. The packet is an TCP syn segment with
12257 # ETH_SRC, ETH_DST, IPV4_SRC, IPV4_ROUTER, IP_CHKSUM, TCP_SPORT, TCP_DPORT, TCP_CHKSUM as specified.
12258 # EXP_IP_CHKSUM and EXP_TCP_RST_CHKSUM are the ip and tcp checksums of the tcp reset segment generated by OVN logical router
12260 # INPORT is an lport number, e.g. 11 for vif11.
12261 # HV is an hypervisor number
12262 # ETH_SRC and ETH_DST are each 12 hex digits.
12263 # IPV4_SRC and IPV4_ROUTER are each 8 hex digits.
12264 # TCP_SPORT and TCP_DPORT are 4 hex digits.
12265 # IP_CHKSUM, TCP_CHKSUM, EXP_IP_CHSUM and EXP_TCP_RST_CHKSUM are each 4 hex digits
12266 test_tcp_syn_packet() {
12267 local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv4_src=$5 ip_router=$6 ip_chksum=$7
12268 local tcp_sport=$8 tcp_dport=$9 tcp_chksum=${10}
12269 local exp_ip_chksum=${11} exp_tcp_rst_chksum=${12}
12273 local packet=${eth_dst}${eth_src}08004500002800004000${ip_ttl}06${ip_chksum}${ipv4_src}${ip_router}${tcp_sport}${tcp_dport}000000010000000050027210${tcp_chksum}0000
12275 local tcp_rst_ttl=fe
12276 local reply=${eth_src}${eth_dst}08004500002800004000${tcp_rst_ttl}06${exp_ip_chksum}${ip_router}${ipv4_src}${tcp_dport}${tcp_sport}000000000000000150040000${exp_tcp_rst_chksum}0000
12277 echo $reply >> vif$inport.expected
12279 as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
12282 # test_tcp6_packet INPORT HV ETH_SRC ETH_DST IPV6_SRC IPV6_ROUTER TCP_SPORT TCP_DPORT TCP_CHKSUM EXP_TCP_RST_CHKSUM
12284 # Causes a packet to be received on INPORT of the hypervisor HV. The packet is a TCP syn segment with
12285 # ETH_SRC, ETH_DST, IPV6_SRC, IPV6_ROUTER, TCP_SPORT, TCP_DPORT and TCP_CHKSUM as specified.
12286 # EXP_TCP_RST_CHKSUM is the tcp checksums of the tcp reset segment generated by OVN logical router
12287 test_tcp6_packet() {
12288 local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv6_src=$5 ipv6_router=$6
12289 local tcp_sport=$7 tcp_dport=$8 tcp_chksum=$9
12290 local exp_tcp_rst_chksum=${10}
12293 local ip6_hdr=60000000001406ff${ipv6_src}${ipv6_router}
12294 local packet=${eth_dst}${eth_src}86dd${ip6_hdr}${tcp_sport}${tcp_dport}000000010000000050027210${tcp_chksum}0000
12296 local reply=${eth_src}${eth_dst}86dd60000000001406fe${ipv6_router}${ipv6_src}${tcp_dport}${tcp_sport}000000000000000150040000${exp_tcp_rst_chksum}0000
12297 echo $reply >> vif$inport.expected
12299 as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
12302 # test_ip6_packet INPORT HV ETH_SRC ETH_DST IPV6_SRC IPV6_DST IPV6_PROTO IPV6_LEN DATA EXP_ICMP_CODE EXP_ICMP_CHKSUM
12304 # Causes a packet to be received on INPORT of the hypervisor HV. The packet is an IPv6
12305 # packet with ETH_SRC, ETH_DST, IPV6_SRC, IPV6_DST, IPV6_PROTO, IPV6_LEN and DATA as specified.
12306 # EXP_ICMP_CODE and EXP_ICMP_CHKSUM are the code and checksum of the icmp6 packet sent by OVN logical router
12307 test_ip6_packet() {
12308 local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv6_src=$5 ipv6_dst=$6 ipv6_proto=$7 ipv6_len=$8 data=$9
12309 local exp_icmp_code=${10} exp_icmp_chksum=${11}
12312 local ip6_hdr=60000000${ipv6_len}${ipv6_proto}ff${ipv6_src}${ipv6_dst}
12313 local packet=${eth_dst}${eth_src}86dd${ip6_hdr}${data}
12315 local reply=${eth_src}${eth_dst}86dd6000000000303afe${ipv6_dst}${ipv6_src}${exp_icmp_code}${exp_icmp_chksum}00000000${ip6_hdr}
12316 echo $reply >> vif$inport.expected
12318 as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
12322 printf "%02x%02x%02x%02x" "$@"
12327 ovn-nbctl ls-add sw$i
12331 ovs-vsctl add-br br-phys
12332 ovn_attach n$i br-phys 192.168.$i.1
12334 ovn-nbctl lsp-add sw$i sw$i-p${i}0 -- \
12335 lsp-set-addresses sw$i-p${i}0 "00:00:00:00:00:0$i 192.168.$i.1 2001:db8:$i::11"
12337 ovs-vsctl -- add-port br-int vif$i -- \
12338 set interface vif$i \
12339 external-ids:iface-id=sw$i-p${i}0 \
12340 options:tx_pcap=hv$i/vif$i-tx.pcap \
12341 options:rxq_pcap=hv$i/vif$i-rx.pcap \
12345 ovn-nbctl lr-add lr0
12347 ovn-nbctl lrp-add lr0 lrp$i 00:00:00:00:ff:0$i 192.168.$i.254/24 2001:db8:$i::1/64
12348 ovn-nbctl -- lsp-add sw$i lrp$i-attachment \
12349 -- set Logical_Switch_Port lrp$i-attachment type=router \
12350 options:router-port=lrp$i addresses='"00:00:00:00:ff:0'$i' 192.168.'$i'.254 2001:db8:'$i'::1"'
12354 # allow some time for ovn-northd and ovn-controller to catch up.
12355 ovn-nbctl --wait=hv sync
12357 test_ip_packet 1 1 000000000001 00000000ff01 $(ip_to_hex 192 168 1 1) $(ip_to_hex 192 168 1 254) 11 0000 7dae fcfc 0303
12358 test_ip_packet 1 1 000000000001 00000000ff01 $(ip_to_hex 192 168 1 1) $(ip_to_hex 192 168 1 254) 84 0000 7dae fcfd 0302
12359 test_ip6_packet 1 1 000000000001 00000000ff01 20010db8000100000000000000000011 20010db8000100000000000000000001 11 0015 dbb8303900155bac6b646f65206676676e6d66720a 0104 d570
12360 OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [vif1.expected])
12362 test_tcp_syn_packet 2 2 000000000002 00000000ff02 $(ip_to_hex 192 168 2 1) $(ip_to_hex 192 168 2 254) 0000 8b40 3039 0000 7bae 4486
12363 test_ip6_packet 2 2 000000000002 00000000ff02 20010db8000200000000000000000011 20010db8000200000000000000000001 84 0004 01020304 0103 627e
12364 test_tcp6_packet 2 2 000000000002 00000000ff02 20010db8000200000000000000000011 20010db8000200000000000000000001 8b40 3039 0000 4486
12365 OVN_CHECK_PACKETS([hv2/vif2-tx.pcap], [vif2.expected])
12367 OVN_CLEANUP([hv1], [hv2])
12370 AT_SETUP([ovn -- ovn-controller exit])
12371 AT_SKIP_IF([test $HAVE_PYTHON = no])
12374 # One Logical Router: ro, with two logical switches sw1 and sw2.
12375 # sw1 is for subnet 10.0.0.0/8
12376 # sw2 is for subnet 20.0.0.0/8
12377 # sw1 has a single port bound on hv1
12378 # sw2 has a single port bound on hv2
12380 ovn-nbctl lr-add ro
12381 ovn-nbctl ls-add sw1
12382 ovn-nbctl ls-add sw2
12384 sw1_ro_mac=00:00:10:00:00:01
12386 sw2_ro_mac=00:00:20:00:00:01
12388 sw1_p1_mac=00:00:10:00:00:02
12390 sw2_p1_mac=00:00:20:00:00:02
12393 ovn-nbctl lrp-add ro ro-sw1 $sw1_ro_mac ${sw1_ro_ip}/8
12394 ovn-nbctl lrp-add ro ro-sw2 $sw2_ro_mac ${sw2_ro_ip}/8
12395 ovn-nbctl lsp-add sw1 sw1-ro -- set Logical_Switch_Port sw1-ro type=router \
12396 options:router-port=ro-sw1 addresses=\"$sw1_ro_mac\"
12397 ovn-nbctl lsp-add sw2 sw2-ro -- set Logical_Switch_Port sw2-ro type=router \
12398 options:router-port=ro-sw2 addresses=\"$sw2_ro_mac\"
12400 ovn-nbctl lsp-add sw1 sw1-p1 \
12401 -- lsp-set-addresses sw1-p1 "$sw1_p1_mac $sw1_p1_ip"
12403 ovn-nbctl lsp-add sw2 sw2-p1 \
12404 -- lsp-set-addresses sw2-p1 "$sw2_p1_mac $sw2_p1_ip"
12410 ovs-vsctl add-br br-phys
12411 ovn_attach n1 br-phys 192.168.0.1
12412 ovs-vsctl -- add-port br-int hv1-vif1 -- \
12413 set interface hv1-vif1 external-ids:iface-id=sw1-p1 \
12414 options:tx_pcap=hv1/vif1-tx.pcap \
12415 options:rxq_pcap=hv1/vif1-rx.pcap \
12420 ovs-vsctl add-br br-phys
12421 ovn_attach n1 br-phys 192.168.0.2
12422 ovs-vsctl -- add-port br-int hv2-vif1 -- \
12423 set interface hv2-vif1 external-ids:iface-id=sw2-p1 \
12424 options:tx_pcap=hv2/vif1-tx.pcap \
12425 options:rxq_pcap=hv2/vif1-rx.pcap \
12432 packet="inport==\"sw1-p1\" && eth.src==$sw1_p1_mac && eth.dst==$sw1_ro_mac &&
12433 ip4 && ip.ttl==64 && ip4.src==$sw1_p1_ip && ip4.dst==$sw2_p1_ip &&
12434 udp && udp.src==53 && udp.dst==4369"
12436 # Start by Sending the packet and make sure it makes it there as expected
12437 as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"
12439 # Expected packet has TTL decreased by 1
12440 expected="eth.src==$sw2_ro_mac && eth.dst==$sw2_p1_mac &&
12441 ip4 && ip.ttl==63 && ip4.src==$sw1_p1_ip && ip4.dst==$sw2_p1_ip &&
12442 udp && udp.src==53 && udp.dst==4369"
12443 echo $expected | ovstest test-ovn expr-to-packets > expected
12445 OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
12447 # Stop ovn-controller on hv2
12448 as hv2 ovs-appctl -t ovn-controller exit
12450 # Now send the packet again. This time, it should not arrive.
12451 as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"
12453 OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
12455 # Start ovn-controller again just so OVN_CLEANUP doesn't complain
12456 as hv2 start_daemon ovn-controller
12458 OVN_CLEANUP([hv1],[hv2])
12461 AT_SETUP([ovn -- external logical port])
12462 AT_SKIP_IF([test $HAVE_PYTHON = no])
12470 ovn-nbctl ls-add ls1
12471 ovn-nbctl lsp-add ls1 ls1-lp1 \
12472 -- lsp-set-addresses ls1-lp1 "f0:00:00:00:00:01 10.0.0.4 ae70::4"
12474 # Add a couple of external logical port
12475 ovn-nbctl lsp-add ls1 ls1-lp_ext1 \
12476 -- lsp-set-addresses ls1-lp_ext1 "f0:00:00:00:00:03 10.0.0.6 ae70::6"
12477 ovn-nbctl lsp-set-port-security ls1-lp_ext1 \
12478 "f0:00:00:00:00:03 10.0.0.6 ae70::6"
12479 ovn-nbctl lsp-set-type ls1-lp_ext1 external
12481 ovn-nbctl lsp-add ls1 ls1-lp_ext2 \
12482 -- lsp-set-addresses ls1-lp_ext2 "f0:00:00:00:00:04 10.0.0.7 ae70::7"
12483 ovn-nbctl lsp-set-port-security ls1-lp_ext2 \
12484 "f0:00:00:00:00:04 10.0.0.7 ae70::8"
12485 ovn-nbctl lsp-set-type ls1-lp_ext2 external
12487 d1="$(ovn-nbctl create DHCP_Options cidr=10.0.0.0/24 \
12488 options="\"server_id\"=\"10.0.0.1\" \"server_mac\"=\"ff:10:00:00:00:01\" \
12489 \"lease_time\"=\"3600\" \"router\"=\"10.0.0.1\"")"
12491 d2="$(ovn-nbctl create DHCP_Options cidr="ae70\:\:/64" \
12492 options="\"server_id\"=\"00:00:00:10:00:01\"")"
12494 ovn-nbctl lsp-set-dhcpv4-options ls1-lp1 ${d1}
12495 ovn-nbctl lsp-set-dhcpv4-options ls1-lp_ext1 ${d1}
12496 ovn-nbctl lsp-set-dhcpv4-options ls1-lp_ext2 ${d1}
12498 ovn-nbctl lsp-set-dhcpv6-options ls1-lp1 ${d2}
12499 ovn-nbctl lsp-set-dhcpv6-options ls1-lp_ext1 ${d2}
12500 ovn-nbctl lsp-set-dhcpv6-options ls1-lp_ext2 ${d2}
12502 # Create a logical router and connect it to ls1
12503 ovn-nbctl lr-add lr0
12504 ovn-nbctl lrp-add lr0 lr0-ls1 a0:10:00:00:00:01 10.0.0.1/24
12505 ovn-nbctl lsp-add ls1 ls1-lr0
12506 ovn-nbctl set Logical_Switch_Port ls1-lr0 type=router \
12507 options:router-port=lr0-ls1 addresses=router
12509 # Create HA chassis group
12510 ovn-nbctl ha-chassis-group-add hagrp1
12511 ovn-nbctl ha-chassis-group-add-chassis hagrp1 hv1 30
12513 hagrp1_uuid=`ovn-nbctl --bare --columns _uuid find ha_chassis_group name="hagrp1"`
12515 # There should be 1 HA_Chassis rows with chassis sets
12516 OVS_WAIT_UNTIL([ovn-sbctl list ha_chassis | grep chassis | awk '{print $3}' \
12517 | grep '-' | wc -l ], [0], [1
12521 ovs-vsctl add-br br-phys
12522 ovn_attach n1 br-phys 192.168.0.1
12523 ovs-vsctl -- add-port br-phys hv1-ext1 -- \
12524 set interface hv1-ext1 options:tx_pcap=hv1/ext1-tx.pcap \
12525 options:rxq_pcap=hv1/ext1-rx.pcap \
12527 ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
12530 ovs-vsctl add-br br-phys
12531 ovn_attach n1 br-phys 192.168.0.2
12532 ovs-vsctl -- add-port br-phys hv2-ext2 -- \
12533 set interface hv2-ext2 options:tx_pcap=hv2/ext2-tx.pcap \
12534 options:rxq_pcap=hv2/ext2-rx.pcap \
12536 ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
12539 ovs-vsctl add-br br-phys
12540 ovn_attach n1 br-phys 192.168.0.3
12541 ovs-vsctl -- add-port br-phys hv3-ext3 -- \
12542 set interface hv3-ext3 options:tx_pcap=hv3/ext3-tx.pcap \
12543 options:rxq_pcap=hv3/ext3-rx.pcap \
12545 ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
12547 # No DHCPv4/v6 flows for the external port - ls1-lp_ext1 - 10.0.0.6 in hv1 and
12548 # hv2 as ha-chassis-group is not set and no localnet port added to ls1.
12549 AT_CHECK([ovn-sbctl dump-flows ls1 | grep "offerip = 10.0.0.6" | \
12552 AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
12553 grep controller | grep "0a.00.00.06" | wc -l], [0], [0
12555 AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
12556 grep controller | grep "0a.00.00.06" | wc -l], [0], [0
12558 AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
12559 grep controller | grep tp_src=546 | grep \
12560 "ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.06" | wc -l], [0], [0
12562 AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
12563 grep controller | grep tp_src=546 | grep \
12564 "ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.06" | wc -l], [0], [0
12567 hv1_uuid=$(ovn-sbctl list chassis hv1 | grep uuid | awk '{print $3}')
12568 hv2_uuid=$(ovn-sbctl list chassis hv2 | grep uuid | awk '{print $3}')
12569 hv3_uuid=$(ovn-sbctl list chassis hv3 | grep uuid | awk '{print $3}')
12571 # The port_binding row for ls1-lp_ext1 should have empty chassis
12572 chassis=`ovn-sbctl --bare --columns chassis find port_binding \
12573 logical_port=ls1-lp_ext1`
12575 AT_CHECK([test x$chassis == x], [0], [])
12577 # Associate hagrp1 ha-chassis-group to ls1-lp_ext1
12578 ovn-nbctl --wait=hv set Logical_Switch_Port ls1-lp_ext1 \
12579 ha-chassis-group=$hagrp1_uuid
12581 # Get the hagrp1 uuid in SB DB.
12582 sb_hagrp1_uuid=`ovn-sbctl --bare --columns _uuid find ha_chassis_group \
12585 # Wait till ls1-lp_ext1 port_binding has ha_chassis_group set
12587 [sb_pb_hagrp=`ovn-sbctl --bare --columns ha_chassis_group find \
12588 port_binding logical_port=ls1-lp_ext1`
12589 test "$sb_pb_hagrp" = "$sb_hagrp1_uuid"])
12591 # No DHCPv4/v6 flows for the external port - ls1-lp_ext1 - 10.0.0.6 in hv1 and hv2
12592 # as no localnet port added to ls1 yet.
12593 AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
12594 grep controller | grep "0a.00.00.06" | wc -l], [0], [0
12596 AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
12597 grep controller | grep "0a.00.00.06" | wc -l], [0], [0
12599 AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
12600 grep controller | grep tp_src=546 | grep \
12601 "ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.06" | wc -l], [0], [0
12603 AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
12604 grep controller | grep tp_src=546 | grep \
12605 "ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.06" | wc -l], [0], [0
12608 # Add the localnet port to the logical switch ls1
12609 ovn-nbctl lsp-add ls1 ln-public
12610 ovn-nbctl lsp-set-addresses ln-public unknown
12611 ovn-nbctl lsp-set-type ln-public localnet
12612 ovn-nbctl --wait=hv lsp-set-options ln-public network_name=phys
12614 ln_public_key=$(ovn-sbctl list port_binding ln-public | grep tunnel_key | \
12617 # The ls1-lp_ext1 should be bound to hv1 as only hv1 is part of the
12618 # ha chassis group.
12620 [chassis=`ovn-sbctl --bare --columns chassis find port_binding \
12621 logical_port=ls1-lp_ext1`
12622 test "$chassis" = "$hv1_uuid"])
12624 # There should be DHCPv4/v6 OF flows for the ls1-lp_ext1 port in hv1
12625 AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
12626 grep controller | grep "0a.00.00.06" | grep reg14=0x$ln_public_key | \
12629 AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
12630 grep controller | grep tp_src=546 | grep \
12631 "ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.06" | \
12632 grep reg14=0x$ln_public_key | wc -l], [0], [1
12635 # There should be no DHCPv4/v6 flows for ls1-lp_ext1 on hv2
12636 AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
12637 grep controller | grep "0a.00.00.06" | wc -l], [0], [0
12639 AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
12640 grep controller | grep tp_src=546 | grep \
12641 "ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.06" | wc -l], [0], [0
12644 # No DHCPv4/v6 flows for the external port - ls1-lp_ext2 - 10.0.0.7 in hv1 and
12645 # hv2 as requested-chassis option is not set.
12646 AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
12647 grep controller | grep "0a.00.00.07" | wc -l], [0], [0
12649 AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
12650 grep controller | grep "0a.00.00.07" | wc -l], [0], [0
12652 AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
12653 grep controller | grep tp_src=546 | grep \
12654 "ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.07" | wc -l], [0], [0
12656 AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
12657 grep controller | grep tp_src=546 | grep \
12658 "ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.07" | wc -l], [0], [0
12664 # This shell function sends a DHCP request packet
12665 # test_dhcp INPORT SRC_MAC DHCP_TYPE OFFER_IP ...
12667 local inport=$1 src_mac=$2 dhcp_type=$3 offer_ip=$4 use_ip=$5
12668 shift; shift; shift; shift; shift;
12669 if test $use_ip != 0; then
12674 src_ip=`ip_to_hex 0 0 0 0`
12675 dst_ip=`ip_to_hex 255 255 255 255`
12677 local request=ffffffffffff${src_mac}0800451001100000000080110000${src_ip}${dst_ip}
12678 # udp header and dhcp header
12679 request=${request}0044004300fc0000
12680 request=${request}010106006359aa760000000000000000000000000000000000000000${src_mac}
12681 # client hardware padding
12682 request=${request}00000000000000000000
12684 request=${request}0000000000000000000000000000000000000000000000000000000000000000
12685 request=${request}0000000000000000000000000000000000000000000000000000000000000000
12687 request=${request}0000000000000000000000000000000000000000000000000000000000000000
12688 request=${request}0000000000000000000000000000000000000000000000000000000000000000
12689 request=${request}0000000000000000000000000000000000000000000000000000000000000000
12690 request=${request}0000000000000000000000000000000000000000000000000000000000000000
12691 # dhcp magic cookie
12692 request=${request}63825363
12693 # dhcp message type
12694 request=${request}3501${dhcp_type}ff
12696 local srv_mac=$1 srv_ip=$2 expected_dhcp_opts=$3
12697 # total IP length will be the IP length of the request packet
12698 # (which is 272 in our case) + 8 (padding bytes) + (expected_dhcp_opts / 2)
12699 ip_len=`expr 280 + ${#expected_dhcp_opts} / 2`
12700 udp_len=`expr $ip_len - 20`
12701 ip_len=$(printf "%x" $ip_len)
12702 udp_len=$(printf "%x" $udp_len)
12703 # $ip_len var will be in 3 digits i.e 134. So adding a '0' before $ip_len
12704 local reply=${src_mac}${srv_mac}080045100${ip_len}000000008011XXXX${srv_ip}${offer_ip}
12705 # udp header and dhcp header.
12706 # $udp_len var will be in 3 digits. So adding a '0' before $udp_len
12707 reply=${reply}004300440${udp_len}0000020106006359aa760000000000000000
12709 reply=${reply}${offer_ip}
12710 # next server ip address, relay agent ip address, client mac address
12711 reply=${reply}0000000000000000${src_mac}
12712 # client hardware padding
12713 reply=${reply}00000000000000000000
12715 reply=${reply}0000000000000000000000000000000000000000000000000000000000000000
12716 reply=${reply}0000000000000000000000000000000000000000000000000000000000000000
12718 reply=${reply}0000000000000000000000000000000000000000000000000000000000000000
12719 reply=${reply}0000000000000000000000000000000000000000000000000000000000000000
12720 reply=${reply}0000000000000000000000000000000000000000000000000000000000000000
12721 reply=${reply}0000000000000000000000000000000000000000000000000000000000000000
12722 # dhcp magic cookie
12723 reply=${reply}63825363
12724 # dhcp message type
12725 local dhcp_reply_type=02
12726 if test $dhcp_type = 03; then
12729 reply=${reply}3501${dhcp_reply_type}${expected_dhcp_opts}00000000ff00000000
12730 echo $reply >> ext1_v4.expected
12732 as hv1 ovs-appctl netdev-dummy/receive hv${inport}-ext${inport} $request
12737 sed 's/\(00\)\{1,\}$//'
12740 # This shell function sends a DHCPv6 request packet
12741 # test_dhcpv6 INPORT SRC_MAC SRC_LLA DHCPv6_MSG_TYPE OFFER_IP OUTPORT...
12742 # The OUTPORTs (zero or more) list the VIFs on which the original DHCPv6
12743 # packet should be received twice (one from ovn-controller and the other
12744 # from the "ovs-ofctl monitor br-int resume"
12746 local inport=$1 src_mac=$2 src_lla=$3 msg_code=$4 offer_ip=$5
12747 local req_pkt_in_expected=$6
12748 local request=ffffffffffff${src_mac}86dd00000000002a1101${src_lla}
12750 request=${request}ff020000000000000000000000010002
12751 # udp header and dhcpv6 header
12752 request=${request}02220223002affff${msg_code}010203
12753 # Client identifier
12754 request=${request}0001000a00030001${src_mac}
12755 # IA-NA (Identity Association for Non Temporary Address)
12756 request=${request}0003000c0102030400000e1000001518
12757 shift; shift; shift; shift; shift;
12759 local server_mac=000000100001
12760 local server_lla=fe80000000000000020000fffe100001
12761 local reply_code=07
12762 if test $msg_code = 01; then
12766 if test $offer_ip = 1; then
12769 local reply=${src_mac}${server_mac}86dd0000000000${msg_len}1101
12770 reply=${reply}${server_lla}${src_lla}
12772 # udp header and dhcpv6 header
12773 reply=${reply}0223022200${msg_len}ffff${reply_code}010203
12774 # Client identifier
12775 reply=${reply}0001000a00030001${src_mac}
12777 if test $offer_ip != 1; then
12778 reply=${reply}0003002801020304ffffffffffffffff00050018${offer_ip}
12779 reply=${reply}ffffffffffffffff
12781 # Server identifier
12782 reply=${reply}0002000a00030001${server_mac}
12784 echo $reply | trim_zeros >> ext${inport}_v6.expected
12785 # The inport also receives the request packet since it is connected
12787 #echo $request >> ext${inport}_v6.expected
12789 as hv1 ovs-appctl netdev-dummy/receive hv${inport}-ext${inport} $request
12792 reset_pcap_file() {
12795 ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \
12796 options:rxq_pcap=dummy-rx.pcap
12797 rm -f ${pcap_file}*.pcap
12798 ovs-vsctl -- set Interface $iface options:tx_pcap=${pcap_file}-tx.pcap \
12799 options:rxq_pcap=${pcap_file}-rx.pcap
12803 printf "%02x%02x%02x%02x" "$@"
12806 AT_CAPTURE_FILE([ofctl_monitor0_hv1.log])
12807 as hv1 ovs-ofctl monitor br-int resume --detach --no-chdir \
12808 --pidfile=ovs-ofctl0.pid 2> ofctl_monitor0_hv1.log
12810 AT_CAPTURE_FILE([ofctl_monitor0_hv2.log])
12811 as hv2 ovs-ofctl monitor br-int resume --detach --no-chdir \
12812 --pidfile=ovs-ofctl0.pid 2> ofctl_monitor0_hv2.log
12814 AT_CAPTURE_FILE([ofctl_monitor0_hv3.log])
12815 as hv3 ovs-ofctl monitor br-int resume --detach --no-chdir \
12816 --pidfile=ovs-ofctl0.pid 2> ofctl_monitor0_hv3.log
12819 reset_pcap_file hv1-ext1 hv1/ext1
12821 # Send DHCPDISCOVER.
12822 offer_ip=`ip_to_hex 10 0 0 6`
12823 server_ip=`ip_to_hex 10 0 0 1`
12824 server_mac=ff1000000001
12825 expected_dhcp_opts=330400000e100104ffffff0003040a00000136040a000001
12826 test_dhcp 1 f00000000003 01 $offer_ip 0 $server_mac $server_ip \
12827 $expected_dhcp_opts
12829 # NXT_RESUMEs should be 1 in hv1.
12830 OVS_WAIT_UNTIL([test 1 = `cat ofctl_monitor0_hv1.log | grep -c NXT_RESUME`])
12832 # NXT_RESUMEs should be 0 in hv2.
12833 OVS_WAIT_UNTIL([test 0 = `cat ofctl_monitor0_hv2.log | grep -c NXT_RESUME`])
12835 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/ext1-tx.pcap > ext1_v4.packets
12836 cat ext1_v4.expected | cut -c -48 > expout
12837 AT_CHECK([cat ext1_v4.packets | cut -c -48], [0], [expout])
12838 # Skipping the IPv4 checksum.
12839 cat ext1_v4.expected | cut -c 53- > expout
12840 AT_CHECK([cat ext1_v4.packets | cut -c 53-], [0], [expout])
12842 # ovs-ofctl also resumes the packets and this causes other ports to receive
12843 # the DHCP request packet. So reset the pcap files so that its easier to test.
12845 reset_pcap_file hv1-ext1 hv1/ext1
12847 rm -f ext1_v4.expected
12848 rm -f ext1_v4.packets
12850 # Send DHCPv6 request
12851 src_mac=f00000000003
12852 src_lla=fe80000000000000f20000fffe000003
12853 offer_ip=ae700000000000000000000000000006
12854 test_dhcpv6 1 $src_mac $src_lla 01 $offer_ip
12856 # NXT_RESUMEs should be 2 in hv1.
12857 OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor0_hv1.log | grep -c NXT_RESUME`])
12859 # NXT_RESUMEs should be 0 in hv2.
12860 OVS_WAIT_UNTIL([test 0 = `cat ofctl_monitor0_hv2.log | grep -c NXT_RESUME`])
12862 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/ext1-tx.pcap | \
12863 sort > ext1_v6.packets
12864 cat ext1_v6.expected | cut -c -120 > expout
12865 AT_CHECK([cat ext1_v6.packets | cut -c -120], [0], [expout])
12866 # Skipping the UDP checksum
12867 cat ext1_v6.expected | cut -c 125- > expout
12868 AT_CHECK([cat ext1_v6.packets | cut -c 125-], [0], [expout])
12870 rm -f ext1_v6.expected
12871 rm -f ext1_v6.packets
12874 reset_pcap_file hv1-ext1 hv1/ext1
12876 # Delete the ha-chassis hv1.
12877 ovn-nbctl ha-chassis-group-remove-chassis hagrp1 hv1
12879 [chassis=`ovn-sbctl --bare --columns chassis find port_binding \
12880 logical_port=ls1-lp_ext1`
12881 test "$chassis" = ""])
12883 # Add hv2 to the ha chassis group
12884 ovn-nbctl --wait=hv ha-chassis-group-add-chassis hagrp1 hv2 20
12886 ovn-sbctl list ha_chassis_group
12887 ovn-sbctl list ha_chassis
12889 ovn-sbctl find port_binding logical_port=ls1-lp_ext1
12891 # The ls1-lp_ext1 should be bound to hv2
12893 [chassis=`ovn-sbctl --bare --columns chassis find port_binding \
12894 logical_port=ls1-lp_ext1`
12895 test "$chassis" = "$hv2_uuid"])
12897 # There should be OF flows for DHCP4/v6 for the ls1-lp_ext1 port in hv2
12898 AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
12899 grep controller | grep "0a.00.00.06" | grep reg14=0x$ln_public_key | \
12902 AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
12903 grep controller | grep tp_src=546 | grep \
12904 "ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.06" | \
12905 grep reg14=0x$ln_public_key | wc -l], [0], [1
12908 # There should be no DHCPv4/v6 flows for ls1-lp_ext1 on hv1
12909 AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
12910 grep controller | grep "0a.00.00.06" | wc -l], [0], [0
12912 AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
12913 grep controller | grep tp_src=546 | grep \
12914 "ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.06" | \
12915 grep reg14=0x$ln_public_key | wc -l], [0], [0
12918 # Send DHCPDISCOVER again for hv1/ext1. The DHCP response should come from
12919 # hv2 ovn-controller.
12920 offer_ip=`ip_to_hex 10 0 0 6`
12921 server_ip=`ip_to_hex 10 0 0 1`
12922 server_mac=ff1000000001
12923 expected_dhcp_opts=330400000e100104ffffff0003040a00000136040a000001
12924 test_dhcp 1 f00000000003 01 $offer_ip 0 $server_mac $server_ip \
12925 $expected_dhcp_opts
12927 # NXT_RESUMEs should be 2 in hv1.
12928 OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor0_hv1.log | grep -c NXT_RESUME`])
12930 # NXT_RESUMEs should be 1 in hv2.
12931 OVS_WAIT_UNTIL([test 1 = `cat ofctl_monitor0_hv2.log | grep -c NXT_RESUME`])
12933 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/ext1-tx.pcap > ext1_v4.packets
12934 cat ext1_v4.expected | cut -c -48 > expout
12935 AT_CHECK([cat ext1_v4.packets | cut -c -48], [0], [expout])
12936 # Skipping the IPv4 checksum.
12937 cat ext1_v4.expected | cut -c 53- > expout
12938 AT_CHECK([cat ext1_v4.packets | cut -c 53-], [0], [expout])
12940 # ovs-ofctl also resumes the packets and this causes other ports to receive
12941 # the DHCP request packet. So reset the pcap files so that its easier to test.
12943 reset_pcap_file hv1-ext1 hv1/ext1
12945 rm -f ext1_v4.expected
12947 # Send DHCPv6 request again
12948 src_mac=f00000000003
12949 src_lla=fe80000000000000f20000fffe000003
12950 offer_ip=ae700000000000000000000000000006
12951 test_dhcpv6 1 $src_mac $src_lla 01 $offer_ip 1
12953 # NXT_RESUMEs should be 2 in hv1.
12954 OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor0_hv1.log | grep -c NXT_RESUME`])
12956 # NXT_RESUMEs should be 2 in hv2.
12957 OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor0_hv2.log | grep -c NXT_RESUME`])
12959 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/ext1-tx.pcap | \
12960 sort > ext1_v6.packets
12961 cat ext1_v6.expected | cut -c -120 > expout
12962 AT_CHECK([cat ext1_v6.packets | cut -c -120], [0], [expout])
12963 # Skipping the UDP checksum
12964 cat ext1_v6.expected | cut -c 125- > expout
12965 AT_CHECK([cat ext1_v6.packets | cut -c 125-], [0], [expout])
12967 rm -f ext1_v6.expected
12968 rm -f ext1_v6.packets
12972 reset_pcap_file hv1-ext1 hv1/ext1
12973 reset_pcap_file br-phys_n1 hv1/br-phys_n1
12974 reset_pcap_file br-phys hv1/br-phys
12978 reset_pcap_file hv2-ext2 hv2/ext2
12979 reset_pcap_file br-phys_n1 hv2/br-phys_n1
12980 reset_pcap_file br-phys hv2/br-phys
12982 # From ls1-lp_ext1, send ARP request for the router ip. The ARP
12983 # response should come from the router pipeline of hv2.
12984 ext1_mac=f00000000003
12985 router_mac=a01000000001
12986 ext1_ip=`ip_to_hex 10 0 0 6`
12987 router_ip=`ip_to_hex 10 0 0 1`
12988 arp_request=ffffffffffff${ext1_mac}08060001080006040001${ext1_mac}${ext1_ip}000000000000${router_ip}
12990 as hv1 ovs-appctl netdev-dummy/receive hv1-ext1 $arp_request
12991 expected_response=${src_mac}${router_mac}08060001080006040002${router_mac}${router_ip}${ext1_mac}${ext1_ip}
12992 echo $expected_response > expout
12993 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/ext1-tx.pcap > ext1_arp_resp
12994 AT_CHECK([cat ext1_arp_resp], [0], [expout])
12996 # Verify that the response came from hv2
12997 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv2/br-phys_n1-tx.pcap > ext1_arp_resp
12998 AT_CHECK([cat ext1_arp_resp], [0], [expout])
13000 # Now add 3 ha chassis to the ha chassis group
13001 ovn-nbctl ha-chassis-group-add-chassis hagrp1 hv1 30
13002 ovn-nbctl ha-chassis-group-add-chassis hagrp1 hv2 20
13003 ovn-nbctl ha-chassis-group-add-chassis hagrp1 hv3 10
13005 # hv1 should be master and claim ls1-lp_ext1
13007 [chassis=`ovn-sbctl --bare --columns chassis find port_binding \
13008 logical_port=ls1-lp_ext1`
13009 test "$chassis" = "$hv1_uuid"])
13013 reset_pcap_file hv1-ext1 hv1/ext1
13014 reset_pcap_file br-phys_n1 hv1/br-phys_n1
13015 reset_pcap_file br-phys hv1/br-phys
13019 reset_pcap_file hv2-ext2 hv2/ext2
13020 reset_pcap_file br-phys_n1 hv2/br-phys_n1
13021 reset_pcap_file br-phys hv2/br-phys
13025 reset_pcap_file hv3-ext3 hv3/ext3
13026 reset_pcap_file br-phys_n1 hv3/br-phys_n1
13027 reset_pcap_file br-phys hv3/br-phys
13029 # Send DHCPDISCOVER.
13030 offer_ip=`ip_to_hex 10 0 0 6`
13031 server_ip=`ip_to_hex 10 0 0 1`
13032 server_mac=ff1000000001
13033 expected_dhcp_opts=330400000e100104ffffff0003040a00000136040a000001
13034 test_dhcp 1 f00000000003 01 $offer_ip 0 $server_mac $server_ip \
13035 $expected_dhcp_opts
13037 # NXT_RESUMEs should be 3 in hv1.
13038 OVS_WAIT_UNTIL([test 3 = `cat ofctl_monitor0_hv1.log | grep -c NXT_RESUME`])
13040 # NXT_RESUMEs should be 2 in hv2.
13041 OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor0_hv2.log | grep -c NXT_RESUME`])
13043 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/ext1-tx.pcap > ext1_v4.packets
13044 cat ext1_v4.expected | cut -c -48 > expout
13045 AT_CHECK([cat ext1_v4.packets | cut -c -48], [0], [expout])
13046 # Skipping the IPv4 checksum.
13047 cat ext1_v4.expected | cut -c 53- > expout
13048 AT_CHECK([cat ext1_v4.packets | cut -c 53-], [0], [expout])
13050 # ovs-ofctl also resumes the packets and this causes other ports to receive
13051 # the DHCP request packet. So reset the pcap files so that its easier to test.
13053 reset_pcap_file hv1-ext1 hv1/ext1
13055 rm -f ext1_v4.expected
13056 rm -f ext1_v4.packets
13058 # Send DHCPv6 request
13059 src_mac=f00000000003
13060 src_lla=fe80000000000000f20000fffe000003
13061 offer_ip=ae700000000000000000000000000006
13062 test_dhcpv6 1 $src_mac $src_lla 01 $offer_ip
13064 # NXT_RESUMEs should be 4 in hv1.
13065 OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor0_hv1.log | grep -c NXT_RESUME`])
13067 # NXT_RESUMEs should be 2 in hv2.
13068 OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor0_hv2.log | grep -c NXT_RESUME`])
13070 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/ext1-tx.pcap | \
13071 sort > ext1_v6.packets
13072 cat ext1_v6.expected | cut -c -120 > expout
13073 AT_CHECK([cat ext1_v6.packets | cut -c -120], [0], [expout])
13074 # Skipping the UDP checksum
13075 cat ext1_v6.expected | cut -c 125- > expout
13076 AT_CHECK([cat ext1_v6.packets | cut -c 125-], [0], [expout])
13078 rm -f ext1_v6.expected
13079 rm -f ext1_v6.packets
13080 as hv1 reset_pcap_file hv1-ext1 hv1/ext1
13082 # Now increase the priority of hv3 so it becomes master.
13083 ovn-nbctl ha-chassis-group-add-chassis hagrp1 hv3 50
13085 # hv3 should be master and claim ls1-lp_ext1
13087 [chassis=`ovn-sbctl --bare --columns chassis find port_binding \
13088 logical_port=ls1-lp_ext1`
13089 test "$chassis" = "$hv3_uuid"])
13093 reset_pcap_file hv1-ext1 hv1/ext1
13094 reset_pcap_file br-phys_n1 hv1/br-phys_n1
13095 reset_pcap_file br-phys hv1/br-phys
13099 reset_pcap_file hv2-ext2 hv2/ext2
13100 reset_pcap_file br-phys_n1 hv2/br-phys_n1
13101 reset_pcap_file br-phys hv2/br-phys
13105 reset_pcap_file hv3-ext3 hv3/ext3
13106 reset_pcap_file br-phys_n1 hv3/br-phys_n1
13107 reset_pcap_file br-phys hv3/br-phys
13109 # Send DHCPDISCOVER.
13110 offer_ip=`ip_to_hex 10 0 0 6`
13111 server_ip=`ip_to_hex 10 0 0 1`
13112 server_mac=ff1000000001
13113 expected_dhcp_opts=330400000e100104ffffff0003040a00000136040a000001
13114 test_dhcp 1 f00000000003 01 $offer_ip 0 $server_mac $server_ip \
13115 $expected_dhcp_opts
13117 # NXT_RESUMEs should be 4 in hv1.
13118 OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor0_hv1.log | grep -c NXT_RESUME`])
13120 # NXT_RESUMEs should be 2 in hv2.
13121 OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor0_hv2.log | grep -c NXT_RESUME`])
13123 # NXT_RESUMEs should be 1 in hv3.
13124 OVS_WAIT_UNTIL([test 1 = `cat ofctl_monitor0_hv3.log | grep -c NXT_RESUME`])
13126 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/ext1-tx.pcap > ext1_v4.packets
13127 cat ext1_v4.expected | cut -c -48 > expout
13128 AT_CHECK([cat ext1_v4.packets | cut -c -48], [0], [expout])
13129 # Skipping the IPv4 checksum.
13130 cat ext1_v4.expected | cut -c 53- > expout
13131 AT_CHECK([cat ext1_v4.packets | cut -c 53-], [0], [expout])
13133 # ovs-ofctl also resumes the packets and this causes other ports to receive
13134 # the DHCP request packet. So reset the pcap files so that its easier to test.
13136 reset_pcap_file hv1-ext1 hv1/ext1
13138 rm -f ext1_v4.expected
13139 rm -f ext1_v4.packets
13141 # Send DHCPv6 request
13142 src_mac=f00000000003
13143 src_lla=fe80000000000000f20000fffe000003
13144 offer_ip=ae700000000000000000000000000006
13145 test_dhcpv6 1 $src_mac $src_lla 01 $offer_ip
13147 # NXT_RESUMEs should be 4 in hv1.
13148 OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor0_hv1.log | grep -c NXT_RESUME`])
13150 # NXT_RESUMEs should be 2 in hv2.
13151 OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor0_hv2.log | grep -c NXT_RESUME`])
13153 # NXT_RESUMEs should be 2 in hv3.
13154 OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor0_hv3.log | grep -c NXT_RESUME`])
13156 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/ext1-tx.pcap | \
13157 sort > ext1_v6.packets
13158 cat ext1_v6.expected | cut -c -120 > expout
13159 AT_CHECK([cat ext1_v6.packets | cut -c -120], [0], [expout])
13160 # Skipping the UDP checksum
13161 cat ext1_v6.expected | cut -c 125- > expout
13162 AT_CHECK([cat ext1_v6.packets | cut -c 125-], [0], [expout])
13164 # disconnect hv3 from the network, hv1 should take over
13166 port=${sandbox}_br-phys
13167 as main ovs-vsctl del-port n1 $port
13169 # hv1 should be master and claim ls1-lp_ext1
13171 [chassis=`ovn-sbctl --bare --columns chassis find port_binding \
13172 logical_port=ls1-lp_ext1`
13173 test "$chassis" = "$hv1_uuid"])
13175 OVN_CLEANUP([hv1],[hv2],[hv3])
13178 AT_SETUP([ovn -- Address Set Incremental Processing])
13179 AT_KEYWORDS([ovn_as_inc])
13180 AT_SKIP_IF([test $HAVE_PYTHON = no])
13186 ovs-vsctl add-br br-phys
13187 ovn_attach n1 br-phys 192.168.0.10
13189 ovn-nbctl ls-add ls1
13191 ovn-nbctl lsp-add ls1 lp$i \
13192 -- lsp-set-addresses lp$i "f0:00:00:00:00:0$i 192.168.1.$i"
13194 -- add-port br-int vif$i \
13195 -- set Interface vif$i \
13196 external-ids:iface-id=lp$i
13200 as1_uuid=`ovn-nbctl --wait=hv create addr name=as1`
13201 as2_uuid=`ovn-nbctl --wait=hv create addr name=as2`
13202 ovn-nbctl --wait=hv acl-add ls1 to-lport 200 \
13203 'outport=="lp1" && ip4 && ip4.src == {$as1, $as2}' allow-related
13204 ovn-nbctl --wait=hv set addr as1 addresses="10.1.2.10"
13205 AT_CHECK([ovs-ofctl dump-flows br-int | grep "10.1.2.10"], [0], [ignore])
13207 # Update address set as1
13208 ovn-nbctl --wait=hv set addr as1 addresses="10.1.2.10 10.1.2.11"
13209 AT_CHECK([ovs-ofctl dump-flows br-int | grep "10.1.2.11"], [0], [ignore])
13211 # Update address set as2
13212 ovn-nbctl --wait=hv set addr as2 addresses="10.1.2.12 10.1.2.13"
13213 AT_CHECK([ovs-ofctl dump-flows br-int | grep "10.1.2.12"], [0], [ignore])
13215 # Add another ACL referencing as1
13216 n_flows_before=`ovs-ofctl dump-flows br-int | grep "10.1.2.10" | wc -l`
13217 ovn-nbctl --wait=hv acl-add ls1 to-lport 200 \
13218 'outport=="lp2" && ip4 && ip4.src == $as1' allow-related
13219 n_flows_after=`ovs-ofctl dump-flows br-int | grep "10.1.2.10" | wc -l`
13220 AT_CHECK([test $(expr $n_flows_before \* 2) = $n_flows_after], [0], [ignore])
13223 ovn-nbctl --wait=hv acl-del ls1 to-lport 200 \
13224 'outport=="lp2" && ip4 && ip4.src == $as1'
13225 n_flows_after=`ovs-ofctl dump-flows br-int | grep "10.1.2.10" | wc -l`
13226 AT_CHECK([test $n_flows_before = $n_flows_after], [0], [ignore])
13228 # Remove as1 while it is still used by an ACL, the lflows should be reparsed and
13229 # parsing should fail.
13230 echo "before del as1"
13231 ovn-nbctl list addr | grep as1
13232 ovn-nbctl --wait=hv destroy addr $as1_uuid
13233 echo "after del as1"
13234 ovn-nbctl list addr | grep as1
13235 AT_CHECK([ovs-ofctl dump-flows br-int | grep "10.1.2.10"], [1], [ignore])
13236 AT_CHECK([ovs-ofctl dump-flows br-int | grep "10.1.2.12"], [1], [ignore])
13239 as1_uuid=`ovn-nbctl --wait=hv create addr name=as1`
13240 AT_CHECK([ovs-ofctl dump-flows br-int | grep "10.1.2.12"], [0], [ignore])
13242 # Remove ACLs and address sets
13243 ovn-nbctl --wait=hv destroy addr $as1_uuid -- destroy addr $as2_uuid
13244 AT_CHECK([ovs-ofctl dump-flows br-int | grep "10.1.2.12"], [1], [ignore])
13246 ovn-nbctl --wait=hv acl-del ls1
13249 # Gracefully terminate daemons
13253 AT_SETUP([ovn -- ovn-controller restart])
13254 AT_SKIP_IF([test $HAVE_PYTHON = no])
13258 # One Logical Router: ro, with two logical switches sw1 and sw2.
13259 # sw1 is for subnet 10.0.0.0/8
13260 # sw2 is for subnet 20.0.0.0/8
13261 # sw1 has a single port bound on hv1
13262 # sw2 has a single port bound on hv2
13264 ovn-nbctl lr-add ro
13265 ovn-nbctl ls-add sw1
13266 ovn-nbctl ls-add sw2
13268 sw1_ro_mac=00:00:10:00:00:01
13270 sw2_ro_mac=00:00:20:00:00:01
13272 sw1_p1_mac=00:00:10:00:00:02
13274 sw2_p1_mac=00:00:20:00:00:02
13277 ovn-nbctl lrp-add ro ro-sw1 $sw1_ro_mac ${sw1_ro_ip}/8
13278 ovn-nbctl lrp-add ro ro-sw2 $sw2_ro_mac ${sw2_ro_ip}/8
13279 ovn-nbctl lsp-add sw1 sw1-ro -- set Logical_Switch_Port sw1-ro type=router \
13280 options:router-port=ro-sw1 addresses=\"$sw1_ro_mac\"
13281 ovn-nbctl lsp-add sw2 sw2-ro -- set Logical_Switch_Port sw2-ro type=router \
13282 options:router-port=ro-sw2 addresses=\"$sw2_ro_mac\"
13284 ovn-nbctl lsp-add sw1 sw1-p1 \
13285 -- lsp-set-addresses sw1-p1 "$sw1_p1_mac $sw1_p1_ip"
13287 ovn-nbctl lsp-add sw2 sw2-p1 \
13288 -- lsp-set-addresses sw2-p1 "$sw2_p1_mac $sw2_p1_ip"
13294 ovs-vsctl add-br br-phys
13295 ovn_attach n1 br-phys 192.168.0.1
13296 ovs-vsctl -- add-port br-int hv1-vif1 -- \
13297 set interface hv1-vif1 external-ids:iface-id=sw1-p1 \
13298 options:tx_pcap=hv1/vif1-tx.pcap \
13299 options:rxq_pcap=hv1/vif1-rx.pcap \
13304 ovs-vsctl add-br br-phys
13305 ovn_attach n1 br-phys 192.168.0.2
13306 ovs-vsctl -- add-port br-int hv2-vif1 -- \
13307 set interface hv2-vif1 external-ids:iface-id=sw2-p1 \
13308 options:tx_pcap=hv2/vif1-tx.pcap \
13309 options:rxq_pcap=hv2/vif1-rx.pcap \
13316 packet="inport==\"sw1-p1\" && eth.src==$sw1_p1_mac && eth.dst==$sw1_ro_mac &&
13317 ip4 && ip.ttl==64 && ip4.src==$sw1_p1_ip && ip4.dst==$sw2_p1_ip &&
13318 udp && udp.src==53 && udp.dst==4369"
13320 # Start by Sending the packet and make sure it makes it there as expected
13321 as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"
13323 # Expected packet has TTL decreased by 1
13324 expected="eth.src==$sw2_ro_mac && eth.dst==$sw2_p1_mac &&
13325 ip4 && ip.ttl==63 && ip4.src==$sw1_p1_ip && ip4.dst==$sw2_p1_ip &&
13326 udp && udp.src==53 && udp.dst==4369"
13327 echo $expected | ovstest test-ovn expr-to-packets > expected
13329 OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
13331 # Stop ovn-controller on hv2 with --restart flag
13332 as hv2 ovs-appctl -t ovn-controller exit --restart
13334 # Now send the packet again. This time, it should still arrive
13335 as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"
13337 cat expected expected > expected2
13339 OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected2])
13341 # Start ovn-controller again just so OVN_CLEANUP doesn't complain
13342 as hv2 start_daemon ovn-controller
13344 OVN_CLEANUP([hv1],[hv2])
13349 AT_SETUP([ovn -- ovn-nbctl duplicate addresses])
13352 # Set up a switch with some switch ports of varying address types
13353 ovn-nbctl ls-add sw1
13354 ovn-nbctl set logical_switch sw1 other_config:subnet=192.168.0.0/24
13356 ovn-nbctl lsp-add sw1 sw1-p1
13357 ovn-nbctl lsp-add sw1 sw1-p2
13358 ovn-nbctl lsp-add sw1 sw1-p3
13359 ovn-nbctl lsp-add sw1 sw1-p4
13361 ovn-nbctl lsp-set-addresses sw1-p1 "00:00:00:00:00:01 10.0.0.1 aef0::1" "00:00:00:00:00:02 10.0.0.2 aef0::2"
13362 ovn-nbctl lsp-set-addresses sw1-p2 "00:00:00:00:00:03 dynamic"
13363 ovn-nbctl lsp-set-addresses sw1-p3 "dynamic"
13364 ovn-nbctl lsp-set-addresses sw1-p4 "router"
13365 ovn-nbctl lsp-set-addresses sw1-p5 "unknown"
13367 ovn-nbctl list logical_switch_port
13369 # Now try to add duplicate addresses on a new port. These should all fail
13370 ovn-nbctl --wait=sb lsp-add sw1 sw1-p5
13371 AT_CHECK([ovn-nbctl lsp-set-addresses sw1-p5 "00:00:00:00:00:04 10.0.0.1"], [1], [],
13372 [ovn-nbctl: Error on switch sw1: duplicate IPv4 address 10.0.0.1
13374 AT_CHECK([ovn-nbctl lsp-set-addresses sw1-p5 "00:00:00:00:00:04 10.0.0.2"], [1], [],
13375 [ovn-nbctl: Error on switch sw1: duplicate IPv4 address 10.0.0.2
13377 AT_CHECK([ovn-nbctl lsp-set-addresses sw1-p5 "00:00:00:00:00:04 aef0::1"], [1], [],
13378 [ovn-nbctl: Error on switch sw1: duplicate IPv6 address aef0::1
13380 AT_CHECK([ovn-nbctl lsp-set-addresses sw1-p5 "00:00:00:00:00:04 aef0::2"], [1], [],
13381 [ovn-nbctl: Error on switch sw1: duplicate IPv6 address aef0::2
13383 AT_CHECK([ovn-nbctl lsp-set-addresses sw1-p5 "00:00:00:00:00:04 192.168.0.2"], [1], [],
13384 [ovn-nbctl: Error on switch sw1: duplicate IPv4 address 192.168.0.2
13386 AT_CHECK([ovn-nbctl lsp-set-addresses sw1-p5 "00:00:00:00:00:04 192.168.0.3"], [1], [],
13387 [ovn-nbctl: Error on switch sw1: duplicate IPv4 address 192.168.0.3
13390 # Now try re-setting sw1-p1. This should succeed
13391 AT_CHECK([ovn-nbctl lsp-set-addresses sw1-p1 "00:00:00:00:00:01 10.0.0.1 aef0::1"])
13393 # Now create a new switch and try setting IP addresses the same as the
13394 # first switch. This should succeed.
13395 ovn-nbctl ls-add sw2
13396 ovn-nbctl lsp-add sw2 sw2-p1
13398 AT_CHECK([ovn-nbctl lsp-set-addresses sw2-p1 "00:00:00:00:00:04 10.0.0.1"])
13399 AT_CHECK([ovn-nbctl lsp-set-addresses sw2-p1 "00:00:00:00:00:04 192.168.0.2"])
13400 AT_CHECK([ovn-nbctl lsp-set-addresses sw2-p1 "00:00:00:00:00:04 192.168.0.3"])
13401 AT_CHECK([ovn-nbctl lsp-set-addresses sw2-p1 "00:00:00:00:00:04 aef0::1"])
13405 AT_SETUP([ovn -- router - check packet length - icmp defrag])
13406 AT_KEYWORDS([check packet length])
13407 AT_SKIP_IF([test $HAVE_PYTHON = no])
13410 ovn-nbctl ls-add sw0
13411 ovn-nbctl lsp-add sw0 sw0-port1
13412 ovn-nbctl lsp-set-addresses sw0-port1 "50:54:00:00:00:01 10.0.0.3"
13414 ovn-nbctl lr-add lr0
13415 ovn-nbctl lrp-add lr0 lr0-sw0 00:00:00:00:ff:01 10.0.0.1/24
13416 ovn-nbctl lsp-add sw0 sw0-lr0
13417 ovn-nbctl lsp-set-type sw0-lr0 router
13418 ovn-nbctl lsp-set-addresses sw0-lr0 router
13419 ovn-nbctl lsp-set-options sw0-lr0 router-port=lr0-sw0
13421 ovn-nbctl ls-add public
13422 ovn-nbctl lrp-add lr0 lr0-public 00:00:20:20:12:13 172.168.0.100/24
13423 ovn-nbctl lsp-add public public-lr0
13424 ovn-nbctl lsp-set-type public-lr0 router
13425 ovn-nbctl lsp-set-addresses public-lr0 router
13426 ovn-nbctl lsp-set-options public-lr0 router-port=lr0-public
13429 ovn-nbctl lsp-add public ln-public
13430 ovn-nbctl lsp-set-type ln-public localnet
13431 ovn-nbctl lsp-set-addresses ln-public unknown
13432 ovn-nbctl lsp-set-options ln-public network_name=phys
13434 ovn-nbctl lrp-set-gateway-chassis lr0-public hv1 20
13435 ovn-nbctl lr-nat-add lr0 snat 172.168.0.100 10.0.0.0/24
13441 ovs-vsctl add-br br-phys
13442 ovn_attach n1 br-phys 192.168.0.1
13443 ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
13444 ovs-vsctl -- add-port br-int hv1-vif1 -- \
13445 set interface hv1-vif1 external-ids:iface-id=sw0-port1 \
13446 options:tx_pcap=hv1/vif1-tx.pcap \
13447 options:rxq_pcap=hv1/vif1-rx.pcap \
13450 reset_pcap_file() {
13453 ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \
13454 options:rxq_pcap=dummy-rx.pcap
13455 rm -f ${pcap_file}*.pcap
13456 ovs-vsctl -- set Interface $iface options:tx_pcap=${pcap_file}-tx.pcap \
13457 options:rxq_pcap=${pcap_file}-rx.pcap
13461 printf "%02x%02x%02x%02x" "$@"
13464 test_ip_packet_larger() {
13465 local icmp_pmtu_reply_expected=$1
13467 # Send ip packet from sw0-port1 to outside
13468 src_mac="505400000001" # sw-port1 mac
13469 dst_mac="00000000ff01" # sw0-lr0 mac (internal router leg)
13470 src_ip=`ip_to_hex 10 0 0 3`
13471 dst_ip=`ip_to_hex 172 168 0 3`
13472 # Set the packet length to 100.
13474 packet=${dst_mac}${src_mac}08004500${pkt_len}0000000040010000
13475 orig_packet_l3=${src_ip}${dst_ip}0304000000000000
13476 orig_packet_l3=${orig_packet_l3}000000000000000000000000000000000000
13477 orig_packet_l3=${orig_packet_l3}000000000000000000000000000000000000
13478 orig_packet_l3=${orig_packet_l3}000000000000000000000000000000000000
13479 orig_packet_l3=${orig_packet_l3}000000000000000000000000000000000000
13480 packet=${packet}${orig_packet_l3}
13482 # If icmp_pmtu_reply_expected is 0, it means the packet is lesser than
13483 # the gateway mtu and should be delivered to the provider bridge via the
13485 # If icmp_pmtu_reply_expected is 1, it means the packet is larger than
13486 # the gateway mtu and ovn-controller should drop the packet and instead
13487 # generate ICMPv4 Destination Unreachable message with pmtu set to 42.
13488 if test $icmp_pmtu_reply_expected = 0; then
13489 # Packet to expect at br-phys.
13490 src_mac="000020201213"
13491 dst_mac="00000012af11"
13492 src_ip=`ip_to_hex 10 0 0 3`
13493 dst_ip=`ip_to_hex 172 168 0 3`
13494 expected=${dst_mac}${src_mac}08004500${pkt_len}000000003f010100
13495 expected=${expected}${src_ip}${dst_ip}0304000000000000
13496 expected=${expected}000000000000000000000000000000000000
13497 expected=${expected}000000000000000000000000000000000000
13498 expected=${expected}000000000000000000000000000000000000
13499 expected=${expected}000000000000000000000000000000000000
13500 echo $expected > br_phys_n1.expected
13502 # MTU would be 100 - 18 = 82 (hex 0052)
13504 src_ip=`ip_to_hex 10 0 0 1`
13505 dst_ip=`ip_to_hex 10 0 0 3`
13506 # pkt len should be 128 (28 (icmp packet) + 100 (orig ip + payload))
13509 icmp_reply=${src_mac}${dst_mac}08004500${reply_pkt_len}00004000fe016879
13510 icmp_reply=${icmp_reply}${src_ip}${dst_ip}0304${ip_csum}0000${mtu}
13511 icmp_reply=${icmp_reply}4500${pkt_len}000000003f010100
13512 icmp_reply=${icmp_reply}${orig_packet_l3}
13513 echo $icmp_reply > hv1-vif1.expected
13516 as hv1 reset_pcap_file br-phys_n1 hv1/br-phys_n1
13517 as hv1 reset_pcap_file hv1-vif1 hv1/vif1
13519 # Send packet from sw0-port1 to outside
13520 as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
13522 if test $icmp_pmtu_reply_expected = 0; then
13523 OVN_CHECK_PACKETS([hv1/br-phys_n1-tx.pcap], [br_phys_n1.expected])
13524 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif1-tx.pcap > packets
13525 AT_CHECK([cat packets], [0], [])
13527 OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [hv1-vif1.expected])
13528 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/br-phys_n1-tx.pcap > \
13530 AT_CHECK([cat packets], [0], [])
13537 AT_CHECK([as hv1 ovs-ofctl dump-flows br-int \
13538 | grep "check_pkt_larger" | wc -l], [0], [[0
13540 dp_uuid=$(ovn-sbctl find datapath_binding | grep sw0 -B2 | grep _uuid | \
13542 ovn-sbctl create MAC_Binding ip=172.168.0.3 datapath=$dp_uuid \
13543 logical_port=lr0-public mac="00\:00\:00\:12\:af\:11"
13545 # Set the gateway mtu to 100. If the packet length is > 100, ovn-controller
13546 # should send icmp host not reachable with pmtu set to 100.
13547 ovn-nbctl --wait=hv set logical_router_port lr0-public options:gateway_mtu=100
13548 as hv3 ovs-appctl netdev-dummy/receive hv3-vif1 $arp_reply
13550 test `as hv1 ovs-ofctl dump-flows br-int | grep "check_pkt_larger(100)" | \
13554 icmp_reply_expected=1
13555 test_ip_packet_larger $icmp_reply_expected
13557 # Set the gateway mtu to 500.
13558 ovn-nbctl --wait=hv set logical_router_port lr0-public options:gateway_mtu=500
13559 as hv3 ovs-appctl netdev-dummy/receive hv3-vif1 $arp_reply
13561 test `as hv1 ovs-ofctl dump-flows br-int | grep "check_pkt_larger(500)" | \
13565 # Now the packet should be sent via the localnet port to br-phys.
13566 icmp_reply_expected=0
13567 test_ip_packet_larger $icmp_reply_expected
13571 AT_SETUP([ovn -- IP packet buffering])
13572 AT_KEYWORDS([ip-buffering])
13573 AT_SKIP_IF([test $HAVE_PYTHON = no])
13577 # One LR lr0 that has switches sw0 (192.168.1.0/24) and
13578 # sw1 (172.16.1.0/24) connected to it.
13580 # Physical network:
13581 # Tw0 hypervisors hv[12].
13582 # hv1 hosts vif sw0-p0.
13583 # hv1 hosts vif sw1-p0.
13585 send_icmp_packet() {
13586 local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv4_src=$5 ipv4_dst=$6 ip_chksum=$7 data=$8
13591 local packet=${eth_dst}${eth_src}08004500${ip_len}00004000${ip_ttl}01${ip_chksum}${ipv4_src}${ipv4_dst}${data}
13592 as hv$hv ovs-appctl netdev-dummy/receive hv$hv-vif$inport $packet
13595 send_icmp6_packet() {
13596 local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv6_src=$5 ipv6_dst=$6 ipv6_router=$7 exp_icmp_chksum=$8
13599 local ip6_hdr=6000000000083aff${ipv6_src}${ipv6_dst}
13600 local packet=${eth_dst}${eth_src}86dd${ip6_hdr}8000dcb662f00001
13602 as hv$hv ovs-appctl netdev-dummy/receive hv$hv-vif$inport $packet
13606 local eth_src=$1 spa=$2 tpa=$3
13607 local request=ffffffffffff${eth_src}08060001080006040001${eth_src}${spa}000000000000${tpa}
13612 local hv=$1 inport=$2 eth_src=$3 eth_dst=$4 spa=$5 tpa=$6
13613 local request=${eth_dst}${eth_src}08060001080006040002${eth_src}${spa}${eth_dst}${tpa}
13614 as hv$hv ovs-appctl netdev-dummy/receive hv${hv}-vif$inport $request
13618 local hv=$1 inport=$2 eth_src=$3 eth_dst=$4 src_ip=$5 dst_ip=$6
13619 local ip6_hdr=6000000000203aff${src_ip}${dst_ip}
13620 local request=${eth_dst}${eth_src}86dd${ip6_hdr}8800d78440000000${src_ip}0201${eth_src}
13622 as hv$hv ovs-appctl netdev-dummy/receive hv${hv}-vif$inport $request
13626 local eth_src=$1 src_ip=$2 dst_ip=$3 ta=$4
13627 local ip6_hdr=6000000000203aff${src_ip}${dst_ip}
13628 request=3333ff000010${eth_src}86dd${ip6_hdr}8700357600000000${ta}0101${eth_src}
13637 ovs-vsctl add-br br-phys
13638 ovn_attach n1 br-phys 192.168.0.1
13639 ovs-vsctl -- add-port br-int hv1-vif1 -- \
13640 set interface hv1-vif1 external-ids:iface-id=sw0-p0 \
13641 options:tx_pcap=hv1/vif1-tx.pcap \
13642 options:rxq_pcap=hv1/vif1-rx.pcap \
13647 ovs-vsctl add-br br-phys
13648 ovn_attach n1 br-phys 192.168.0.2
13649 ovs-vsctl -- add-port br-int hv2-vif1 -- \
13650 set interface hv2-vif1 external-ids:iface-id=sw1-p0 \
13651 options:tx_pcap=hv2/vif1-tx.pcap \
13652 options:rxq_pcap=hv2/vif1-rx.pcap \
13655 ovn-nbctl create Logical_Router name=lr0 options:chassis=hv1
13656 ovn-nbctl ls-add sw0
13657 ovn-nbctl ls-add sw1
13659 ovn-nbctl lrp-add lr0 sw0 00:00:01:01:02:03 192.168.1.1/24 2001:0:0:0:0:0:0:1/64
13660 ovn-nbctl lsp-add sw0 rp-sw0 -- set Logical_Switch_Port rp-sw0 \
13661 type=router options:router-port=sw0 \
13662 -- lsp-set-addresses rp-sw0 router
13664 ovn-nbctl lrp-add lr0 sw1 00:00:02:01:02:03 172.16.1.1/24 2002:0:0:0:0:0:0:1/64
13665 ovn-nbctl lsp-add sw1 rp-sw1 -- set Logical_Switch_Port rp-sw1 \
13666 type=router options:router-port=sw1 \
13667 -- lsp-set-addresses rp-sw1 router
13669 ovn-nbctl lsp-add sw0 sw0-p0 \
13670 -- lsp-set-addresses sw0-p0 "f0:00:00:01:02:03 192.168.1.2 2001::2"
13672 ovn-nbctl lsp-add sw1 sw1-p0 \
13673 -- lsp-set-addresses sw1-p0 unknown
13676 ovn-nbctl --wait=hv sync
13679 printf "%02x%02x%02x%02x" "$@"
13682 src_mac=f00000010203
13683 src_ip=$(ip_to_hex 192 168 1 2)
13684 src_ip6=20010000000000000000000000000002
13686 router_mac0=000001010203
13687 router_mac1=000002010203
13688 router_ip=$(ip_to_hex 172 16 1 1)
13689 router_ip6=20020000000000000000000000000001
13691 dst_mac=001122334455
13692 dst_ip=$(ip_to_hex 172 16 1 10)
13693 dst_ip6=20020000000000000000000000000010
13695 data=0800bee4391a0001
13697 send_icmp_packet 1 1 $src_mac $router_mac0 $src_ip $dst_ip 0000 $data
13698 send_arp_reply 2 1 $dst_mac $router_mac1 $dst_ip $router_ip
13699 echo $(get_arp_req $router_mac1 $router_ip $dst_ip) > expected
13700 echo "${dst_mac}${router_mac1}08004500001c00004000fe010100${src_ip}${dst_ip}${data}" >> expected
13702 OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
13704 nd_ip=ff0200000000000000000001ff000010
13705 ip6_hdr=6000000000083afe${src_ip6}${dst_ip6}
13707 send_icmp6_packet 1 1 $src_mac $router_mac0 $src_ip6 $dst_ip6
13708 echo $(get_nd $router_mac1 $src_ip6 $nd_ip $dst_ip6) >> expected
13709 echo "${dst_mac}${router_mac1}86dd${ip6_hdr}8000dcb662f00001" >> expected
13710 send_na 2 1 $dst_mac $router_mac1 $dst_ip6 $router_ip6
13712 OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
13714 OVN_CLEANUP([hv1],[hv2])
13717 AT_SETUP([ovn -- neighbor update on same HV])
13718 AT_SKIP_IF([test $HAVE_PYTHON = no])
13722 # A public switch (pub) with a localnet port connected to two LRs (lr0 and lr1)
13723 # each with a distributed gateway port.
13724 # Two VMs: lp0 on sw0 connected to lr0
13725 # lp1 on sw1 connected to lr1
13727 # This test adds a floating IP to each VM so when they are bound to the same
13728 # hypervisor, it checks that the GARP sent by ovn-controller causes the
13729 # MAC_Binding entries to be updated properly on each logical router.
13730 # It will also capture packets on the physical interface to make sure that the
13731 # GARPs have been sent out to the external network as well.
13733 # Create logical switches
13734 ovn-nbctl ls-add sw0
13735 ovn-nbctl ls-add sw1
13736 ovn-nbctl ls-add pub
13738 # Created localnet port on public switch
13739 ovn-nbctl lsp-add pub ln-pub
13740 ovn-nbctl lsp-set-type ln-pub localnet
13741 ovn-nbctl lsp-set-addresses ln-pub unknown
13742 ovn-nbctl lsp-set-options ln-pub network_name=phys
13744 # Create logical routers and connect them to public switch
13745 ovn-nbctl create Logical_Router name=lr0
13746 ovn-nbctl create Logical_Router name=lr1
13748 ovn-nbctl lrp-add lr0 lr0-pub f0:00:00:00:00:01 172.24.4.220/24
13749 ovn-nbctl lsp-add pub pub-lr0 -- set Logical_Switch_Port pub-lr0 \
13750 type=router options:router-port=lr0-pub options:nat-addresses="router" addresses="router"
13751 ovn-nbctl lrp-add lr1 lr1-pub f0:00:00:00:01:01 172.24.4.221/24
13752 ovn-nbctl lsp-add pub pub-lr1 -- set Logical_Switch_Port pub-lr1 \
13753 type=router options:router-port=lr1-pub options:nat-addresses="router" addresses="router"
13755 ovn-nbctl lrp-set-gateway-chassis lr0-pub hv1 10
13756 ovn-nbctl lrp-set-gateway-chassis lr1-pub hv1 10
13758 # Connect sw0 and sw1 to lr0 and lr1
13759 ovn-nbctl lrp-add lr0 lr0-sw0 00:00:00:00:ff:01 10.0.0.254/24
13760 ovn-nbctl lsp-add sw0 sw0-lr0 -- set Logical_Switch_Port sw0-lr0 type=router \
13761 options:router-port=lr0-sw0 addresses="router"
13762 ovn-nbctl lrp-add lr1 lr1-sw1 00:00:00:00:ff:02 20.0.0.254/24
13763 ovn-nbctl lsp-add sw1 sw1-lr1 -- set Logical_Switch_Port sw1-lr1 type=router \
13764 options:router-port=lr1-sw1 addresses="router"
13768 ovn-nbctl lr-nat-add lr0 snat 172.24.4.220 10.0.0.0/24
13769 ovn-nbctl lr-nat-add lr1 snat 172.24.4.221 20.0.0.0/24
13774 ovs-vsctl add-br br-phys
13775 ovn_attach n1 br-phys 172.24.4.1
13776 ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
13778 ovs-vsctl add-port br-int vif0 -- set Interface vif0 external-ids:iface-id=lp0
13779 ovs-vsctl add-port br-int vif1 -- set Interface vif1 external-ids:iface-id=lp1
13781 ovn-nbctl lsp-add sw0 lp0
13782 ovn-nbctl lsp-add sw1 lp1
13783 ovn-nbctl lsp-set-addresses lp0 "50:54:00:00:00:01 10.0.0.10"
13784 ovn-nbctl lsp-set-addresses lp1 "50:54:00:00:00:02 20.0.0.10"
13786 OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up lp0` = xup])
13787 OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up lp1` = xup])
13789 # Create two floating IPs, one for each VIF
13790 ovn-nbctl lr-nat-add lr0 dnat_and_snat 172.24.4.100 10.0.0.10
13791 ovn-nbctl lr-nat-add lr1 dnat_and_snat 172.24.4.200 20.0.0.10
13793 # Check that the MAC_Binding entries have been properly created
13794 OVS_WAIT_UNTIL([test `ovn-sbctl find mac_binding logical_port="lr0-pub" ip="172.24.4.200" | wc -l` -gt 0])
13795 OVS_WAIT_UNTIL([test `ovn-sbctl find mac_binding logical_port="lr1-pub" ip="172.24.4.100" | wc -l` -gt 0])
13797 # Check that the GARPs went also to the external physical network
13798 # Wait until at least 4 packets have arrived and copy them to a separate file as
13799 # more GARPs are expected in the capture in order to avoid race conditions.
13800 OVS_WAIT_UNTIL([test `$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/br-phys-tx.pcap | wc -l` -gt 4])
13801 $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/br-phys-tx.pcap | head -n4 > hv1/br-phys-tx4.pcap
13803 # GARP for lp0 172.24.4.100 on lr0-pub MAC (f0:00:00:00:00:01)
13804 echo "fffffffffffff0000000000108060001080006040001f00000000001ac180464000000000000ac180464" > expout
13805 # GARP for 172.24.4.220 on lr0-pub (f0:00:00:00:00:01)
13806 echo "fffffffffffff0000000000108060001080006040001f00000000001ac1804dc000000000000ac1804dc" >> expout
13807 # GARP for lp1 172.24.4.200 on lr1-pub MAC (f0:00:00:00:01:01)
13808 echo "fffffffffffff0000000010108060001080006040001f00000000101ac1804c8000000000000ac1804c8" >> expout
13809 # GARP for 172.24.4.221 on lr1-pub (f0:00:00:00:01:01)
13810 echo "fffffffffffff0000000010108060001080006040001f00000000101ac1804dd000000000000ac1804dd" >> expout
13811 AT_CHECK([sort hv1/br-phys-tx4.pcap], [0], [expout])
13812 #OVN_CHECK_PACKETS([hv1/br-phys-tx4.pcap], [br-phys.expected])
13817 AT_SETUP([ovn -- ipam to non-ipam])
13820 ovn-nbctl --wait=hv set NB_Global . options:mac_prefix="0a:00:00:00:00:00"
13821 ovn-nbctl ls-add sw0
13822 ovn-nbctl lsp-add sw0 p0 -- lsp-set-addresses p0 dynamic
13823 ovn-nbctl --wait=sb add Logical-Switch sw0 other_config subnet=192.168.1.0/24
13825 AT_CHECK([ovn-nbctl get Logical-Switch-Port p0 dynamic_addresses], [0],
13826 ["0a:00:00:a8:01:03 192.168.1.2"
13829 ovn-nbctl --wait=sb lsp-set-addresses p0 router
13831 ovn-nbctl get Logical-Switch-Port p0 dynamic_addresses
13833 AT_CHECK([ovn-nbctl get Logical-Switch-Port p0 dynamic_addresses], [0], [[[]]
13837 AT_SETUP([ovn -- ipam router ports])
13840 ovn-nbctl ls-add sw
13841 ovn-nbctl set logical_switch sw other-config:subnet=192.168.1.0/24
13844 ovn-nbctl lr-add ro$i
13845 ovn-nbctl lsp-add sw swp$i
13846 ovn-nbctl --wait=sb lsp-set-addresses swp$i "02:00:00:00:00:0$i dynamic"
13847 cidr=$(ovn-nbctl get logical_switch_port swp$i dynamic_addresses |cut -f2 -d' '|cut -f1 -d\")
13848 ovn-nbctl lrp-add ro$i rop$i 02:00:00:00:00:0$i $cidr/24 -- set logical_switch_port swp$i type=router options:router-port=rop$i addresses=router;
13849 AT_CHECK_UNQUOTED([ovn-nbctl get logical_router_port rop$i networks], [0], [[["192.168.1.$i/24"]]
13853 ovn-nbctl list logical_switch_port
13854 ovn-nbctl list logical_router_port
13858 AT_SETUP([ovn -- test transport zones])
13862 for i in 1 2 3 4 5; do
13865 ovs-vsctl add-br br-phys
13866 ovn_attach n1 br-phys 192.168.$i.1
13869 dnl Wait for the changes to be propagated
13870 ovn-nbctl --wait=sb --timeout=3 sync
13871 ovn-nbctl --wait=hv --timeout=3 sync
13873 dnl Assert that each Chassis has a tunnel formed to every other Chassis
13875 AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | awk NF | sort], [0],
13883 AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | awk NF | sort], [0],
13891 AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | awk NF | sort], [0],
13899 AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | awk NF | sort], [0],
13907 AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | awk NF | sort], [0],
13914 dnl Let's now add some Chassis to different transport zones
13915 dnl * hv1: Will be part of two transport zones: tz1 and tz2 so it
13916 dnl should have tunnels formed between the other two Chassis (hv2 and hv3)
13918 dnl * hv2: Will be part of one transport zone: tz1. It should have a tunnel
13919 dnl to hv1 but not to hv3
13921 dnl * hv3: Will be part of one transport zone: tz2. It should have a tunnel
13922 dnl to hv1 but not to hv2
13924 dnl * hv4 and hv5: Will not have any TZ set so they will keep the tunnels
13925 dnl between themselves and remove the tunnels to other Chassis which now
13926 dnl belongs to some TZs
13929 ovs-vsctl set open . external-ids:ovn-transport-zones=tz1,tz2
13932 ovs-vsctl set open . external-ids:ovn-transport-zones=tz1
13935 ovs-vsctl set open . external-ids:ovn-transport-zones=tz2
13937 dnl Wait for the changes to be propagated
13938 ovn-nbctl --wait=sb --timeout=3 sync
13939 ovn-nbctl --wait=hv --timeout=3 sync
13942 AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | awk NF | sort], [0],
13948 AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | awk NF | sort], [0],
13953 AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | awk NF | sort], [0],
13958 AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | awk NF | sort], [0],
13963 AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | awk NF | sort], [0],
13967 dnl Removing the transport zones should make all Chassis to create
13968 dnl tunnels between every other Chassis again
13971 ovs-vsctl remove open . external-ids ovn-transport-zones
13974 dnl Wait for the changes to be propagated
13975 ovn-nbctl --wait=sb --timeout=3 sync
13976 ovn-nbctl --wait=hv --timeout=3 sync
13979 AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | awk NF | sort], [0],
13987 AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | awk NF | sort], [0],
13995 AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | awk NF | sort], [0],
14003 AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | awk NF | sort], [0],
14011 AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | awk NF | sort], [0],
14018 OVN_CLEANUP([hv1], [hv2], [hv3])