Branch data Line data Source code
1 : : /*
2 : : * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Nicira, Inc.
3 : : *
4 : : * Licensed under the Apache License, Version 2.0 (the "License");
5 : : * you may not use this file except in compliance with the License.
6 : : * You may obtain a copy of the License at:
7 : : *
8 : : * http://www.apache.org/licenses/LICENSE-2.0
9 : : *
10 : : * Unless required by applicable law or agreed to in writing, software
11 : : * distributed under the License is distributed on an "AS IS" BASIS,
12 : : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 : : * See the License for the specific language governing permissions and
14 : : * limitations under the License.
15 : : */
16 : :
17 : : #include <config.h>
18 : : #include <errno.h>
19 : :
20 : : #include "bfd.h"
21 : : #include "bond.h"
22 : : #include "bundle.h"
23 : : #include "byte-order.h"
24 : : #include "connectivity.h"
25 : : #include "connmgr.h"
26 : : #include "coverage.h"
27 : : #include "cfm.h"
28 : : #include "dpif.h"
29 : : #include "fail-open.h"
30 : : #include "guarded-list.h"
31 : : #include "hmapx.h"
32 : : #include "lacp.h"
33 : : #include "learn.h"
34 : : #include "mac-learning.h"
35 : : #include "mcast-snooping.h"
36 : : #include "multipath.h"
37 : : #include "netdev-vport.h"
38 : : #include "netdev.h"
39 : : #include "netlink.h"
40 : : #include "nx-match.h"
41 : : #include "odp-util.h"
42 : : #include "odp-execute.h"
43 : : #include "ofproto/ofproto-dpif.h"
44 : : #include "ofproto/ofproto-provider.h"
45 : : #include "ofproto-dpif-ipfix.h"
46 : : #include "ofproto-dpif-mirror.h"
47 : : #include "ofproto-dpif-monitor.h"
48 : : #include "ofproto-dpif-rid.h"
49 : : #include "ofproto-dpif-sflow.h"
50 : : #include "ofproto-dpif-upcall.h"
51 : : #include "ofproto-dpif-xlate.h"
52 : : #include "openvswitch/ofp-actions.h"
53 : : #include "openvswitch/dynamic-string.h"
54 : : #include "openvswitch/meta-flow.h"
55 : : #include "openvswitch/ofp-parse.h"
56 : : #include "openvswitch/ofp-print.h"
57 : : #include "openvswitch/ofp-util.h"
58 : : #include "openvswitch/ofpbuf.h"
59 : : #include "openvswitch/vlog.h"
60 : : #include "ovs-lldp.h"
61 : : #include "ovs-rcu.h"
62 : : #include "ovs-router.h"
63 : : #include "poll-loop.h"
64 : : #include "seq.h"
65 : : #include "simap.h"
66 : : #include "smap.h"
67 : : #include "timer.h"
68 : : #include "tunnel.h"
69 : : #include "unaligned.h"
70 : : #include "unixctl.h"
71 : : #include "util.h"
72 : : #include "vlan-bitmap.h"
73 : :
74 : 1288 : VLOG_DEFINE_THIS_MODULE(ofproto_dpif);
75 : :
76 : 71698 : COVERAGE_DEFINE(ofproto_dpif_expired);
77 : 71668 : COVERAGE_DEFINE(packet_in_overflow);
78 : :
79 : : struct flow_miss;
80 : :
81 : : struct rule_dpif {
82 : : struct rule up;
83 : :
84 : : /* These statistics:
85 : : *
86 : : * - Do include packets and bytes from datapath flows which have not
87 : : * recently been processed by a revalidator. */
88 : : struct ovs_mutex stats_mutex;
89 : : struct dpif_flow_stats stats OVS_GUARDED;
90 : :
91 : : /* In non-NULL, will point to a new rule (for which a reference is held) to
92 : : * which all the stats updates should be forwarded. This exists only
93 : : * transitionally when flows are replaced.
94 : : *
95 : : * Protected by stats_mutex. If both 'rule->stats_mutex' and
96 : : * 'rule->new_rule->stats_mutex' must be held together, acquire them in that
97 : : * order, */
98 : : struct rule_dpif *new_rule OVS_GUARDED;
99 : : bool forward_counts OVS_GUARDED; /* Forward counts? 'used' time will be
100 : : * forwarded in all cases. */
101 : :
102 : : /* If non-zero then the recirculation id that has
103 : : * been allocated for use with this rule.
104 : : * The recirculation id and associated internal flow should
105 : : * be freed when the rule is freed */
106 : : uint32_t recirc_id;
107 : : };
108 : :
109 : : /* RULE_CAST() depends on this. */
110 : : BUILD_ASSERT_DECL(offsetof(struct rule_dpif, up) == 0);
111 : :
112 : : static void rule_get_stats(struct rule *, uint64_t *packets, uint64_t *bytes,
113 : : long long int *used);
114 : : static struct rule_dpif *rule_dpif_cast(const struct rule *);
115 : : static void rule_expire(struct rule_dpif *, long long now);
116 : :
117 : : struct group_dpif {
118 : : struct ofgroup up;
119 : :
120 : : /* These statistics:
121 : : *
122 : : * - Do include packets and bytes from datapath flows which have not
123 : : * recently been processed by a revalidator. */
124 : : struct ovs_mutex stats_mutex;
125 : : uint64_t packet_count OVS_GUARDED; /* Number of packets received. */
126 : : uint64_t byte_count OVS_GUARDED; /* Number of bytes received. */
127 : : };
128 : :
129 : : struct ofbundle {
130 : : struct hmap_node hmap_node; /* In struct ofproto's "bundles" hmap. */
131 : : struct ofproto_dpif *ofproto; /* Owning ofproto. */
132 : : void *aux; /* Key supplied by ofproto's client. */
133 : : char *name; /* Identifier for log messages. */
134 : :
135 : : /* Configuration. */
136 : : struct ovs_list ports; /* Contains "struct ofport"s. */
137 : : enum port_vlan_mode vlan_mode; /* VLAN mode */
138 : : int vlan; /* -1=trunk port, else a 12-bit VLAN ID. */
139 : : unsigned long *trunks; /* Bitmap of trunked VLANs, if 'vlan' == -1.
140 : : * NULL if all VLANs are trunked. */
141 : : struct lacp *lacp; /* LACP if LACP is enabled, otherwise NULL. */
142 : : struct bond *bond; /* Nonnull iff more than one port. */
143 : : bool use_priority_tags; /* Use 802.1p tag for frames in VLAN 0? */
144 : :
145 : : /* Status. */
146 : : bool floodable; /* True if no port has OFPUTIL_PC_NO_FLOOD set. */
147 : : };
148 : :
149 : : static void bundle_remove(struct ofport *);
150 : : static void bundle_update(struct ofbundle *);
151 : : static void bundle_destroy(struct ofbundle *);
152 : : static void bundle_del_port(struct ofport_dpif *);
153 : : static void bundle_run(struct ofbundle *);
154 : : static void bundle_wait(struct ofbundle *);
155 : : static void bundle_flush_macs(struct ofbundle *, bool);
156 : : static void bundle_move(struct ofbundle *, struct ofbundle *);
157 : :
158 : : static void stp_run(struct ofproto_dpif *ofproto);
159 : : static void stp_wait(struct ofproto_dpif *ofproto);
160 : : static int set_stp_port(struct ofport *,
161 : : const struct ofproto_port_stp_settings *);
162 : :
163 : : static void rstp_run(struct ofproto_dpif *ofproto);
164 : : static void set_rstp_port(struct ofport *,
165 : : const struct ofproto_port_rstp_settings *);
166 : :
167 : : struct ofport_dpif {
168 : : struct hmap_node odp_port_node; /* In dpif_backer's "odp_to_ofport_map". */
169 : : struct ofport up;
170 : :
171 : : odp_port_t odp_port;
172 : : struct ofbundle *bundle; /* Bundle that contains this port, if any. */
173 : : struct ovs_list bundle_node;/* In struct ofbundle's "ports" list. */
174 : : struct cfm *cfm; /* Connectivity Fault Management, if any. */
175 : : struct bfd *bfd; /* BFD, if any. */
176 : : struct lldp *lldp; /* lldp, if any. */
177 : : bool may_enable; /* May be enabled in bonds. */
178 : : bool is_tunnel; /* This port is a tunnel. */
179 : : bool is_layer3; /* This is a layer 3 port. */
180 : : long long int carrier_seq; /* Carrier status changes. */
181 : : struct ofport_dpif *peer; /* Peer if patch port. */
182 : :
183 : : /* Spanning tree. */
184 : : struct stp_port *stp_port; /* Spanning Tree Protocol, if any. */
185 : : enum stp_state stp_state; /* Always STP_DISABLED if STP not in use. */
186 : : long long int stp_state_entered;
187 : :
188 : : /* Rapid Spanning Tree. */
189 : : struct rstp_port *rstp_port; /* Rapid Spanning Tree Protocol, if any. */
190 : : enum rstp_state rstp_state; /* Always RSTP_DISABLED if RSTP not in use. */
191 : :
192 : : /* Queue to DSCP mapping. */
193 : : struct ofproto_port_queue *qdscp;
194 : : size_t n_qdscp;
195 : : };
196 : :
197 : : static odp_port_t ofp_port_to_odp_port(const struct ofproto_dpif *,
198 : : ofp_port_t);
199 : :
200 : : static ofp_port_t odp_port_to_ofp_port(const struct ofproto_dpif *,
201 : : odp_port_t);
202 : :
203 : : static struct ofport_dpif *
204 : 563780 : ofport_dpif_cast(const struct ofport *ofport)
205 : : {
206 [ + - ]: 563780 : return ofport ? CONTAINER_OF(ofport, struct ofport_dpif, up) : NULL;
207 : : }
208 : :
209 : : static void port_run(struct ofport_dpif *);
210 : : static int set_bfd(struct ofport *, const struct smap *);
211 : : static int set_cfm(struct ofport *, const struct cfm_settings *);
212 : : static int set_lldp(struct ofport *ofport_, const struct smap *cfg);
213 : : static void ofport_update_peer(struct ofport_dpif *);
214 : :
215 : : /* Reasons that we might need to revalidate every datapath flow, and
216 : : * corresponding coverage counters.
217 : : *
218 : : * A value of 0 means that there is no need to revalidate.
219 : : *
220 : : * It would be nice to have some cleaner way to integrate with coverage
221 : : * counters, but with only a few reasons I guess this is good enough for
222 : : * now. */
223 : : enum revalidate_reason {
224 : : REV_RECONFIGURE = 1, /* Switch configuration changed. */
225 : : REV_STP, /* Spanning tree protocol port status change. */
226 : : REV_RSTP, /* RSTP port status change. */
227 : : REV_BOND, /* Bonding changed. */
228 : : REV_PORT_TOGGLED, /* Port enabled or disabled by CFM, LACP, ...*/
229 : : REV_FLOW_TABLE, /* Flow table changed. */
230 : : REV_MAC_LEARNING, /* Mac learning changed. */
231 : : REV_MCAST_SNOOPING, /* Multicast snooping changed. */
232 : : };
233 : 97552 : COVERAGE_DEFINE(rev_reconfigure);
234 : 71686 : COVERAGE_DEFINE(rev_stp);
235 : 71686 : COVERAGE_DEFINE(rev_rstp);
236 : 71860 : COVERAGE_DEFINE(rev_bond);
237 : 74356 : COVERAGE_DEFINE(rev_port_toggled);
238 : 149098 : COVERAGE_DEFINE(rev_flow_table);
239 : 74902 : COVERAGE_DEFINE(rev_mac_learning);
240 : 71668 : COVERAGE_DEFINE(rev_mcast_snooping);
241 : :
242 : : /* All datapaths of a given type share a single dpif backer instance. */
243 : : struct dpif_backer {
244 : : char *type;
245 : : int refcount;
246 : : struct dpif *dpif;
247 : : struct udpif *udpif;
248 : :
249 : : struct ovs_rwlock odp_to_ofport_lock;
250 : : struct hmap odp_to_ofport_map OVS_GUARDED; /* Contains "struct ofport"s. */
251 : :
252 : : struct simap tnl_backers; /* Set of dpif ports backing tunnels. */
253 : :
254 : : enum revalidate_reason need_revalidate; /* Revalidate all flows. */
255 : :
256 : : bool recv_set_enable; /* Enables or disables receiving packets. */
257 : :
258 : : /* Version string of the datapath stored in OVSDB. */
259 : : char *dp_version_string;
260 : :
261 : : /* Datapath feature support. */
262 : : struct dpif_backer_support support;
263 : : struct atomic_count tnl_count;
264 : : };
265 : :
266 : : /* All existing ofproto_backer instances, indexed by ofproto->up.type. */
267 : : static struct shash all_dpif_backers = SHASH_INITIALIZER(&all_dpif_backers);
268 : :
269 : : struct ofproto_dpif {
270 : : struct hmap_node all_ofproto_dpifs_node; /* In 'all_ofproto_dpifs'. */
271 : : struct ofproto up;
272 : : struct dpif_backer *backer;
273 : :
274 : : /* Unique identifier for this instantiation of this bridge in this running
275 : : * process. */
276 : : struct uuid uuid;
277 : :
278 : : ATOMIC(ovs_version_t) tables_version; /* For classifier lookups. */
279 : :
280 : : uint64_t dump_seq; /* Last read of udpif_dump_seq(). */
281 : :
282 : : /* Special OpenFlow rules. */
283 : : struct rule_dpif *miss_rule; /* Sends flow table misses to controller. */
284 : : struct rule_dpif *no_packet_in_rule; /* Drops flow table misses. */
285 : : struct rule_dpif *drop_frags_rule; /* Used in OFPUTIL_FRAG_DROP mode. */
286 : :
287 : : /* Bridging. */
288 : : struct netflow *netflow;
289 : : struct dpif_sflow *sflow;
290 : : struct dpif_ipfix *ipfix;
291 : : struct hmap bundles; /* Contains "struct ofbundle"s. */
292 : : struct mac_learning *ml;
293 : : struct mcast_snooping *ms;
294 : : bool has_bonded_bundles;
295 : : bool lacp_enabled;
296 : : struct mbridge *mbridge;
297 : :
298 : : struct ovs_mutex stats_mutex;
299 : : struct netdev_stats stats OVS_GUARDED; /* To account packets generated and
300 : : * consumed in userspace. */
301 : :
302 : : /* Spanning tree. */
303 : : struct stp *stp;
304 : : long long int stp_last_tick;
305 : :
306 : : /* Rapid Spanning Tree. */
307 : : struct rstp *rstp;
308 : : long long int rstp_last_tick;
309 : :
310 : : /* Ports. */
311 : : struct sset ports; /* Set of standard port names. */
312 : : struct sset ghost_ports; /* Ports with no datapath port. */
313 : : struct sset port_poll_set; /* Queued names for port_poll() reply. */
314 : : int port_poll_errno; /* Last errno for port_poll() reply. */
315 : : uint64_t change_seq; /* Connectivity status changes. */
316 : :
317 : : /* Work queues. */
318 : : struct guarded_list ams; /* Contains "struct ofproto_async_msgs"s. */
319 : : struct seq *ams_seq; /* For notifying 'ams' reception. */
320 : : uint64_t ams_seqno;
321 : : };
322 : :
323 : : /* All existing ofproto_dpif instances, indexed by ->up.name. */
324 : : static struct hmap all_ofproto_dpifs = HMAP_INITIALIZER(&all_ofproto_dpifs);
325 : :
326 : : static bool ofproto_use_tnl_push_pop = true;
327 : : static void ofproto_unixctl_init(void);
328 : :
329 : : static inline struct ofproto_dpif *
330 : 1204441 : ofproto_dpif_cast(const struct ofproto *ofproto)
331 : : {
332 [ - + ]: 1204441 : ovs_assert(ofproto->ofproto_class == &ofproto_dpif_class);
333 : 1204441 : return CONTAINER_OF(ofproto, struct ofproto_dpif, up);
334 : : }
335 : :
336 : : bool
337 : 37059 : ofproto_dpif_get_enable_ufid(const struct dpif_backer *backer)
338 : : {
339 : 37059 : return backer->support.ufid;
340 : : }
341 : :
342 : : struct dpif_backer_support *
343 : 41074 : ofproto_dpif_get_support(const struct ofproto_dpif *ofproto)
344 : : {
345 : 41074 : return &ofproto->backer->support;
346 : : }
347 : :
348 : : static void ofproto_trace(struct ofproto_dpif *, struct flow *,
349 : : const struct dp_packet *packet,
350 : : const struct ofpact[], size_t ofpacts_len,
351 : : struct ds *);
352 : :
353 : : /* Global variables. */
354 : : static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
355 : :
356 : : /* Initial mappings of port to bridge mappings. */
357 : : static struct shash init_ofp_ports = SHASH_INITIALIZER(&init_ofp_ports);
358 : :
359 : : /* Executes 'fm'. The caller retains ownership of 'fm' and everything in
360 : : * it. */
361 : : void
362 : 51 : ofproto_dpif_flow_mod(struct ofproto_dpif *ofproto,
363 : : const struct ofputil_flow_mod *fm)
364 : : {
365 : 51 : ofproto_flow_mod(&ofproto->up, fm);
366 : 51 : }
367 : :
368 : : /* Appends 'am' to the queue of asynchronous messages to be sent to the
369 : : * controller. Takes ownership of 'am' and any data it points to. */
370 : : void
371 : 1051 : ofproto_dpif_send_async_msg(struct ofproto_dpif *ofproto,
372 : : struct ofproto_async_msg *am)
373 : : {
374 [ - + ]: 1051 : if (!guarded_list_push_back(&ofproto->ams, &am->list_node, 1024)) {
375 : 0 : COVERAGE_INC(packet_in_overflow);
376 : 0 : ofproto_async_msg_free(am);
377 : : }
378 : :
379 : : /* Wakes up main thread for packet-in I/O. */
380 : 1051 : seq_change(ofproto->ams_seq);
381 : 1051 : }
382 : :
383 : : /* The default "table-miss" behaviour for OpenFlow1.3+ is to drop the
384 : : * packet rather than to send the packet to the controller.
385 : : *
386 : : * This function returns false to indicate that a packet_in message
387 : : * for a "table-miss" should be sent to at least one controller.
388 : : * False otherwise. */
389 : : bool
390 : 0 : ofproto_dpif_wants_packet_in_on_miss(struct ofproto_dpif *ofproto)
391 : : {
392 : 0 : return connmgr_wants_packet_in_on_miss(ofproto->up.connmgr);
393 : : }
394 : :
395 : : /* Factory functions. */
396 : :
397 : : static void
398 : 615 : init(const struct shash *iface_hints)
399 : : {
400 : : struct shash_node *node;
401 : :
402 : : /* Make a local copy, since we don't own 'iface_hints' elements. */
403 [ + + ][ - + ]: 624 : SHASH_FOR_EACH(node, iface_hints) {
404 : 9 : const struct iface_hint *orig_hint = node->data;
405 : 9 : struct iface_hint *new_hint = xmalloc(sizeof *new_hint);
406 : :
407 : 9 : new_hint->br_name = xstrdup(orig_hint->br_name);
408 : 9 : new_hint->br_type = xstrdup(orig_hint->br_type);
409 : 9 : new_hint->ofp_port = orig_hint->ofp_port;
410 : :
411 : 9 : shash_add(&init_ofp_ports, node->name, new_hint);
412 : : }
413 : :
414 : 615 : ofproto_unixctl_init();
415 : 615 : udpif_init();
416 : 615 : }
417 : :
418 : : static void
419 : 773926 : enumerate_types(struct sset *types)
420 : : {
421 : 773926 : dp_enumerate_types(types);
422 : 773926 : }
423 : :
424 : : static int
425 : 8408 : enumerate_names(const char *type, struct sset *names)
426 : : {
427 : : struct ofproto_dpif *ofproto;
428 : :
429 : 8408 : sset_clear(names);
430 [ + + ][ - + ]: 16634 : HMAP_FOR_EACH (ofproto, all_ofproto_dpifs_node, &all_ofproto_dpifs) {
431 [ + + ]: 8226 : if (strcmp(type, ofproto->up.type)) {
432 : 4275 : continue;
433 : : }
434 : 3951 : sset_add(names, ofproto->up.name);
435 : : }
436 : :
437 : 8408 : return 0;
438 : : }
439 : :
440 : : static int
441 : 0 : del(const char *type, const char *name)
442 : : {
443 : : struct dpif *dpif;
444 : : int error;
445 : :
446 : 0 : error = dpif_open(name, type, &dpif);
447 [ # # ]: 0 : if (!error) {
448 : 0 : error = dpif_delete(dpif);
449 : 0 : dpif_close(dpif);
450 : : }
451 : 0 : return error;
452 : : }
453 : :
454 : : static const char *
455 : 64923 : port_open_type(const char *datapath_type, const char *port_type)
456 : : {
457 : 64923 : return dpif_port_open_type(datapath_type, port_type);
458 : : }
459 : :
460 : : /* Type functions. */
461 : :
462 : : static void process_dpif_port_changes(struct dpif_backer *);
463 : : static void process_dpif_all_ports_changed(struct dpif_backer *);
464 : : static void process_dpif_port_change(struct dpif_backer *,
465 : : const char *devname);
466 : : static void process_dpif_port_error(struct dpif_backer *, int error);
467 : :
468 : : static struct ofproto_dpif *
469 : 5042 : lookup_ofproto_dpif_by_port_name(const char *name)
470 : : {
471 : : struct ofproto_dpif *ofproto;
472 : :
473 [ + + ][ - + ]: 8482 : HMAP_FOR_EACH (ofproto, all_ofproto_dpifs_node, &all_ofproto_dpifs) {
474 [ + + ]: 7290 : if (sset_contains(&ofproto->ports, name)) {
475 : 3850 : return ofproto;
476 : : }
477 : : }
478 : :
479 : 1192 : return NULL;
480 : : }
481 : :
482 : : bool
483 : 90 : ofproto_dpif_backer_enabled(struct dpif_backer* backer)
484 : : {
485 : 90 : return backer->recv_set_enable;
486 : : }
487 : :
488 : : static int
489 : 245845 : type_run(const char *type)
490 : : {
491 : : struct dpif_backer *backer;
492 : :
493 : 245845 : backer = shash_find_data(&all_dpif_backers, type);
494 [ + + ]: 245845 : if (!backer) {
495 : : /* This is not necessarily a problem, since backers are only
496 : : * created on demand. */
497 : 140146 : return 0;
498 : : }
499 : :
500 : : /* This must be called before dpif_run() */
501 : 105699 : dpif_poll_threads_set(backer->dpif, pmd_cpu_mask);
502 : :
503 [ + + ]: 105699 : if (dpif_run(backer->dpif)) {
504 : 715 : backer->need_revalidate = REV_RECONFIGURE;
505 : : }
506 : :
507 : 105699 : udpif_run(backer->udpif);
508 : :
509 : : /* If vswitchd started with other_config:flow_restore_wait set as "true",
510 : : * and the configuration has now changed to "false", enable receiving
511 : : * packets from the datapath. */
512 [ + + ][ + + ]: 105699 : if (!backer->recv_set_enable && !ofproto_get_flow_restore_wait()) {
513 : : int error;
514 : :
515 : 1 : backer->recv_set_enable = true;
516 : :
517 : 1 : error = dpif_recv_set(backer->dpif, backer->recv_set_enable);
518 [ - + ]: 1 : if (error) {
519 [ # # ]: 0 : VLOG_ERR("Failed to enable receiving packets in dpif.");
520 : 0 : return error;
521 : : }
522 : 1 : dpif_flow_flush(backer->dpif);
523 : 1 : backer->need_revalidate = REV_RECONFIGURE;
524 : : }
525 : :
526 [ + + ]: 105699 : if (backer->recv_set_enable) {
527 : 105660 : udpif_set_threads(backer->udpif, n_handlers, n_revalidators);
528 : : }
529 : :
530 [ + + ]: 105699 : if (backer->need_revalidate) {
531 : : struct ofproto_dpif *ofproto;
532 : : struct simap_node *node;
533 : : struct simap tmp_backers;
534 : :
535 : : /* Handle tunnel garbage collection. */
536 : 18244 : simap_init(&tmp_backers);
537 : 18244 : simap_swap(&backer->tnl_backers, &tmp_backers);
538 : :
539 [ + + ][ - + ]: 41303 : HMAP_FOR_EACH (ofproto, all_ofproto_dpifs_node, &all_ofproto_dpifs) {
540 : : struct ofport_dpif *iter;
541 : :
542 [ - + ]: 23059 : if (backer != ofproto->backer) {
543 : 0 : continue;
544 : : }
545 : :
546 [ + + ][ - + ]: 123368 : HMAP_FOR_EACH (iter, up.hmap_node, &ofproto->up.ports) {
547 : : char namebuf[NETDEV_VPORT_NAME_BUFSIZE];
548 : : const char *dp_port;
549 : :
550 [ + + ]: 100309 : if (!iter->is_tunnel) {
551 : 76324 : continue;
552 : : }
553 : :
554 : 23985 : dp_port = netdev_vport_get_dpif_port(iter->up.netdev,
555 : : namebuf, sizeof namebuf);
556 : 23985 : node = simap_find(&tmp_backers, dp_port);
557 [ + + ]: 23985 : if (node) {
558 : 2741 : simap_put(&backer->tnl_backers, dp_port, node->data);
559 : 2741 : simap_delete(&tmp_backers, node);
560 : 2741 : node = simap_find(&backer->tnl_backers, dp_port);
561 : : } else {
562 : 21244 : node = simap_find(&backer->tnl_backers, dp_port);
563 [ + + ]: 21244 : if (!node) {
564 : 2 : odp_port_t odp_port = ODPP_NONE;
565 : :
566 [ + - ]: 2 : if (!dpif_port_add(backer->dpif, iter->up.netdev,
567 : : &odp_port)) {
568 : 2 : simap_put(&backer->tnl_backers, dp_port,
569 : : odp_to_u32(odp_port));
570 : 2 : node = simap_find(&backer->tnl_backers, dp_port);
571 : : }
572 : : }
573 : : }
574 : :
575 [ + - ]: 23985 : iter->odp_port = node ? u32_to_odp(node->data) : ODPP_NONE;
576 [ + + ]: 23985 : if (tnl_port_reconfigure(iter, iter->up.netdev,
577 : : iter->odp_port,
578 : 23985 : ovs_native_tunneling_is_on(ofproto), dp_port)) {
579 : 23985 : backer->need_revalidate = REV_RECONFIGURE;
580 : : }
581 : : }
582 : : }
583 : :
584 [ + + ][ - + ]: 18277 : SIMAP_FOR_EACH (node, &tmp_backers) {
585 : 33 : dpif_port_del(backer->dpif, u32_to_odp(node->data));
586 : : }
587 : 18244 : simap_destroy(&tmp_backers);
588 : :
589 [ + + + + : 18244 : switch (backer->need_revalidate) {
+ + + -
- ]
590 : 4314 : case REV_RECONFIGURE: COVERAGE_INC(rev_reconfigure); break;
591 : 3 : case REV_STP: COVERAGE_INC(rev_stp); break;
592 : 3 : case REV_RSTP: COVERAGE_INC(rev_rstp); break;
593 : 32 : case REV_BOND: COVERAGE_INC(rev_bond); break;
594 : 448 : case REV_PORT_TOGGLED: COVERAGE_INC(rev_port_toggled); break;
595 : 12905 : case REV_FLOW_TABLE: COVERAGE_INC(rev_flow_table); break;
596 : 539 : case REV_MAC_LEARNING: COVERAGE_INC(rev_mac_learning); break;
597 : 0 : case REV_MCAST_SNOOPING: COVERAGE_INC(rev_mcast_snooping); break;
598 : : }
599 : 18244 : backer->need_revalidate = 0;
600 : :
601 [ + + ][ - + ]: 41303 : HMAP_FOR_EACH (ofproto, all_ofproto_dpifs_node, &all_ofproto_dpifs) {
602 : : struct ofport_dpif *ofport;
603 : : struct ofbundle *bundle;
604 : :
605 [ - + ]: 23059 : if (ofproto->backer != backer) {
606 : 0 : continue;
607 : : }
608 : :
609 : 23059 : xlate_txn_start();
610 : 23059 : xlate_ofproto_set(ofproto, ofproto->up.name,
611 : 23059 : ofproto->backer->dpif, ofproto->ml,
612 : 23059 : ofproto->stp, ofproto->rstp, ofproto->ms,
613 : 23059 : ofproto->mbridge, ofproto->sflow, ofproto->ipfix,
614 : 23059 : ofproto->netflow,
615 : 23059 : ofproto->up.forward_bpdu,
616 : 23059 : connmgr_has_in_band(ofproto->up.connmgr),
617 : 23059 : &ofproto->backer->support);
618 : :
619 [ + + ][ - + ]: 122721 : HMAP_FOR_EACH (bundle, hmap_node, &ofproto->bundles) {
620 : 99662 : xlate_bundle_set(ofproto, bundle, bundle->name,
621 : : bundle->vlan_mode, bundle->vlan,
622 : 99662 : bundle->trunks, bundle->use_priority_tags,
623 : 99662 : bundle->bond, bundle->lacp,
624 : 99662 : bundle->floodable);
625 : : }
626 : :
627 [ + + ][ - + ]: 123368 : HMAP_FOR_EACH (ofport, up.hmap_node, &ofproto->up.ports) {
628 : 200618 : int stp_port = ofport->stp_port
629 : 18 : ? stp_port_no(ofport->stp_port)
630 [ + + ]: 100309 : : -1;
631 : 100309 : xlate_ofport_set(ofproto, ofport->bundle, ofport,
632 : : ofport->up.ofp_port, ofport->odp_port,
633 : 100309 : ofport->up.netdev, ofport->cfm, ofport->bfd,
634 : 100309 : ofport->lldp, ofport->peer, stp_port,
635 : 100309 : ofport->rstp_port, ofport->qdscp,
636 : : ofport->n_qdscp, ofport->up.pp.config,
637 : 100309 : ofport->up.pp.state, ofport->is_tunnel,
638 : 100309 : ofport->may_enable);
639 : : }
640 : 23059 : xlate_txn_commit();
641 : : }
642 : :
643 : 18244 : udpif_revalidate(backer->udpif);
644 : : }
645 : :
646 : 105699 : process_dpif_port_changes(backer);
647 : :
648 : 105699 : return 0;
649 : : }
650 : :
651 : : /* Check for and handle port changes in 'backer''s dpif. */
652 : : static void
653 : 105699 : process_dpif_port_changes(struct dpif_backer *backer)
654 : : {
655 : : for (;;) {
656 : : char *devname;
657 : : int error;
658 : :
659 : 107252 : error = dpif_port_poll(backer->dpif, &devname);
660 [ + + + - ]: 107252 : switch (error) {
661 : : case EAGAIN:
662 : 105699 : return;
663 : :
664 : : case ENOBUFS:
665 : 1385 : process_dpif_all_ports_changed(backer);
666 : 1385 : break;
667 : :
668 : : case 0:
669 : 168 : process_dpif_port_change(backer, devname);
670 : 168 : free(devname);
671 : 168 : break;
672 : :
673 : : default:
674 : 0 : process_dpif_port_error(backer, error);
675 : 0 : break;
676 : : }
677 : 1553 : }
678 : : }
679 : :
680 : : static void
681 : 1385 : process_dpif_all_ports_changed(struct dpif_backer *backer)
682 : : {
683 : : struct ofproto_dpif *ofproto;
684 : : struct dpif_port dpif_port;
685 : : struct dpif_port_dump dump;
686 : : struct sset devnames;
687 : : const char *devname;
688 : :
689 : 1385 : sset_init(&devnames);
690 [ + + ][ - + ]: 3180 : HMAP_FOR_EACH (ofproto, all_ofproto_dpifs_node, &all_ofproto_dpifs) {
691 [ + - ]: 1795 : if (ofproto->backer == backer) {
692 : : struct ofport *ofport;
693 : :
694 [ + + ][ - + ]: 6674 : HMAP_FOR_EACH (ofport, hmap_node, &ofproto->up.ports) {
695 : 4879 : sset_add(&devnames, netdev_get_name(ofport->netdev));
696 : : }
697 : : }
698 : : }
699 [ + + ][ + + ]: 6604 : DPIF_PORT_FOR_EACH (&dpif_port, &dump, backer->dpif) {
700 : 5219 : sset_add(&devnames, dpif_port.name);
701 : : }
702 : :
703 [ + - ][ + + ]: 7797 : SSET_FOR_EACH (devname, &devnames) {
[ + + ]
704 : 6412 : process_dpif_port_change(backer, devname);
705 : : }
706 : 1385 : sset_destroy(&devnames);
707 : 1385 : }
708 : :
709 : : static void
710 : 6580 : process_dpif_port_change(struct dpif_backer *backer, const char *devname)
711 : : {
712 : : struct ofproto_dpif *ofproto;
713 : : struct dpif_port port;
714 : :
715 : : /* Don't report on the datapath's device. */
716 [ + + ]: 6580 : if (!strcmp(devname, dpif_base_name(backer->dpif))) {
717 : 1538 : return;
718 : : }
719 : :
720 [ + + ][ - + ]: 13442 : HMAP_FOR_EACH (ofproto, all_ofproto_dpifs_node,
721 : : &all_ofproto_dpifs) {
722 [ + + ]: 8400 : if (simap_contains(&ofproto->backer->tnl_backers, devname)) {
723 : 153 : return;
724 : : }
725 : : }
726 : :
727 : 5042 : ofproto = lookup_ofproto_dpif_by_port_name(devname);
728 [ + + ]: 5042 : if (dpif_port_query_by_name(backer->dpif, devname, &port)) {
729 : : /* The port was removed. If we know the datapath,
730 : : * report it through poll_set(). If we don't, it may be
731 : : * notifying us of a removal we initiated, so ignore it.
732 : : * If there's a pending ENOBUFS, let it stand, since
733 : : * everything will be reevaluated. */
734 [ + + ][ + - ]: 1193 : if (ofproto && ofproto->port_poll_errno != ENOBUFS) {
735 : 1 : sset_add(&ofproto->port_poll_set, devname);
736 : 1193 : ofproto->port_poll_errno = 0;
737 : : }
738 [ - + ]: 3849 : } else if (!ofproto) {
739 : : /* The port was added, but we don't know with which
740 : : * ofproto we should associate it. Delete it. */
741 : 0 : dpif_port_del(backer->dpif, port.port_no);
742 : : } else {
743 : : struct ofport_dpif *ofport;
744 : :
745 : 3849 : ofport = ofport_dpif_cast(shash_find_data(
746 : 3849 : &ofproto->up.port_by_name, devname));
747 [ + - ]: 3849 : if (ofport
748 [ + + ]: 3849 : && ofport->odp_port != port.port_no
749 [ + - ]: 1 : && !odp_port_to_ofport(backer, port.port_no))
750 : : {
751 : : /* 'ofport''s datapath port number has changed from
752 : : * 'ofport->odp_port' to 'port.port_no'. Update our internal data
753 : : * structures to match. */
754 : 1 : ovs_rwlock_wrlock(&backer->odp_to_ofport_lock);
755 : 1 : hmap_remove(&backer->odp_to_ofport_map, &ofport->odp_port_node);
756 : 1 : ofport->odp_port = port.port_no;
757 : 1 : hmap_insert(&backer->odp_to_ofport_map, &ofport->odp_port_node,
758 : : hash_odp_port(port.port_no));
759 : 1 : ovs_rwlock_unlock(&backer->odp_to_ofport_lock);
760 : 1 : backer->need_revalidate = REV_RECONFIGURE;
761 : : }
762 : : }
763 : 5042 : dpif_port_destroy(&port);
764 : : }
765 : :
766 : : /* Propagate 'error' to all ofprotos based on 'backer'. */
767 : : static void
768 : 0 : process_dpif_port_error(struct dpif_backer *backer, int error)
769 : : {
770 : : struct ofproto_dpif *ofproto;
771 : :
772 [ # # ][ # # ]: 0 : HMAP_FOR_EACH (ofproto, all_ofproto_dpifs_node, &all_ofproto_dpifs) {
773 [ # # ]: 0 : if (ofproto->backer == backer) {
774 : 0 : sset_clear(&ofproto->port_poll_set);
775 : 0 : ofproto->port_poll_errno = error;
776 : : }
777 : : }
778 : 0 : }
779 : :
780 : : static void
781 : 237444 : type_wait(const char *type)
782 : : {
783 : : struct dpif_backer *backer;
784 : :
785 : 237444 : backer = shash_find_data(&all_dpif_backers, type);
786 [ + + ]: 237444 : if (!backer) {
787 : : /* This is not necessarily a problem, since backers are only
788 : : * created on demand. */
789 : 134755 : return;
790 : : }
791 : :
792 : 102689 : dpif_wait(backer->dpif);
793 : : }
794 : :
795 : : /* Basic life-cycle. */
796 : :
797 : : static int add_internal_flows(struct ofproto_dpif *);
798 : :
799 : : static struct ofproto *
800 : 749 : alloc(void)
801 : : {
802 : 749 : struct ofproto_dpif *ofproto = xzalloc(sizeof *ofproto);
803 : 749 : return &ofproto->up;
804 : : }
805 : :
806 : : static void
807 : 123 : dealloc(struct ofproto *ofproto_)
808 : : {
809 : 123 : struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
810 : 123 : free(ofproto);
811 : 123 : }
812 : :
813 : : static void
814 : 749 : close_dpif_backer(struct dpif_backer *backer)
815 : : {
816 [ - + ]: 749 : ovs_assert(backer->refcount > 0);
817 : :
818 [ + + ]: 749 : if (--backer->refcount) {
819 : 135 : return;
820 : : }
821 : :
822 : 614 : udpif_destroy(backer->udpif);
823 : :
824 : 614 : simap_destroy(&backer->tnl_backers);
825 : 614 : ovs_rwlock_destroy(&backer->odp_to_ofport_lock);
826 : 614 : hmap_destroy(&backer->odp_to_ofport_map);
827 : 614 : shash_find_and_delete(&all_dpif_backers, backer->type);
828 : 614 : free(backer->type);
829 : 614 : free(backer->dp_version_string);
830 : 614 : dpif_close(backer->dpif);
831 : 614 : free(backer);
832 : : }
833 : :
834 : : /* Datapath port slated for removal from datapath. */
835 : : struct odp_garbage {
836 : : struct ovs_list list_node;
837 : : odp_port_t odp_port;
838 : : };
839 : :
840 : : static bool check_variable_length_userdata(struct dpif_backer *backer);
841 : : static void check_support(struct dpif_backer *backer);
842 : :
843 : : static int
844 : 749 : open_dpif_backer(const char *type, struct dpif_backer **backerp)
845 : : {
846 : : struct dpif_backer *backer;
847 : : struct dpif_port_dump port_dump;
848 : : struct dpif_port port;
849 : : struct shash_node *node;
850 : : struct ovs_list garbage_list;
851 : : struct odp_garbage *garbage;
852 : :
853 : : struct sset names;
854 : : char *backer_name;
855 : : const char *name;
856 : : int error;
857 : :
858 : 749 : backer = shash_find_data(&all_dpif_backers, type);
859 [ + + ]: 749 : if (backer) {
860 : 135 : backer->refcount++;
861 : 135 : *backerp = backer;
862 : 135 : return 0;
863 : : }
864 : :
865 : 614 : backer_name = xasprintf("ovs-%s", type);
866 : :
867 : : /* Remove any existing datapaths, since we assume we're the only
868 : : * userspace controlling the datapath. */
869 : 614 : sset_init(&names);
870 : 614 : dp_enumerate_names(type, &names);
871 [ - + ][ # # ]: 614 : SSET_FOR_EACH(name, &names) {
[ - + ]
872 : : struct dpif *old_dpif;
873 : :
874 : : /* Don't remove our backer if it exists. */
875 [ # # ]: 0 : if (!strcmp(name, backer_name)) {
876 : 0 : continue;
877 : : }
878 : :
879 [ # # ]: 0 : if (dpif_open(name, type, &old_dpif)) {
880 [ # # ]: 0 : VLOG_WARN("couldn't open old datapath %s to remove it", name);
881 : : } else {
882 : 0 : dpif_delete(old_dpif);
883 : 0 : dpif_close(old_dpif);
884 : : }
885 : : }
886 : 614 : sset_destroy(&names);
887 : :
888 : 614 : backer = xmalloc(sizeof *backer);
889 : :
890 : 614 : error = dpif_create_and_open(backer_name, type, &backer->dpif);
891 : 614 : free(backer_name);
892 [ - + ]: 614 : if (error) {
893 [ # # ]: 0 : VLOG_ERR("failed to open datapath of type %s: %s", type,
894 : : ovs_strerror(error));
895 : 0 : free(backer);
896 : 0 : return error;
897 : : }
898 : 614 : backer->udpif = udpif_create(backer, backer->dpif);
899 : :
900 : 614 : backer->type = xstrdup(type);
901 : 614 : backer->refcount = 1;
902 : 614 : hmap_init(&backer->odp_to_ofport_map);
903 : 614 : ovs_rwlock_init(&backer->odp_to_ofport_lock);
904 : 614 : backer->need_revalidate = 0;
905 : 614 : simap_init(&backer->tnl_backers);
906 : 614 : backer->recv_set_enable = !ofproto_get_flow_restore_wait();
907 : 614 : *backerp = backer;
908 : :
909 [ + + ]: 614 : if (backer->recv_set_enable) {
910 : 613 : dpif_flow_flush(backer->dpif);
911 : : }
912 : :
913 : : /* Loop through the ports already on the datapath and remove any
914 : : * that we don't need anymore. */
915 : 614 : ovs_list_init(&garbage_list);
916 : 614 : dpif_port_dump_start(&port_dump, backer->dpif);
917 [ + + ]: 1228 : while (dpif_port_dump_next(&port_dump, &port)) {
918 : 614 : node = shash_find(&init_ofp_ports, port.name);
919 [ + - ][ - + ]: 614 : if (!node && strcmp(port.name, dpif_base_name(backer->dpif))) {
920 : 0 : garbage = xmalloc(sizeof *garbage);
921 : 0 : garbage->odp_port = port.port_no;
922 : 0 : ovs_list_push_front(&garbage_list, &garbage->list_node);
923 : : }
924 : : }
925 : 614 : dpif_port_dump_done(&port_dump);
926 : :
927 [ - + ]: 614 : LIST_FOR_EACH_POP (garbage, list_node, &garbage_list) {
928 : 0 : dpif_port_del(backer->dpif, garbage->odp_port);
929 : 0 : free(garbage);
930 : : }
931 : :
932 : 614 : shash_add(&all_dpif_backers, type, backer);
933 : :
934 : 614 : check_support(backer);
935 : 614 : atomic_count_init(&backer->tnl_count, 0);
936 : :
937 : 614 : error = dpif_recv_set(backer->dpif, backer->recv_set_enable);
938 [ - + ]: 614 : if (error) {
939 [ # # ]: 0 : VLOG_ERR("failed to listen on datapath of type %s: %s",
940 : : type, ovs_strerror(error));
941 : 0 : close_dpif_backer(backer);
942 : 0 : return error;
943 : : }
944 : :
945 [ + + ]: 614 : if (backer->recv_set_enable) {
946 : 613 : udpif_set_threads(backer->udpif, n_handlers, n_revalidators);
947 : : }
948 : :
949 : : /* This check fails if performed before udpif threads have been set,
950 : : * as the kernel module checks that the 'pid' in userspace action
951 : : * is non-zero. */
952 : : backer->support.variable_length_userdata
953 : 614 : = check_variable_length_userdata(backer);
954 : 614 : backer->dp_version_string = dpif_get_dp_version(backer->dpif);
955 : :
956 : 749 : return error;
957 : : }
958 : :
959 : : bool
960 : 1473014 : ovs_native_tunneling_is_on(struct ofproto_dpif *ofproto)
961 : : {
962 [ + + ]: 2919995 : return ofproto_use_tnl_push_pop && ofproto->backer->support.tnl_push_pop &&
[ + + + + ]
963 : 1446982 : atomic_count_get(&ofproto->backer->tnl_count);
964 : : }
965 : :
966 : : /* Tests whether 'backer''s datapath supports recirculation. Only newer
967 : : * datapaths support OVS_KEY_ATTR_RECIRC_ID in keys. We need to disable some
968 : : * features on older datapaths that don't support this feature.
969 : : *
970 : : * Returns false if 'backer' definitely does not support recirculation, true if
971 : : * it seems to support recirculation or if at least the error we get is
972 : : * ambiguous. */
973 : : static bool
974 : 614 : check_recirc(struct dpif_backer *backer)
975 : : {
976 : : struct flow flow;
977 : : struct odputil_keybuf keybuf;
978 : : struct ofpbuf key;
979 : : bool enable_recirc;
980 : 614 : struct odp_flow_key_parms odp_parms = {
981 : : .flow = &flow,
982 : : .support = {
983 : : .recirc = true,
984 : : },
985 : : };
986 : :
987 : 614 : memset(&flow, 0, sizeof flow);
988 : 614 : flow.recirc_id = 1;
989 : 614 : flow.dp_hash = 1;
990 : :
991 : 614 : ofpbuf_use_stack(&key, &keybuf, sizeof keybuf);
992 : 614 : odp_flow_key_from_flow(&odp_parms, &key);
993 : 614 : enable_recirc = dpif_probe_feature(backer->dpif, "recirculation", &key,
994 : : NULL);
995 : :
996 [ + - ]: 614 : if (enable_recirc) {
997 [ + - ]: 614 : VLOG_INFO("%s: Datapath supports recirculation",
998 : : dpif_name(backer->dpif));
999 : : } else {
1000 [ # # ]: 0 : VLOG_INFO("%s: Datapath does not support recirculation",
1001 : : dpif_name(backer->dpif));
1002 : : }
1003 : :
1004 : 614 : return enable_recirc;
1005 : : }
1006 : :
1007 : : /* Tests whether 'dpif' supports unique flow ids. We can skip serializing
1008 : : * some flow attributes for datapaths that support this feature.
1009 : : *
1010 : : * Returns true if 'dpif' supports UFID for flow operations.
1011 : : * Returns false if 'dpif' does not support UFID. */
1012 : : static bool
1013 : 614 : check_ufid(struct dpif_backer *backer)
1014 : : {
1015 : : struct flow flow;
1016 : : struct odputil_keybuf keybuf;
1017 : : struct ofpbuf key;
1018 : : ovs_u128 ufid;
1019 : : bool enable_ufid;
1020 : 614 : struct odp_flow_key_parms odp_parms = {
1021 : : .flow = &flow,
1022 : : };
1023 : :
1024 : 614 : memset(&flow, 0, sizeof flow);
1025 : 614 : flow.dl_type = htons(0x1234);
1026 : :
1027 : 614 : ofpbuf_use_stack(&key, &keybuf, sizeof keybuf);
1028 : 614 : odp_flow_key_from_flow(&odp_parms, &key);
1029 : 614 : dpif_flow_hash(backer->dpif, key.data, key.size, &ufid);
1030 : :
1031 : 614 : enable_ufid = dpif_probe_feature(backer->dpif, "UFID", &key, &ufid);
1032 : :
1033 [ + - ]: 614 : if (enable_ufid) {
1034 [ + - ]: 614 : VLOG_INFO("%s: Datapath supports unique flow ids",
1035 : : dpif_name(backer->dpif));
1036 : : } else {
1037 [ # # ]: 0 : VLOG_INFO("%s: Datapath does not support unique flow ids",
1038 : : dpif_name(backer->dpif));
1039 : : }
1040 : 614 : return enable_ufid;
1041 : : }
1042 : :
1043 : : /* Tests whether 'backer''s datapath supports variable-length
1044 : : * OVS_USERSPACE_ATTR_USERDATA in OVS_ACTION_ATTR_USERSPACE actions. We need
1045 : : * to disable some features on older datapaths that don't support this
1046 : : * feature.
1047 : : *
1048 : : * Returns false if 'backer' definitely does not support variable-length
1049 : : * userdata, true if it seems to support them or if at least the error we get
1050 : : * is ambiguous. */
1051 : : static bool
1052 : 614 : check_variable_length_userdata(struct dpif_backer *backer)
1053 : : {
1054 : : struct eth_header *eth;
1055 : : struct ofpbuf actions;
1056 : : struct dpif_execute execute;
1057 : : struct dp_packet packet;
1058 : : struct flow flow;
1059 : : size_t start;
1060 : : int error;
1061 : :
1062 : : /* Compose a userspace action that will cause an ERANGE error on older
1063 : : * datapaths that don't support variable-length userdata.
1064 : : *
1065 : : * We really test for using userdata longer than 8 bytes, but older
1066 : : * datapaths accepted these, silently truncating the userdata to 8 bytes.
1067 : : * The same older datapaths rejected userdata shorter than 8 bytes, so we
1068 : : * test for that instead as a proxy for longer userdata support. */
1069 : 614 : ofpbuf_init(&actions, 64);
1070 : 614 : start = nl_msg_start_nested(&actions, OVS_ACTION_ATTR_USERSPACE);
1071 : 614 : nl_msg_put_u32(&actions, OVS_USERSPACE_ATTR_PID,
1072 : 614 : dpif_port_get_pid(backer->dpif, ODPP_NONE, 0));
1073 : 614 : nl_msg_put_unspec_zero(&actions, OVS_USERSPACE_ATTR_USERDATA, 4);
1074 : 614 : nl_msg_end_nested(&actions, start);
1075 : :
1076 : : /* Compose a dummy ethernet packet. */
1077 : 614 : dp_packet_init(&packet, ETH_HEADER_LEN);
1078 : 614 : eth = dp_packet_put_zeros(&packet, ETH_HEADER_LEN);
1079 : 614 : eth->eth_type = htons(0x1234);
1080 : :
1081 : 614 : flow_extract(&packet, &flow);
1082 : :
1083 : : /* Execute the actions. On older datapaths this fails with ERANGE, on
1084 : : * newer datapaths it succeeds. */
1085 : 614 : execute.actions = actions.data;
1086 : 614 : execute.actions_len = actions.size;
1087 : 614 : execute.packet = &packet;
1088 : 614 : execute.flow = &flow;
1089 : 614 : execute.needs_help = false;
1090 : 614 : execute.probe = true;
1091 : 614 : execute.mtu = 0;
1092 : :
1093 : 614 : error = dpif_execute(backer->dpif, &execute);
1094 : :
1095 : 614 : dp_packet_uninit(&packet);
1096 : 614 : ofpbuf_uninit(&actions);
1097 : :
1098 [ + - - ]: 614 : switch (error) {
1099 : : case 0:
1100 : 614 : return true;
1101 : :
1102 : : case ERANGE:
1103 : : /* Variable-length userdata is not supported. */
1104 [ # # ]: 0 : VLOG_WARN("%s: datapath does not support variable-length userdata "
1105 : : "feature (needs Linux 3.10+ or kernel module from OVS "
1106 : : "1..11+). The NXAST_SAMPLE action will be ignored.",
1107 : : dpif_name(backer->dpif));
1108 : 0 : return false;
1109 : :
1110 : : default:
1111 : : /* Something odd happened. We're not sure whether variable-length
1112 : : * userdata is supported. Default to "yes". */
1113 [ # # ]: 0 : VLOG_WARN("%s: variable-length userdata feature probe failed (%s)",
1114 : : dpif_name(backer->dpif), ovs_strerror(error));
1115 : 614 : return true;
1116 : : }
1117 : : }
1118 : :
1119 : : /* Tests the MPLS label stack depth supported by 'backer''s datapath.
1120 : : *
1121 : : * Returns the number of elements in a struct flow's mpls_lse field
1122 : : * if the datapath supports at least that many entries in an
1123 : : * MPLS label stack.
1124 : : * Otherwise returns the number of MPLS push actions supported by
1125 : : * the datapath. */
1126 : : static size_t
1127 : 614 : check_max_mpls_depth(struct dpif_backer *backer)
1128 : : {
1129 : : struct flow flow;
1130 : : int n;
1131 : :
1132 [ + + ]: 2330 : for (n = 0; n < FLOW_MAX_MPLS_LABELS; n++) {
1133 : : struct odputil_keybuf keybuf;
1134 : : struct ofpbuf key;
1135 : 1779 : struct odp_flow_key_parms odp_parms = {
1136 : : .flow = &flow,
1137 : : };
1138 : :
1139 : 1779 : memset(&flow, 0, sizeof flow);
1140 : 1779 : flow.dl_type = htons(ETH_TYPE_MPLS);
1141 : 1779 : flow_set_mpls_bos(&flow, n, 1);
1142 : :
1143 : 1779 : ofpbuf_use_stack(&key, &keybuf, sizeof keybuf);
1144 : 1779 : odp_flow_key_from_flow(&odp_parms, &key);
1145 [ + + ]: 1779 : if (!dpif_probe_feature(backer->dpif, "MPLS", &key, NULL)) {
1146 : 63 : break;
1147 : : }
1148 : : }
1149 : :
1150 [ + - ]: 614 : VLOG_INFO("%s: MPLS label stack length probed as %d",
1151 : : dpif_name(backer->dpif), n);
1152 : 614 : return n;
1153 : : }
1154 : :
1155 : : /* Tests whether 'backer''s datapath supports masked data in
1156 : : * OVS_ACTION_ATTR_SET actions. We need to disable some features on older
1157 : : * datapaths that don't support this feature. */
1158 : : static bool
1159 : 614 : check_masked_set_action(struct dpif_backer *backer)
1160 : : {
1161 : : struct eth_header *eth;
1162 : : struct ofpbuf actions;
1163 : : struct dpif_execute execute;
1164 : : struct dp_packet packet;
1165 : : struct flow flow;
1166 : : int error;
1167 : : struct ovs_key_ethernet key, mask;
1168 : :
1169 : : /* Compose a set action that will cause an EINVAL error on older
1170 : : * datapaths that don't support masked set actions.
1171 : : * Avoid using a full mask, as it could be translated to a non-masked
1172 : : * set action instead. */
1173 : 614 : ofpbuf_init(&actions, 64);
1174 : 614 : memset(&key, 0x53, sizeof key);
1175 : 614 : memset(&mask, 0x7f, sizeof mask);
1176 : 614 : commit_masked_set_action(&actions, OVS_KEY_ATTR_ETHERNET, &key, &mask,
1177 : : sizeof key);
1178 : :
1179 : : /* Compose a dummy ethernet packet. */
1180 : 614 : dp_packet_init(&packet, ETH_HEADER_LEN);
1181 : 614 : eth = dp_packet_put_zeros(&packet, ETH_HEADER_LEN);
1182 : 614 : eth->eth_type = htons(0x1234);
1183 : :
1184 : 614 : flow_extract(&packet, &flow);
1185 : :
1186 : : /* Execute the actions. On older datapaths this fails with EINVAL, on
1187 : : * newer datapaths it succeeds. */
1188 : 614 : execute.actions = actions.data;
1189 : 614 : execute.actions_len = actions.size;
1190 : 614 : execute.packet = &packet;
1191 : 614 : execute.flow = &flow;
1192 : 614 : execute.needs_help = false;
1193 : 614 : execute.probe = true;
1194 : 614 : execute.mtu = 0;
1195 : :
1196 : 614 : error = dpif_execute(backer->dpif, &execute);
1197 : :
1198 : 614 : dp_packet_uninit(&packet);
1199 : 614 : ofpbuf_uninit(&actions);
1200 : :
1201 [ - + ]: 614 : if (error) {
1202 : : /* Masked set action is not supported. */
1203 [ # # ]: 0 : VLOG_INFO("%s: datapath does not support masked set action feature.",
1204 : : dpif_name(backer->dpif));
1205 : : }
1206 : 614 : return !error;
1207 : : }
1208 : :
1209 : : /* Tests whether 'backer''s datapath supports truncation of a packet in
1210 : : * OVS_ACTION_ATTR_TRUNC. We need to disable some features on older
1211 : : * datapaths that don't support this feature. */
1212 : : static bool
1213 : 614 : check_trunc_action(struct dpif_backer *backer)
1214 : : {
1215 : : struct eth_header *eth;
1216 : : struct ofpbuf actions;
1217 : : struct dpif_execute execute;
1218 : : struct dp_packet packet;
1219 : : struct ovs_action_trunc *trunc;
1220 : : struct flow flow;
1221 : : int error;
1222 : :
1223 : : /* Compose an action with output(port:1,
1224 : : * max_len:OVS_ACTION_OUTPUT_MIN + 1).
1225 : : * This translates to one truncate action and one output action. */
1226 : 614 : ofpbuf_init(&actions, 64);
1227 : 614 : trunc = nl_msg_put_unspec_uninit(&actions,
1228 : : OVS_ACTION_ATTR_TRUNC, sizeof *trunc);
1229 : :
1230 : 614 : trunc->max_len = ETH_HEADER_LEN + 1;
1231 : 614 : nl_msg_put_odp_port(&actions, OVS_ACTION_ATTR_OUTPUT, u32_to_odp(1));
1232 : :
1233 : : /* Compose a dummy Ethernet packet. */
1234 : 614 : dp_packet_init(&packet, ETH_HEADER_LEN);
1235 : 614 : eth = dp_packet_put_zeros(&packet, ETH_HEADER_LEN);
1236 : 614 : eth->eth_type = htons(0x1234);
1237 : :
1238 : 614 : flow_extract(&packet, &flow);
1239 : :
1240 : : /* Execute the actions. On older datapaths this fails with EINVAL, on
1241 : : * newer datapaths it succeeds. */
1242 : 614 : execute.actions = actions.data;
1243 : 614 : execute.actions_len = actions.size;
1244 : 614 : execute.packet = &packet;
1245 : 614 : execute.flow = &flow;
1246 : 614 : execute.needs_help = false;
1247 : 614 : execute.probe = true;
1248 : 614 : execute.mtu = 0;
1249 : :
1250 : 614 : error = dpif_execute(backer->dpif, &execute);
1251 : :
1252 : 614 : dp_packet_uninit(&packet);
1253 : 614 : ofpbuf_uninit(&actions);
1254 : :
1255 [ - + ]: 614 : if (error) {
1256 [ # # ]: 0 : VLOG_INFO("%s: Datapath does not support truncate action",
1257 : : dpif_name(backer->dpif));
1258 : : } else {
1259 [ + - ]: 614 : VLOG_INFO("%s: Datapath supports truncate action",
1260 : : dpif_name(backer->dpif));
1261 : : }
1262 : :
1263 : 614 : return !error;
1264 : : }
1265 : :
1266 : : #define CHECK_FEATURE__(NAME, SUPPORT, FIELD, VALUE) \
1267 : : static bool \
1268 : : check_##NAME(struct dpif_backer *backer) \
1269 : : { \
1270 : : struct flow flow; \
1271 : : struct odputil_keybuf keybuf; \
1272 : : struct ofpbuf key; \
1273 : : bool enable; \
1274 : : struct odp_flow_key_parms odp_parms = { \
1275 : : .flow = &flow, \
1276 : : .support = { \
1277 : : .SUPPORT = true, \
1278 : : }, \
1279 : : }; \
1280 : : \
1281 : : memset(&flow, 0, sizeof flow); \
1282 : : flow.FIELD = VALUE; \
1283 : : \
1284 : : ofpbuf_use_stack(&key, &keybuf, sizeof keybuf); \
1285 : : odp_flow_key_from_flow(&odp_parms, &key); \
1286 : : enable = dpif_probe_feature(backer->dpif, #NAME, &key, NULL); \
1287 : : \
1288 : : if (enable) { \
1289 : : VLOG_INFO("%s: Datapath supports "#NAME, dpif_name(backer->dpif)); \
1290 : : } else { \
1291 : : VLOG_INFO("%s: Datapath does not support "#NAME, \
1292 : : dpif_name(backer->dpif)); \
1293 : : } \
1294 : : \
1295 : : return enable; \
1296 : : }
1297 : : #define CHECK_FEATURE(FIELD) CHECK_FEATURE__(FIELD, FIELD, FIELD, 1)
1298 : :
1299 [ + - ][ + - ]: 1228 : CHECK_FEATURE(ct_state)
[ # # ]
1300 [ + - ][ + - ]: 1228 : CHECK_FEATURE(ct_zone)
[ # # ]
1301 [ + - ][ + - ]: 1228 : CHECK_FEATURE(ct_mark)
[ # # ]
1302 [ + - ][ + - ]: 1228 : CHECK_FEATURE__(ct_label, ct_label, ct_label.u64.lo, 1)
[ # # ]
1303 [ + + ][ + - ]: 1228 : CHECK_FEATURE__(ct_state_nat, ct_state, ct_state, CS_TRACKED|CS_SRC_NAT)
[ + - ]
1304 : :
1305 : : #undef CHECK_FEATURE
1306 : : #undef CHECK_FEATURE__
1307 : :
1308 : : static void
1309 : 614 : check_support(struct dpif_backer *backer)
1310 : : {
1311 : : /* This feature needs to be tested after udpif threads are set. */
1312 : 614 : backer->support.variable_length_userdata = false;
1313 : :
1314 : 614 : backer->support.odp.recirc = check_recirc(backer);
1315 : 614 : backer->support.odp.max_mpls_depth = check_max_mpls_depth(backer);
1316 : 614 : backer->support.masked_set_action = check_masked_set_action(backer);
1317 : 614 : backer->support.trunc = check_trunc_action(backer);
1318 : 614 : backer->support.ufid = check_ufid(backer);
1319 : 614 : backer->support.tnl_push_pop = dpif_supports_tnl_push_pop(backer->dpif);
1320 : :
1321 : 614 : backer->support.odp.ct_state = check_ct_state(backer);
1322 : 614 : backer->support.odp.ct_zone = check_ct_zone(backer);
1323 : 614 : backer->support.odp.ct_mark = check_ct_mark(backer);
1324 : 614 : backer->support.odp.ct_label = check_ct_label(backer);
1325 : :
1326 : 614 : backer->support.odp.ct_state_nat = check_ct_state_nat(backer);
1327 : 614 : }
1328 : :
1329 : : static int
1330 : 749 : construct(struct ofproto *ofproto_)
1331 : : {
1332 : 749 : struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
1333 : : struct shash_node *node, *next;
1334 : : int error;
1335 : :
1336 : : /* Tunnel module can get used right after the udpif threads are running. */
1337 : 749 : ofproto_tunnel_init();
1338 : :
1339 : 749 : error = open_dpif_backer(ofproto->up.type, &ofproto->backer);
1340 [ - + ]: 749 : if (error) {
1341 : 0 : return error;
1342 : : }
1343 : :
1344 : 749 : uuid_generate(&ofproto->uuid);
1345 : 749 : atomic_init(&ofproto->tables_version, OVS_VERSION_MIN);
1346 : 749 : ofproto->netflow = NULL;
1347 : 749 : ofproto->sflow = NULL;
1348 : 749 : ofproto->ipfix = NULL;
1349 : 749 : ofproto->stp = NULL;
1350 : 749 : ofproto->rstp = NULL;
1351 : 749 : ofproto->dump_seq = 0;
1352 : 749 : hmap_init(&ofproto->bundles);
1353 : 749 : ofproto->ml = mac_learning_create(MAC_ENTRY_DEFAULT_IDLE_TIME);
1354 : 749 : ofproto->ms = NULL;
1355 : 749 : ofproto->mbridge = mbridge_create();
1356 : 749 : ofproto->has_bonded_bundles = false;
1357 : 749 : ofproto->lacp_enabled = false;
1358 : 749 : ovs_mutex_init_adaptive(&ofproto->stats_mutex);
1359 : :
1360 : 749 : guarded_list_init(&ofproto->ams);
1361 : :
1362 : 749 : sset_init(&ofproto->ports);
1363 : 749 : sset_init(&ofproto->ghost_ports);
1364 : 749 : sset_init(&ofproto->port_poll_set);
1365 : 749 : ofproto->port_poll_errno = 0;
1366 : 749 : ofproto->change_seq = 0;
1367 : 749 : ofproto->ams_seq = seq_create();
1368 : 749 : ofproto->ams_seqno = seq_read(ofproto->ams_seq);
1369 : :
1370 : :
1371 [ + + ][ - + ]: 762 : SHASH_FOR_EACH_SAFE (node, next, &init_ofp_ports) {
[ + + ]
1372 : 13 : struct iface_hint *iface_hint = node->data;
1373 : :
1374 [ + + ]: 13 : if (!strcmp(iface_hint->br_name, ofproto->up.name)) {
1375 : : /* Check if the datapath already has this port. */
1376 [ - + ]: 9 : if (dpif_port_exists(ofproto->backer->dpif, node->name)) {
1377 : 0 : sset_add(&ofproto->ports, node->name);
1378 : : }
1379 : :
1380 : 9 : free(iface_hint->br_name);
1381 : 9 : free(iface_hint->br_type);
1382 : 9 : free(iface_hint);
1383 : 9 : shash_delete(&init_ofp_ports, node);
1384 : : }
1385 : : }
1386 : :
1387 : 749 : hmap_insert(&all_ofproto_dpifs, &ofproto->all_ofproto_dpifs_node,
1388 : : hash_string(ofproto->up.name, 0));
1389 : 749 : memset(&ofproto->stats, 0, sizeof ofproto->stats);
1390 : :
1391 : 749 : ofproto_init_tables(ofproto_, N_TABLES);
1392 : 749 : error = add_internal_flows(ofproto);
1393 : :
1394 : 749 : ofproto->up.tables[TBL_INTERNAL].flags = OFTABLE_HIDDEN | OFTABLE_READONLY;
1395 : :
1396 : 749 : return error;
1397 : : }
1398 : :
1399 : : static int
1400 : 2247 : add_internal_miss_flow(struct ofproto_dpif *ofproto, int id,
1401 : : const struct ofpbuf *ofpacts, struct rule_dpif **rulep)
1402 : : {
1403 : : struct match match;
1404 : : int error;
1405 : : struct rule *rule;
1406 : :
1407 : 2247 : match_init_catchall(&match);
1408 : 2247 : match_set_reg(&match, 0, id);
1409 : :
1410 : 2247 : error = ofproto_dpif_add_internal_flow(ofproto, &match, 0, 0, ofpacts,
1411 : : &rule);
1412 [ + - ]: 2247 : *rulep = error ? NULL : rule_dpif_cast(rule);
1413 : :
1414 : 2247 : return error;
1415 : : }
1416 : :
1417 : : static int
1418 : 749 : add_internal_flows(struct ofproto_dpif *ofproto)
1419 : : {
1420 : : struct ofpact_controller *controller;
1421 : : uint64_t ofpacts_stub[128 / 8];
1422 : : struct ofpbuf ofpacts;
1423 : : struct rule *unused_rulep OVS_UNUSED;
1424 : : struct match match;
1425 : : int error;
1426 : : int id;
1427 : :
1428 : 749 : ofpbuf_use_stack(&ofpacts, ofpacts_stub, sizeof ofpacts_stub);
1429 : 749 : id = 1;
1430 : :
1431 : 749 : controller = ofpact_put_CONTROLLER(&ofpacts);
1432 : 749 : controller->max_len = UINT16_MAX;
1433 : 749 : controller->controller_id = 0;
1434 : 749 : controller->reason = OFPR_IMPLICIT_MISS;
1435 : 749 : ofpact_finish_CONTROLLER(&ofpacts, &controller);
1436 : :
1437 : 749 : error = add_internal_miss_flow(ofproto, id++, &ofpacts,
1438 : : &ofproto->miss_rule);
1439 [ - + ]: 749 : if (error) {
1440 : 0 : return error;
1441 : : }
1442 : :
1443 : 749 : ofpbuf_clear(&ofpacts);
1444 : 749 : error = add_internal_miss_flow(ofproto, id++, &ofpacts,
1445 : : &ofproto->no_packet_in_rule);
1446 [ - + ]: 749 : if (error) {
1447 : 0 : return error;
1448 : : }
1449 : :
1450 : 749 : error = add_internal_miss_flow(ofproto, id++, &ofpacts,
1451 : : &ofproto->drop_frags_rule);
1452 [ - + ]: 749 : if (error) {
1453 : 0 : return error;
1454 : : }
1455 : :
1456 : : /* Drop any run away non-recirc rule lookups. Recirc_id has to be
1457 : : * zero when reaching this rule.
1458 : : *
1459 : : * (priority=2), recirc_id=0, actions=drop
1460 : : */
1461 : 749 : ofpbuf_clear(&ofpacts);
1462 : 749 : match_init_catchall(&match);
1463 : 749 : match_set_recirc_id(&match, 0);
1464 : 749 : error = ofproto_dpif_add_internal_flow(ofproto, &match, 2, 0, &ofpacts,
1465 : : &unused_rulep);
1466 : 749 : return error;
1467 : : }
1468 : :
1469 : : static void
1470 : 749 : destruct(struct ofproto *ofproto_)
1471 : : {
1472 : 749 : struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
1473 : : struct ofproto_async_msg *am;
1474 : : struct rule_dpif *rule;
1475 : : struct oftable *table;
1476 : : struct ovs_list ams;
1477 : :
1478 : 749 : ofproto->backer->need_revalidate = REV_RECONFIGURE;
1479 : 749 : xlate_txn_start();
1480 : 749 : xlate_remove_ofproto(ofproto);
1481 : 749 : xlate_txn_commit();
1482 : :
1483 : : /* Ensure that the upcall processing threads have no remaining references
1484 : : * to the ofproto or anything in it. */
1485 : 749 : udpif_synchronize(ofproto->backer->udpif);
1486 : :
1487 : 749 : hmap_remove(&all_ofproto_dpifs, &ofproto->all_ofproto_dpifs_node);
1488 : :
1489 [ + + ]: 191744 : OFPROTO_FOR_EACH_TABLE (table, &ofproto->up) {
1490 [ + + ][ + + ]: 195271 : CLS_FOR_EACH (rule, up.cr, &table->cls) {
1491 : 4276 : ofproto_rule_delete(&ofproto->up, &rule->up);
1492 : : }
1493 : : }
1494 : 749 : ofproto_group_delete_all(&ofproto->up);
1495 : :
1496 : 749 : guarded_list_pop_all(&ofproto->ams, &ams);
1497 [ - + ]: 749 : LIST_FOR_EACH_POP (am, list_node, &ams) {
1498 : 0 : ofproto_async_msg_free(am);
1499 : : }
1500 : 749 : guarded_list_destroy(&ofproto->ams);
1501 : :
1502 : 749 : recirc_free_ofproto(ofproto, ofproto->up.name);
1503 : :
1504 : 749 : mbridge_unref(ofproto->mbridge);
1505 : :
1506 : 749 : netflow_unref(ofproto->netflow);
1507 : 749 : dpif_sflow_unref(ofproto->sflow);
1508 : 749 : dpif_ipfix_unref(ofproto->ipfix);
1509 : 749 : hmap_destroy(&ofproto->bundles);
1510 : 749 : mac_learning_unref(ofproto->ml);
1511 : 749 : mcast_snooping_unref(ofproto->ms);
1512 : :
1513 : 749 : sset_destroy(&ofproto->ports);
1514 : 749 : sset_destroy(&ofproto->ghost_ports);
1515 : 749 : sset_destroy(&ofproto->port_poll_set);
1516 : :
1517 : 749 : ovs_mutex_destroy(&ofproto->stats_mutex);
1518 : :
1519 : 749 : seq_destroy(ofproto->ams_seq);
1520 : :
1521 : 749 : close_dpif_backer(ofproto->backer);
1522 : 749 : }
1523 : :
1524 : : static int
1525 : 157605 : run(struct ofproto *ofproto_)
1526 : : {
1527 : 157605 : struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
1528 : : uint64_t new_seq, new_dump_seq;
1529 : :
1530 [ - + ]: 157605 : if (mbridge_need_revalidate(ofproto->mbridge)) {
1531 : 0 : ofproto->backer->need_revalidate = REV_RECONFIGURE;
1532 : 0 : ovs_rwlock_wrlock(&ofproto->ml->rwlock);
1533 : 0 : mac_learning_flush(ofproto->ml);
1534 : 0 : ovs_rwlock_unlock(&ofproto->ml->rwlock);
1535 : 0 : mcast_snooping_mdb_flush(ofproto->ms);
1536 : : }
1537 : :
1538 : : /* Always updates the ofproto->ams_seqno to avoid frequent wakeup during
1539 : : * flow restore. Even though nothing is processed during flow restore,
1540 : : * all queued 'ams' will be handled immediately when flow restore
1541 : : * completes. */
1542 : 157605 : ofproto->ams_seqno = seq_read(ofproto->ams_seq);
1543 : :
1544 : : /* Do not perform any periodic activity required by 'ofproto' while
1545 : : * waiting for flow restore to complete. */
1546 [ + + ]: 157605 : if (!ofproto_get_flow_restore_wait()) {
1547 : : struct ofproto_async_msg *am;
1548 : : struct ovs_list ams;
1549 : :
1550 : 157527 : guarded_list_pop_all(&ofproto->ams, &ams);
1551 [ + + ]: 158578 : LIST_FOR_EACH_POP (am, list_node, &ams) {
1552 : 1051 : connmgr_send_async_msg(ofproto->up.connmgr, am);
1553 : 1051 : ofproto_async_msg_free(am);
1554 : : }
1555 : : }
1556 : :
1557 [ + + ]: 157605 : if (ofproto->netflow) {
1558 : 1336 : netflow_run(ofproto->netflow);
1559 : : }
1560 [ + + ]: 157605 : if (ofproto->sflow) {
1561 : 425 : dpif_sflow_run(ofproto->sflow);
1562 : : }
1563 [ + + ]: 157605 : if (ofproto->ipfix) {
1564 : 287 : dpif_ipfix_run(ofproto->ipfix);
1565 : : }
1566 : :
1567 : 157605 : new_seq = seq_read(connectivity_seq_get());
1568 [ + + ]: 157605 : if (ofproto->change_seq != new_seq) {
1569 : : struct ofport_dpif *ofport;
1570 : :
1571 [ + + ][ - + ]: 41960 : HMAP_FOR_EACH (ofport, up.hmap_node, &ofproto->up.ports) {
1572 : 35828 : port_run(ofport);
1573 : : }
1574 : :
1575 : 6132 : ofproto->change_seq = new_seq;
1576 : : }
1577 [ + + ][ + + ]: 157605 : if (ofproto->lacp_enabled || ofproto->has_bonded_bundles) {
1578 : : struct ofbundle *bundle;
1579 : :
1580 [ + + ][ - + ]: 20948 : HMAP_FOR_EACH (bundle, hmap_node, &ofproto->bundles) {
1581 : 15523 : bundle_run(bundle);
1582 : : }
1583 : : }
1584 : :
1585 : 157605 : stp_run(ofproto);
1586 : 157605 : rstp_run(ofproto);
1587 : 157605 : ovs_rwlock_wrlock(&ofproto->ml->rwlock);
1588 [ + + ]: 157605 : if (mac_learning_run(ofproto->ml)) {
1589 : 569 : ofproto->backer->need_revalidate = REV_MAC_LEARNING;
1590 : : }
1591 : 157605 : ovs_rwlock_unlock(&ofproto->ml->rwlock);
1592 : :
1593 [ - + ]: 157605 : if (mcast_snooping_run(ofproto->ms)) {
1594 : 0 : ofproto->backer->need_revalidate = REV_MCAST_SNOOPING;
1595 : : }
1596 : :
1597 : 157605 : new_dump_seq = seq_read(udpif_dump_seq(ofproto->backer->udpif));
1598 [ + + ]: 157605 : if (ofproto->dump_seq != new_dump_seq) {
1599 : : struct rule *rule, *next_rule;
1600 : 38106 : long long now = time_msec();
1601 : :
1602 : : /* We know stats are relatively fresh, so now is a good time to do some
1603 : : * periodic work. */
1604 : 38106 : ofproto->dump_seq = new_dump_seq;
1605 : :
1606 : : /* Expire OpenFlow flows whose idle_timeout or hard_timeout
1607 : : * has passed. */
1608 : 38106 : ovs_mutex_lock(&ofproto_mutex);
1609 [ + + ][ + + ]: 38480 : LIST_FOR_EACH_SAFE (rule, next_rule, expirable,
1610 : : &ofproto->up.expirable) {
1611 : 374 : rule_expire(rule_dpif_cast(rule), now);
1612 : : }
1613 : 38106 : ovs_mutex_unlock(&ofproto_mutex);
1614 : :
1615 : : /* All outstanding data in existing flows has been accounted, so it's a
1616 : : * good time to do bond rebalancing. */
1617 [ + + ]: 38106 : if (ofproto->has_bonded_bundles) {
1618 : : struct ofbundle *bundle;
1619 : :
1620 [ + + ][ - + ]: 3866 : HMAP_FOR_EACH (bundle, hmap_node, &ofproto->bundles) {
1621 [ + + ]: 2803 : if (bundle->bond) {
1622 : 1063 : bond_rebalance(bundle->bond);
1623 : : }
1624 : : }
1625 : : }
1626 : : }
1627 : 157605 : return 0;
1628 : : }
1629 : :
1630 : : static void
1631 : 153645 : ofproto_dpif_wait(struct ofproto *ofproto_)
1632 : : {
1633 : 153645 : struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
1634 : :
1635 [ + + ]: 153645 : if (ofproto_get_flow_restore_wait()) {
1636 : 78 : return;
1637 : : }
1638 : :
1639 [ + + ]: 153567 : if (ofproto->sflow) {
1640 : 425 : dpif_sflow_wait(ofproto->sflow);
1641 : : }
1642 [ + + ]: 153567 : if (ofproto->ipfix) {
1643 : 283 : dpif_ipfix_wait(ofproto->ipfix);
1644 : : }
1645 [ + + ][ + + ]: 153567 : if (ofproto->lacp_enabled || ofproto->has_bonded_bundles) {
1646 : : struct ofbundle *bundle;
1647 : :
1648 [ + + ][ - + ]: 20907 : HMAP_FOR_EACH (bundle, hmap_node, &ofproto->bundles) {
1649 : 15495 : bundle_wait(bundle);
1650 : : }
1651 : : }
1652 [ + + ]: 153567 : if (ofproto->netflow) {
1653 : 1336 : netflow_wait(ofproto->netflow);
1654 : : }
1655 : 153567 : ovs_rwlock_rdlock(&ofproto->ml->rwlock);
1656 : 153567 : mac_learning_wait(ofproto->ml);
1657 : 153567 : ovs_rwlock_unlock(&ofproto->ml->rwlock);
1658 : 153567 : mcast_snooping_wait(ofproto->ms);
1659 : 153567 : stp_wait(ofproto);
1660 [ + + ]: 153567 : if (ofproto->backer->need_revalidate) {
1661 : 17508 : poll_immediate_wake();
1662 : : }
1663 : :
1664 : 153567 : seq_wait(udpif_dump_seq(ofproto->backer->udpif), ofproto->dump_seq);
1665 : 153567 : seq_wait(ofproto->ams_seq, ofproto->ams_seqno);
1666 : : }
1667 : :
1668 : : static void
1669 : 162 : type_get_memory_usage(const char *type, struct simap *usage)
1670 : : {
1671 : : struct dpif_backer *backer;
1672 : :
1673 : 162 : backer = shash_find_data(&all_dpif_backers, type);
1674 [ + + ]: 162 : if (backer) {
1675 : 72 : udpif_get_memory_usage(backer->udpif, usage);
1676 : : }
1677 : 162 : }
1678 : :
1679 : : static void
1680 : 895 : flush(struct ofproto *ofproto_)
1681 : : {
1682 : 895 : struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
1683 : 895 : struct dpif_backer *backer = ofproto->backer;
1684 : :
1685 [ + - ]: 895 : if (backer) {
1686 : 895 : udpif_flush(backer->udpif);
1687 : : }
1688 : 895 : }
1689 : :
1690 : : static void
1691 : 82 : query_tables(struct ofproto *ofproto,
1692 : : struct ofputil_table_features *features,
1693 : : struct ofputil_table_stats *stats)
1694 : : {
1695 : 82 : strcpy(features->name, "classifier");
1696 : :
1697 [ + + ]: 82 : if (stats) {
1698 : : int i;
1699 : :
1700 [ + + ]: 2560 : for (i = 0; i < ofproto->n_tables; i++) {
1701 : : unsigned long missed, matched;
1702 : :
1703 : 2550 : atomic_read_relaxed(&ofproto->tables[i].n_matched, &matched);
1704 : 2550 : atomic_read_relaxed(&ofproto->tables[i].n_missed, &missed);
1705 : :
1706 : 2550 : stats[i].matched_count = matched;
1707 : 2550 : stats[i].lookup_count = matched + missed;
1708 : : }
1709 : : }
1710 : 82 : }
1711 : :
1712 : : static void
1713 : 41413 : set_tables_version(struct ofproto *ofproto_, ovs_version_t version)
1714 : : {
1715 : 41413 : struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
1716 : :
1717 : 41413 : atomic_store_relaxed(&ofproto->tables_version, version);
1718 : 41413 : ofproto->backer->need_revalidate = REV_FLOW_TABLE;
1719 : 41413 : }
1720 : :
1721 : : static struct ofport *
1722 : 2690 : port_alloc(void)
1723 : : {
1724 : 2690 : struct ofport_dpif *port = xzalloc(sizeof *port);
1725 : 2690 : return &port->up;
1726 : : }
1727 : :
1728 : : static void
1729 : 2690 : port_dealloc(struct ofport *port_)
1730 : : {
1731 : 2690 : struct ofport_dpif *port = ofport_dpif_cast(port_);
1732 : 2690 : free(port);
1733 : 2690 : }
1734 : :
1735 : : static int
1736 : 2690 : port_construct(struct ofport *port_)
1737 : : {
1738 : 2690 : struct ofport_dpif *port = ofport_dpif_cast(port_);
1739 : 2690 : struct ofproto_dpif *ofproto = ofproto_dpif_cast(port->up.ofproto);
1740 : 2690 : const struct netdev *netdev = port->up.netdev;
1741 : : char namebuf[NETDEV_VPORT_NAME_BUFSIZE];
1742 : : const char *dp_port_name;
1743 : : struct dpif_port dpif_port;
1744 : : int error;
1745 : :
1746 : 2690 : ofproto->backer->need_revalidate = REV_RECONFIGURE;
1747 : 2690 : port->bundle = NULL;
1748 : 2690 : port->cfm = NULL;
1749 : 2690 : port->bfd = NULL;
1750 : 2690 : port->lldp = NULL;
1751 : 2690 : port->may_enable = false;
1752 : 2690 : port->stp_port = NULL;
1753 : 2690 : port->stp_state = STP_DISABLED;
1754 : 2690 : port->rstp_port = NULL;
1755 : 2690 : port->rstp_state = RSTP_DISABLED;
1756 : 2690 : port->is_tunnel = false;
1757 : 2690 : port->peer = NULL;
1758 : 2690 : port->qdscp = NULL;
1759 : 2690 : port->n_qdscp = 0;
1760 : 2690 : port->carrier_seq = netdev_get_carrier_resets(netdev);
1761 : 2690 : port->is_layer3 = netdev_vport_is_layer3(netdev);
1762 : :
1763 [ + + ]: 2690 : if (netdev_vport_is_patch(netdev)) {
1764 : : /* By bailing out here, we don't submit the port to the sFlow module
1765 : : * to be considered for counter polling export. This is correct
1766 : : * because the patch port represents an interface that sFlow considers
1767 : : * to be "internal" to the switch as a whole, and therefore not a
1768 : : * candidate for counter polling. */
1769 : 322 : port->odp_port = ODPP_NONE;
1770 : 322 : ofport_update_peer(port);
1771 : 322 : return 0;
1772 : : }
1773 : :
1774 : 2368 : dp_port_name = netdev_vport_get_dpif_port(netdev, namebuf, sizeof namebuf);
1775 : 2368 : error = dpif_port_query_by_name(ofproto->backer->dpif, dp_port_name,
1776 : : &dpif_port);
1777 [ - + ]: 2368 : if (error) {
1778 : 0 : return error;
1779 : : }
1780 : :
1781 : 2368 : port->odp_port = dpif_port.port_no;
1782 : :
1783 [ + + ]: 2368 : if (netdev_get_tunnel_config(netdev)) {
1784 : 320 : atomic_count_inc(&ofproto->backer->tnl_count);
1785 : 320 : error = tnl_port_add(port, port->up.netdev, port->odp_port,
1786 : 320 : ovs_native_tunneling_is_on(ofproto), dp_port_name);
1787 [ + + ]: 320 : if (error) {
1788 : 1 : atomic_count_dec(&ofproto->backer->tnl_count);
1789 : 1 : dpif_port_destroy(&dpif_port);
1790 : 1 : return error;
1791 : : }
1792 : :
1793 : 319 : port->is_tunnel = true;
1794 [ - + ]: 319 : if (ofproto->ipfix) {
1795 : 319 : dpif_ipfix_add_tunnel_port(ofproto->ipfix, port_, port->odp_port);
1796 : : }
1797 : : } else {
1798 : : /* Sanity-check that a mapping doesn't already exist. This
1799 : : * shouldn't happen for non-tunnel ports. */
1800 [ - + ]: 2048 : if (odp_port_to_ofp_port(ofproto, port->odp_port) != OFPP_NONE) {
1801 [ # # ]: 0 : VLOG_ERR("port %s already has an OpenFlow port number",
1802 : : dpif_port.name);
1803 : 0 : dpif_port_destroy(&dpif_port);
1804 : 0 : return EBUSY;
1805 : : }
1806 : :
1807 : 2048 : ovs_rwlock_wrlock(&ofproto->backer->odp_to_ofport_lock);
1808 : 2048 : hmap_insert(&ofproto->backer->odp_to_ofport_map, &port->odp_port_node,
1809 : : hash_odp_port(port->odp_port));
1810 : 2048 : ovs_rwlock_unlock(&ofproto->backer->odp_to_ofport_lock);
1811 : : }
1812 : 2367 : dpif_port_destroy(&dpif_port);
1813 : :
1814 [ - + ]: 2367 : if (ofproto->sflow) {
1815 : 0 : dpif_sflow_add_port(ofproto->sflow, port_, port->odp_port);
1816 : : }
1817 : :
1818 : 2690 : return 0;
1819 : : }
1820 : :
1821 : : static void
1822 : 2689 : port_destruct(struct ofport *port_, bool del)
1823 : : {
1824 : 2689 : struct ofport_dpif *port = ofport_dpif_cast(port_);
1825 : 2689 : struct ofproto_dpif *ofproto = ofproto_dpif_cast(port->up.ofproto);
1826 : 2689 : const char *devname = netdev_get_name(port->up.netdev);
1827 : : char namebuf[NETDEV_VPORT_NAME_BUFSIZE];
1828 : : const char *dp_port_name;
1829 : :
1830 : 2689 : ofproto->backer->need_revalidate = REV_RECONFIGURE;
1831 : 2689 : xlate_txn_start();
1832 : 2689 : xlate_ofport_remove(port);
1833 : 2689 : xlate_txn_commit();
1834 : :
1835 : 2689 : dp_port_name = netdev_vport_get_dpif_port(port->up.netdev, namebuf,
1836 : : sizeof namebuf);
1837 [ + + ][ + + ]: 2689 : if (del && dpif_port_exists(ofproto->backer->dpif, dp_port_name)) {
1838 : : /* The underlying device is still there, so delete it. This
1839 : : * happens when the ofproto is being destroyed, since the caller
1840 : : * assumes that removal of attached ports will happen as part of
1841 : : * destruction. */
1842 [ + + ]: 61 : if (!port->is_tunnel) {
1843 : 15 : dpif_port_del(ofproto->backer->dpif, port->odp_port);
1844 : : }
1845 : : }
1846 : :
1847 [ + + ]: 2689 : if (port->peer) {
1848 : 158 : port->peer->peer = NULL;
1849 : 158 : port->peer = NULL;
1850 : : }
1851 : :
1852 [ + + ][ + + ]: 2689 : if (port->odp_port != ODPP_NONE && !port->is_tunnel) {
1853 : 2048 : ovs_rwlock_wrlock(&ofproto->backer->odp_to_ofport_lock);
1854 : 2048 : hmap_remove(&ofproto->backer->odp_to_ofport_map, &port->odp_port_node);
1855 : 2048 : ovs_rwlock_unlock(&ofproto->backer->odp_to_ofport_lock);
1856 : : }
1857 : :
1858 [ + + ]: 2689 : if (port->is_tunnel) {
1859 : 319 : atomic_count_dec(&ofproto->backer->tnl_count);
1860 : : }
1861 : :
1862 [ + + ][ - + ]: 2689 : if (port->is_tunnel && ofproto->ipfix) {
1863 : 0 : dpif_ipfix_del_tunnel_port(ofproto->ipfix, port->odp_port);
1864 : : }
1865 : :
1866 : 2689 : tnl_port_del(port);
1867 : 2689 : sset_find_and_delete(&ofproto->ports, devname);
1868 : 2689 : sset_find_and_delete(&ofproto->ghost_ports, devname);
1869 : 2689 : bundle_remove(port_);
1870 : 2689 : set_cfm(port_, NULL);
1871 : 2689 : set_bfd(port_, NULL);
1872 : 2689 : set_lldp(port_, NULL);
1873 [ - + ]: 2689 : if (port->stp_port) {
1874 : 0 : stp_port_disable(port->stp_port);
1875 : : }
1876 : 2689 : set_rstp_port(port_, NULL);
1877 [ + + ]: 2689 : if (ofproto->sflow) {
1878 : 18 : dpif_sflow_del_port(ofproto->sflow, port->odp_port);
1879 : : }
1880 : :
1881 : 2689 : free(port->qdscp);
1882 : 2689 : }
1883 : :
1884 : : static void
1885 : 5006 : port_modified(struct ofport *port_)
1886 : : {
1887 : 5006 : struct ofport_dpif *port = ofport_dpif_cast(port_);
1888 : : char namebuf[NETDEV_VPORT_NAME_BUFSIZE];
1889 : : const char *dp_port_name;
1890 : 5006 : struct netdev *netdev = port->up.netdev;
1891 : :
1892 [ + - ][ + + ]: 5006 : if (port->bundle && port->bundle->bond) {
1893 : 36 : bond_slave_set_netdev(port->bundle->bond, port, netdev);
1894 : : }
1895 : :
1896 [ - + ]: 5006 : if (port->cfm) {
1897 : 0 : cfm_set_netdev(port->cfm, netdev);
1898 : : }
1899 : :
1900 [ + + ]: 5006 : if (port->bfd) {
1901 : 1 : bfd_set_netdev(port->bfd, netdev);
1902 : : }
1903 : :
1904 : 5006 : ofproto_dpif_monitor_port_update(port, port->bfd, port->cfm,
1905 : 5006 : port->lldp, &port->up.pp.hw_addr);
1906 : :
1907 : 5006 : dp_port_name = netdev_vport_get_dpif_port(netdev, namebuf, sizeof namebuf);
1908 : :
1909 [ + + ]: 5006 : if (port->is_tunnel) {
1910 : 5 : struct ofproto_dpif *ofproto = ofproto_dpif_cast(port->up.ofproto);
1911 : :
1912 [ - + ]: 5 : if (tnl_port_reconfigure(port, netdev, port->odp_port,
1913 : 5 : ovs_native_tunneling_is_on(ofproto),
1914 : : dp_port_name)) {
1915 : 0 : ofproto->backer->need_revalidate = REV_RECONFIGURE;
1916 : : }
1917 : : }
1918 : :
1919 : 5006 : ofport_update_peer(port);
1920 : 5006 : }
1921 : :
1922 : : static void
1923 : 39 : port_reconfigured(struct ofport *port_, enum ofputil_port_config old_config)
1924 : : {
1925 : 39 : struct ofport_dpif *port = ofport_dpif_cast(port_);
1926 : 39 : struct ofproto_dpif *ofproto = ofproto_dpif_cast(port->up.ofproto);
1927 : 39 : enum ofputil_port_config changed = old_config ^ port->up.pp.config;
1928 : :
1929 [ + + ]: 39 : if (changed & (OFPUTIL_PC_NO_RECV | OFPUTIL_PC_NO_RECV_STP |
1930 : : OFPUTIL_PC_NO_FWD | OFPUTIL_PC_NO_FLOOD |
1931 : : OFPUTIL_PC_NO_PACKET_IN)) {
1932 : 22 : ofproto->backer->need_revalidate = REV_RECONFIGURE;
1933 : :
1934 [ + + ][ + - ]: 22 : if (changed & OFPUTIL_PC_NO_FLOOD && port->bundle) {
1935 : 3 : bundle_update(port->bundle);
1936 : : }
1937 : : }
1938 : 39 : }
1939 : :
1940 : : static int
1941 : 4700 : set_sflow(struct ofproto *ofproto_,
1942 : : const struct ofproto_sflow_options *sflow_options)
1943 : : {
1944 : 4700 : struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
1945 : 4700 : struct dpif_sflow *ds = ofproto->sflow;
1946 : :
1947 [ + + ]: 4700 : if (sflow_options) {
1948 [ - + ]: 6 : uint32_t old_probability = ds ? dpif_sflow_get_probability(ds) : 0;
1949 [ + - ]: 6 : if (!ds) {
1950 : : struct ofport_dpif *ofport;
1951 : :
1952 : 6 : ds = ofproto->sflow = dpif_sflow_create();
1953 [ + + ][ - + ]: 24 : HMAP_FOR_EACH (ofport, up.hmap_node, &ofproto->up.ports) {
1954 : 18 : dpif_sflow_add_port(ds, &ofport->up, ofport->odp_port);
1955 : : }
1956 : : }
1957 : 6 : dpif_sflow_set_options(ds, sflow_options);
1958 [ + - ]: 6 : if (dpif_sflow_get_probability(ds) != old_probability) {
1959 : 6 : ofproto->backer->need_revalidate = REV_RECONFIGURE;
1960 : : }
1961 : : } else {
1962 [ - + ]: 4694 : if (ds) {
1963 : 0 : dpif_sflow_unref(ds);
1964 : 0 : ofproto->backer->need_revalidate = REV_RECONFIGURE;
1965 : 0 : ofproto->sflow = NULL;
1966 : : }
1967 : : }
1968 : 4700 : return 0;
1969 : : }
1970 : :
1971 : : static int
1972 : 4700 : set_ipfix(
1973 : : struct ofproto *ofproto_,
1974 : : const struct ofproto_ipfix_bridge_exporter_options *bridge_exporter_options,
1975 : : const struct ofproto_ipfix_flow_exporter_options *flow_exporters_options,
1976 : : size_t n_flow_exporters_options)
1977 : : {
1978 : 4700 : struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
1979 : 4700 : struct dpif_ipfix *di = ofproto->ipfix;
1980 [ + + ][ + + ]: 4700 : bool has_options = bridge_exporter_options || flow_exporters_options;
1981 : 4700 : bool new_di = false;
1982 : :
1983 [ + + ][ + - ]: 4700 : if (has_options && !di) {
1984 : 5 : di = ofproto->ipfix = dpif_ipfix_create();
1985 : 5 : new_di = true;
1986 : : }
1987 : :
1988 [ + + ]: 4700 : if (di) {
1989 : : /* Call set_options in any case to cleanly flush the flow
1990 : : * caches in the last exporters that are to be destroyed. */
1991 : 9 : dpif_ipfix_set_options(
1992 : : di, bridge_exporter_options, flow_exporters_options,
1993 : : n_flow_exporters_options);
1994 : :
1995 : : /* Add tunnel ports only when a new ipfix created */
1996 [ + + ]: 9 : if (new_di == true) {
1997 : : struct ofport_dpif *ofport;
1998 [ + + ][ - + ]: 21 : HMAP_FOR_EACH (ofport, up.hmap_node, &ofproto->up.ports) {
1999 [ + + ]: 16 : if (ofport->is_tunnel == true) {
2000 : 2 : dpif_ipfix_add_tunnel_port(di, &ofport->up, ofport->odp_port);
2001 : : }
2002 : : }
2003 : : }
2004 : :
2005 [ + + ]: 9 : if (!has_options) {
2006 : 4 : dpif_ipfix_unref(di);
2007 : 4 : ofproto->ipfix = NULL;
2008 : : }
2009 : : }
2010 : :
2011 : 4700 : return 0;
2012 : : }
2013 : :
2014 : : static int
2015 : 6 : get_ipfix_stats(const struct ofproto *ofproto_,
2016 : : bool bridge_ipfix,
2017 : : struct ovs_list *replies)
2018 : : {
2019 : 6 : struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
2020 : 6 : struct dpif_ipfix *di = ofproto->ipfix;
2021 : :
2022 [ + + ]: 6 : if (!di) {
2023 : 4 : return OFPERR_NXST_NOT_CONFIGURED;
2024 : : }
2025 : :
2026 : 2 : return dpif_ipfix_get_stats(di, bridge_ipfix, replies);
2027 : : }
2028 : :
2029 : : static int
2030 : 37214 : set_cfm(struct ofport *ofport_, const struct cfm_settings *s)
2031 : : {
2032 : 37214 : struct ofport_dpif *ofport = ofport_dpif_cast(ofport_);
2033 : 37214 : struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofport->up.ofproto);
2034 : 37214 : struct cfm *old = ofport->cfm;
2035 : 37214 : int error = 0;
2036 : :
2037 [ + + ]: 37214 : if (s) {
2038 [ + + ]: 32 : if (!ofport->cfm) {
2039 : 16 : ofport->cfm = cfm_create(ofport->up.netdev);
2040 : : }
2041 : :
2042 [ + - ]: 32 : if (cfm_configure(ofport->cfm, s)) {
2043 : 32 : error = 0;
2044 : 32 : goto out;
2045 : : }
2046 : :
2047 : 0 : error = EINVAL;
2048 : : }
2049 : 37182 : cfm_unref(ofport->cfm);
2050 : 37182 : ofport->cfm = NULL;
2051 : : out:
2052 [ + + ]: 37214 : if (ofport->cfm != old) {
2053 : 32 : ofproto->backer->need_revalidate = REV_RECONFIGURE;
2054 : : }
2055 : 37214 : ofproto_dpif_monitor_port_update(ofport, ofport->bfd, ofport->cfm,
2056 : 37214 : ofport->lldp, &ofport->up.pp.hw_addr);
2057 : 37214 : return error;
2058 : : }
2059 : :
2060 : : static bool
2061 : 36468 : cfm_status_changed(struct ofport *ofport_)
2062 : : {
2063 : 36468 : struct ofport_dpif *ofport = ofport_dpif_cast(ofport_);
2064 : :
2065 [ + + ][ + + ]: 36468 : return ofport->cfm ? cfm_check_status_change(ofport->cfm) : true;
2066 : : }
2067 : :
2068 : : static int
2069 : 36453 : get_cfm_status(const struct ofport *ofport_,
2070 : : struct cfm_status *status)
2071 : : {
2072 : 36453 : struct ofport_dpif *ofport = ofport_dpif_cast(ofport_);
2073 : 36453 : int ret = 0;
2074 : :
2075 [ + + ]: 36453 : if (ofport->cfm) {
2076 : 72 : cfm_get_status(ofport->cfm, status);
2077 : : } else {
2078 : 36381 : ret = ENOENT;
2079 : : }
2080 : :
2081 : 36453 : return ret;
2082 : : }
2083 : :
2084 : : static int
2085 : 34526 : set_bfd(struct ofport *ofport_, const struct smap *cfg)
2086 : : {
2087 : 34526 : struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofport_->ofproto);
2088 : 34526 : struct ofport_dpif *ofport = ofport_dpif_cast(ofport_);
2089 : : struct bfd *old;
2090 : :
2091 : 34526 : old = ofport->bfd;
2092 : 34526 : ofport->bfd = bfd_configure(old, netdev_get_name(ofport->up.netdev),
2093 : : cfg, ofport->up.netdev);
2094 [ + + ]: 34526 : if (ofport->bfd != old) {
2095 : 468 : ofproto->backer->need_revalidate = REV_RECONFIGURE;
2096 : : }
2097 : 34526 : ofproto_dpif_monitor_port_update(ofport, ofport->bfd, ofport->cfm,
2098 : 34526 : ofport->lldp, &ofport->up.pp.hw_addr);
2099 : 34526 : return 0;
2100 : : }
2101 : :
2102 : : static bool
2103 : 36468 : bfd_status_changed(struct ofport *ofport_)
2104 : : {
2105 : 36468 : struct ofport_dpif *ofport = ofport_dpif_cast(ofport_);
2106 : :
2107 [ + + ][ + + ]: 36468 : return ofport->bfd ? bfd_check_status_change(ofport->bfd) : true;
2108 : : }
2109 : :
2110 : : static int
2111 : 36409 : get_bfd_status(struct ofport *ofport_, struct smap *smap)
2112 : : {
2113 : 36409 : struct ofport_dpif *ofport = ofport_dpif_cast(ofport_);
2114 : 36409 : int ret = 0;
2115 : :
2116 [ + + ]: 36409 : if (ofport->bfd) {
2117 : 20105 : bfd_get_status(ofport->bfd, smap);
2118 : : } else {
2119 : 16304 : ret = ENOENT;
2120 : : }
2121 : :
2122 : 36409 : return ret;
2123 : : }
2124 : :
2125 : : static int
2126 : 34526 : set_lldp(struct ofport *ofport_,
2127 : : const struct smap *cfg)
2128 : : {
2129 : 34526 : struct ofport_dpif *ofport = ofport_dpif_cast(ofport_);
2130 : 34526 : int error = 0;
2131 : :
2132 [ + + ]: 34526 : if (cfg) {
2133 [ + - ]: 31837 : if (!ofport->lldp) {
2134 : : struct ofproto_dpif *ofproto;
2135 : :
2136 : 31837 : ofproto = ofproto_dpif_cast(ofport->up.ofproto);
2137 : 31837 : ofproto->backer->need_revalidate = REV_RECONFIGURE;
2138 : 31837 : ofport->lldp = lldp_create(ofport->up.netdev, ofport_->mtu, cfg);
2139 : : }
2140 : :
2141 [ - + ]: 31837 : if (!lldp_configure(ofport->lldp, cfg)) {
2142 : 0 : error = EINVAL;
2143 : : }
2144 : : }
2145 [ - + ]: 34526 : if (error) {
2146 : 0 : lldp_unref(ofport->lldp);
2147 : 0 : ofport->lldp = NULL;
2148 : : }
2149 : :
2150 : 34526 : ofproto_dpif_monitor_port_update(ofport,
2151 : : ofport->bfd,
2152 : : ofport->cfm,
2153 : : ofport->lldp,
2154 : 34526 : &ofport->up.pp.hw_addr);
2155 : 34526 : return error;
2156 : : }
2157 : :
2158 : : static bool
2159 : 0 : get_lldp_status(const struct ofport *ofport_,
2160 : : struct lldp_status *status OVS_UNUSED)
2161 : : {
2162 : 0 : struct ofport_dpif *ofport = ofport_dpif_cast(ofport_);
2163 : :
2164 : 0 : return ofport->lldp ? true : false;
2165 : : }
2166 : :
2167 : : static int
2168 : 4700 : set_aa(struct ofproto *ofproto OVS_UNUSED,
2169 : : const struct aa_settings *s)
2170 : : {
2171 : 4700 : return aa_configure(s);
2172 : : }
2173 : :
2174 : : static int
2175 : 0 : aa_mapping_set(struct ofproto *ofproto_ OVS_UNUSED, void *aux,
2176 : : const struct aa_mapping_settings *s)
2177 : : {
2178 : 0 : return aa_mapping_register(aux, s);
2179 : : }
2180 : :
2181 : : static int
2182 : 0 : aa_mapping_unset(struct ofproto *ofproto OVS_UNUSED, void *aux)
2183 : : {
2184 : 0 : return aa_mapping_unregister(aux);
2185 : : }
2186 : :
2187 : : static int
2188 : 0 : aa_vlan_get_queued(struct ofproto *ofproto OVS_UNUSED, struct ovs_list *list)
2189 : : {
2190 : 0 : return aa_get_vlan_queued(list);
2191 : : }
2192 : :
2193 : : static unsigned int
2194 : 5132 : aa_vlan_get_queue_size(struct ofproto *ofproto OVS_UNUSED)
2195 : : {
2196 : 5132 : return aa_get_vlan_queue_size();
2197 : : }
2198 : :
2199 : :
2200 : : /* Spanning Tree. */
2201 : :
2202 : : /* Called while rstp_mutex is held. */
2203 : : static void
2204 : 7 : rstp_send_bpdu_cb(struct dp_packet *pkt, void *ofport_, void *ofproto_)
2205 : : {
2206 : 7 : struct ofproto_dpif *ofproto = ofproto_;
2207 : 7 : struct ofport_dpif *ofport = ofport_;
2208 : 7 : struct eth_header *eth = dp_packet_l2(pkt);
2209 : :
2210 : 7 : netdev_get_etheraddr(ofport->up.netdev, ð->eth_src);
2211 [ - + ]: 7 : if (eth_addr_is_zero(eth->eth_src)) {
2212 [ # # ]: 0 : VLOG_WARN_RL(&rl, "%s port %d: cannot send RSTP BPDU on a port which "
2213 : : "does not have a configured source MAC address.",
2214 : : ofproto->up.name, ofp_to_u16(ofport->up.ofp_port));
2215 : : } else {
2216 : 7 : ofproto_dpif_send_packet(ofport, false, pkt);
2217 : : }
2218 : 7 : dp_packet_delete(pkt);
2219 : 7 : }
2220 : :
2221 : : static void
2222 : 13 : send_bpdu_cb(struct dp_packet *pkt, int port_num, void *ofproto_)
2223 : : {
2224 : 13 : struct ofproto_dpif *ofproto = ofproto_;
2225 : 13 : struct stp_port *sp = stp_get_port(ofproto->stp, port_num);
2226 : : struct ofport_dpif *ofport;
2227 : :
2228 : 13 : ofport = stp_port_get_aux(sp);
2229 [ - + ]: 13 : if (!ofport) {
2230 [ # # ]: 0 : VLOG_WARN_RL(&rl, "%s: cannot send BPDU on unknown port %d",
2231 : : ofproto->up.name, port_num);
2232 : : } else {
2233 : 13 : struct eth_header *eth = dp_packet_l2(pkt);
2234 : :
2235 : 13 : netdev_get_etheraddr(ofport->up.netdev, ð->eth_src);
2236 [ - + ]: 13 : if (eth_addr_is_zero(eth->eth_src)) {
2237 [ # # ]: 0 : VLOG_WARN_RL(&rl, "%s: cannot send BPDU on port %d "
2238 : : "with unknown MAC", ofproto->up.name, port_num);
2239 : : } else {
2240 : 13 : ofproto_dpif_send_packet(ofport, false, pkt);
2241 : : }
2242 : : }
2243 : 13 : dp_packet_delete(pkt);
2244 : 13 : }
2245 : :
2246 : : /* Configure RSTP on 'ofproto_' using the settings defined in 's'. */
2247 : : static void
2248 : 4700 : set_rstp(struct ofproto *ofproto_, const struct ofproto_rstp_settings *s)
2249 : : {
2250 : 4700 : struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
2251 : :
2252 : : /* Only revalidate flows if the configuration changed. */
2253 [ + + ]: 4700 : if (!s != !ofproto->rstp) {
2254 : 2 : ofproto->backer->need_revalidate = REV_RECONFIGURE;
2255 : : }
2256 : :
2257 [ + + ]: 4700 : if (s) {
2258 [ + + ]: 12 : if (!ofproto->rstp) {
2259 : 2 : ofproto->rstp = rstp_create(ofproto_->name, s->address,
2260 : : rstp_send_bpdu_cb, ofproto);
2261 : 2 : ofproto->rstp_last_tick = time_msec();
2262 : : }
2263 : 12 : rstp_set_bridge_address(ofproto->rstp, s->address);
2264 : 12 : rstp_set_bridge_priority(ofproto->rstp, s->priority);
2265 : 12 : rstp_set_bridge_ageing_time(ofproto->rstp, s->ageing_time);
2266 : 12 : rstp_set_bridge_force_protocol_version(ofproto->rstp,
2267 : : s->force_protocol_version);
2268 : 12 : rstp_set_bridge_max_age(ofproto->rstp, s->bridge_max_age);
2269 : 12 : rstp_set_bridge_forward_delay(ofproto->rstp, s->bridge_forward_delay);
2270 : 12 : rstp_set_bridge_transmit_hold_count(ofproto->rstp,
2271 : 12 : s->transmit_hold_count);
2272 : : } else {
2273 : : struct ofport *ofport;
2274 [ + + ][ - + ]: 36575 : HMAP_FOR_EACH (ofport, hmap_node, &ofproto->up.ports) {
2275 : 31887 : set_rstp_port(ofport, NULL);
2276 : : }
2277 : 4688 : rstp_unref(ofproto->rstp);
2278 : 4688 : ofproto->rstp = NULL;
2279 : : }
2280 : 4700 : }
2281 : :
2282 : : static void
2283 : 6579 : get_rstp_status(struct ofproto *ofproto_, struct ofproto_rstp_status *s)
2284 : : {
2285 : 6579 : struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
2286 : :
2287 [ + + ]: 6579 : if (ofproto->rstp) {
2288 : 25 : s->enabled = true;
2289 : 25 : s->root_id = rstp_get_root_id(ofproto->rstp);
2290 : 25 : s->bridge_id = rstp_get_bridge_id(ofproto->rstp);
2291 : 25 : s->designated_id = rstp_get_designated_id(ofproto->rstp);
2292 : 25 : s->root_path_cost = rstp_get_root_path_cost(ofproto->rstp);
2293 : 25 : s->designated_port_id = rstp_get_designated_port_id(ofproto->rstp);
2294 : 25 : s->bridge_port_id = rstp_get_bridge_port_id(ofproto->rstp);
2295 : : } else {
2296 : 6554 : s->enabled = false;
2297 : : }
2298 : 6579 : }
2299 : :
2300 : : static void
2301 : 15 : update_rstp_port_state(struct ofport_dpif *ofport)
2302 : : {
2303 : 15 : struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofport->up.ofproto);
2304 : : enum rstp_state state;
2305 : :
2306 : : /* Figure out new state. */
2307 [ + + ]: 15 : state = ofport->rstp_port ? rstp_port_get_state(ofport->rstp_port)
2308 : : : RSTP_DISABLED;
2309 : :
2310 : : /* Update state. */
2311 [ + + ]: 15 : if (ofport->rstp_state != state) {
2312 : : enum ofputil_port_state of_state;
2313 : : bool fwd_change;
2314 : :
2315 [ + - ]: 6 : VLOG_DBG("port %s: RSTP state changed from %s to %s",
2316 : : netdev_get_name(ofport->up.netdev),
2317 : : rstp_state_name(ofport->rstp_state),
2318 : : rstp_state_name(state));
2319 : :
2320 [ + + ]: 12 : if (rstp_learn_in_state(ofport->rstp_state)
2321 : 6 : != rstp_learn_in_state(state)) {
2322 : : /* XXX: Learning action flows should also be flushed. */
2323 [ + + ]: 4 : if (ofport->bundle) {
2324 [ - + ]: 2 : if (!rstp_shift_root_learned_address(ofproto->rstp)
2325 [ # # ]: 0 : || rstp_get_old_root_aux(ofproto->rstp) != ofport) {
2326 : 2 : bundle_flush_macs(ofport->bundle, false);
2327 : : }
2328 : : }
2329 : : }
2330 : 6 : fwd_change = rstp_forward_in_state(ofport->rstp_state)
2331 : 6 : != rstp_forward_in_state(state);
2332 : :
2333 : 6 : ofproto->backer->need_revalidate = REV_RSTP;
2334 : 6 : ofport->rstp_state = state;
2335 : :
2336 [ + + ][ + + ]: 6 : if (fwd_change && ofport->bundle) {
2337 : 2 : bundle_update(ofport->bundle);
2338 : : }
2339 : :
2340 : : /* Update the RSTP state bits in the OpenFlow port description. */
2341 : 6 : of_state = ofport->up.pp.state & ~OFPUTIL_PS_STP_MASK;
2342 [ + - ][ + + ]: 6 : of_state |= (state == RSTP_LEARNING ? OFPUTIL_PS_STP_LEARN
2343 : : : state == RSTP_FORWARDING ? OFPUTIL_PS_STP_FORWARD
2344 : : : state == RSTP_DISCARDING ? OFPUTIL_PS_STP_LISTEN
2345 : : : 0);
2346 : 6 : ofproto_port_set_state(&ofport->up, of_state);
2347 : : }
2348 : 15 : }
2349 : :
2350 : : static void
2351 : 157605 : rstp_run(struct ofproto_dpif *ofproto)
2352 : : {
2353 [ + + ]: 157605 : if (ofproto->rstp) {
2354 : 186 : long long int now = time_msec();
2355 : 186 : long long int elapsed = now - ofproto->rstp_last_tick;
2356 : : struct rstp_port *rp;
2357 : : struct ofport_dpif *ofport;
2358 : :
2359 : : /* Every second, decrease the values of the timers. */
2360 [ + + ]: 186 : if (elapsed >= 1000) {
2361 : 4 : rstp_tick_timers(ofproto->rstp);
2362 : 4 : ofproto->rstp_last_tick = now;
2363 : : }
2364 : 186 : rp = NULL;
2365 [ + + ]: 190 : while ((ofport = rstp_get_next_changed_port_aux(ofproto->rstp, &rp))) {
2366 : 4 : update_rstp_port_state(ofport);
2367 : : }
2368 : 186 : rp = NULL;
2369 : 186 : ofport = NULL;
2370 : : /* FIXME: This check should be done on-event (i.e., when setting
2371 : : * p->fdb_flush) and not periodically.
2372 : : */
2373 [ + + ]: 188 : while ((ofport = rstp_check_and_reset_fdb_flush(ofproto->rstp, &rp))) {
2374 [ - + ]: 2 : if (!rstp_shift_root_learned_address(ofproto->rstp)
2375 [ # # ]: 0 : || rstp_get_old_root_aux(ofproto->rstp) != ofport) {
2376 : 2 : bundle_flush_macs(ofport->bundle, false);
2377 : : }
2378 : : }
2379 : :
2380 [ - + ]: 186 : if (rstp_shift_root_learned_address(ofproto->rstp)) {
2381 : 0 : struct ofport_dpif *old_root_aux =
2382 : 0 : (struct ofport_dpif *)rstp_get_old_root_aux(ofproto->rstp);
2383 : 0 : struct ofport_dpif *new_root_aux =
2384 : 0 : (struct ofport_dpif *)rstp_get_new_root_aux(ofproto->rstp);
2385 [ # # ][ # # ]: 0 : if (old_root_aux != NULL && new_root_aux != NULL) {
2386 : 0 : bundle_move(old_root_aux->bundle, new_root_aux->bundle);
2387 : 186 : rstp_reset_root_changed(ofproto->rstp);
2388 : : }
2389 : : }
2390 : : }
2391 : 157605 : }
2392 : :
2393 : : /* Configures STP on 'ofproto_' using the settings defined in 's'. */
2394 : : static int
2395 : 4700 : set_stp(struct ofproto *ofproto_, const struct ofproto_stp_settings *s)
2396 : : {
2397 : 4700 : struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
2398 : :
2399 : : /* Only revalidate flows if the configuration changed. */
2400 [ + + ]: 4700 : if (!s != !ofproto->stp) {
2401 : 2 : ofproto->backer->need_revalidate = REV_RECONFIGURE;
2402 : : }
2403 : :
2404 [ + + ]: 4700 : if (s) {
2405 [ + + ]: 10 : if (!ofproto->stp) {
2406 : 2 : ofproto->stp = stp_create(ofproto_->name, s->system_id,
2407 : : send_bpdu_cb, ofproto);
2408 : 2 : ofproto->stp_last_tick = time_msec();
2409 : : }
2410 : :
2411 : 10 : stp_set_bridge_id(ofproto->stp, s->system_id);
2412 : 10 : stp_set_bridge_priority(ofproto->stp, s->priority);
2413 : 10 : stp_set_hello_time(ofproto->stp, s->hello_time);
2414 : 10 : stp_set_max_age(ofproto->stp, s->max_age);
2415 : 10 : stp_set_forward_delay(ofproto->stp, s->fwd_delay);
2416 : : } else {
2417 : : struct ofport *ofport;
2418 : :
2419 [ + + ][ - + ]: 36587 : HMAP_FOR_EACH (ofport, hmap_node, &ofproto->up.ports) {
2420 : 31897 : set_stp_port(ofport, NULL);
2421 : : }
2422 : :
2423 : 4690 : stp_unref(ofproto->stp);
2424 : 4690 : ofproto->stp = NULL;
2425 : : }
2426 : :
2427 : 4700 : return 0;
2428 : : }
2429 : :
2430 : : static int
2431 : 6579 : get_stp_status(struct ofproto *ofproto_, struct ofproto_stp_status *s)
2432 : : {
2433 : 6579 : struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
2434 : :
2435 [ + + ]: 6579 : if (ofproto->stp) {
2436 : 38 : s->enabled = true;
2437 : 38 : s->bridge_id = stp_get_bridge_id(ofproto->stp);
2438 : 38 : s->designated_root = stp_get_designated_root(ofproto->stp);
2439 : 38 : s->root_path_cost = stp_get_root_path_cost(ofproto->stp);
2440 : : } else {
2441 : 6541 : s->enabled = false;
2442 : : }
2443 : :
2444 : 6579 : return 0;
2445 : : }
2446 : :
2447 : : static void
2448 : 14 : update_stp_port_state(struct ofport_dpif *ofport)
2449 : : {
2450 : 14 : struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofport->up.ofproto);
2451 : : enum stp_state state;
2452 : :
2453 : : /* Figure out new state. */
2454 [ + + ]: 14 : state = ofport->stp_port ? stp_port_get_state(ofport->stp_port)
2455 : : : STP_DISABLED;
2456 : :
2457 : : /* Update state. */
2458 [ + + ]: 14 : if (ofport->stp_state != state) {
2459 : : enum ofputil_port_state of_state;
2460 : : bool fwd_change;
2461 : :
2462 [ + - ]: 8 : VLOG_DBG("port %s: STP state changed from %s to %s",
2463 : : netdev_get_name(ofport->up.netdev),
2464 : : stp_state_name(ofport->stp_state),
2465 : : stp_state_name(state));
2466 [ + + ]: 16 : if (stp_learn_in_state(ofport->stp_state)
2467 : 8 : != stp_learn_in_state(state)) {
2468 : : /* xxx Learning action flows should also be flushed. */
2469 : 4 : ovs_rwlock_wrlock(&ofproto->ml->rwlock);
2470 : 4 : mac_learning_flush(ofproto->ml);
2471 : 4 : ovs_rwlock_unlock(&ofproto->ml->rwlock);
2472 : 4 : mcast_snooping_mdb_flush(ofproto->ms);
2473 : : }
2474 : 8 : fwd_change = stp_forward_in_state(ofport->stp_state)
2475 : 8 : != stp_forward_in_state(state);
2476 : :
2477 : 8 : ofproto->backer->need_revalidate = REV_STP;
2478 : 8 : ofport->stp_state = state;
2479 : 8 : ofport->stp_state_entered = time_msec();
2480 : :
2481 [ + + ][ + + ]: 8 : if (fwd_change && ofport->bundle) {
2482 : 2 : bundle_update(ofport->bundle);
2483 : : }
2484 : :
2485 : : /* Update the STP state bits in the OpenFlow port description. */
2486 : 8 : of_state = ofport->up.pp.state & ~OFPUTIL_PS_STP_MASK;
2487 [ + + ][ + + ]: 8 : of_state |= (state == STP_LISTENING ? OFPUTIL_PS_STP_LISTEN
[ + + ][ - + ]
2488 : : : state == STP_LEARNING ? OFPUTIL_PS_STP_LEARN
2489 : : : state == STP_FORWARDING ? OFPUTIL_PS_STP_FORWARD
2490 : : : state == STP_BLOCKING ? OFPUTIL_PS_STP_BLOCK
2491 : : : 0);
2492 : 8 : ofproto_port_set_state(&ofport->up, of_state);
2493 : : }
2494 : 14 : }
2495 : :
2496 : : /* Configures STP on 'ofport_' using the settings defined in 's'. The
2497 : : * caller is responsible for assigning STP port numbers and ensuring
2498 : : * there are no duplicates. */
2499 : : static int
2500 : 34605 : set_stp_port(struct ofport *ofport_,
2501 : : const struct ofproto_port_stp_settings *s)
2502 : : {
2503 : 34605 : struct ofport_dpif *ofport = ofport_dpif_cast(ofport_);
2504 : 34605 : struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofport->up.ofproto);
2505 : 34605 : struct stp_port *sp = ofport->stp_port;
2506 : :
2507 [ + + ][ + + ]: 34605 : if (!s || !s->enable) {
2508 [ + + ]: 34599 : if (sp) {
2509 : 2 : ofport->stp_port = NULL;
2510 : 2 : stp_port_disable(sp);
2511 : 2 : update_stp_port_state(ofport);
2512 : : }
2513 : 34599 : return 0;
2514 [ + + ][ - + ]: 6 : } else if (sp && stp_port_no(sp) != s->port_num
2515 [ # # ]: 0 : && ofport == stp_port_get_aux(sp)) {
2516 : : /* The port-id changed, so disable the old one if it's not
2517 : : * already in use by another port. */
2518 : 0 : stp_port_disable(sp);
2519 : : }
2520 : :
2521 : 6 : sp = ofport->stp_port = stp_get_port(ofproto->stp, s->port_num);
2522 : :
2523 : : /* Set name before enabling the port so that debugging messages can print
2524 : : * the name. */
2525 : 6 : stp_port_set_name(sp, netdev_get_name(ofport->up.netdev));
2526 : 6 : stp_port_enable(sp);
2527 : :
2528 : 6 : stp_port_set_aux(sp, ofport);
2529 : 6 : stp_port_set_priority(sp, s->priority);
2530 : 6 : stp_port_set_path_cost(sp, s->path_cost);
2531 : :
2532 : 6 : update_stp_port_state(ofport);
2533 : :
2534 : 6 : return 0;
2535 : : }
2536 : :
2537 : : static int
2538 : 36256 : get_stp_port_status(struct ofport *ofport_,
2539 : : struct ofproto_port_stp_status *s)
2540 : : {
2541 : 36256 : struct ofport_dpif *ofport = ofport_dpif_cast(ofport_);
2542 : 36256 : struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofport->up.ofproto);
2543 : 36256 : struct stp_port *sp = ofport->stp_port;
2544 : :
2545 [ + + ][ + + ]: 36256 : if (!ofproto->stp || !sp) {
2546 : 36222 : s->enabled = false;
2547 : 36222 : return 0;
2548 : : }
2549 : :
2550 : 34 : s->enabled = true;
2551 : 34 : s->port_id = stp_port_get_id(sp);
2552 : 34 : s->state = stp_port_get_state(sp);
2553 : 34 : s->sec_in_state = (time_msec() - ofport->stp_state_entered) / 1000;
2554 : 34 : s->role = stp_port_get_role(sp);
2555 : :
2556 : 34 : return 0;
2557 : : }
2558 : :
2559 : : static int
2560 : 5240 : get_stp_port_stats(struct ofport *ofport_,
2561 : : struct ofproto_port_stp_stats *s)
2562 : : {
2563 : 5240 : struct ofport_dpif *ofport = ofport_dpif_cast(ofport_);
2564 : 5240 : struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofport->up.ofproto);
2565 : 5240 : struct stp_port *sp = ofport->stp_port;
2566 : :
2567 [ + + ][ + + ]: 5240 : if (!ofproto->stp || !sp) {
2568 : 5230 : s->enabled = false;
2569 : 5230 : return 0;
2570 : : }
2571 : :
2572 : 10 : s->enabled = true;
2573 : 10 : stp_port_get_counts(sp, &s->tx_count, &s->rx_count, &s->error_count);
2574 : :
2575 : 10 : return 0;
2576 : : }
2577 : :
2578 : : static void
2579 : 157605 : stp_run(struct ofproto_dpif *ofproto)
2580 : : {
2581 [ + + ]: 157605 : if (ofproto->stp) {
2582 : 244 : long long int now = time_msec();
2583 : 244 : long long int elapsed = now - ofproto->stp_last_tick;
2584 : : struct stp_port *sp;
2585 : :
2586 [ + + ]: 244 : if (elapsed > 0) {
2587 : 62 : stp_tick(ofproto->stp, MIN(INT_MAX, elapsed));
2588 : 62 : ofproto->stp_last_tick = now;
2589 : : }
2590 [ + + ]: 250 : while (stp_get_changed_port(ofproto->stp, &sp)) {
2591 : 6 : struct ofport_dpif *ofport = stp_port_get_aux(sp);
2592 : :
2593 [ + - ]: 6 : if (ofport) {
2594 : 6 : update_stp_port_state(ofport);
2595 : : }
2596 : : }
2597 : :
2598 [ + + ]: 244 : if (stp_check_and_reset_fdb_flush(ofproto->stp)) {
2599 : 3 : ovs_rwlock_wrlock(&ofproto->ml->rwlock);
2600 : 3 : mac_learning_flush(ofproto->ml);
2601 : 3 : ovs_rwlock_unlock(&ofproto->ml->rwlock);
2602 : 244 : mcast_snooping_mdb_flush(ofproto->ms);
2603 : : }
2604 : : }
2605 : 157605 : }
2606 : :
2607 : : static void
2608 : 153567 : stp_wait(struct ofproto_dpif *ofproto)
2609 : : {
2610 [ + + ]: 153567 : if (ofproto->stp) {
2611 : 236 : poll_timer_wait(1000);
2612 : : }
2613 : 153567 : }
2614 : :
2615 : : /* Configures RSTP on 'ofport_' using the settings defined in 's'. The
2616 : : * caller is responsible for assigning RSTP port numbers and ensuring
2617 : : * there are no duplicates. */
2618 : : static void
2619 : 37294 : set_rstp_port(struct ofport *ofport_,
2620 : : const struct ofproto_port_rstp_settings *s)
2621 : : {
2622 : 37294 : struct ofport_dpif *ofport = ofport_dpif_cast(ofport_);
2623 : 37294 : struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofport->up.ofproto);
2624 : 37294 : struct rstp_port *rp = ofport->rstp_port;
2625 : :
2626 [ + + ][ + + ]: 37294 : if (!s || !s->enable) {
2627 [ + + ]: 37285 : if (rp) {
2628 : 2 : rstp_port_set_aux(rp, NULL);
2629 : 2 : rstp_port_set_state(rp, RSTP_DISABLED);
2630 : 2 : rstp_port_set_mac_operational(rp, false);
2631 : 2 : ofport->rstp_port = NULL;
2632 : 2 : rstp_port_unref(rp);
2633 : 2 : update_rstp_port_state(ofport);
2634 : : }
2635 : 37285 : return;
2636 : : }
2637 : :
2638 : : /* Check if need to add a new port. */
2639 [ + + ]: 9 : if (!rp) {
2640 : 2 : rp = ofport->rstp_port = rstp_add_port(ofproto->rstp);
2641 : : }
2642 : :
2643 : 9 : rstp_port_set(rp, s->port_num, s->priority, s->path_cost,
2644 : 18 : s->admin_edge_port, s->auto_edge,
2645 : 27 : s->admin_p2p_mac_state, s->admin_port_state, s->mcheck,
2646 : : ofport);
2647 : 9 : update_rstp_port_state(ofport);
2648 : : /* Synchronize operational status. */
2649 : 9 : rstp_port_set_mac_operational(rp, ofport->may_enable);
2650 : : }
2651 : :
2652 : : static void
2653 : 36256 : get_rstp_port_status(struct ofport *ofport_,
2654 : : struct ofproto_port_rstp_status *s)
2655 : : {
2656 : 36256 : struct ofport_dpif *ofport = ofport_dpif_cast(ofport_);
2657 : 36256 : struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofport->up.ofproto);
2658 : 36256 : struct rstp_port *rp = ofport->rstp_port;
2659 : :
2660 [ + + ][ + + ]: 36256 : if (!ofproto->rstp || !rp) {
2661 : 36234 : s->enabled = false;
2662 : 36234 : return;
2663 : : }
2664 : :
2665 : 22 : s->enabled = true;
2666 : 22 : rstp_port_get_status(rp, &s->port_id, &s->state, &s->role,
2667 : : &s->designated_bridge_id, &s->designated_port_id,
2668 : : &s->designated_path_cost, &s->tx_count,
2669 : : &s->rx_count, &s->error_count, &s->uptime);
2670 : : }
2671 : :
2672 : :
2673 : : static int
2674 : 31837 : set_queues(struct ofport *ofport_, const struct ofproto_port_queue *qdscp,
2675 : : size_t n_qdscp)
2676 : : {
2677 : 31837 : struct ofport_dpif *ofport = ofport_dpif_cast(ofport_);
2678 : 31837 : struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofport->up.ofproto);
2679 : :
2680 [ + + ]: 31837 : if (ofport->n_qdscp != n_qdscp
2681 [ - + ][ # # ]: 31836 : || (n_qdscp && memcmp(ofport->qdscp, qdscp,
2682 : : n_qdscp * sizeof *qdscp))) {
2683 : 1 : ofproto->backer->need_revalidate = REV_RECONFIGURE;
2684 : 1 : free(ofport->qdscp);
2685 : 1 : ofport->qdscp = n_qdscp
2686 : 1 : ? xmemdup(qdscp, n_qdscp * sizeof *qdscp)
2687 [ + - ]: 1 : : NULL;
2688 : 1 : ofport->n_qdscp = n_qdscp;
2689 : : }
2690 : :
2691 : 31837 : return 0;
2692 : : }
2693 : :
2694 : : /* Bundles. */
2695 : :
2696 : : /* Expires all MAC learning entries associated with 'bundle' and forces its
2697 : : * ofproto to revalidate every flow.
2698 : : *
2699 : : * Normally MAC learning entries are removed only from the ofproto associated
2700 : : * with 'bundle', but if 'all_ofprotos' is true, then the MAC learning entries
2701 : : * are removed from every ofproto. When patch ports and SLB bonds are in use
2702 : : * and a VM migration happens and the gratuitous ARPs are somehow lost, this
2703 : : * avoids a MAC_ENTRY_IDLE_TIME delay before the migrated VM can communicate
2704 : : * with the host from which it migrated. */
2705 : : static void
2706 : 2687 : bundle_flush_macs(struct ofbundle *bundle, bool all_ofprotos)
2707 : : {
2708 : 2687 : struct ofproto_dpif *ofproto = bundle->ofproto;
2709 : 2687 : struct mac_learning *ml = ofproto->ml;
2710 : : struct mac_entry *mac, *next_mac;
2711 : :
2712 : 2687 : ofproto->backer->need_revalidate = REV_RECONFIGURE;
2713 : 2687 : ovs_rwlock_wrlock(&ml->rwlock);
2714 [ + + ][ + + ]: 3865 : LIST_FOR_EACH_SAFE (mac, next_mac, lru_node, &ml->lrus) {
2715 [ + + ]: 1178 : if (mac_entry_get_port(ml, mac) == bundle) {
2716 [ + - ]: 508 : if (all_ofprotos) {
2717 : : struct ofproto_dpif *o;
2718 : :
2719 [ + + ][ - + ]: 1217 : HMAP_FOR_EACH (o, all_ofproto_dpifs_node, &all_ofproto_dpifs) {
2720 [ + + ]: 709 : if (o != ofproto) {
2721 : : struct mac_entry *e;
2722 : :
2723 : 201 : ovs_rwlock_wrlock(&o->ml->rwlock);
2724 : 201 : e = mac_learning_lookup(o->ml, mac->mac, mac->vlan);
2725 [ + + ]: 201 : if (e) {
2726 : 117 : mac_learning_expire(o->ml, e);
2727 : : }
2728 : 201 : ovs_rwlock_unlock(&o->ml->rwlock);
2729 : : }
2730 : : }
2731 : : }
2732 : :
2733 : 508 : mac_learning_expire(ml, mac);
2734 : : }
2735 : : }
2736 : 2687 : ovs_rwlock_unlock(&ml->rwlock);
2737 : 2687 : }
2738 : :
2739 : : static void
2740 : 0 : bundle_move(struct ofbundle *old, struct ofbundle *new)
2741 : : {
2742 : 0 : struct ofproto_dpif *ofproto = old->ofproto;
2743 : 0 : struct mac_learning *ml = ofproto->ml;
2744 : : struct mac_entry *mac, *next_mac;
2745 : :
2746 [ # # ]: 0 : ovs_assert(new->ofproto == old->ofproto);
2747 : :
2748 : 0 : ofproto->backer->need_revalidate = REV_RECONFIGURE;
2749 : 0 : ovs_rwlock_wrlock(&ml->rwlock);
2750 [ # # ][ # # ]: 0 : LIST_FOR_EACH_SAFE (mac, next_mac, lru_node, &ml->lrus) {
2751 [ # # ]: 0 : if (mac_entry_get_port(ml, mac) == old) {
2752 : 0 : mac_entry_set_port(ml, mac, new);
2753 : : }
2754 : : }
2755 : 0 : ovs_rwlock_unlock(&ml->rwlock);
2756 : 0 : }
2757 : :
2758 : : static struct ofbundle *
2759 : 34643 : bundle_lookup(const struct ofproto_dpif *ofproto, void *aux)
2760 : : {
2761 : : struct ofbundle *bundle;
2762 : :
2763 [ + + ][ - + ]: 56565 : HMAP_FOR_EACH_IN_BUCKET (bundle, hmap_node, hash_pointer(aux, 0),
2764 : : &ofproto->bundles) {
2765 [ + + ]: 53624 : if (bundle->aux == aux) {
2766 : 31702 : return bundle;
2767 : : }
2768 : : }
2769 : 2941 : return NULL;
2770 : : }
2771 : :
2772 : : static void
2773 : 2696 : bundle_update(struct ofbundle *bundle)
2774 : : {
2775 : : struct ofport_dpif *port;
2776 : :
2777 : 2696 : bundle->floodable = true;
2778 [ + + ]: 2726 : LIST_FOR_EACH (port, bundle_node, &bundle->ports) {
2779 [ + + ]: 32 : if (port->up.pp.config & OFPUTIL_PC_NO_FLOOD
2780 [ + - ]: 30 : || port->is_layer3
2781 [ + + ][ + - ]: 30 : || (bundle->ofproto->stp && !stp_forward_in_state(port->stp_state))
2782 [ + + ][ - + ]: 30 : || (bundle->ofproto->rstp && !rstp_forward_in_state(port->rstp_state))) {
2783 : 2 : bundle->floodable = false;
2784 : 2 : break;
2785 : : }
2786 : : }
2787 : 2696 : }
2788 : :
2789 : : static void
2790 : 2689 : bundle_del_port(struct ofport_dpif *port)
2791 : : {
2792 : 2689 : struct ofbundle *bundle = port->bundle;
2793 : :
2794 : 2689 : bundle->ofproto->backer->need_revalidate = REV_RECONFIGURE;
2795 : :
2796 : 2689 : ovs_list_remove(&port->bundle_node);
2797 : 2689 : port->bundle = NULL;
2798 : :
2799 [ + + ]: 2689 : if (bundle->lacp) {
2800 : 27 : lacp_slave_unregister(bundle->lacp, port);
2801 : : }
2802 [ + + ]: 2689 : if (bundle->bond) {
2803 : 41 : bond_slave_unregister(bundle->bond, port);
2804 : : }
2805 : :
2806 : 2689 : bundle_update(bundle);
2807 : 2689 : }
2808 : :
2809 : : static bool
2810 : 31837 : bundle_add_port(struct ofbundle *bundle, ofp_port_t ofp_port,
2811 : : struct lacp_slave_settings *lacp)
2812 : : {
2813 : : struct ofport_dpif *port;
2814 : :
2815 : 31837 : port = ofp_port_to_ofport(bundle->ofproto, ofp_port);
2816 [ - + ]: 31837 : if (!port) {
2817 : 0 : return false;
2818 : : }
2819 : :
2820 [ + + ]: 31837 : if (port->bundle != bundle) {
2821 : 2689 : bundle->ofproto->backer->need_revalidate = REV_RECONFIGURE;
2822 [ - + ]: 2689 : if (port->bundle) {
2823 : 0 : bundle_remove(&port->up);
2824 : : }
2825 : :
2826 : 2689 : port->bundle = bundle;
2827 : 2689 : ovs_list_push_back(&bundle->ports, &port->bundle_node);
2828 [ + - ]: 2689 : if (port->up.pp.config & OFPUTIL_PC_NO_FLOOD
2829 [ + + ]: 2689 : || port->is_layer3
2830 [ + + ][ - + ]: 2687 : || (bundle->ofproto->stp && !stp_forward_in_state(port->stp_state))
2831 [ + + ][ + - ]: 2683 : || (bundle->ofproto->rstp && !rstp_forward_in_state(port->rstp_state))) {
2832 : 8 : bundle->floodable = false;
2833 : : }
2834 : : }
2835 [ + + ]: 31837 : if (lacp) {
2836 : 41 : bundle->ofproto->backer->need_revalidate = REV_RECONFIGURE;
2837 : 41 : lacp_slave_register(bundle->lacp, port, lacp);
2838 : : }
2839 : :
2840 : 31837 : return true;
2841 : : }
2842 : :
2843 : : static void
2844 : 2935 : bundle_destroy(struct ofbundle *bundle)
2845 : : {
2846 : : struct ofproto_dpif *ofproto;
2847 : : struct ofport_dpif *port, *next_port;
2848 : :
2849 [ + + ]: 2935 : if (!bundle) {
2850 : 268 : return;
2851 : : }
2852 : :
2853 : 2667 : ofproto = bundle->ofproto;
2854 : 2667 : mbridge_unregister_bundle(ofproto->mbridge, bundle);
2855 : :
2856 : 2667 : xlate_txn_start();
2857 : 2667 : xlate_bundle_remove(bundle);
2858 : 2667 : xlate_txn_commit();
2859 : :
2860 [ + + ][ + + ]: 5088 : LIST_FOR_EACH_SAFE (port, next_port, bundle_node, &bundle->ports) {
2861 : 2421 : bundle_del_port(port);
2862 : : }
2863 : :
2864 : 2667 : bundle_flush_macs(bundle, true);
2865 : 2667 : hmap_remove(&ofproto->bundles, &bundle->hmap_node);
2866 : 2667 : free(bundle->name);
2867 : 2667 : free(bundle->trunks);
2868 : 2667 : lacp_unref(bundle->lacp);
2869 : 2667 : bond_unref(bundle->bond);
2870 : 2667 : free(bundle);
2871 : : }
2872 : :
2873 : : static int
2874 : 34469 : bundle_set(struct ofproto *ofproto_, void *aux,
2875 : : const struct ofproto_bundle_settings *s)
2876 : : {
2877 : 34469 : struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
2878 : 34469 : bool need_flush = false;
2879 : : struct ofport_dpif *port;
2880 : : struct ofbundle *bundle;
2881 : : unsigned long *trunks;
2882 : : int vlan;
2883 : : size_t i;
2884 : : bool ok;
2885 : :
2886 [ + + ]: 34469 : if (!s) {
2887 : 2667 : bundle_destroy(bundle_lookup(ofproto, aux));
2888 : 2667 : return 0;
2889 : : }
2890 : :
2891 [ + + ][ - + ]: 31802 : ovs_assert(s->n_slaves == 1 || s->bond != NULL);
2892 [ - + ]: 31802 : ovs_assert((s->lacp != NULL) == (s->lacp_slaves != NULL));
2893 : :
2894 : 31802 : bundle = bundle_lookup(ofproto, aux);
2895 [ + + ]: 31802 : if (!bundle) {
2896 : 2667 : bundle = xmalloc(sizeof *bundle);
2897 : :
2898 : 2667 : bundle->ofproto = ofproto;
2899 : 2667 : hmap_insert(&ofproto->bundles, &bundle->hmap_node,
2900 : : hash_pointer(aux, 0));
2901 : 2667 : bundle->aux = aux;
2902 : 2667 : bundle->name = NULL;
2903 : :
2904 : 2667 : ovs_list_init(&bundle->ports);
2905 : 2667 : bundle->vlan_mode = PORT_VLAN_TRUNK;
2906 : 2667 : bundle->vlan = -1;
2907 : 2667 : bundle->trunks = NULL;
2908 : 2667 : bundle->use_priority_tags = s->use_priority_tags;
2909 : 2667 : bundle->lacp = NULL;
2910 : 2667 : bundle->bond = NULL;
2911 : :
2912 : 2667 : bundle->floodable = true;
2913 : 2667 : mbridge_register_bundle(ofproto->mbridge, bundle);
2914 : : }
2915 : :
2916 [ + + ][ - + ]: 31802 : if (!bundle->name || strcmp(s->name, bundle->name)) {
2917 : 2667 : free(bundle->name);
2918 : 2667 : bundle->name = xstrdup(s->name);
2919 : : }
2920 : :
2921 : : /* LACP. */
2922 [ + + ]: 31802 : if (s->lacp) {
2923 : 20 : ofproto->lacp_enabled = true;
2924 [ + + ]: 20 : if (!bundle->lacp) {
2925 : 13 : ofproto->backer->need_revalidate = REV_RECONFIGURE;
2926 : 13 : bundle->lacp = lacp_create();
2927 : : }
2928 : 20 : lacp_configure(bundle->lacp, s->lacp);
2929 : : } else {
2930 : 31782 : lacp_unref(bundle->lacp);
2931 : 31782 : bundle->lacp = NULL;
2932 : : }
2933 : :
2934 : : /* Update set of ports. */
2935 : 31802 : ok = true;
2936 [ + + ]: 63639 : for (i = 0; i < s->n_slaves; i++) {
2937 [ + + ][ - + ]: 31837 : if (!bundle_add_port(bundle, s->slaves[i],
2938 : 31878 : s->lacp ? &s->lacp_slaves[i] : NULL)) {
2939 : 0 : ok = false;
2940 : : }
2941 : : }
2942 [ + - ][ - + ]: 31802 : if (!ok || ovs_list_size(&bundle->ports) != s->n_slaves) {
2943 : : struct ofport_dpif *next_port;
2944 : :
2945 [ # # ][ # # ]: 0 : LIST_FOR_EACH_SAFE (port, next_port, bundle_node, &bundle->ports) {
2946 [ # # ]: 0 : for (i = 0; i < s->n_slaves; i++) {
2947 [ # # ]: 0 : if (s->slaves[i] == port->up.ofp_port) {
2948 : 0 : goto found;
2949 : : }
2950 : : }
2951 : :
2952 : 0 : bundle_del_port(port);
2953 : : found: ;
2954 : : }
2955 : : }
2956 [ - + ]: 31802 : ovs_assert(ovs_list_size(&bundle->ports) <= s->n_slaves);
2957 : :
2958 [ - + ]: 31802 : if (ovs_list_is_empty(&bundle->ports)) {
2959 : 0 : bundle_destroy(bundle);
2960 : 0 : return EINVAL;
2961 : : }
2962 : :
2963 : : /* Set VLAN tagging mode */
2964 [ + + ]: 31802 : if (s->vlan_mode != bundle->vlan_mode
2965 [ - + ]: 31787 : || s->use_priority_tags != bundle->use_priority_tags) {
2966 : 15 : bundle->vlan_mode = s->vlan_mode;
2967 : 15 : bundle->use_priority_tags = s->use_priority_tags;
2968 : 15 : need_flush = true;
2969 : : }
2970 : :
2971 : : /* Set VLAN tag. */
2972 : 63604 : vlan = (s->vlan_mode == PORT_VLAN_TRUNK ? -1
2973 [ + + ][ + - ]: 31832 : : s->vlan >= 0 && s->vlan <= 4095 ? s->vlan
2974 [ + - ]: 30 : : 0);
2975 [ + + ]: 31802 : if (vlan != bundle->vlan) {
2976 : 15 : bundle->vlan = vlan;
2977 : 15 : need_flush = true;
2978 : : }
2979 : :
2980 : : /* Get trunked VLANs. */
2981 [ + + + - ]: 31802 : switch (s->vlan_mode) {
2982 : : case PORT_VLAN_ACCESS:
2983 : 11 : trunks = NULL;
2984 : 11 : break;
2985 : :
2986 : : case PORT_VLAN_TRUNK:
2987 : 31787 : trunks = CONST_CAST(unsigned long *, s->trunks);
2988 : 31787 : break;
2989 : :
2990 : : case PORT_VLAN_NATIVE_UNTAGGED:
2991 : : case PORT_VLAN_NATIVE_TAGGED:
2992 [ + - ][ + + ]: 4 : if (vlan != 0 && (!s->trunks
2993 [ + - ]: 2 : || !bitmap_is_set(s->trunks, vlan)
2994 [ - + ]: 2 : || bitmap_is_set(s->trunks, 0))) {
2995 : : /* Force trunking the native VLAN and prohibit trunking VLAN 0. */
2996 [ - + ]: 2 : if (s->trunks) {
2997 : 0 : trunks = bitmap_clone(s->trunks, 4096);
2998 : : } else {
2999 : 2 : trunks = bitmap_allocate1(4096);
3000 : : }
3001 : 2 : bitmap_set1(trunks, vlan);
3002 : 2 : bitmap_set0(trunks, 0);
3003 : : } else {
3004 : 2 : trunks = CONST_CAST(unsigned long *, s->trunks);
3005 : : }
3006 : 4 : break;
3007 : :
3008 : : default:
3009 : 0 : OVS_NOT_REACHED();
3010 : : }
3011 [ + + ]: 31802 : if (!vlan_bitmap_equal(trunks, bundle->trunks)) {
3012 : 5 : free(bundle->trunks);
3013 [ + + ]: 5 : if (trunks == s->trunks) {
3014 : 3 : bundle->trunks = vlan_bitmap_clone(trunks);
3015 : : } else {
3016 : 2 : bundle->trunks = trunks;
3017 : 2 : trunks = NULL;
3018 : : }
3019 : 5 : need_flush = true;
3020 : : }
3021 [ - + ]: 31802 : if (trunks != s->trunks) {
3022 : 0 : free(trunks);
3023 : : }
3024 : :
3025 : : /* Bonding. */
3026 [ + + ]: 31802 : if (!ovs_list_is_short(&bundle->ports)) {
3027 : 32 : bundle->ofproto->has_bonded_bundles = true;
3028 [ + + ]: 32 : if (bundle->bond) {
3029 [ - + ]: 13 : if (bond_reconfigure(bundle->bond, s->bond)) {
3030 : 13 : ofproto->backer->need_revalidate = REV_RECONFIGURE;
3031 : : }
3032 : : } else {
3033 : 19 : bundle->bond = bond_create(s->bond, ofproto);
3034 : 19 : ofproto->backer->need_revalidate = REV_RECONFIGURE;
3035 : : }
3036 : :
3037 [ + + ]: 99 : LIST_FOR_EACH (port, bundle_node, &bundle->ports) {
3038 : 67 : bond_slave_register(bundle->bond, port,
3039 : : port->up.ofp_port, port->up.netdev);
3040 : : }
3041 : : } else {
3042 : 31770 : bond_unref(bundle->bond);
3043 : 31770 : bundle->bond = NULL;
3044 : : }
3045 : :
3046 : : /* If we changed something that would affect MAC learning, un-learn
3047 : : * everything on this port and force flow revalidation. */
3048 [ + + ]: 31802 : if (need_flush) {
3049 : 16 : bundle_flush_macs(bundle, false);
3050 : : }
3051 : :
3052 : 31802 : return 0;
3053 : : }
3054 : :
3055 : : static void
3056 : 5660 : bundle_remove(struct ofport *port_)
3057 : : {
3058 : 5660 : struct ofport_dpif *port = ofport_dpif_cast(port_);
3059 : 5660 : struct ofbundle *bundle = port->bundle;
3060 : :
3061 [ + + ]: 5660 : if (bundle) {
3062 : 268 : bundle_del_port(port);
3063 [ + - ]: 268 : if (ovs_list_is_empty(&bundle->ports)) {
3064 : 268 : bundle_destroy(bundle);
3065 [ # # ]: 0 : } else if (ovs_list_is_short(&bundle->ports)) {
3066 : 0 : bond_unref(bundle->bond);
3067 : 0 : bundle->bond = NULL;
3068 : : }
3069 : : }
3070 : 5660 : }
3071 : :
3072 : : static void
3073 : 80 : send_pdu_cb(void *port_, const void *pdu, size_t pdu_size)
3074 : : {
3075 : : static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 10);
3076 : 80 : struct ofport_dpif *port = port_;
3077 : : struct eth_addr ea;
3078 : : int error;
3079 : :
3080 : 80 : error = netdev_get_etheraddr(port->up.netdev, &ea);
3081 [ + - ]: 80 : if (!error) {
3082 : : struct dp_packet packet;
3083 : : void *packet_pdu;
3084 : :
3085 : 80 : dp_packet_init(&packet, 0);
3086 : 80 : packet_pdu = eth_compose(&packet, eth_addr_lacp, ea, ETH_TYPE_LACP,
3087 : : pdu_size);
3088 : 80 : memcpy(packet_pdu, pdu, pdu_size);
3089 : :
3090 : 80 : ofproto_dpif_send_packet(port, false, &packet);
3091 : 80 : dp_packet_uninit(&packet);
3092 : : } else {
3093 [ # # ]: 0 : VLOG_ERR_RL(&rl, "port %s: cannot obtain Ethernet address of iface "
3094 : : "%s (%s)", port->bundle->name,
3095 : : netdev_get_name(port->up.netdev), ovs_strerror(error));
3096 : : }
3097 : 80 : }
3098 : :
3099 : : static void
3100 : 8 : bundle_send_learning_packets(struct ofbundle *bundle)
3101 : : {
3102 : 8 : struct ofproto_dpif *ofproto = bundle->ofproto;
3103 : : int error, n_packets, n_errors;
3104 : : struct mac_entry *e;
3105 : : struct pkt_list {
3106 : : struct ovs_list list_node;
3107 : : struct ofport_dpif *port;
3108 : : struct dp_packet *pkt;
3109 : : } *pkt_node;
3110 : : struct ovs_list packets;
3111 : :
3112 : 8 : ovs_list_init(&packets);
3113 : 8 : ovs_rwlock_rdlock(&ofproto->ml->rwlock);
3114 [ + + ]: 10 : LIST_FOR_EACH (e, lru_node, &ofproto->ml->lrus) {
3115 [ + - ]: 2 : if (mac_entry_get_port(ofproto->ml, e) != bundle) {
3116 : 2 : pkt_node = xmalloc(sizeof *pkt_node);
3117 : 2 : pkt_node->pkt = bond_compose_learning_packet(bundle->bond,
3118 : 2 : e->mac, e->vlan,
3119 : 2 : (void **)&pkt_node->port);
3120 : 2 : ovs_list_push_back(&packets, &pkt_node->list_node);
3121 : : }
3122 : : }
3123 : 8 : ovs_rwlock_unlock(&ofproto->ml->rwlock);
3124 : :
3125 : 8 : error = n_packets = n_errors = 0;
3126 [ + + ]: 10 : LIST_FOR_EACH_POP (pkt_node, list_node, &packets) {
3127 : : int ret;
3128 : :
3129 : 2 : ret = ofproto_dpif_send_packet(pkt_node->port, false, pkt_node->pkt);
3130 : 2 : dp_packet_delete(pkt_node->pkt);
3131 : 2 : free(pkt_node);
3132 [ - + ]: 2 : if (ret) {
3133 : 0 : error = ret;
3134 : 0 : n_errors++;
3135 : : }
3136 : 2 : n_packets++;
3137 : : }
3138 : :
3139 [ - + ]: 8 : if (n_errors) {
3140 : : static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
3141 [ # # ]: 0 : VLOG_WARN_RL(&rl, "bond %s: %d errors sending %d gratuitous learning "
3142 : : "packets, last error was: %s",
3143 : : bundle->name, n_errors, n_packets, ovs_strerror(error));
3144 : : } else {
3145 [ + - ]: 8 : VLOG_DBG("bond %s: sent %d gratuitous learning packets",
3146 : : bundle->name, n_packets);
3147 : : }
3148 : 8 : }
3149 : :
3150 : : static void
3151 : 15523 : bundle_run(struct ofbundle *bundle)
3152 : : {
3153 [ + + ]: 15523 : if (bundle->lacp) {
3154 : 3909 : lacp_run(bundle->lacp, send_pdu_cb);
3155 : : }
3156 [ + + ]: 15523 : if (bundle->bond) {
3157 : : struct ofport_dpif *port;
3158 : :
3159 [ + + ]: 20138 : LIST_FOR_EACH (port, bundle_node, &bundle->ports) {
3160 : 14728 : bond_slave_set_may_enable(bundle->bond, port, port->may_enable);
3161 : : }
3162 : :
3163 [ + + ]: 5410 : if (bond_run(bundle->bond, lacp_status(bundle->lacp))) {
3164 : 44 : bundle->ofproto->backer->need_revalidate = REV_BOND;
3165 : : }
3166 : :
3167 [ + + ]: 5410 : if (bond_should_send_learning_packets(bundle->bond)) {
3168 : 8 : bundle_send_learning_packets(bundle);
3169 : : }
3170 : : }
3171 : 15523 : }
3172 : :
3173 : : static void
3174 : 15495 : bundle_wait(struct ofbundle *bundle)
3175 : : {
3176 [ + + ]: 15495 : if (bundle->lacp) {
3177 : 3902 : lacp_wait(bundle->lacp);
3178 : : }
3179 [ + + ]: 15495 : if (bundle->bond) {
3180 : 5397 : bond_wait(bundle->bond);
3181 : : }
3182 : 15495 : }
3183 : :
3184 : : /* Mirrors. */
3185 : :
3186 : : static int
3187 : 44 : mirror_set__(struct ofproto *ofproto_, void *aux,
3188 : : const struct ofproto_mirror_settings *s)
3189 : : {
3190 : 44 : struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
3191 : : struct ofbundle **srcs, **dsts;
3192 : : int error;
3193 : : size_t i;
3194 : :
3195 [ + + ]: 44 : if (!s) {
3196 : 22 : mirror_destroy(ofproto->mbridge, aux);
3197 : 22 : return 0;
3198 : : }
3199 : :
3200 : 22 : srcs = xmalloc(s->n_srcs * sizeof *srcs);
3201 : 22 : dsts = xmalloc(s->n_dsts * sizeof *dsts);
3202 : :
3203 [ + + ]: 89 : for (i = 0; i < s->n_srcs; i++) {
3204 : 67 : srcs[i] = bundle_lookup(ofproto, s->srcs[i]);
3205 : : }
3206 : :
3207 [ + + ]: 92 : for (i = 0; i < s->n_dsts; i++) {
3208 : 70 : dsts[i] = bundle_lookup(ofproto, s->dsts[i]);
3209 : : }
3210 : :
3211 : 22 : error = mirror_set(ofproto->mbridge, aux, s->name, srcs, s->n_srcs, dsts,
3212 : : s->n_dsts, s->src_vlans,
3213 : : bundle_lookup(ofproto, s->out_bundle),
3214 : 44 : s->snaplen, s->out_vlan);
3215 : 22 : free(srcs);
3216 : 22 : free(dsts);
3217 : 22 : return error;
3218 : : }
3219 : :
3220 : : static int
3221 : 0 : mirror_get_stats__(struct ofproto *ofproto, void *aux,
3222 : : uint64_t *packets, uint64_t *bytes)
3223 : : {
3224 : 0 : return mirror_get_stats(ofproto_dpif_cast(ofproto)->mbridge, aux, packets,
3225 : : bytes);
3226 : : }
3227 : :
3228 : : static int
3229 : 4700 : set_flood_vlans(struct ofproto *ofproto_, unsigned long *flood_vlans)
3230 : : {
3231 : 4700 : struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
3232 : 4700 : ovs_rwlock_wrlock(&ofproto->ml->rwlock);
3233 [ - + ]: 4700 : if (mac_learning_set_flood_vlans(ofproto->ml, flood_vlans)) {
3234 : 0 : mac_learning_flush(ofproto->ml);
3235 : : }
3236 : 4700 : ovs_rwlock_unlock(&ofproto->ml->rwlock);
3237 : 4700 : return 0;
3238 : : }
3239 : :
3240 : : static bool
3241 : 15 : is_mirror_output_bundle(const struct ofproto *ofproto_, void *aux)
3242 : : {
3243 : 15 : struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
3244 : 15 : struct ofbundle *bundle = bundle_lookup(ofproto, aux);
3245 [ + - ][ - + ]: 15 : return bundle && mirror_bundle_out(ofproto->mbridge, bundle) != 0;
3246 : : }
3247 : :
3248 : : static void
3249 : 0 : forward_bpdu_changed(struct ofproto *ofproto_)
3250 : : {
3251 : 0 : struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
3252 : 0 : ofproto->backer->need_revalidate = REV_RECONFIGURE;
3253 : 0 : }
3254 : :
3255 : : static void
3256 : 4700 : set_mac_table_config(struct ofproto *ofproto_, unsigned int idle_time,
3257 : : size_t max_entries)
3258 : : {
3259 : 4700 : struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
3260 : 4700 : ovs_rwlock_wrlock(&ofproto->ml->rwlock);
3261 : 4700 : mac_learning_set_idle_time(ofproto->ml, idle_time);
3262 : 4700 : mac_learning_set_max_entries(ofproto->ml, max_entries);
3263 : 4700 : ovs_rwlock_unlock(&ofproto->ml->rwlock);
3264 : 4700 : }
3265 : :
3266 : : /* Configures multicast snooping on 'ofport' using the settings
3267 : : * defined in 's'. */
3268 : : static int
3269 : 4700 : set_mcast_snooping(struct ofproto *ofproto_,
3270 : : const struct ofproto_mcast_snooping_settings *s)
3271 : : {
3272 : 4700 : struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
3273 : :
3274 : : /* Only revalidate flows if the configuration changed. */
3275 [ - + ]: 4700 : if (!s != !ofproto->ms) {
3276 : 0 : ofproto->backer->need_revalidate = REV_RECONFIGURE;
3277 : : }
3278 : :
3279 [ - + ]: 4700 : if (s) {
3280 [ # # ]: 0 : if (!ofproto->ms) {
3281 : 0 : ofproto->ms = mcast_snooping_create();
3282 : : }
3283 : :
3284 : 0 : ovs_rwlock_wrlock(&ofproto->ms->rwlock);
3285 : 0 : mcast_snooping_set_idle_time(ofproto->ms, s->idle_time);
3286 : 0 : mcast_snooping_set_max_entries(ofproto->ms, s->max_entries);
3287 [ # # ]: 0 : if (mcast_snooping_set_flood_unreg(ofproto->ms, s->flood_unreg)) {
3288 : 0 : ofproto->backer->need_revalidate = REV_RECONFIGURE;
3289 : : }
3290 : 0 : ovs_rwlock_unlock(&ofproto->ms->rwlock);
3291 : : } else {
3292 : 4700 : mcast_snooping_unref(ofproto->ms);
3293 : 4700 : ofproto->ms = NULL;
3294 : : }
3295 : :
3296 : 4700 : return 0;
3297 : : }
3298 : :
3299 : : /* Configures multicast snooping port's flood settings on 'ofproto'. */
3300 : : static int
3301 : 0 : set_mcast_snooping_port(struct ofproto *ofproto_, void *aux,
3302 : : const struct ofproto_mcast_snooping_port_settings *s)
3303 : : {
3304 : 0 : struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
3305 : 0 : struct ofbundle *bundle = bundle_lookup(ofproto, aux);
3306 : :
3307 [ # # ][ # # ]: 0 : if (ofproto->ms && s) {
3308 : 0 : ovs_rwlock_wrlock(&ofproto->ms->rwlock);
3309 : 0 : mcast_snooping_set_port_flood(ofproto->ms, bundle, s->flood);
3310 : 0 : mcast_snooping_set_port_flood_reports(ofproto->ms, bundle,
3311 : 0 : s->flood_reports);
3312 : 0 : ovs_rwlock_unlock(&ofproto->ms->rwlock);
3313 : : }
3314 : 0 : return 0;
3315 : : }
3316 : :
3317 : :
3318 : : /* Ports. */
3319 : :
3320 : : struct ofport_dpif *
3321 : 40604 : ofp_port_to_ofport(const struct ofproto_dpif *ofproto, ofp_port_t ofp_port)
3322 : : {
3323 : 40604 : struct ofport *ofport = ofproto_get_port(&ofproto->up, ofp_port);
3324 [ + + ]: 40604 : return ofport ? ofport_dpif_cast(ofport) : NULL;
3325 : : }
3326 : :
3327 : : static void
3328 : 16635 : ofproto_port_from_dpif_port(struct ofproto_dpif *ofproto,
3329 : : struct ofproto_port *ofproto_port,
3330 : : struct dpif_port *dpif_port)
3331 : : {
3332 : 16635 : ofproto_port->name = dpif_port->name;
3333 : 16635 : ofproto_port->type = dpif_port->type;
3334 : 16635 : ofproto_port->ofp_port = odp_port_to_ofp_port(ofproto, dpif_port->port_no);
3335 : 16635 : }
3336 : :
3337 : : static void
3338 : 5328 : ofport_update_peer(struct ofport_dpif *ofport)
3339 : : {
3340 : : const struct ofproto_dpif *ofproto;
3341 : : struct dpif_backer *backer;
3342 : : char *peer_name;
3343 : :
3344 [ + + ]: 5328 : if (!netdev_vport_is_patch(ofport->up.netdev)) {
3345 : 5004 : return;
3346 : : }
3347 : :
3348 : 324 : backer = ofproto_dpif_cast(ofport->up.ofproto)->backer;
3349 : 324 : backer->need_revalidate = REV_RECONFIGURE;
3350 : :
3351 [ + + ]: 324 : if (ofport->peer) {
3352 : 2 : ofport->peer->peer = NULL;
3353 : 2 : ofport->peer = NULL;
3354 : : }
3355 : :
3356 : 324 : peer_name = netdev_vport_patch_peer(ofport->up.netdev);
3357 [ - + ]: 324 : if (!peer_name) {
3358 : 0 : return;
3359 : : }
3360 : :
3361 [ + + ][ - + ]: 794 : HMAP_FOR_EACH (ofproto, all_ofproto_dpifs_node, &all_ofproto_dpifs) {
3362 : : struct ofport *peer_ofport;
3363 : : struct ofport_dpif *peer;
3364 : : char *peer_peer;
3365 : :
3366 [ - + ]: 631 : if (ofproto->backer != backer) {
3367 : 0 : continue;
3368 : : }
3369 : :
3370 : 631 : peer_ofport = shash_find_data(&ofproto->up.port_by_name, peer_name);
3371 [ + + ]: 631 : if (!peer_ofport) {
3372 : 470 : continue;
3373 : : }
3374 : :
3375 : 161 : peer = ofport_dpif_cast(peer_ofport);
3376 : 161 : peer_peer = netdev_vport_patch_peer(peer->up.netdev);
3377 [ + - ][ + - ]: 161 : if (peer_peer && !strcmp(netdev_get_name(ofport->up.netdev),
3378 : : peer_peer)) {
3379 : 161 : ofport->peer = peer;
3380 : 161 : ofport->peer->peer = ofport;
3381 : : }
3382 : 161 : free(peer_peer);
3383 : :
3384 : 161 : break;
3385 : : }
3386 : 324 : free(peer_name);
3387 : : }
3388 : :
3389 : : static void
3390 : 35828 : port_run(struct ofport_dpif *ofport)
3391 : : {
3392 : 35828 : long long int carrier_seq = netdev_get_carrier_resets(ofport->up.netdev);
3393 : 35828 : bool carrier_changed = carrier_seq != ofport->carrier_seq;
3394 : 35828 : bool enable = netdev_get_carrier(ofport->up.netdev);
3395 : 35828 : bool cfm_enable = false;
3396 : 35828 : bool bfd_enable = false;
3397 : :
3398 : 35828 : ofport->carrier_seq = carrier_seq;
3399 : :
3400 [ + + ]: 35828 : if (ofport->cfm) {
3401 : 90 : int cfm_opup = cfm_get_opup(ofport->cfm);
3402 : :
3403 : 90 : cfm_enable = !cfm_get_fault(ofport->cfm);
3404 : :
3405 [ + + ]: 90 : if (cfm_opup >= 0) {
3406 [ + + ][ + - ]: 73 : cfm_enable = cfm_enable && cfm_opup;
3407 : : }
3408 : : }
3409 : :
3410 [ + + ]: 35828 : if (ofport->bfd) {
3411 : 20186 : bfd_enable = bfd_forwarding(ofport->bfd);
3412 : : }
3413 : :
3414 [ + + ][ + + ]: 35828 : if (ofport->bfd || ofport->cfm) {
3415 [ + - ][ + + ]: 20263 : enable = enable && (cfm_enable || bfd_enable);
[ + + ]
3416 : : }
3417 : :
3418 [ + + ]: 35828 : if (ofport->bundle) {
3419 [ + + ][ + + ]: 35748 : enable = enable && lacp_slave_may_enable(ofport->bundle->lacp, ofport);
3420 [ + + ]: 35748 : if (carrier_changed) {
3421 : 97 : lacp_slave_carrier_changed(ofport->bundle->lacp, ofport);
3422 : : }
3423 : : }
3424 : :
3425 [ + + ]: 35828 : if (ofport->may_enable != enable) {
3426 : 867 : struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofport->up.ofproto);
3427 : :
3428 : 867 : ofproto->backer->need_revalidate = REV_PORT_TOGGLED;
3429 : :
3430 [ + + ]: 867 : if (ofport->rstp_port) {
3431 : 2 : rstp_port_set_mac_operational(ofport->rstp_port, enable);
3432 : : }
3433 : : }
3434 : :
3435 : 35828 : ofport->may_enable = enable;
3436 : 35828 : }
3437 : :
3438 : : static int
3439 : 40308 : port_query_by_name(const struct ofproto *ofproto_, const char *devname,
3440 : : struct ofproto_port *ofproto_port)
3441 : : {
3442 : 40308 : struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
3443 : : struct dpif_port dpif_port;
3444 : : int error;
3445 : :
3446 [ + + ]: 40308 : if (sset_contains(&ofproto->ghost_ports, devname)) {
3447 : 23366 : const char *type = netdev_get_type_from_name(devname);
3448 : :
3449 : : /* We may be called before ofproto->up.port_by_name is populated with
3450 : : * the appropriate ofport. For this reason, we must get the name and
3451 : : * type from the netdev layer directly. */
3452 [ + + ]: 23366 : if (type) {
3453 : : const struct ofport *ofport;
3454 : :
3455 : 23188 : ofport = shash_find_data(&ofproto->up.port_by_name, devname);
3456 [ + + ]: 23188 : ofproto_port->ofp_port = ofport ? ofport->ofp_port : OFPP_NONE;
3457 : 23188 : ofproto_port->name = xstrdup(devname);
3458 : 23188 : ofproto_port->type = xstrdup(type);
3459 : 23188 : return 0;
3460 : : }
3461 : 178 : return ENODEV;
3462 : : }
3463 : :
3464 [ + + ]: 16942 : if (!sset_contains(&ofproto->ports, devname)) {
3465 : 23 : return ENODEV;
3466 : : }
3467 : 16919 : error = dpif_port_query_by_name(ofproto->backer->dpif,
3468 : : devname, &dpif_port);
3469 [ + + ]: 16919 : if (!error) {
3470 : 16635 : ofproto_port_from_dpif_port(ofproto, ofproto_port, &dpif_port);
3471 : : }
3472 : 40308 : return error;
3473 : : }
3474 : :
3475 : : static int
3476 : 2690 : port_add(struct ofproto *ofproto_, struct netdev *netdev)
3477 : : {
3478 : 2690 : struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
3479 : 2690 : const char *devname = netdev_get_name(netdev);
3480 : : char namebuf[NETDEV_VPORT_NAME_BUFSIZE];
3481 : : const char *dp_port_name;
3482 : :
3483 [ + + ]: 2690 : if (netdev_vport_is_patch(netdev)) {
3484 : 322 : sset_add(&ofproto->ghost_ports, netdev_get_name(netdev));
3485 : 322 : return 0;
3486 : : }
3487 : :
3488 : 2368 : dp_port_name = netdev_vport_get_dpif_port(netdev, namebuf, sizeof namebuf);
3489 [ + + ]: 2368 : if (!dpif_port_exists(ofproto->backer->dpif, dp_port_name)) {
3490 : 2134 : odp_port_t port_no = ODPP_NONE;
3491 : : int error;
3492 : :
3493 : 2134 : error = dpif_port_add(ofproto->backer->dpif, netdev, &port_no);
3494 [ - + ]: 2134 : if (error) {
3495 : 0 : return error;
3496 : : }
3497 [ + + ]: 2134 : if (netdev_get_tunnel_config(netdev)) {
3498 : 2134 : simap_put(&ofproto->backer->tnl_backers,
3499 : : dp_port_name, odp_to_u32(port_no));
3500 : : }
3501 : : }
3502 : :
3503 [ + + ]: 2368 : if (netdev_get_tunnel_config(netdev)) {
3504 : 320 : sset_add(&ofproto->ghost_ports, devname);
3505 : : } else {
3506 : 2048 : sset_add(&ofproto->ports, devname);
3507 : : }
3508 : 2690 : return 0;
3509 : : }
3510 : :
3511 : : static int
3512 : 388 : port_del(struct ofproto *ofproto_, ofp_port_t ofp_port)
3513 : : {
3514 : 388 : struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
3515 : 388 : struct ofport_dpif *ofport = ofp_port_to_ofport(ofproto, ofp_port);
3516 : 388 : int error = 0;
3517 : :
3518 [ + + ]: 388 : if (!ofport) {
3519 : 82 : return 0;
3520 : : }
3521 : :
3522 : 306 : sset_find_and_delete(&ofproto->ghost_ports,
3523 : 306 : netdev_get_name(ofport->up.netdev));
3524 : 306 : ofproto->backer->need_revalidate = REV_RECONFIGURE;
3525 [ + + ][ + + ]: 306 : if (!ofport->is_tunnel && !netdev_vport_is_patch(ofport->up.netdev)) {
3526 : 283 : error = dpif_port_del(ofproto->backer->dpif, ofport->odp_port);
3527 [ + - ]: 283 : if (!error) {
3528 : : /* The caller is going to close ofport->up.netdev. If this is a
3529 : : * bonded port, then the bond is using that netdev, so remove it
3530 : : * from the bond. The client will need to reconfigure everything
3531 : : * after deleting ports, so then the slave will get re-added. */
3532 : 283 : bundle_remove(&ofport->up);
3533 : : }
3534 : : }
3535 : 306 : return error;
3536 : : }
3537 : :
3538 : : static int
3539 : 31837 : port_set_config(const struct ofport *ofport_, const struct smap *cfg)
3540 : : {
3541 : 31837 : struct ofport_dpif *ofport = ofport_dpif_cast(ofport_);
3542 : 31837 : struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofport->up.ofproto);
3543 : :
3544 [ + + ]: 31837 : if (sset_contains(&ofproto->ghost_ports,
3545 : 31837 : netdev_get_name(ofport->up.netdev))) {
3546 : 22531 : return 0;
3547 : : }
3548 : :
3549 : 9306 : return dpif_port_set_config(ofproto->backer->dpif, ofport->odp_port, cfg);
3550 : : }
3551 : :
3552 : : static int
3553 : 60 : port_get_stats(const struct ofport *ofport_, struct netdev_stats *stats)
3554 : : {
3555 : 60 : struct ofport_dpif *ofport = ofport_dpif_cast(ofport_);
3556 : : int error;
3557 : :
3558 : 60 : error = netdev_get_stats(ofport->up.netdev, stats);
3559 : :
3560 [ + - ][ + + ]: 60 : if (!error && ofport_->ofp_port == OFPP_LOCAL) {
3561 : 15 : struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofport->up.ofproto);
3562 : :
3563 : 15 : ovs_mutex_lock(&ofproto->stats_mutex);
3564 : : /* ofproto->stats.tx_packets represents packets that we created
3565 : : * internally and sent to some port (e.g. packets sent with
3566 : : * ofproto_dpif_send_packet()). Account for them as if they had
3567 : : * come from OFPP_LOCAL and got forwarded. */
3568 : :
3569 [ + - ]: 15 : if (stats->rx_packets != UINT64_MAX) {
3570 : 15 : stats->rx_packets += ofproto->stats.tx_packets;
3571 : : }
3572 : :
3573 [ + - ]: 15 : if (stats->rx_bytes != UINT64_MAX) {
3574 : 15 : stats->rx_bytes += ofproto->stats.tx_bytes;
3575 : : }
3576 : :
3577 : : /* ofproto->stats.rx_packets represents packets that were received on
3578 : : * some port and we processed internally and dropped (e.g. STP).
3579 : : * Account for them as if they had been forwarded to OFPP_LOCAL. */
3580 : :
3581 [ + - ]: 15 : if (stats->tx_packets != UINT64_MAX) {
3582 : 15 : stats->tx_packets += ofproto->stats.rx_packets;
3583 : : }
3584 : :
3585 [ + - ]: 15 : if (stats->tx_bytes != UINT64_MAX) {
3586 : 15 : stats->tx_bytes += ofproto->stats.rx_bytes;
3587 : : }
3588 : 15 : ovs_mutex_unlock(&ofproto->stats_mutex);
3589 : : }
3590 : :
3591 : 60 : return error;
3592 : : }
3593 : :
3594 : : static int
3595 : 14 : port_get_lacp_stats(const struct ofport *ofport_, struct lacp_slave_stats *stats)
3596 : : {
3597 : 14 : struct ofport_dpif *ofport = ofport_dpif_cast(ofport_);
3598 [ + - ][ + + ]: 14 : if (ofport->bundle && ofport->bundle->lacp) {
3599 [ + - ]: 2 : if (lacp_get_slave_stats(ofport->bundle->lacp, ofport, stats)) {
3600 : 2 : return 0;
3601 : : }
3602 : : }
3603 : 12 : return -1;
3604 : : }
3605 : :
3606 : : struct port_dump_state {
3607 : : struct sset_position pos;
3608 : : bool ghost;
3609 : :
3610 : : struct ofproto_port port;
3611 : : bool has_port;
3612 : : };
3613 : :
3614 : : static int
3615 : 4700 : port_dump_start(const struct ofproto *ofproto_ OVS_UNUSED, void **statep)
3616 : : {
3617 : 4700 : *statep = xzalloc(sizeof(struct port_dump_state));
3618 : 4700 : return 0;
3619 : : }
3620 : :
3621 : : static int
3622 : 38838 : port_dump_next(const struct ofproto *ofproto_, void *state_,
3623 : : struct ofproto_port *port)
3624 : : {
3625 : 38838 : struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
3626 : 38838 : struct port_dump_state *state = state_;
3627 : : const struct sset *sset;
3628 : : struct sset_node *node;
3629 : :
3630 [ + + ]: 38838 : if (state->has_port) {
3631 : 29438 : ofproto_port_destroy(&state->port);
3632 : 29438 : state->has_port = false;
3633 : : }
3634 [ + + ]: 38838 : sset = state->ghost ? &ofproto->ghost_ports : &ofproto->ports;
3635 [ + + ]: 38936 : while ((node = sset_at_position(sset, &state->pos))) {
3636 : : int error;
3637 : :
3638 : 29536 : error = port_query_by_name(ofproto_, node->name, &state->port);
3639 [ + + ]: 29536 : if (!error) {
3640 : 29438 : *port = state->port;
3641 : 29438 : state->has_port = true;
3642 : 29438 : return 0;
3643 [ - + ]: 98 : } else if (error != ENODEV) {
3644 : 0 : return error;
3645 : : }
3646 : : }
3647 : :
3648 [ + + ]: 9400 : if (!state->ghost) {
3649 : 4700 : state->ghost = true;
3650 : 4700 : memset(&state->pos, 0, sizeof state->pos);
3651 : 4700 : return port_dump_next(ofproto_, state_, port);
3652 : : }
3653 : :
3654 : 4700 : return EOF;
3655 : : }
3656 : :
3657 : : static int
3658 : 4700 : port_dump_done(const struct ofproto *ofproto_ OVS_UNUSED, void *state_)
3659 : : {
3660 : 4700 : struct port_dump_state *state = state_;
3661 : :
3662 [ - + ]: 4700 : if (state->has_port) {
3663 : 0 : ofproto_port_destroy(&state->port);
3664 : : }
3665 : 4700 : free(state);
3666 : 4700 : return 0;
3667 : : }
3668 : :
3669 : : static int
3670 : 157606 : port_poll(const struct ofproto *ofproto_, char **devnamep)
3671 : : {
3672 : 157606 : struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
3673 : :
3674 [ - + ]: 157606 : if (ofproto->port_poll_errno) {
3675 : 0 : int error = ofproto->port_poll_errno;
3676 : 0 : ofproto->port_poll_errno = 0;
3677 : 0 : return error;
3678 : : }
3679 : :
3680 [ + + ]: 157606 : if (sset_is_empty(&ofproto->port_poll_set)) {
3681 : 157605 : return EAGAIN;
3682 : : }
3683 : :
3684 : 1 : *devnamep = sset_pop(&ofproto->port_poll_set);
3685 : 1 : return 0;
3686 : : }
3687 : :
3688 : : static void
3689 : 153645 : port_poll_wait(const struct ofproto *ofproto_)
3690 : : {
3691 : 153645 : struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
3692 : 153645 : dpif_port_poll_wait(ofproto->backer->dpif);
3693 : 153645 : }
3694 : :
3695 : : static int
3696 : 36468 : port_is_lacp_current(const struct ofport *ofport_)
3697 : : {
3698 : 36468 : const struct ofport_dpif *ofport = ofport_dpif_cast(ofport_);
3699 [ + + ]: 72936 : return (ofport->bundle && ofport->bundle->lacp
3700 : 145 : ? lacp_slave_is_current(ofport->bundle->lacp, ofport)
3701 [ + - ]: 72936 : : -1);
3702 : : }
3703 : :
3704 : : /* If 'rule' is an OpenFlow rule, that has expired according to OpenFlow rules,
3705 : : * then delete it entirely. */
3706 : : static void
3707 : 374 : rule_expire(struct rule_dpif *rule, long long now)
3708 : : OVS_REQUIRES(ofproto_mutex)
3709 : : {
3710 : : uint16_t hard_timeout, idle_timeout;
3711 : 374 : int reason = -1;
3712 : :
3713 : 374 : hard_timeout = rule->up.hard_timeout;
3714 : 374 : idle_timeout = rule->up.idle_timeout;
3715 : :
3716 : : /* Has 'rule' expired? */
3717 [ + + ]: 374 : if (hard_timeout) {
3718 : : long long int modified;
3719 : :
3720 : 164 : ovs_mutex_lock(&rule->up.mutex);
3721 : 164 : modified = rule->up.modified;
3722 : 164 : ovs_mutex_unlock(&rule->up.mutex);
3723 : :
3724 [ + + ]: 164 : if (now > modified + hard_timeout * 1000) {
3725 : 4 : reason = OFPRR_HARD_TIMEOUT;
3726 : : }
3727 : : }
3728 : :
3729 [ + + ][ + + ]: 374 : if (reason < 0 && idle_timeout) {
3730 : : long long int used;
3731 : :
3732 : 220 : ovs_mutex_lock(&rule->stats_mutex);
3733 : 220 : used = rule->stats.used;
3734 : 220 : ovs_mutex_unlock(&rule->stats_mutex);
3735 : :
3736 [ + + ]: 220 : if (now > used + idle_timeout * 1000) {
3737 : 1 : reason = OFPRR_IDLE_TIMEOUT;
3738 : : }
3739 : : }
3740 : :
3741 [ + + ]: 374 : if (reason >= 0) {
3742 : 5 : COVERAGE_INC(ofproto_dpif_expired);
3743 : 5 : ofproto_rule_expire(&rule->up, reason);
3744 : : }
3745 : 374 : }
3746 : :
3747 : : static void
3748 : 8260 : ofproto_dpif_set_packet_odp_port(const struct ofproto_dpif *ofproto,
3749 : : ofp_port_t in_port, struct dp_packet *packet)
3750 : : {
3751 [ + + ]: 8260 : if (in_port == OFPP_NONE) {
3752 : 6551 : in_port = OFPP_LOCAL;
3753 : : }
3754 : 8260 : packet->md.in_port.odp_port = ofp_port_to_odp_port(ofproto, in_port);
3755 : 8260 : }
3756 : :
3757 : : int
3758 : 8061 : ofproto_dpif_execute_actions__(struct ofproto_dpif *ofproto,
3759 : : const struct flow *flow,
3760 : : struct rule_dpif *rule,
3761 : : const struct ofpact *ofpacts, size_t ofpacts_len,
3762 : : int indentation, int depth, int resubmits,
3763 : : struct dp_packet *packet)
3764 : : {
3765 : : struct dpif_flow_stats stats;
3766 : : struct xlate_out xout;
3767 : : struct xlate_in xin;
3768 : : struct dpif_execute execute;
3769 : : int error;
3770 : :
3771 [ - + ]: 8061 : ovs_assert((rule != NULL) != (ofpacts != NULL));
3772 : :
3773 : 8061 : dpif_flow_stats_extract(flow, packet, time_msec(), &stats);
3774 : :
3775 [ - + ]: 8061 : if (rule) {
3776 : 0 : rule_dpif_credit_stats(rule, &stats);
3777 : : }
3778 : :
3779 : : uint64_t odp_actions_stub[1024 / 8];
3780 : 8061 : struct ofpbuf odp_actions = OFPBUF_STUB_INITIALIZER(odp_actions_stub);
3781 : 8061 : xlate_in_init(&xin, ofproto, flow, flow->in_port.ofp_port, rule,
3782 : 8061 : stats.tcp_flags, packet, NULL, &odp_actions);
3783 : 8061 : xin.ofpacts = ofpacts;
3784 : 8061 : xin.ofpacts_len = ofpacts_len;
3785 : 8061 : xin.resubmit_stats = &stats;
3786 : 8061 : xin.indentation = indentation;
3787 : 8061 : xin.depth = depth;
3788 : 8061 : xin.resubmits = resubmits;
3789 [ - + ]: 8061 : if (xlate_actions(&xin, &xout) != XLATE_OK) {
3790 : 0 : error = EINVAL;
3791 : 0 : goto out;
3792 : : }
3793 : :
3794 : 8061 : execute.actions = odp_actions.data;
3795 : 8061 : execute.actions_len = odp_actions.size;
3796 : :
3797 : 8061 : pkt_metadata_from_flow(&packet->md, flow);
3798 : 8061 : execute.packet = packet;
3799 : 8061 : execute.flow = flow;
3800 : 8061 : execute.needs_help = (xout.slow & SLOW_ACTION) != 0;
3801 : 8061 : execute.probe = false;
3802 : 8061 : execute.mtu = 0;
3803 : :
3804 : : /* Fix up in_port. */
3805 : 8061 : ofproto_dpif_set_packet_odp_port(ofproto, flow->in_port.ofp_port, packet);
3806 : :
3807 : 8061 : error = dpif_execute(ofproto->backer->dpif, &execute);
3808 : : out:
3809 : 8061 : xlate_out_uninit(&xout);
3810 : 8061 : ofpbuf_uninit(&odp_actions);
3811 : :
3812 : 8061 : return error;
3813 : : }
3814 : :
3815 : : /* Executes, within 'ofproto', the actions in 'rule' or 'ofpacts' on 'packet'.
3816 : : * 'flow' must reflect the data in 'packet'. */
3817 : : int
3818 : 8050 : ofproto_dpif_execute_actions(struct ofproto_dpif *ofproto,
3819 : : const struct flow *flow,
3820 : : struct rule_dpif *rule,
3821 : : const struct ofpact *ofpacts, size_t ofpacts_len,
3822 : : struct dp_packet *packet)
3823 : : {
3824 : 8050 : return ofproto_dpif_execute_actions__(ofproto, flow, rule, ofpacts,
3825 : : ofpacts_len, 0, 0, 0, packet);
3826 : : }
3827 : :
3828 : : static void
3829 : 179817 : rule_dpif_credit_stats__(struct rule_dpif *rule,
3830 : : const struct dpif_flow_stats *stats,
3831 : : bool credit_counts)
3832 : : OVS_REQUIRES(rule->stats_mutex)
3833 : : {
3834 [ + - ]: 179817 : if (credit_counts) {
3835 : 179817 : rule->stats.n_packets += stats->n_packets;
3836 : 179817 : rule->stats.n_bytes += stats->n_bytes;
3837 : : }
3838 : 179817 : rule->stats.used = MAX(rule->stats.used, stats->used);
3839 : 179817 : }
3840 : :
3841 : : void
3842 : 179817 : rule_dpif_credit_stats(struct rule_dpif *rule,
3843 : : const struct dpif_flow_stats *stats)
3844 : : {
3845 : 179817 : ovs_mutex_lock(&rule->stats_mutex);
3846 [ - + ]: 179817 : if (OVS_UNLIKELY(rule->new_rule)) {
3847 : 0 : ovs_mutex_lock(&rule->new_rule->stats_mutex);
3848 : 0 : rule_dpif_credit_stats__(rule->new_rule, stats, rule->forward_counts);
3849 : 0 : ovs_mutex_unlock(&rule->new_rule->stats_mutex);
3850 : : } else {
3851 : 179817 : rule_dpif_credit_stats__(rule, stats, true);
3852 : : }
3853 : 179817 : ovs_mutex_unlock(&rule->stats_mutex);
3854 : 179817 : }
3855 : :
3856 : : ovs_be64
3857 : 1286678 : rule_dpif_get_flow_cookie(const struct rule_dpif *rule)
3858 : : OVS_REQUIRES(rule->up.mutex)
3859 : : {
3860 : 1286678 : return rule->up.flow_cookie;
3861 : : }
3862 : :
3863 : : void
3864 : 1 : rule_dpif_reduce_timeouts(struct rule_dpif *rule, uint16_t idle_timeout,
3865 : : uint16_t hard_timeout)
3866 : : {
3867 : 1 : ofproto_rule_reduce_timeouts(&rule->up, idle_timeout, hard_timeout);
3868 : 1 : }
3869 : :
3870 : : /* Returns 'rule''s actions. The returned actions are RCU-protected, and can
3871 : : * be read until the calling thread quiesces. */
3872 : : const struct rule_actions *
3873 : 1294163 : rule_dpif_get_actions(const struct rule_dpif *rule)
3874 : : {
3875 : 1294163 : return rule_get_actions(&rule->up);
3876 : : }
3877 : :
3878 : : /* Sets 'rule''s recirculation id. */
3879 : : static void
3880 : 0 : rule_dpif_set_recirc_id(struct rule_dpif *rule, uint32_t id)
3881 : : OVS_REQUIRES(rule->up.mutex)
3882 : : {
3883 [ # # ][ # # ]: 0 : ovs_assert(!rule->recirc_id || rule->recirc_id == id);
3884 [ # # ]: 0 : if (rule->recirc_id == id) {
3885 : : /* Release the new reference to the same id. */
3886 : 0 : recirc_free_id(id);
3887 : : } else {
3888 : 0 : rule->recirc_id = id;
3889 : : }
3890 : 0 : }
3891 : :
3892 : : /* Sets 'rule''s recirculation id. */
3893 : : void
3894 : 0 : rule_set_recirc_id(struct rule *rule_, uint32_t id)
3895 : : {
3896 : 0 : struct rule_dpif *rule = rule_dpif_cast(rule_);
3897 : :
3898 : 0 : ovs_mutex_lock(&rule->up.mutex);
3899 : 0 : rule_dpif_set_recirc_id(rule, id);
3900 : 0 : ovs_mutex_unlock(&rule->up.mutex);
3901 : 0 : }
3902 : :
3903 : : ovs_version_t
3904 : 124615 : ofproto_dpif_get_tables_version(struct ofproto_dpif *ofproto OVS_UNUSED)
3905 : : {
3906 : : ovs_version_t version;
3907 : :
3908 : 124615 : atomic_read_relaxed(&ofproto->tables_version, &version);
3909 : :
3910 : 124615 : return version;
3911 : : }
3912 : :
3913 : : /* The returned rule (if any) is valid at least until the next RCU quiescent
3914 : : * period. If the rule needs to stay around longer, the caller should take
3915 : : * a reference.
3916 : : *
3917 : : * 'flow' is non-const to allow for temporary modifications during the lookup.
3918 : : * Any changes are restored before returning. */
3919 : : static struct rule_dpif *
3920 : 1293596 : rule_dpif_lookup_in_table(struct ofproto_dpif *ofproto, ovs_version_t version,
3921 : : uint8_t table_id, struct flow *flow,
3922 : : struct flow_wildcards *wc)
3923 : : {
3924 : 1293596 : struct classifier *cls = &ofproto->up.tables[table_id].cls;
3925 : 1293596 : return rule_dpif_cast(rule_from_cls_rule(classifier_lookup(cls, version,
3926 : : flow, wc)));
3927 : : }
3928 : :
3929 : : /* Look up 'flow' in 'ofproto''s classifier version 'version', starting from
3930 : : * table '*table_id'. Returns the rule that was found, which may be one of the
3931 : : * special rules according to packet miss hadling. If 'may_packet_in' is
3932 : : * false, returning of the miss_rule (which issues packet ins for the
3933 : : * controller) is avoided. Updates 'wc', if nonnull, to reflect the fields
3934 : : * that were used during the lookup.
3935 : : *
3936 : : * If 'honor_table_miss' is true, the first lookup occurs in '*table_id', but
3937 : : * if none is found then the table miss configuration for that table is
3938 : : * honored, which can result in additional lookups in other OpenFlow tables.
3939 : : * In this case the function updates '*table_id' to reflect the final OpenFlow
3940 : : * table that was searched.
3941 : : *
3942 : : * If 'honor_table_miss' is false, then only one table lookup occurs, in
3943 : : * '*table_id'.
3944 : : *
3945 : : * The rule is returned in '*rule', which is valid at least until the next
3946 : : * RCU quiescent period. If the '*rule' needs to stay around longer, the
3947 : : * caller must take a reference.
3948 : : *
3949 : : * 'in_port' allows the lookup to take place as if the in port had the value
3950 : : * 'in_port'. This is needed for resubmit action support.
3951 : : *
3952 : : * 'flow' is non-const to allow for temporary modifications during the lookup.
3953 : : * Any changes are restored before returning. */
3954 : : struct rule_dpif *
3955 : 1286781 : rule_dpif_lookup_from_table(struct ofproto_dpif *ofproto,
3956 : : ovs_version_t version, struct flow *flow,
3957 : : struct flow_wildcards *wc,
3958 : : const struct dpif_flow_stats *stats,
3959 : : uint8_t *table_id, ofp_port_t in_port,
3960 : : bool may_packet_in, bool honor_table_miss)
3961 : : {
3962 : 1286781 : ovs_be16 old_tp_src = flow->tp_src, old_tp_dst = flow->tp_dst;
3963 : 1286781 : ofp_port_t old_in_port = flow->in_port.ofp_port;
3964 : : enum ofputil_table_miss miss_config;
3965 : : struct rule_dpif *rule;
3966 : : uint8_t next_id;
3967 : :
3968 : : /* We always unwildcard nw_frag (for IP), so they
3969 : : * need not be unwildcarded here. */
3970 [ + + ]: 1286781 : if (flow->nw_frag & FLOW_NW_FRAG_ANY
3971 [ + + ]: 209 : && ofproto->up.frag_handling != OFPUTIL_FRAG_NX_MATCH) {
3972 [ + + ]: 205 : if (ofproto->up.frag_handling == OFPUTIL_FRAG_NORMAL) {
3973 : : /* We must pretend that transport ports are unavailable. */
3974 : 201 : flow->tp_src = htons(0);
3975 : 201 : flow->tp_dst = htons(0);
3976 : : } else {
3977 : : /* Must be OFPUTIL_FRAG_DROP (we don't have OFPUTIL_FRAG_REASM).
3978 : : * Use the drop_frags_rule (which cannot disappear). */
3979 : 4 : rule = ofproto->drop_frags_rule;
3980 [ + + ]: 4 : if (stats) {
3981 : 2 : struct oftable *tbl = &ofproto->up.tables[*table_id];
3982 : : unsigned long orig;
3983 : :
3984 : 2 : atomic_add_relaxed(&tbl->n_matched, stats->n_packets, &orig);
3985 : : }
3986 : 4 : return rule;
3987 : : }
3988 : : }
3989 : :
3990 : : /* Look up a flow with 'in_port' as the input port. Then restore the
3991 : : * original input port (otherwise OFPP_NORMAL and OFPP_IN_PORT will
3992 : : * have surprising behavior). */
3993 : 1286777 : flow->in_port.ofp_port = in_port;
3994 : :
3995 : : /* Our current implementation depends on n_tables == N_TABLES, and
3996 : : * TBL_INTERNAL being the last table. */
3997 : : BUILD_ASSERT_DECL(N_TABLES == TBL_INTERNAL + 1);
3998 : :
3999 : 1286777 : miss_config = OFPUTIL_TABLE_MISS_CONTINUE;
4000 : :
4001 [ + + ]: 1288817 : for (next_id = *table_id;
4002 : 1288817 : next_id < ofproto->up.n_tables;
4003 : 2040 : next_id++, next_id += (next_id == TBL_INTERNAL))
4004 : : {
4005 : 1288809 : *table_id = next_id;
4006 : 1288809 : rule = rule_dpif_lookup_in_table(ofproto, version, next_id, flow, wc);
4007 [ + + ]: 1288808 : if (stats) {
4008 : 153383 : struct oftable *tbl = &ofproto->up.tables[next_id];
4009 : : unsigned long orig;
4010 : :
4011 [ + + ]: 153383 : atomic_add_relaxed(rule ? &tbl->n_matched : &tbl->n_missed,
4012 : : stats->n_packets, &orig);
4013 : : }
4014 [ + + ]: 1288808 : if (rule) {
4015 : 1279712 : goto out; /* Match. */
4016 : : }
4017 [ + + ]: 9096 : if (honor_table_miss) {
4018 : 5948 : miss_config = ofproto_table_get_miss_config(&ofproto->up,
4019 : 5948 : *table_id);
4020 [ + + ]: 5948 : if (miss_config == OFPUTIL_TABLE_MISS_CONTINUE) {
4021 : 2040 : continue;
4022 : : }
4023 : : }
4024 : 7056 : break;
4025 : : }
4026 : : /* Miss. */
4027 : 7064 : rule = ofproto->no_packet_in_rule;
4028 [ + + ]: 7064 : if (may_packet_in) {
4029 [ + + ]: 3916 : if (miss_config == OFPUTIL_TABLE_MISS_CONTINUE
4030 [ - + ]: 3916 : || miss_config == OFPUTIL_TABLE_MISS_CONTROLLER) {
4031 : : struct ofport_dpif *port;
4032 : :
4033 : 8 : port = ofp_port_to_ofport(ofproto, old_in_port);
4034 [ - + ]: 8 : if (!port) {
4035 [ # # ]: 0 : VLOG_WARN_RL(&rl, "packet-in on unknown OpenFlow port %"PRIu16,
4036 : : old_in_port);
4037 [ + - ]: 8 : } else if (!(port->up.pp.config & OFPUTIL_PC_NO_PACKET_IN)) {
4038 : 8 : rule = ofproto->miss_rule;
4039 : : }
4040 [ + + + + ]: 7812 : } else if (miss_config == OFPUTIL_TABLE_MISS_DEFAULT &&
4041 : 3904 : connmgr_wants_packet_in_on_miss(ofproto->up.connmgr)) {
4042 : 134 : rule = ofproto->miss_rule;
4043 : : }
4044 : : }
4045 : : out:
4046 : : /* Restore port numbers, as they may have been modified above. */
4047 : 1286776 : flow->tp_src = old_tp_src;
4048 : 1286776 : flow->tp_dst = old_tp_dst;
4049 : : /* Restore the old in port. */
4050 : 1286776 : flow->in_port.ofp_port = old_in_port;
4051 : :
4052 : 1286776 : return rule;
4053 : : }
4054 : :
4055 : 1436096 : static struct rule_dpif *rule_dpif_cast(const struct rule *rule)
4056 : : {
4057 : 1436096 : return rule ? CONTAINER_OF(rule, struct rule_dpif, up) : NULL;
4058 : : }
4059 : :
4060 : : static struct rule *
4061 : 32020 : rule_alloc(void)
4062 : : {
4063 : 32020 : struct rule_dpif *rule = xzalloc(sizeof *rule);
4064 : 32020 : return &rule->up;
4065 : : }
4066 : :
4067 : : static void
4068 : 28492 : rule_dealloc(struct rule *rule_)
4069 : : {
4070 : 28492 : struct rule_dpif *rule = rule_dpif_cast(rule_);
4071 : 28492 : free(rule);
4072 : 28492 : }
4073 : :
4074 : : static enum ofperr
4075 : 32020 : check_mask(struct ofproto_dpif *ofproto, const struct miniflow *flow)
4076 : : {
4077 : : const struct odp_support *support;
4078 : : uint16_t ct_state, ct_zone;
4079 : : ovs_u128 ct_label;
4080 : : uint32_t ct_mark;
4081 : :
4082 : 32020 : support = &ofproto_dpif_get_support(ofproto)->odp;
4083 [ + + ]: 32020 : ct_state = MINIFLOW_GET_U16(flow, ct_state);
4084 [ + - ][ + - ]: 32020 : if (support->ct_state && support->ct_zone && support->ct_mark
[ + - ]
4085 [ + - ][ + + ]: 32020 : && support->ct_label && support->ct_state_nat) {
4086 [ - + ]: 3599 : return ct_state & CS_UNSUPPORTED_MASK ? OFPERR_OFPBMC_BAD_MASK : 0;
4087 : : }
4088 : :
4089 [ + + ]: 28421 : ct_zone = MINIFLOW_GET_U16(flow, ct_zone);
4090 [ + + ]: 28421 : ct_mark = MINIFLOW_GET_U32(flow, ct_mark);
4091 [ + + ][ + + ]: 28421 : ct_label = MINIFLOW_GET_U128(flow, ct_label);
4092 : :
4093 [ + + ][ + - ]: 28421 : if ((ct_state && !support->ct_state)
4094 [ + - ]: 28421 : || (ct_state & CS_UNSUPPORTED_MASK)
4095 [ - + ][ # # ]: 28421 : || ((ct_state & (CS_SRC_NAT | CS_DST_NAT)) && !support->ct_state_nat)
4096 [ + + ][ + - ]: 28421 : || (ct_zone && !support->ct_zone)
4097 [ + + ][ + - ]: 28421 : || (ct_mark && !support->ct_mark)
4098 [ + + ][ - + ]: 28421 : || (!ovs_u128_is_zero(ct_label) && !support->ct_label)) {
4099 : 0 : return OFPERR_OFPBMC_BAD_MASK;
4100 : : }
4101 : :
4102 : 32020 : return 0;
4103 : : }
4104 : :
4105 : : static enum ofperr
4106 : 32020 : check_actions(const struct ofproto_dpif *ofproto,
4107 : : const struct rule_actions *const actions)
4108 : : {
4109 : : const struct ofpact *ofpact;
4110 : :
4111 [ + + ]: 71701 : OFPACT_FOR_EACH (ofpact, actions->ofpacts, actions->ofpacts_len) {
4112 : : const struct odp_support *support;
4113 : : const struct ofpact_conntrack *ct;
4114 : : const struct ofpact *a;
4115 : :
4116 [ + + ]: 40239 : if (ofpact->type != OFPACT_CT) {
4117 : 37872 : continue;
4118 : : }
4119 : :
4120 : 2367 : ct = CONTAINER_OF(ofpact, struct ofpact_conntrack, ofpact);
4121 : 2367 : support = &ofproto_dpif_get_support(ofproto)->odp;
4122 : :
4123 [ - + ]: 2367 : if (!support->ct_state) {
4124 : 0 : return OFPERR_OFPBAC_BAD_TYPE;
4125 : : }
4126 [ + + ][ + + ]: 2367 : if ((ct->zone_imm || ct->zone_src.field) && !support->ct_zone) {
[ - + ]
4127 : 0 : return OFPERR_OFPBAC_BAD_ARGUMENT;
4128 : : }
4129 : :
4130 [ + + ]: 3304 : OFPACT_FOR_EACH(a, ct->actions, ofpact_ct_get_action_len(ct)) {
4131 : 1495 : const struct mf_field *dst = ofpact_get_mf_dst(a);
4132 : :
4133 [ + + ][ + + ]: 1495 : if (a->type == OFPACT_NAT && !support->ct_state_nat) {
4134 : : /* The backer doesn't seem to support the NAT bits in
4135 : : * 'ct_state': assume that it doesn't support the NAT
4136 : : * action. */
4137 : 558 : return OFPERR_OFPBAC_BAD_TYPE;
4138 : : }
4139 [ + + ][ + + ]: 937 : if (dst && ((dst->id == MFF_CT_MARK && !support->ct_mark)
[ + - ]
4140 [ + + ][ - + ]: 748 : || (dst->id == MFF_CT_LABEL && !support->ct_label))) {
4141 : 0 : return OFPERR_OFPBAC_BAD_SET_ARGUMENT;
4142 : : }
4143 : : }
4144 : : }
4145 : :
4146 : 31462 : return 0;
4147 : : }
4148 : :
4149 : : static enum ofperr
4150 : 32020 : rule_check(struct rule *rule)
4151 : : {
4152 : 32020 : struct ofproto_dpif *ofproto = ofproto_dpif_cast(rule->ofproto);
4153 : : enum ofperr err;
4154 : :
4155 : 32020 : err = check_mask(ofproto, &rule->cr.match.mask->masks);
4156 [ - + ]: 32020 : if (err) {
4157 : 0 : return err;
4158 : : }
4159 : 32020 : return check_actions(ofproto, rule->actions);
4160 : : }
4161 : :
4162 : : static enum ofperr
4163 : 32020 : rule_construct(struct rule *rule_)
4164 : : OVS_NO_THREAD_SAFETY_ANALYSIS
4165 : : {
4166 : 32020 : struct rule_dpif *rule = rule_dpif_cast(rule_);
4167 : : int error;
4168 : :
4169 : 32020 : error = rule_check(rule_);
4170 [ + + ]: 32020 : if (error) {
4171 : 558 : return error;
4172 : : }
4173 : :
4174 : 31462 : ovs_mutex_init_adaptive(&rule->stats_mutex);
4175 : 31462 : rule->stats.n_packets = 0;
4176 : 31462 : rule->stats.n_bytes = 0;
4177 : 31462 : rule->stats.used = rule->up.modified;
4178 : 31462 : rule->recirc_id = 0;
4179 : 31462 : rule->new_rule = NULL;
4180 : 31462 : rule->forward_counts = false;
4181 : :
4182 : 31462 : return 0;
4183 : : }
4184 : :
4185 : : static void
4186 : 31430 : rule_insert(struct rule *rule_, struct rule *old_rule_, bool forward_counts)
4187 : : OVS_REQUIRES(ofproto_mutex)
4188 : : {
4189 : 31430 : struct rule_dpif *rule = rule_dpif_cast(rule_);
4190 : :
4191 [ + + ]: 31430 : if (old_rule_) {
4192 : 995 : struct rule_dpif *old_rule = rule_dpif_cast(old_rule_);
4193 : :
4194 [ - + ]: 995 : ovs_assert(!old_rule->new_rule);
4195 : :
4196 : : /* Take a reference to the new rule, and refer all stats updates from
4197 : : * the old rule to the new rule. */
4198 : 995 : rule_dpif_ref(rule);
4199 : :
4200 : 995 : ovs_mutex_lock(&old_rule->stats_mutex);
4201 : 995 : ovs_mutex_lock(&rule->stats_mutex);
4202 : 995 : old_rule->new_rule = rule; /* Forward future stats. */
4203 : 995 : old_rule->forward_counts = forward_counts;
4204 : :
4205 [ + + ]: 995 : if (forward_counts) {
4206 : 879 : rule->stats = old_rule->stats; /* Transfer stats to the new
4207 : : * rule. */
4208 : : } else {
4209 : : /* Used timestamp must be forwarded whenever a rule is modified. */
4210 : 116 : rule->stats.used = old_rule->stats.used;
4211 : : }
4212 : 995 : ovs_mutex_unlock(&rule->stats_mutex);
4213 : 995 : ovs_mutex_unlock(&old_rule->stats_mutex);
4214 : : }
4215 : 31430 : }
4216 : :
4217 : : static void
4218 : 27934 : rule_destruct(struct rule *rule_)
4219 : : OVS_NO_THREAD_SAFETY_ANALYSIS
4220 : : {
4221 : 27934 : struct rule_dpif *rule = rule_dpif_cast(rule_);
4222 : :
4223 : 27934 : ovs_mutex_destroy(&rule->stats_mutex);
4224 : : /* Release reference to the new rule, if any. */
4225 [ + + ]: 27934 : if (rule->new_rule) {
4226 : 995 : rule_dpif_unref(rule->new_rule);
4227 : : }
4228 [ - + ]: 27934 : if (rule->recirc_id) {
4229 : 0 : recirc_free_id(rule->recirc_id);
4230 : : }
4231 : 27934 : }
4232 : :
4233 : : static void
4234 : 19009 : rule_get_stats(struct rule *rule_, uint64_t *packets, uint64_t *bytes,
4235 : : long long int *used)
4236 : : {
4237 : 19009 : struct rule_dpif *rule = rule_dpif_cast(rule_);
4238 : :
4239 : 19009 : ovs_mutex_lock(&rule->stats_mutex);
4240 [ - + ]: 19009 : if (OVS_UNLIKELY(rule->new_rule)) {
4241 : 0 : rule_get_stats(&rule->new_rule->up, packets, bytes, used);
4242 : : } else {
4243 : 19009 : *packets = rule->stats.n_packets;
4244 : 19009 : *bytes = rule->stats.n_bytes;
4245 : 19009 : *used = rule->stats.used;
4246 : : }
4247 : 19009 : ovs_mutex_unlock(&rule->stats_mutex);
4248 : 19009 : }
4249 : :
4250 : 526 : static struct group_dpif *group_dpif_cast(const struct ofgroup *group)
4251 : : {
4252 : 526 : return group ? CONTAINER_OF(group, struct group_dpif, up) : NULL;
4253 : : }
4254 : :
4255 : : static struct ofgroup *
4256 : 103 : group_alloc(void)
4257 : : {
4258 : 103 : struct group_dpif *group = xzalloc(sizeof *group);
4259 : 103 : return &group->up;
4260 : : }
4261 : :
4262 : : static void
4263 : 74 : group_dealloc(struct ofgroup *group_)
4264 : : {
4265 : 74 : struct group_dpif *group = group_dpif_cast(group_);
4266 : 74 : free(group);
4267 : 74 : }
4268 : :
4269 : : static void
4270 : 103 : group_construct_stats(struct group_dpif *group)
4271 : : OVS_REQUIRES(group->stats_mutex)
4272 : : {
4273 : : struct ofputil_bucket *bucket;
4274 : : const struct ovs_list *buckets;
4275 : :
4276 : 103 : group->packet_count = 0;
4277 : 103 : group->byte_count = 0;
4278 : :
4279 : 103 : buckets = group_dpif_get_buckets(group);
4280 [ + + ]: 238 : LIST_FOR_EACH (bucket, list_node, buckets) {
4281 : 135 : bucket->stats.packet_count = 0;
4282 : 135 : bucket->stats.byte_count = 0;
4283 : : }
4284 : 103 : }
4285 : :
4286 : : void
4287 : 245 : group_dpif_credit_stats(struct group_dpif *group,
4288 : : struct ofputil_bucket *bucket,
4289 : : const struct dpif_flow_stats *stats)
4290 : : {
4291 : 245 : ovs_mutex_lock(&group->stats_mutex);
4292 : 245 : group->packet_count += stats->n_packets;
4293 : 245 : group->byte_count += stats->n_bytes;
4294 [ + + ]: 245 : if (bucket) {
4295 : 241 : bucket->stats.packet_count += stats->n_packets;
4296 : 241 : bucket->stats.byte_count += stats->n_bytes;
4297 : : } else { /* Credit to all buckets */
4298 : : const struct ovs_list *buckets;
4299 : :
4300 : 4 : buckets = group_dpif_get_buckets(group);
4301 [ + + ]: 12 : LIST_FOR_EACH (bucket, list_node, buckets) {
4302 : 8 : bucket->stats.packet_count += stats->n_packets;
4303 : 8 : bucket->stats.byte_count += stats->n_bytes;
4304 : : }
4305 : : }
4306 : 245 : ovs_mutex_unlock(&group->stats_mutex);
4307 : 245 : }
4308 : :
4309 : : static enum ofperr
4310 : 103 : group_construct(struct ofgroup *group_)
4311 : : {
4312 : 103 : struct group_dpif *group = group_dpif_cast(group_);
4313 : :
4314 : 103 : ovs_mutex_init_adaptive(&group->stats_mutex);
4315 : 103 : ovs_mutex_lock(&group->stats_mutex);
4316 : 103 : group_construct_stats(group);
4317 : 103 : ovs_mutex_unlock(&group->stats_mutex);
4318 : 103 : return 0;
4319 : : }
4320 : :
4321 : : static void
4322 : 74 : group_destruct(struct ofgroup *group_)
4323 : : {
4324 : 74 : struct group_dpif *group = group_dpif_cast(group_);
4325 : 74 : ovs_mutex_destroy(&group->stats_mutex);
4326 : 74 : }
4327 : :
4328 : : static void
4329 : 31 : group_modify(struct ofgroup *group_)
4330 : : {
4331 : 31 : struct ofproto_dpif *ofproto = ofproto_dpif_cast(group_->ofproto);
4332 : :
4333 : 31 : ofproto->backer->need_revalidate = REV_FLOW_TABLE;
4334 : 31 : }
4335 : :
4336 : : static enum ofperr
4337 : 11 : group_get_stats(const struct ofgroup *group_, struct ofputil_group_stats *ogs)
4338 : : {
4339 : 11 : struct group_dpif *group = group_dpif_cast(group_);
4340 : : struct ofputil_bucket *bucket;
4341 : : const struct ovs_list *buckets;
4342 : : struct bucket_counter *bucket_stats;
4343 : :
4344 : 11 : ovs_mutex_lock(&group->stats_mutex);
4345 : 11 : ogs->packet_count = group->packet_count;
4346 : 11 : ogs->byte_count = group->byte_count;
4347 : :
4348 : 11 : buckets = group_dpif_get_buckets(group);
4349 : 11 : bucket_stats = ogs->bucket_stats;
4350 [ + + ]: 26 : LIST_FOR_EACH (bucket, list_node, buckets) {
4351 : 15 : bucket_stats->packet_count = bucket->stats.packet_count;
4352 : 15 : bucket_stats->byte_count = bucket->stats.byte_count;
4353 : 15 : bucket_stats++;
4354 : : }
4355 : 11 : ovs_mutex_unlock(&group->stats_mutex);
4356 : :
4357 : 11 : return 0;
4358 : : }
4359 : :
4360 : : /* If the group exists, this function increments the groups's reference count.
4361 : : *
4362 : : * Make sure to call group_dpif_unref() after no longer needing to maintain
4363 : : * a reference to the group. */
4364 : : struct group_dpif *
4365 : 264 : group_dpif_lookup(struct ofproto_dpif *ofproto, uint32_t group_id,
4366 : : ovs_version_t version, bool take_ref)
4367 : : {
4368 : 264 : struct ofgroup *ofgroup = ofproto_group_lookup(&ofproto->up, group_id,
4369 : : version, take_ref);
4370 [ + - ]: 264 : return ofgroup ? group_dpif_cast(ofgroup) : NULL;
4371 : : }
4372 : :
4373 : : const struct ovs_list *
4374 : 382 : group_dpif_get_buckets(const struct group_dpif *group)
4375 : : {
4376 : 382 : return &group->up.buckets;
4377 : : }
4378 : :
4379 : : enum ofp11_group_type
4380 : 264 : group_dpif_get_type(const struct group_dpif *group)
4381 : : {
4382 : 264 : return group->up.type;
4383 : : }
4384 : :
4385 : : const char *
4386 : 250 : group_dpif_get_selection_method(const struct group_dpif *group)
4387 : : {
4388 : 250 : return group->up.props.selection_method;
4389 : : }
4390 : :
4391 : : /* Sends 'packet' out 'ofport'. If 'port' is a tunnel and that tunnel type
4392 : : * supports a notion of an OAM flag, sets it if 'oam' is true.
4393 : : * May modify 'packet'.
4394 : : * Returns 0 if successful, otherwise a positive errno value. */
4395 : : int
4396 : 6534 : ofproto_dpif_send_packet(const struct ofport_dpif *ofport, bool oam,
4397 : : struct dp_packet *packet)
4398 : : {
4399 : 6534 : struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofport->up.ofproto);
4400 : : int error;
4401 : :
4402 : 6534 : error = xlate_send_packet(ofport, oam, packet);
4403 : :
4404 : 6534 : ovs_mutex_lock(&ofproto->stats_mutex);
4405 : 6534 : ofproto->stats.tx_packets++;
4406 : 6534 : ofproto->stats.tx_bytes += dp_packet_size(packet);
4407 : 6534 : ovs_mutex_unlock(&ofproto->stats_mutex);
4408 : 6534 : return error;
4409 : : }
4410 : :
4411 : : uint64_t
4412 : 0 : group_dpif_get_selection_method_param(const struct group_dpif *group)
4413 : : {
4414 : 0 : return group->up.props.selection_method_param;
4415 : : }
4416 : :
4417 : : const struct field_array *
4418 : 0 : group_dpif_get_fields(const struct group_dpif *group)
4419 : : {
4420 : 0 : return &group->up.props.fields;
4421 : : }
4422 : :
4423 : : /* Return the version string of the datapath that backs up
4424 : : * this 'ofproto'.
4425 : : */
4426 : : static const char *
4427 : 6579 : get_datapath_version(const struct ofproto *ofproto_)
4428 : : {
4429 : 6579 : struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
4430 : :
4431 : 6579 : return ofproto->backer->dp_version_string;
4432 : : }
4433 : :
4434 : : static bool
4435 : 4 : set_frag_handling(struct ofproto *ofproto_,
4436 : : enum ofputil_frag_handling frag_handling)
4437 : : {
4438 : 4 : struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
4439 [ + - ]: 4 : if (frag_handling != OFPUTIL_FRAG_REASM) {
4440 : 4 : ofproto->backer->need_revalidate = REV_RECONFIGURE;
4441 : 4 : return true;
4442 : : } else {
4443 : 0 : return false;
4444 : : }
4445 : : }
4446 : :
4447 : : static enum ofperr
4448 : 1562 : packet_out(struct ofproto *ofproto_, struct dp_packet *packet,
4449 : : const struct flow *flow,
4450 : : const struct ofpact *ofpacts, size_t ofpacts_len)
4451 : : {
4452 : 1562 : struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
4453 : :
4454 : 1562 : ofproto_dpif_execute_actions(ofproto, flow, NULL, ofpacts,
4455 : : ofpacts_len, packet);
4456 : 1562 : return 0;
4457 : : }
4458 : :
4459 : : static enum ofperr
4460 : 199 : nxt_resume(struct ofproto *ofproto_,
4461 : : const struct ofputil_packet_in_private *pin)
4462 : : {
4463 : 199 : struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
4464 : :
4465 : : /* Translate pin into datapath actions. */
4466 : : uint64_t odp_actions_stub[1024 / 8];
4467 : 199 : struct ofpbuf odp_actions = OFPBUF_STUB_INITIALIZER(odp_actions_stub);
4468 : : enum slow_path_reason slow;
4469 : 199 : enum ofperr error = xlate_resume(ofproto, pin, &odp_actions, &slow);
4470 : :
4471 : : /* Steal 'pin->packet' and put it into a dp_packet. */
4472 : : struct dp_packet packet;
4473 : 199 : dp_packet_init(&packet, pin->public.packet_len);
4474 : 199 : dp_packet_put(&packet, pin->public.packet, pin->public.packet_len);
4475 : :
4476 : 199 : pkt_metadata_from_flow(&packet.md, &pin->public.flow_metadata.flow);
4477 : :
4478 : : /* Fix up in_port. */
4479 : 199 : ofproto_dpif_set_packet_odp_port(ofproto,
4480 : : pin->public.flow_metadata.flow.in_port.ofp_port,
4481 : : &packet);
4482 : :
4483 : : struct flow headers;
4484 : 199 : flow_extract(&packet, &headers);
4485 : :
4486 : : /* Execute the datapath actions on the packet. */
4487 : 796 : struct dpif_execute execute = {
4488 : 199 : .actions = odp_actions.data,
4489 : 199 : .actions_len = odp_actions.size,
4490 : 199 : .needs_help = (slow & SLOW_ACTION) != 0,
4491 : : .packet = &packet,
4492 : : .flow = &headers,
4493 : : };
4494 : 199 : dpif_execute(ofproto->backer->dpif, &execute);
4495 : :
4496 : : /* Clean up. */
4497 : 199 : ofpbuf_uninit(&odp_actions);
4498 : 199 : dp_packet_uninit(&packet);
4499 : :
4500 : 199 : return error;
4501 : : }
4502 : :
4503 : : /* NetFlow. */
4504 : :
4505 : : static int
4506 : 4700 : set_netflow(struct ofproto *ofproto_,
4507 : : const struct netflow_options *netflow_options)
4508 : : {
4509 : 4700 : struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
4510 : :
4511 [ + + ]: 4700 : if (netflow_options) {
4512 [ + - ]: 6 : if (!ofproto->netflow) {
4513 : 6 : ofproto->netflow = netflow_create();
4514 : 6 : ofproto->backer->need_revalidate = REV_RECONFIGURE;
4515 : : }
4516 : 6 : return netflow_set_options(ofproto->netflow, netflow_options);
4517 [ - + ]: 4694 : } else if (ofproto->netflow) {
4518 : 0 : ofproto->backer->need_revalidate = REV_RECONFIGURE;
4519 : 0 : netflow_unref(ofproto->netflow);
4520 : 0 : ofproto->netflow = NULL;
4521 : : }
4522 : :
4523 : 4694 : return 0;
4524 : : }
4525 : :
4526 : : static void
4527 : 6 : get_netflow_ids(const struct ofproto *ofproto_,
4528 : : uint8_t *engine_type, uint8_t *engine_id)
4529 : : {
4530 : 6 : struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
4531 : :
4532 : 6 : dpif_get_netflow_ids(ofproto->backer->dpif, engine_type, engine_id);
4533 : 6 : }
4534 : :
4535 : : static struct ofproto_dpif *
4536 : 602 : ofproto_dpif_lookup(const char *name)
4537 : : {
4538 : : struct ofproto_dpif *ofproto;
4539 : :
4540 [ + + ][ - + ]: 602 : HMAP_FOR_EACH_WITH_HASH (ofproto, all_ofproto_dpifs_node,
4541 : : hash_string(name, 0), &all_ofproto_dpifs) {
4542 [ + - ]: 599 : if (!strcmp(ofproto->up.name, name)) {
4543 : 599 : return ofproto;
4544 : : }
4545 : : }
4546 : 3 : return NULL;
4547 : : }
4548 : :
4549 : : static void
4550 : 0 : ofproto_unixctl_fdb_flush(struct unixctl_conn *conn, int argc,
4551 : : const char *argv[], void *aux OVS_UNUSED)
4552 : : {
4553 : : struct ofproto_dpif *ofproto;
4554 : :
4555 [ # # ]: 0 : if (argc > 1) {
4556 : 0 : ofproto = ofproto_dpif_lookup(argv[1]);
4557 [ # # ]: 0 : if (!ofproto) {
4558 : 0 : unixctl_command_reply_error(conn, "no such bridge");
4559 : 0 : return;
4560 : : }
4561 : 0 : ovs_rwlock_wrlock(&ofproto->ml->rwlock);
4562 : 0 : mac_learning_flush(ofproto->ml);
4563 : 0 : ovs_rwlock_unlock(&ofproto->ml->rwlock);
4564 : : } else {
4565 [ # # ][ # # ]: 0 : HMAP_FOR_EACH (ofproto, all_ofproto_dpifs_node, &all_ofproto_dpifs) {
4566 : 0 : ovs_rwlock_wrlock(&ofproto->ml->rwlock);
4567 : 0 : mac_learning_flush(ofproto->ml);
4568 : 0 : ovs_rwlock_unlock(&ofproto->ml->rwlock);
4569 : : }
4570 : : }
4571 : :
4572 : 0 : unixctl_command_reply(conn, "table successfully flushed");
4573 : : }
4574 : :
4575 : : static void
4576 : 0 : ofproto_unixctl_mcast_snooping_flush(struct unixctl_conn *conn, int argc,
4577 : : const char *argv[], void *aux OVS_UNUSED)
4578 : : {
4579 : : struct ofproto_dpif *ofproto;
4580 : :
4581 [ # # ]: 0 : if (argc > 1) {
4582 : 0 : ofproto = ofproto_dpif_lookup(argv[1]);
4583 [ # # ]: 0 : if (!ofproto) {
4584 : 0 : unixctl_command_reply_error(conn, "no such bridge");
4585 : 0 : return;
4586 : : }
4587 : :
4588 [ # # ]: 0 : if (!mcast_snooping_enabled(ofproto->ms)) {
4589 : 0 : unixctl_command_reply_error(conn, "multicast snooping is disabled");
4590 : 0 : return;
4591 : : }
4592 : 0 : mcast_snooping_mdb_flush(ofproto->ms);
4593 : : } else {
4594 [ # # ][ # # ]: 0 : HMAP_FOR_EACH (ofproto, all_ofproto_dpifs_node, &all_ofproto_dpifs) {
4595 [ # # ]: 0 : if (!mcast_snooping_enabled(ofproto->ms)) {
4596 : 0 : continue;
4597 : : }
4598 : 0 : mcast_snooping_mdb_flush(ofproto->ms);
4599 : : }
4600 : : }
4601 : :
4602 : 0 : unixctl_command_reply(conn, "table successfully flushed");
4603 : : }
4604 : :
4605 : : static struct ofport_dpif *
4606 : 55 : ofbundle_get_a_port(const struct ofbundle *bundle)
4607 : : {
4608 : 55 : return CONTAINER_OF(ovs_list_front(&bundle->ports), struct ofport_dpif,
4609 : : bundle_node);
4610 : : }
4611 : :
4612 : : static void
4613 : 15 : ofproto_unixctl_fdb_show(struct unixctl_conn *conn, int argc OVS_UNUSED,
4614 : : const char *argv[], void *aux OVS_UNUSED)
4615 : : {
4616 : 15 : struct ds ds = DS_EMPTY_INITIALIZER;
4617 : : const struct ofproto_dpif *ofproto;
4618 : : const struct mac_entry *e;
4619 : :
4620 : 15 : ofproto = ofproto_dpif_lookup(argv[1]);
4621 [ - + ]: 15 : if (!ofproto) {
4622 : 0 : unixctl_command_reply_error(conn, "no such bridge");
4623 : 0 : return;
4624 : : }
4625 : :
4626 : 15 : ds_put_cstr(&ds, " port VLAN MAC Age\n");
4627 : 15 : ovs_rwlock_rdlock(&ofproto->ml->rwlock);
4628 [ + + ]: 70 : LIST_FOR_EACH (e, lru_node, &ofproto->ml->lrus) {
4629 : 55 : struct ofbundle *bundle = mac_entry_get_port(ofproto->ml, e);
4630 : : char name[OFP_MAX_PORT_NAME_LEN];
4631 : :
4632 : 55 : ofputil_port_to_string(ofbundle_get_a_port(bundle)->up.ofp_port,
4633 : : name, sizeof name);
4634 : 55 : ds_put_format(&ds, "%5s %4d "ETH_ADDR_FMT" %3d\n",
4635 : 385 : name, e->vlan, ETH_ADDR_ARGS(e->mac),
4636 : 55 : mac_entry_age(ofproto->ml, e));
4637 : : }
4638 : 15 : ovs_rwlock_unlock(&ofproto->ml->rwlock);
4639 : 15 : unixctl_command_reply(conn, ds_cstr(&ds));
4640 : 15 : ds_destroy(&ds);
4641 : : }
4642 : :
4643 : : static void
4644 : 0 : ofproto_unixctl_mcast_snooping_show(struct unixctl_conn *conn,
4645 : : int argc OVS_UNUSED,
4646 : : const char *argv[],
4647 : : void *aux OVS_UNUSED)
4648 : : {
4649 : 0 : struct ds ds = DS_EMPTY_INITIALIZER;
4650 : : const struct ofproto_dpif *ofproto;
4651 : : const struct ofbundle *bundle;
4652 : : const struct mcast_group *grp;
4653 : : struct mcast_group_bundle *b;
4654 : : struct mcast_mrouter_bundle *mrouter;
4655 : :
4656 : 0 : ofproto = ofproto_dpif_lookup(argv[1]);
4657 [ # # ]: 0 : if (!ofproto) {
4658 : 0 : unixctl_command_reply_error(conn, "no such bridge");
4659 : 0 : return;
4660 : : }
4661 : :
4662 [ # # ]: 0 : if (!mcast_snooping_enabled(ofproto->ms)) {
4663 : 0 : unixctl_command_reply_error(conn, "multicast snooping is disabled");
4664 : 0 : return;
4665 : : }
4666 : :
4667 : 0 : ds_put_cstr(&ds, " port VLAN GROUP Age\n");
4668 : 0 : ovs_rwlock_rdlock(&ofproto->ms->rwlock);
4669 [ # # ]: 0 : LIST_FOR_EACH (grp, group_node, &ofproto->ms->group_lru) {
4670 [ # # ]: 0 : LIST_FOR_EACH(b, bundle_node, &grp->bundle_lru) {
4671 : : char name[OFP_MAX_PORT_NAME_LEN];
4672 : :
4673 : 0 : bundle = b->port;
4674 : 0 : ofputil_port_to_string(ofbundle_get_a_port(bundle)->up.ofp_port,
4675 : : name, sizeof name);
4676 : 0 : ds_put_format(&ds, "%5s %4d ", name, grp->vlan);
4677 : 0 : ipv6_format_mapped(&grp->addr, &ds);
4678 : 0 : ds_put_format(&ds, " %3d\n",
4679 : 0 : mcast_bundle_age(ofproto->ms, b));
4680 : : }
4681 : : }
4682 : :
4683 : : /* ports connected to multicast routers */
4684 [ # # ]: 0 : LIST_FOR_EACH(mrouter, mrouter_node, &ofproto->ms->mrouter_lru) {
4685 : : char name[OFP_MAX_PORT_NAME_LEN];
4686 : :
4687 : 0 : bundle = mrouter->port;
4688 : 0 : ofputil_port_to_string(ofbundle_get_a_port(bundle)->up.ofp_port,
4689 : : name, sizeof name);
4690 : 0 : ds_put_format(&ds, "%5s %4d querier %3d\n",
4691 : 0 : name, mrouter->vlan,
4692 : 0 : mcast_mrouter_age(ofproto->ms, mrouter));
4693 : : }
4694 : 0 : ovs_rwlock_unlock(&ofproto->ms->rwlock);
4695 : 0 : unixctl_command_reply(conn, ds_cstr(&ds));
4696 : 0 : ds_destroy(&ds);
4697 : : }
4698 : :
4699 : : struct trace_ctx {
4700 : : struct xlate_out xout;
4701 : : struct xlate_in xin;
4702 : : const struct flow *key;
4703 : : struct flow flow;
4704 : : struct ds *result;
4705 : : struct flow_wildcards wc;
4706 : : struct ofpbuf odp_actions;
4707 : : };
4708 : :
4709 : : static void
4710 : 7485 : trace_format_rule(struct ds *result, int level, const struct rule_dpif *rule)
4711 : : {
4712 : : const struct rule_actions *actions;
4713 : : ovs_be64 cookie;
4714 : :
4715 : 7485 : ds_put_char_multiple(result, '\t', level);
4716 [ - + ]: 7485 : if (!rule) {
4717 : 0 : ds_put_cstr(result, "No match\n");
4718 : 0 : return;
4719 : : }
4720 : :
4721 : 7485 : ovs_mutex_lock(&rule->up.mutex);
4722 : 7485 : cookie = rule->up.flow_cookie;
4723 : 7485 : ovs_mutex_unlock(&rule->up.mutex);
4724 : :
4725 [ + - ]: 7485 : ds_put_format(result, "Rule: table=%"PRIu8" cookie=%#"PRIx64" ",
4726 : 7485 : rule ? rule->up.table_id : 0, ntohll(cookie));
4727 : 7485 : cls_rule_format(&rule->up.cr, result);
4728 : 7485 : ds_put_char(result, '\n');
4729 : :
4730 : 7485 : actions = rule_dpif_get_actions(rule);
4731 : :
4732 : 7485 : ds_put_char_multiple(result, '\t', level);
4733 : 7485 : ds_put_cstr(result, "OpenFlow actions=");
4734 : 7485 : ofpacts_format(actions->ofpacts, actions->ofpacts_len, result);
4735 : 7485 : ds_put_char(result, '\n');
4736 : : }
4737 : :
4738 : : static void
4739 : 7493 : trace_format_flow(struct ds *result, int level, const char *title,
4740 : : struct trace_ctx *trace)
4741 : : {
4742 : 7493 : ds_put_char_multiple(result, '\t', level);
4743 : 7493 : ds_put_format(result, "%s: ", title);
4744 : : /* Do not report unchanged flows for resubmits. */
4745 [ + + ][ + + ]: 7493 : if ((level > 0 && flow_equal(&trace->xin.flow, &trace->flow))
4746 [ + + ][ + + ]: 999 : || (level == 0 && flow_equal(&trace->xin.flow, trace->key))) {
4747 : 7317 : ds_put_cstr(result, "unchanged");
4748 : : } else {
4749 : 176 : flow_format(result, &trace->xin.flow);
4750 : 176 : trace->flow = trace->xin.flow;
4751 : : }
4752 : 7493 : ds_put_char(result, '\n');
4753 : 7493 : }
4754 : :
4755 : : static void
4756 : 6612 : trace_format_regs(struct ds *result, int level, const char *title,
4757 : : struct trace_ctx *trace)
4758 : : {
4759 : : size_t i;
4760 : :
4761 : 6612 : ds_put_char_multiple(result, '\t', level);
4762 : 6612 : ds_put_format(result, "%s:", title);
4763 [ + + ]: 112404 : for (i = 0; i < FLOW_N_REGS; i++) {
4764 : 105792 : ds_put_format(result, " reg%"PRIuSIZE"=0x%"PRIx32, i, trace->flow.regs[i]);
4765 : : }
4766 : 6612 : ds_put_char(result, '\n');
4767 : 6612 : }
4768 : :
4769 : : static void
4770 : 6612 : trace_format_odp(struct ds *result, int level, const char *title,
4771 : : struct trace_ctx *trace)
4772 : : {
4773 : 6612 : struct ofpbuf *odp_actions = &trace->odp_actions;
4774 : :
4775 : 6612 : ds_put_char_multiple(result, '\t', level);
4776 : 6612 : ds_put_format(result, "%s: ", title);
4777 : 6612 : format_odp_actions(result, odp_actions->data, odp_actions->size);
4778 : 6612 : ds_put_char(result, '\n');
4779 : 6612 : }
4780 : :
4781 : : static void
4782 : 7493 : trace_format_megaflow(struct ds *result, int level, const char *title,
4783 : : struct trace_ctx *trace)
4784 : : {
4785 : : struct match match;
4786 : :
4787 : 7493 : ds_put_char_multiple(result, '\t', level);
4788 : 7493 : ds_put_format(result, "%s: ", title);
4789 : 7493 : match_init(&match, trace->key, &trace->wc);
4790 : 7493 : match_format(&match, result, OFP_DEFAULT_PRIORITY);
4791 : 7493 : ds_put_char(result, '\n');
4792 : 7493 : }
4793 : :
4794 : : static void trace_report(struct xlate_in *, int indentation,
4795 : : const char *format, ...)
4796 : : OVS_PRINTF_FORMAT(3, 4);
4797 : : static void trace_report_valist(struct xlate_in *, int indentation,
4798 : : const char *format, va_list args)
4799 : : OVS_PRINTF_FORMAT(3, 0);
4800 : :
4801 : : static void
4802 : 7485 : trace_resubmit(struct xlate_in *xin, struct rule_dpif *rule, int indentation)
4803 : : {
4804 : 7485 : struct trace_ctx *trace = CONTAINER_OF(xin, struct trace_ctx, xin);
4805 : 7485 : struct ds *result = trace->result;
4806 : :
4807 [ + + ]: 7485 : if (!indentation) {
4808 [ - + ]: 873 : if (rule == xin->ofproto->miss_rule) {
4809 : 0 : trace_report(xin, indentation,
4810 : : "No match, flow generates \"packet in\"s.");
4811 [ + + ]: 873 : } else if (rule == xin->ofproto->no_packet_in_rule) {
4812 : 5 : trace_report(xin, indentation, "No match, packets dropped because "
4813 : : "OFPPC_NO_PACKET_IN is set on in_port.");
4814 [ + + ]: 868 : } else if (rule == xin->ofproto->drop_frags_rule) {
4815 : 2 : trace_report(xin, indentation,
4816 : : "Packets dropped because they are IP fragments and "
4817 : : "the fragment handling mode is \"drop\".");
4818 : : }
4819 : : }
4820 : :
4821 : 7485 : ds_put_char(result, '\n');
4822 [ + + ]: 7485 : if (indentation) {
4823 : 6612 : trace_format_flow(result, indentation, "Resubmitted flow", trace);
4824 : 6612 : trace_format_regs(result, indentation, "Resubmitted regs", trace);
4825 : 6612 : trace_format_odp(result, indentation, "Resubmitted odp", trace);
4826 : 6612 : trace_format_megaflow(result, indentation, "Resubmitted megaflow",
4827 : : trace);
4828 : : }
4829 : 7485 : trace_format_rule(result, indentation, rule);
4830 : 7485 : }
4831 : :
4832 : : static void
4833 : 273 : trace_report_valist(struct xlate_in *xin, int indentation,
4834 : : const char *format, va_list args)
4835 : : {
4836 : 273 : struct trace_ctx *trace = CONTAINER_OF(xin, struct trace_ctx, xin);
4837 : 273 : struct ds *result = trace->result;
4838 : :
4839 : 273 : ds_put_char_multiple(result, '\t', indentation);
4840 : 273 : ds_put_format_valist(result, format, args);
4841 : 273 : ds_put_char(result, '\n');
4842 : 273 : }
4843 : :
4844 : : static void
4845 : 7 : trace_report(struct xlate_in *xin, int indentation, const char *format, ...)
4846 : : {
4847 : : va_list args;
4848 : :
4849 : 7 : va_start(args, format);
4850 : 7 : trace_report_valist(xin, indentation, format, args);
4851 : 7 : va_end(args);
4852 : 7 : }
4853 : :
4854 : : /* Parses the 'argc' elements of 'argv', ignoring argv[0]. The following
4855 : : * forms are supported:
4856 : : *
4857 : : * - [dpname] odp_flow [-generate | packet]
4858 : : * - bridge br_flow [-generate | packet]
4859 : : *
4860 : : * On success, initializes '*ofprotop' and 'flow' and returns NULL. On failure
4861 : : * returns a nonnull malloced error message. */
4862 : : static char * OVS_WARN_UNUSED_RESULT
4863 : 902 : parse_flow_and_packet(int argc, const char *argv[],
4864 : : struct ofproto_dpif **ofprotop, struct flow *flow,
4865 : : struct dp_packet **packetp)
4866 : : {
4867 : 902 : const struct dpif_backer *backer = NULL;
4868 : 902 : const char *error = NULL;
4869 : 902 : char *m_err = NULL;
4870 : 902 : struct simap port_names = SIMAP_INITIALIZER(&port_names);
4871 : : struct dp_packet *packet;
4872 : : struct ofpbuf odp_key;
4873 : : struct ofpbuf odp_mask;
4874 : :
4875 : 902 : ofpbuf_init(&odp_key, 0);
4876 : 902 : ofpbuf_init(&odp_mask, 0);
4877 : :
4878 : : /* Handle "-generate" or a hex string as the last argument. */
4879 [ + + ]: 902 : if (!strcmp(argv[argc - 1], "-generate")) {
4880 : 96 : packet = dp_packet_new(0);
4881 : 96 : argc--;
4882 : : } else {
4883 : 806 : error = eth_from_hex(argv[argc - 1], &packet);
4884 [ + + ]: 806 : if (!error) {
4885 : 11 : argc--;
4886 [ + + ]: 795 : } else if (argc == 4) {
4887 : : /* The 3-argument form must end in "-generate' or a hex string. */
4888 : 1 : goto exit;
4889 : : }
4890 : 805 : error = NULL;
4891 : : }
4892 : :
4893 : : /* odp_flow can have its in_port specified as a name instead of port no.
4894 : : * We do not yet know whether a given flow is a odp_flow or a br_flow.
4895 : : * But, to know whether a flow is odp_flow through odp_flow_from_string(),
4896 : : * we need to create a simap of name to port no. */
4897 [ + + ]: 901 : if (argc == 3) {
4898 : : const char *dp_type;
4899 [ + + ]: 891 : if (!strncmp(argv[1], "ovs-", 4)) {
4900 : 319 : dp_type = argv[1] + 4;
4901 : : } else {
4902 : 572 : dp_type = argv[1];
4903 : : }
4904 : 891 : backer = shash_find_data(&all_dpif_backers, dp_type);
4905 [ + - ]: 10 : } else if (argc == 2) {
4906 : : struct shash_node *node;
4907 [ + - ]: 10 : if (shash_count(&all_dpif_backers) == 1) {
4908 : 10 : node = shash_first(&all_dpif_backers);
4909 : 10 : backer = node->data;
4910 : : }
4911 : : } else {
4912 : 0 : error = "Syntax error";
4913 : 0 : goto exit;
4914 : : }
4915 [ + + ][ + - ]: 901 : if (backer && backer->dpif) {
4916 : : struct dpif_port dpif_port;
4917 : : struct dpif_port_dump port_dump;
4918 [ + + ][ + + ]: 2495 : DPIF_PORT_FOR_EACH (&dpif_port, &port_dump, backer->dpif) {
4919 : 2169 : simap_put(&port_names, dpif_port.name,
4920 : : odp_to_u32(dpif_port.port_no));
4921 : : }
4922 : : }
4923 : :
4924 : : /* Parse the flow and determine whether a datapath or
4925 : : * bridge is specified. If function odp_flow_key_from_string()
4926 : : * returns 0, the flow is a odp_flow. If function
4927 : : * parse_ofp_exact_flow() returns NULL, the flow is a br_flow. */
4928 [ + + ]: 901 : if (!odp_flow_from_string(argv[argc - 1], &port_names,
4929 : : &odp_key, &odp_mask)) {
4930 [ + + ]: 332 : if (!backer) {
4931 : 12 : error = "Cannot find the datapath";
4932 : 12 : goto exit;
4933 : : }
4934 : :
4935 [ - + ]: 320 : if (odp_flow_key_to_flow(odp_key.data, odp_key.size, flow) == ODP_FIT_ERROR) {
4936 : 0 : error = "Failed to parse datapath flow key";
4937 : 0 : goto exit;
4938 : : }
4939 : :
4940 : 320 : *ofprotop = xlate_lookup_ofproto(backer, flow,
4941 : : &flow->in_port.ofp_port);
4942 [ + + ]: 320 : if (*ofprotop == NULL) {
4943 : 2 : error = "Invalid datapath flow";
4944 : 2 : goto exit;
4945 : : }
4946 : : } else {
4947 : 569 : char *err = parse_ofp_exact_flow(flow, NULL, argv[argc - 1], NULL);
4948 : :
4949 [ - + ]: 569 : if (err) {
4950 : 0 : m_err = xasprintf("Bad openflow flow syntax: %s", err);
4951 : 0 : free(err);
4952 : 0 : goto exit;
4953 : : } else {
4954 [ + + ]: 569 : if (argc != 3) {
4955 : 3 : error = "Must specify bridge name";
4956 : 3 : goto exit;
4957 : : }
4958 : :
4959 : 566 : *ofprotop = ofproto_dpif_lookup(argv[1]);
4960 [ + + ]: 566 : if (!*ofprotop) {
4961 : 3 : error = "Unknown bridge name";
4962 : 3 : goto exit;
4963 : : }
4964 : : }
4965 : : }
4966 : :
4967 : : /* Generate a packet, if requested. */
4968 [ + + ]: 881 : if (packet) {
4969 [ + + ]: 95 : if (!dp_packet_size(packet)) {
4970 : 90 : flow_compose(packet, flow);
4971 : : } else {
4972 : : /* Use the metadata from the flow and the packet argument
4973 : : * to reconstruct the flow. */
4974 : 5 : pkt_metadata_from_flow(&packet->md, flow);
4975 : 5 : flow_extract(packet, flow);
4976 : : }
4977 : : }
4978 : :
4979 : : exit:
4980 [ + + ][ + - ]: 902 : if (error && !m_err) {
4981 : 21 : m_err = xstrdup(error);
4982 : : }
4983 [ + + ]: 902 : if (m_err) {
4984 : 21 : dp_packet_delete(packet);
4985 : 21 : packet = NULL;
4986 : : }
4987 : 902 : *packetp = packet;
4988 : 902 : ofpbuf_uninit(&odp_key);
4989 : 902 : ofpbuf_uninit(&odp_mask);
4990 : 902 : simap_destroy(&port_names);
4991 : 902 : return m_err;
4992 : : }
4993 : :
4994 : : static void
4995 : 901 : ofproto_unixctl_trace(struct unixctl_conn *conn, int argc, const char *argv[],
4996 : : void *aux OVS_UNUSED)
4997 : : {
4998 : : struct ofproto_dpif *ofproto;
4999 : : struct dp_packet *packet;
5000 : : char *error;
5001 : : struct flow flow;
5002 : :
5003 : 901 : error = parse_flow_and_packet(argc, argv, &ofproto, &flow, &packet);
5004 [ + + ]: 901 : if (!error) {
5005 : : struct ds result;
5006 : :
5007 : 880 : ds_init(&result);
5008 : 880 : ofproto_trace(ofproto, &flow, packet, NULL, 0, &result);
5009 : 880 : unixctl_command_reply(conn, ds_cstr(&result));
5010 : 880 : ds_destroy(&result);
5011 : 880 : dp_packet_delete(packet);
5012 : : } else {
5013 : 21 : unixctl_command_reply_error(conn, error);
5014 : 21 : free(error);
5015 : : }
5016 : 901 : }
5017 : :
5018 : : static void
5019 : 1 : ofproto_unixctl_trace_actions(struct unixctl_conn *conn, int argc,
5020 : : const char *argv[], void *aux OVS_UNUSED)
5021 : : {
5022 : : enum ofputil_protocol usable_protocols;
5023 : : struct ofproto_dpif *ofproto;
5024 : : bool enforce_consistency;
5025 : : struct ofpbuf ofpacts;
5026 : : struct dp_packet *packet;
5027 : : struct ds result;
5028 : : struct flow flow;
5029 : : uint16_t in_port;
5030 : :
5031 : : /* Three kinds of error return values! */
5032 : : enum ofperr retval;
5033 : : char *error;
5034 : :
5035 : 1 : packet = NULL;
5036 : 1 : ds_init(&result);
5037 : 1 : ofpbuf_init(&ofpacts, 0);
5038 : :
5039 : : /* Parse actions. */
5040 : 1 : error = ofpacts_parse_actions(argv[--argc], &ofpacts, &usable_protocols);
5041 [ - + ]: 1 : if (error) {
5042 : 0 : unixctl_command_reply_error(conn, error);
5043 : 0 : free(error);
5044 : 0 : goto exit;
5045 : : }
5046 : :
5047 : : /* OpenFlow 1.1 and later suggest that the switch enforces certain forms of
5048 : : * consistency between the flow and the actions. With -consistent, we
5049 : : * enforce consistency even for a flow supported in OpenFlow 1.0. */
5050 [ - + ]: 1 : if (!strcmp(argv[1], "-consistent")) {
5051 : 0 : enforce_consistency = true;
5052 : 0 : argv++;
5053 : 0 : argc--;
5054 : : } else {
5055 : 1 : enforce_consistency = false;
5056 : : }
5057 : :
5058 : 1 : error = parse_flow_and_packet(argc, argv, &ofproto, &flow, &packet);
5059 [ - + ]: 1 : if (error) {
5060 : 0 : unixctl_command_reply_error(conn, error);
5061 : 0 : free(error);
5062 : 0 : goto exit;
5063 : : }
5064 : :
5065 : : /* Do the same checks as handle_packet_out() in ofproto.c.
5066 : : *
5067 : : * We pass a 'table_id' of 0 to ofpacts_check(), which isn't
5068 : : * strictly correct because these actions aren't in any table, but it's OK
5069 : : * because it 'table_id' is used only to check goto_table instructions, but
5070 : : * packet-outs take a list of actions and therefore it can't include
5071 : : * instructions.
5072 : : *
5073 : : * We skip the "meter" check here because meter is an instruction, not an
5074 : : * action, and thus cannot appear in ofpacts. */
5075 : 1 : in_port = ofp_to_u16(flow.in_port.ofp_port);
5076 [ - + ][ # # ]: 1 : if (in_port >= ofproto->up.max_ports && in_port < ofp_to_u16(OFPP_MAX)) {
5077 : 0 : unixctl_command_reply_error(conn, "invalid in_port");
5078 : 0 : goto exit;
5079 : : }
5080 [ - + ]: 1 : if (enforce_consistency) {
5081 : 0 : retval = ofpacts_check_consistency(ofpacts.data, ofpacts.size, &flow,
5082 : 0 : u16_to_ofp(ofproto->up.max_ports),
5083 : 0 : 0, ofproto->up.n_tables,
5084 : : usable_protocols);
5085 : : } else {
5086 : 1 : retval = ofpacts_check(ofpacts.data, ofpacts.size, &flow,
5087 : 1 : u16_to_ofp(ofproto->up.max_ports), 0,
5088 : 1 : ofproto->up.n_tables, &usable_protocols);
5089 : : }
5090 [ + - ]: 1 : if (!retval) {
5091 : 1 : retval = ofproto_check_ofpacts(&ofproto->up, ofpacts.data,
5092 : 1 : ofpacts.size);
5093 : : }
5094 : :
5095 [ - + ]: 1 : if (retval) {
5096 : 0 : ds_clear(&result);
5097 : 0 : ds_put_format(&result, "Bad actions: %s", ofperr_to_string(retval));
5098 : 0 : unixctl_command_reply_error(conn, ds_cstr(&result));
5099 : 0 : goto exit;
5100 : : }
5101 : :
5102 : 1 : ofproto_trace(ofproto, &flow, packet,
5103 : 2 : ofpacts.data, ofpacts.size, &result);
5104 : 1 : unixctl_command_reply(conn, ds_cstr(&result));
5105 : :
5106 : : exit:
5107 : 1 : ds_destroy(&result);
5108 : 1 : dp_packet_delete(packet);
5109 : 1 : ofpbuf_uninit(&ofpacts);
5110 : 1 : }
5111 : :
5112 : : /* Implements a "trace" through 'ofproto''s flow table, appending a textual
5113 : : * description of the results to 'ds'.
5114 : : *
5115 : : * The trace follows a packet with the specified 'flow' through the flow
5116 : : * table. 'packet' may be nonnull to trace an actual packet, with consequent
5117 : : * side effects (if it is nonnull then its flow must be 'flow').
5118 : : *
5119 : : * If 'ofpacts' is nonnull then its 'ofpacts_len' bytes specify the actions to
5120 : : * trace, otherwise the actions are determined by a flow table lookup. */
5121 : : static void
5122 : 881 : ofproto_trace(struct ofproto_dpif *ofproto, struct flow *flow,
5123 : : const struct dp_packet *packet,
5124 : : const struct ofpact ofpacts[], size_t ofpacts_len,
5125 : : struct ds *ds)
5126 : : {
5127 : : struct trace_ctx trace;
5128 : : enum xlate_error error;
5129 : :
5130 : 881 : ds_put_format(ds, "Bridge: %s\n", ofproto->up.name);
5131 : 881 : ds_put_cstr(ds, "Flow: ");
5132 : 881 : flow_format(ds, flow);
5133 : 881 : ds_put_char(ds, '\n');
5134 : :
5135 : 881 : ofpbuf_init(&trace.odp_actions, 0);
5136 : :
5137 : 881 : trace.result = ds;
5138 : 881 : trace.key = flow; /* Original flow key, used for megaflow. */
5139 : 881 : trace.flow = *flow; /* May be modified by actions. */
5140 : 881 : xlate_in_init(&trace.xin, ofproto, flow, flow->in_port.ofp_port, NULL,
5141 : 881 : ntohs(flow->tcp_flags), packet, &trace.wc,
5142 : : &trace.odp_actions);
5143 : 881 : trace.xin.ofpacts = ofpacts;
5144 : 881 : trace.xin.ofpacts_len = ofpacts_len;
5145 : 881 : trace.xin.resubmit_hook = trace_resubmit;
5146 : 881 : trace.xin.report_hook = trace_report_valist;
5147 : :
5148 : 881 : error = xlate_actions(&trace.xin, &trace.xout);
5149 : 881 : ds_put_char(ds, '\n');
5150 : 881 : trace.xin.flow.actset_output = 0;
5151 : 881 : trace_format_flow(ds, 0, "Final flow", &trace);
5152 : 881 : trace_format_megaflow(ds, 0, "Megaflow", &trace);
5153 : :
5154 : 881 : ds_put_cstr(ds, "Datapath actions: ");
5155 : 881 : format_odp_actions(ds, trace.odp_actions.data, trace.odp_actions.size);
5156 : :
5157 [ + + ]: 881 : if (error != XLATE_OK) {
5158 : 4 : ds_put_format(ds, "\nTranslation failed (%s), packet is dropped.\n",
5159 : : xlate_strerror(error));
5160 [ + + ]: 877 : } else if (trace.xout.slow) {
5161 : : enum slow_path_reason slow;
5162 : :
5163 : 8 : ds_put_cstr(ds, "\nThis flow is handled by the userspace "
5164 : : "slow path because it:");
5165 : :
5166 : 8 : slow = trace.xout.slow;
5167 [ + + ]: 16 : while (slow) {
5168 : 8 : enum slow_path_reason bit = rightmost_1bit(slow);
5169 : :
5170 : 8 : ds_put_format(ds, "\n\t- %s.",
5171 : : slow_path_reason_to_explanation(bit));
5172 : :
5173 : 8 : slow &= ~bit;
5174 : : }
5175 : : }
5176 : :
5177 : 881 : xlate_out_uninit(&trace.xout);
5178 : 881 : ofpbuf_uninit(&trace.odp_actions);
5179 : 881 : }
5180 : :
5181 : : /* Store the current ofprotos in 'ofproto_shash'. Returns a sorted list
5182 : : * of the 'ofproto_shash' nodes. It is the responsibility of the caller
5183 : : * to destroy 'ofproto_shash' and free the returned value. */
5184 : : static const struct shash_node **
5185 : 33 : get_ofprotos(struct shash *ofproto_shash)
5186 : : {
5187 : : const struct ofproto_dpif *ofproto;
5188 : :
5189 [ + + ][ - + ]: 74 : HMAP_FOR_EACH (ofproto, all_ofproto_dpifs_node, &all_ofproto_dpifs) {
5190 : 41 : char *name = xasprintf("%s@%s", ofproto->up.type, ofproto->up.name);
5191 : 41 : shash_add_nocopy(ofproto_shash, name, ofproto);
5192 : : }
5193 : :
5194 : 33 : return shash_sort(ofproto_shash);
5195 : : }
5196 : :
5197 : : static void
5198 : 1 : ofproto_unixctl_dpif_dump_dps(struct unixctl_conn *conn, int argc OVS_UNUSED,
5199 : : const char *argv[] OVS_UNUSED,
5200 : : void *aux OVS_UNUSED)
5201 : : {
5202 : 1 : struct ds ds = DS_EMPTY_INITIALIZER;
5203 : : struct shash ofproto_shash;
5204 : : const struct shash_node **sorted_ofprotos;
5205 : : int i;
5206 : :
5207 : 1 : shash_init(&ofproto_shash);
5208 : 1 : sorted_ofprotos = get_ofprotos(&ofproto_shash);
5209 [ + + ]: 3 : for (i = 0; i < shash_count(&ofproto_shash); i++) {
5210 : 2 : const struct shash_node *node = sorted_ofprotos[i];
5211 : 2 : ds_put_format(&ds, "%s\n", node->name);
5212 : : }
5213 : :
5214 : 1 : shash_destroy(&ofproto_shash);
5215 : 1 : free(sorted_ofprotos);
5216 : :
5217 : 1 : unixctl_command_reply(conn, ds_cstr(&ds));
5218 : 1 : ds_destroy(&ds);
5219 : 1 : }
5220 : :
5221 : : static void
5222 : 32 : dpif_show_backer(const struct dpif_backer *backer, struct ds *ds)
5223 : : {
5224 : : const struct shash_node **ofprotos;
5225 : : struct dpif_dp_stats dp_stats;
5226 : : struct shash ofproto_shash;
5227 : : size_t i;
5228 : :
5229 : 32 : dpif_get_dp_stats(backer->dpif, &dp_stats);
5230 : :
5231 : 32 : ds_put_format(ds, "%s: hit:%"PRIu64" missed:%"PRIu64"\n",
5232 : 32 : dpif_name(backer->dpif), dp_stats.n_hit, dp_stats.n_missed);
5233 : :
5234 : 32 : shash_init(&ofproto_shash);
5235 : 32 : ofprotos = get_ofprotos(&ofproto_shash);
5236 [ + + ]: 71 : for (i = 0; i < shash_count(&ofproto_shash); i++) {
5237 : 39 : struct ofproto_dpif *ofproto = ofprotos[i]->data;
5238 : : const struct shash_node **ports;
5239 : : size_t j;
5240 : :
5241 [ - + ]: 39 : if (ofproto->backer != backer) {
5242 : 0 : continue;
5243 : : }
5244 : :
5245 : 39 : ds_put_format(ds, "\t%s:\n", ofproto->up.name);
5246 : :
5247 : 39 : ports = shash_sort(&ofproto->up.port_by_name);
5248 [ + + ]: 150 : for (j = 0; j < shash_count(&ofproto->up.port_by_name); j++) {
5249 : 111 : const struct shash_node *node = ports[j];
5250 : 111 : struct ofport *ofport = node->data;
5251 : : struct smap config;
5252 : : odp_port_t odp_port;
5253 : :
5254 : 111 : ds_put_format(ds, "\t\t%s %u/", netdev_get_name(ofport->netdev),
5255 : : ofport->ofp_port);
5256 : :
5257 : 111 : odp_port = ofp_port_to_odp_port(ofproto, ofport->ofp_port);
5258 [ + + ]: 111 : if (odp_port != ODPP_NONE) {
5259 : 105 : ds_put_format(ds, "%"PRIu32":", odp_port);
5260 : : } else {
5261 : 6 : ds_put_cstr(ds, "none:");
5262 : : }
5263 : :
5264 : 111 : ds_put_format(ds, " (%s", netdev_get_type(ofport->netdev));
5265 : :
5266 : 111 : smap_init(&config);
5267 [ + - ]: 111 : if (!netdev_get_config(ofport->netdev, &config)) {
5268 : : const struct smap_node **nodes;
5269 : : size_t i;
5270 : :
5271 : 111 : nodes = smap_sort(&config);
5272 [ + + ]: 212 : for (i = 0; i < smap_count(&config); i++) {
5273 : 101 : const struct smap_node *node = nodes[i];
5274 [ + + ]: 101 : ds_put_format(ds, "%c %s=%s", i ? ',' : ':',
5275 : : node->key, node->value);
5276 : : }
5277 : 111 : free(nodes);
5278 : : }
5279 : 111 : smap_destroy(&config);
5280 : :
5281 : 111 : ds_put_char(ds, ')');
5282 : 111 : ds_put_char(ds, '\n');
5283 : : }
5284 : 39 : free(ports);
5285 : : }
5286 : 32 : shash_destroy(&ofproto_shash);
5287 : 32 : free(ofprotos);
5288 : 32 : }
5289 : :
5290 : : static void
5291 : 32 : ofproto_unixctl_dpif_show(struct unixctl_conn *conn, int argc OVS_UNUSED,
5292 : : const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED)
5293 : : {
5294 : 32 : struct ds ds = DS_EMPTY_INITIALIZER;
5295 : : const struct shash_node **backers;
5296 : : int i;
5297 : :
5298 : 32 : backers = shash_sort(&all_dpif_backers);
5299 [ + + ]: 64 : for (i = 0; i < shash_count(&all_dpif_backers); i++) {
5300 : 32 : dpif_show_backer(backers[i]->data, &ds);
5301 : : }
5302 : 32 : free(backers);
5303 : :
5304 : 32 : unixctl_command_reply(conn, ds_cstr(&ds));
5305 : 32 : ds_destroy(&ds);
5306 : 32 : }
5307 : :
5308 : : static void
5309 : 21 : ofproto_unixctl_dpif_dump_flows(struct unixctl_conn *conn,
5310 : : int argc OVS_UNUSED, const char *argv[],
5311 : : void *aux OVS_UNUSED)
5312 : : {
5313 : : const struct ofproto_dpif *ofproto;
5314 : :
5315 : 21 : struct ds ds = DS_EMPTY_INITIALIZER;
5316 : 21 : bool verbosity = false;
5317 : :
5318 : : struct dpif_port dpif_port;
5319 : : struct dpif_port_dump port_dump;
5320 : : struct hmap portno_names;
5321 : :
5322 : : struct dpif_flow_dump *flow_dump;
5323 : : struct dpif_flow_dump_thread *flow_dump_thread;
5324 : : struct dpif_flow f;
5325 : : int error;
5326 : :
5327 : 21 : ofproto = ofproto_dpif_lookup(argv[argc - 1]);
5328 [ - + ]: 21 : if (!ofproto) {
5329 : 0 : unixctl_command_reply_error(conn, "no such bridge");
5330 : 0 : return;
5331 : : }
5332 : :
5333 [ + + ][ + - ]: 21 : if (argc > 2 && !strcmp(argv[1], "-m")) {
5334 : 6 : verbosity = true;
5335 : : }
5336 : :
5337 : 21 : hmap_init(&portno_names);
5338 [ + + ][ + + ]: 139 : DPIF_PORT_FOR_EACH (&dpif_port, &port_dump, ofproto->backer->dpif) {
5339 : 118 : odp_portno_names_set(&portno_names, dpif_port.port_no, dpif_port.name);
5340 : : }
5341 : :
5342 : 21 : ds_init(&ds);
5343 : 21 : flow_dump = dpif_flow_dump_create(ofproto->backer->dpif, false);
5344 : 21 : flow_dump_thread = dpif_flow_dump_thread_create(flow_dump);
5345 [ + + ]: 2079 : while (dpif_flow_dump_next(flow_dump_thread, &f, 1)) {
5346 : : struct flow flow;
5347 : :
5348 [ + - ]: 2058 : if (odp_flow_key_to_flow(f.key, f.key_len, &flow) == ODP_FIT_ERROR
5349 [ + + ]: 2058 : || xlate_lookup_ofproto(ofproto->backer, &flow, NULL) != ofproto) {
5350 : 1085 : continue;
5351 : : }
5352 : :
5353 [ + + ]: 973 : if (verbosity) {
5354 : 7 : odp_format_ufid(&f.ufid, &ds);
5355 : 7 : ds_put_cstr(&ds, " ");
5356 : : }
5357 : 973 : odp_flow_format(f.key, f.key_len, f.mask, f.mask_len,
5358 : : &portno_names, &ds, verbosity);
5359 : 973 : ds_put_cstr(&ds, ", ");
5360 : 973 : dpif_flow_stats_format(&f.stats, &ds);
5361 : 973 : ds_put_cstr(&ds, ", actions:");
5362 : 973 : format_odp_actions(&ds, f.actions, f.actions_len);
5363 : 973 : ds_put_char(&ds, '\n');
5364 : : }
5365 : 21 : dpif_flow_dump_thread_destroy(flow_dump_thread);
5366 : 21 : error = dpif_flow_dump_destroy(flow_dump);
5367 : :
5368 [ - + ]: 21 : if (error) {
5369 : 0 : ds_clear(&ds);
5370 : 0 : ds_put_format(&ds, "dpif/dump_flows failed: %s", ovs_strerror(errno));
5371 : 0 : unixctl_command_reply_error(conn, ds_cstr(&ds));
5372 : : } else {
5373 : 21 : unixctl_command_reply(conn, ds_cstr(&ds));
5374 : : }
5375 : 21 : odp_portno_names_destroy(&portno_names);
5376 : 21 : hmap_destroy(&portno_names);
5377 : 21 : ds_destroy(&ds);
5378 : : }
5379 : :
5380 : : static void
5381 : 19 : ofproto_revalidate_all_backers(void)
5382 : : {
5383 : : const struct shash_node **backers;
5384 : : int i;
5385 : :
5386 : 19 : backers = shash_sort(&all_dpif_backers);
5387 [ + + ]: 38 : for (i = 0; i < shash_count(&all_dpif_backers); i++) {
5388 : 19 : struct dpif_backer *backer = backers[i]->data;
5389 : 19 : backer->need_revalidate = REV_RECONFIGURE;
5390 : : }
5391 : 19 : free(backers);
5392 : 19 : }
5393 : :
5394 : : static void
5395 : 19 : disable_tnl_push_pop(struct unixctl_conn *conn OVS_UNUSED, int argc OVS_UNUSED,
5396 : : const char *argv[], void *aux OVS_UNUSED)
5397 : : {
5398 [ + - ]: 19 : if (!strcasecmp(argv[1], "off")) {
5399 : 19 : ofproto_use_tnl_push_pop = false;
5400 : 19 : unixctl_command_reply(conn, "Tunnel push-pop off");
5401 : 19 : ofproto_revalidate_all_backers();
5402 [ # # ]: 0 : } else if (!strcasecmp(argv[1], "on")) {
5403 : 0 : ofproto_use_tnl_push_pop = true;
5404 : 0 : unixctl_command_reply(conn, "Tunnel push-pop on");
5405 : 0 : ofproto_revalidate_all_backers();
5406 : : } else {
5407 : 0 : unixctl_command_reply_error(conn, "Invalid argument");
5408 : : }
5409 : 19 : }
5410 : :
5411 : : static void
5412 : 4 : disable_datapath_truncate(struct unixctl_conn *conn OVS_UNUSED,
5413 : : int argc OVS_UNUSED,
5414 : : const char *argv[] OVS_UNUSED,
5415 : : void *aux OVS_UNUSED)
5416 : : {
5417 : : const struct shash_node **backers;
5418 : : int i;
5419 : :
5420 : 4 : backers = shash_sort(&all_dpif_backers);
5421 [ + + ]: 8 : for (i = 0; i < shash_count(&all_dpif_backers); i++) {
5422 : 4 : struct dpif_backer *backer = backers[i]->data;
5423 : 4 : backer->support.trunc = false;
5424 : : }
5425 : 4 : free(backers);
5426 : 4 : unixctl_command_reply(conn, "Datapath truncate action diabled");
5427 : 4 : }
5428 : :
5429 : : static void
5430 : 615 : ofproto_unixctl_init(void)
5431 : : {
5432 : : static bool registered;
5433 [ - + ]: 615 : if (registered) {
5434 : 0 : return;
5435 : : }
5436 : 615 : registered = true;
5437 : :
5438 : 615 : unixctl_command_register(
5439 : : "ofproto/trace",
5440 : : "{[dp_name] odp_flow | bridge br_flow} [-generate|packet]",
5441 : : 1, 3, ofproto_unixctl_trace, NULL);
5442 : 615 : unixctl_command_register(
5443 : : "ofproto/trace-packet-out",
5444 : : "[-consistent] {[dp_name] odp_flow | bridge br_flow} [-generate|packet] actions",
5445 : : 2, 6, ofproto_unixctl_trace_actions, NULL);
5446 : 615 : unixctl_command_register("fdb/flush", "[bridge]", 0, 1,
5447 : : ofproto_unixctl_fdb_flush, NULL);
5448 : 615 : unixctl_command_register("fdb/show", "bridge", 1, 1,
5449 : : ofproto_unixctl_fdb_show, NULL);
5450 : 615 : unixctl_command_register("mdb/flush", "[bridge]", 0, 1,
5451 : : ofproto_unixctl_mcast_snooping_flush, NULL);
5452 : 615 : unixctl_command_register("mdb/show", "bridge", 1, 1,
5453 : : ofproto_unixctl_mcast_snooping_show, NULL);
5454 : 615 : unixctl_command_register("dpif/dump-dps", "", 0, 0,
5455 : : ofproto_unixctl_dpif_dump_dps, NULL);
5456 : 615 : unixctl_command_register("dpif/show", "", 0, 0, ofproto_unixctl_dpif_show,
5457 : : NULL);
5458 : 615 : unixctl_command_register("dpif/dump-flows", "[-m] bridge", 1, 2,
5459 : : ofproto_unixctl_dpif_dump_flows, NULL);
5460 : :
5461 : 615 : unixctl_command_register("ofproto/tnl-push-pop", "[on]|[off]", 1, 1,
5462 : : disable_tnl_push_pop, NULL);
5463 : :
5464 : 615 : unixctl_command_register("dpif/disable-truncate", "", 0, 0,
5465 : : disable_datapath_truncate, NULL);
5466 : : }
5467 : :
5468 : : /* Returns true if 'table' is the table used for internal rules,
5469 : : * false otherwise. */
5470 : : bool
5471 : 0 : table_is_internal(uint8_t table_id)
5472 : : {
5473 : 0 : return table_id == TBL_INTERNAL;
5474 : : }
5475 : :
5476 : :
5477 : : static odp_port_t
5478 : 8371 : ofp_port_to_odp_port(const struct ofproto_dpif *ofproto, ofp_port_t ofp_port)
5479 : : {
5480 : 8371 : const struct ofport_dpif *ofport = ofp_port_to_ofport(ofproto, ofp_port);
5481 [ + + ]: 8371 : return ofport ? ofport->odp_port : ODPP_NONE;
5482 : : }
5483 : :
5484 : : struct ofport_dpif *
5485 : 88064 : odp_port_to_ofport(const struct dpif_backer *backer, odp_port_t odp_port)
5486 : : {
5487 : : struct ofport_dpif *port;
5488 : :
5489 : 88064 : ovs_rwlock_rdlock(&backer->odp_to_ofport_lock);
5490 [ + + ][ - + ]: 127150 : HMAP_FOR_EACH_IN_BUCKET (port, odp_port_node, hash_odp_port(odp_port),
5491 : : &backer->odp_to_ofport_map) {
5492 [ + + ]: 122378 : if (port->odp_port == odp_port) {
5493 : 83292 : ovs_rwlock_unlock(&backer->odp_to_ofport_lock);
5494 : 83292 : return port;
5495 : : }
5496 : : }
5497 : :
5498 : 4772 : ovs_rwlock_unlock(&backer->odp_to_ofport_lock);
5499 : 4772 : return NULL;
5500 : : }
5501 : :
5502 : : static ofp_port_t
5503 : 18683 : odp_port_to_ofp_port(const struct ofproto_dpif *ofproto, odp_port_t odp_port)
5504 : : {
5505 : : struct ofport_dpif *port;
5506 : :
5507 : 18683 : port = odp_port_to_ofport(ofproto->backer, odp_port);
5508 [ + + ][ + - ]: 18683 : if (port && &ofproto->up == port->up.ofproto) {
5509 : 14588 : return port->up.ofp_port;
5510 : : } else {
5511 : 4095 : return OFPP_NONE;
5512 : : }
5513 : : }
5514 : :
5515 : : int
5516 : 4788 : ofproto_dpif_add_internal_flow(struct ofproto_dpif *ofproto,
5517 : : const struct match *match, int priority,
5518 : : uint16_t idle_timeout,
5519 : : const struct ofpbuf *ofpacts,
5520 : : struct rule **rulep)
5521 : : {
5522 : : struct ofputil_flow_mod fm;
5523 : : struct rule_dpif *rule;
5524 : : int error;
5525 : :
5526 : 4788 : fm = (struct ofputil_flow_mod) {
5527 : : .buffer_id = UINT32_MAX,
5528 : 4788 : .match = *match,
5529 : : .priority = priority,
5530 : : .table_id = TBL_INTERNAL,
5531 : : .command = OFPFC_ADD,
5532 : : .idle_timeout = idle_timeout,
5533 : : .flags = OFPUTIL_FF_HIDDEN_FIELDS | OFPUTIL_FF_NO_READONLY,
5534 : 4788 : .ofpacts = ofpacts->data,
5535 : 4788 : .ofpacts_len = ofpacts->size,
5536 : : };
5537 : :
5538 : 4788 : error = ofproto_flow_mod(&ofproto->up, &fm);
5539 [ - + ]: 4788 : if (error) {
5540 [ # # ]: 0 : VLOG_ERR_RL(&rl, "failed to add internal flow (%s)",
5541 : : ofperr_to_string(error));
5542 : 0 : *rulep = NULL;
5543 : 0 : return error;
5544 : : }
5545 : :
5546 : 4788 : rule = rule_dpif_lookup_in_table(ofproto,
5547 : : ofproto_dpif_get_tables_version(ofproto),
5548 : : TBL_INTERNAL, &fm.match.flow,
5549 : : &fm.match.wc);
5550 [ + - ]: 4788 : if (rule) {
5551 : 4788 : *rulep = &rule->up;
5552 : : } else {
5553 : 0 : OVS_NOT_REACHED();
5554 : : }
5555 : 4788 : return 0;
5556 : : }
5557 : :
5558 : : int
5559 : 512 : ofproto_dpif_delete_internal_flow(struct ofproto_dpif *ofproto,
5560 : : struct match *match, int priority)
5561 : : {
5562 : : struct ofputil_flow_mod fm;
5563 : : int error;
5564 : :
5565 : 512 : fm = (struct ofputil_flow_mod) {
5566 : : .buffer_id = UINT32_MAX,
5567 : 512 : .match = *match,
5568 : : .priority = priority,
5569 : : .table_id = TBL_INTERNAL,
5570 : : .flags = OFPUTIL_FF_HIDDEN_FIELDS | OFPUTIL_FF_NO_READONLY,
5571 : : .command = OFPFC_DELETE_STRICT,
5572 : : };
5573 : :
5574 : 512 : error = ofproto_flow_mod(&ofproto->up, &fm);
5575 [ - + ]: 512 : if (error) {
5576 [ # # ]: 0 : VLOG_ERR_RL(&rl, "failed to delete internal flow (%s)",
5577 : : ofperr_to_string(error));
5578 : 0 : return error;
5579 : : }
5580 : :
5581 : 512 : return 0;
5582 : : }
5583 : :
5584 : : const struct uuid *
5585 : 3711 : ofproto_dpif_get_uuid(const struct ofproto_dpif *ofproto)
5586 : : {
5587 : 3711 : return &ofproto->uuid;
5588 : : }
5589 : :
5590 : : const struct ofproto_class ofproto_dpif_class = {
5591 : : init,
5592 : : enumerate_types,
5593 : : enumerate_names,
5594 : : del,
5595 : : port_open_type,
5596 : : type_run,
5597 : : type_wait,
5598 : : alloc,
5599 : : construct,
5600 : : destruct,
5601 : : dealloc,
5602 : : run,
5603 : : ofproto_dpif_wait,
5604 : : NULL, /* get_memory_usage. */
5605 : : type_get_memory_usage,
5606 : : flush,
5607 : : query_tables,
5608 : : set_tables_version,
5609 : : port_alloc,
5610 : : port_construct,
5611 : : port_destruct,
5612 : : port_dealloc,
5613 : : port_modified,
5614 : : port_reconfigured,
5615 : : port_query_by_name,
5616 : : port_add,
5617 : : port_del,
5618 : : port_set_config,
5619 : : port_get_stats,
5620 : : port_dump_start,
5621 : : port_dump_next,
5622 : : port_dump_done,
5623 : : port_poll,
5624 : : port_poll_wait,
5625 : : port_is_lacp_current,
5626 : : port_get_lacp_stats,
5627 : : NULL, /* rule_choose_table */
5628 : : rule_alloc,
5629 : : rule_construct,
5630 : : rule_insert,
5631 : : NULL, /* rule_delete */
5632 : : rule_destruct,
5633 : : rule_dealloc,
5634 : : rule_get_stats,
5635 : : set_frag_handling,
5636 : : packet_out,
5637 : : nxt_resume,
5638 : : set_netflow,
5639 : : get_netflow_ids,
5640 : : set_sflow,
5641 : : set_ipfix,
5642 : : get_ipfix_stats,
5643 : : set_cfm,
5644 : : cfm_status_changed,
5645 : : get_cfm_status,
5646 : : set_lldp,
5647 : : get_lldp_status,
5648 : : set_aa,
5649 : : aa_mapping_set,
5650 : : aa_mapping_unset,
5651 : : aa_vlan_get_queued,
5652 : : aa_vlan_get_queue_size,
5653 : : set_bfd,
5654 : : bfd_status_changed,
5655 : : get_bfd_status,
5656 : : set_stp,
5657 : : get_stp_status,
5658 : : set_stp_port,
5659 : : get_stp_port_status,
5660 : : get_stp_port_stats,
5661 : : set_rstp,
5662 : : get_rstp_status,
5663 : : set_rstp_port,
5664 : : get_rstp_port_status,
5665 : : set_queues,
5666 : : bundle_set,
5667 : : bundle_remove,
5668 : : mirror_set__,
5669 : : mirror_get_stats__,
5670 : : set_flood_vlans,
5671 : : is_mirror_output_bundle,
5672 : : forward_bpdu_changed,
5673 : : set_mac_table_config,
5674 : : set_mcast_snooping,
5675 : : set_mcast_snooping_port,
5676 : : NULL, /* meter_get_features */
5677 : : NULL, /* meter_set */
5678 : : NULL, /* meter_get */
5679 : : NULL, /* meter_del */
5680 : : group_alloc, /* group_alloc */
5681 : : group_construct, /* group_construct */
5682 : : group_destruct, /* group_destruct */
5683 : : group_dealloc, /* group_dealloc */
5684 : : group_modify, /* group_modify */
5685 : : group_get_stats, /* group_get_stats */
5686 : : get_datapath_version, /* get_datapath_version */
5687 : : };
|