Branch data Line data Source code
1 : : /* Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Nicira, Inc.
2 : : *
3 : : * Licensed under the Apache License, Version 2.0 (the "License");
4 : : * you may not use this file except in compliance with the License.
5 : : * You may obtain a copy of the License at:
6 : : *
7 : : * http://www.apache.org/licenses/LICENSE-2.0
8 : : *
9 : : * Unless required by applicable law or agreed to in writing, software
10 : : * distributed under the License is distributed on an "AS IS" BASIS,
11 : : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : : * See the License for the specific language governing permissions and
13 : : * limitations under the License. */
14 : :
15 : : #include <config.h>
16 : : #include "ofproto-dpif-upcall.h"
17 : :
18 : : #include <errno.h>
19 : : #include <stdbool.h>
20 : : #include <inttypes.h>
21 : :
22 : : #include "connmgr.h"
23 : : #include "coverage.h"
24 : : #include "cmap.h"
25 : : #include "dpif.h"
26 : : #include "openvswitch/dynamic-string.h"
27 : : #include "fail-open.h"
28 : : #include "guarded-list.h"
29 : : #include "latch.h"
30 : : #include "openvswitch/list.h"
31 : : #include "netlink.h"
32 : : #include "openvswitch/ofpbuf.h"
33 : : #include "ofproto-dpif-ipfix.h"
34 : : #include "ofproto-dpif-sflow.h"
35 : : #include "ofproto-dpif-xlate.h"
36 : : #include "ovs-rcu.h"
37 : : #include "packets.h"
38 : : #include "poll-loop.h"
39 : : #include "seq.h"
40 : : #include "unixctl.h"
41 : : #include "openvswitch/vlog.h"
42 : :
43 : : #define MAX_QUEUE_LENGTH 512
44 : : #define UPCALL_MAX_BATCH 64
45 : : #define REVALIDATE_MAX_BATCH 50
46 : :
47 : 1288 : VLOG_DEFINE_THIS_MODULE(ofproto_dpif_upcall);
48 : :
49 : 71668 : COVERAGE_DEFINE(dumped_duplicate_flow);
50 : 110308 : COVERAGE_DEFINE(dumped_new_flow);
51 : 71788 : COVERAGE_DEFINE(handler_duplicate_upcall);
52 : 71668 : COVERAGE_DEFINE(upcall_ukey_contention);
53 : 71668 : COVERAGE_DEFINE(upcall_ukey_replace);
54 : 71668 : COVERAGE_DEFINE(revalidate_missed_dp_flow);
55 : :
56 : : /* A thread that reads upcalls from dpif, forwards each upcall's packet,
57 : : * and possibly sets up a kernel flow as a cache. */
58 : : struct handler {
59 : : struct udpif *udpif; /* Parent udpif. */
60 : : pthread_t thread; /* Thread ID. */
61 : : uint32_t handler_id; /* Handler id. */
62 : : };
63 : :
64 : : /* In the absence of a multiple-writer multiple-reader datastructure for
65 : : * storing udpif_keys ("ukeys"), we use a large number of cmaps, each with its
66 : : * own lock for writing. */
67 : : #define N_UMAPS 512 /* per udpif. */
68 : : struct umap {
69 : : struct ovs_mutex mutex; /* Take for writing to the following. */
70 : : struct cmap cmap; /* Datapath flow keys. */
71 : : };
72 : :
73 : : /* A thread that processes datapath flows, updates OpenFlow statistics, and
74 : : * updates or removes them if necessary.
75 : : *
76 : : * Revalidator threads operate in two phases: "dump" and "sweep". In between
77 : : * each phase, all revalidators sync up so that all revalidator threads are
78 : : * either in one phase or the other, but not a combination.
79 : : *
80 : : * During the dump phase, revalidators fetch flows from the datapath and
81 : : * attribute the statistics to OpenFlow rules. Each datapath flow has a
82 : : * corresponding ukey which caches the most recently seen statistics. If
83 : : * a flow needs to be deleted (for example, because it is unused over a
84 : : * period of time), revalidator threads may delete the flow during the
85 : : * dump phase. The datapath is not guaranteed to reliably dump all flows
86 : : * from the datapath, and there is no mapping between datapath flows to
87 : : * revalidators, so a particular flow may be handled by zero or more
88 : : * revalidators during a single dump phase. To avoid duplicate attribution
89 : : * of statistics, ukeys are never deleted during this phase.
90 : : *
91 : : * During the sweep phase, each revalidator takes ownership of a different
92 : : * slice of umaps and sweeps through all ukeys in those umaps to figure out
93 : : * whether they need to be deleted. During this phase, revalidators may
94 : : * fetch individual flows which were not dumped during the dump phase to
95 : : * validate them and attribute statistics.
96 : : */
97 : : struct revalidator {
98 : : struct udpif *udpif; /* Parent udpif. */
99 : : pthread_t thread; /* Thread ID. */
100 : : unsigned int id; /* ovsthread_id_self(). */
101 : : };
102 : :
103 : : /* An upcall handler for ofproto_dpif.
104 : : *
105 : : * udpif keeps records of two kind of logically separate units:
106 : : *
107 : : * upcall handling
108 : : * ---------------
109 : : *
110 : : * - An array of 'struct handler's for upcall handling and flow
111 : : * installation.
112 : : *
113 : : * flow revalidation
114 : : * -----------------
115 : : *
116 : : * - Revalidation threads which read the datapath flow table and maintains
117 : : * them.
118 : : */
119 : : struct udpif {
120 : : struct ovs_list list_node; /* In all_udpifs list. */
121 : :
122 : : struct dpif *dpif; /* Datapath handle. */
123 : : struct dpif_backer *backer; /* Opaque dpif_backer pointer. */
124 : :
125 : : struct handler *handlers; /* Upcall handlers. */
126 : : size_t n_handlers;
127 : :
128 : : struct revalidator *revalidators; /* Flow revalidators. */
129 : : size_t n_revalidators;
130 : :
131 : : struct latch exit_latch; /* Tells child threads to exit. */
132 : :
133 : : /* Revalidation. */
134 : : struct seq *reval_seq; /* Incremented to force revalidation. */
135 : : bool reval_exit; /* Set by leader on 'exit_latch. */
136 : : struct ovs_barrier reval_barrier; /* Barrier used by revalidators. */
137 : : struct dpif_flow_dump *dump; /* DPIF flow dump state. */
138 : : long long int dump_duration; /* Duration of the last flow dump. */
139 : : struct seq *dump_seq; /* Increments each dump iteration. */
140 : : atomic_bool enable_ufid; /* If true, skip dumping flow attrs. */
141 : :
142 : : /* These variables provide a mechanism for the main thread to pause
143 : : * all revalidation without having to completely shut the threads down.
144 : : * 'pause_latch' is shared between the main thread and the lead
145 : : * revalidator thread, so when it is desirable to halt revalidation, the
146 : : * main thread will set the latch. 'pause' and 'pause_barrier' are shared
147 : : * by revalidator threads. The lead revalidator will set 'pause' when it
148 : : * observes the latch has been set, and this will cause all revalidator
149 : : * threads to wait on 'pause_barrier' at the beginning of the next
150 : : * revalidation round. */
151 : : bool pause; /* Set by leader on 'pause_latch. */
152 : : struct latch pause_latch; /* Set to force revalidators pause. */
153 : : struct ovs_barrier pause_barrier; /* Barrier used to pause all */
154 : : /* revalidators by main thread. */
155 : :
156 : : /* There are 'N_UMAPS' maps containing 'struct udpif_key' elements.
157 : : *
158 : : * During the flow dump phase, revalidators insert into these with a random
159 : : * distribution. During the garbage collection phase, each revalidator
160 : : * takes care of garbage collecting a slice of these maps. */
161 : : struct umap *ukeys;
162 : :
163 : : /* Datapath flow statistics. */
164 : : unsigned int max_n_flows;
165 : : unsigned int avg_n_flows;
166 : :
167 : : /* Following fields are accessed and modified by different threads. */
168 : : atomic_uint flow_limit; /* Datapath flow hard limit. */
169 : :
170 : : /* n_flows_mutex prevents multiple threads updating these concurrently. */
171 : : atomic_uint n_flows; /* Number of flows in the datapath. */
172 : : atomic_llong n_flows_timestamp; /* Last time n_flows was updated. */
173 : : struct ovs_mutex n_flows_mutex;
174 : :
175 : : /* Following fields are accessed and modified only from the main thread. */
176 : : struct unixctl_conn **conns; /* Connections waiting on dump_seq. */
177 : : uint64_t conn_seq; /* Corresponds to 'dump_seq' when
178 : : conns[n_conns-1] was stored. */
179 : : size_t n_conns; /* Number of connections waiting. */
180 : : };
181 : :
182 : : enum upcall_type {
183 : : BAD_UPCALL, /* Some kind of bug somewhere. */
184 : : MISS_UPCALL, /* A flow miss. */
185 : : SFLOW_UPCALL, /* sFlow sample. */
186 : : FLOW_SAMPLE_UPCALL, /* Per-flow sampling. */
187 : : IPFIX_UPCALL /* Per-bridge sampling. */
188 : : };
189 : :
190 : : enum reval_result {
191 : : UKEY_KEEP,
192 : : UKEY_DELETE,
193 : : UKEY_MODIFY
194 : : };
195 : :
196 : : struct upcall {
197 : : struct ofproto_dpif *ofproto; /* Parent ofproto. */
198 : : const struct recirc_id_node *recirc; /* Recirculation context. */
199 : : bool have_recirc_ref; /* Reference held on recirc ctx? */
200 : :
201 : : /* The flow and packet are only required to be constant when using
202 : : * dpif-netdev. If a modification is absolutely necessary, a const cast
203 : : * may be used with other datapaths. */
204 : : const struct flow *flow; /* Parsed representation of the packet. */
205 : : const ovs_u128 *ufid; /* Unique identifier for 'flow'. */
206 : : unsigned pmd_id; /* Datapath poll mode driver id. */
207 : : const struct dp_packet *packet; /* Packet associated with this upcall. */
208 : : ofp_port_t in_port; /* OpenFlow in port, or OFPP_NONE. */
209 : : uint16_t mru; /* If !0, Maximum receive unit of
210 : : fragmented IP packet */
211 : :
212 : : enum dpif_upcall_type type; /* Datapath type of the upcall. */
213 : : const struct nlattr *userdata; /* Userdata for DPIF_UC_ACTION Upcalls. */
214 : : const struct nlattr *actions; /* Flow actions in DPIF_UC_ACTION Upcalls. */
215 : :
216 : : bool xout_initialized; /* True if 'xout' must be uninitialized. */
217 : : struct xlate_out xout; /* Result of xlate_actions(). */
218 : : struct ofpbuf odp_actions; /* Datapath actions from xlate_actions(). */
219 : : struct flow_wildcards wc; /* Dependencies that megaflow must match. */
220 : : struct ofpbuf put_actions; /* Actions 'put' in the fastpath. */
221 : :
222 : : struct dpif_ipfix *ipfix; /* IPFIX pointer or NULL. */
223 : : struct dpif_sflow *sflow; /* SFlow pointer or NULL. */
224 : :
225 : : struct udpif_key *ukey; /* Revalidator flow cache. */
226 : : bool ukey_persists; /* Set true to keep 'ukey' beyond the
227 : : lifetime of this upcall. */
228 : :
229 : : uint64_t dump_seq; /* udpif->dump_seq at translation time. */
230 : : uint64_t reval_seq; /* udpif->reval_seq at translation time. */
231 : :
232 : : /* Not used by the upcall callback interface. */
233 : : const struct nlattr *key; /* Datapath flow key. */
234 : : size_t key_len; /* Datapath flow key length. */
235 : : const struct nlattr *out_tun_key; /* Datapath output tunnel key. */
236 : :
237 : : uint64_t odp_actions_stub[1024 / 8]; /* Stub for odp_actions. */
238 : : };
239 : :
240 : : /* Ukeys must transition through these states using transition_ukey(). */
241 : : enum ukey_state {
242 : : UKEY_CREATED = 0,
243 : : UKEY_VISIBLE, /* Ukey is in umap, datapath flow install is queued. */
244 : : UKEY_OPERATIONAL, /* Ukey is in umap, datapath flow is installed. */
245 : : UKEY_EVICTING, /* Ukey is in umap, datapath flow delete is queued. */
246 : : UKEY_EVICTED, /* Ukey is in umap, datapath flow is deleted. */
247 : : UKEY_DELETED, /* Ukey removed from umap, ukey free is deferred. */
248 : : };
249 : : #define N_UKEY_STATES (UKEY_DELETED + 1)
250 : :
251 : : /* 'udpif_key's are responsible for tracking the little bit of state udpif
252 : : * needs to do flow expiration which can't be pulled directly from the
253 : : * datapath. They may be created by any handler or revalidator thread at any
254 : : * time, and read by any revalidator during the dump phase. They are however
255 : : * each owned by a single revalidator which takes care of destroying them
256 : : * during the garbage-collection phase.
257 : : *
258 : : * The mutex within the ukey protects some members of the ukey. The ukey
259 : : * itself is protected by RCU and is held within a umap in the parent udpif.
260 : : * Adding or removing a ukey from a umap is only safe when holding the
261 : : * corresponding umap lock. */
262 : : struct udpif_key {
263 : : struct cmap_node cmap_node; /* In parent revalidator 'ukeys' map. */
264 : :
265 : : /* These elements are read only once created, and therefore aren't
266 : : * protected by a mutex. */
267 : : const struct nlattr *key; /* Datapath flow key. */
268 : : size_t key_len; /* Length of 'key'. */
269 : : const struct nlattr *mask; /* Datapath flow mask. */
270 : : size_t mask_len; /* Length of 'mask'. */
271 : : ovs_u128 ufid; /* Unique flow identifier. */
272 : : bool ufid_present; /* True if 'ufid' is in datapath. */
273 : : uint32_t hash; /* Pre-computed hash for 'key'. */
274 : : unsigned pmd_id; /* Datapath poll mode driver id. */
275 : :
276 : : struct ovs_mutex mutex; /* Guards the following. */
277 : : struct dpif_flow_stats stats OVS_GUARDED; /* Last known stats.*/
278 : : long long int created OVS_GUARDED; /* Estimate of creation time. */
279 : : uint64_t dump_seq OVS_GUARDED; /* Tracks udpif->dump_seq. */
280 : : uint64_t reval_seq OVS_GUARDED; /* Tracks udpif->reval_seq. */
281 : : enum ukey_state state OVS_GUARDED; /* Tracks ukey lifetime. */
282 : :
283 : : /* Datapath flow actions as nlattrs. Protected by RCU. Read with
284 : : * ukey_get_actions(), and write with ukey_set_actions(). */
285 : : OVSRCU_TYPE(struct ofpbuf *) actions;
286 : :
287 : : struct xlate_cache *xcache OVS_GUARDED; /* Cache for xlate entries that
288 : : * are affected by this ukey.
289 : : * Used for stats and learning.*/
290 : : union {
291 : : struct odputil_keybuf buf;
292 : : struct nlattr nla;
293 : : } keybuf, maskbuf;
294 : :
295 : : uint32_t key_recirc_id; /* Non-zero if reference is held by the ukey. */
296 : : struct recirc_refs recircs; /* Action recirc IDs with references held. */
297 : : };
298 : :
299 : : /* Datapath operation with optional ukey attached. */
300 : : struct ukey_op {
301 : : struct udpif_key *ukey;
302 : : struct dpif_flow_stats stats; /* Stats for 'op'. */
303 : : struct dpif_op dop; /* Flow operation. */
304 : : };
305 : :
306 : : static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
307 : : static struct ovs_list all_udpifs = OVS_LIST_INITIALIZER(&all_udpifs);
308 : :
309 : : static size_t recv_upcalls(struct handler *);
310 : : static int process_upcall(struct udpif *, struct upcall *,
311 : : struct ofpbuf *odp_actions, struct flow_wildcards *);
312 : : static void handle_upcalls(struct udpif *, struct upcall *, size_t n_upcalls);
313 : : static void udpif_stop_threads(struct udpif *);
314 : : static void udpif_start_threads(struct udpif *, size_t n_handlers,
315 : : size_t n_revalidators);
316 : : static void udpif_pause_revalidators(struct udpif *);
317 : : static void udpif_resume_revalidators(struct udpif *);
318 : : static void *udpif_upcall_handler(void *);
319 : : static void *udpif_revalidator(void *);
320 : : static unsigned long udpif_get_n_flows(struct udpif *);
321 : : static void revalidate(struct revalidator *);
322 : : static void revalidator_pause(struct revalidator *);
323 : : static void revalidator_sweep(struct revalidator *);
324 : : static void revalidator_purge(struct revalidator *);
325 : : static void upcall_unixctl_show(struct unixctl_conn *conn, int argc,
326 : : const char *argv[], void *aux);
327 : : static void upcall_unixctl_disable_megaflows(struct unixctl_conn *, int argc,
328 : : const char *argv[], void *aux);
329 : : static void upcall_unixctl_enable_megaflows(struct unixctl_conn *, int argc,
330 : : const char *argv[], void *aux);
331 : : static void upcall_unixctl_disable_ufid(struct unixctl_conn *, int argc,
332 : : const char *argv[], void *aux);
333 : : static void upcall_unixctl_enable_ufid(struct unixctl_conn *, int argc,
334 : : const char *argv[], void *aux);
335 : : static void upcall_unixctl_set_flow_limit(struct unixctl_conn *conn, int argc,
336 : : const char *argv[], void *aux);
337 : : static void upcall_unixctl_dump_wait(struct unixctl_conn *conn, int argc,
338 : : const char *argv[], void *aux);
339 : : static void upcall_unixctl_purge(struct unixctl_conn *conn, int argc,
340 : : const char *argv[], void *aux);
341 : :
342 : : static struct udpif_key *ukey_create_from_upcall(struct upcall *,
343 : : struct flow_wildcards *);
344 : : static int ukey_create_from_dpif_flow(const struct udpif *,
345 : : const struct dpif_flow *,
346 : : struct udpif_key **);
347 : : static void ukey_get_actions(struct udpif_key *, const struct nlattr **actions,
348 : : size_t *size);
349 : : static bool ukey_install__(struct udpif *, struct udpif_key *ukey)
350 : : OVS_TRY_LOCK(true, ukey->mutex);
351 : : static bool ukey_install(struct udpif *udpif, struct udpif_key *ukey);
352 : : static void transition_ukey(struct udpif_key *ukey, enum ukey_state dst)
353 : : OVS_REQUIRES(ukey->mutex);
354 : : static struct udpif_key *ukey_lookup(struct udpif *udpif,
355 : : const ovs_u128 *ufid,
356 : : const unsigned pmd_id);
357 : : static int ukey_acquire(struct udpif *, const struct dpif_flow *,
358 : : struct udpif_key **result, int *error);
359 : : static void ukey_delete__(struct udpif_key *);
360 : : static void ukey_delete(struct umap *, struct udpif_key *);
361 : : static enum upcall_type classify_upcall(enum dpif_upcall_type type,
362 : : const struct nlattr *userdata);
363 : :
364 : : static void put_op_init(struct ukey_op *op, struct udpif_key *ukey,
365 : : enum dpif_flow_put_flags flags);
366 : : static void delete_op_init(struct udpif *udpif, struct ukey_op *op,
367 : : struct udpif_key *ukey);
368 : :
369 : : static int upcall_receive(struct upcall *, const struct dpif_backer *,
370 : : const struct dp_packet *packet, enum dpif_upcall_type,
371 : : const struct nlattr *userdata, const struct flow *,
372 : : const unsigned int mru,
373 : : const ovs_u128 *ufid, const unsigned pmd_id);
374 : : static void upcall_uninit(struct upcall *);
375 : :
376 : : static upcall_callback upcall_cb;
377 : : static dp_purge_callback dp_purge_cb;
378 : :
379 : : static atomic_bool enable_megaflows = ATOMIC_VAR_INIT(true);
380 : : static atomic_bool enable_ufid = ATOMIC_VAR_INIT(true);
381 : :
382 : : void
383 : 615 : udpif_init(void)
384 : : {
385 : : static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER;
386 [ + - ]: 615 : if (ovsthread_once_start(&once)) {
387 : 615 : unixctl_command_register("upcall/show", "", 0, 0, upcall_unixctl_show,
388 : : NULL);
389 : 615 : unixctl_command_register("upcall/disable-megaflows", "", 0, 0,
390 : : upcall_unixctl_disable_megaflows, NULL);
391 : 615 : unixctl_command_register("upcall/enable-megaflows", "", 0, 0,
392 : : upcall_unixctl_enable_megaflows, NULL);
393 : 615 : unixctl_command_register("upcall/disable-ufid", "", 0, 0,
394 : : upcall_unixctl_disable_ufid, NULL);
395 : 615 : unixctl_command_register("upcall/enable-ufid", "", 0, 0,
396 : : upcall_unixctl_enable_ufid, NULL);
397 : 615 : unixctl_command_register("upcall/set-flow-limit", "", 1, 1,
398 : : upcall_unixctl_set_flow_limit, NULL);
399 : 615 : unixctl_command_register("revalidator/wait", "", 0, 0,
400 : : upcall_unixctl_dump_wait, NULL);
401 : 615 : unixctl_command_register("revalidator/purge", "", 0, 0,
402 : : upcall_unixctl_purge, NULL);
403 : 615 : ovsthread_once_done(&once);
404 : : }
405 : 615 : }
406 : :
407 : : struct udpif *
408 : 614 : udpif_create(struct dpif_backer *backer, struct dpif *dpif)
409 : : {
410 : 614 : struct udpif *udpif = xzalloc(sizeof *udpif);
411 : :
412 : 614 : udpif->dpif = dpif;
413 : 614 : udpif->backer = backer;
414 : 614 : atomic_init(&udpif->flow_limit, MIN(ofproto_flow_limit, 10000));
415 : 614 : udpif->reval_seq = seq_create();
416 : 614 : udpif->dump_seq = seq_create();
417 : 614 : latch_init(&udpif->exit_latch);
418 : 614 : latch_init(&udpif->pause_latch);
419 : 614 : ovs_list_push_back(&all_udpifs, &udpif->list_node);
420 : 614 : atomic_init(&udpif->enable_ufid, false);
421 : 614 : atomic_init(&udpif->n_flows, 0);
422 : 614 : atomic_init(&udpif->n_flows_timestamp, LLONG_MIN);
423 : 614 : ovs_mutex_init(&udpif->n_flows_mutex);
424 : 614 : udpif->ukeys = xmalloc(N_UMAPS * sizeof *udpif->ukeys);
425 [ + + ]: 314982 : for (int i = 0; i < N_UMAPS; i++) {
426 : 314368 : cmap_init(&udpif->ukeys[i].cmap);
427 : 314368 : ovs_mutex_init(&udpif->ukeys[i].mutex);
428 : : }
429 : :
430 : 614 : dpif_register_upcall_cb(dpif, upcall_cb, udpif);
431 : 614 : dpif_register_dp_purge_cb(dpif, dp_purge_cb, udpif);
432 : :
433 : 614 : return udpif;
434 : : }
435 : :
436 : : void
437 : 105699 : udpif_run(struct udpif *udpif)
438 : : {
439 [ + + ][ + - ]: 105699 : if (udpif->conns && udpif->conn_seq != seq_read(udpif->dump_seq)) {
440 : : int i;
441 : :
442 [ + + ]: 20 : for (i = 0; i < udpif->n_conns; i++) {
443 : 10 : unixctl_command_reply(udpif->conns[i], NULL);
444 : : }
445 : 10 : free(udpif->conns);
446 : 10 : udpif->conns = NULL;
447 : 10 : udpif->n_conns = 0;
448 : : }
449 : 105699 : }
450 : :
451 : : void
452 : 614 : udpif_destroy(struct udpif *udpif)
453 : : {
454 : 614 : udpif_stop_threads(udpif);
455 : :
456 : 614 : dpif_register_dp_purge_cb(udpif->dpif, NULL, udpif);
457 : 614 : dpif_register_upcall_cb(udpif->dpif, NULL, udpif);
458 : :
459 [ + + ]: 314982 : for (int i = 0; i < N_UMAPS; i++) {
460 : 314368 : cmap_destroy(&udpif->ukeys[i].cmap);
461 : 314368 : ovs_mutex_destroy(&udpif->ukeys[i].mutex);
462 : : }
463 : 614 : free(udpif->ukeys);
464 : 614 : udpif->ukeys = NULL;
465 : :
466 : 614 : ovs_list_remove(&udpif->list_node);
467 : 614 : latch_destroy(&udpif->exit_latch);
468 : 614 : latch_destroy(&udpif->pause_latch);
469 : 614 : seq_destroy(udpif->reval_seq);
470 : 614 : seq_destroy(udpif->dump_seq);
471 : 614 : ovs_mutex_destroy(&udpif->n_flows_mutex);
472 : 614 : free(udpif);
473 : 614 : }
474 : :
475 : : /* Stops the handler and revalidator threads, must be enclosed in
476 : : * ovsrcu quiescent state unless when destroying udpif. */
477 : : static void
478 : 2881 : udpif_stop_threads(struct udpif *udpif)
479 : : {
480 [ + - ][ + + ]: 2881 : if (udpif && (udpif->n_handlers != 0 || udpif->n_revalidators != 0)) {
[ - + ]
481 : : size_t i;
482 : :
483 : 2266 : latch_set(&udpif->exit_latch);
484 : :
485 [ + + ]: 4532 : for (i = 0; i < udpif->n_handlers; i++) {
486 : 2266 : struct handler *handler = &udpif->handlers[i];
487 : :
488 : 2266 : xpthread_join(handler->thread, NULL);
489 : : }
490 : :
491 [ + + ]: 4535 : for (i = 0; i < udpif->n_revalidators; i++) {
492 : 2269 : xpthread_join(udpif->revalidators[i].thread, NULL);
493 : : }
494 : :
495 : 2266 : dpif_disable_upcall(udpif->dpif);
496 : :
497 [ + + ]: 4535 : for (i = 0; i < udpif->n_revalidators; i++) {
498 : 2269 : struct revalidator *revalidator = &udpif->revalidators[i];
499 : :
500 : : /* Delete ukeys, and delete all flows from the datapath to prevent
501 : : * double-counting stats. */
502 : 2269 : revalidator_purge(revalidator);
503 : : }
504 : :
505 : 2266 : latch_poll(&udpif->exit_latch);
506 : :
507 : 2266 : ovs_barrier_destroy(&udpif->reval_barrier);
508 : 2266 : ovs_barrier_destroy(&udpif->pause_barrier);
509 : :
510 : 2266 : free(udpif->revalidators);
511 : 2266 : udpif->revalidators = NULL;
512 : 2266 : udpif->n_revalidators = 0;
513 : :
514 : 2266 : free(udpif->handlers);
515 : 2266 : udpif->handlers = NULL;
516 : 2266 : udpif->n_handlers = 0;
517 : : }
518 : 2881 : }
519 : :
520 : : /* Starts the handler and revalidator threads, must be enclosed in
521 : : * ovsrcu quiescent state. */
522 : : static void
523 : 2267 : udpif_start_threads(struct udpif *udpif, size_t n_handlers,
524 : : size_t n_revalidators)
525 : : {
526 [ + - ][ + + ]: 2267 : if (udpif && n_handlers && n_revalidators) {
[ + - ]
527 : : size_t i;
528 : : bool enable_ufid;
529 : :
530 : 2266 : udpif->n_handlers = n_handlers;
531 : 2266 : udpif->n_revalidators = n_revalidators;
532 : :
533 : 2266 : udpif->handlers = xzalloc(udpif->n_handlers * sizeof *udpif->handlers);
534 [ + + ]: 4532 : for (i = 0; i < udpif->n_handlers; i++) {
535 : 2266 : struct handler *handler = &udpif->handlers[i];
536 : :
537 : 2266 : handler->udpif = udpif;
538 : 2266 : handler->handler_id = i;
539 : 2266 : handler->thread = ovs_thread_create(
540 : : "handler", udpif_upcall_handler, handler);
541 : : }
542 : :
543 : 2266 : enable_ufid = ofproto_dpif_get_enable_ufid(udpif->backer);
544 : 2266 : atomic_init(&udpif->enable_ufid, enable_ufid);
545 : 2266 : dpif_enable_upcall(udpif->dpif);
546 : :
547 : 2266 : ovs_barrier_init(&udpif->reval_barrier, udpif->n_revalidators);
548 : 2266 : ovs_barrier_init(&udpif->pause_barrier, udpif->n_revalidators + 1);
549 : 2266 : udpif->reval_exit = false;
550 : 2266 : udpif->pause = false;
551 : 2266 : udpif->revalidators = xzalloc(udpif->n_revalidators
552 : : * sizeof *udpif->revalidators);
553 [ + + ]: 4535 : for (i = 0; i < udpif->n_revalidators; i++) {
554 : 2269 : struct revalidator *revalidator = &udpif->revalidators[i];
555 : :
556 : 2269 : revalidator->udpif = udpif;
557 : 2269 : revalidator->thread = ovs_thread_create(
558 : : "revalidator", udpif_revalidator, revalidator);
559 : : }
560 : : }
561 : 2267 : }
562 : :
563 : : /* Pauses all revalidators. Should only be called by the main thread.
564 : : * When function returns, all revalidators are paused and will proceed
565 : : * only after udpif_resume_revalidators() is called. */
566 : : static void
567 : 45 : udpif_pause_revalidators(struct udpif *udpif)
568 : : {
569 [ + - ]: 45 : if (ofproto_dpif_backer_enabled(udpif->backer)) {
570 : 45 : latch_set(&udpif->pause_latch);
571 : 45 : ovs_barrier_block(&udpif->pause_barrier);
572 : : }
573 : 45 : }
574 : :
575 : : /* Resumes the pausing of revalidators. Should only be called by the
576 : : * main thread. */
577 : : static void
578 : 45 : udpif_resume_revalidators(struct udpif *udpif)
579 : : {
580 [ + - ]: 45 : if (ofproto_dpif_backer_enabled(udpif->backer)) {
581 : 45 : latch_poll(&udpif->pause_latch);
582 : 45 : ovs_barrier_block(&udpif->pause_barrier);
583 : : }
584 : 45 : }
585 : :
586 : : /* Tells 'udpif' how many threads it should use to handle upcalls.
587 : : * 'n_handlers' and 'n_revalidators' can never be zero. 'udpif''s
588 : : * datapath handle must have packet reception enabled before starting
589 : : * threads. */
590 : : void
591 : 106273 : udpif_set_threads(struct udpif *udpif, size_t n_handlers,
592 : : size_t n_revalidators)
593 : : {
594 [ - + ]: 106273 : ovs_assert(udpif);
595 [ + - ][ - + ]: 106273 : ovs_assert(n_handlers && n_revalidators);
596 : :
597 : 106273 : ovsrcu_quiesce_start();
598 [ + + ]: 106273 : if (udpif->n_handlers != n_handlers
599 [ + + ]: 105659 : || udpif->n_revalidators != n_revalidators) {
600 : 615 : udpif_stop_threads(udpif);
601 : : }
602 : :
603 [ + + ][ + - ]: 106273 : if (!udpif->handlers && !udpif->revalidators) {
604 : : int error;
605 : :
606 : 615 : error = dpif_handlers_set(udpif->dpif, n_handlers);
607 [ - + ]: 615 : if (error) {
608 [ # # ]: 0 : VLOG_ERR("failed to configure handlers in dpif %s: %s",
609 : : dpif_name(udpif->dpif), ovs_strerror(error));
610 : 0 : return;
611 : : }
612 : :
613 : 615 : udpif_start_threads(udpif, n_handlers, n_revalidators);
614 : : }
615 : 106273 : ovsrcu_quiesce_end();
616 : : }
617 : :
618 : : /* Waits for all ongoing upcall translations to complete. This ensures that
619 : : * there are no transient references to any removed ofprotos (or other
620 : : * objects). In particular, this should be called after an ofproto is removed
621 : : * (e.g. via xlate_remove_ofproto()) but before it is destroyed. */
622 : : void
623 : 749 : udpif_synchronize(struct udpif *udpif)
624 : : {
625 : : /* This is stronger than necessary. It would be sufficient to ensure
626 : : * (somehow) that each handler and revalidator thread had passed through
627 : : * its main loop once. */
628 : 749 : size_t n_handlers = udpif->n_handlers;
629 : 749 : size_t n_revalidators = udpif->n_revalidators;
630 : :
631 : 749 : ovsrcu_quiesce_start();
632 : 749 : udpif_stop_threads(udpif);
633 : 749 : udpif_start_threads(udpif, n_handlers, n_revalidators);
634 : 749 : ovsrcu_quiesce_end();
635 : 749 : }
636 : :
637 : : /* Notifies 'udpif' that something changed which may render previous
638 : : * xlate_actions() results invalid. */
639 : : void
640 : 18244 : udpif_revalidate(struct udpif *udpif)
641 : : {
642 : 18244 : seq_change(udpif->reval_seq);
643 : 18244 : }
644 : :
645 : : /* Returns a seq which increments every time 'udpif' pulls stats from the
646 : : * datapath. Callers can use this to get a sense of when might be a good time
647 : : * to do periodic work which relies on relatively up to date statistics. */
648 : : struct seq *
649 : 311172 : udpif_dump_seq(struct udpif *udpif)
650 : : {
651 : 311172 : return udpif->dump_seq;
652 : : }
653 : :
654 : : void
655 : 72 : udpif_get_memory_usage(struct udpif *udpif, struct simap *usage)
656 : : {
657 : : size_t i;
658 : :
659 : 72 : simap_increase(usage, "handlers", udpif->n_handlers);
660 : :
661 : 72 : simap_increase(usage, "revalidators", udpif->n_revalidators);
662 [ + + ]: 36936 : for (i = 0; i < N_UMAPS; i++) {
663 : 36864 : simap_increase(usage, "udpif keys", cmap_count(&udpif->ukeys[i].cmap));
664 : : }
665 : 72 : }
666 : :
667 : : /* Remove flows from a single datapath. */
668 : : void
669 : 903 : udpif_flush(struct udpif *udpif)
670 : : {
671 : : size_t n_handlers, n_revalidators;
672 : :
673 : 903 : n_handlers = udpif->n_handlers;
674 : 903 : n_revalidators = udpif->n_revalidators;
675 : :
676 : 903 : ovsrcu_quiesce_start();
677 : :
678 : 903 : udpif_stop_threads(udpif);
679 : 903 : dpif_flow_flush(udpif->dpif);
680 : 903 : udpif_start_threads(udpif, n_handlers, n_revalidators);
681 : :
682 : 903 : ovsrcu_quiesce_end();
683 : 903 : }
684 : :
685 : : /* Removes all flows from all datapaths. */
686 : : static void
687 : 8 : udpif_flush_all_datapaths(void)
688 : : {
689 : : struct udpif *udpif;
690 : :
691 [ + + ]: 16 : LIST_FOR_EACH (udpif, list_node, &all_udpifs) {
692 : 8 : udpif_flush(udpif);
693 : : }
694 : 8 : }
695 : :
696 : : static bool
697 : 34855 : udpif_use_ufid(struct udpif *udpif)
698 : : {
699 : : bool enable;
700 : :
701 : 34855 : atomic_read_relaxed(&enable_ufid, &enable);
702 [ + + ][ + - ]: 34855 : return enable && ofproto_dpif_get_enable_ufid(udpif->backer);
703 : : }
704 : :
705 : :
706 : : static unsigned long
707 : 45487 : udpif_get_n_flows(struct udpif *udpif)
708 : : {
709 : : long long int time, now;
710 : : unsigned long flow_count;
711 : :
712 : 45487 : now = time_msec();
713 : 45487 : atomic_read_relaxed(&udpif->n_flows_timestamp, &time);
714 [ + + ][ + - ]: 57779 : if (time < now - 100 && !ovs_mutex_trylock(&udpif->n_flows_mutex)) {
715 : : struct dpif_dp_stats stats;
716 : :
717 : 12292 : atomic_store_relaxed(&udpif->n_flows_timestamp, now);
718 : 12292 : dpif_get_dp_stats(udpif->dpif, &stats);
719 : 12292 : flow_count = stats.n_flows;
720 : 12292 : atomic_store_relaxed(&udpif->n_flows, flow_count);
721 : 12292 : ovs_mutex_unlock(&udpif->n_flows_mutex);
722 : : } else {
723 : 33195 : atomic_read_relaxed(&udpif->n_flows, &flow_count);
724 : : }
725 : 45487 : return flow_count;
726 : : }
727 : :
728 : : /* The upcall handler thread tries to read a batch of UPCALL_MAX_BATCH
729 : : * upcalls from dpif, processes the batch and installs corresponding flows
730 : : * in dpif. */
731 : : static void *
732 : 2266 : udpif_upcall_handler(void *arg)
733 : : {
734 : 2266 : struct handler *handler = arg;
735 : 2266 : struct udpif *udpif = handler->udpif;
736 : :
737 [ + + ]: 10839 : while (!latch_is_set(&handler->udpif->exit_latch)) {
738 [ + + ]: 8573 : if (recv_upcalls(handler)) {
739 : 1190 : poll_immediate_wake();
740 : : } else {
741 : 7383 : dpif_recv_wait(udpif->dpif, handler->handler_id);
742 : 7383 : latch_wait(&udpif->exit_latch);
743 : : }
744 : 8573 : poll_block();
745 : : }
746 : :
747 : 2266 : return NULL;
748 : : }
749 : :
750 : : static size_t
751 : 8573 : recv_upcalls(struct handler *handler)
752 : : {
753 : 8573 : struct udpif *udpif = handler->udpif;
754 : : uint64_t recv_stubs[UPCALL_MAX_BATCH][512 / 8];
755 : : struct ofpbuf recv_bufs[UPCALL_MAX_BATCH];
756 : : struct dpif_upcall dupcalls[UPCALL_MAX_BATCH];
757 : : struct upcall upcalls[UPCALL_MAX_BATCH];
758 : : struct flow flows[UPCALL_MAX_BATCH];
759 : : size_t n_upcalls, i;
760 : :
761 : 8573 : n_upcalls = 0;
762 [ + - ]: 9947 : while (n_upcalls < UPCALL_MAX_BATCH) {
763 : 9947 : struct ofpbuf *recv_buf = &recv_bufs[n_upcalls];
764 : 9947 : struct dpif_upcall *dupcall = &dupcalls[n_upcalls];
765 : 9947 : struct upcall *upcall = &upcalls[n_upcalls];
766 : 9947 : struct flow *flow = &flows[n_upcalls];
767 : : unsigned int mru;
768 : : int error;
769 : :
770 : 9947 : ofpbuf_use_stub(recv_buf, recv_stubs[n_upcalls],
771 : : sizeof recv_stubs[n_upcalls]);
772 [ + + ]: 9947 : if (dpif_recv(udpif->dpif, handler->handler_id, dupcall, recv_buf)) {
773 : 8573 : ofpbuf_uninit(recv_buf);
774 : 8573 : break;
775 : : }
776 : :
777 [ - + ]: 1374 : if (odp_flow_key_to_flow(dupcall->key, dupcall->key_len, flow)
778 : : == ODP_FIT_ERROR) {
779 : 0 : goto free_dupcall;
780 : : }
781 : :
782 [ + + ]: 1374 : if (dupcall->mru) {
783 : 6 : mru = nl_attr_get_u16(dupcall->mru);
784 : : } else {
785 : 1368 : mru = 0;
786 : : }
787 : :
788 : 1374 : error = upcall_receive(upcall, udpif->backer, &dupcall->packet,
789 : 1374 : dupcall->type, dupcall->userdata, flow, mru,
790 : 1374 : &dupcall->ufid, PMD_ID_NULL);
791 [ + + ]: 1374 : if (error) {
792 [ + - ]: 63 : if (error == ENODEV) {
793 : : /* Received packet on datapath port for which we couldn't
794 : : * associate an ofproto. This can happen if a port is removed
795 : : * while traffic is being received. Print a rate-limited
796 : : * message in case it happens frequently. */
797 : 63 : dpif_flow_put(udpif->dpif, DPIF_FP_CREATE, dupcall->key,
798 : : dupcall->key_len, NULL, 0, NULL, 0,
799 : 63 : &dupcall->ufid, PMD_ID_NULL, NULL);
800 [ + - ]: 63 : VLOG_INFO_RL(&rl, "received packet on unassociated datapath "
801 : : "port %"PRIu32, flow->in_port.odp_port);
802 : : }
803 : 63 : goto free_dupcall;
804 : : }
805 : :
806 : 1311 : upcall->key = dupcall->key;
807 : 1311 : upcall->key_len = dupcall->key_len;
808 : 1311 : upcall->ufid = &dupcall->ufid;
809 : :
810 : 1311 : upcall->out_tun_key = dupcall->out_tun_key;
811 : 1311 : upcall->actions = dupcall->actions;
812 : :
813 : 1311 : pkt_metadata_from_flow(&dupcall->packet.md, flow);
814 : 1311 : flow_extract(&dupcall->packet, flow);
815 : :
816 : 1311 : error = process_upcall(udpif, upcall,
817 : : &upcall->odp_actions, &upcall->wc);
818 [ - + ]: 1311 : if (error) {
819 : 0 : goto cleanup;
820 : : }
821 : :
822 : 1311 : n_upcalls++;
823 : 1311 : continue;
824 : :
825 : : cleanup:
826 : 0 : upcall_uninit(upcall);
827 : : free_dupcall:
828 : 63 : dp_packet_uninit(&dupcall->packet);
829 : 63 : ofpbuf_uninit(recv_buf);
830 : : }
831 : :
832 [ + + ]: 8573 : if (n_upcalls) {
833 : 1190 : handle_upcalls(handler->udpif, upcalls, n_upcalls);
834 [ + + ]: 2501 : for (i = 0; i < n_upcalls; i++) {
835 : 1311 : dp_packet_uninit(&dupcalls[i].packet);
836 : 1311 : ofpbuf_uninit(&recv_bufs[i]);
837 : 1311 : upcall_uninit(&upcalls[i]);
838 : : }
839 : : }
840 : :
841 : 8573 : return n_upcalls;
842 : : }
843 : :
844 : : static void *
845 : 2269 : udpif_revalidator(void *arg)
846 : : {
847 : : /* Used by all revalidators. */
848 : 2269 : struct revalidator *revalidator = arg;
849 : 2269 : struct udpif *udpif = revalidator->udpif;
850 : 2269 : bool leader = revalidator == &udpif->revalidators[0];
851 : :
852 : : /* Used only by the leader. */
853 : 2269 : long long int start_time = 0;
854 : 2269 : uint64_t last_reval_seq = 0;
855 : 2269 : size_t n_flows = 0;
856 : :
857 : 2269 : revalidator->id = ovsthread_id_self();
858 : : for (;;) {
859 [ + + ]: 30436 : if (leader) {
860 : : uint64_t reval_seq;
861 : :
862 : 30430 : recirc_run(); /* Recirculation cleanup. */
863 : :
864 : 30430 : reval_seq = seq_read(udpif->reval_seq);
865 : 30430 : last_reval_seq = reval_seq;
866 : :
867 : 30430 : n_flows = udpif_get_n_flows(udpif);
868 : 30430 : udpif->max_n_flows = MAX(n_flows, udpif->max_n_flows);
869 : 30430 : udpif->avg_n_flows = (udpif->avg_n_flows + n_flows) / 2;
870 : :
871 : : /* Only the leader checks the pause latch to prevent a race where
872 : : * some threads think it's false and proceed to block on
873 : : * reval_barrier and others think it's true and block indefinitely
874 : : * on the pause_barrier */
875 : 30430 : udpif->pause = latch_is_set(&udpif->pause_latch);
876 : :
877 : : /* Only the leader checks the exit latch to prevent a race where
878 : : * some threads think it's true and exit and others think it's
879 : : * false and block indefinitely on the reval_barrier */
880 : 30430 : udpif->reval_exit = latch_is_set(&udpif->exit_latch);
881 : :
882 : 30430 : start_time = time_msec();
883 [ + + ]: 30430 : if (!udpif->reval_exit) {
884 : : bool terse_dump;
885 : :
886 : 28164 : terse_dump = udpif_use_ufid(udpif);
887 : 28164 : udpif->dump = dpif_flow_dump_create(udpif->dpif, terse_dump);
888 : : }
889 : : }
890 : :
891 : : /* Wait for the leader to start the flow dump. */
892 : 30436 : ovs_barrier_block(&udpif->reval_barrier);
893 [ + + ]: 30436 : if (udpif->pause) {
894 : 45 : revalidator_pause(revalidator);
895 : : }
896 : :
897 [ + + ]: 30436 : if (udpif->reval_exit) {
898 : 2269 : break;
899 : : }
900 : 28167 : revalidate(revalidator);
901 : :
902 : : /* Wait for all flows to have been dumped before we garbage collect. */
903 : 28167 : ovs_barrier_block(&udpif->reval_barrier);
904 : 28167 : revalidator_sweep(revalidator);
905 : :
906 : : /* Wait for all revalidators to finish garbage collection. */
907 : 28167 : ovs_barrier_block(&udpif->reval_barrier);
908 : :
909 [ + + ]: 28167 : if (leader) {
910 : : unsigned int flow_limit;
911 : : long long int duration;
912 : :
913 : 28164 : atomic_read_relaxed(&udpif->flow_limit, &flow_limit);
914 : :
915 : 28164 : dpif_flow_dump_destroy(udpif->dump);
916 : 28164 : seq_change(udpif->dump_seq);
917 : :
918 [ + + ]: 28164 : duration = MAX(time_msec() - start_time, 1);
919 : 28164 : udpif->dump_duration = duration;
920 [ - + ]: 28164 : if (duration > 2000) {
921 : 0 : flow_limit /= duration / 1000;
922 [ - + ]: 28164 : } else if (duration > 1300) {
923 : 0 : flow_limit = flow_limit * 3 / 4;
924 [ + - ][ - + ]: 28164 : } else if (duration < 1000 && n_flows > 2000
925 [ # # ]: 0 : && flow_limit < n_flows * 1000 / duration) {
926 : 0 : flow_limit += 1000;
927 : : }
928 : 28164 : flow_limit = MIN(ofproto_flow_limit, MAX(flow_limit, 1000));
929 : 28164 : atomic_store_relaxed(&udpif->flow_limit, flow_limit);
930 : :
931 [ - + ]: 28164 : if (duration > 2000) {
932 [ # # ]: 0 : VLOG_INFO("Spent an unreasonably long %lldms dumping flows",
933 : : duration);
934 : : }
935 : :
936 [ - + ]: 28164 : poll_timer_wait_until(start_time + MIN(ofproto_max_idle, 500));
937 : 28164 : seq_wait(udpif->reval_seq, last_reval_seq);
938 : 28164 : latch_wait(&udpif->exit_latch);
939 : 28164 : latch_wait(&udpif->pause_latch);
940 : 28164 : poll_block();
941 : : }
942 : 28167 : }
943 : :
944 : 2269 : return NULL;
945 : : }
946 : :
947 : : static enum upcall_type
948 : 6943 : classify_upcall(enum dpif_upcall_type type, const struct nlattr *userdata)
949 : : {
950 : : union user_action_cookie cookie;
951 : : size_t userdata_len;
952 : :
953 : : /* First look at the upcall type. */
954 [ + + - ]: 6943 : switch (type) {
955 : : case DPIF_UC_ACTION:
956 : 262 : break;
957 : :
958 : : case DPIF_UC_MISS:
959 : 6681 : return MISS_UPCALL;
960 : :
961 : : case DPIF_N_UC_TYPES:
962 : : default:
963 [ # # ]: 0 : VLOG_WARN_RL(&rl, "upcall has unexpected type %"PRIu32, type);
964 : 0 : return BAD_UPCALL;
965 : : }
966 : :
967 : : /* "action" upcalls need a closer look. */
968 [ - + ]: 262 : if (!userdata) {
969 [ # # ]: 0 : VLOG_WARN_RL(&rl, "action upcall missing cookie");
970 : 0 : return BAD_UPCALL;
971 : : }
972 : 262 : userdata_len = nl_attr_get_size(userdata);
973 [ + - ]: 262 : if (userdata_len < sizeof cookie.type
974 [ - + ]: 262 : || userdata_len > sizeof cookie) {
975 [ # # ]: 0 : VLOG_WARN_RL(&rl, "action upcall cookie has unexpected size %"PRIuSIZE,
976 : : userdata_len);
977 : 0 : return BAD_UPCALL;
978 : : }
979 : 262 : memset(&cookie, 0, sizeof cookie);
980 : 262 : memcpy(&cookie, nl_attr_get(userdata), userdata_len);
981 [ + + ]: 262 : if (userdata_len == MAX(8, sizeof cookie.sflow)
982 [ + + ]: 239 : && cookie.type == USER_ACTION_COOKIE_SFLOW) {
983 : 14 : return SFLOW_UPCALL;
984 [ + + ]: 248 : } else if (userdata_len == MAX(8, sizeof cookie.slow_path)
985 [ + + ]: 225 : && cookie.type == USER_ACTION_COOKIE_SLOW_PATH) {
986 : 202 : return MISS_UPCALL;
987 [ + + ]: 46 : } else if (userdata_len == MAX(8, sizeof cookie.flow_sample)
988 [ + - ]: 23 : && cookie.type == USER_ACTION_COOKIE_FLOW_SAMPLE) {
989 : 23 : return FLOW_SAMPLE_UPCALL;
990 [ + - ]: 23 : } else if (userdata_len == MAX(8, sizeof cookie.ipfix)
991 [ + - ]: 23 : && cookie.type == USER_ACTION_COOKIE_IPFIX) {
992 : 23 : return IPFIX_UPCALL;
993 : : } else {
994 [ # # ]: 0 : VLOG_WARN_RL(&rl, "invalid user cookie of type %"PRIu16
995 : : " and size %"PRIuSIZE, cookie.type, userdata_len);
996 : 6943 : return BAD_UPCALL;
997 : : }
998 : : }
999 : :
1000 : : /* Calculates slow path actions for 'xout'. 'buf' must statically be
1001 : : * initialized with at least 128 bytes of space. */
1002 : : static void
1003 : 27665 : compose_slow_path(struct udpif *udpif, struct xlate_out *xout,
1004 : : const struct flow *flow, odp_port_t odp_in_port,
1005 : : struct ofpbuf *buf)
1006 : : {
1007 : : union user_action_cookie cookie;
1008 : : odp_port_t port;
1009 : : uint32_t pid;
1010 : :
1011 : 27665 : cookie.type = USER_ACTION_COOKIE_SLOW_PATH;
1012 : 27665 : cookie.slow_path.unused = 0;
1013 : 27665 : cookie.slow_path.reason = xout->slow;
1014 : :
1015 : 55330 : port = xout->slow & (SLOW_CFM | SLOW_BFD | SLOW_LACP | SLOW_STP)
1016 : : ? ODPP_NONE
1017 [ + + ]: 27665 : : odp_in_port;
1018 : 27665 : pid = dpif_port_get_pid(udpif->dpif, port, flow_hash_5tuple(flow, 0));
1019 : 27665 : odp_put_userspace_action(pid, &cookie, sizeof cookie.slow_path,
1020 : : ODPP_NONE, false, buf);
1021 : 27665 : }
1022 : :
1023 : : /* If there is no error, the upcall must be destroyed with upcall_uninit()
1024 : : * before quiescing, as the referred objects are guaranteed to exist only
1025 : : * until the calling thread quiesces. Otherwise, do not call upcall_uninit()
1026 : : * since the 'upcall->put_actions' remains uninitialized. */
1027 : : static int
1028 : 7556 : upcall_receive(struct upcall *upcall, const struct dpif_backer *backer,
1029 : : const struct dp_packet *packet, enum dpif_upcall_type type,
1030 : : const struct nlattr *userdata, const struct flow *flow,
1031 : : const unsigned int mru,
1032 : : const ovs_u128 *ufid, const unsigned pmd_id)
1033 : : {
1034 : : int error;
1035 : :
1036 : 7556 : error = xlate_lookup(backer, flow, &upcall->ofproto, &upcall->ipfix,
1037 : : &upcall->sflow, NULL, &upcall->in_port);
1038 [ + + ]: 7556 : if (error) {
1039 : 613 : return error;
1040 : : }
1041 : :
1042 : 6943 : upcall->recirc = NULL;
1043 : 6943 : upcall->have_recirc_ref = false;
1044 : 6943 : upcall->flow = flow;
1045 : 6943 : upcall->packet = packet;
1046 : 6943 : upcall->ufid = ufid;
1047 : 6943 : upcall->pmd_id = pmd_id;
1048 : 6943 : upcall->type = type;
1049 : 6943 : upcall->userdata = userdata;
1050 : 6943 : ofpbuf_use_stub(&upcall->odp_actions, upcall->odp_actions_stub,
1051 : : sizeof upcall->odp_actions_stub);
1052 : 6943 : ofpbuf_init(&upcall->put_actions, 0);
1053 : :
1054 : 6943 : upcall->xout_initialized = false;
1055 : 6943 : upcall->ukey_persists = false;
1056 : :
1057 : 6943 : upcall->ukey = NULL;
1058 : 6943 : upcall->key = NULL;
1059 : 6943 : upcall->key_len = 0;
1060 : 6943 : upcall->mru = mru;
1061 : :
1062 : 6943 : upcall->out_tun_key = NULL;
1063 : 6943 : upcall->actions = NULL;
1064 : :
1065 : 6943 : return 0;
1066 : : }
1067 : :
1068 : : static void
1069 : 6883 : upcall_xlate(struct udpif *udpif, struct upcall *upcall,
1070 : : struct ofpbuf *odp_actions, struct flow_wildcards *wc)
1071 : : {
1072 : : struct dpif_flow_stats stats;
1073 : : struct xlate_in xin;
1074 : :
1075 : 6883 : stats.n_packets = 1;
1076 : 6883 : stats.n_bytes = dp_packet_size(upcall->packet);
1077 : 6883 : stats.used = time_msec();
1078 : 6883 : stats.tcp_flags = ntohs(upcall->flow->tcp_flags);
1079 : :
1080 : 6883 : xlate_in_init(&xin, upcall->ofproto, upcall->flow, upcall->in_port, NULL,
1081 : 6883 : stats.tcp_flags, upcall->packet, wc, odp_actions);
1082 : :
1083 [ + + ]: 6883 : if (upcall->type == DPIF_UC_MISS) {
1084 : 6681 : xin.resubmit_stats = &stats;
1085 : :
1086 [ + + ]: 6681 : if (xin.frozen_state) {
1087 : : /* We may install a datapath flow only if we get a reference to the
1088 : : * recirculation context (otherwise we could have recirculation
1089 : : * upcalls using recirculation ID for which no context can be
1090 : : * found). We may still execute the flow's actions even if we
1091 : : * don't install the flow. */
1092 : 771 : upcall->recirc = recirc_id_node_from_state(xin.frozen_state);
1093 : 6681 : upcall->have_recirc_ref = recirc_id_node_try_ref_rcu(upcall->recirc);
1094 : : }
1095 : : } else {
1096 : : /* For non-miss upcalls, we are either executing actions (one of which
1097 : : * is an userspace action) for an upcall, in which case the stats have
1098 : : * already been taken care of, or there's a flow in the datapath which
1099 : : * this packet was accounted to. Presumably the revalidators will deal
1100 : : * with pushing its stats eventually. */
1101 : : }
1102 : :
1103 : 6883 : upcall->dump_seq = seq_read(udpif->dump_seq);
1104 : 6883 : upcall->reval_seq = seq_read(udpif->reval_seq);
1105 : :
1106 : 6883 : xlate_actions(&xin, &upcall->xout);
1107 [ + + ]: 6883 : if (wc) {
1108 : : /* Convert the input port wildcard from OFP to ODP format. There's no
1109 : : * real way to do this for arbitrary bitmasks since the numbering spaces
1110 : : * aren't the same. However, flow translation always exact matches the
1111 : : * whole thing, so we can do the same here. */
1112 : 6683 : WC_MASK_FIELD(wc, in_port.odp_port);
1113 : : }
1114 : :
1115 : 6883 : upcall->xout_initialized = true;
1116 : :
1117 [ + + ]: 6883 : if (!upcall->xout.slow) {
1118 : 5843 : ofpbuf_use_const(&upcall->put_actions,
1119 : 11686 : odp_actions->data, odp_actions->size);
1120 : : } else {
1121 : : /* upcall->put_actions already initialized by upcall_receive(). */
1122 : 1040 : compose_slow_path(udpif, &upcall->xout, upcall->flow,
1123 : 1040 : upcall->flow->in_port.odp_port,
1124 : : &upcall->put_actions);
1125 : : }
1126 : :
1127 : : /* This function is also called for slow-pathed flows. As we are only
1128 : : * going to create new datapath flows for actual datapath misses, there is
1129 : : * no point in creating a ukey otherwise. */
1130 [ + + ]: 6883 : if (upcall->type == DPIF_UC_MISS) {
1131 : 6681 : upcall->ukey = ukey_create_from_upcall(upcall, wc);
1132 : : }
1133 : 6883 : }
1134 : :
1135 : : static void
1136 : 6943 : upcall_uninit(struct upcall *upcall)
1137 : : {
1138 [ + - ]: 6943 : if (upcall) {
1139 [ + + ]: 6943 : if (upcall->xout_initialized) {
1140 : 6883 : xlate_out_uninit(&upcall->xout);
1141 : : }
1142 : 6943 : ofpbuf_uninit(&upcall->odp_actions);
1143 : 6943 : ofpbuf_uninit(&upcall->put_actions);
1144 [ + + ]: 6943 : if (upcall->ukey) {
1145 [ + + ]: 6681 : if (!upcall->ukey_persists) {
1146 : 6681 : ukey_delete__(upcall->ukey);
1147 : : }
1148 [ - + ]: 262 : } else if (upcall->have_recirc_ref) {
1149 : : /* The reference was transferred to the ukey if one was created. */
1150 : 0 : recirc_id_node_unref(upcall->recirc);
1151 : : }
1152 : : }
1153 : 6943 : }
1154 : :
1155 : : /* If there are less flows than the limit, and this is a miss upcall which
1156 : : *
1157 : : * - Has no recirc_id, OR
1158 : : * - Has a recirc_id and we can get a reference on the recirc ctx,
1159 : : *
1160 : : * Then we should install the flow (true). Otherwise, return false. */
1161 : : static bool
1162 : 6883 : should_install_flow(struct udpif *udpif, struct upcall *upcall)
1163 : : {
1164 : : unsigned int flow_limit;
1165 : :
1166 [ + + ]: 6883 : if (upcall->type != DPIF_UC_MISS) {
1167 : 202 : return false;
1168 [ + + ][ + + ]: 6681 : } else if (upcall->recirc && !upcall->have_recirc_ref) {
1169 [ - + ]: 5 : VLOG_DBG_RL(&rl, "upcall: no reference for recirc flow");
1170 : 5 : return false;
1171 : : }
1172 : :
1173 : 6676 : atomic_read_relaxed(&udpif->flow_limit, &flow_limit);
1174 [ - + ]: 6676 : if (udpif_get_n_flows(udpif) >= flow_limit) {
1175 [ # # ]: 0 : VLOG_WARN_RL(&rl, "upcall: datapath flow limit reached");
1176 : 0 : return false;
1177 : : }
1178 : :
1179 : 6883 : return true;
1180 : : }
1181 : :
1182 : : static int
1183 : 6182 : upcall_cb(const struct dp_packet *packet, const struct flow *flow, ovs_u128 *ufid,
1184 : : unsigned pmd_id, enum dpif_upcall_type type,
1185 : : const struct nlattr *userdata, struct ofpbuf *actions,
1186 : : struct flow_wildcards *wc, struct ofpbuf *put_actions, void *aux)
1187 : : {
1188 : : static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
1189 : 6182 : struct udpif *udpif = aux;
1190 : : struct upcall upcall;
1191 : : bool megaflow;
1192 : : int error;
1193 : :
1194 : 6182 : atomic_read_relaxed(&enable_megaflows, &megaflow);
1195 : :
1196 : 6182 : error = upcall_receive(&upcall, udpif->backer, packet, type, userdata,
1197 : : flow, 0, ufid, pmd_id);
1198 [ + + ]: 6182 : if (error) {
1199 : 550 : return error;
1200 : : }
1201 : :
1202 : 5632 : error = process_upcall(udpif, &upcall, actions, wc);
1203 [ + + ]: 5632 : if (error) {
1204 : 60 : goto out;
1205 : : }
1206 : :
1207 [ + + ][ + + ]: 5572 : if (upcall.xout.slow && put_actions) {
1208 : 783 : ofpbuf_put(put_actions, upcall.put_actions.data,
1209 : 783 : upcall.put_actions.size);
1210 : : }
1211 : :
1212 [ + + ]: 5572 : if (OVS_UNLIKELY(!megaflow)) {
1213 : 777 : flow_wildcards_init_for_packet(wc, flow);
1214 : : }
1215 : :
1216 [ + + ]: 5572 : if (!should_install_flow(udpif, &upcall)) {
1217 : 200 : error = ENOSPC;
1218 : 200 : goto out;
1219 : : }
1220 : :
1221 [ + - ][ - + ]: 5372 : if (upcall.ukey && !ukey_install(udpif, upcall.ukey)) {
1222 [ # # ]: 0 : VLOG_WARN_RL(&rl, "upcall_cb failure: ukey installation fails");
1223 : 0 : error = ENOSPC;
1224 : : }
1225 : : out:
1226 [ + + ]: 5632 : if (!error) {
1227 : 5372 : upcall.ukey_persists = true;
1228 : : }
1229 : 5632 : upcall_uninit(&upcall);
1230 : 6182 : return error;
1231 : : }
1232 : :
1233 : : static int
1234 : 6943 : process_upcall(struct udpif *udpif, struct upcall *upcall,
1235 : : struct ofpbuf *odp_actions, struct flow_wildcards *wc)
1236 : : {
1237 : 6943 : const struct nlattr *userdata = upcall->userdata;
1238 : 6943 : const struct dp_packet *packet = upcall->packet;
1239 : 6943 : const struct flow *flow = upcall->flow;
1240 : :
1241 [ + + + + : 6943 : switch (classify_upcall(upcall->type, userdata)) {
- - ]
1242 : : case MISS_UPCALL:
1243 : 6883 : upcall_xlate(udpif, upcall, odp_actions, wc);
1244 : 6883 : return 0;
1245 : :
1246 : : case SFLOW_UPCALL:
1247 [ + - ]: 14 : if (upcall->sflow) {
1248 : : union user_action_cookie cookie;
1249 : : const struct nlattr *actions;
1250 : 14 : size_t actions_len = 0;
1251 : : struct dpif_sflow_actions sflow_actions;
1252 : 14 : memset(&sflow_actions, 0, sizeof sflow_actions);
1253 : 14 : memset(&cookie, 0, sizeof cookie);
1254 : 14 : memcpy(&cookie, nl_attr_get(userdata), sizeof cookie.sflow);
1255 [ - + ]: 14 : if (upcall->actions) {
1256 : : /* Actions were passed up from datapath. */
1257 : 0 : actions = nl_attr_get(upcall->actions);
1258 : 0 : actions_len = nl_attr_get_size(upcall->actions);
1259 [ # # ][ # # ]: 0 : if (actions && actions_len) {
1260 : 0 : dpif_sflow_read_actions(flow, actions, actions_len,
1261 : : &sflow_actions);
1262 : : }
1263 : : }
1264 [ + - ]: 14 : if (actions_len == 0) {
1265 : : /* Lookup actions in userspace cache. */
1266 : 14 : struct udpif_key *ukey = ukey_lookup(udpif, upcall->ufid,
1267 : : upcall->pmd_id);
1268 [ + - ]: 14 : if (ukey) {
1269 : 14 : ukey_get_actions(ukey, &actions, &actions_len);
1270 : 14 : dpif_sflow_read_actions(flow, actions, actions_len,
1271 : : &sflow_actions);
1272 : : }
1273 : : }
1274 [ + - ]: 14 : dpif_sflow_received(upcall->sflow, packet, flow,
1275 : : flow->in_port.odp_port, &cookie,
1276 : 14 : actions_len > 0 ? &sflow_actions : NULL);
1277 : : }
1278 : 14 : break;
1279 : :
1280 : : case IPFIX_UPCALL:
1281 [ + - ]: 23 : if (upcall->ipfix) {
1282 : : union user_action_cookie cookie;
1283 : : struct flow_tnl output_tunnel_key;
1284 : :
1285 : 23 : memset(&cookie, 0, sizeof cookie);
1286 : 23 : memcpy(&cookie, nl_attr_get(userdata), sizeof cookie.ipfix);
1287 : :
1288 [ - + ]: 23 : if (upcall->out_tun_key) {
1289 : 0 : odp_tun_key_from_attr(upcall->out_tun_key, false,
1290 : : &output_tunnel_key);
1291 : : }
1292 [ - + ]: 23 : dpif_ipfix_bridge_sample(upcall->ipfix, packet, flow,
1293 : : flow->in_port.odp_port,
1294 : : cookie.ipfix.output_odp_port,
1295 : 23 : upcall->out_tun_key ?
1296 : : &output_tunnel_key : NULL);
1297 : : }
1298 : 23 : break;
1299 : :
1300 : : case FLOW_SAMPLE_UPCALL:
1301 [ + - ]: 23 : if (upcall->ipfix) {
1302 : : union user_action_cookie cookie;
1303 : : struct flow_tnl output_tunnel_key;
1304 : :
1305 : 23 : memset(&cookie, 0, sizeof cookie);
1306 : 23 : memcpy(&cookie, nl_attr_get(userdata), sizeof cookie.flow_sample);
1307 : :
1308 [ - + ]: 23 : if (upcall->out_tun_key) {
1309 : 0 : odp_tun_key_from_attr(upcall->out_tun_key, false,
1310 : : &output_tunnel_key);
1311 : : }
1312 : :
1313 : : /* The flow reflects exactly the contents of the packet.
1314 : : * Sample the packet using it. */
1315 [ - + ]: 23 : dpif_ipfix_flow_sample(upcall->ipfix, packet, flow,
1316 : : &cookie, flow->in_port.odp_port,
1317 : 23 : upcall->out_tun_key ?
1318 : : &output_tunnel_key : NULL);
1319 : : }
1320 : 23 : break;
1321 : :
1322 : : case BAD_UPCALL:
1323 : 0 : break;
1324 : : }
1325 : :
1326 : 60 : return EAGAIN;
1327 : : }
1328 : :
1329 : : static void
1330 : 1190 : handle_upcalls(struct udpif *udpif, struct upcall *upcalls,
1331 : : size_t n_upcalls)
1332 : : {
1333 : : struct dpif_op *opsp[UPCALL_MAX_BATCH * 2];
1334 : : struct ukey_op ops[UPCALL_MAX_BATCH * 2];
1335 : : size_t n_ops, n_opsp, i;
1336 : :
1337 : : /* Handle the packets individually in order of arrival.
1338 : : *
1339 : : * - For SLOW_CFM, SLOW_LACP, SLOW_STP, and SLOW_BFD, translation is what
1340 : : * processes received packets for these protocols.
1341 : : *
1342 : : * - For SLOW_CONTROLLER, translation sends the packet to the OpenFlow
1343 : : * controller.
1344 : : *
1345 : : * The loop fills 'ops' with an array of operations to execute in the
1346 : : * datapath. */
1347 : 1190 : n_ops = 0;
1348 [ + + ]: 2501 : for (i = 0; i < n_upcalls; i++) {
1349 : 1311 : struct upcall *upcall = &upcalls[i];
1350 : 1311 : const struct dp_packet *packet = upcall->packet;
1351 : : struct ukey_op *op;
1352 : :
1353 [ + + ]: 1311 : if (should_install_flow(udpif, upcall)) {
1354 : 1304 : struct udpif_key *ukey = upcall->ukey;
1355 : :
1356 [ + + ]: 1304 : if (ukey_install(udpif, ukey)) {
1357 : 1284 : upcall->ukey_persists = true;
1358 : 1284 : put_op_init(&ops[n_ops++], ukey, DPIF_FP_CREATE);
1359 : : }
1360 : : }
1361 : :
1362 [ + + ]: 1311 : if (upcall->odp_actions.size) {
1363 : 997 : op = &ops[n_ops++];
1364 : 997 : op->ukey = NULL;
1365 : 997 : op->dop.type = DPIF_OP_EXECUTE;
1366 : 997 : op->dop.u.execute.packet = CONST_CAST(struct dp_packet *, packet);
1367 : 997 : op->dop.u.execute.flow = upcall->flow;
1368 : 997 : odp_key_to_pkt_metadata(upcall->key, upcall->key_len,
1369 : 997 : &op->dop.u.execute.packet->md);
1370 : 997 : op->dop.u.execute.actions = upcall->odp_actions.data;
1371 : 997 : op->dop.u.execute.actions_len = upcall->odp_actions.size;
1372 : 997 : op->dop.u.execute.needs_help = (upcall->xout.slow & SLOW_ACTION) != 0;
1373 : 997 : op->dop.u.execute.probe = false;
1374 : 997 : op->dop.u.execute.mtu = upcall->mru;
1375 : : }
1376 : : }
1377 : :
1378 : : /* Execute batch. */
1379 : 1190 : n_opsp = 0;
1380 [ + + ]: 3471 : for (i = 0; i < n_ops; i++) {
1381 : 2281 : opsp[n_opsp++] = &ops[i].dop;
1382 : : }
1383 : 1190 : dpif_operate(udpif->dpif, opsp, n_opsp);
1384 [ + + ]: 3471 : for (i = 0; i < n_ops; i++) {
1385 : 2281 : struct udpif_key *ukey = ops[i].ukey;
1386 : :
1387 [ + + ]: 2281 : if (ukey) {
1388 : 1284 : ovs_mutex_lock(&ukey->mutex);
1389 [ + + ]: 1284 : if (ops[i].dop.error) {
1390 : 28 : transition_ukey(ukey, UKEY_EVICTED);
1391 : : } else {
1392 : 1256 : transition_ukey(ukey, UKEY_OPERATIONAL);
1393 : : }
1394 : 1284 : ovs_mutex_unlock(&ukey->mutex);
1395 : : }
1396 : : }
1397 : 1190 : }
1398 : :
1399 : : static uint32_t
1400 : 367260 : get_ukey_hash(const ovs_u128 *ufid, const unsigned pmd_id)
1401 : : {
1402 : 367260 : return hash_2words(ufid->u32[0], pmd_id);
1403 : : }
1404 : :
1405 : : static struct udpif_key *
1406 : 180258 : ukey_lookup(struct udpif *udpif, const ovs_u128 *ufid, const unsigned pmd_id)
1407 : : {
1408 : : struct udpif_key *ukey;
1409 : 180258 : int idx = get_ukey_hash(ufid, pmd_id) % N_UMAPS;
1410 : 180258 : struct cmap *cmap = &udpif->ukeys[idx].cmap;
1411 : :
1412 [ + + ]: 180258 : CMAP_FOR_EACH_WITH_HASH (ukey, cmap_node,
1413 : : get_ukey_hash(ufid, pmd_id), cmap) {
1414 [ + - ]: 173476 : if (ovs_u128_equals(ukey->ufid, *ufid)) {
1415 : 173476 : return ukey;
1416 : : }
1417 : : }
1418 : 6782 : return NULL;
1419 : : }
1420 : :
1421 : : /* Provides safe lockless access of RCU protected 'ukey->actions'. Callers may
1422 : : * alternatively access the field directly if they take 'ukey->mutex'. */
1423 : : static void
1424 : 1727 : ukey_get_actions(struct udpif_key *ukey, const struct nlattr **actions, size_t *size)
1425 : : {
1426 : 1727 : const struct ofpbuf *buf = ovsrcu_get(struct ofpbuf *, &ukey->actions);
1427 : 1727 : *actions = buf->data;
1428 : 1727 : *size = buf->size;
1429 : 1727 : }
1430 : :
1431 : : static void
1432 : 7173 : ukey_set_actions(struct udpif_key *ukey, const struct ofpbuf *actions)
1433 : : {
1434 : 7173 : ovsrcu_postpone(ofpbuf_delete,
1435 : : ovsrcu_get_protected(struct ofpbuf *, &ukey->actions));
1436 : 7173 : ovsrcu_set(&ukey->actions, ofpbuf_clone(actions));
1437 : 7173 : }
1438 : :
1439 : : static struct udpif_key *
1440 : 6744 : ukey_create__(const struct nlattr *key, size_t key_len,
1441 : : const struct nlattr *mask, size_t mask_len,
1442 : : bool ufid_present, const ovs_u128 *ufid,
1443 : : const unsigned pmd_id, const struct ofpbuf *actions,
1444 : : uint64_t dump_seq, uint64_t reval_seq, long long int used,
1445 : : uint32_t key_recirc_id, struct xlate_out *xout)
1446 : : OVS_NO_THREAD_SAFETY_ANALYSIS
1447 : : {
1448 : 6744 : struct udpif_key *ukey = xmalloc(sizeof *ukey);
1449 : :
1450 : 6744 : memcpy(&ukey->keybuf, key, key_len);
1451 : 6744 : ukey->key = &ukey->keybuf.nla;
1452 : 6744 : ukey->key_len = key_len;
1453 : 6744 : memcpy(&ukey->maskbuf, mask, mask_len);
1454 : 6744 : ukey->mask = &ukey->maskbuf.nla;
1455 : 6744 : ukey->mask_len = mask_len;
1456 : 6744 : ukey->ufid_present = ufid_present;
1457 : 6744 : ukey->ufid = *ufid;
1458 : 6744 : ukey->pmd_id = pmd_id;
1459 : 6744 : ukey->hash = get_ukey_hash(&ukey->ufid, pmd_id);
1460 : :
1461 : 6744 : ovsrcu_init(&ukey->actions, NULL);
1462 : 6744 : ukey_set_actions(ukey, actions);
1463 : :
1464 : 6744 : ovs_mutex_init(&ukey->mutex);
1465 : 6744 : ukey->dump_seq = dump_seq;
1466 : 6744 : ukey->reval_seq = reval_seq;
1467 : 6744 : ukey->state = UKEY_CREATED;
1468 : 6744 : ukey->created = time_msec();
1469 : 6744 : memset(&ukey->stats, 0, sizeof ukey->stats);
1470 : 6744 : ukey->stats.used = used;
1471 : 6744 : ukey->xcache = NULL;
1472 : :
1473 : 6744 : ukey->key_recirc_id = key_recirc_id;
1474 : 6744 : recirc_refs_init(&ukey->recircs);
1475 [ + + ]: 6744 : if (xout) {
1476 : : /* Take ownership of the action recirc id references. */
1477 : 6681 : recirc_refs_swap(&ukey->recircs, &xout->recircs);
1478 : : }
1479 : :
1480 : 6744 : return ukey;
1481 : : }
1482 : :
1483 : : static struct udpif_key *
1484 : 6681 : ukey_create_from_upcall(struct upcall *upcall, struct flow_wildcards *wc)
1485 : : {
1486 : : struct odputil_keybuf keystub, maskstub;
1487 : : struct ofpbuf keybuf, maskbuf;
1488 : : bool megaflow;
1489 : 20043 : struct odp_flow_key_parms odp_parms = {
1490 : 6681 : .flow = upcall->flow,
1491 : 6681 : .mask = &wc->masks,
1492 : : };
1493 : :
1494 : 6681 : odp_parms.support = ofproto_dpif_get_support(upcall->ofproto)->odp;
1495 [ + + ]: 6681 : if (upcall->key_len) {
1496 : 1309 : ofpbuf_use_const(&keybuf, upcall->key, upcall->key_len);
1497 : : } else {
1498 : : /* dpif-netdev doesn't provide a netlink-formatted flow key in the
1499 : : * upcall, so convert the upcall's flow here. */
1500 : 5372 : ofpbuf_use_stack(&keybuf, &keystub, sizeof keystub);
1501 : 5372 : odp_flow_key_from_flow(&odp_parms, &keybuf);
1502 : : }
1503 : :
1504 : 6681 : atomic_read_relaxed(&enable_megaflows, &megaflow);
1505 : 6681 : ofpbuf_use_stack(&maskbuf, &maskstub, sizeof maskstub);
1506 [ + + ]: 6681 : if (megaflow) {
1507 : 5904 : odp_parms.key_buf = &keybuf;
1508 : 5904 : odp_flow_key_from_mask(&odp_parms, &maskbuf);
1509 : : }
1510 : :
1511 [ + + ]: 6681 : return ukey_create__(keybuf.data, keybuf.size, maskbuf.data, maskbuf.size,
1512 : : true, upcall->ufid, upcall->pmd_id,
1513 : 6681 : &upcall->put_actions, upcall->dump_seq,
1514 : : upcall->reval_seq, 0,
1515 : 7447 : upcall->have_recirc_ref ? upcall->recirc->id : 0,
1516 : : &upcall->xout);
1517 : : }
1518 : :
1519 : : static int
1520 : 63 : ukey_create_from_dpif_flow(const struct udpif *udpif,
1521 : : const struct dpif_flow *flow,
1522 : : struct udpif_key **ukey)
1523 : : {
1524 : : struct dpif_flow full_flow;
1525 : : struct ofpbuf actions;
1526 : : uint64_t dump_seq, reval_seq;
1527 : : uint64_t stub[DPIF_FLOW_BUFSIZE / 8];
1528 : : const struct nlattr *a;
1529 : : unsigned int left;
1530 : :
1531 [ - + ][ # # ]: 63 : if (!flow->key_len || !flow->actions_len) {
1532 : : struct ofpbuf buf;
1533 : : int err;
1534 : :
1535 : : /* If the key or actions were not provided by the datapath, fetch the
1536 : : * full flow. */
1537 : 63 : ofpbuf_use_stack(&buf, &stub, sizeof stub);
1538 [ + - ]: 63 : err = dpif_flow_get(udpif->dpif, flow->key, flow->key_len,
1539 : 63 : flow->ufid_present ? &flow->ufid : NULL,
1540 : : flow->pmd_id, &buf, &full_flow);
1541 [ - + ]: 63 : if (err) {
1542 : 0 : return err;
1543 : : }
1544 : 63 : flow = &full_flow;
1545 : : }
1546 : :
1547 : : /* Check the flow actions for recirculation action. As recirculation
1548 : : * relies on OVS userspace internal state, we need to delete all old
1549 : : * datapath flows with either a non-zero recirc_id in the key, or any
1550 : : * recirculation actions upon OVS restart. */
1551 [ + + ]: 756 : NL_ATTR_FOR_EACH_UNSAFE (a, left, flow->key, flow->key_len) {
1552 [ + + ]: 693 : if (nl_attr_type(a) == OVS_KEY_ATTR_RECIRC_ID
1553 [ - + ]: 63 : && nl_attr_get_u32(a) != 0) {
1554 : 0 : return EINVAL;
1555 : : }
1556 : : }
1557 [ - + ]: 63 : NL_ATTR_FOR_EACH_UNSAFE (a, left, flow->actions, flow->actions_len) {
1558 [ # # ]: 0 : if (nl_attr_type(a) == OVS_ACTION_ATTR_RECIRC) {
1559 : 0 : return EINVAL;
1560 : : }
1561 : : }
1562 : :
1563 : 63 : dump_seq = seq_read(udpif->dump_seq);
1564 : 63 : reval_seq = seq_read(udpif->reval_seq);
1565 : 63 : ofpbuf_use_const(&actions, &flow->actions, flow->actions_len);
1566 : 63 : *ukey = ukey_create__(flow->key, flow->key_len,
1567 : 63 : flow->mask, flow->mask_len, flow->ufid_present,
1568 : : &flow->ufid, flow->pmd_id, &actions, dump_seq,
1569 : : reval_seq, flow->stats.used, 0, NULL);
1570 : :
1571 : 63 : return 0;
1572 : : }
1573 : :
1574 : : static bool
1575 : 20 : try_ukey_replace(struct umap *umap, struct udpif_key *old_ukey,
1576 : : struct udpif_key *new_ukey)
1577 : : OVS_REQUIRES(umap->mutex)
1578 : : OVS_TRY_LOCK(true, new_ukey->mutex)
1579 : : {
1580 : 20 : bool replaced = false;
1581 : :
1582 [ + - ]: 20 : if (!ovs_mutex_trylock(&old_ukey->mutex)) {
1583 [ - + ]: 20 : if (old_ukey->state == UKEY_EVICTED) {
1584 : : /* The flow was deleted during the current revalidator dump,
1585 : : * but its ukey won't be fully cleaned up until the sweep phase.
1586 : : * In the mean time, we are receiving upcalls for this traffic.
1587 : : * Expedite the (new) flow install by replacing the ukey. */
1588 : 0 : ovs_mutex_lock(&new_ukey->mutex);
1589 : 0 : cmap_replace(&umap->cmap, &old_ukey->cmap_node,
1590 : : &new_ukey->cmap_node, new_ukey->hash);
1591 : 0 : ovsrcu_postpone(ukey_delete__, old_ukey);
1592 : 0 : transition_ukey(old_ukey, UKEY_DELETED);
1593 : 0 : transition_ukey(new_ukey, UKEY_VISIBLE);
1594 : 0 : replaced = true;
1595 : : }
1596 : 20 : ovs_mutex_unlock(&old_ukey->mutex);
1597 : : }
1598 : :
1599 [ - + ]: 20 : if (replaced) {
1600 : 0 : COVERAGE_INC(upcall_ukey_replace);
1601 : : } else {
1602 : 20 : COVERAGE_INC(handler_duplicate_upcall);
1603 : : }
1604 : 20 : return replaced;
1605 : : }
1606 : :
1607 : : /* Attempts to insert a ukey into the shared ukey maps.
1608 : : *
1609 : : * On success, returns true, installs the ukey and returns it in a locked
1610 : : * state. Otherwise, returns false. */
1611 : : static bool
1612 : 6739 : ukey_install__(struct udpif *udpif, struct udpif_key *new_ukey)
1613 : : OVS_TRY_LOCK(true, new_ukey->mutex)
1614 : : {
1615 : : struct umap *umap;
1616 : : struct udpif_key *old_ukey;
1617 : : uint32_t idx;
1618 : 6739 : bool locked = false;
1619 : :
1620 : 6739 : idx = new_ukey->hash % N_UMAPS;
1621 : 6739 : umap = &udpif->ukeys[idx];
1622 : 6739 : ovs_mutex_lock(&umap->mutex);
1623 : 6739 : old_ukey = ukey_lookup(udpif, &new_ukey->ufid, new_ukey->pmd_id);
1624 [ + + ]: 6739 : if (old_ukey) {
1625 : : /* Uncommon case: A ukey is already installed with the same UFID. */
1626 [ + - ]: 20 : if (old_ukey->key_len == new_ukey->key_len
1627 [ + - ]: 20 : && !memcmp(old_ukey->key, new_ukey->key, new_ukey->key_len)) {
1628 : 20 : locked = try_ukey_replace(umap, old_ukey, new_ukey);
1629 : : } else {
1630 : 0 : struct ds ds = DS_EMPTY_INITIALIZER;
1631 : :
1632 : 0 : odp_format_ufid(&old_ukey->ufid, &ds);
1633 : 0 : ds_put_cstr(&ds, " ");
1634 : 0 : odp_flow_key_format(old_ukey->key, old_ukey->key_len, &ds);
1635 : 0 : ds_put_cstr(&ds, "\n");
1636 : 0 : odp_format_ufid(&new_ukey->ufid, &ds);
1637 : 0 : ds_put_cstr(&ds, " ");
1638 : 0 : odp_flow_key_format(new_ukey->key, new_ukey->key_len, &ds);
1639 : :
1640 [ # # ]: 0 : VLOG_WARN_RL(&rl, "Conflicting ukey for flows:\n%s", ds_cstr(&ds));
1641 : 20 : ds_destroy(&ds);
1642 : : }
1643 : : } else {
1644 : 6719 : ovs_mutex_lock(&new_ukey->mutex);
1645 : 6719 : cmap_insert(&umap->cmap, &new_ukey->cmap_node, new_ukey->hash);
1646 : 6719 : transition_ukey(new_ukey, UKEY_VISIBLE);
1647 : 6719 : locked = true;
1648 : : }
1649 : 6739 : ovs_mutex_unlock(&umap->mutex);
1650 : :
1651 : 6739 : return locked;
1652 : : }
1653 : :
1654 : : static void
1655 : 195169 : transition_ukey(struct udpif_key *ukey, enum ukey_state dst)
1656 : : OVS_REQUIRES(ukey->mutex)
1657 : : {
1658 [ - + ]: 195169 : ovs_assert(dst >= ukey->state);
1659 [ + + ]: 195169 : if (ukey->state == dst) {
1660 : 161834 : return;
1661 : : }
1662 : :
1663 : : /* Valid state transitions:
1664 : : * UKEY_CREATED -> UKEY_VISIBLE
1665 : : * Ukey is now visible in the umap.
1666 : : * UKEY_VISIBLE -> UKEY_OPERATIONAL
1667 : : * A handler has installed the flow, and the flow is in the datapath.
1668 : : * UKEY_VISIBLE -> UKEY_EVICTING
1669 : : * A handler installs the flow, then revalidator sweeps the ukey before
1670 : : * the flow is dumped. Most likely the flow was installed; start trying
1671 : : * to delete it.
1672 : : * UKEY_VISIBLE -> UKEY_EVICTED
1673 : : * A handler attempts to install the flow, but the datapath rejects it.
1674 : : * Consider that the datapath has already destroyed it.
1675 : : * UKEY_OPERATIONAL -> UKEY_EVICTING
1676 : : * A revalidator decides to evict the datapath flow.
1677 : : * UKEY_EVICTING -> UKEY_EVICTED
1678 : : * A revalidator has evicted the datapath flow.
1679 : : * UKEY_EVICTED -> UKEY_DELETED
1680 : : * A revalidator has removed the ukey from the umap and is deleting it.
1681 : : */
1682 [ + + ][ + - ]: 33335 : if (ukey->state == dst - 1 || (ukey->state == UKEY_VISIBLE &&
[ + - ]
1683 : : dst < UKEY_DELETED)) {
1684 : 33335 : ukey->state = dst;
1685 : : } else {
1686 : 0 : struct ds ds = DS_EMPTY_INITIALIZER;
1687 : :
1688 : 0 : odp_format_ufid(&ukey->ufid, &ds);
1689 [ # # ]: 0 : VLOG_WARN_RL(&rl, "Invalid state transition for ukey %s: %d -> %d",
1690 : : ds_cstr(&ds), ukey->state, dst);
1691 : 0 : ds_destroy(&ds);
1692 : : }
1693 : : }
1694 : :
1695 : : static bool
1696 : 6676 : ukey_install(struct udpif *udpif, struct udpif_key *ukey)
1697 : : {
1698 : : bool installed;
1699 : :
1700 : 6676 : installed = ukey_install__(udpif, ukey);
1701 [ + + ]: 6676 : if (installed) {
1702 : 6656 : ovs_mutex_unlock(&ukey->mutex);
1703 : : }
1704 : :
1705 : 6676 : return installed;
1706 : : }
1707 : :
1708 : : /* Searches for a ukey in 'udpif->ukeys' that matches 'flow' and attempts to
1709 : : * lock the ukey. If the ukey does not exist, create it.
1710 : : *
1711 : : * Returns 0 on success, setting *result to the matching ukey and returning it
1712 : : * in a locked state. Otherwise, returns an errno and clears *result. EBUSY
1713 : : * indicates that another thread is handling this flow. Other errors indicate
1714 : : * an unexpected condition creating a new ukey.
1715 : : *
1716 : : * *error is an output parameter provided to appease the threadsafety analyser,
1717 : : * and its value matches the return value. */
1718 : : static int
1719 : 173505 : ukey_acquire(struct udpif *udpif, const struct dpif_flow *flow,
1720 : : struct udpif_key **result, int *error)
1721 : : OVS_TRY_LOCK(0, (*result)->mutex)
1722 : : {
1723 : : struct udpif_key *ukey;
1724 : : int retval;
1725 : :
1726 : 173505 : ukey = ukey_lookup(udpif, &flow->ufid, flow->pmd_id);
1727 [ + + ]: 173505 : if (ukey) {
1728 : 173442 : retval = ovs_mutex_trylock(&ukey->mutex);
1729 : : } else {
1730 : : /* Usually we try to avoid installing flows from revalidator threads,
1731 : : * because locking on a umap may cause handler threads to block.
1732 : : * However there are certain cases, like when ovs-vswitchd is
1733 : : * restarted, where it is desirable to handle flows that exist in the
1734 : : * datapath gracefully (ie, don't just clear the datapath). */
1735 : : bool install;
1736 : :
1737 : 63 : retval = ukey_create_from_dpif_flow(udpif, flow, &ukey);
1738 [ - + ]: 63 : if (retval) {
1739 : 0 : goto done;
1740 : : }
1741 : 63 : install = ukey_install__(udpif, ukey);
1742 [ + - ]: 63 : if (install) {
1743 : 63 : retval = 0;
1744 : : } else {
1745 : 0 : ukey_delete__(ukey);
1746 : 0 : retval = EBUSY;
1747 : : }
1748 : : }
1749 : :
1750 : : done:
1751 : 173505 : *error = retval;
1752 [ - + ]: 173505 : if (retval) {
1753 : 0 : *result = NULL;
1754 : : } else {
1755 : 173505 : *result = ukey;
1756 : : }
1757 : 173505 : return retval;
1758 : : }
1759 : :
1760 : : static void
1761 : 6723 : ukey_delete__(struct udpif_key *ukey)
1762 : : OVS_NO_THREAD_SAFETY_ANALYSIS
1763 : : {
1764 [ + - ]: 6723 : if (ukey) {
1765 [ + + ]: 6723 : if (ukey->key_recirc_id) {
1766 : 764 : recirc_free_id(ukey->key_recirc_id);
1767 : : }
1768 : 6723 : recirc_refs_unref(&ukey->recircs);
1769 : 6723 : xlate_cache_delete(ukey->xcache);
1770 : 6723 : ofpbuf_delete(ovsrcu_get(struct ofpbuf *, &ukey->actions));
1771 : 6723 : ovs_mutex_destroy(&ukey->mutex);
1772 : 6723 : free(ukey);
1773 : : }
1774 : 6723 : }
1775 : :
1776 : : static void
1777 : 6719 : ukey_delete(struct umap *umap, struct udpif_key *ukey)
1778 : : OVS_REQUIRES(umap->mutex)
1779 : : {
1780 : 6719 : ovs_mutex_lock(&ukey->mutex);
1781 : 6719 : cmap_remove(&umap->cmap, &ukey->cmap_node, ukey->hash);
1782 : 6719 : ovsrcu_postpone(ukey_delete__, ukey);
1783 : 6719 : transition_ukey(ukey, UKEY_DELETED);
1784 : 6719 : ovs_mutex_unlock(&ukey->mutex);
1785 : 6719 : }
1786 : :
1787 : : static bool
1788 : 9836 : should_revalidate(const struct udpif *udpif, uint64_t packets,
1789 : : long long int used)
1790 : : {
1791 : : long long int metric, now, duration;
1792 : :
1793 [ + - ]: 9836 : if (udpif->dump_duration < 200) {
1794 : : /* We are likely to handle full revalidation for the flows. */
1795 : 9836 : return true;
1796 : : }
1797 : :
1798 : : /* Calculate the mean time between seeing these packets. If this
1799 : : * exceeds the threshold, then delete the flow rather than performing
1800 : : * costly revalidation for flows that aren't being hit frequently.
1801 : : *
1802 : : * This is targeted at situations where the dump_duration is high (~1s),
1803 : : * and revalidation is triggered by a call to udpif_revalidate(). In
1804 : : * these situations, revalidation of all flows causes fluctuations in the
1805 : : * flow_limit due to the interaction with the dump_duration and max_idle.
1806 : : * This tends to result in deletion of low-throughput flows anyway, so
1807 : : * skip the revalidation and just delete those flows. */
1808 : 0 : packets = MAX(packets, 1);
1809 [ # # ]: 0 : now = MAX(used, time_msec());
1810 : 0 : duration = now - used;
1811 : 0 : metric = duration / packets;
1812 : :
1813 [ # # ]: 0 : if (metric < 200) {
1814 : : /* The flow is receiving more than ~5pps, so keep it. */
1815 : 0 : return true;
1816 : : }
1817 : 0 : return false;
1818 : : }
1819 : :
1820 : : /* Verifies that the datapath actions of 'ukey' are still correct, and pushes
1821 : : * 'stats' for it.
1822 : : *
1823 : : * Returns a recommended action for 'ukey', options include:
1824 : : * UKEY_DELETE The ukey should be deleted.
1825 : : * UKEY_KEEP The ukey is fine as is.
1826 : : * UKEY_MODIFY The ukey's actions should be changed but is otherwise
1827 : : * fine. Callers should change the actions to those found
1828 : : * in the caller supplied 'odp_actions' buffer. The
1829 : : * recirculation references can be found in 'recircs' and
1830 : : * must be handled by the caller.
1831 : : *
1832 : : * If the result is UKEY_MODIFY, then references to all recirc_ids used by the
1833 : : * new flow will be held within 'recircs' (which may be none).
1834 : : *
1835 : : * The caller is responsible for both initializing 'recircs' prior this call,
1836 : : * and ensuring any references are eventually freed.
1837 : : */
1838 : : static enum reval_result
1839 : 164564 : revalidate_ukey(struct udpif *udpif, struct udpif_key *ukey,
1840 : : const struct dpif_flow_stats *stats,
1841 : : struct ofpbuf *odp_actions, uint64_t reval_seq,
1842 : : struct recirc_refs *recircs)
1843 : : OVS_REQUIRES(ukey->mutex)
1844 : : {
1845 : : struct xlate_out xout, *xoutp;
1846 : : struct netflow *netflow;
1847 : : struct ofproto_dpif *ofproto;
1848 : : struct dpif_flow_stats push;
1849 : : struct flow flow;
1850 : : struct flow_wildcards dp_mask, wc;
1851 : : enum reval_result result;
1852 : : ofp_port_t ofp_in_port;
1853 : : struct xlate_in xin;
1854 : : long long int last_used;
1855 : : int error;
1856 : : bool need_revalidate;
1857 : :
1858 : 164564 : result = UKEY_DELETE;
1859 : 164564 : xoutp = NULL;
1860 : 164564 : netflow = NULL;
1861 : :
1862 : 164564 : ofpbuf_clear(odp_actions);
1863 : 164564 : need_revalidate = (ukey->reval_seq != reval_seq);
1864 : 164564 : last_used = ukey->stats.used;
1865 : 164564 : push.used = stats->used;
1866 : 164564 : push.tcp_flags = stats->tcp_flags;
1867 : 329128 : push.n_packets = (stats->n_packets > ukey->stats.n_packets
1868 : 5162 : ? stats->n_packets - ukey->stats.n_packets
1869 [ + + ]: 164564 : : 0);
1870 : 329128 : push.n_bytes = (stats->n_bytes > ukey->stats.n_bytes
1871 : 5162 : ? stats->n_bytes - ukey->stats.n_bytes
1872 [ + + ]: 164564 : : 0);
1873 : :
1874 [ + + ][ + + ]: 164564 : if (need_revalidate && last_used
1875 [ - + ]: 9836 : && !should_revalidate(udpif, push.n_packets, last_used)) {
1876 : 0 : goto exit;
1877 : : }
1878 : :
1879 : : /* We will push the stats, so update the ukey stats cache. */
1880 : 164564 : ukey->stats = *stats;
1881 [ + + ][ + + ]: 164564 : if (!push.n_packets && !need_revalidate) {
1882 : 92049 : result = UKEY_KEEP;
1883 : 92049 : goto exit;
1884 : : }
1885 : :
1886 [ + + ][ + + ]: 72515 : if (ukey->xcache && !need_revalidate) {
1887 : 3942 : xlate_push_stats(ukey->xcache, &push);
1888 : 3942 : result = UKEY_KEEP;
1889 : 3942 : goto exit;
1890 : : }
1891 : :
1892 [ - + ]: 68573 : if (odp_flow_key_to_flow(ukey->key, ukey->key_len, &flow)
1893 : : == ODP_FIT_ERROR) {
1894 : 0 : goto exit;
1895 : : }
1896 : :
1897 : 68573 : error = xlate_lookup(udpif->backer, &flow, &ofproto, NULL, NULL, &netflow,
1898 : : &ofp_in_port);
1899 [ + + ]: 68573 : if (error) {
1900 : 165 : goto exit;
1901 : : }
1902 : :
1903 [ + + ]: 68408 : if (need_revalidate) {
1904 : 67741 : xlate_cache_clear(ukey->xcache);
1905 : : }
1906 [ + + ]: 68408 : if (!ukey->xcache) {
1907 : 3611 : ukey->xcache = xlate_cache_new();
1908 : : }
1909 : :
1910 [ + + ]: 68408 : xlate_in_init(&xin, ofproto, &flow, ofp_in_port, NULL, push.tcp_flags,
1911 : : NULL, need_revalidate ? &wc : NULL, odp_actions);
1912 [ + + ]: 68408 : if (push.n_packets) {
1913 : 1220 : xin.resubmit_stats = &push;
1914 : 1220 : xin.may_learn = true;
1915 : : }
1916 : 68408 : xin.xcache = ukey->xcache;
1917 : 68408 : xlate_actions(&xin, &xout);
1918 : 68408 : xoutp = &xout;
1919 : :
1920 [ + + ]: 68408 : if (!need_revalidate) {
1921 : 667 : result = UKEY_KEEP;
1922 : 667 : goto exit;
1923 : : }
1924 : :
1925 [ + + ]: 67741 : if (xout.slow) {
1926 : 26625 : ofpbuf_clear(odp_actions);
1927 : 26625 : compose_slow_path(udpif, &xout, &flow, flow.in_port.odp_port,
1928 : : odp_actions);
1929 : : }
1930 : :
1931 [ - + ]: 67741 : if (odp_flow_key_to_mask(ukey->mask, ukey->mask_len, ukey->key,
1932 : : ukey->key_len, &dp_mask, &flow)
1933 : : == ODP_FIT_ERROR) {
1934 : 0 : goto exit;
1935 : : }
1936 : :
1937 : : /* Do not modify if any bit is wildcarded by the installed datapath flow,
1938 : : * but not the newly revalidated wildcard mask (wc), i.e., if revalidation
1939 : : * tells that the datapath flow is now too generic and must be narrowed
1940 : : * down. Note that we do not know if the datapath has ignored any of the
1941 : : * wildcarded bits, so we may be overtly conservative here. */
1942 [ + + ]: 67741 : if (flow_wildcards_has_extra(&dp_mask, &wc)) {
1943 : 590 : goto exit;
1944 : : }
1945 : :
1946 [ + + ]: 67151 : if (!ofpbuf_equal(odp_actions,
1947 : 67151 : ovsrcu_get(struct ofpbuf *, &ukey->actions))) {
1948 : : /* The datapath mask was OK, but the actions seem to have changed.
1949 : : * Let's modify it in place. */
1950 : 429 : result = UKEY_MODIFY;
1951 : : /* Transfer recirc action ID references to the caller. */
1952 : 429 : recirc_refs_swap(recircs, &xoutp->recircs);
1953 : 429 : goto exit;
1954 : : }
1955 : :
1956 : 66722 : result = UKEY_KEEP;
1957 : :
1958 : : exit:
1959 [ + + ]: 164564 : if (result != UKEY_DELETE) {
1960 : 163809 : ukey->reval_seq = reval_seq;
1961 : : }
1962 [ + + ][ - + ]: 164564 : if (netflow && result == UKEY_DELETE) {
1963 : 0 : netflow_flow_clear(netflow, &flow);
1964 : : }
1965 : 164564 : xlate_out_uninit(xoutp);
1966 : 164564 : return result;
1967 : : }
1968 : :
1969 : : static void
1970 : 0 : delete_op_init__(struct udpif *udpif, struct ukey_op *op,
1971 : : const struct dpif_flow *flow)
1972 : : {
1973 : 0 : op->ukey = NULL;
1974 : 0 : op->dop.type = DPIF_OP_FLOW_DEL;
1975 : 0 : op->dop.u.flow_del.key = flow->key;
1976 : 0 : op->dop.u.flow_del.key_len = flow->key_len;
1977 [ # # ]: 0 : op->dop.u.flow_del.ufid = flow->ufid_present ? &flow->ufid : NULL;
1978 : 0 : op->dop.u.flow_del.pmd_id = flow->pmd_id;
1979 : 0 : op->dop.u.flow_del.stats = &op->stats;
1980 : 0 : op->dop.u.flow_del.terse = udpif_use_ufid(udpif);
1981 : 0 : }
1982 : :
1983 : : static void
1984 : 6691 : delete_op_init(struct udpif *udpif, struct ukey_op *op, struct udpif_key *ukey)
1985 : : {
1986 : 6691 : op->ukey = ukey;
1987 : 6691 : op->dop.type = DPIF_OP_FLOW_DEL;
1988 : 6691 : op->dop.u.flow_del.key = ukey->key;
1989 : 6691 : op->dop.u.flow_del.key_len = ukey->key_len;
1990 [ + - ]: 6691 : op->dop.u.flow_del.ufid = ukey->ufid_present ? &ukey->ufid : NULL;
1991 : 6691 : op->dop.u.flow_del.pmd_id = ukey->pmd_id;
1992 : 6691 : op->dop.u.flow_del.stats = &op->stats;
1993 : 6691 : op->dop.u.flow_del.terse = udpif_use_ufid(udpif);
1994 : 6691 : }
1995 : :
1996 : : static void
1997 : 1713 : put_op_init(struct ukey_op *op, struct udpif_key *ukey,
1998 : : enum dpif_flow_put_flags flags)
1999 : : {
2000 : 1713 : op->ukey = ukey;
2001 : 1713 : op->dop.type = DPIF_OP_FLOW_PUT;
2002 : 1713 : op->dop.u.flow_put.flags = flags;
2003 : 1713 : op->dop.u.flow_put.key = ukey->key;
2004 : 1713 : op->dop.u.flow_put.key_len = ukey->key_len;
2005 : 1713 : op->dop.u.flow_put.mask = ukey->mask;
2006 : 1713 : op->dop.u.flow_put.mask_len = ukey->mask_len;
2007 [ + - ]: 1713 : op->dop.u.flow_put.ufid = ukey->ufid_present ? &ukey->ufid : NULL;
2008 : 1713 : op->dop.u.flow_put.pmd_id = ukey->pmd_id;
2009 : 1713 : op->dop.u.flow_put.stats = NULL;
2010 : 1713 : ukey_get_actions(ukey, &op->dop.u.flow_put.actions,
2011 : : &op->dop.u.flow_put.actions_len);
2012 : 1713 : }
2013 : :
2014 : : /* Executes datapath operations 'ops' and attributes stats retrieved from the
2015 : : * datapath as part of those operations. */
2016 : : static void
2017 : 4455 : push_dp_ops(struct udpif *udpif, struct ukey_op *ops, size_t n_ops)
2018 : : {
2019 : : struct dpif_op *opsp[REVALIDATE_MAX_BATCH];
2020 : : size_t i;
2021 : :
2022 [ - + ]: 4455 : ovs_assert(n_ops <= REVALIDATE_MAX_BATCH);
2023 [ + + ]: 11575 : for (i = 0; i < n_ops; i++) {
2024 : 7120 : opsp[i] = &ops[i].dop;
2025 : : }
2026 : 4455 : dpif_operate(udpif->dpif, opsp, n_ops);
2027 : :
2028 [ + + ]: 11575 : for (i = 0; i < n_ops; i++) {
2029 : 7120 : struct ukey_op *op = &ops[i];
2030 : : struct dpif_flow_stats *push, *stats, push_buf;
2031 : :
2032 : 7120 : stats = op->dop.u.flow_del.stats;
2033 : 7120 : push = &push_buf;
2034 : :
2035 [ + + ]: 7120 : if (op->dop.type != DPIF_OP_FLOW_DEL) {
2036 : : /* Only deleted flows need their stats pushed. */
2037 : 697 : continue;
2038 : : }
2039 : :
2040 [ - + ]: 6691 : if (op->dop.error) {
2041 : : /* flow_del error, 'stats' is unusable. */
2042 : 0 : continue;
2043 : : }
2044 : :
2045 [ + - ]: 6691 : if (op->ukey) {
2046 : 6691 : ovs_mutex_lock(&op->ukey->mutex);
2047 : 6691 : transition_ukey(op->ukey, UKEY_EVICTED);
2048 : 6691 : push->used = MAX(stats->used, op->ukey->stats.used);
2049 : 6691 : push->tcp_flags = stats->tcp_flags | op->ukey->stats.tcp_flags;
2050 : 6691 : push->n_packets = stats->n_packets - op->ukey->stats.n_packets;
2051 : 6691 : push->n_bytes = stats->n_bytes - op->ukey->stats.n_bytes;
2052 : 6691 : ovs_mutex_unlock(&op->ukey->mutex);
2053 : : } else {
2054 : 0 : push = stats;
2055 : : }
2056 : :
2057 [ + + ][ + + ]: 6691 : if (push->n_packets || netflow_exists()) {
2058 : 465 : const struct nlattr *key = op->dop.u.flow_del.key;
2059 : 465 : size_t key_len = op->dop.u.flow_del.key_len;
2060 : : struct ofproto_dpif *ofproto;
2061 : : struct netflow *netflow;
2062 : : ofp_port_t ofp_in_port;
2063 : : struct flow flow;
2064 : : int error;
2065 : :
2066 [ + - ]: 465 : if (op->ukey) {
2067 : 465 : ovs_mutex_lock(&op->ukey->mutex);
2068 [ + + ]: 465 : if (op->ukey->xcache) {
2069 : 268 : xlate_push_stats(op->ukey->xcache, push);
2070 : 268 : ovs_mutex_unlock(&op->ukey->mutex);
2071 : 6691 : continue;
2072 : : }
2073 : 197 : ovs_mutex_unlock(&op->ukey->mutex);
2074 : 197 : key = op->ukey->key;
2075 : 197 : key_len = op->ukey->key_len;
2076 : : }
2077 : :
2078 [ - + ]: 197 : if (odp_flow_key_to_flow(key, key_len, &flow)
2079 : : == ODP_FIT_ERROR) {
2080 : 0 : continue;
2081 : : }
2082 : :
2083 : 197 : error = xlate_lookup(udpif->backer, &flow, &ofproto, NULL, NULL,
2084 : : &netflow, &ofp_in_port);
2085 [ + - ]: 197 : if (!error) {
2086 : : struct xlate_in xin;
2087 : :
2088 : 197 : xlate_in_init(&xin, ofproto, &flow, ofp_in_port, NULL,
2089 : 197 : push->tcp_flags, NULL, NULL, NULL);
2090 [ + - ]: 197 : xin.resubmit_stats = push->n_packets ? push : NULL;
2091 : 197 : xin.may_learn = push->n_packets > 0;
2092 : 197 : xlate_actions_for_side_effects(&xin);
2093 : :
2094 [ - + ]: 197 : if (netflow) {
2095 : 197 : netflow_flow_clear(netflow, &flow);
2096 : : }
2097 : : }
2098 : : }
2099 : : }
2100 : 4455 : }
2101 : :
2102 : : /* Executes datapath operations 'ops', attributes stats retrieved from the
2103 : : * datapath, and deletes ukeys corresponding to deleted flows. */
2104 : : static void
2105 : 2902 : push_ukey_ops(struct udpif *udpif, struct umap *umap,
2106 : : struct ukey_op *ops, size_t n_ops)
2107 : : {
2108 : : int i;
2109 : :
2110 : 2902 : push_dp_ops(udpif, ops, n_ops);
2111 : 2902 : ovs_mutex_lock(&umap->mutex);
2112 [ + + ]: 6337 : for (i = 0; i < n_ops; i++) {
2113 [ + - ]: 3435 : if (ops[i].dop.type == DPIF_OP_FLOW_DEL) {
2114 : 3435 : ukey_delete(umap, ops[i].ukey);
2115 : : }
2116 : : }
2117 : 2902 : ovs_mutex_unlock(&umap->mutex);
2118 : 2902 : }
2119 : :
2120 : : static void
2121 : 0 : log_unexpected_flow(const struct dpif_flow *flow, int error)
2122 : : {
2123 : : static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(10, 60);
2124 : 0 : struct ds ds = DS_EMPTY_INITIALIZER;
2125 : :
2126 : 0 : ds_put_format(&ds, "Failed to acquire udpif_key corresponding to "
2127 : : "unexpected flow (%s): ", ovs_strerror(error));
2128 : 0 : odp_format_ufid(&flow->ufid, &ds);
2129 [ # # ]: 0 : VLOG_WARN_RL(&rl, "%s", ds_cstr(&ds));
2130 : 0 : ds_destroy(&ds);
2131 : 0 : }
2132 : :
2133 : : static void
2134 : 7114 : reval_op_init(struct ukey_op *op, enum reval_result result,
2135 : : struct udpif *udpif, struct udpif_key *ukey,
2136 : : struct recirc_refs *recircs, struct ofpbuf *odp_actions)
2137 : : OVS_REQUIRES(ukey->mutex)
2138 : : {
2139 [ + + ]: 7114 : if (result == UKEY_DELETE) {
2140 : 6685 : delete_op_init(udpif, op, ukey);
2141 : 6685 : transition_ukey(ukey, UKEY_EVICTING);
2142 [ + - ]: 429 : } else if (result == UKEY_MODIFY) {
2143 : : /* Store the new recircs. */
2144 : 429 : recirc_refs_swap(&ukey->recircs, recircs);
2145 : : /* Release old recircs. */
2146 : 429 : recirc_refs_unref(recircs);
2147 : : /* ukey->key_recirc_id remains, as the key is the same as before. */
2148 : :
2149 : 429 : ukey_set_actions(ukey, odp_actions);
2150 : 429 : put_op_init(op, ukey, DPIF_FP_MODIFY);
2151 : : }
2152 : 7114 : }
2153 : :
2154 : : static void
2155 : 28167 : revalidate(struct revalidator *revalidator)
2156 : : {
2157 : : uint64_t odp_actions_stub[1024 / 8];
2158 : 28167 : struct ofpbuf odp_actions = OFPBUF_STUB_INITIALIZER(odp_actions_stub);
2159 : :
2160 : 28167 : struct udpif *udpif = revalidator->udpif;
2161 : : struct dpif_flow_dump_thread *dump_thread;
2162 : : uint64_t dump_seq, reval_seq;
2163 : : unsigned int flow_limit;
2164 : :
2165 : 28167 : dump_seq = seq_read(udpif->dump_seq);
2166 : 28167 : reval_seq = seq_read(udpif->reval_seq);
2167 : 28167 : atomic_read_relaxed(&udpif->flow_limit, &flow_limit);
2168 : 28167 : dump_thread = dpif_flow_dump_thread_create(udpif->dump);
2169 : : for (;;) {
2170 : : struct ukey_op ops[REVALIDATE_MAX_BATCH];
2171 : 36548 : int n_ops = 0;
2172 : :
2173 : : struct dpif_flow flows[REVALIDATE_MAX_BATCH];
2174 : : const struct dpif_flow *f;
2175 : : int n_dumped;
2176 : :
2177 : : long long int max_idle;
2178 : : long long int now;
2179 : : size_t n_dp_flows;
2180 : : bool kill_them_all;
2181 : :
2182 : 36548 : n_dumped = dpif_flow_dump_next(dump_thread, flows, ARRAY_SIZE(flows));
2183 [ + + ]: 36548 : if (!n_dumped) {
2184 : 28167 : break;
2185 : : }
2186 : :
2187 : 8381 : now = time_msec();
2188 : :
2189 : : /* In normal operation we want to keep flows around until they have
2190 : : * been idle for 'ofproto_max_idle' milliseconds. However:
2191 : : *
2192 : : * - If the number of datapath flows climbs above 'flow_limit',
2193 : : * drop that down to 100 ms to try to bring the flows down to
2194 : : * the limit.
2195 : : *
2196 : : * - If the number of datapath flows climbs above twice
2197 : : * 'flow_limit', delete all the datapath flows as an emergency
2198 : : * measure. (We reassess this condition for the next batch of
2199 : : * datapath flows, so we will recover before all the flows are
2200 : : * gone.) */
2201 : 8381 : n_dp_flows = udpif_get_n_flows(udpif);
2202 : 8381 : kill_them_all = n_dp_flows > flow_limit * 2;
2203 [ + - ]: 8381 : max_idle = n_dp_flows > flow_limit ? 100 : ofproto_max_idle;
2204 : :
2205 [ + + ]: 181886 : for (f = flows; f < &flows[n_dumped]; f++) {
2206 : 173505 : long long int used = f->stats.used;
2207 : 173505 : struct recirc_refs recircs = RECIRC_REFS_EMPTY_INITIALIZER;
2208 : : enum reval_result result;
2209 : : struct udpif_key *ukey;
2210 : : bool already_dumped;
2211 : : int error;
2212 : :
2213 [ - + ]: 173505 : if (ukey_acquire(udpif, f, &ukey, &error)) {
2214 [ # # ]: 0 : if (error == EBUSY) {
2215 : : /* Another thread is processing this flow, so don't bother
2216 : : * processing it.*/
2217 : 0 : COVERAGE_INC(upcall_ukey_contention);
2218 : : } else {
2219 : 0 : log_unexpected_flow(f, error);
2220 [ # # ]: 0 : if (error != ENOENT) {
2221 : 0 : delete_op_init__(udpif, &ops[n_ops++], f);
2222 : : }
2223 : : }
2224 : 6440 : continue;
2225 : : }
2226 : :
2227 : 173505 : already_dumped = ukey->dump_seq == dump_seq;
2228 [ + + ]: 173505 : if (already_dumped) {
2229 : : /* The flow has already been handled during this flow dump
2230 : : * operation. Skip it. */
2231 [ - + ]: 6440 : if (ukey->xcache) {
2232 : 0 : COVERAGE_INC(dumped_duplicate_flow);
2233 : : } else {
2234 : 6440 : COVERAGE_INC(dumped_new_flow);
2235 : : }
2236 : 6440 : ovs_mutex_unlock(&ukey->mutex);
2237 : 6440 : continue;
2238 : : }
2239 : :
2240 : : /* The flow is now confirmed to be in the datapath. */
2241 : 167065 : transition_ukey(ukey, UKEY_OPERATIONAL);
2242 : :
2243 [ + + ]: 167065 : if (!used) {
2244 : 140316 : used = ukey->created;
2245 : : }
2246 [ + - ][ + - ]: 167065 : if (kill_them_all || (used && used < now - max_idle)) {
[ + + ]
2247 : 2501 : result = UKEY_DELETE;
2248 : : } else {
2249 : 164564 : result = revalidate_ukey(udpif, ukey, &f->stats, &odp_actions,
2250 : : reval_seq, &recircs);
2251 : : }
2252 : 167065 : ukey->dump_seq = dump_seq;
2253 : :
2254 [ + + ]: 167065 : if (result != UKEY_KEEP) {
2255 : : /* Takes ownership of 'recircs'. */
2256 : 3685 : reval_op_init(&ops[n_ops++], result, udpif, ukey, &recircs,
2257 : : &odp_actions);
2258 : : }
2259 : 167065 : ovs_mutex_unlock(&ukey->mutex);
2260 : : }
2261 : :
2262 [ + + ]: 8381 : if (n_ops) {
2263 : : /* Push datapath ops but defer ukey deletion to 'sweep' phase. */
2264 : 1553 : push_dp_ops(udpif, ops, n_ops);
2265 : : }
2266 : 8381 : ovsrcu_quiesce();
2267 : 8381 : }
2268 : 28167 : dpif_flow_dump_thread_destroy(dump_thread);
2269 : 28167 : ofpbuf_uninit(&odp_actions);
2270 : 28167 : }
2271 : :
2272 : : /* Pauses the 'revalidator', can only proceed after main thread
2273 : : * calls udpif_resume_revalidators(). */
2274 : : static void
2275 : 45 : revalidator_pause(struct revalidator *revalidator)
2276 : : {
2277 : : /* The first block is for sync'ing the pause with main thread. */
2278 : 45 : ovs_barrier_block(&revalidator->udpif->pause_barrier);
2279 : : /* The second block is for pausing until main thread resumes. */
2280 : 45 : ovs_barrier_block(&revalidator->udpif->pause_barrier);
2281 : 45 : }
2282 : :
2283 : : static void
2284 : 30495 : revalidator_sweep__(struct revalidator *revalidator, bool purge)
2285 : : {
2286 : : struct udpif *udpif;
2287 : : uint64_t dump_seq, reval_seq;
2288 : : int slice;
2289 : :
2290 : 30495 : udpif = revalidator->udpif;
2291 : 30495 : dump_seq = seq_read(udpif->dump_seq);
2292 : 30495 : reval_seq = seq_read(udpif->reval_seq);
2293 : 30495 : slice = revalidator - udpif->revalidators;
2294 [ - + ]: 30495 : ovs_assert(slice < udpif->n_revalidators);
2295 : :
2296 [ + + ]: 15640863 : for (int i = slice; i < N_UMAPS; i += udpif->n_revalidators) {
2297 : : uint64_t odp_actions_stub[1024 / 8];
2298 : 15610368 : struct ofpbuf odp_actions = OFPBUF_STUB_INITIALIZER(odp_actions_stub);
2299 : :
2300 : : struct ukey_op ops[REVALIDATE_MAX_BATCH];
2301 : : struct udpif_key *ukey;
2302 : 15610368 : struct umap *umap = &udpif->ukeys[i];
2303 : 15610368 : size_t n_ops = 0;
2304 : :
2305 [ + + ][ + + ]: 15787389 : CMAP_FOR_EACH(ukey, cmap_node, &umap->cmap) {
2306 : : enum ukey_state ukey_state;
2307 : :
2308 : : /* Handler threads could be holding a ukey lock while it installs a
2309 : : * new flow, so don't hang around waiting for access to it. */
2310 [ - + ]: 177021 : if (ovs_mutex_trylock(&ukey->mutex)) {
2311 : 0 : continue;
2312 : : }
2313 : 177021 : ukey_state = ukey->state;
2314 [ + + ]: 177021 : if (ukey_state == UKEY_OPERATIONAL
2315 [ + + ][ + + ]: 8800 : || (ukey_state == UKEY_VISIBLE && purge)) {
2316 : 168422 : struct recirc_refs recircs = RECIRC_REFS_EMPTY_INITIALIZER;
2317 : 336844 : bool seq_mismatch = (ukey->dump_seq != dump_seq
2318 [ + + ][ + + ]: 168422 : && ukey->reval_seq != reval_seq);
2319 : : enum reval_result result;
2320 : :
2321 [ + + ]: 168422 : if (purge) {
2322 : 3429 : result = UKEY_DELETE;
2323 [ + - ]: 164993 : } else if (!seq_mismatch) {
2324 : 164993 : result = UKEY_KEEP;
2325 : : } else {
2326 : : struct dpif_flow_stats stats;
2327 : 0 : COVERAGE_INC(revalidate_missed_dp_flow);
2328 : 0 : memset(&stats, 0, sizeof stats);
2329 : 0 : result = revalidate_ukey(udpif, ukey, &stats, &odp_actions,
2330 : : reval_seq, &recircs);
2331 : : }
2332 [ + + ]: 168422 : if (result != UKEY_KEEP) {
2333 : : /* Clears 'recircs' if filled by revalidate_ukey(). */
2334 : 168422 : reval_op_init(&ops[n_ops++], result, udpif, ukey, &recircs,
2335 : : &odp_actions);
2336 : : }
2337 : : }
2338 : 177021 : ovs_mutex_unlock(&ukey->mutex);
2339 : :
2340 [ + + ]: 177021 : if (ukey_state == UKEY_EVICTED) {
2341 : : /* The common flow deletion case involves deletion of the flow
2342 : : * during the dump phase and ukey deletion here. */
2343 : 3284 : ovs_mutex_lock(&umap->mutex);
2344 : 3284 : ukey_delete(umap, ukey);
2345 : 3284 : ovs_mutex_unlock(&umap->mutex);
2346 : : }
2347 : :
2348 [ - + ]: 177021 : if (n_ops == REVALIDATE_MAX_BATCH) {
2349 : : /* Update/delete missed flows and clean up corresponding ukeys
2350 : : * if necessary. */
2351 : 0 : push_ukey_ops(udpif, umap, ops, n_ops);
2352 : 0 : n_ops = 0;
2353 : : }
2354 : : }
2355 : :
2356 [ + + ]: 15610368 : if (n_ops) {
2357 : 2896 : push_ukey_ops(udpif, umap, ops, n_ops);
2358 : : }
2359 : :
2360 : 15610368 : ofpbuf_uninit(&odp_actions);
2361 : 15610368 : ovsrcu_quiesce();
2362 : : }
2363 : 30495 : }
2364 : :
2365 : : static void
2366 : 28167 : revalidator_sweep(struct revalidator *revalidator)
2367 : : {
2368 : 28167 : revalidator_sweep__(revalidator, false);
2369 : 28167 : }
2370 : :
2371 : : static void
2372 : 2328 : revalidator_purge(struct revalidator *revalidator)
2373 : : {
2374 : 2328 : revalidator_sweep__(revalidator, true);
2375 : 2328 : }
2376 : :
2377 : : /* In reaction to dpif purge, purges all 'ukey's with same 'pmd_id'. */
2378 : : static void
2379 : 45 : dp_purge_cb(void *aux, unsigned pmd_id)
2380 : : OVS_NO_THREAD_SAFETY_ANALYSIS
2381 : : {
2382 : 45 : struct udpif *udpif = aux;
2383 : : size_t i;
2384 : :
2385 : 45 : udpif_pause_revalidators(udpif);
2386 [ + + ]: 23085 : for (i = 0; i < N_UMAPS; i++) {
2387 : : struct ukey_op ops[REVALIDATE_MAX_BATCH];
2388 : : struct udpif_key *ukey;
2389 : 23040 : struct umap *umap = &udpif->ukeys[i];
2390 : 23040 : size_t n_ops = 0;
2391 : :
2392 [ + + ][ + + ]: 23050 : CMAP_FOR_EACH(ukey, cmap_node, &umap->cmap) {
2393 [ + + ]: 10 : if (ukey->pmd_id == pmd_id) {
2394 : 6 : delete_op_init(udpif, &ops[n_ops++], ukey);
2395 : 6 : transition_ukey(ukey, UKEY_EVICTING);
2396 : :
2397 [ - + ]: 6 : if (n_ops == REVALIDATE_MAX_BATCH) {
2398 : 0 : push_ukey_ops(udpif, umap, ops, n_ops);
2399 : 0 : n_ops = 0;
2400 : : }
2401 : : }
2402 : : }
2403 : :
2404 [ + + ]: 23040 : if (n_ops) {
2405 : 6 : push_ukey_ops(udpif, umap, ops, n_ops);
2406 : : }
2407 : :
2408 : 23040 : ovsrcu_quiesce();
2409 : : }
2410 : 45 : udpif_resume_revalidators(udpif);
2411 : 45 : }
2412 : :
2413 : : static void
2414 : 0 : upcall_unixctl_show(struct unixctl_conn *conn, int argc OVS_UNUSED,
2415 : : const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED)
2416 : : {
2417 : 0 : struct ds ds = DS_EMPTY_INITIALIZER;
2418 : : struct udpif *udpif;
2419 : :
2420 [ # # ]: 0 : LIST_FOR_EACH (udpif, list_node, &all_udpifs) {
2421 : : unsigned int flow_limit;
2422 : : bool ufid_enabled;
2423 : : size_t i;
2424 : :
2425 : 0 : atomic_read_relaxed(&udpif->flow_limit, &flow_limit);
2426 : 0 : ufid_enabled = udpif_use_ufid(udpif);
2427 : :
2428 : 0 : ds_put_format(&ds, "%s:\n", dpif_name(udpif->dpif));
2429 : 0 : ds_put_format(&ds, "\tflows : (current %lu)"
2430 : : " (avg %u) (max %u) (limit %u)\n", udpif_get_n_flows(udpif),
2431 : : udpif->avg_n_flows, udpif->max_n_flows, flow_limit);
2432 : 0 : ds_put_format(&ds, "\tdump duration : %lldms\n", udpif->dump_duration);
2433 : 0 : ds_put_format(&ds, "\tufid enabled : ");
2434 [ # # ]: 0 : if (ufid_enabled) {
2435 : 0 : ds_put_format(&ds, "true\n");
2436 : : } else {
2437 : 0 : ds_put_format(&ds, "false\n");
2438 : : }
2439 : 0 : ds_put_char(&ds, '\n');
2440 : :
2441 [ # # ]: 0 : for (i = 0; i < n_revalidators; i++) {
2442 : 0 : struct revalidator *revalidator = &udpif->revalidators[i];
2443 : 0 : int j, elements = 0;
2444 : :
2445 [ # # ]: 0 : for (j = i; j < N_UMAPS; j += n_revalidators) {
2446 : 0 : elements += cmap_count(&udpif->ukeys[j].cmap);
2447 : : }
2448 : 0 : ds_put_format(&ds, "\t%u: (keys %d)\n", revalidator->id, elements);
2449 : : }
2450 : : }
2451 : :
2452 : 0 : unixctl_command_reply(conn, ds_cstr(&ds));
2453 : 0 : ds_destroy(&ds);
2454 : 0 : }
2455 : :
2456 : : /* Disable using the megaflows.
2457 : : *
2458 : : * This command is only needed for advanced debugging, so it's not
2459 : : * documented in the man page. */
2460 : : static void
2461 : 8 : upcall_unixctl_disable_megaflows(struct unixctl_conn *conn,
2462 : : int argc OVS_UNUSED,
2463 : : const char *argv[] OVS_UNUSED,
2464 : : void *aux OVS_UNUSED)
2465 : : {
2466 : 8 : atomic_store_relaxed(&enable_megaflows, false);
2467 : 8 : udpif_flush_all_datapaths();
2468 : 8 : unixctl_command_reply(conn, "megaflows disabled");
2469 : 8 : }
2470 : :
2471 : : /* Re-enable using megaflows.
2472 : : *
2473 : : * This command is only needed for advanced debugging, so it's not
2474 : : * documented in the man page. */
2475 : : static void
2476 : 0 : upcall_unixctl_enable_megaflows(struct unixctl_conn *conn,
2477 : : int argc OVS_UNUSED,
2478 : : const char *argv[] OVS_UNUSED,
2479 : : void *aux OVS_UNUSED)
2480 : : {
2481 : 0 : atomic_store_relaxed(&enable_megaflows, true);
2482 : 0 : udpif_flush_all_datapaths();
2483 : 0 : unixctl_command_reply(conn, "megaflows enabled");
2484 : 0 : }
2485 : :
2486 : : /* Disable skipping flow attributes during flow dump.
2487 : : *
2488 : : * This command is only needed for advanced debugging, so it's not
2489 : : * documented in the man page. */
2490 : : static void
2491 : 8 : upcall_unixctl_disable_ufid(struct unixctl_conn *conn, int argc OVS_UNUSED,
2492 : : const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED)
2493 : : {
2494 : 8 : atomic_store_relaxed(&enable_ufid, false);
2495 : 8 : unixctl_command_reply(conn, "Datapath dumping tersely using UFID disabled");
2496 : 8 : }
2497 : :
2498 : : /* Re-enable skipping flow attributes during flow dump.
2499 : : *
2500 : : * This command is only needed for advanced debugging, so it's not documented
2501 : : * in the man page. */
2502 : : static void
2503 : 0 : upcall_unixctl_enable_ufid(struct unixctl_conn *conn, int argc OVS_UNUSED,
2504 : : const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED)
2505 : : {
2506 : 0 : atomic_store_relaxed(&enable_ufid, true);
2507 : 0 : unixctl_command_reply(conn, "Datapath dumping tersely using UFID enabled "
2508 : : "for supported datapaths");
2509 : 0 : }
2510 : :
2511 : : /* Set the flow limit.
2512 : : *
2513 : : * This command is only needed for advanced debugging, so it's not
2514 : : * documented in the man page. */
2515 : : static void
2516 : 0 : upcall_unixctl_set_flow_limit(struct unixctl_conn *conn,
2517 : : int argc OVS_UNUSED,
2518 : : const char *argv[] OVS_UNUSED,
2519 : : void *aux OVS_UNUSED)
2520 : : {
2521 : 0 : struct ds ds = DS_EMPTY_INITIALIZER;
2522 : : struct udpif *udpif;
2523 : 0 : unsigned int flow_limit = atoi(argv[1]);
2524 : :
2525 [ # # ]: 0 : LIST_FOR_EACH (udpif, list_node, &all_udpifs) {
2526 : 0 : atomic_store_relaxed(&udpif->flow_limit, flow_limit);
2527 : : }
2528 : 0 : ds_put_format(&ds, "set flow_limit to %u\n", flow_limit);
2529 : 0 : unixctl_command_reply(conn, ds_cstr(&ds));
2530 : 0 : ds_destroy(&ds);
2531 : 0 : }
2532 : :
2533 : : static void
2534 : 10 : upcall_unixctl_dump_wait(struct unixctl_conn *conn,
2535 : : int argc OVS_UNUSED,
2536 : : const char *argv[] OVS_UNUSED,
2537 : : void *aux OVS_UNUSED)
2538 : : {
2539 [ + - ]: 10 : if (ovs_list_is_singleton(&all_udpifs)) {
2540 : 10 : struct udpif *udpif = NULL;
2541 : : size_t len;
2542 : :
2543 : 10 : udpif = OBJECT_CONTAINING(ovs_list_front(&all_udpifs), udpif, list_node);
2544 : 10 : len = (udpif->n_conns + 1) * sizeof *udpif->conns;
2545 : 10 : udpif->conn_seq = seq_read(udpif->dump_seq);
2546 : 10 : udpif->conns = xrealloc(udpif->conns, len);
2547 : 10 : udpif->conns[udpif->n_conns++] = conn;
2548 : : } else {
2549 : 0 : unixctl_command_reply_error(conn, "can't wait on multiple udpifs.");
2550 : : }
2551 : 10 : }
2552 : :
2553 : : static void
2554 : 59 : upcall_unixctl_purge(struct unixctl_conn *conn, int argc OVS_UNUSED,
2555 : : const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED)
2556 : : {
2557 : : struct udpif *udpif;
2558 : :
2559 [ + + ]: 118 : LIST_FOR_EACH (udpif, list_node, &all_udpifs) {
2560 : : int n;
2561 : :
2562 [ + + ]: 118 : for (n = 0; n < udpif->n_revalidators; n++) {
2563 : 59 : revalidator_purge(&udpif->revalidators[n]);
2564 : : }
2565 : : }
2566 : 59 : unixctl_command_reply(conn, "");
2567 : 59 : }
|