summaryrefslogtreecommitdiff
path: root/tests/ovn-controller-vtep.at
blob: 9b9e42115678b37e412535fe34c8dc06b67e250e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
AT_BANNER([ovn_controller_vtep])

# OVN_CONTROLLER_VTEP_START
#
# Starts the test with a setup with vtep device.  Each test case must first
# call this macro.
#
# Uses vtep-ovs to simulate the vtep switch 'br-vtep' with two physical ports
# 'p0', 'p1'.
#
# Configures ovn-nb with a logical switch 'br-test'.
#
#
m4_define([OVN_CONTROLLER_VTEP_START],
  [
   AT_KEYWORDS([ovn])
   # this will cause skip when 'make check' using Windows setup.
   AT_SKIP_IF([test $HAVE_PYTHON = no])

   dnl Create databases (ovn-nb, ovn-sb, vtep).
   AT_CHECK([ovsdb-tool create vswitchd.db $abs_top_srcdir/vswitchd/vswitch.ovsschema])
   for daemon in ovn-nb ovn-sb vtep; do
      AT_CHECK([ovsdb-tool create $daemon.db $abs_top_srcdir/${daemon%%-*}/${daemon}.ovsschema])
   done

   dnl Start ovsdb-server.
   AT_CHECK([ovsdb-server --detach --no-chdir --pidfile --log-file --remote=punix:$OVS_RUNDIR/db.sock vswitchd.db vtep.db], [0], [], [stderr])
   AT_CHECK([ovsdb-server --detach --no-chdir --pidfile=ovsdb-nb-server.pid --log-file=ovsdb-nb-server.log --remote=punix:$OVS_RUNDIR/ovnnb_db.sock ovn-nb.db], [0], [], [stderr])
   AT_CHECK([ovsdb-server --detach --no-chdir --pidfile=ovsdb-sb-server.pid --log-file=ovsdb-sb-server.log --remote=punix:$OVS_RUNDIR/ovnsb_db.sock ovn-sb.db ovn-sb.db], [0], [], [stderr])
   on_exit "kill `cat ovsdb-server.pid` `cat ovsdb-nb-server.pid` `cat ovsdb-sb-server.pid`"
   AT_CHECK([[sed < stderr '
/vlog|INFO|opened log file/d
/ovsdb_server|INFO|ovsdb-server (Open vSwitch)/d']])
   AT_CAPTURE_FILE([ovsdb-server.log])

   dnl Start ovs-vswitchd.
   AT_CHECK([ovs-vswitchd --enable-dummy=system --disable-system --detach --no-chdir --pidfile --log-file -vvconn -vofproto_dpif], [0], [], [stderr])
   AT_CAPTURE_FILE([ovs-vswitchd.log])
   on_exit "kill `cat ovs-vswitchd.pid`"
   AT_CHECK([[sed < stderr '
/ovs_numa|INFO|Discovered /d
/vlog|INFO|opened log file/d
/vswitchd|INFO|ovs-vswitchd (Open vSwitch)/d
/reconnect|INFO|/d
/ofproto|INFO|using datapath ID/d
/ofproto|INFO|datapath ID changed to fedcba9876543210/d']])
   AT_CHECK([ovs-vsctl -- add-br br-vtep \
              -- set bridge br-vtep datapath-type=dummy other-config:datapath-id=fedcba9876543210 other-config:hwaddr=aa:55:aa:55:00:00 protocols=[[OpenFlow10,OpenFlow11,OpenFlow12,OpenFlow13,OpenFlow14,OpenFlow15]] fail-mode=secure \
              -- add-port br-vtep p0 -- set Interface p0 type=dummy ofport_request=1 \
              -- add-port br-vtep p1 -- set Interface p1 type=dummy ofport_request=2])

   dnl Start ovs-vtep.
   AT_CHECK([vtep-ctl add-ps br-vtep -- set Physical_Switch br-vtep tunnel_ips=1.2.3.4])
   AT_CHECK([ovs-vtep --log-file=ovs-vtep.log --pidfile=ovs-vtep.pid --detach br-vtep \], [0], [], [stderr])
   on_exit "kill `cat ovs-vtep.pid`"
   AT_CHECK([[sed < stderr '
/vlog|INFO|opened log file/d']])
   # waits until ovs-vtep starts up.
   OVS_WAIT_UNTIL([test -n "`vtep-ctl show | grep Physical_Port`"])

   dnl Start ovn-northd.
   AT_CHECK([ovn-nbctl ls-add br-test])
   AT_CHECK([ovn-northd --detach --pidfile --log-file], [0], [], [stderr])
   on_exit "kill `cat ovn-northd.pid`"
   AT_CHECK([[sed < stderr '
/vlog|INFO|opened log file/d']])
   AT_CAPTURE_FILE([ovn-northd.log])

   dnl Start ovn-controllger-vtep.
   AT_CHECK([ovn-controller-vtep --detach --pidfile --log-file --vtep-db=unix:$OVS_RUNDIR/db.sock --ovnsb-db=unix:$OVS_RUNDIR/ovnsb_db.sock], [0], [], [stderr])
   AT_CAPTURE_FILE([ovn-controller-vtep.log])
   on_exit "kill `cat ovn-controller-vtep.pid`"
   AT_CHECK([[sed < stderr '
/vlog|INFO|opened log file/d
/reconnect|INFO|/d']])
])

# OVN_CONTROLLER_VTEP_STOP
#
# So many exits... Yeah, we started a lot daemons~
#
m4_define([OVN_CONTROLLER_VTEP_STOP],
  [# removes all 'Broken pipe' warning logs from ovsdb-server.log.  this is in
   # that *ctl command (e.g. ovn-nbctl) exits right after committing the change
   # to database.  however, in reaction, some daemon (e.g. ovn-controller-vtep)
   # may immediately update the database.  this later update may cause database
   # sending update back to *ctl command if *ctl has not proceeded to exit yet.
   # and if *ctl command exits before database calling send, the send from
   # database will fail with 'Broken pipe' error. Also removes all "connection
   # reset" warning logs by a similar rationale (either EPIPE or ECONNRESET can
   # be returned on a send depending on whether the peer had unconsumed data when
   # it closed the socket).
   AT_CHECK([check_logs "$1
/reset by peer/d
/Broken pipe/d"])
   OVS_APP_EXIT_AND_WAIT([ovs-vtep])
   OVS_APP_EXIT_AND_WAIT([ovn-northd])
   OVS_APP_EXIT_AND_WAIT([ovn-controller-vtep])
   OVS_APP_EXIT_AND_WAIT([ovsdb-server])
   OVS_APP_EXIT_AND_WAIT([ovs-vswitchd])])

# Adds logical port for a vtep gateway chassis in ovn-nb database.
#
# $1: logical switch name in ovn-nb database
# $2: logical port name
# $3: physical vtep gateway name
# $4: logical switch name on vtep gateway chassis
m4_define([OVN_NB_ADD_VTEP_PORT], [
AT_CHECK([ovn-nbctl lsp-add $1 $2])

AT_CHECK([ovn-nbctl lsp-set-type $2 vtep])
AT_CHECK([ovn-nbctl lsp-set-options $2 vtep-physical-switch=$3 vtep-logical-switch=$4])
])

##############################################

# tests chassis related updates.
AT_SETUP([ovn-controller-vtep - chassis])
OVN_CONTROLLER_VTEP_START

# verifies the initial ovn-sb db configuration.
OVS_WAIT_UNTIL([test -n "`ovn-sbctl show | grep Chassis`"])
AT_CHECK([ovn-sbctl show], [0], [dnl
Chassis br-vtep
    Encap vxlan
        ip: "1.2.3.4"
        options: {csum="false"}
])

# deletes the chassis via ovn-sbctl and check that it is readded back
# with the log.
AT_CHECK([ovn-sbctl chassis-del br-vtep])
OVS_WAIT_UNTIL([test -n "`grep WARN ovn-controller-vtep.log`"])
AT_CHECK([sed -n 's/^.*\(|WARN|.*\)$/\1/p' ovn-controller-vtep.log], [0], [dnl
|WARN|Chassis for VTEP physical switch (br-vtep) disappears, maybe deleted by ovn-sbctl, adding it back
])

# changes the tunnel_ip on physical switch, watches the update of chassis's
# encap.
AT_CHECK([vtep-ctl set Physical_Switch br-vtep tunnel_ips=1.2.3.5])
OVS_WAIT_UNTIL([test -n "`ovn-sbctl show | grep 1\.2\.3\.5`"])
AT_CHECK([ovn-sbctl --columns=ip list Encap | cut -d ':' -f2 | tr -d ' '], [0], [dnl
"1.2.3.5"
])

# adds vlan_bindings to physical ports.
AT_CHECK([vtep-ctl add-ls lswitch0 -- bind-ls br-vtep p0 100 lswitch0 -- bind-ls br-vtep p0 200 lswitch0 -- bind-ls br-vtep p1 300 lswitch0])
OVS_WAIT_UNTIL([test -n "`ovn-sbctl list Chassis | grep -- lswitch0`"])
AT_CHECK([ovn-sbctl --columns=vtep_logical_switches list Chassis | cut -d ':' -f2 | tr -d ' ' ], [0], [dnl
[["lswitch0"]]
])

# adds another logical switch and new vlan_bindings.
AT_CHECK([vtep-ctl add-ls lswitch1 -- bind-ls br-vtep p0 300 lswitch1])
OVS_WAIT_UNTIL([test -n "`ovn-sbctl list Chassis | grep -- lswitch1`"])
AT_CHECK([ovn-sbctl --columns=vtep_logical_switches list Chassis | cut -d ':' -f2 | tr -d ' '], [0], [dnl
[["lswitch0","lswitch1"]]
])

# unbinds one port from lswitch0, nothing should change.
AT_CHECK([vtep-ctl unbind-ls br-vtep p0 200])
OVS_WAIT_UNTIL([test -z "`vtep-ctl --columns=vlan_bindings list physical_port p0 | grep -- '200='`"])
AT_CHECK([ovn-sbctl --columns=vtep_logical_switches list Chassis | cut -d ':' -f2 | tr -d ' ' ], [0], [dnl
[["lswitch0","lswitch1"]]
])

# unbinds all ports from lswitch0.
AT_CHECK([vtep-ctl unbind-ls br-vtep p0 100 -- unbind-ls br-vtep p1 300])
OVS_WAIT_UNTIL([test -z "`ovn-sbctl list Chassis | grep -- br-vtep_lswitch0`"])
AT_CHECK([ovn-sbctl --columns=vtep_logical_switches list Chassis | cut -d ':' -f2 | tr -d ' ' ], [0], [dnl
[["lswitch1"]]
])

# unbinds all ports from lswitch1.
AT_CHECK([vtep-ctl unbind-ls br-vtep p0 300])
OVS_WAIT_UNTIL([test -z "`ovn-sbctl list Chassis | grep -- br-vtep_lswitch1`"])
AT_CHECK([ovn-sbctl --columns=vtep_logical_switches list Chassis | cut -d ':' -f2 | tr -d ' '], [0], [dnl
[[]]
])

OVN_CONTROLLER_VTEP_STOP([/Chassis for VTEP physical switch (br-vtep) disappears/d])
AT_CLEANUP


# Tests binding updates.
AT_SETUP([ovn-controller-vtep - binding 1])
OVN_CONTROLLER_VTEP_START

# adds logical switch 'lswitch0' and vlan_bindings.
AT_CHECK([vtep-ctl add-ls lswitch0 -- bind-ls br-vtep p0 100 lswitch0 -- bind-ls br-vtep p1 300 lswitch0])
# adds logical switch port in ovn-nb database, and sets the type and options.
OVN_NB_ADD_VTEP_PORT([br-test], [br-vtep_lswitch0], [br-vtep], [lswitch0])
ovn-sbctl --timeout=10 wait-until Port_Binding br-vtep_lswitch0 chassis!='[[]]'
# should see one binding, associated to chassis of 'br-vtep'.
chassis_uuid=$(ovn-sbctl --columns=_uuid list Chassis br-vtep | cut -d ':' -f2 | tr -d ' ')
AT_CHECK_UNQUOTED([ovn-sbctl --columns=chassis list Port_Binding br-vtep_lswitch0 | cut -d ':' -f2 | tr -d ' '], [0], [dnl
${chassis_uuid}
])

# adds another logical switch 'lswitch1' and vlan_bindings.
AT_CHECK([vtep-ctl add-ls lswitch1 -- bind-ls br-vtep p0 200 lswitch1])
# adds logical switch port in ovn-nb database for lswitch1.
OVN_NB_ADD_VTEP_PORT([br-test], [br-vtep_lswitch1], [br-vtep], [lswitch1])
ovn-sbctl --timeout=10 wait-until Port_Binding br-vtep_lswitch1 chassis!='[[]]'
# This is allowed, but not recommended, to have two vlan_bindings (to different vtep logical switches)
# from one vtep gateway physical port in one ovn-nb logical swithch.
AT_CHECK_UNQUOTED([ovn-sbctl --columns=chassis list Port_Binding | cut -d ':' -f2 | tr -d ' ' | sort], [0], [dnl

${chassis_uuid}
${chassis_uuid}
])

# adds another logical switch port in ovn-nb database for lswitch0.
OVN_NB_ADD_VTEP_PORT([br-test], [br-vtep_lswitch0_dup], [br-vtep], [lswitch0])
ovn-sbctl --timeout=10 wait-until Port_Binding br-vtep_lswitch0_dup chassis!='[[]]'
# it is not allowed to have more than one ovn-nb logical port for the same
# vtep logical switch on a vtep gateway chassis, so should still see only
# two port_binding entries bound.
AT_CHECK_UNQUOTED([ovn-sbctl --columns=chassis list Port_Binding | cut -d ':' -f2 | tr -d ' ' | sort | sort -d], [0], [dnl


[[]]
${chassis_uuid}
${chassis_uuid}
])
# confirms the warning log.
AT_CHECK([sed -n 's/^.*\(|WARN|.*\)$/\1/p' ovn-controller-vtep.log | sed 's/([[-_0-9a-z]][[-_0-9a-z]]*)/()/g' | uniq], [0], [dnl
|WARN|logical switch (), on vtep gateway chassis () has already been associated with logical port (), ignore logical port ()
])

# deletes physical ports from vtep.
AT_CHECK([ovs-vsctl del-port p0 -- del-port p1])
OVS_WAIT_UNTIL([test -z "`ovn-sbctl list Chassis | grep -- br-vtep_lswitch`"])
OVS_WAIT_UNTIL([test -z "`vtep-ctl list physical_port p0`"])
OVS_WAIT_UNTIL([test -z "`vtep-ctl list physical_port p1`"])
# should see empty chassis column in both binding entries.
AT_CHECK_UNQUOTED([ovn-sbctl --columns=chassis list Port_Binding | cut -d ':' -f2 | tr -d ' ' | sort], [0], [dnl


[[]]
[[]]
[[]]
])

OVN_CONTROLLER_VTEP_STOP([/has already been associated with logical port/d])
AT_CLEANUP


# Tests corner case: Binding the vtep logical switch from two different
# datapath.
AT_SETUP([ovn-controller-vtep - binding 2])
OVN_CONTROLLER_VTEP_START

# adds logical switch 'lswitch0' and vlan_bindings.
AT_CHECK([vtep-ctl add-ls lswitch0 -- bind-ls br-vtep p0 100 lswitch0])
# adds logical switch port in ovn-nb database, and sets the type and options.
OVN_NB_ADD_VTEP_PORT([br-test], [br-vtep_lswitch0], [br-vtep], [lswitch0])
ovn-sbctl --timeout=10 wait-until Port_Binding br-vtep_lswitch0 chassis!='[[]]'

# adds another lswitch 'br-void' in ovn-nb database.
AT_CHECK([ovn-nbctl ls-add br-void])
# adds another vtep pswitch 'br-vtep-void' in vtep database.
AT_CHECK([vtep-ctl add-ps br-vtep-void -- add-port br-vtep-void p0-void -- bind-ls br-vtep-void p0-void 100 lswitch0])
# adds a conflicting logical port (both br-vtep_lswitch0 and br-vtep-void_lswitch0
# are bound to the same logical switch, but they are on different datapath).
OVN_NB_ADD_VTEP_PORT([br-void], [br-vtep-void_lswitch0], [br-vtep-void], [lswitch0])
ovn-sbctl --timeout=10 wait-until Port_Binding br-vtep_lswitch0
OVS_WAIT_UNTIL([test -n "`grep WARN ovn-controller-vtep.log`"])
# confirms the warning log.
AT_CHECK([sed -n 's/^.*\(|WARN|.*\)$/\1/p' ovn-controller-vtep.log | sed 's/([[-_0-9a-z]][[-_0-9a-z]]*)/()/g;s/(with tunnel key [[0-9]][[0-9]]*)/()/g' | uniq], [0], [dnl
|WARN|logical switch (), on vtep gateway chassis () has already been associated with logical datapath (), ignore logical port () which belongs to logical datapath ()
])

# then deletes 'br-void' and 'br-vtep-void', should see 'br-vtep_lswitch0'
# bound correctly.
AT_CHECK([ovn-nbctl ls-del br-void])
# adds another vtep pswitch 'br-vtep-void' in vtep database.
AT_CHECK([vtep-ctl del-ps br-vtep-void])
OVS_WAIT_UNTIL([test -z "`ovn-sbctl list Port_Binding | grep br-vtep-void_lswitch0`"])
chassis_uuid=$(ovn-sbctl --columns=_uuid list Chassis br-vtep | cut -d ':' -f2 | tr -d ' ')
AT_CHECK_UNQUOTED([ovn-sbctl --columns=chassis list Port_Binding br-vtep_lswitch0 | cut -d ':' -f2 | tr -d ' '], [0], [dnl
${chassis_uuid}
])

OVN_CONTROLLER_VTEP_STOP([/has already been associated with logical datapath/d])
AT_CLEANUP


# Tests vtep module vtep logical switch tunnel key update.
AT_SETUP([ovn-controller-vtep - vtep-lswitch])
OVN_CONTROLLER_VTEP_START

# creates the logical switch in vtep and adds the corresponding logical
# port to 'br-test'.
AT_CHECK([vtep-ctl add-ls lswitch0 -- bind-ls br-vtep p0 100 lswitch0])
OVN_NB_ADD_VTEP_PORT([br-test], [br-vtep_lswitch0], [br-vtep], [lswitch0])
OVS_WAIT_UNTIL([test -n "`ovn-sbctl list Port_Binding  | grep -- br-vtep_lswitch0`"])

# retrieves the expected tunnel key.
datapath_uuid=$(ovn-sbctl --columns=datapath list Port_Binding br-vtep_lswitch0 | cut -d ':' -f2 | tr -d ' ')
tunnel_key=$(ovn-sbctl --columns=tunnel_key list Datapath_Binding ${datapath_uuid} | cut -d ':' -f2 | tr -d ' ')
OVS_WAIT_UNTIL([test -z "`vtep-ctl --columns=tunnel_key list Logical_Switch | grep 0`"])
# checks the vtep logical switch tunnel key configuration.
AT_CHECK_UNQUOTED([vtep-ctl --columns=tunnel_key list Logical_Switch | cut -d ':' -f2 | tr -d ' '], [0], [dnl
${tunnel_key}
])

# creates a second physical switch in vtep database, and binds its p0 vlan-100
# to the same logical switch 'lswitch0'.
AT_CHECK([vtep-ctl add-ps br-vtep-void -- add-port br-vtep-void p0 -- bind-ls br-vtep-void p0 100 lswitch0])
OVS_WAIT_UNTIL([test -n "`ovn-sbctl --columns=name list Chassis  | grep -- br-vtep-void`"])
OVN_NB_ADD_VTEP_PORT([br-test], [br-vtep-void_lswitch0], [br-vtep-void], [lswitch0])
OVS_WAIT_UNTIL([test -n "`ovn-sbctl list Port_Binding  | grep -- br-vtep-void_lswitch0`"])

# checks the vtep logical switch tunnel key configuration.
AT_CHECK_UNQUOTED([vtep-ctl --columns=tunnel_key list Logical_Switch | cut -d ':' -f2 | tr -d ' '], [0], [dnl
${tunnel_key}
])

# now, deletes br-vtep-void.
AT_CHECK([vtep-ctl del-ps br-vtep-void])
OVS_WAIT_UNTIL([test -z "`ovn-sbctl --columns=name list Chassis  | grep -- br-vtep-void`"])
# checks the vtep logical switch tunnel key configuration.
AT_CHECK_UNQUOTED([vtep-ctl --columns=tunnel_key list Logical_Switch | cut -d ':' -f2 | tr -d ' '], [0], [dnl
${tunnel_key}
])

# changes the ovn-nb logical port type so that it is no longer
# vtep port.
AT_CHECK([ovn-nbctl lsp-set-type br-vtep_lswitch0 void])
OVS_WAIT_UNTIL([test -z "`vtep-ctl --columns=tunnel_key list Logical_Switch | grep 1`"])
# now should see the tunnel key reset.
AT_CHECK([vtep-ctl --columns=tunnel_key list Logical_Switch | cut -d ':' -f2 | tr -d ' '], [0], [dnl
0
])

OVN_CONTROLLER_VTEP_STOP
AT_CLEANUP


# Tests vtep module 'Ucast_Macs_Remote's.
AT_SETUP([ovn-controller-vtep - vtep-macs 1])
OVN_CONTROLLER_VTEP_START

# creates a simple logical network with the vtep device and a fake hv chassis
# 'ch0'.
AT_CHECK([ovn-nbctl lsp-add br-test vif0])
AT_CHECK([ovn-nbctl lsp-set-addresses vif0 f0:ab:cd:ef:01:02])
AT_CHECK([ovn-nbctl --timeout=10 --wait=sb sync])
AT_CHECK([ovn-sbctl chassis-add ch0 vxlan 1.2.3.5])
AT_CHECK([ovn-sbctl lsp-bind vif0 ch0])

# creates the logical switch in vtep and adds the corresponding logical
# port to 'br-test'.
AT_CHECK([vtep-ctl add-ls lswitch0 -- bind-ls br-vtep p0 100 lswitch0])
OVN_NB_ADD_VTEP_PORT([br-test], [br-vtep_lswitch0], [br-vtep], [lswitch0])
OVS_WAIT_UNTIL([test -n "`ovn-sbctl list Port_Binding  | grep br-vtep_lswitch0`"])

# adds another lswitch 'br-void' in ovn-nb database.
AT_CHECK([ovn-nbctl ls-add br-void])
# adds fake hv chassis 'ch1'.
AT_CHECK([ovn-nbctl lsp-add br-void vif1])
AT_CHECK([ovn-nbctl lsp-set-addresses vif1 f0:ab:cd:ef:01:02])
AT_CHECK([ovn-nbctl --timeout=10 --wait=sb sync])
AT_CHECK([ovn-sbctl chassis-add ch1 vxlan 1.2.3.6])
AT_CHECK([ovn-sbctl lsp-bind vif1 ch1])

# checks Ucast_Macs_Remote creation.
OVS_WAIT_UNTIL([test -n "`vtep-ctl list Ucast_Macs_Remote | grep _uuid`"])
AT_CHECK([vtep-ctl --columns=MAC list Ucast_Macs_Remote | cut -d ':' -f2- | tr -d ' '], [0], [dnl
"f0:ab:cd:ef:01:02"
])

# checks physical locator creation.
OVS_WAIT_UNTIL([test -n "`vtep-ctl list Physical_Locator | grep _uuid`"])
AT_CHECK([vtep-ctl --columns=dst_ip list Physical_Locator | cut -d ':' -f2 | tr -d ' ' | grep -v 1.2.3.4 | sed '/^$/d'], [0], [dnl
"1.2.3.5"
])

# checks tunnel creation by ovs-vtep.
OVS_WAIT_UNTIL([test -n "`ovs-vsctl list Interface bfd1.2.3.5`"])
AT_CHECK([ovs-vsctl --columns=options list Interface bfd1.2.3.5 | cut -d ':' -f2 | tr -d ' '], [0], [dnl
{remote_ip="1.2.3.5"}
])

# adds another mac to logical switch port.
AT_CHECK([ovn-nbctl lsp-set-addresses vif0 f0:ab:cd:ef:01:02 f0:ab:cd:ef:01:03])
OVS_WAIT_UNTIL([test -n "`vtep-ctl list Ucast_Macs_Remote | grep 03`"])
AT_CHECK([vtep-ctl --columns=MAC list Ucast_Macs_Remote | cut -d ':' -f2- | tr -d ' ' | sort], [0], [dnl

"f0:ab:cd:ef:01:02"
"f0:ab:cd:ef:01:03"
])

# removes one mac to logical switch port.
AT_CHECK([ovn-nbctl lsp-set-addresses vif0 f0:ab:cd:ef:01:03])
OVS_WAIT_UNTIL([test -z "`vtep-ctl --columns=MAC list Ucast_Macs_Remote | grep 02`"])
AT_CHECK([vtep-ctl --columns=MAC list Ucast_Macs_Remote | cut -d ':' -f2- | tr -d ' ' | sort], [0], [dnl
"f0:ab:cd:ef:01:03"
])

# migrates mac to logical switch port vif1 on 'br-void'.
AT_CHECK([ovn-nbctl lsp-set-addresses vif0])
AT_CHECK([ovn-nbctl lsp-set-addresses vif1 f0:ab:cd:ef:01:03])
OVS_WAIT_UNTIL([test -z "`vtep-ctl --columns=MAC list Ucast_Macs_Remote | grep 03`"])
AT_CHECK([vtep-ctl --columns=MAC list Ucast_Macs_Remote | cut -d ':' -f2- | tr -d ' ' | sort], [0], [dnl
])

OVN_CONTROLLER_VTEP_STOP
AT_CLEANUP


# Tests vtep module 'Ucast_Macs_Remote's (corner cases).
AT_SETUP([ovn-controller-vtep - vtep-macs 2])
OVN_CONTROLLER_VTEP_START

# creates a simple logical network with the vtep device and a fake hv chassis
# 'ch0'.
AT_CHECK([ovn-nbctl lsp-add br-test vif0])
AT_CHECK([ovn-nbctl lsp-set-addresses vif0 f0:ab:cd:ef:01:02])
AT_CHECK([ovn-nbctl --timeout=10 --wait=sb sync])
AT_CHECK([ovn-sbctl chassis-add ch0 vxlan 1.2.3.5])
AT_CHECK([ovn-sbctl lsp-bind vif0 ch0])

# creates another vif in the same logical switch with duplicate mac.
AT_CHECK([ovn-nbctl lsp-add br-test vif1])
AT_CHECK([ovn-nbctl lsp-set-addresses vif1 f0:ab:cd:ef:01:02])
AT_CHECK([ovn-nbctl --timeout=10 --wait=sb sync])
AT_CHECK([ovn-sbctl lsp-bind vif1 ch0])

# creates the logical switch in vtep and adds the corresponding logical
# port to 'br-test'.
AT_CHECK([vtep-ctl add-ls lswitch0 -- bind-ls br-vtep p0 100 lswitch0])
OVN_NB_ADD_VTEP_PORT([br-test], [br-vtep_lswitch0], [br-vtep], [lswitch0])
OVS_WAIT_UNTIL([test -n "`ovn-sbctl list Port_Binding  | grep br-vtep_lswitch0`"])

# checks Ucast_Macs_Remote creation.  Should still only be one entry, since duplicate
# mac in the same logical switch is not allowed.
OVS_WAIT_UNTIL([test -n "`vtep-ctl list Ucast_Macs_Remote | grep _uuid`"])
AT_CHECK([vtep-ctl --columns=MAC list Ucast_Macs_Remote | cut -d ':' -f2- | tr -d ' '], [0], [dnl
"f0:ab:cd:ef:01:02"
])
# confirms the warning log.
OVS_WAIT_UNTIL([test -n "`grep WARN ovn-controller-vtep.log`"])
AT_CHECK([sed -n 's/^.*\(|WARN|.*\)$/\1/p' ovn-controller-vtep.log | sed 's/([[-_:0-9a-z]][[-_:0-9a-z]]*)/()/g' | uniq], [0], [dnl
|WARN|MAC address () has already been known to be on logical port () in the same logical datapath, so just ignore this logical port ()
])

# deletes vif1.
AT_CHECK([ovn-nbctl lsp-del vif1])

# adds another lswitch 'br-void' in ovn-nb database.
AT_CHECK([ovn-nbctl ls-add br-void])
# adds fake hv chassis 'ch1' and vif1 with same mac address as vif0.
AT_CHECK([ovn-nbctl lsp-add br-void vif1])
AT_CHECK([ovn-nbctl lsp-set-addresses vif1 f0:ab:cd:ef:01:02])
AT_CHECK([ovn-nbctl --timeout=10 --wait=sb sync])
AT_CHECK([ovn-sbctl chassis-add ch1 vxlan 1.2.3.6])
AT_CHECK([ovn-sbctl lsp-bind vif1 ch1])
OVS_WAIT_UNTIL([test -n "`ovn-sbctl list Port_Binding | grep vif1`"])

# creates another logical switch in vtep and adds the corresponding logical
# port to 'br-void'.
AT_CHECK([vtep-ctl add-ls lswitch1 -- bind-ls br-vtep p0 200 lswitch1])
OVN_NB_ADD_VTEP_PORT([br-void], [br-void_lswitch1], [br-vtep], [lswitch1])
OVS_WAIT_UNTIL([test -n "`ovn-sbctl list Port_Binding  | grep br-void_lswitch1`"])

# checks Ucast_Macs_Remote creation.  Should see two entries since it is allowed
# to have duplicate macs in different logical switches.
OVS_WAIT_UNTIL([test `vtep-ctl --columns=MAC list Ucast_Macs_Remote | grep 02 | wc -l` -gt 1])
AT_CHECK([vtep-ctl --columns=MAC list Ucast_Macs_Remote | cut -d ':' -f2- | tr -d ' ' | sort], [0], [dnl

"f0:ab:cd:ef:01:02"
"f0:ab:cd:ef:01:02"
])

OVN_CONTROLLER_VTEP_STOP([/has already been known to be on logical port/d])
AT_CLEANUP