2 * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc.
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:
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 #include "dpif-netdev.h"
24 #include <netinet/in.h>
25 #include <sys/socket.h>
30 #include <sys/ioctl.h>
34 #include "classifier.h"
38 #include "dpif-provider.h"
40 #include "dynamic-string.h"
41 #include "fat-rwlock.h"
46 #include "meta-flow.h"
48 #include "netdev-dpdk.h"
49 #include "netdev-vport.h"
51 #include "odp-execute.h"
53 #include "ofp-print.h"
56 #include "packet-dpif.h"
58 #include "poll-loop.h"
68 VLOG_DEFINE_THIS_MODULE(dpif_netdev
);
70 /* By default, choose a priority in the middle. */
71 #define NETDEV_RULE_PRIORITY 0x8000
73 #define FLOW_DUMP_MAX_BATCH 50
74 /* Use per thread recirc_depth to prevent recirculation loop. */
75 #define MAX_RECIRC_DEPTH 5
76 DEFINE_STATIC_PER_THREAD_DATA(uint32_t, recirc_depth
, 0)
78 /* Configuration parameters. */
79 enum { MAX_FLOWS
= 65536 }; /* Maximum number of flows in flow table. */
81 /* Protects against changes to 'dp_netdevs'. */
82 static struct ovs_mutex dp_netdev_mutex
= OVS_MUTEX_INITIALIZER
;
84 /* Contains all 'struct dp_netdev's. */
85 static struct shash dp_netdevs
OVS_GUARDED_BY(dp_netdev_mutex
)
86 = SHASH_INITIALIZER(&dp_netdevs
);
88 struct dp_netdev_queue
{
89 unsigned int packet_count
;
91 struct dpif_upcall upcalls
[NETDEV_MAX_RX_BATCH
];
92 struct ofpbuf bufs
[NETDEV_MAX_RX_BATCH
];
95 #define DP_NETDEV_QUEUE_INITIALIZER { .packet_count = 0 }
97 /* Datapath based on the network device interface from netdev.h.
103 * Some members, marked 'const', are immutable. Accessing other members
104 * requires synchronization, as noted in more detail below.
106 * Acquisition order is, from outermost to innermost:
108 * dp_netdev_mutex (global)
113 const struct dpif_class
*const class;
114 const char *const name
;
116 struct ovs_refcount ref_cnt
;
117 atomic_flag destroyed
;
121 * Writers of 'flow_table' must take the 'flow_mutex'. Corresponding
122 * changes to 'cls' must be made while still holding the 'flow_mutex'.
124 struct ovs_mutex flow_mutex
;
125 struct classifier cls
;
126 struct cmap flow_table OVS_GUARDED
; /* Flow table. */
130 * ovsthread_stats is internally synchronized. */
131 struct ovsthread_stats stats
; /* Contains 'struct dp_netdev_stats *'. */
135 * Protected by RCU. Take the mutex to add or remove ports. */
136 struct ovs_mutex port_mutex
;
138 struct seq
*port_seq
; /* Incremented whenever a port changes. */
140 /* Protects access to ofproto-dpif-upcall interface during revalidator
141 * thread synchronization. */
142 struct fat_rwlock upcall_rwlock
;
143 exec_upcall_cb
*upcall_cb
; /* Callback function for executing upcalls. */
145 /* Forwarding threads. */
146 struct latch exit_latch
;
147 struct pmd_thread
*pmd_threads
;
148 size_t n_pmd_threads
;
152 static struct dp_netdev_port
*dp_netdev_lookup_port(const struct dp_netdev
*dp
,
156 DP_STAT_HIT
, /* Packets that matched in the flow table. */
157 DP_STAT_MISS
, /* Packets that did not match. */
158 DP_STAT_LOST
, /* Packets not passed up to the client. */
162 /* Contained by struct dp_netdev's 'stats' member. */
163 struct dp_netdev_stats
{
164 struct ovs_mutex mutex
; /* Protects 'n'. */
166 /* Indexed by DP_STAT_*, protected by 'mutex'. */
167 unsigned long long int n
[DP_N_STATS
] OVS_GUARDED
;
171 /* A port in a netdev-based datapath. */
172 struct dp_netdev_port
{
173 struct cmap_node node
; /* Node in dp_netdev's 'ports'. */
175 struct netdev
*netdev
;
176 struct netdev_saved_flags
*sf
;
177 struct netdev_rxq
**rxq
;
178 struct ovs_refcount ref_cnt
;
179 char *type
; /* Port type as requested by user. */
183 /* Stores a miniflow */
185 /* There are fields in the flow structure that we never use. Therefore we can
186 * save a few words of memory */
187 #define NETDEV_KEY_BUF_SIZE_U32 (FLOW_U32S - MINI_N_INLINE \
188 - FLOW_U32_SIZE(regs) \
189 - FLOW_U32_SIZE(metadata) \
191 struct netdev_flow_key
{
192 struct miniflow flow
;
193 uint32_t buf
[NETDEV_KEY_BUF_SIZE_U32
];
196 /* A flow in dp_netdev's 'flow_table'.
202 * Except near the beginning or ending of its lifespan, rule 'rule' belongs to
203 * its dp_netdev's classifier. The text below calls this classifier 'cls'.
208 * The thread safety rules described here for "struct dp_netdev_flow" are
209 * motivated by two goals:
211 * - Prevent threads that read members of "struct dp_netdev_flow" from
212 * reading bad data due to changes by some thread concurrently modifying
215 * - Prevent two threads making changes to members of a given "struct
216 * dp_netdev_flow" from interfering with each other.
222 * A flow 'flow' may be accessed without a risk of being freed by code that
223 * holds a read-lock or write-lock on 'cls->rwlock' or that owns a reference to
224 * 'flow->ref_cnt' (or both). Code that needs to hold onto a flow for a while
225 * should take 'cls->rwlock', find the flow it needs, increment 'flow->ref_cnt'
226 * with dpif_netdev_flow_ref(), and drop 'cls->rwlock'.
228 * 'flow->ref_cnt' protects 'flow' from being freed. It doesn't protect the
229 * flow from being deleted from 'cls' (that's 'cls->rwlock') and it doesn't
230 * protect members of 'flow' from modification.
232 * Some members, marked 'const', are immutable. Accessing other members
233 * requires synchronization, as noted in more detail below.
235 struct dp_netdev_flow
{
236 /* Packet classification. */
237 const struct cls_rule cr
; /* In owning dp_netdev's 'cls'. */
239 /* Hash table index by unmasked flow. */
240 const struct cmap_node node
; /* In owning dp_netdev's 'flow_table'. */
241 const struct flow flow
; /* The flow that created this entry. */
245 * Reading or writing these members requires 'mutex'. */
246 struct ovsthread_stats stats
; /* Contains "struct dp_netdev_flow_stats". */
249 OVSRCU_TYPE(struct dp_netdev_actions
*) actions
;
252 static void dp_netdev_flow_free(struct dp_netdev_flow
*);
254 /* Contained by struct dp_netdev_flow's 'stats' member. */
255 struct dp_netdev_flow_stats
{
256 struct ovs_mutex mutex
; /* Guards all the other members. */
258 long long int used OVS_GUARDED
; /* Last used time, in monotonic msecs. */
259 long long int packet_count OVS_GUARDED
; /* Number of packets matched. */
260 long long int byte_count OVS_GUARDED
; /* Number of bytes matched. */
261 uint16_t tcp_flags OVS_GUARDED
; /* Bitwise-OR of seen tcp_flags values. */
264 /* A set of datapath actions within a "struct dp_netdev_flow".
270 * A struct dp_netdev_actions 'actions' is protected with RCU. */
271 struct dp_netdev_actions
{
272 /* These members are immutable: they do not change during the struct's
274 struct nlattr
*actions
; /* Sequence of OVS_ACTION_ATTR_* attributes. */
275 unsigned int size
; /* Size of 'actions', in bytes. */
278 struct dp_netdev_actions
*dp_netdev_actions_create(const struct nlattr
*,
280 struct dp_netdev_actions
*dp_netdev_flow_get_actions(
281 const struct dp_netdev_flow
*);
282 static void dp_netdev_actions_free(struct dp_netdev_actions
*);
284 /* PMD: Poll modes drivers. PMD accesses devices via polling to eliminate
285 * the performance overhead of interrupt processing. Therefore netdev can
286 * not implement rx-wait for these devices. dpif-netdev needs to poll
287 * these device to check for recv buffer. pmd-thread does polling for
288 * devices assigned to itself thread.
290 * DPDK used PMD for accessing NIC.
292 * A thread that receives packets from PMD ports, looks them up in the flow
293 * table, and executes the actions it finds.
296 struct dp_netdev
*dp
;
299 atomic_uint change_seq
;
302 /* Interface to netdev-based datapath. */
305 struct dp_netdev
*dp
;
306 uint64_t last_port_seq
;
309 static int get_port_by_number(struct dp_netdev
*dp
, odp_port_t port_no
,
310 struct dp_netdev_port
**portp
);
311 static int get_port_by_name(struct dp_netdev
*dp
, const char *devname
,
312 struct dp_netdev_port
**portp
);
313 static void dp_netdev_free(struct dp_netdev
*)
314 OVS_REQUIRES(dp_netdev_mutex
);
315 static void dp_netdev_flow_flush(struct dp_netdev
*);
316 static int do_add_port(struct dp_netdev
*dp
, const char *devname
,
317 const char *type
, odp_port_t port_no
)
318 OVS_REQUIRES(dp
->port_mutex
);
319 static void do_del_port(struct dp_netdev
*dp
, struct dp_netdev_port
*)
320 OVS_REQUIRES(dp
->port_mutex
);
321 static int dpif_netdev_open(const struct dpif_class
*, const char *name
,
322 bool create
, struct dpif
**);
323 static int dp_netdev_queue_userspace_packet(struct dp_netdev_queue
*,
324 struct ofpbuf
*, int type
,
325 const struct miniflow
*,
326 const struct nlattr
*);
327 static void dp_netdev_execute_userspace_queue(struct dp_netdev_queue
*,
329 static void dp_netdev_execute_actions(struct dp_netdev
*dp
,
330 struct dpif_packet
**, int c
,
331 bool may_steal
, struct pkt_metadata
*,
332 const struct nlattr
*actions
,
334 static void dp_netdev_port_input(struct dp_netdev
*dp
,
335 struct dpif_packet
**packets
, int cnt
,
338 static void dp_netdev_set_pmd_threads(struct dp_netdev
*, int n
);
339 static void dp_netdev_disable_upcall(struct dp_netdev
*);
341 static struct dpif_netdev
*
342 dpif_netdev_cast(const struct dpif
*dpif
)
344 ovs_assert(dpif
->dpif_class
->open
== dpif_netdev_open
);
345 return CONTAINER_OF(dpif
, struct dpif_netdev
, dpif
);
348 static struct dp_netdev
*
349 get_dp_netdev(const struct dpif
*dpif
)
351 return dpif_netdev_cast(dpif
)->dp
;
355 dpif_netdev_enumerate(struct sset
*all_dps
,
356 const struct dpif_class
*dpif_class
)
358 struct shash_node
*node
;
360 ovs_mutex_lock(&dp_netdev_mutex
);
361 SHASH_FOR_EACH(node
, &dp_netdevs
) {
362 struct dp_netdev
*dp
= node
->data
;
363 if (dpif_class
!= dp
->class) {
364 /* 'dp_netdevs' contains both "netdev" and "dummy" dpifs.
365 * If the class doesn't match, skip this dpif. */
368 sset_add(all_dps
, node
->name
);
370 ovs_mutex_unlock(&dp_netdev_mutex
);
376 dpif_netdev_class_is_dummy(const struct dpif_class
*class)
378 return class != &dpif_netdev_class
;
382 dpif_netdev_port_open_type(const struct dpif_class
*class, const char *type
)
384 return strcmp(type
, "internal") ? type
385 : dpif_netdev_class_is_dummy(class) ? "dummy"
390 create_dpif_netdev(struct dp_netdev
*dp
)
392 uint16_t netflow_id
= hash_string(dp
->name
, 0);
393 struct dpif_netdev
*dpif
;
395 ovs_refcount_ref(&dp
->ref_cnt
);
397 dpif
= xmalloc(sizeof *dpif
);
398 dpif_init(&dpif
->dpif
, dp
->class, dp
->name
, netflow_id
>> 8, netflow_id
);
400 dpif
->last_port_seq
= seq_read(dp
->port_seq
);
405 /* Choose an unused, non-zero port number and return it on success.
406 * Return ODPP_NONE on failure. */
408 choose_port(struct dp_netdev
*dp
, const char *name
)
409 OVS_REQUIRES(dp
->port_mutex
)
413 if (dp
->class != &dpif_netdev_class
) {
417 /* If the port name begins with "br", start the number search at
418 * 100 to make writing tests easier. */
419 if (!strncmp(name
, "br", 2)) {
423 /* If the port name contains a number, try to assign that port number.
424 * This can make writing unit tests easier because port numbers are
426 for (p
= name
; *p
!= '\0'; p
++) {
427 if (isdigit((unsigned char) *p
)) {
428 port_no
= start_no
+ strtol(p
, NULL
, 10);
429 if (port_no
> 0 && port_no
!= odp_to_u32(ODPP_NONE
)
430 && !dp_netdev_lookup_port(dp
, u32_to_odp(port_no
))) {
431 return u32_to_odp(port_no
);
438 for (port_no
= 1; port_no
<= UINT16_MAX
; port_no
++) {
439 if (!dp_netdev_lookup_port(dp
, u32_to_odp(port_no
))) {
440 return u32_to_odp(port_no
);
448 create_dp_netdev(const char *name
, const struct dpif_class
*class,
449 struct dp_netdev
**dpp
)
450 OVS_REQUIRES(dp_netdev_mutex
)
452 struct dp_netdev
*dp
;
455 dp
= xzalloc(sizeof *dp
);
456 shash_add(&dp_netdevs
, name
, dp
);
458 *CONST_CAST(const struct dpif_class
**, &dp
->class) = class;
459 *CONST_CAST(const char **, &dp
->name
) = xstrdup(name
);
460 ovs_refcount_init(&dp
->ref_cnt
);
461 atomic_flag_clear(&dp
->destroyed
);
463 ovs_mutex_init(&dp
->flow_mutex
);
464 classifier_init(&dp
->cls
, NULL
);
465 cmap_init(&dp
->flow_table
);
467 ovsthread_stats_init(&dp
->stats
);
469 ovs_mutex_init(&dp
->port_mutex
);
470 cmap_init(&dp
->ports
);
471 dp
->port_seq
= seq_create();
472 latch_init(&dp
->exit_latch
);
473 fat_rwlock_init(&dp
->upcall_rwlock
);
475 /* Disable upcalls by default. */
476 dp_netdev_disable_upcall(dp
);
477 dp
->upcall_cb
= NULL
;
479 ovs_mutex_lock(&dp
->port_mutex
);
480 error
= do_add_port(dp
, name
, "internal", ODPP_LOCAL
);
481 ovs_mutex_unlock(&dp
->port_mutex
);
492 dpif_netdev_open(const struct dpif_class
*class, const char *name
,
493 bool create
, struct dpif
**dpifp
)
495 struct dp_netdev
*dp
;
498 ovs_mutex_lock(&dp_netdev_mutex
);
499 dp
= shash_find_data(&dp_netdevs
, name
);
501 error
= create
? create_dp_netdev(name
, class, &dp
) : ENODEV
;
503 error
= (dp
->class != class ? EINVAL
508 *dpifp
= create_dpif_netdev(dp
);
511 ovs_mutex_unlock(&dp_netdev_mutex
);
516 /* Requires dp_netdev_mutex so that we can't get a new reference to 'dp'
517 * through the 'dp_netdevs' shash while freeing 'dp'. */
519 dp_netdev_free(struct dp_netdev
*dp
)
520 OVS_REQUIRES(dp_netdev_mutex
)
522 struct dp_netdev_port
*port
;
523 struct dp_netdev_stats
*bucket
;
526 shash_find_and_delete(&dp_netdevs
, dp
->name
);
528 dp_netdev_set_pmd_threads(dp
, 0);
529 free(dp
->pmd_threads
);
531 dp_netdev_flow_flush(dp
);
532 ovs_mutex_lock(&dp
->port_mutex
);
533 CMAP_FOR_EACH (port
, node
, &dp
->ports
) {
534 do_del_port(dp
, port
);
536 ovs_mutex_unlock(&dp
->port_mutex
);
538 OVSTHREAD_STATS_FOR_EACH_BUCKET (bucket
, i
, &dp
->stats
) {
539 ovs_mutex_destroy(&bucket
->mutex
);
540 free_cacheline(bucket
);
542 ovsthread_stats_destroy(&dp
->stats
);
544 classifier_destroy(&dp
->cls
);
545 cmap_destroy(&dp
->flow_table
);
546 ovs_mutex_destroy(&dp
->flow_mutex
);
547 seq_destroy(dp
->port_seq
);
548 cmap_destroy(&dp
->ports
);
549 fat_rwlock_destroy(&dp
->upcall_rwlock
);
550 latch_destroy(&dp
->exit_latch
);
551 free(CONST_CAST(char *, dp
->name
));
556 dp_netdev_unref(struct dp_netdev
*dp
)
559 /* Take dp_netdev_mutex so that, if dp->ref_cnt falls to zero, we can't
560 * get a new reference to 'dp' through the 'dp_netdevs' shash. */
561 ovs_mutex_lock(&dp_netdev_mutex
);
562 if (ovs_refcount_unref_relaxed(&dp
->ref_cnt
) == 1) {
565 ovs_mutex_unlock(&dp_netdev_mutex
);
570 dpif_netdev_close(struct dpif
*dpif
)
572 struct dp_netdev
*dp
= get_dp_netdev(dpif
);
579 dpif_netdev_destroy(struct dpif
*dpif
)
581 struct dp_netdev
*dp
= get_dp_netdev(dpif
);
583 if (!atomic_flag_test_and_set(&dp
->destroyed
)) {
584 if (ovs_refcount_unref_relaxed(&dp
->ref_cnt
) == 1) {
585 /* Can't happen: 'dpif' still owns a reference to 'dp'. */
594 dpif_netdev_get_stats(const struct dpif
*dpif
, struct dpif_dp_stats
*stats
)
596 struct dp_netdev
*dp
= get_dp_netdev(dpif
);
597 struct dp_netdev_stats
*bucket
;
600 stats
->n_flows
= cmap_count(&dp
->flow_table
);
602 stats
->n_hit
= stats
->n_missed
= stats
->n_lost
= 0;
603 OVSTHREAD_STATS_FOR_EACH_BUCKET (bucket
, i
, &dp
->stats
) {
604 ovs_mutex_lock(&bucket
->mutex
);
605 stats
->n_hit
+= bucket
->n
[DP_STAT_HIT
];
606 stats
->n_missed
+= bucket
->n
[DP_STAT_MISS
];
607 stats
->n_lost
+= bucket
->n
[DP_STAT_LOST
];
608 ovs_mutex_unlock(&bucket
->mutex
);
610 stats
->n_masks
= UINT32_MAX
;
611 stats
->n_mask_hit
= UINT64_MAX
;
617 dp_netdev_reload_pmd_threads(struct dp_netdev
*dp
)
621 for (i
= 0; i
< dp
->n_pmd_threads
; i
++) {
622 struct pmd_thread
*f
= &dp
->pmd_threads
[i
];
625 atomic_add(&f
->change_seq
, 1, &id
);
630 hash_port_no(odp_port_t port_no
)
632 return hash_int(odp_to_u32(port_no
), 0);
636 do_add_port(struct dp_netdev
*dp
, const char *devname
, const char *type
,
638 OVS_REQUIRES(dp
->port_mutex
)
640 struct netdev_saved_flags
*sf
;
641 struct dp_netdev_port
*port
;
642 struct netdev
*netdev
;
643 enum netdev_flags flags
;
644 const char *open_type
;
648 /* XXX reject devices already in some dp_netdev. */
650 /* Open and validate network device. */
651 open_type
= dpif_netdev_port_open_type(dp
->class, type
);
652 error
= netdev_open(devname
, open_type
, &netdev
);
656 /* XXX reject non-Ethernet devices */
658 netdev_get_flags(netdev
, &flags
);
659 if (flags
& NETDEV_LOOPBACK
) {
660 VLOG_ERR("%s: cannot add a loopback device", devname
);
661 netdev_close(netdev
);
665 port
= xzalloc(sizeof *port
);
666 port
->port_no
= port_no
;
667 port
->netdev
= netdev
;
668 port
->rxq
= xmalloc(sizeof *port
->rxq
* netdev_n_rxq(netdev
));
669 port
->type
= xstrdup(type
);
670 for (i
= 0; i
< netdev_n_rxq(netdev
); i
++) {
671 error
= netdev_rxq_open(netdev
, &port
->rxq
[i
], i
);
673 && !(error
== EOPNOTSUPP
&& dpif_netdev_class_is_dummy(dp
->class))) {
674 VLOG_ERR("%s: cannot receive packets on this network device (%s)",
675 devname
, ovs_strerror(errno
));
676 netdev_close(netdev
);
681 error
= netdev_turn_flags_on(netdev
, NETDEV_PROMISC
, &sf
);
683 for (i
= 0; i
< netdev_n_rxq(netdev
); i
++) {
684 netdev_rxq_close(port
->rxq
[i
]);
686 netdev_close(netdev
);
693 if (netdev_is_pmd(netdev
)) {
695 dp_netdev_set_pmd_threads(dp
, NR_PMD_THREADS
);
696 dp_netdev_reload_pmd_threads(dp
);
698 ovs_refcount_init(&port
->ref_cnt
);
700 cmap_insert(&dp
->ports
, &port
->node
, hash_port_no(port_no
));
701 seq_change(dp
->port_seq
);
707 dpif_netdev_port_add(struct dpif
*dpif
, struct netdev
*netdev
,
708 odp_port_t
*port_nop
)
710 struct dp_netdev
*dp
= get_dp_netdev(dpif
);
711 char namebuf
[NETDEV_VPORT_NAME_BUFSIZE
];
712 const char *dpif_port
;
716 ovs_mutex_lock(&dp
->port_mutex
);
717 dpif_port
= netdev_vport_get_dpif_port(netdev
, namebuf
, sizeof namebuf
);
718 if (*port_nop
!= ODPP_NONE
) {
720 error
= dp_netdev_lookup_port(dp
, *port_nop
) ? EBUSY
: 0;
722 port_no
= choose_port(dp
, dpif_port
);
723 error
= port_no
== ODPP_NONE
? EFBIG
: 0;
727 error
= do_add_port(dp
, dpif_port
, netdev_get_type(netdev
), port_no
);
729 ovs_mutex_unlock(&dp
->port_mutex
);
735 dpif_netdev_port_del(struct dpif
*dpif
, odp_port_t port_no
)
737 struct dp_netdev
*dp
= get_dp_netdev(dpif
);
740 ovs_mutex_lock(&dp
->port_mutex
);
741 if (port_no
== ODPP_LOCAL
) {
744 struct dp_netdev_port
*port
;
746 error
= get_port_by_number(dp
, port_no
, &port
);
748 do_del_port(dp
, port
);
751 ovs_mutex_unlock(&dp
->port_mutex
);
757 is_valid_port_number(odp_port_t port_no
)
759 return port_no
!= ODPP_NONE
;
762 static struct dp_netdev_port
*
763 dp_netdev_lookup_port(const struct dp_netdev
*dp
, odp_port_t port_no
)
765 struct dp_netdev_port
*port
;
767 CMAP_FOR_EACH_WITH_HASH (port
, node
, hash_port_no(port_no
), &dp
->ports
) {
768 if (port
->port_no
== port_no
) {
776 get_port_by_number(struct dp_netdev
*dp
,
777 odp_port_t port_no
, struct dp_netdev_port
**portp
)
779 if (!is_valid_port_number(port_no
)) {
783 *portp
= dp_netdev_lookup_port(dp
, port_no
);
784 return *portp
? 0 : ENOENT
;
789 port_ref(struct dp_netdev_port
*port
)
792 ovs_refcount_ref(&port
->ref_cnt
);
797 port_destroy__(struct dp_netdev_port
*port
)
799 int n_rxq
= netdev_n_rxq(port
->netdev
);
802 netdev_close(port
->netdev
);
803 netdev_restore_flags(port
->sf
);
805 for (i
= 0; i
< n_rxq
; i
++) {
806 netdev_rxq_close(port
->rxq
[i
]);
814 port_unref(struct dp_netdev_port
*port
)
816 if (port
&& ovs_refcount_unref_relaxed(&port
->ref_cnt
) == 1) {
817 ovsrcu_postpone(port_destroy__
, port
);
822 get_port_by_name(struct dp_netdev
*dp
,
823 const char *devname
, struct dp_netdev_port
**portp
)
824 OVS_REQUIRES(dp
->port_mutex
)
826 struct dp_netdev_port
*port
;
828 CMAP_FOR_EACH (port
, node
, &dp
->ports
) {
829 if (!strcmp(netdev_get_name(port
->netdev
), devname
)) {
838 do_del_port(struct dp_netdev
*dp
, struct dp_netdev_port
*port
)
839 OVS_REQUIRES(dp
->port_mutex
)
841 cmap_remove(&dp
->ports
, &port
->node
, hash_odp_port(port
->port_no
));
842 seq_change(dp
->port_seq
);
843 if (netdev_is_pmd(port
->netdev
)) {
844 dp_netdev_reload_pmd_threads(dp
);
851 answer_port_query(const struct dp_netdev_port
*port
,
852 struct dpif_port
*dpif_port
)
854 dpif_port
->name
= xstrdup(netdev_get_name(port
->netdev
));
855 dpif_port
->type
= xstrdup(port
->type
);
856 dpif_port
->port_no
= port
->port_no
;
860 dpif_netdev_port_query_by_number(const struct dpif
*dpif
, odp_port_t port_no
,
861 struct dpif_port
*dpif_port
)
863 struct dp_netdev
*dp
= get_dp_netdev(dpif
);
864 struct dp_netdev_port
*port
;
867 error
= get_port_by_number(dp
, port_no
, &port
);
868 if (!error
&& dpif_port
) {
869 answer_port_query(port
, dpif_port
);
876 dpif_netdev_port_query_by_name(const struct dpif
*dpif
, const char *devname
,
877 struct dpif_port
*dpif_port
)
879 struct dp_netdev
*dp
= get_dp_netdev(dpif
);
880 struct dp_netdev_port
*port
;
883 ovs_mutex_lock(&dp
->port_mutex
);
884 error
= get_port_by_name(dp
, devname
, &port
);
885 if (!error
&& dpif_port
) {
886 answer_port_query(port
, dpif_port
);
888 ovs_mutex_unlock(&dp
->port_mutex
);
894 dp_netdev_flow_free(struct dp_netdev_flow
*flow
)
896 struct dp_netdev_flow_stats
*bucket
;
899 OVSTHREAD_STATS_FOR_EACH_BUCKET (bucket
, i
, &flow
->stats
) {
900 ovs_mutex_destroy(&bucket
->mutex
);
901 free_cacheline(bucket
);
903 ovsthread_stats_destroy(&flow
->stats
);
905 cls_rule_destroy(CONST_CAST(struct cls_rule
*, &flow
->cr
));
906 dp_netdev_actions_free(dp_netdev_flow_get_actions(flow
));
911 dp_netdev_remove_flow(struct dp_netdev
*dp
, struct dp_netdev_flow
*flow
)
912 OVS_REQUIRES(dp
->flow_mutex
)
914 struct cls_rule
*cr
= CONST_CAST(struct cls_rule
*, &flow
->cr
);
915 struct cmap_node
*node
= CONST_CAST(struct cmap_node
*, &flow
->node
);
917 classifier_remove(&dp
->cls
, cr
);
918 cmap_remove(&dp
->flow_table
, node
, flow_hash(&flow
->flow
, 0));
919 ovsrcu_postpone(dp_netdev_flow_free
, flow
);
923 dp_netdev_flow_flush(struct dp_netdev
*dp
)
925 struct dp_netdev_flow
*netdev_flow
;
927 ovs_mutex_lock(&dp
->flow_mutex
);
928 CMAP_FOR_EACH_SAFE (netdev_flow
, node
, &dp
->flow_table
) {
929 dp_netdev_remove_flow(dp
, netdev_flow
);
931 ovs_mutex_unlock(&dp
->flow_mutex
);
935 dpif_netdev_flow_flush(struct dpif
*dpif
)
937 struct dp_netdev
*dp
= get_dp_netdev(dpif
);
939 dp_netdev_flow_flush(dp
);
943 struct dp_netdev_port_state
{
944 struct cmap_position position
;
949 dpif_netdev_port_dump_start(const struct dpif
*dpif OVS_UNUSED
, void **statep
)
951 *statep
= xzalloc(sizeof(struct dp_netdev_port_state
));
956 dpif_netdev_port_dump_next(const struct dpif
*dpif
, void *state_
,
957 struct dpif_port
*dpif_port
)
959 struct dp_netdev_port_state
*state
= state_
;
960 struct dp_netdev
*dp
= get_dp_netdev(dpif
);
961 struct cmap_node
*node
;
964 node
= cmap_next_position(&dp
->ports
, &state
->position
);
966 struct dp_netdev_port
*port
;
968 port
= CONTAINER_OF(node
, struct dp_netdev_port
, node
);
971 state
->name
= xstrdup(netdev_get_name(port
->netdev
));
972 dpif_port
->name
= state
->name
;
973 dpif_port
->type
= port
->type
;
974 dpif_port
->port_no
= port
->port_no
;
985 dpif_netdev_port_dump_done(const struct dpif
*dpif OVS_UNUSED
, void *state_
)
987 struct dp_netdev_port_state
*state
= state_
;
994 dpif_netdev_port_poll(const struct dpif
*dpif_
, char **devnamep OVS_UNUSED
)
996 struct dpif_netdev
*dpif
= dpif_netdev_cast(dpif_
);
997 uint64_t new_port_seq
;
1000 new_port_seq
= seq_read(dpif
->dp
->port_seq
);
1001 if (dpif
->last_port_seq
!= new_port_seq
) {
1002 dpif
->last_port_seq
= new_port_seq
;
1012 dpif_netdev_port_poll_wait(const struct dpif
*dpif_
)
1014 struct dpif_netdev
*dpif
= dpif_netdev_cast(dpif_
);
1016 seq_wait(dpif
->dp
->port_seq
, dpif
->last_port_seq
);
1019 static struct dp_netdev_flow
*
1020 dp_netdev_flow_cast(const struct cls_rule
*cr
)
1022 return cr
? CONTAINER_OF(cr
, struct dp_netdev_flow
, cr
) : NULL
;
1025 static struct dp_netdev_flow
*
1026 dp_netdev_lookup_flow(const struct dp_netdev
*dp
, const struct miniflow
*key
)
1028 struct dp_netdev_flow
*netdev_flow
;
1029 struct cls_rule
*rule
;
1031 classifier_lookup_miniflow_batch(&dp
->cls
, &key
, &rule
, 1);
1032 netdev_flow
= dp_netdev_flow_cast(rule
);
1037 static struct dp_netdev_flow
*
1038 dp_netdev_find_flow(const struct dp_netdev
*dp
, const struct flow
*flow
)
1040 struct dp_netdev_flow
*netdev_flow
;
1042 CMAP_FOR_EACH_WITH_HASH (netdev_flow
, node
, flow_hash(flow
, 0),
1044 if (flow_equal(&netdev_flow
->flow
, flow
)) {
1053 get_dpif_flow_stats(struct dp_netdev_flow
*netdev_flow
,
1054 struct dpif_flow_stats
*stats
)
1056 struct dp_netdev_flow_stats
*bucket
;
1059 memset(stats
, 0, sizeof *stats
);
1060 OVSTHREAD_STATS_FOR_EACH_BUCKET (bucket
, i
, &netdev_flow
->stats
) {
1061 ovs_mutex_lock(&bucket
->mutex
);
1062 stats
->n_packets
+= bucket
->packet_count
;
1063 stats
->n_bytes
+= bucket
->byte_count
;
1064 stats
->used
= MAX(stats
->used
, bucket
->used
);
1065 stats
->tcp_flags
|= bucket
->tcp_flags
;
1066 ovs_mutex_unlock(&bucket
->mutex
);
1071 dpif_netdev_mask_from_nlattrs(const struct nlattr
*key
, uint32_t key_len
,
1072 const struct nlattr
*mask_key
,
1073 uint32_t mask_key_len
, const struct flow
*flow
,
1077 enum odp_key_fitness fitness
;
1079 fitness
= odp_flow_key_to_mask(mask_key
, mask_key_len
, mask
, flow
);
1081 /* This should not happen: it indicates that
1082 * odp_flow_key_from_mask() and odp_flow_key_to_mask()
1083 * disagree on the acceptable form of a mask. Log the problem
1084 * as an error, with enough details to enable debugging. */
1085 static struct vlog_rate_limit rl
= VLOG_RATE_LIMIT_INIT(1, 5);
1087 if (!VLOG_DROP_ERR(&rl
)) {
1091 odp_flow_format(key
, key_len
, mask_key
, mask_key_len
, NULL
, &s
,
1093 VLOG_ERR("internal error parsing flow mask %s (%s)",
1094 ds_cstr(&s
), odp_key_fitness_to_string(fitness
));
1101 enum mf_field_id id
;
1102 /* No mask key, unwildcard everything except fields whose
1103 * prerequisities are not met. */
1104 memset(mask
, 0x0, sizeof *mask
);
1106 for (id
= 0; id
< MFF_N_IDS
; ++id
) {
1107 /* Skip registers and metadata. */
1108 if (!(id
>= MFF_REG0
&& id
< MFF_REG0
+ FLOW_N_REGS
)
1109 && id
!= MFF_METADATA
) {
1110 const struct mf_field
*mf
= mf_from_id(id
);
1111 if (mf_are_prereqs_ok(mf
, flow
)) {
1112 mf_mask_field(mf
, mask
);
1118 /* Force unwildcard the in_port.
1120 * We need to do this even in the case where we unwildcard "everything"
1121 * above because "everything" only includes the 16-bit OpenFlow port number
1122 * mask->in_port.ofp_port, which only covers half of the 32-bit datapath
1123 * port number mask->in_port.odp_port. */
1124 mask
->in_port
.odp_port
= u32_to_odp(UINT32_MAX
);
1130 dpif_netdev_flow_from_nlattrs(const struct nlattr
*key
, uint32_t key_len
,
1135 if (odp_flow_key_to_flow(key
, key_len
, flow
)) {
1136 /* This should not happen: it indicates that odp_flow_key_from_flow()
1137 * and odp_flow_key_to_flow() disagree on the acceptable form of a
1138 * flow. Log the problem as an error, with enough details to enable
1140 static struct vlog_rate_limit rl
= VLOG_RATE_LIMIT_INIT(1, 5);
1142 if (!VLOG_DROP_ERR(&rl
)) {
1146 odp_flow_format(key
, key_len
, NULL
, 0, NULL
, &s
, true);
1147 VLOG_ERR("internal error parsing flow key %s", ds_cstr(&s
));
1154 in_port
= flow
->in_port
.odp_port
;
1155 if (!is_valid_port_number(in_port
) && in_port
!= ODPP_NONE
) {
1163 dpif_netdev_flow_get(const struct dpif
*dpif
,
1164 const struct nlattr
*nl_key
, size_t nl_key_len
,
1165 struct ofpbuf
**bufp
,
1166 struct nlattr
**maskp
, size_t *mask_len
,
1167 struct nlattr
**actionsp
, size_t *actions_len
,
1168 struct dpif_flow_stats
*stats
)
1170 struct dp_netdev
*dp
= get_dp_netdev(dpif
);
1171 struct dp_netdev_flow
*netdev_flow
;
1175 error
= dpif_netdev_flow_from_nlattrs(nl_key
, nl_key_len
, &key
);
1180 netdev_flow
= dp_netdev_find_flow(dp
, &key
);
1184 get_dpif_flow_stats(netdev_flow
, stats
);
1188 struct flow_wildcards wc
;
1190 *bufp
= ofpbuf_new(sizeof(struct odputil_keybuf
));
1191 minimask_expand(&netdev_flow
->cr
.match
.mask
, &wc
);
1192 odp_flow_key_from_mask(*bufp
, &wc
.masks
, &netdev_flow
->flow
,
1193 odp_to_u32(wc
.masks
.in_port
.odp_port
),
1195 *maskp
= ofpbuf_data(*bufp
);
1196 *mask_len
= ofpbuf_size(*bufp
);
1199 struct dp_netdev_actions
*actions
;
1201 actions
= dp_netdev_flow_get_actions(netdev_flow
);
1202 *actionsp
= actions
->actions
;
1203 *actions_len
= actions
->size
;
1213 dp_netdev_flow_add(struct dp_netdev
*dp
, const struct flow
*flow
,
1214 const struct flow_wildcards
*wc
,
1215 const struct nlattr
*actions
,
1217 OVS_REQUIRES(dp
->flow_mutex
)
1219 struct dp_netdev_flow
*netdev_flow
;
1222 netdev_flow
= xzalloc(sizeof *netdev_flow
);
1223 *CONST_CAST(struct flow
*, &netdev_flow
->flow
) = *flow
;
1225 ovsthread_stats_init(&netdev_flow
->stats
);
1227 ovsrcu_set(&netdev_flow
->actions
,
1228 dp_netdev_actions_create(actions
, actions_len
));
1230 match_init(&match
, flow
, wc
);
1231 cls_rule_init(CONST_CAST(struct cls_rule
*, &netdev_flow
->cr
),
1232 &match
, NETDEV_RULE_PRIORITY
);
1233 cmap_insert(&dp
->flow_table
,
1234 CONST_CAST(struct cmap_node
*, &netdev_flow
->node
),
1235 flow_hash(flow
, 0));
1236 classifier_insert(&dp
->cls
,
1237 CONST_CAST(struct cls_rule
*, &netdev_flow
->cr
));
1243 clear_stats(struct dp_netdev_flow
*netdev_flow
)
1245 struct dp_netdev_flow_stats
*bucket
;
1248 OVSTHREAD_STATS_FOR_EACH_BUCKET (bucket
, i
, &netdev_flow
->stats
) {
1249 ovs_mutex_lock(&bucket
->mutex
);
1251 bucket
->packet_count
= 0;
1252 bucket
->byte_count
= 0;
1253 bucket
->tcp_flags
= 0;
1254 ovs_mutex_unlock(&bucket
->mutex
);
1259 dpif_netdev_flow_put(struct dpif
*dpif
, const struct dpif_flow_put
*put
)
1261 struct dp_netdev
*dp
= get_dp_netdev(dpif
);
1262 struct dp_netdev_flow
*netdev_flow
;
1264 struct miniflow miniflow
;
1265 struct flow_wildcards wc
;
1268 error
= dpif_netdev_flow_from_nlattrs(put
->key
, put
->key_len
, &flow
);
1272 error
= dpif_netdev_mask_from_nlattrs(put
->key
, put
->key_len
,
1273 put
->mask
, put
->mask_len
,
1278 miniflow_init(&miniflow
, &flow
);
1280 ovs_mutex_lock(&dp
->flow_mutex
);
1281 netdev_flow
= dp_netdev_lookup_flow(dp
, &miniflow
);
1283 if (put
->flags
& DPIF_FP_CREATE
) {
1284 if (cmap_count(&dp
->flow_table
) < MAX_FLOWS
) {
1286 memset(put
->stats
, 0, sizeof *put
->stats
);
1288 error
= dp_netdev_flow_add(dp
, &flow
, &wc
, put
->actions
,
1297 if (put
->flags
& DPIF_FP_MODIFY
1298 && flow_equal(&flow
, &netdev_flow
->flow
)) {
1299 struct dp_netdev_actions
*new_actions
;
1300 struct dp_netdev_actions
*old_actions
;
1302 new_actions
= dp_netdev_actions_create(put
->actions
,
1305 old_actions
= dp_netdev_flow_get_actions(netdev_flow
);
1306 ovsrcu_set(&netdev_flow
->actions
, new_actions
);
1309 get_dpif_flow_stats(netdev_flow
, put
->stats
);
1311 if (put
->flags
& DPIF_FP_ZERO_STATS
) {
1312 clear_stats(netdev_flow
);
1315 ovsrcu_postpone(dp_netdev_actions_free
, old_actions
);
1316 } else if (put
->flags
& DPIF_FP_CREATE
) {
1319 /* Overlapping flow. */
1323 ovs_mutex_unlock(&dp
->flow_mutex
);
1324 miniflow_destroy(&miniflow
);
1330 dpif_netdev_flow_del(struct dpif
*dpif
, const struct dpif_flow_del
*del
)
1332 struct dp_netdev
*dp
= get_dp_netdev(dpif
);
1333 struct dp_netdev_flow
*netdev_flow
;
1337 error
= dpif_netdev_flow_from_nlattrs(del
->key
, del
->key_len
, &key
);
1342 ovs_mutex_lock(&dp
->flow_mutex
);
1343 netdev_flow
= dp_netdev_find_flow(dp
, &key
);
1346 get_dpif_flow_stats(netdev_flow
, del
->stats
);
1348 dp_netdev_remove_flow(dp
, netdev_flow
);
1352 ovs_mutex_unlock(&dp
->flow_mutex
);
1357 struct dpif_netdev_flow_dump
{
1358 struct dpif_flow_dump up
;
1359 struct cmap_position pos
;
1361 struct ovs_mutex mutex
;
1364 static struct dpif_netdev_flow_dump
*
1365 dpif_netdev_flow_dump_cast(struct dpif_flow_dump
*dump
)
1367 return CONTAINER_OF(dump
, struct dpif_netdev_flow_dump
, up
);
1370 static struct dpif_flow_dump
*
1371 dpif_netdev_flow_dump_create(const struct dpif
*dpif_
)
1373 struct dpif_netdev_flow_dump
*dump
;
1375 dump
= xmalloc(sizeof *dump
);
1376 dpif_flow_dump_init(&dump
->up
, dpif_
);
1377 memset(&dump
->pos
, 0, sizeof dump
->pos
);
1379 ovs_mutex_init(&dump
->mutex
);
1385 dpif_netdev_flow_dump_destroy(struct dpif_flow_dump
*dump_
)
1387 struct dpif_netdev_flow_dump
*dump
= dpif_netdev_flow_dump_cast(dump_
);
1389 ovs_mutex_destroy(&dump
->mutex
);
1394 struct dpif_netdev_flow_dump_thread
{
1395 struct dpif_flow_dump_thread up
;
1396 struct dpif_netdev_flow_dump
*dump
;
1397 struct odputil_keybuf keybuf
[FLOW_DUMP_MAX_BATCH
];
1398 struct odputil_keybuf maskbuf
[FLOW_DUMP_MAX_BATCH
];
1401 static struct dpif_netdev_flow_dump_thread
*
1402 dpif_netdev_flow_dump_thread_cast(struct dpif_flow_dump_thread
*thread
)
1404 return CONTAINER_OF(thread
, struct dpif_netdev_flow_dump_thread
, up
);
1407 static struct dpif_flow_dump_thread
*
1408 dpif_netdev_flow_dump_thread_create(struct dpif_flow_dump
*dump_
)
1410 struct dpif_netdev_flow_dump
*dump
= dpif_netdev_flow_dump_cast(dump_
);
1411 struct dpif_netdev_flow_dump_thread
*thread
;
1413 thread
= xmalloc(sizeof *thread
);
1414 dpif_flow_dump_thread_init(&thread
->up
, &dump
->up
);
1415 thread
->dump
= dump
;
1420 dpif_netdev_flow_dump_thread_destroy(struct dpif_flow_dump_thread
*thread_
)
1422 struct dpif_netdev_flow_dump_thread
*thread
1423 = dpif_netdev_flow_dump_thread_cast(thread_
);
1429 dpif_netdev_flow_dump_next(struct dpif_flow_dump_thread
*thread_
,
1430 struct dpif_flow
*flows
, int max_flows
)
1432 struct dpif_netdev_flow_dump_thread
*thread
1433 = dpif_netdev_flow_dump_thread_cast(thread_
);
1434 struct dpif_netdev_flow_dump
*dump
= thread
->dump
;
1435 struct dpif_netdev
*dpif
= dpif_netdev_cast(thread
->up
.dpif
);
1436 struct dp_netdev_flow
*netdev_flows
[FLOW_DUMP_MAX_BATCH
];
1437 struct dp_netdev
*dp
= get_dp_netdev(&dpif
->dpif
);
1441 ovs_mutex_lock(&dump
->mutex
);
1442 if (!dump
->status
) {
1443 for (n_flows
= 0; n_flows
< MIN(max_flows
, FLOW_DUMP_MAX_BATCH
);
1445 struct cmap_node
*node
;
1447 node
= cmap_next_position(&dp
->flow_table
, &dump
->pos
);
1452 netdev_flows
[n_flows
] = CONTAINER_OF(node
, struct dp_netdev_flow
,
1456 ovs_mutex_unlock(&dump
->mutex
);
1458 for (i
= 0; i
< n_flows
; i
++) {
1459 struct odputil_keybuf
*maskbuf
= &thread
->maskbuf
[i
];
1460 struct odputil_keybuf
*keybuf
= &thread
->keybuf
[i
];
1461 struct dp_netdev_flow
*netdev_flow
= netdev_flows
[i
];
1462 struct dpif_flow
*f
= &flows
[i
];
1463 struct dp_netdev_actions
*dp_actions
;
1464 struct flow_wildcards wc
;
1467 minimask_expand(&netdev_flow
->cr
.match
.mask
, &wc
);
1470 ofpbuf_use_stack(&buf
, keybuf
, sizeof *keybuf
);
1471 odp_flow_key_from_flow(&buf
, &netdev_flow
->flow
, &wc
.masks
,
1472 netdev_flow
->flow
.in_port
.odp_port
, true);
1473 f
->key
= ofpbuf_data(&buf
);
1474 f
->key_len
= ofpbuf_size(&buf
);
1477 ofpbuf_use_stack(&buf
, maskbuf
, sizeof *maskbuf
);
1478 odp_flow_key_from_mask(&buf
, &wc
.masks
, &netdev_flow
->flow
,
1479 odp_to_u32(wc
.masks
.in_port
.odp_port
),
1481 f
->mask
= ofpbuf_data(&buf
);
1482 f
->mask_len
= ofpbuf_size(&buf
);
1485 dp_actions
= dp_netdev_flow_get_actions(netdev_flow
);
1486 f
->actions
= dp_actions
->actions
;
1487 f
->actions_len
= dp_actions
->size
;
1490 get_dpif_flow_stats(netdev_flow
, &f
->stats
);
1497 dpif_netdev_execute(struct dpif
*dpif
, struct dpif_execute
*execute
)
1499 struct dp_netdev
*dp
= get_dp_netdev(dpif
);
1500 struct dpif_packet packet
, *pp
;
1501 struct pkt_metadata
*md
= &execute
->md
;
1503 if (ofpbuf_size(execute
->packet
) < ETH_HEADER_LEN
||
1504 ofpbuf_size(execute
->packet
) > UINT16_MAX
) {
1508 packet
.ofpbuf
= *execute
->packet
;
1511 dp_netdev_execute_actions(dp
, &pp
, 1, false, md
,
1512 execute
->actions
, execute
->actions_len
);
1514 /* Even though may_steal is set to false, some actions could modify or
1515 * reallocate the ofpbuf memory. We need to pass those changes to the
1517 *execute
->packet
= packet
.ofpbuf
;
1523 dpif_netdev_queue_to_priority(const struct dpif
*dpif OVS_UNUSED
,
1524 uint32_t queue_id
, uint32_t *priority
)
1526 *priority
= queue_id
;
1531 /* Creates and returns a new 'struct dp_netdev_actions', with a reference count
1532 * of 1, whose actions are a copy of from the 'ofpacts_len' bytes of
1534 struct dp_netdev_actions
*
1535 dp_netdev_actions_create(const struct nlattr
*actions
, size_t size
)
1537 struct dp_netdev_actions
*netdev_actions
;
1539 netdev_actions
= xmalloc(sizeof *netdev_actions
);
1540 netdev_actions
->actions
= xmemdup(actions
, size
);
1541 netdev_actions
->size
= size
;
1543 return netdev_actions
;
1546 struct dp_netdev_actions
*
1547 dp_netdev_flow_get_actions(const struct dp_netdev_flow
*flow
)
1549 return ovsrcu_get(struct dp_netdev_actions
*, &flow
->actions
);
1553 dp_netdev_actions_free(struct dp_netdev_actions
*actions
)
1555 free(actions
->actions
);
1561 dp_netdev_process_rxq_port(struct dp_netdev
*dp
,
1562 struct dp_netdev_port
*port
,
1563 struct netdev_rxq
*rxq
)
1565 struct dpif_packet
*packets
[NETDEV_MAX_RX_BATCH
];
1568 error
= netdev_rxq_recv(rxq
, packets
, &cnt
);
1570 dp_netdev_port_input(dp
, packets
, cnt
, port
->port_no
);
1571 } else if (error
!= EAGAIN
&& error
!= EOPNOTSUPP
) {
1572 static struct vlog_rate_limit rl
1573 = VLOG_RATE_LIMIT_INIT(1, 5);
1575 VLOG_ERR_RL(&rl
, "error receiving data from %s: %s",
1576 netdev_get_name(port
->netdev
),
1577 ovs_strerror(error
));
1582 dpif_netdev_run(struct dpif
*dpif
)
1584 struct dp_netdev_port
*port
;
1585 struct dp_netdev
*dp
= get_dp_netdev(dpif
);
1587 CMAP_FOR_EACH (port
, node
, &dp
->ports
) {
1588 if (!netdev_is_pmd(port
->netdev
)) {
1591 for (i
= 0; i
< netdev_n_rxq(port
->netdev
); i
++) {
1592 dp_netdev_process_rxq_port(dp
, port
, port
->rxq
[i
]);
1599 dpif_netdev_wait(struct dpif
*dpif
)
1601 struct dp_netdev_port
*port
;
1602 struct dp_netdev
*dp
= get_dp_netdev(dpif
);
1604 ovs_mutex_lock(&dp_netdev_mutex
);
1605 CMAP_FOR_EACH (port
, node
, &dp
->ports
) {
1606 if (!netdev_is_pmd(port
->netdev
)) {
1609 for (i
= 0; i
< netdev_n_rxq(port
->netdev
); i
++) {
1610 netdev_rxq_wait(port
->rxq
[i
]);
1614 ovs_mutex_unlock(&dp_netdev_mutex
);
1618 struct dp_netdev_port
*port
;
1619 struct netdev_rxq
*rx
;
1623 pmd_load_queues(struct pmd_thread
*f
,
1624 struct rxq_poll
**ppoll_list
, int poll_cnt
)
1626 struct dp_netdev
*dp
= f
->dp
;
1627 struct rxq_poll
*poll_list
= *ppoll_list
;
1628 struct dp_netdev_port
*port
;
1633 /* Simple scheduler for netdev rx polling. */
1634 for (i
= 0; i
< poll_cnt
; i
++) {
1635 port_unref(poll_list
[i
].port
);
1641 CMAP_FOR_EACH (port
, node
, &f
->dp
->ports
) {
1642 if (netdev_is_pmd(port
->netdev
)) {
1645 for (i
= 0; i
< netdev_n_rxq(port
->netdev
); i
++) {
1646 if ((index
% dp
->n_pmd_threads
) == id
) {
1647 poll_list
= xrealloc(poll_list
, sizeof *poll_list
* (poll_cnt
+ 1));
1650 poll_list
[poll_cnt
].port
= port
;
1651 poll_list
[poll_cnt
].rx
= port
->rxq
[i
];
1659 *ppoll_list
= poll_list
;
1664 pmd_thread_main(void *f_
)
1666 struct pmd_thread
*f
= f_
;
1667 struct dp_netdev
*dp
= f
->dp
;
1668 unsigned int lc
= 0;
1669 struct rxq_poll
*poll_list
;
1670 unsigned int port_seq
;
1677 pmd_thread_setaffinity_cpu(f
->id
);
1679 poll_cnt
= pmd_load_queues(f
, &poll_list
, poll_cnt
);
1680 atomic_read(&f
->change_seq
, &port_seq
);
1683 unsigned int c_port_seq
;
1686 for (i
= 0; i
< poll_cnt
; i
++) {
1687 dp_netdev_process_rxq_port(dp
, poll_list
[i
].port
, poll_list
[i
].rx
);
1693 /* TODO: need completely userspace based signaling method.
1694 * to keep this thread entirely in userspace.
1695 * For now using atomic counter. */
1697 atomic_read_explicit(&f
->change_seq
, &c_port_seq
, memory_order_consume
);
1698 if (c_port_seq
!= port_seq
) {
1704 if (!latch_is_set(&f
->dp
->exit_latch
)){
1708 for (i
= 0; i
< poll_cnt
; i
++) {
1709 port_unref(poll_list
[i
].port
);
1717 dp_netdev_disable_upcall(struct dp_netdev
*dp
)
1718 OVS_ACQUIRES(dp
->upcall_rwlock
)
1720 fat_rwlock_wrlock(&dp
->upcall_rwlock
);
1724 dpif_netdev_disable_upcall(struct dpif
*dpif
)
1725 OVS_NO_THREAD_SAFETY_ANALYSIS
1727 struct dp_netdev
*dp
= get_dp_netdev(dpif
);
1728 dp_netdev_disable_upcall(dp
);
1732 dp_netdev_enable_upcall(struct dp_netdev
*dp
)
1733 OVS_RELEASES(dp
->upcall_rwlock
)
1735 fat_rwlock_unlock(&dp
->upcall_rwlock
);
1739 dpif_netdev_enable_upcall(struct dpif
*dpif
)
1740 OVS_NO_THREAD_SAFETY_ANALYSIS
1742 struct dp_netdev
*dp
= get_dp_netdev(dpif
);
1743 dp_netdev_enable_upcall(dp
);
1747 dp_netdev_set_pmd_threads(struct dp_netdev
*dp
, int n
)
1751 if (n
== dp
->n_pmd_threads
) {
1755 /* Stop existing threads. */
1756 latch_set(&dp
->exit_latch
);
1757 dp_netdev_reload_pmd_threads(dp
);
1758 for (i
= 0; i
< dp
->n_pmd_threads
; i
++) {
1759 struct pmd_thread
*f
= &dp
->pmd_threads
[i
];
1761 xpthread_join(f
->thread
, NULL
);
1763 latch_poll(&dp
->exit_latch
);
1764 free(dp
->pmd_threads
);
1766 /* Start new threads. */
1767 dp
->pmd_threads
= xmalloc(n
* sizeof *dp
->pmd_threads
);
1768 dp
->n_pmd_threads
= n
;
1770 for (i
= 0; i
< n
; i
++) {
1771 struct pmd_thread
*f
= &dp
->pmd_threads
[i
];
1775 atomic_store(&f
->change_seq
, 1);
1777 /* Each thread will distribute all devices rx-queues among
1779 f
->thread
= ovs_thread_create("pmd", pmd_thread_main
, f
);
1785 dp_netdev_flow_stats_new_cb(void)
1787 struct dp_netdev_flow_stats
*bucket
= xzalloc_cacheline(sizeof *bucket
);
1788 ovs_mutex_init(&bucket
->mutex
);
1793 dp_netdev_flow_used(struct dp_netdev_flow
*netdev_flow
,
1797 long long int now
= time_msec();
1798 struct dp_netdev_flow_stats
*bucket
;
1800 bucket
= ovsthread_stats_bucket_get(&netdev_flow
->stats
,
1801 dp_netdev_flow_stats_new_cb
);
1803 ovs_mutex_lock(&bucket
->mutex
);
1804 bucket
->used
= MAX(now
, bucket
->used
);
1805 bucket
->packet_count
+= cnt
;
1806 bucket
->byte_count
+= size
;
1807 bucket
->tcp_flags
|= tcp_flags
;
1808 ovs_mutex_unlock(&bucket
->mutex
);
1812 dp_netdev_stats_new_cb(void)
1814 struct dp_netdev_stats
*bucket
= xzalloc_cacheline(sizeof *bucket
);
1815 ovs_mutex_init(&bucket
->mutex
);
1820 dp_netdev_count_packet(struct dp_netdev
*dp
, enum dp_stat_type type
, int cnt
)
1822 struct dp_netdev_stats
*bucket
;
1824 bucket
= ovsthread_stats_bucket_get(&dp
->stats
, dp_netdev_stats_new_cb
);
1825 ovs_mutex_lock(&bucket
->mutex
);
1826 bucket
->n
[type
] += cnt
;
1827 ovs_mutex_unlock(&bucket
->mutex
);
1830 struct packet_batch
{
1831 unsigned int packet_count
;
1832 unsigned int byte_count
;
1835 struct dp_netdev_flow
*flow
;
1837 struct dpif_packet
*packets
[NETDEV_MAX_RX_BATCH
];
1838 struct pkt_metadata md
;
1842 packet_batch_update(struct packet_batch
*batch
,
1843 struct dpif_packet
*packet
, const struct miniflow
*mf
)
1845 batch
->tcp_flags
|= miniflow_get_tcp_flags(mf
);
1846 batch
->packets
[batch
->packet_count
++] = packet
;
1847 batch
->byte_count
+= ofpbuf_size(&packet
->ofpbuf
);
1851 packet_batch_init(struct packet_batch
*batch
, struct dp_netdev_flow
*flow
,
1852 struct pkt_metadata
*md
)
1857 batch
->packet_count
= 0;
1858 batch
->byte_count
= 0;
1859 batch
->tcp_flags
= 0;
1863 packet_batch_execute(struct packet_batch
*batch
, struct dp_netdev
*dp
)
1865 struct dp_netdev_actions
*actions
;
1866 struct dp_netdev_flow
*flow
= batch
->flow
;
1868 dp_netdev_flow_used(batch
->flow
, batch
->packet_count
, batch
->byte_count
,
1871 actions
= dp_netdev_flow_get_actions(flow
);
1873 dp_netdev_execute_actions(dp
, batch
->packets
,
1874 batch
->packet_count
, true, &batch
->md
,
1875 actions
->actions
, actions
->size
);
1877 dp_netdev_count_packet(dp
, DP_STAT_HIT
, batch
->packet_count
);
1881 dp_netdev_input(struct dp_netdev
*dp
, struct dpif_packet
**packets
, int cnt
,
1882 struct pkt_metadata
*md
)
1884 struct dp_netdev_queue q
= DP_NETDEV_QUEUE_INITIALIZER
;
1885 struct packet_batch batches
[NETDEV_MAX_RX_BATCH
];
1886 struct netdev_flow_key keys
[NETDEV_MAX_RX_BATCH
];
1887 const struct miniflow
*mfs
[NETDEV_MAX_RX_BATCH
]; /* NULL at bad packets. */
1888 struct cls_rule
*rules
[NETDEV_MAX_RX_BATCH
];
1889 size_t n_batches
, i
;
1891 for (i
= 0; i
< cnt
; i
++) {
1892 if (OVS_UNLIKELY(ofpbuf_size(&packets
[i
]->ofpbuf
) < ETH_HEADER_LEN
)) {
1893 dpif_packet_delete(packets
[i
]);
1898 miniflow_initialize(&keys
[i
].flow
, keys
[i
].buf
);
1899 miniflow_extract(&packets
[i
]->ofpbuf
, md
, &keys
[i
].flow
);
1900 mfs
[i
] = &keys
[i
].flow
;
1903 classifier_lookup_miniflow_batch(&dp
->cls
, mfs
, rules
, cnt
);
1906 for (i
= 0; i
< cnt
; i
++) {
1907 struct dp_netdev_flow
*flow
;
1908 struct packet_batch
*batch
;
1911 if (OVS_UNLIKELY(!mfs
[i
])) {
1915 if (OVS_UNLIKELY(!rules
[i
])) {
1916 struct ofpbuf
*buf
= &packets
[i
]->ofpbuf
;
1918 dp_netdev_count_packet(dp
, DP_STAT_MISS
, 1);
1919 dp_netdev_queue_userspace_packet(&q
, buf
, DPIF_UC_MISS
,
1921 dpif_packet_delete(packets
[i
]);
1925 /* XXX: This O(n^2) algortihm makes sense if we're operating under the
1926 * assumption that the number of distinct flows (and therefore the
1927 * number of distinct batches) is quite small. If this turns out not
1928 * to be the case, it may make sense to pre sort based on the
1929 * netdev_flow pointer. That done we can get the appropriate batching
1930 * in O(n * log(n)) instead. */
1932 flow
= dp_netdev_flow_cast(rules
[i
]);
1933 for (j
= 0; j
< n_batches
; j
++) {
1934 if (batches
[j
].flow
== flow
) {
1935 batch
= &batches
[j
];
1941 batch
= &batches
[n_batches
++];
1942 packet_batch_init(batch
, flow
, md
);
1944 packet_batch_update(batch
, packets
[i
], mfs
[i
]);
1947 for (i
= 0; i
< n_batches
; i
++) {
1948 packet_batch_execute(&batches
[i
], dp
);
1951 if (q
.packet_count
) {
1952 dp_netdev_execute_userspace_queue(&q
, dp
);
1957 dp_netdev_port_input(struct dp_netdev
*dp
, struct dpif_packet
**packets
,
1958 int cnt
, odp_port_t port_no
)
1960 uint32_t *recirc_depth
= recirc_depth_get();
1961 struct pkt_metadata md
= PKT_METADATA_INITIALIZER(port_no
);
1964 dp_netdev_input(dp
, packets
, cnt
, &md
);
1968 dp_netdev_queue_userspace_packet(struct dp_netdev_queue
*q
,
1969 struct ofpbuf
*packet
, int type
,
1970 const struct miniflow
*key
,
1971 const struct nlattr
*userdata
)
1973 if (q
->packet_count
< NETDEV_MAX_RX_BATCH
) {
1974 int cnt
= q
->packet_count
;
1975 struct dpif_upcall
*upcall
= &q
->upcalls
[cnt
];
1976 struct ofpbuf
*buf
= &q
->bufs
[cnt
];
1981 upcall
->type
= type
;
1983 /* Allocate buffer big enough for everything. */
1984 buf_size
= ODPUTIL_FLOW_KEY_BYTES
;
1986 buf_size
+= NLA_ALIGN(userdata
->nla_len
);
1988 buf_size
+= ofpbuf_size(packet
);
1989 ofpbuf_init(buf
, buf_size
);
1992 miniflow_expand(key
, &flow
);
1993 odp_flow_key_from_flow(buf
, &flow
, NULL
, flow
.in_port
.odp_port
, true);
1994 upcall
->key
= ofpbuf_data(buf
);
1995 upcall
->key_len
= ofpbuf_size(buf
);
1999 upcall
->userdata
= ofpbuf_put(buf
, userdata
,
2000 NLA_ALIGN(userdata
->nla_len
));
2003 /* We have to perform a copy of the packet, because we cannot send DPDK
2004 * mbufs to a non pmd thread. When the upcall processing will be done
2005 * in the pmd thread, this copy can be avoided */
2006 data
= ofpbuf_put(buf
, ofpbuf_data(packet
), ofpbuf_size(packet
));
2007 ofpbuf_use_stub(&upcall
->packet
, data
, ofpbuf_size(packet
));
2008 ofpbuf_set_size(&upcall
->packet
, ofpbuf_size(packet
));
2018 dp_netdev_execute_userspace_queue(struct dp_netdev_queue
*q
,
2019 struct dp_netdev
*dp
)
2021 struct dpif_upcall
*upcalls
= q
->upcalls
;
2022 struct ofpbuf
*bufs
= q
->bufs
;
2023 int cnt
= q
->packet_count
;
2025 if (!fat_rwlock_tryrdlock(&dp
->upcall_rwlock
)) {
2026 ovs_assert(dp
->upcall_cb
);
2027 dp
->upcall_cb(dp
->dpif
, upcalls
, bufs
, cnt
);
2028 fat_rwlock_unlock(&dp
->upcall_rwlock
);
2032 for (i
= 0; i
< cnt
; i
++) {
2033 ofpbuf_uninit(&bufs
[i
]);
2034 ofpbuf_uninit(&upcalls
[i
].packet
);
2039 struct dp_netdev_execute_aux
{
2040 struct dp_netdev
*dp
;
2044 dpif_netdev_register_upcall_cb(struct dpif
*dpif
, exec_upcall_cb
*cb
)
2046 struct dp_netdev
*dp
= get_dp_netdev(dpif
);
2051 dp_execute_cb(void *aux_
, struct dpif_packet
**packets
, int cnt
,
2052 struct pkt_metadata
*md
,
2053 const struct nlattr
*a
, bool may_steal
)
2054 OVS_NO_THREAD_SAFETY_ANALYSIS
2056 struct dp_netdev_execute_aux
*aux
= aux_
;
2057 int type
= nl_attr_type(a
);
2058 struct dp_netdev_port
*p
;
2059 uint32_t *depth
= recirc_depth_get();
2062 switch ((enum ovs_action_attr
)type
) {
2063 case OVS_ACTION_ATTR_OUTPUT
:
2064 p
= dp_netdev_lookup_port(aux
->dp
, u32_to_odp(nl_attr_get_u32(a
)));
2065 if (OVS_LIKELY(p
)) {
2066 netdev_send(p
->netdev
, packets
, cnt
, may_steal
);
2067 } else if (may_steal
) {
2068 for (i
= 0; i
< cnt
; i
++) {
2069 dpif_packet_delete(packets
[i
]);
2074 case OVS_ACTION_ATTR_USERSPACE
: {
2075 const struct nlattr
*userdata
;
2076 struct netdev_flow_key key
;
2077 struct dp_netdev_queue q
= DP_NETDEV_QUEUE_INITIALIZER
;
2079 userdata
= nl_attr_find_nested(a
, OVS_USERSPACE_ATTR_USERDATA
);
2081 miniflow_initialize(&key
.flow
, key
.buf
);
2083 for (i
= 0; i
< cnt
; i
++) {
2084 struct ofpbuf
*packet
;
2086 packet
= &packets
[i
]->ofpbuf
;
2088 miniflow_extract(packet
, md
, &key
.flow
);
2090 dp_netdev_queue_userspace_packet(&q
, packet
,
2091 DPIF_UC_ACTION
, &key
.flow
,
2094 dpif_packet_delete(packets
[i
]);
2098 if (q
.packet_count
) {
2099 dp_netdev_execute_userspace_queue(&q
, aux
->dp
);
2104 case OVS_ACTION_ATTR_HASH
: {
2105 const struct ovs_action_hash
*hash_act
;
2106 struct netdev_flow_key key
;
2109 hash_act
= nl_attr_get(a
);
2111 miniflow_initialize(&key
.flow
, key
.buf
);
2113 for (i
= 0; i
< cnt
; i
++) {
2115 /* TODO: this is slow. Use RSS hash in the future */
2116 miniflow_extract(&packets
[i
]->ofpbuf
, md
, &key
.flow
);
2118 if (hash_act
->hash_alg
== OVS_HASH_ALG_L4
) {
2119 /* Hash need not be symmetric, nor does it need to include
2121 hash
= miniflow_hash_5tuple(&key
.flow
, hash_act
->hash_basis
);
2123 VLOG_WARN("Unknown hash algorithm specified "
2124 "for the hash action.");
2129 hash
= 1; /* 0 is not valid */
2135 packets
[i
]->dp_hash
= hash
;
2140 case OVS_ACTION_ATTR_RECIRC
:
2141 if (*depth
< MAX_RECIRC_DEPTH
) {
2144 for (i
= 0; i
< cnt
; i
++) {
2145 struct dpif_packet
*recirc_pkt
;
2146 struct pkt_metadata recirc_md
= *md
;
2148 recirc_pkt
= (may_steal
) ? packets
[i
]
2149 : dpif_packet_clone(packets
[i
]);
2151 recirc_md
.recirc_id
= nl_attr_get_u32(a
);
2153 /* Hash is private to each packet */
2154 recirc_md
.dp_hash
= packets
[i
]->dp_hash
;
2156 dp_netdev_input(aux
->dp
, &recirc_pkt
, 1, &recirc_md
);
2162 VLOG_WARN("Packet dropped. Max recirculation depth exceeded.");
2164 for (i
= 0; i
< cnt
; i
++) {
2165 dpif_packet_delete(packets
[i
]);
2171 case OVS_ACTION_ATTR_PUSH_VLAN
:
2172 case OVS_ACTION_ATTR_POP_VLAN
:
2173 case OVS_ACTION_ATTR_PUSH_MPLS
:
2174 case OVS_ACTION_ATTR_POP_MPLS
:
2175 case OVS_ACTION_ATTR_SET
:
2176 case OVS_ACTION_ATTR_SAMPLE
:
2177 case OVS_ACTION_ATTR_UNSPEC
:
2178 case __OVS_ACTION_ATTR_MAX
:
2184 dp_netdev_execute_actions(struct dp_netdev
*dp
,
2185 struct dpif_packet
**packets
, int cnt
,
2186 bool may_steal
, struct pkt_metadata
*md
,
2187 const struct nlattr
*actions
, size_t actions_len
)
2189 struct dp_netdev_execute_aux aux
= {dp
};
2191 odp_execute_actions(&aux
, packets
, cnt
, may_steal
, md
, actions
,
2192 actions_len
, dp_execute_cb
);
2195 const struct dpif_class dpif_netdev_class
= {
2197 dpif_netdev_enumerate
,
2198 dpif_netdev_port_open_type
,
2201 dpif_netdev_destroy
,
2204 dpif_netdev_get_stats
,
2205 dpif_netdev_port_add
,
2206 dpif_netdev_port_del
,
2207 dpif_netdev_port_query_by_number
,
2208 dpif_netdev_port_query_by_name
,
2209 NULL
, /* port_get_pid */
2210 dpif_netdev_port_dump_start
,
2211 dpif_netdev_port_dump_next
,
2212 dpif_netdev_port_dump_done
,
2213 dpif_netdev_port_poll
,
2214 dpif_netdev_port_poll_wait
,
2215 dpif_netdev_flow_get
,
2216 dpif_netdev_flow_put
,
2217 dpif_netdev_flow_del
,
2218 dpif_netdev_flow_flush
,
2219 dpif_netdev_flow_dump_create
,
2220 dpif_netdev_flow_dump_destroy
,
2221 dpif_netdev_flow_dump_thread_create
,
2222 dpif_netdev_flow_dump_thread_destroy
,
2223 dpif_netdev_flow_dump_next
,
2224 dpif_netdev_execute
,
2226 NULL
, /* recv_set */
2227 NULL
, /* handlers_set */
2228 dpif_netdev_queue_to_priority
,
2230 NULL
, /* recv_wait */
2231 NULL
, /* recv_purge */
2232 dpif_netdev_register_upcall_cb
,
2233 dpif_netdev_enable_upcall
,
2234 dpif_netdev_disable_upcall
,
2238 dpif_dummy_change_port_number(struct unixctl_conn
*conn
, int argc OVS_UNUSED
,
2239 const char *argv
[], void *aux OVS_UNUSED
)
2241 struct dp_netdev_port
*old_port
;
2242 struct dp_netdev_port
*new_port
;
2243 struct dp_netdev
*dp
;
2246 ovs_mutex_lock(&dp_netdev_mutex
);
2247 dp
= shash_find_data(&dp_netdevs
, argv
[1]);
2248 if (!dp
|| !dpif_netdev_class_is_dummy(dp
->class)) {
2249 ovs_mutex_unlock(&dp_netdev_mutex
);
2250 unixctl_command_reply_error(conn
, "unknown datapath or not a dummy");
2253 ovs_refcount_ref(&dp
->ref_cnt
);
2254 ovs_mutex_unlock(&dp_netdev_mutex
);
2256 ovs_mutex_lock(&dp
->port_mutex
);
2257 if (get_port_by_name(dp
, argv
[2], &old_port
)) {
2258 unixctl_command_reply_error(conn
, "unknown port");
2262 port_no
= u32_to_odp(atoi(argv
[3]));
2263 if (!port_no
|| port_no
== ODPP_NONE
) {
2264 unixctl_command_reply_error(conn
, "bad port number");
2267 if (dp_netdev_lookup_port(dp
, port_no
)) {
2268 unixctl_command_reply_error(conn
, "port number already in use");
2272 /* Remove old port. */
2273 cmap_remove(&dp
->ports
, &old_port
->node
, hash_port_no(old_port
->port_no
));
2274 ovsrcu_postpone(free
, old_port
);
2276 /* Insert new port (cmap semantics mean we cannot re-insert 'old_port'). */
2277 new_port
= xmemdup(old_port
, sizeof *old_port
);
2278 new_port
->port_no
= port_no
;
2279 cmap_insert(&dp
->ports
, &new_port
->node
, hash_port_no(port_no
));
2281 seq_change(dp
->port_seq
);
2282 unixctl_command_reply(conn
, NULL
);
2285 ovs_mutex_unlock(&dp
->port_mutex
);
2286 dp_netdev_unref(dp
);
2290 dpif_dummy_delete_port(struct unixctl_conn
*conn
, int argc OVS_UNUSED
,
2291 const char *argv
[], void *aux OVS_UNUSED
)
2293 struct dp_netdev_port
*port
;
2294 struct dp_netdev
*dp
;
2296 ovs_mutex_lock(&dp_netdev_mutex
);
2297 dp
= shash_find_data(&dp_netdevs
, argv
[1]);
2298 if (!dp
|| !dpif_netdev_class_is_dummy(dp
->class)) {
2299 ovs_mutex_unlock(&dp_netdev_mutex
);
2300 unixctl_command_reply_error(conn
, "unknown datapath or not a dummy");
2303 ovs_refcount_ref(&dp
->ref_cnt
);
2304 ovs_mutex_unlock(&dp_netdev_mutex
);
2306 ovs_mutex_lock(&dp
->port_mutex
);
2307 if (get_port_by_name(dp
, argv
[2], &port
)) {
2308 unixctl_command_reply_error(conn
, "unknown port");
2309 } else if (port
->port_no
== ODPP_LOCAL
) {
2310 unixctl_command_reply_error(conn
, "can't delete local port");
2312 do_del_port(dp
, port
);
2313 unixctl_command_reply(conn
, NULL
);
2315 ovs_mutex_unlock(&dp
->port_mutex
);
2317 dp_netdev_unref(dp
);
2321 dpif_dummy_register__(const char *type
)
2323 struct dpif_class
*class;
2325 class = xmalloc(sizeof *class);
2326 *class = dpif_netdev_class
;
2327 class->type
= xstrdup(type
);
2328 dp_register_provider(class);
2332 dpif_dummy_register(bool override
)
2339 dp_enumerate_types(&types
);
2340 SSET_FOR_EACH (type
, &types
) {
2341 if (!dp_unregister_provider(type
)) {
2342 dpif_dummy_register__(type
);
2345 sset_destroy(&types
);
2348 dpif_dummy_register__("dummy");
2350 unixctl_command_register("dpif-dummy/change-port-number",
2351 "DP PORT NEW-NUMBER",
2352 3, 3, dpif_dummy_change_port_number
, NULL
);
2353 unixctl_command_register("dpif-dummy/delete-port", "DP PORT",
2354 2, 2, dpif_dummy_delete_port
, NULL
);