summaryrefslogtreecommitdiff
path: root/tests/ofproto-macros.at
blob: 676d55aa956d1625ff0c42c4007181f28bbb085b (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
m4_divert_push([PREPARE_TESTS])
[
# Strips out uninteresting parts of ovs-ofctl output, as well as parts
# that vary from one run to another.
ofctl_strip () {
    sed '
s/ (xid=0x[0-9a-fA-F]*)//
s/ duration=[0-9.]*s,//
s/ cookie=0x0,//
s/ table=0,//
s/ n_packets=0,//
s/ n_bytes=0,//
s/ idle_age=[0-9]*,//
s/ hard_age=[0-9]*,//
s/dp_hash=0x[0-9a-f]*\//dp_hash=0x0\//
s/recirc_id=0x[0-9a-f]*,/recirc_id=0x0,/
s/[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9]Z|//
s/dir\/[0-9]*\/br0.mgmt/dir\/XXXX\/br0.mgmt/
'
}

# Filter (multiline) vconn debug messages from ovs-vswitchd.log.
# Use with vconn_sub() and ofctl_strip()
print_vconn_debug () { awk -F\| < ovs-vswitchd.log '
BEGIN { prt=0 }
/\|vconn\|DBG\|/ { sub(/[ \t]*$/, ""); print $3 "|" $4 "|" $5; prt=1; next }
$4 != "" { prt=0; next }
prt==1 { sub(/[ \t]*$/, ""); print $0 }
'
}

vconn_sub() {
    sed '
s/tcp:127.0.0.1:[0-9][0-9]*:/unix:/
s/unix#[0-9]*:/unix:/
'
}
]

# PARSE_LISTENING_PORT LOGFILE VARIABLE
#
# Parses the TCP or SSL port on which a server is listening from
# LOGFILE, given that the server was told to listen on a kernel-chosen
# port, and assigns the port number to shell VARIABLE.  You should
# specify the listening remote as ptcp:0:127.0.0.1 or
# pssl:0:127.0.0.1, or the equivalent with [::1] instead of 127.0.0.1.
#
# Here's an example of how to use this with ovsdb-server:
#
#    ovsdb-server --log-file --remote=ptcp:0:127.0.0.1 ...
#    PARSE_LISTENING_PORT([ovsdb-server.log], [TCP_PORT])
#    # Now $TCP_PORT holds the listening port.
m4_define([PARSE_LISTENING_PORT],
    [OVS_WAIT_UNTIL([$2=`sed -n 's/.*0:.*: listening on port \([[0-9]]*\)$/\1/p' "$1"` && test X != X"[$]$2"])])

start_daemon () {
    "$@" -vconsole:off --detach --no-chdir --pidfile --log-file
    pidfile="$OVS_RUNDIR"/$1.pid
    on_exit "test -e \"$pidfile\" && kill \`cat \"$pidfile\"\`"
}

# sim_add SANDBOX
#
# Starts a new simulated Open vSwitch instance named SANDBOX.  Files related to
# the instance, such as logs, databases, sockets, and pidfiles, are created in
# a subdirectory of the main test directory also named SANDBOX.  Afterward, the
# "as" command (see below) can be used to run Open vSwitch utilities in the
# context of the new sandbox.
#
# The new sandbox starts out without any bridges.  Use ovs-vsctl in the context
# of the new sandbox to create a bridge, e.g.:
#
#     sim_add hv0           # Create sandbox hv0.
#     as hv0                # Set hv0 as default sandbox.
#     ovs-vsctl add-br br0  # Add bridge br0 inside hv0.
#
# or:
#
#     sim_add hv0
#     as hv0 ovs-vsctl add-br br0
sims=
sim_add () {
   echo "adding simulator '$1'"

   sims="$sims $1"

   # Create sandbox.
   local d="$ovs_base"/$1
   mkdir "$d" || return 1
   ovs_setenv $1

   # Create database and start ovsdb-server.
   : > "$d"/.conf.db.~lock~
   as $1 ovsdb-tool create "$d"/conf.db "$abs_top_srcdir"/vswitchd/vswitch.ovsschema || return 1
   as $1 start_daemon ovsdb-server --remote=punix:"$d"/db.sock || return 1

   # Initialize database.
   as $1 ovs-vsctl --no-wait -- init || return 1

   # Start ovs-vswitchd
   as $1 start_daemon ovs-vswitchd --enable-dummy=system -vvconn -vofproto_dpif -vunixctl
}

# "as $1" sets the OVS_*DIR environment variables to point to $ovs_base/$1.
#
# "as $1 COMMAND..." sets those variables in a subshell and invokes COMMAND
# there.
as() {
    if test "X$2" != X; then
        (ovs_setenv $1; shift; "$@")
    else
        ovs_setenv $1
    fi
}

# Strips 'xid=0x1234' from ovs-ofctl output.
strip_xids () {
    sed 's/ (xid=0x[[0-9a-fA-F]]*)//'
}

# Changes all 'used:...' to say 'used:0.0', to make output easier to compare.
strip_used () {
    sed 's/used:[[0-9]]\.[[0-9]]*/used:0.0/'
}

# Removes all 'duration=...' to make output easier to compare.
strip_duration () {
    sed 's/duration=[[0-9]]*\.[[0-9]]*s,//'
}

# Strips 'ufid:...' from output, to make it easier to compare.
# (ufids are random.)
strip_ufid () {
    sed 's/mega_ufid:[[-0-9a-f]]* //
    s/ufid:[[-0-9a-f]]* //'
}

# Strips packets: and bytes: from output
strip_stats () {
    sed 's/packets:[[0-9]]*/packets:0/
    s/bytes:[[0-9]]*/bytes:0/'
}

# Changes all 'recirc(...)' and 'recirc=...' to say 'recirc(<recirc_id>)' and
# 'recirc=<recirc_id>' respectively.  This should make output easier to
# compare.
strip_recirc() {
   sed 's/recirc_id([[x0-9]]*)/recirc_id(<recirc>)/
        s/recirc_id=[[x0-9]]*/recirc_id=<recirc>/
        s/recirc([[x0-9]]*)/recirc(<recirc>)/'
}
m4_divert_pop([PREPARE_TESTS])

m4_define([TESTABLE_LOG], [-vPATTERN:ANY:'%c|%p|%m'])

# _OVS_VSWITCHD_START([vswitchd-aux-args] [dbinit-aux-args])
#
# Creates an empty database and starts ovsdb-server.
# Starts ovs-vswitchd, with additional arguments 'vswitchd-aux-args'.
# 'dbinit-aux-args' are passed as additional commands to 'ovs-vsctl init'
# before starting ovs-vswitchd.
#
m4_define([_OVS_VSWITCHD_START],
  [dnl Create database.
   touch .conf.db.~lock~
   AT_CHECK([ovsdb-tool create conf.db $abs_top_srcdir/vswitchd/vswitch.ovsschema])

   dnl Start ovsdb-server.
   AT_CHECK([ovsdb-server --detach --no-chdir --pidfile --log-file --remote=punix:$OVS_RUNDIR/db.sock], [0], [], [stderr])
   on_exit "kill `cat ovsdb-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 Initialize database.
   AT_CHECK([ovs-vsctl --no-wait init $2])

   dnl Start ovs-vswitchd.
   AT_CHECK([ovs-vswitchd $1 --detach --no-chdir --pidfile --log-file -vvconn -vofproto_dpif -vunixctl], [0], [], [stderr])
   AT_CAPTURE_FILE([ovs-vswitchd.log])
   on_exit "kill_ovs_vswitchd `cat ovs-vswitchd.pid`"
   AT_CHECK([[sed < stderr '
/ovs_numa|INFO|Discovered /d
/odp_execute_impl|INFO|Action implementation /d
/vlog|INFO|opened log file/d
/vswitchd|INFO|ovs-vswitchd (Open vSwitch)/d
/reconnect|INFO|/d
/dpif_netlink|INFO|Generic Netlink family .ovs_datapath. does not exist/d
/ofproto|INFO|using datapath ID/d
/netdev_linux|INFO|.*device has unknown hardware address family/d
/ofproto|INFO|datapath ID changed to fedcba9876543210/d
/dpdk|INFO|DPDK Disabled - Use other_config:dpdk-init to enable/d
/netlink_socket|INFO|netlink: could not enable listening to all nsid/d
/netdev_offload|INFO|netdev: Flow API Enabled/d
/probe tc:/d
/setting extended ack support failed/d
/tc: Using policy/d']])
])

# OVS_VSWITCHD_START([vsctl-args], [vsctl-output], [=override],
#                    [vswitchd-aux-args])
#
# Creates a database and starts ovsdb-server, starts ovs-vswitchd
# connected to that database, calls ovs-vsctl to create a bridge named
# br0 with predictable settings, passing 'vsctl-args' as additional
# commands to ovs-vsctl.  If 'vsctl-args' causes ovs-vsctl to provide
# output (e.g. because it includes "create" commands) then 'vsctl-output'
# specifies the expected output after filtering through uuidfilt.
#
# If a test needs to use "system" devices (as dummies), then specify
# =override (literally) as the third argument.  Otherwise, system devices
# won't work at all (which makes sense because tests should not access a
# system's real Ethernet devices).
#
# 'vswitchd-aux-args' provides a way to pass extra command line arguments
# to ovs-vswitchd
m4_define([OVS_VSWITCHD_START],
  [_OVS_VSWITCHD_START([--enable-dummy$3 --disable-system --disable-system-route $4])
   AT_CHECK([add_of_br 0 $1 m4_if([$2], [], [], [| uuidfilt])], [0], [$2])
])

# check_logs scans through all *.log files (except '*.log' and testsuite.log)
# and reports all WARN, ERR, EMER log entries.  User can add custom sed filters
# in $1.
m4_divert_push([PREPARE_TESTS])
check_logs () {
    local logs
    for log in *.log; do
        case ${log} in # (
            '*.log'|testsuite.log) ;; # (
            *) logs="${logs} ${log}" ;;
        esac
    done

    # We most notably ignore 'Broken pipe' warnings.  These often and
    # intermittently appear in ovsdb-server.log, because *ctl commands
    # (e.g. ovs-vsctl) exit right after committing a change to the
    # database.  However, in reaction, some daemon may immediately update the
    # database, and this later update may cause database sending update back to
    # *ctl command if *ctl has not exited yet.  If *ctl command exits before
    # the database calls send, the send fails with 'Broken pipe' or
    # 'not connected' depending on system.  Also removes all 'connection reset'
    # warning logs for similar reasons (EPIPE, ENOTCONN or ECONNRESET can be
    # returned on a send depending on whether the peer had unconsumed data
    # when it closed the socket).
    #
    # We also ignore "Dropped # log messages..." messages.  Otherwise, even if
    # we ignore the messages that were rate-limited, we can end up failing just
    # because of the announcement that rate-limiting happened (and in a racy,
    # timing-dependent way, too).
    sed -n "$1
/reset by peer/d
/Broken pipe/d
/is not connected/d
/timeval.*Unreasonably long [[0-9]]*ms poll interval/d
/timeval.*faults: [[0-9]]* minor, [[0-9]]* major/d
/timeval.*disk: [[0-9]]* reads, [[0-9]]* writes/d
/timeval.*context switches: [[0-9]]* voluntary, [[0-9]]* involuntary/d
/ovs_rcu.*blocked [[0-9]]* ms waiting for .* to quiesce/d
/Dropped [[0-9]]* log messages/d
/setting extended ack support failed/d
/|WARN|/p
/|ERR|/p
/|EMER|/p" ${logs}
}

# add_of_br BRNUM [ARG...]
add_of_br () {
    local brnum=$1; shift
    local br=br$brnum
    local dpid=fedcba987654321$brnum
    local mac=aa:55:aa:55:00:0$brnum
    ovs-vsctl \
        -- add-br $br \
        -- set bridge $br datapath-type=dummy \
                          fail-mode=secure \
                          other-config:datapath-id=$dpid \
                          other-config:hwaddr=$mac \
                          protocols="[[OpenFlow10,OpenFlow11,OpenFlow12,\
                                       OpenFlow13,OpenFlow14,OpenFlow15]]" \
        -- "$@"
}

# add_of_ports__ PORT_TYPE [--pcap] BRIDGE PNUM...
#
# Creates PORT_TYPE interfaces in BRIDGE named pPNUM, OpenFlow port number
# PNUM, and datapath port number PNUM (the latter is a consequence of
# the dummy implementation, which tries to assign datapath port
# numbers based on port names).
#
# If --pcap is supplied then packets received from the interface will
# be written to $port-rx.pcap and those sent to it to $port-tx.pcap.
add_of_ports__ () {
    local args
    local pcap=false
    local ptype=$1
    shift
    if test "$1" = --pcap; then
        pcap=:
    shift
    fi
    local br=$1; shift
    for pnum; do
        AS_VAR_APPEND([args], [" -- add-port $br p$pnum -- set Interface p$pnum type=$ptype ofport_request=$pnum"])
    if $pcap; then
        AS_VAR_APPEND([args], [" -- set Interface p$pnum options:rxq_pcap=p$pnum-rx.pcap options:tx_pcap=p$pnum-tx.pcap"])
    fi
    done
    echo ovs-vsctl $args
    ovs-vsctl $args
}

# add_of_ports [--pcap] BRIDGE PNUM...
#
add_of_ports () {
    add_of_ports__ dummy $@
}

# add_pmd_of_ports [--pcap] BRIDGE PNUM...
#
add_pmd_of_ports () {
    add_of_ports__ dummy-pmd $@
}

m4_divert_pop([PREPARE_TESTS])

# OVS_VSWITCHD_STOP([ALLOWLIST])
#
# Gracefully stops ovs-vswitchd and ovsdb-server, checking their log files
# for messages with severity WARN or higher and signaling an error if any
# is present.  The optional ALLOWLIST may contain shell-quoted "sed"
# commands to delete any warnings that are actually expected, e.g.:
#
#   OVS_VSWITCHD_STOP(["/expected error/d"])
m4_define([OVS_VSWITCHD_STOP],
  [AT_CHECK([check_logs $1])
   OVS_APP_EXIT_AND_WAIT([ovs-vswitchd])
   OVS_APP_EXIT_AND_WAIT([ovsdb-server])])

m4_define([OVS_VSWITCHD_DISABLE_TUNNEL_PUSH_POP],
  [AT_CHECK([ovs-appctl dpif/set-dp-features br0 tnl_push_pop false], [0])
])

# WAIT_FOR_DUMMY_PORTS(NETDEV_DUMMY_PORT[, NETDEV_DUMMY_PORT...])
#
# Wait until the netdev dummy ports are connected to each other
m4_define([WAIT_FOR_DUMMY_PORTS], \
  [m4_foreach([dummy_port], [$@],
      [  \
         OVS_WAIT_WHILE([ovs-appctl netdev-dummy/conn-state dummy_port \
                  | grep 'unknown\|disconnected'])])])