]> git.proxmox.com Git - mirror_ovs.git/blame - lib/dpif-netlink.c
netlink: Introduce helpers for 128-bit integer attributes.
[mirror_ovs.git] / lib / dpif-netlink.c
CommitLineData
96fba48f 1/*
aa5c0216 2 * Copyright (c) 2008-2017 Nicira, Inc.
96fba48f
BP
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>
9fe3b9a2 18
93451a0a 19#include "dpif-netlink.h"
96fba48f 20
96fba48f
BP
21#include <ctype.h>
22#include <errno.h>
23#include <fcntl.h>
24#include <inttypes.h>
25#include <net/if.h>
b90fa799 26#include <linux/types.h>
aae51f53 27#include <linux/pkt_sched.h>
8522ba09 28#include <poll.h>
96fba48f 29#include <stdlib.h>
8522ba09 30#include <strings.h>
50f80534 31#include <sys/epoll.h>
10dcf8de 32#include <sys/stat.h>
96fba48f
BP
33#include <unistd.h>
34
773cd538 35#include "bitmap.h"
96fba48f 36#include "dpif-provider.h"
c4e08753 37#include "dpif-netlink-rtnl.h"
3e8a2ad1 38#include "openvswitch/dynamic-string.h"
eb8b28e7 39#include "flow.h"
1579cf67 40#include "fat-rwlock.h"
3abc4a1a 41#include "netdev.h"
032aa6a3 42#include "netdev-linux.h"
c3827f61 43#include "netdev-vport.h"
c11c9f4a 44#include "netlink-conntrack.h"
45c8d3a1 45#include "netlink-notifier.h"
982b8810 46#include "netlink-socket.h"
856081f6 47#include "netlink.h"
feebdea2 48#include "odp-util.h"
64c96779 49#include "openvswitch/ofpbuf.h"
856081f6 50#include "packets.h"
96fba48f 51#include "poll-loop.h"
17411ecf 52#include "random.h"
ee89ea7b 53#include "openvswitch/shash.h"
b3c01ed3 54#include "sset.h"
14b4d2f9 55#include "timeval.h"
d6569377 56#include "unaligned.h"
96fba48f 57#include "util.h"
e6211adc 58#include "openvswitch/vlog.h"
2482b0b0 59#include "openvswitch/flow.h"
5136ce49 60
93451a0a 61VLOG_DEFINE_THIS_MODULE(dpif_netlink);
09cac43f 62#ifdef _WIN32
da467899 63#include "wmi.h"
09cac43f
NR
64enum { WINDOWS = 1 };
65#else
66enum { WINDOWS = 0 };
67#endif
95b1d73a 68enum { MAX_PORTS = USHRT_MAX };
773cd538 69
24b019f8
JP
70/* This ethtool flag was introduced in Linux 2.6.24, so it might be
71 * missing if we have old headers. */
72#define ETH_FLAG_LRO (1 << 15) /* LRO is enabled */
73
93451a0a 74struct dpif_netlink_dp {
aaff4b55
BP
75 /* Generic Netlink header. */
76 uint8_t cmd;
d6569377 77
df2c07f4 78 /* struct ovs_header. */
254f2dc8 79 int dp_ifindex;
d6569377
BP
80
81 /* Attributes. */
df2c07f4 82 const char *name; /* OVS_DP_ATTR_NAME. */
fcd5d230 83 const uint32_t *upcall_pid; /* OVS_DP_ATTR_UPCALL_PID. */
b7fd5e38 84 uint32_t user_features; /* OVS_DP_ATTR_USER_FEATURES */
6a54dedc
BP
85 const struct ovs_dp_stats *stats; /* OVS_DP_ATTR_STATS. */
86 const struct ovs_dp_megaflow_stats *megaflow_stats;
847108dc 87 /* OVS_DP_ATTR_MEGAFLOW_STATS.*/
d6569377
BP
88};
89
93451a0a
AS
90static void dpif_netlink_dp_init(struct dpif_netlink_dp *);
91static int dpif_netlink_dp_from_ofpbuf(struct dpif_netlink_dp *,
92 const struct ofpbuf *);
93static void dpif_netlink_dp_dump_start(struct nl_dump *);
94static int dpif_netlink_dp_transact(const struct dpif_netlink_dp *request,
95 struct dpif_netlink_dp *reply,
96 struct ofpbuf **bufp);
97static int dpif_netlink_dp_get(const struct dpif *,
98 struct dpif_netlink_dp *reply,
99 struct ofpbuf **bufp);
100
101struct dpif_netlink_flow {
37a1300c
BP
102 /* Generic Netlink header. */
103 uint8_t cmd;
d6569377 104
df2c07f4 105 /* struct ovs_header. */
d6569377 106 unsigned int nlmsg_flags;
254f2dc8 107 int dp_ifindex;
d6569377
BP
108
109 /* Attributes.
110 *
0e70cdcb
BP
111 * The 'stats' member points to 64-bit data that might only be aligned on
112 * 32-bit boundaries, so get_unaligned_u64() should be used to access its
113 * values.
d2a23af2 114 *
df2c07f4 115 * If 'actions' is nonnull then OVS_FLOW_ATTR_ACTIONS will be included in
d2a23af2 116 * the Netlink version of the command, even if actions_len is zero. */
df2c07f4 117 const struct nlattr *key; /* OVS_FLOW_ATTR_KEY. */
d6569377 118 size_t key_len;
e6cc0bab
AZ
119 const struct nlattr *mask; /* OVS_FLOW_ATTR_MASK. */
120 size_t mask_len;
df2c07f4 121 const struct nlattr *actions; /* OVS_FLOW_ATTR_ACTIONS. */
d6569377 122 size_t actions_len;
70e5ed6f
JS
123 ovs_u128 ufid; /* OVS_FLOW_ATTR_FLOW_ID. */
124 bool ufid_present; /* Is there a UFID? */
125 bool ufid_terse; /* Skip serializing key/mask/acts? */
df2c07f4
JP
126 const struct ovs_flow_stats *stats; /* OVS_FLOW_ATTR_STATS. */
127 const uint8_t *tcp_flags; /* OVS_FLOW_ATTR_TCP_FLAGS. */
0e70cdcb 128 const ovs_32aligned_u64 *used; /* OVS_FLOW_ATTR_USED. */
df2c07f4 129 bool clear; /* OVS_FLOW_ATTR_CLEAR. */
43f9ac0a 130 bool probe; /* OVS_FLOW_ATTR_PROBE. */
d6569377
BP
131};
132
93451a0a
AS
133static void dpif_netlink_flow_init(struct dpif_netlink_flow *);
134static int dpif_netlink_flow_from_ofpbuf(struct dpif_netlink_flow *,
135 const struct ofpbuf *);
136static void dpif_netlink_flow_to_ofpbuf(const struct dpif_netlink_flow *,
137 struct ofpbuf *);
138static int dpif_netlink_flow_transact(struct dpif_netlink_flow *request,
139 struct dpif_netlink_flow *reply,
140 struct ofpbuf **bufp);
141static void dpif_netlink_flow_get_stats(const struct dpif_netlink_flow *,
142 struct dpif_flow_stats *);
7af12bd7 143static void dpif_netlink_flow_to_dpif_flow(struct dpif *, struct dpif_flow *,
93451a0a 144 const struct dpif_netlink_flow *);
d6569377 145
989fd548 146/* One of the dpif channels between the kernel and userspace. */
fe3d61b3 147struct dpif_channel {
14b4d2f9 148 struct nl_sock *sock; /* Netlink socket. */
14b4d2f9 149 long long int last_poll; /* Last time this channel was polled. */
fe3d61b3
BP
150};
151
09cac43f
NR
152#ifdef _WIN32
153#define VPORT_SOCK_POOL_SIZE 1
154/* On Windows, there is no native support for epoll. There are equivalent
155 * interfaces though, that are not used currently. For simpicity, a pool of
156 * netlink sockets is used. Each socket is represented by 'struct
157 * dpif_windows_vport_sock'. Since it is a pool, multiple OVS ports may be
158 * sharing the same socket. In the future, we can add a reference count and
159 * such fields. */
160struct dpif_windows_vport_sock {
161 struct nl_sock *nl_sock; /* netlink socket. */
162};
163#endif
164
1579cf67
AW
165struct dpif_handler {
166 struct dpif_channel *channels;/* Array of channels for each handler. */
167 struct epoll_event *epoll_events;
168 int epoll_fd; /* epoll fd that includes channel socks. */
169 int n_events; /* Num events returned by epoll_wait(). */
170 int event_offset; /* Offset into 'epoll_events'. */
09cac43f
NR
171
172#ifdef _WIN32
173 /* Pool of sockets. */
174 struct dpif_windows_vport_sock *vport_sock_pool;
175 size_t last_used_pool_idx; /* Index to aid in allocating a
176 socket in the pool to a port. */
177#endif
1579cf67 178};
14b4d2f9 179
96fba48f 180/* Datapath interface for the openvswitch Linux kernel module. */
93451a0a 181struct dpif_netlink {
96fba48f 182 struct dpif dpif;
254f2dc8 183 int dp_ifindex;
e9e28be3 184
b063d9f0 185 /* Upcall messages. */
1579cf67
AW
186 struct fat_rwlock upcall_lock;
187 struct dpif_handler *handlers;
188 uint32_t n_handlers; /* Num of upcall handlers. */
189 int uc_array_size; /* Size of 'handler->channels' and */
190 /* 'handler->epoll_events'. */
982b8810 191
e9e28be3 192 /* Change notification. */
e4516b20 193 struct nl_sock *port_notifier; /* vport multicast group subscriber. */
61eae437 194 bool refresh_channels;
96fba48f
BP
195};
196
93451a0a 197static void report_loss(struct dpif_netlink *, struct dpif_channel *,
9b00386b 198 uint32_t ch_idx, uint32_t handler_id);
1579cf67 199
96fba48f
BP
200static struct vlog_rate_limit error_rl = VLOG_RATE_LIMIT_INIT(9999, 5);
201
e4516b20
BP
202/* Generic Netlink family numbers for OVS.
203 *
93451a0a 204 * Initialized by dpif_netlink_init(). */
df2c07f4
JP
205static int ovs_datapath_family;
206static int ovs_vport_family;
207static int ovs_flow_family;
208static int ovs_packet_family;
982b8810 209
e4516b20
BP
210/* Generic Netlink multicast groups for OVS.
211 *
93451a0a 212 * Initialized by dpif_netlink_init(). */
e4516b20 213static unsigned int ovs_vport_mcgroup;
982b8810 214
921c370a
EG
215/* If true, tunnel devices are created using OVS compat/genetlink.
216 * If false, tunnel devices are created with rtnetlink and using light weight
217 * tunnels. If we fail to create the tunnel the rtnetlink+LWT, then we fallback
218 * to using the compat interface. */
219static bool ovs_tunnels_out_of_tree = true;
220
93451a0a
AS
221static int dpif_netlink_init(void);
222static int open_dpif(const struct dpif_netlink_dp *, struct dpif **);
223static uint32_t dpif_netlink_port_get_pid(const struct dpif *,
224 odp_port_t port_no, uint32_t hash);
09cac43f 225static void dpif_netlink_handler_uninit(struct dpif_handler *handler);
93451a0a
AS
226static int dpif_netlink_refresh_channels(struct dpif_netlink *,
227 uint32_t n_handlers);
228static void dpif_netlink_vport_to_ofpbuf(const struct dpif_netlink_vport *,
229 struct ofpbuf *);
230static int dpif_netlink_vport_from_ofpbuf(struct dpif_netlink_vport *,
231 const struct ofpbuf *);
921c370a
EG
232static int dpif_netlink_port_query__(const struct dpif_netlink *dpif,
233 odp_port_t port_no, const char *port_name,
234 struct dpif_port *dpif_port);
f0fef760 235
93451a0a
AS
236static struct dpif_netlink *
237dpif_netlink_cast(const struct dpif *dpif)
96fba48f 238{
93451a0a
AS
239 dpif_assert_class(dpif, &dpif_netlink_class);
240 return CONTAINER_OF(dpif, struct dpif_netlink, dpif);
96fba48f
BP
241}
242
d3d22744 243static int
93451a0a
AS
244dpif_netlink_enumerate(struct sset *all_dps,
245 const struct dpif_class *dpif_class OVS_UNUSED)
d3d22744 246{
aaff4b55 247 struct nl_dump dump;
d57695d7
JS
248 uint64_t reply_stub[NL_DUMP_BUFSIZE / 8];
249 struct ofpbuf msg, buf;
aaff4b55 250 int error;
982b8810 251
93451a0a 252 error = dpif_netlink_init();
aaff4b55
BP
253 if (error) {
254 return error;
982b8810 255 }
d3d22744 256
d57695d7 257 ofpbuf_use_stub(&buf, reply_stub, sizeof reply_stub);
93451a0a 258 dpif_netlink_dp_dump_start(&dump);
d57695d7 259 while (nl_dump_next(&dump, &msg, &buf)) {
93451a0a 260 struct dpif_netlink_dp dp;
d6569377 261
93451a0a 262 if (!dpif_netlink_dp_from_ofpbuf(&dp, &msg)) {
d0c23a1a 263 sset_add(all_dps, dp.name);
d3d22744
BP
264 }
265 }
d57695d7 266 ofpbuf_uninit(&buf);
aaff4b55 267 return nl_dump_done(&dump);
d3d22744
BP
268}
269
96fba48f 270static int
93451a0a
AS
271dpif_netlink_open(const struct dpif_class *class OVS_UNUSED, const char *name,
272 bool create, struct dpif **dpifp)
96fba48f 273{
93451a0a 274 struct dpif_netlink_dp dp_request, dp;
c19e6535 275 struct ofpbuf *buf;
ea36840f 276 uint32_t upcall_pid;
c19e6535 277 int error;
96fba48f 278
93451a0a 279 error = dpif_netlink_init();
982b8810
BP
280 if (error) {
281 return error;
282 }
283
982b8810 284 /* Create or look up datapath. */
93451a0a 285 dpif_netlink_dp_init(&dp_request);
ea36840f
BP
286 if (create) {
287 dp_request.cmd = OVS_DP_CMD_NEW;
288 upcall_pid = 0;
289 dp_request.upcall_pid = &upcall_pid;
290 } else {
b7fd5e38
TG
291 /* Use OVS_DP_CMD_SET to report user features */
292 dp_request.cmd = OVS_DP_CMD_SET;
ea36840f 293 }
254f2dc8 294 dp_request.name = name;
b7fd5e38 295 dp_request.user_features |= OVS_DP_F_UNALIGNED;
1579cf67 296 dp_request.user_features |= OVS_DP_F_VPORT_PIDS;
93451a0a 297 error = dpif_netlink_dp_transact(&dp_request, &dp, &buf);
982b8810
BP
298 if (error) {
299 return error;
c19e6535 300 }
254f2dc8 301
e4516b20 302 error = open_dpif(&dp, dpifp);
8f4a4df5 303 ofpbuf_delete(buf);
e4516b20 304 return error;
c19e6535
BP
305}
306
e4516b20 307static int
93451a0a 308open_dpif(const struct dpif_netlink_dp *dp, struct dpif **dpifp)
c19e6535 309{
93451a0a 310 struct dpif_netlink *dpif;
c19e6535 311
17411ecf 312 dpif = xzalloc(sizeof *dpif);
e4516b20 313 dpif->port_notifier = NULL;
1579cf67 314 fat_rwlock_init(&dpif->upcall_lock);
c19e6535 315
93451a0a 316 dpif_init(&dpif->dpif, &dpif_netlink_class, dp->name,
254f2dc8 317 dp->dp_ifindex, dp->dp_ifindex);
c19e6535 318
254f2dc8 319 dpif->dp_ifindex = dp->dp_ifindex;
c19e6535 320 *dpifp = &dpif->dpif;
e4516b20
BP
321
322 return 0;
96fba48f
BP
323}
324
1579cf67
AW
325/* Destroys the netlink sockets pointed by the elements in 'socksp'
326 * and frees the 'socksp'. */
17411ecf 327static void
09cac43f 328vport_del_socksp__(struct nl_sock **socksp, uint32_t n_socks)
17411ecf 329{
1579cf67 330 size_t i;
17411ecf 331
1579cf67
AW
332 for (i = 0; i < n_socks; i++) {
333 nl_sock_destroy(socksp[i]);
50f80534 334 }
989fd548 335
1579cf67
AW
336 free(socksp);
337}
989fd548 338
1579cf67
AW
339/* Creates an array of netlink sockets. Returns an array of the
340 * corresponding pointers. Records the error in 'error'. */
341static struct nl_sock **
09cac43f 342vport_create_socksp__(uint32_t n_socks, int *error)
1579cf67
AW
343{
344 struct nl_sock **socksp = xzalloc(n_socks * sizeof *socksp);
345 size_t i;
346
347 for (i = 0; i < n_socks; i++) {
348 *error = nl_sock_create(NETLINK_GENERIC, &socksp[i]);
349 if (*error) {
350 goto error;
989fd548 351 }
1579cf67 352 }
989fd548 353
1579cf67 354 return socksp;
9fafa796 355
1579cf67 356error:
09cac43f 357 vport_del_socksp__(socksp, n_socks);
989fd548 358
1579cf67
AW
359 return NULL;
360}
361
09cac43f
NR
362#ifdef _WIN32
363static void
364vport_delete_sock_pool(struct dpif_handler *handler)
365 OVS_REQ_WRLOCK(dpif->upcall_lock)
366{
367 if (handler->vport_sock_pool) {
368 uint32_t i;
369 struct dpif_windows_vport_sock *sock_pool =
370 handler->vport_sock_pool;
371
372 for (i = 0; i < VPORT_SOCK_POOL_SIZE; i++) {
373 if (sock_pool[i].nl_sock) {
374 nl_sock_unsubscribe_packets(sock_pool[i].nl_sock);
375 nl_sock_destroy(sock_pool[i].nl_sock);
376 sock_pool[i].nl_sock = NULL;
377 }
378 }
379
380 free(handler->vport_sock_pool);
381 handler->vport_sock_pool = NULL;
382 }
383}
384
385static int
386vport_create_sock_pool(struct dpif_handler *handler)
387 OVS_REQ_WRLOCK(dpif->upcall_lock)
388{
389 struct dpif_windows_vport_sock *sock_pool;
390 size_t i;
391 int error = 0;
392
393 sock_pool = xzalloc(VPORT_SOCK_POOL_SIZE * sizeof *sock_pool);
394 for (i = 0; i < VPORT_SOCK_POOL_SIZE; i++) {
395 error = nl_sock_create(NETLINK_GENERIC, &sock_pool[i].nl_sock);
396 if (error) {
397 goto error;
398 }
399
400 /* Enable the netlink socket to receive packets. This is equivalent to
401 * calling nl_sock_join_mcgroup() to receive events. */
402 error = nl_sock_subscribe_packets(sock_pool[i].nl_sock);
403 if (error) {
404 goto error;
405 }
406 }
407
408 handler->vport_sock_pool = sock_pool;
409 handler->last_used_pool_idx = 0;
410 return 0;
411
412error:
413 vport_delete_sock_pool(handler);
414 return error;
415}
416
417/* Returns an array pointers to netlink sockets. The sockets are picked from a
418 * pool. Records the error in 'error'. */
419static struct nl_sock **
420vport_create_socksp_windows(struct dpif_netlink *dpif, int *error)
421 OVS_REQ_WRLOCK(dpif->upcall_lock)
422{
423 uint32_t n_socks = dpif->n_handlers;
424 struct nl_sock **socksp;
425 size_t i;
426
427 ovs_assert(n_socks <= 1);
428 socksp = xzalloc(n_socks * sizeof *socksp);
429
430 /* Pick netlink sockets to use in a round-robin fashion from each
431 * handler's pool of sockets. */
432 for (i = 0; i < n_socks; i++) {
433 struct dpif_handler *handler = &dpif->handlers[i];
434 struct dpif_windows_vport_sock *sock_pool = handler->vport_sock_pool;
435 size_t index = handler->last_used_pool_idx;
436
437 /* A pool of sockets is allocated when the handler is initialized. */
438 if (sock_pool == NULL) {
439 free(socksp);
440 *error = EINVAL;
441 return NULL;
442 }
443
444 ovs_assert(index < VPORT_SOCK_POOL_SIZE);
445 socksp[i] = sock_pool[index].nl_sock;
446 socksp[i] = sock_pool[index].nl_sock;
447 ovs_assert(socksp[i]);
448 index = (index == VPORT_SOCK_POOL_SIZE - 1) ? 0 : index + 1;
449 handler->last_used_pool_idx = index;
450 }
451
452 return socksp;
453}
454
455static void
456vport_del_socksp_windows(struct dpif_netlink *dpif, struct nl_sock **socksp)
457{
458 free(socksp);
459}
460#endif /* _WIN32 */
461
462static struct nl_sock **
463vport_create_socksp(struct dpif_netlink *dpif, int *error)
464{
465#ifdef _WIN32
466 return vport_create_socksp_windows(dpif, error);
467#else
468 return vport_create_socksp__(dpif->n_handlers, error);
469#endif
470}
471
472static void
473vport_del_socksp(struct dpif_netlink *dpif, struct nl_sock **socksp)
474{
475#ifdef _WIN32
476 vport_del_socksp_windows(dpif, socksp);
477#else
478 vport_del_socksp__(socksp, dpif->n_handlers);
479#endif
480}
481
1579cf67
AW
482/* Given the array of pointers to netlink sockets 'socksp', returns
483 * the array of corresponding pids. If the 'socksp' is NULL, returns
484 * a single-element array of value 0. */
485static uint32_t *
486vport_socksp_to_pids(struct nl_sock **socksp, uint32_t n_socks)
487{
488 uint32_t *pids;
489
490 if (!socksp) {
491 pids = xzalloc(sizeof *pids);
492 } else {
493 size_t i;
494
495 pids = xzalloc(n_socks * sizeof *pids);
496 for (i = 0; i < n_socks; i++) {
497 pids[i] = nl_sock_pid(socksp[i]);
498 }
17411ecf 499 }
989fd548 500
1579cf67
AW
501 return pids;
502}
503
504/* Given the port number 'port_idx', extracts the pids of netlink sockets
505 * associated to the port and assigns it to 'upcall_pids'. */
506static bool
93451a0a 507vport_get_pids(struct dpif_netlink *dpif, uint32_t port_idx,
1579cf67
AW
508 uint32_t **upcall_pids)
509{
510 uint32_t *pids;
511 size_t i;
989fd548 512
1579cf67
AW
513 /* Since the nl_sock can only be assigned in either all
514 * or none "dpif->handlers" channels, the following check
515 * would suffice. */
516 if (!dpif->handlers[0].channels[port_idx].sock) {
517 return false;
518 }
09cac43f 519 ovs_assert(!WINDOWS || dpif->n_handlers <= 1);
1579cf67
AW
520
521 pids = xzalloc(dpif->n_handlers * sizeof *pids);
522
523 for (i = 0; i < dpif->n_handlers; i++) {
524 pids[i] = nl_sock_pid(dpif->handlers[i].channels[port_idx].sock);
525 }
526
527 *upcall_pids = pids;
989fd548 528
1579cf67 529 return true;
989fd548
JP
530}
531
532static int
93451a0a 533vport_add_channels(struct dpif_netlink *dpif, odp_port_t port_no,
1579cf67 534 struct nl_sock **socksp)
989fd548
JP
535{
536 struct epoll_event event;
4e022ec0 537 uint32_t port_idx = odp_to_u32(port_no);
1579cf67
AW
538 size_t i, j;
539 int error;
989fd548 540
1579cf67 541 if (dpif->handlers == NULL) {
989fd548
JP
542 return 0;
543 }
544
1579cf67
AW
545 /* We assume that the datapath densely chooses port numbers, which can
546 * therefore be used as an index into 'channels' and 'epoll_events' of
547 * 'dpif->handler'. */
4e022ec0
AW
548 if (port_idx >= dpif->uc_array_size) {
549 uint32_t new_size = port_idx + 1;
989fd548 550
12d76859 551 if (new_size > MAX_PORTS) {
989fd548
JP
552 VLOG_WARN_RL(&error_rl, "%s: datapath port %"PRIu32" too big",
553 dpif_name(&dpif->dpif), port_no);
554 return EFBIG;
555 }
556
1579cf67
AW
557 for (i = 0; i < dpif->n_handlers; i++) {
558 struct dpif_handler *handler = &dpif->handlers[i];
559
560 handler->channels = xrealloc(handler->channels,
561 new_size * sizeof *handler->channels);
562
563 for (j = dpif->uc_array_size; j < new_size; j++) {
564 handler->channels[j].sock = NULL;
565 }
566
567 handler->epoll_events = xrealloc(handler->epoll_events,
568 new_size * sizeof *handler->epoll_events);
989fd548 569
1579cf67 570 }
989fd548
JP
571 dpif->uc_array_size = new_size;
572 }
573
574 memset(&event, 0, sizeof event);
575 event.events = EPOLLIN;
4e022ec0 576 event.data.u32 = port_idx;
989fd548 577
1579cf67
AW
578 for (i = 0; i < dpif->n_handlers; i++) {
579 struct dpif_handler *handler = &dpif->handlers[i];
580
09cac43f 581#ifndef _WIN32
1579cf67
AW
582 if (epoll_ctl(handler->epoll_fd, EPOLL_CTL_ADD, nl_sock_fd(socksp[i]),
583 &event) < 0) {
584 error = errno;
585 goto error;
586 }
93451a0a 587#endif
1579cf67
AW
588 dpif->handlers[i].channels[port_idx].sock = socksp[i];
589 dpif->handlers[i].channels[port_idx].last_poll = LLONG_MIN;
590 }
989fd548
JP
591
592 return 0;
1579cf67
AW
593
594error:
595 for (j = 0; j < i; j++) {
09cac43f 596#ifndef _WIN32
1579cf67
AW
597 epoll_ctl(dpif->handlers[j].epoll_fd, EPOLL_CTL_DEL,
598 nl_sock_fd(socksp[j]), NULL);
93451a0a 599#endif
1579cf67
AW
600 dpif->handlers[j].channels[port_idx].sock = NULL;
601 }
602
603 return error;
989fd548
JP
604}
605
606static void
93451a0a 607vport_del_channels(struct dpif_netlink *dpif, odp_port_t port_no)
989fd548 608{
4e022ec0 609 uint32_t port_idx = odp_to_u32(port_no);
1579cf67 610 size_t i;
989fd548 611
1579cf67 612 if (!dpif->handlers || port_idx >= dpif->uc_array_size) {
989fd548
JP
613 return;
614 }
615
1579cf67
AW
616 /* Since the sock can only be assigned in either all or none
617 * of "dpif->handlers" channels, the following check would
618 * suffice. */
619 if (!dpif->handlers[0].channels[port_idx].sock) {
989fd548
JP
620 return;
621 }
622
1579cf67
AW
623 for (i = 0; i < dpif->n_handlers; i++) {
624 struct dpif_handler *handler = &dpif->handlers[i];
09cac43f 625#ifndef _WIN32
1579cf67
AW
626 epoll_ctl(handler->epoll_fd, EPOLL_CTL_DEL,
627 nl_sock_fd(handler->channels[port_idx].sock), NULL);
628 nl_sock_destroy(handler->channels[port_idx].sock);
09cac43f 629#endif
1579cf67
AW
630 handler->channels[port_idx].sock = NULL;
631 handler->event_offset = handler->n_events = 0;
632 }
633}
634
635static void
93451a0a
AS
636destroy_all_channels(struct dpif_netlink *dpif)
637 OVS_REQ_WRLOCK(dpif->upcall_lock)
1579cf67
AW
638{
639 unsigned int i;
640
641 if (!dpif->handlers) {
642 return;
643 }
644
645 for (i = 0; i < dpif->uc_array_size; i++ ) {
93451a0a 646 struct dpif_netlink_vport vport_request;
1579cf67
AW
647 uint32_t upcall_pids = 0;
648
649 /* Since the sock can only be assigned in either all or none
650 * of "dpif->handlers" channels, the following check would
651 * suffice. */
652 if (!dpif->handlers[0].channels[i].sock) {
653 continue;
654 }
655
656 /* Turn off upcalls. */
93451a0a 657 dpif_netlink_vport_init(&vport_request);
1579cf67
AW
658 vport_request.cmd = OVS_VPORT_CMD_SET;
659 vport_request.dp_ifindex = dpif->dp_ifindex;
660 vport_request.port_no = u32_to_odp(i);
a78f446a 661 vport_request.n_upcall_pids = 1;
1579cf67 662 vport_request.upcall_pids = &upcall_pids;
93451a0a 663 dpif_netlink_vport_transact(&vport_request, NULL, NULL);
1579cf67
AW
664
665 vport_del_channels(dpif, u32_to_odp(i));
666 }
667
668 for (i = 0; i < dpif->n_handlers; i++) {
669 struct dpif_handler *handler = &dpif->handlers[i];
670
09cac43f 671 dpif_netlink_handler_uninit(handler);
1579cf67
AW
672 free(handler->epoll_events);
673 free(handler->channels);
674 }
989fd548 675
1579cf67
AW
676 free(dpif->handlers);
677 dpif->handlers = NULL;
678 dpif->n_handlers = 0;
679 dpif->uc_array_size = 0;
17411ecf
JG
680}
681
96fba48f 682static void
93451a0a 683dpif_netlink_close(struct dpif *dpif_)
96fba48f 684{
93451a0a 685 struct dpif_netlink *dpif = dpif_netlink_cast(dpif_);
c7178a0b 686
e4516b20 687 nl_sock_destroy(dpif->port_notifier);
1579cf67
AW
688
689 fat_rwlock_wrlock(&dpif->upcall_lock);
690 destroy_all_channels(dpif);
691 fat_rwlock_unlock(&dpif->upcall_lock);
692
693 fat_rwlock_destroy(&dpif->upcall_lock);
96fba48f
BP
694 free(dpif);
695}
696
697static int
93451a0a 698dpif_netlink_destroy(struct dpif *dpif_)
96fba48f 699{
93451a0a
AS
700 struct dpif_netlink *dpif = dpif_netlink_cast(dpif_);
701 struct dpif_netlink_dp dp;
d6569377 702
93451a0a 703 dpif_netlink_dp_init(&dp);
df2c07f4 704 dp.cmd = OVS_DP_CMD_DEL;
254f2dc8 705 dp.dp_ifindex = dpif->dp_ifindex;
93451a0a 706 return dpif_netlink_dp_transact(&dp, NULL, NULL);
96fba48f
BP
707}
708
a36de779 709static bool
93451a0a 710dpif_netlink_run(struct dpif *dpif_)
61eae437 711{
93451a0a 712 struct dpif_netlink *dpif = dpif_netlink_cast(dpif_);
1579cf67 713
61eae437
BP
714 if (dpif->refresh_channels) {
715 dpif->refresh_channels = false;
1579cf67 716 fat_rwlock_wrlock(&dpif->upcall_lock);
93451a0a 717 dpif_netlink_refresh_channels(dpif, dpif->n_handlers);
1579cf67 718 fat_rwlock_unlock(&dpif->upcall_lock);
61eae437 719 }
a36de779 720 return false;
61eae437
BP
721}
722
96fba48f 723static int
93451a0a 724dpif_netlink_get_stats(const struct dpif *dpif_, struct dpif_dp_stats *stats)
96fba48f 725{
93451a0a 726 struct dpif_netlink_dp dp;
d6569377
BP
727 struct ofpbuf *buf;
728 int error;
729
93451a0a 730 error = dpif_netlink_dp_get(dpif_, &dp, &buf);
d6569377 731 if (!error) {
6a54dedc
BP
732 memset(stats, 0, sizeof *stats);
733
734 if (dp.stats) {
735 stats->n_hit = get_32aligned_u64(&dp.stats->n_hit);
736 stats->n_missed = get_32aligned_u64(&dp.stats->n_missed);
737 stats->n_lost = get_32aligned_u64(&dp.stats->n_lost);
738 stats->n_flows = get_32aligned_u64(&dp.stats->n_flows);
739 }
740
741 if (dp.megaflow_stats) {
742 stats->n_masks = dp.megaflow_stats->n_masks;
743 stats->n_mask_hit = get_32aligned_u64(
744 &dp.megaflow_stats->n_mask_hit);
745 } else {
746 stats->n_masks = UINT32_MAX;
747 stats->n_mask_hit = UINT64_MAX;
748 }
d6569377
BP
749 ofpbuf_delete(buf);
750 }
751 return error;
96fba48f
BP
752}
753
b9ad7294 754static const char *
93451a0a 755get_vport_type(const struct dpif_netlink_vport *vport)
b9ad7294
EJ
756{
757 static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 20);
758
759 switch (vport->type) {
5ed51209
JS
760 case OVS_VPORT_TYPE_NETDEV: {
761 const char *type = netdev_get_type_from_name(vport->name);
762
763 return type ? type : "system";
764 }
b9ad7294
EJ
765
766 case OVS_VPORT_TYPE_INTERNAL:
767 return "internal";
768
c1fc1411
JG
769 case OVS_VPORT_TYPE_GENEVE:
770 return "geneve";
771
b9ad7294
EJ
772 case OVS_VPORT_TYPE_GRE:
773 return "gre";
774
b9ad7294
EJ
775 case OVS_VPORT_TYPE_VXLAN:
776 return "vxlan";
777
a6ae068b
LJ
778 case OVS_VPORT_TYPE_LISP:
779 return "lisp";
780
4237026e
PS
781 case OVS_VPORT_TYPE_STT:
782 return "stt";
783
b9ad7294
EJ
784 case OVS_VPORT_TYPE_UNSPEC:
785 case __OVS_VPORT_TYPE_MAX:
786 break;
787 }
788
789 VLOG_WARN_RL(&rl, "dp%d: port `%s' has unsupported type %u",
790 vport->dp_ifindex, vport->name, (unsigned int) vport->type);
791 return "unknown";
792}
793
c4e08753 794enum ovs_vport_type
20c57607 795netdev_to_ovs_vport_type(const char *type)
c060c4cf 796{
c060c4cf
EJ
797 if (!strcmp(type, "tap") || !strcmp(type, "system")) {
798 return OVS_VPORT_TYPE_NETDEV;
799 } else if (!strcmp(type, "internal")) {
800 return OVS_VPORT_TYPE_INTERNAL;
4237026e
PS
801 } else if (strstr(type, "stt")) {
802 return OVS_VPORT_TYPE_STT;
c1fc1411
JG
803 } else if (!strcmp(type, "geneve")) {
804 return OVS_VPORT_TYPE_GENEVE;
c060c4cf
EJ
805 } else if (strstr(type, "gre")) {
806 return OVS_VPORT_TYPE_GRE;
c060c4cf
EJ
807 } else if (!strcmp(type, "vxlan")) {
808 return OVS_VPORT_TYPE_VXLAN;
a6ae068b
LJ
809 } else if (!strcmp(type, "lisp")) {
810 return OVS_VPORT_TYPE_LISP;
c060c4cf
EJ
811 } else {
812 return OVS_VPORT_TYPE_UNSPEC;
813 }
814}
815
96fba48f 816static int
20c57607
EG
817dpif_netlink_port_add__(struct dpif_netlink *dpif, const char *name,
818 enum ovs_vport_type type,
819 struct ofpbuf *options,
93451a0a 820 odp_port_t *port_nop)
b90de034 821 OVS_REQ_WRLOCK(dpif->upcall_lock)
96fba48f 822{
93451a0a 823 struct dpif_netlink_vport request, reply;
c19e6535 824 struct ofpbuf *buf;
1579cf67
AW
825 struct nl_sock **socksp = NULL;
826 uint32_t *upcall_pids;
827 int error = 0;
96fba48f 828
1579cf67 829 if (dpif->handlers) {
09cac43f 830 socksp = vport_create_socksp(dpif, &error);
1579cf67 831 if (!socksp) {
989fd548
JP
832 return error;
833 }
834 }
835
93451a0a 836 dpif_netlink_vport_init(&request);
df2c07f4 837 request.cmd = OVS_VPORT_CMD_NEW;
254f2dc8 838 request.dp_ifindex = dpif->dp_ifindex;
20c57607
EG
839 request.type = type;
840 request.name = name;
841
842 request.port_no = *port_nop;
843 upcall_pids = vport_socksp_to_pids(socksp, dpif->n_handlers);
844 request.n_upcall_pids = socksp ? dpif->n_handlers : 1;
845 request.upcall_pids = upcall_pids;
846
847 if (options) {
848 request.options = options->data;
849 request.options_len = options->size;
850 }
851
852 error = dpif_netlink_vport_transact(&request, &reply, &buf);
853 if (!error) {
854 *port_nop = reply.port_no;
855 } else {
856 if (error == EBUSY && *port_nop != ODPP_NONE) {
857 VLOG_INFO("%s: requested port %"PRIu32" is in use",
858 dpif_name(&dpif->dpif), *port_nop);
859 }
860
861 vport_del_socksp(dpif, socksp);
862 goto exit;
863 }
864
865 if (socksp) {
866 error = vport_add_channels(dpif, *port_nop, socksp);
867 if (error) {
868 VLOG_INFO("%s: could not add channel for port %s",
869 dpif_name(&dpif->dpif), name);
870
871 /* Delete the port. */
872 dpif_netlink_vport_init(&request);
873 request.cmd = OVS_VPORT_CMD_DEL;
874 request.dp_ifindex = dpif->dp_ifindex;
875 request.port_no = *port_nop;
876 dpif_netlink_vport_transact(&request, NULL, NULL);
877 vport_del_socksp(dpif, socksp);
878 goto exit;
879 }
880 }
881 free(socksp);
882
883exit:
884 ofpbuf_delete(buf);
885 free(upcall_pids);
886
887 return error;
888}
889
890static int
891dpif_netlink_port_add_compat(struct dpif_netlink *dpif, struct netdev *netdev,
892 odp_port_t *port_nop)
893 OVS_REQ_WRLOCK(dpif->upcall_lock)
894{
895 const struct netdev_tunnel_config *tnl_cfg;
896 char namebuf[NETDEV_VPORT_NAME_BUFSIZE];
897 const char *type = netdev_get_type(netdev);
898 uint64_t options_stub[64 / 8];
899 enum ovs_vport_type ovs_type;
900 struct ofpbuf options;
901 const char *name;
902
903 name = netdev_vport_get_dpif_port(netdev, namebuf, sizeof namebuf);
904
905 ovs_type = netdev_to_ovs_vport_type(netdev_get_type(netdev));
906 if (ovs_type == OVS_VPORT_TYPE_UNSPEC) {
c283069c
BP
907 VLOG_WARN_RL(&error_rl, "%s: cannot create port `%s' because it has "
908 "unsupported type `%s'",
9b00386b 909 dpif_name(&dpif->dpif), name, type);
c283069c
BP
910 return EINVAL;
911 }
c3827f61 912
20c57607 913 if (ovs_type == OVS_VPORT_TYPE_NETDEV) {
93451a0a 914#ifdef _WIN32
09cac43f 915 /* XXX : Map appropiate Windows handle */
93451a0a 916#else
24b019f8 917 netdev_linux_ethtool_set_flag(netdev, ETH_FLAG_LRO, "LRO", false);
93451a0a 918#endif
24b019f8
JP
919 }
920
da467899 921#ifdef _WIN32
20c57607 922 if (ovs_type == OVS_VPORT_TYPE_INTERNAL) {
da467899
AS
923 if (!create_wmi_port(name)){
924 VLOG_ERR("Could not create wmi internal port with name:%s", name);
da467899
AS
925 return EINVAL;
926 };
927 }
928#endif
929
26508d9a 930 tnl_cfg = netdev_get_tunnel_config(netdev);
526df7d8 931 if (tnl_cfg && (tnl_cfg->dst_port != 0 || tnl_cfg->exts)) {
26508d9a 932 ofpbuf_use_stack(&options, options_stub, sizeof options_stub);
526df7d8
TG
933 if (tnl_cfg->dst_port) {
934 nl_msg_put_u16(&options, OVS_TUNNEL_ATTR_DST_PORT,
935 ntohs(tnl_cfg->dst_port));
936 }
937 if (tnl_cfg->exts) {
938 size_t ext_ofs;
939 int i;
940
941 ext_ofs = nl_msg_start_nested(&options, OVS_TUNNEL_ATTR_EXTENSION);
942 for (i = 0; i < 32; i++) {
943 if (tnl_cfg->exts & (1 << i)) {
944 nl_msg_put_flag(&options, i);
945 }
946 }
947 nl_msg_end_nested(&options, ext_ofs);
948 }
20c57607
EG
949 return dpif_netlink_port_add__(dpif, name, ovs_type, &options,
950 port_nop);
2510ba7c 951 } else {
20c57607 952 return dpif_netlink_port_add__(dpif, name, ovs_type, NULL, port_nop);
78a2d59c 953 }
c3827f61 954
20c57607 955}
989fd548 956
921c370a 957static int
c4e08753
EG
958dpif_netlink_rtnl_port_create_and_add(struct dpif_netlink *dpif,
959 struct netdev *netdev,
960 odp_port_t *port_nop)
961 OVS_REQ_WRLOCK(dpif->upcall_lock)
962{
963 static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 20);
964 char namebuf[NETDEV_VPORT_NAME_BUFSIZE];
965 const char *name;
966 int error;
989fd548 967
c4e08753
EG
968 error = dpif_netlink_rtnl_port_create(netdev);
969 if (error) {
970 if (error != EOPNOTSUPP) {
971 VLOG_INFO_RL(&rl, "Failed to create %s with rtnetlink: %s",
972 netdev_get_name(netdev), ovs_strerror(error));
973 }
974 return error;
975 }
1579cf67 976
c4e08753
EG
977 name = netdev_vport_get_dpif_port(netdev, namebuf, sizeof namebuf);
978 error = dpif_netlink_port_add__(dpif, name, OVS_VPORT_TYPE_NETDEV, NULL,
979 port_nop);
980 if (error) {
981 dpif_netlink_rtnl_port_destroy(name, netdev_get_type(netdev));
982 }
983 return error;
984}
96fba48f
BP
985
986static int
93451a0a
AS
987dpif_netlink_port_add(struct dpif *dpif_, struct netdev *netdev,
988 odp_port_t *port_nop)
9fafa796 989{
93451a0a 990 struct dpif_netlink *dpif = dpif_netlink_cast(dpif_);
921c370a 991 int error = EOPNOTSUPP;
9fafa796 992
1579cf67 993 fat_rwlock_wrlock(&dpif->upcall_lock);
921c370a
EG
994 if (!ovs_tunnels_out_of_tree) {
995 error = dpif_netlink_rtnl_port_create_and_add(dpif, netdev, port_nop);
996 }
997 if (error) {
998 error = dpif_netlink_port_add_compat(dpif, netdev, port_nop);
999 }
1579cf67 1000 fat_rwlock_unlock(&dpif->upcall_lock);
9fafa796
BP
1001
1002 return error;
1003}
1004
1005static int
93451a0a 1006dpif_netlink_port_del__(struct dpif_netlink *dpif, odp_port_t port_no)
b90de034 1007 OVS_REQ_WRLOCK(dpif->upcall_lock)
96fba48f 1008{
93451a0a 1009 struct dpif_netlink_vport vport;
921c370a 1010 struct dpif_port dpif_port;
773cd538 1011 int error;
c19e6535 1012
921c370a
EG
1013 error = dpif_netlink_port_query__(dpif, port_no, NULL, &dpif_port);
1014 if (error) {
1015 return error;
1016 }
1017
93451a0a 1018 dpif_netlink_vport_init(&vport);
df2c07f4 1019 vport.cmd = OVS_VPORT_CMD_DEL;
254f2dc8 1020 vport.dp_ifindex = dpif->dp_ifindex;
c19e6535 1021 vport.port_no = port_no;
da467899 1022#ifdef _WIN32
921c370a
EG
1023 if (!strcmp(dpif_port.type, "internal")) {
1024 if (!delete_wmi_port(dpif_port.name)) {
da467899 1025 VLOG_ERR("Could not delete wmi port with name: %s",
921c370a 1026 dpif_port.name);
da467899
AS
1027 };
1028 }
1029#endif
93451a0a 1030 error = dpif_netlink_vport_transact(&vport, NULL, NULL);
773cd538 1031
1579cf67 1032 vport_del_channels(dpif, port_no);
989fd548 1033
921c370a
EG
1034 if (!error && !ovs_tunnels_out_of_tree) {
1035 error = dpif_netlink_rtnl_port_destroy(dpif_port.name, dpif_port.type);
1036 if (error == EOPNOTSUPP) {
1037 error = 0;
1038 }
1039 }
1040
1041 dpif_port_destroy(&dpif_port);
1042
773cd538 1043 return error;
c3827f61 1044}
3abc4a1a 1045
9fafa796 1046static int
93451a0a 1047dpif_netlink_port_del(struct dpif *dpif_, odp_port_t port_no)
9fafa796 1048{
93451a0a 1049 struct dpif_netlink *dpif = dpif_netlink_cast(dpif_);
9fafa796
BP
1050 int error;
1051
1579cf67 1052 fat_rwlock_wrlock(&dpif->upcall_lock);
93451a0a 1053 error = dpif_netlink_port_del__(dpif, port_no);
1579cf67 1054 fat_rwlock_unlock(&dpif->upcall_lock);
9fafa796
BP
1055
1056 return error;
1057}
1058
c3827f61 1059static int
93451a0a
AS
1060dpif_netlink_port_query__(const struct dpif_netlink *dpif, odp_port_t port_no,
1061 const char *port_name, struct dpif_port *dpif_port)
c3827f61 1062{
93451a0a
AS
1063 struct dpif_netlink_vport request;
1064 struct dpif_netlink_vport reply;
c19e6535 1065 struct ofpbuf *buf;
4c738a8d
BP
1066 int error;
1067
93451a0a 1068 dpif_netlink_vport_init(&request);
df2c07f4 1069 request.cmd = OVS_VPORT_CMD_GET;
9b00386b 1070 request.dp_ifindex = dpif->dp_ifindex;
c19e6535
BP
1071 request.port_no = port_no;
1072 request.name = port_name;
4c738a8d 1073
93451a0a 1074 error = dpif_netlink_vport_transact(&request, &reply, &buf);
c19e6535 1075 if (!error) {
33db1592
BP
1076 if (reply.dp_ifindex != request.dp_ifindex) {
1077 /* A query by name reported that 'port_name' is in some datapath
1078 * other than 'dpif', but the caller wants to know about 'dpif'. */
1079 error = ENODEV;
4afba28d 1080 } else if (dpif_port) {
33db1592 1081 dpif_port->name = xstrdup(reply.name);
b9ad7294 1082 dpif_port->type = xstrdup(get_vport_type(&reply));
33db1592
BP
1083 dpif_port->port_no = reply.port_no;
1084 }
c19e6535 1085 ofpbuf_delete(buf);
3abc4a1a 1086 }
c19e6535 1087 return error;
96fba48f
BP
1088}
1089
1090static int
93451a0a
AS
1091dpif_netlink_port_query_by_number(const struct dpif *dpif_, odp_port_t port_no,
1092 struct dpif_port *dpif_port)
96fba48f 1093{
93451a0a 1094 struct dpif_netlink *dpif = dpif_netlink_cast(dpif_);
9b00386b 1095
93451a0a 1096 return dpif_netlink_port_query__(dpif, port_no, NULL, dpif_port);
96fba48f
BP
1097}
1098
1099static int
93451a0a 1100dpif_netlink_port_query_by_name(const struct dpif *dpif_, const char *devname,
4c738a8d 1101 struct dpif_port *dpif_port)
96fba48f 1102{
93451a0a 1103 struct dpif_netlink *dpif = dpif_netlink_cast(dpif_);
9b00386b 1104
93451a0a 1105 return dpif_netlink_port_query__(dpif, 0, devname, dpif_port);
96fba48f
BP
1106}
1107
98403001 1108static uint32_t
93451a0a
AS
1109dpif_netlink_port_get_pid__(const struct dpif_netlink *dpif,
1110 odp_port_t port_no, uint32_t hash)
b90de034 1111 OVS_REQ_RDLOCK(dpif->upcall_lock)
98403001 1112{
4e022ec0 1113 uint32_t port_idx = odp_to_u32(port_no);
9fafa796 1114 uint32_t pid = 0;
98403001 1115
f8fc5489 1116 if (dpif->handlers && dpif->uc_array_size > 0) {
4e022ec0 1117 /* The ODPP_NONE "reserved" port number uses the "ovs-system"'s
989fd548 1118 * channel, since it is not heavily loaded. */
4e022ec0 1119 uint32_t idx = port_idx >= dpif->uc_array_size ? 0 : port_idx;
1579cf67
AW
1120 struct dpif_handler *h = &dpif->handlers[hash % dpif->n_handlers];
1121
17f2748d
AW
1122 /* Needs to check in case the socket pointer is changed in between
1123 * the holding of upcall_lock. A known case happens when the main
1124 * thread deletes the vport while the handler thread is handling
1125 * the upcall from that port. */
1126 if (h->channels[idx].sock) {
1127 pid = nl_sock_pid(h->channels[idx].sock);
1128 }
98403001 1129 }
9fafa796
BP
1130
1131 return pid;
98403001
BP
1132}
1133
b90de034 1134static uint32_t
93451a0a
AS
1135dpif_netlink_port_get_pid(const struct dpif *dpif_, odp_port_t port_no,
1136 uint32_t hash)
b90de034 1137{
93451a0a 1138 const struct dpif_netlink *dpif = dpif_netlink_cast(dpif_);
b90de034
AW
1139 uint32_t ret;
1140
1141 fat_rwlock_rdlock(&dpif->upcall_lock);
93451a0a 1142 ret = dpif_netlink_port_get_pid__(dpif, port_no, hash);
b90de034
AW
1143 fat_rwlock_unlock(&dpif->upcall_lock);
1144
1145 return ret;
1146}
1147
96fba48f 1148static int
93451a0a 1149dpif_netlink_flow_flush(struct dpif *dpif_)
96fba48f 1150{
93451a0a
AS
1151 const struct dpif_netlink *dpif = dpif_netlink_cast(dpif_);
1152 struct dpif_netlink_flow flow;
37a1300c 1153
93451a0a 1154 dpif_netlink_flow_init(&flow);
df2c07f4 1155 flow.cmd = OVS_FLOW_CMD_DEL;
254f2dc8 1156 flow.dp_ifindex = dpif->dp_ifindex;
93451a0a 1157 return dpif_netlink_flow_transact(&flow, NULL, NULL);
96fba48f
BP
1158}
1159
93451a0a 1160struct dpif_netlink_port_state {
f0fef760 1161 struct nl_dump dump;
d57695d7 1162 struct ofpbuf buf;
c19e6535
BP
1163};
1164
222837c4 1165static void
93451a0a
AS
1166dpif_netlink_port_dump_start__(const struct dpif_netlink *dpif,
1167 struct nl_dump *dump)
96fba48f 1168{
93451a0a 1169 struct dpif_netlink_vport request;
f0fef760
BP
1170 struct ofpbuf *buf;
1171
93451a0a 1172 dpif_netlink_vport_init(&request);
067f1e23 1173 request.cmd = OVS_VPORT_CMD_GET;
254f2dc8 1174 request.dp_ifindex = dpif->dp_ifindex;
f0fef760
BP
1175
1176 buf = ofpbuf_new(1024);
93451a0a 1177 dpif_netlink_vport_to_ofpbuf(&request, buf);
222837c4 1178 nl_dump_start(dump, NETLINK_GENERIC, buf);
f0fef760 1179 ofpbuf_delete(buf);
222837c4
BP
1180}
1181
1182static int
93451a0a 1183dpif_netlink_port_dump_start(const struct dpif *dpif_, void **statep)
222837c4 1184{
93451a0a
AS
1185 struct dpif_netlink *dpif = dpif_netlink_cast(dpif_);
1186 struct dpif_netlink_port_state *state;
222837c4
BP
1187
1188 *statep = state = xmalloc(sizeof *state);
93451a0a 1189 dpif_netlink_port_dump_start__(dpif, &state->dump);
f0fef760 1190
d57695d7 1191 ofpbuf_init(&state->buf, NL_DUMP_BUFSIZE);
b0ec0f27
BP
1192 return 0;
1193}
1194
7c1ef244 1195static int
93451a0a
AS
1196dpif_netlink_port_dump_next__(const struct dpif_netlink *dpif,
1197 struct nl_dump *dump,
1198 struct dpif_netlink_vport *vport,
1199 struct ofpbuf *buffer)
222837c4 1200{
222837c4
BP
1201 struct ofpbuf buf;
1202 int error;
1203
d57695d7 1204 if (!nl_dump_next(dump, &buf, buffer)) {
222837c4
BP
1205 return EOF;
1206 }
1207
93451a0a 1208 error = dpif_netlink_vport_from_ofpbuf(vport, &buf);
222837c4
BP
1209 if (error) {
1210 VLOG_WARN_RL(&error_rl, "%s: failed to parse vport record (%s)",
1211 dpif_name(&dpif->dpif), ovs_strerror(error));
1212 }
1213 return error;
1214}
1215
b0ec0f27 1216static int
93451a0a
AS
1217dpif_netlink_port_dump_next(const struct dpif *dpif_, void *state_,
1218 struct dpif_port *dpif_port)
b0ec0f27 1219{
93451a0a
AS
1220 struct dpif_netlink *dpif = dpif_netlink_cast(dpif_);
1221 struct dpif_netlink_port_state *state = state_;
1222 struct dpif_netlink_vport vport;
96fba48f
BP
1223 int error;
1224
93451a0a
AS
1225 error = dpif_netlink_port_dump_next__(dpif, &state->dump, &vport,
1226 &state->buf);
c3827f61 1227 if (error) {
f0fef760 1228 return error;
c3827f61 1229 }
ebc56baa 1230 dpif_port->name = CONST_CAST(char *, vport.name);
b9ad7294 1231 dpif_port->type = CONST_CAST(char *, get_vport_type(&vport));
f0fef760
BP
1232 dpif_port->port_no = vport.port_no;
1233 return 0;
b0ec0f27
BP
1234}
1235
1236static int
93451a0a 1237dpif_netlink_port_dump_done(const struct dpif *dpif_ OVS_UNUSED, void *state_)
b0ec0f27 1238{
93451a0a 1239 struct dpif_netlink_port_state *state = state_;
f0fef760 1240 int error = nl_dump_done(&state->dump);
8522b383 1241
d57695d7 1242 ofpbuf_uninit(&state->buf);
b0ec0f27 1243 free(state);
f0fef760 1244 return error;
96fba48f
BP
1245}
1246
e9e28be3 1247static int
93451a0a 1248dpif_netlink_port_poll(const struct dpif *dpif_, char **devnamep)
e9e28be3 1249{
93451a0a 1250 struct dpif_netlink *dpif = dpif_netlink_cast(dpif_);
e9e28be3 1251
e4516b20
BP
1252 /* Lazily create the Netlink socket to listen for notifications. */
1253 if (!dpif->port_notifier) {
1254 struct nl_sock *sock;
1255 int error;
1256
1257 error = nl_sock_create(NETLINK_GENERIC, &sock);
1258 if (error) {
1259 return error;
1260 }
1261
1262 error = nl_sock_join_mcgroup(sock, ovs_vport_mcgroup);
1263 if (error) {
1264 nl_sock_destroy(sock);
1265 return error;
1266 }
1267 dpif->port_notifier = sock;
1268
1269 /* We have no idea of the current state so report that everything
1270 * changed. */
1271 return ENOBUFS;
1272 }
1273
1274 for (;;) {
1275 static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
1276 uint64_t buf_stub[4096 / 8];
1277 struct ofpbuf buf;
1278 int error;
1279
1280 ofpbuf_use_stub(&buf, buf_stub, sizeof buf_stub);
1281 error = nl_sock_recv(dpif->port_notifier, &buf, false);
1282 if (!error) {
93451a0a 1283 struct dpif_netlink_vport vport;
e4516b20 1284
93451a0a 1285 error = dpif_netlink_vport_from_ofpbuf(&vport, &buf);
e4516b20
BP
1286 if (!error) {
1287 if (vport.dp_ifindex == dpif->dp_ifindex
1288 && (vport.cmd == OVS_VPORT_CMD_NEW
1289 || vport.cmd == OVS_VPORT_CMD_DEL
1290 || vport.cmd == OVS_VPORT_CMD_SET)) {
1291 VLOG_DBG("port_changed: dpif:%s vport:%s cmd:%"PRIu8,
1292 dpif->dpif.full_name, vport.name, vport.cmd);
1579cf67 1293 if (vport.cmd == OVS_VPORT_CMD_DEL && dpif->handlers) {
61eae437
BP
1294 dpif->refresh_channels = true;
1295 }
e4516b20 1296 *devnamep = xstrdup(vport.name);
59e0c910 1297 ofpbuf_uninit(&buf);
e4516b20 1298 return 0;
e4516b20
BP
1299 }
1300 }
59e0c910
BP
1301 } else if (error != EAGAIN) {
1302 VLOG_WARN_RL(&rl, "error reading or parsing netlink (%s)",
1303 ovs_strerror(error));
1304 nl_sock_drain(dpif->port_notifier);
1305 error = ENOBUFS;
e4516b20
BP
1306 }
1307
59e0c910
BP
1308 ofpbuf_uninit(&buf);
1309 if (error) {
1310 return error;
1311 }
e9e28be3 1312 }
e9e28be3
BP
1313}
1314
1315static void
93451a0a 1316dpif_netlink_port_poll_wait(const struct dpif *dpif_)
e9e28be3 1317{
93451a0a 1318 const struct dpif_netlink *dpif = dpif_netlink_cast(dpif_);
e4516b20
BP
1319
1320 if (dpif->port_notifier) {
1321 nl_sock_wait(dpif->port_notifier, POLLIN);
1322 } else {
e9e28be3 1323 poll_immediate_wake();
e9e28be3
BP
1324 }
1325}
1326
6fe09f8c 1327static void
70e5ed6f
JS
1328dpif_netlink_flow_init_ufid(struct dpif_netlink_flow *request,
1329 const ovs_u128 *ufid, bool terse)
1330{
1331 if (ufid) {
1332 request->ufid = *ufid;
1333 request->ufid_present = true;
1334 } else {
1335 request->ufid_present = false;
1336 }
1337 request->ufid_terse = terse;
1338}
1339
1340static void
1341dpif_netlink_init_flow_get__(const struct dpif_netlink *dpif,
1342 const struct nlattr *key, size_t key_len,
1343 const ovs_u128 *ufid, bool terse,
1344 struct dpif_netlink_flow *request)
96fba48f 1345{
93451a0a 1346 dpif_netlink_flow_init(request);
6fe09f8c
JS
1347 request->cmd = OVS_FLOW_CMD_GET;
1348 request->dp_ifindex = dpif->dp_ifindex;
1349 request->key = key;
1350 request->key_len = key_len;
70e5ed6f
JS
1351 dpif_netlink_flow_init_ufid(request, ufid, terse);
1352}
1353
1354static void
1355dpif_netlink_init_flow_get(const struct dpif_netlink *dpif,
1356 const struct dpif_flow_get *get,
1357 struct dpif_netlink_flow *request)
1358{
1359 dpif_netlink_init_flow_get__(dpif, get->key, get->key_len, get->ufid,
1360 false, request);
30053024
BP
1361}
1362
1363static int
70e5ed6f
JS
1364dpif_netlink_flow_get__(const struct dpif_netlink *dpif,
1365 const struct nlattr *key, size_t key_len,
1366 const ovs_u128 *ufid, bool terse,
1367 struct dpif_netlink_flow *reply, struct ofpbuf **bufp)
30053024 1368{
93451a0a 1369 struct dpif_netlink_flow request;
30053024 1370
70e5ed6f 1371 dpif_netlink_init_flow_get__(dpif, key, key_len, ufid, terse, &request);
93451a0a 1372 return dpif_netlink_flow_transact(&request, reply, bufp);
96fba48f
BP
1373}
1374
70e5ed6f
JS
1375static int
1376dpif_netlink_flow_get(const struct dpif_netlink *dpif,
1377 const struct dpif_netlink_flow *flow,
1378 struct dpif_netlink_flow *reply, struct ofpbuf **bufp)
1379{
1380 return dpif_netlink_flow_get__(dpif, flow->key, flow->key_len,
1381 flow->ufid_present ? &flow->ufid : NULL,
1382 false, reply, bufp);
1383}
1384
6bc60024 1385static void
93451a0a
AS
1386dpif_netlink_init_flow_put(struct dpif_netlink *dpif,
1387 const struct dpif_flow_put *put,
1388 struct dpif_netlink_flow *request)
6bc60024 1389{
d64e176c 1390 static const struct nlattr dummy_action;
6bc60024 1391
93451a0a 1392 dpif_netlink_flow_init(request);
89625d1e 1393 request->cmd = (put->flags & DPIF_FP_CREATE
6bc60024
BP
1394 ? OVS_FLOW_CMD_NEW : OVS_FLOW_CMD_SET);
1395 request->dp_ifindex = dpif->dp_ifindex;
89625d1e
BP
1396 request->key = put->key;
1397 request->key_len = put->key_len;
e6cc0bab
AZ
1398 request->mask = put->mask;
1399 request->mask_len = put->mask_len;
70e5ed6f
JS
1400 dpif_netlink_flow_init_ufid(request, put->ufid, false);
1401
6bc60024 1402 /* Ensure that OVS_FLOW_ATTR_ACTIONS will always be included. */
d64e176c
BP
1403 request->actions = (put->actions
1404 ? put->actions
1405 : CONST_CAST(struct nlattr *, &dummy_action));
89625d1e
BP
1406 request->actions_len = put->actions_len;
1407 if (put->flags & DPIF_FP_ZERO_STATS) {
6bc60024
BP
1408 request->clear = true;
1409 }
43f9ac0a
JR
1410 if (put->flags & DPIF_FP_PROBE) {
1411 request->probe = true;
1412 }
89625d1e 1413 request->nlmsg_flags = put->flags & DPIF_FP_MODIFY ? 0 : NLM_F_CREATE;
6bc60024
BP
1414}
1415
b99d3cee 1416static void
70e5ed6f
JS
1417dpif_netlink_init_flow_del__(struct dpif_netlink *dpif,
1418 const struct nlattr *key, size_t key_len,
1419 const ovs_u128 *ufid, bool terse,
1420 struct dpif_netlink_flow *request)
96fba48f 1421{
93451a0a 1422 dpif_netlink_flow_init(request);
b99d3cee
BP
1423 request->cmd = OVS_FLOW_CMD_DEL;
1424 request->dp_ifindex = dpif->dp_ifindex;
70e5ed6f
JS
1425 request->key = key;
1426 request->key_len = key_len;
1427 dpif_netlink_flow_init_ufid(request, ufid, terse);
1428}
1429
1430static void
1431dpif_netlink_init_flow_del(struct dpif_netlink *dpif,
1432 const struct dpif_flow_del *del,
1433 struct dpif_netlink_flow *request)
1434{
37382aa6
AS
1435 dpif_netlink_init_flow_del__(dpif, del->key, del->key_len,
1436 del->ufid, del->terse, request);
70e5ed6f
JS
1437}
1438
93451a0a 1439struct dpif_netlink_flow_dump {
ac64794a
BP
1440 struct dpif_flow_dump up;
1441 struct nl_dump nl_dump;
d2ad7ef1 1442 atomic_int status;
e723fd32
JS
1443};
1444
93451a0a
AS
1445static struct dpif_netlink_flow_dump *
1446dpif_netlink_flow_dump_cast(struct dpif_flow_dump *dump)
e723fd32 1447{
93451a0a 1448 return CONTAINER_OF(dump, struct dpif_netlink_flow_dump, up);
e723fd32
JS
1449}
1450
ac64794a 1451static struct dpif_flow_dump *
64bb477f 1452dpif_netlink_flow_dump_create(const struct dpif *dpif_, bool terse)
96fba48f 1453{
93451a0a
AS
1454 const struct dpif_netlink *dpif = dpif_netlink_cast(dpif_);
1455 struct dpif_netlink_flow_dump *dump;
1456 struct dpif_netlink_flow request;
37a1300c
BP
1457 struct ofpbuf *buf;
1458
ac64794a
BP
1459 dump = xmalloc(sizeof *dump);
1460 dpif_flow_dump_init(&dump->up, dpif_);
37a1300c 1461
93451a0a 1462 dpif_netlink_flow_init(&request);
067f1e23 1463 request.cmd = OVS_FLOW_CMD_GET;
254f2dc8 1464 request.dp_ifindex = dpif->dp_ifindex;
64bb477f
JS
1465 request.ufid_present = false;
1466 request.ufid_terse = terse;
37a1300c
BP
1467
1468 buf = ofpbuf_new(1024);
93451a0a 1469 dpif_netlink_flow_to_ofpbuf(&request, buf);
ac64794a 1470 nl_dump_start(&dump->nl_dump, NETLINK_GENERIC, buf);
37a1300c 1471 ofpbuf_delete(buf);
ac64794a 1472 atomic_init(&dump->status, 0);
64bb477f 1473 dump->up.terse = terse;
30053024 1474
ac64794a 1475 return &dump->up;
704a1e09
BP
1476}
1477
1478static int
93451a0a 1479dpif_netlink_flow_dump_destroy(struct dpif_flow_dump *dump_)
704a1e09 1480{
93451a0a 1481 struct dpif_netlink_flow_dump *dump = dpif_netlink_flow_dump_cast(dump_);
ac64794a
BP
1482 unsigned int nl_status = nl_dump_done(&dump->nl_dump);
1483 int dump_status;
96fba48f 1484
7424fc44
JR
1485 /* No other thread has access to 'dump' at this point. */
1486 atomic_read_relaxed(&dump->status, &dump_status);
ac64794a
BP
1487 free(dump);
1488 return dump_status ? dump_status : nl_status;
1489}
feebdea2 1490
93451a0a 1491struct dpif_netlink_flow_dump_thread {
ac64794a 1492 struct dpif_flow_dump_thread up;
93451a0a
AS
1493 struct dpif_netlink_flow_dump *dump;
1494 struct dpif_netlink_flow flow;
ac64794a
BP
1495 struct dpif_flow_stats stats;
1496 struct ofpbuf nl_flows; /* Always used to store flows. */
1497 struct ofpbuf *nl_actions; /* Used if kernel does not supply actions. */
1498};
1499
93451a0a
AS
1500static struct dpif_netlink_flow_dump_thread *
1501dpif_netlink_flow_dump_thread_cast(struct dpif_flow_dump_thread *thread)
ac64794a 1502{
93451a0a 1503 return CONTAINER_OF(thread, struct dpif_netlink_flow_dump_thread, up);
ac64794a
BP
1504}
1505
1506static struct dpif_flow_dump_thread *
93451a0a 1507dpif_netlink_flow_dump_thread_create(struct dpif_flow_dump *dump_)
ac64794a 1508{
93451a0a
AS
1509 struct dpif_netlink_flow_dump *dump = dpif_netlink_flow_dump_cast(dump_);
1510 struct dpif_netlink_flow_dump_thread *thread;
ac64794a
BP
1511
1512 thread = xmalloc(sizeof *thread);
1513 dpif_flow_dump_thread_init(&thread->up, &dump->up);
1514 thread->dump = dump;
1515 ofpbuf_init(&thread->nl_flows, NL_DUMP_BUFSIZE);
1516 thread->nl_actions = NULL;
1517
1518 return &thread->up;
1519}
1520
1521static void
93451a0a 1522dpif_netlink_flow_dump_thread_destroy(struct dpif_flow_dump_thread *thread_)
ac64794a 1523{
93451a0a
AS
1524 struct dpif_netlink_flow_dump_thread *thread
1525 = dpif_netlink_flow_dump_thread_cast(thread_);
ac64794a
BP
1526
1527 ofpbuf_uninit(&thread->nl_flows);
1528 ofpbuf_delete(thread->nl_actions);
1529 free(thread);
1530}
1531
1532static void
7af12bd7 1533dpif_netlink_flow_to_dpif_flow(struct dpif *dpif, struct dpif_flow *dpif_flow,
7fe98598 1534 const struct dpif_netlink_flow *datapath_flow)
ac64794a 1535{
7fe98598
NR
1536 dpif_flow->key = datapath_flow->key;
1537 dpif_flow->key_len = datapath_flow->key_len;
1538 dpif_flow->mask = datapath_flow->mask;
1539 dpif_flow->mask_len = datapath_flow->mask_len;
1540 dpif_flow->actions = datapath_flow->actions;
1541 dpif_flow->actions_len = datapath_flow->actions_len;
70e5ed6f 1542 dpif_flow->ufid_present = datapath_flow->ufid_present;
ec97c2df 1543 dpif_flow->pmd_id = PMD_ID_NULL;
70e5ed6f
JS
1544 if (datapath_flow->ufid_present) {
1545 dpif_flow->ufid = datapath_flow->ufid;
1546 } else {
1547 ovs_assert(datapath_flow->key && datapath_flow->key_len);
1548 dpif_flow_hash(dpif, datapath_flow->key, datapath_flow->key_len,
1549 &dpif_flow->ufid);
1550 }
7fe98598 1551 dpif_netlink_flow_get_stats(datapath_flow, &dpif_flow->stats);
ac64794a
BP
1552}
1553
1554static int
93451a0a
AS
1555dpif_netlink_flow_dump_next(struct dpif_flow_dump_thread *thread_,
1556 struct dpif_flow *flows, int max_flows)
ac64794a 1557{
93451a0a
AS
1558 struct dpif_netlink_flow_dump_thread *thread
1559 = dpif_netlink_flow_dump_thread_cast(thread_);
1560 struct dpif_netlink_flow_dump *dump = thread->dump;
1561 struct dpif_netlink *dpif = dpif_netlink_cast(thread->up.dpif);
ac64794a
BP
1562 int n_flows;
1563
1564 ofpbuf_delete(thread->nl_actions);
1565 thread->nl_actions = NULL;
1566
1567 n_flows = 0;
1568 while (!n_flows
6fd6ed71 1569 || (n_flows < max_flows && thread->nl_flows.size)) {
7fe98598 1570 struct dpif_netlink_flow datapath_flow;
ac64794a
BP
1571 struct ofpbuf nl_flow;
1572 int error;
1573
1574 /* Try to grab another flow. */
1575 if (!nl_dump_next(&dump->nl_dump, &nl_flow, &thread->nl_flows)) {
1576 break;
feebdea2 1577 }
30053024 1578
ac64794a 1579 /* Convert the flow to our output format. */
7fe98598 1580 error = dpif_netlink_flow_from_ofpbuf(&datapath_flow, &nl_flow);
30053024 1581 if (error) {
7424fc44 1582 atomic_store_relaxed(&dump->status, error);
ac64794a 1583 break;
feebdea2 1584 }
30053024 1585
64bb477f
JS
1586 if (dump->up.terse || datapath_flow.actions) {
1587 /* Common case: we don't want actions, or the flow includes
1588 * actions. */
7af12bd7
JS
1589 dpif_netlink_flow_to_dpif_flow(&dpif->dpif, &flows[n_flows++],
1590 &datapath_flow);
ac64794a
BP
1591 } else {
1592 /* Rare case: the flow does not include actions. Retrieve this
1593 * individual flow again to get the actions. */
70e5ed6f 1594 error = dpif_netlink_flow_get(dpif, &datapath_flow,
7fe98598 1595 &datapath_flow, &thread->nl_actions);
30053024
BP
1596 if (error == ENOENT) {
1597 VLOG_DBG("dumped flow disappeared on get");
ac64794a 1598 continue;
30053024 1599 } else if (error) {
10a89ef0
BP
1600 VLOG_WARN("error fetching dumped flow: %s",
1601 ovs_strerror(error));
7424fc44 1602 atomic_store_relaxed(&dump->status, error);
ac64794a 1603 break;
30053024 1604 }
30053024 1605
ac64794a
BP
1606 /* Save this flow. Then exit, because we only have one buffer to
1607 * handle this case. */
7af12bd7
JS
1608 dpif_netlink_flow_to_dpif_flow(&dpif->dpif, &flows[n_flows++],
1609 &datapath_flow);
ac64794a
BP
1610 break;
1611 }
feebdea2 1612 }
ac64794a 1613 return n_flows;
96fba48f
BP
1614}
1615
eabe7c68 1616static void
93451a0a
AS
1617dpif_netlink_encode_execute(int dp_ifindex, const struct dpif_execute *d_exec,
1618 struct ofpbuf *buf)
96fba48f 1619{
89625d1e 1620 struct ovs_header *k_exec;
758c456d 1621 size_t key_ofs;
f7cd0081 1622
eabe7c68 1623 ofpbuf_prealloc_tailroom(buf, (64
cf62fa4c 1624 + dp_packet_size(d_exec->packet)
758c456d 1625 + ODP_KEY_METADATA_SIZE
eabe7c68 1626 + d_exec->actions_len));
f7cd0081 1627
df2c07f4 1628 nl_msg_put_genlmsghdr(buf, 0, ovs_packet_family, NLM_F_REQUEST,
69685a88 1629 OVS_PACKET_CMD_EXECUTE, OVS_PACKET_VERSION);
f7cd0081 1630
89625d1e
BP
1631 k_exec = ofpbuf_put_uninit(buf, sizeof *k_exec);
1632 k_exec->dp_ifindex = dp_ifindex;
f7cd0081 1633
89625d1e 1634 nl_msg_put_unspec(buf, OVS_PACKET_ATTR_PACKET,
cf62fa4c
PS
1635 dp_packet_data(d_exec->packet),
1636 dp_packet_size(d_exec->packet));
758c456d
JR
1637
1638 key_ofs = nl_msg_start_nested(buf, OVS_PACKET_ATTR_KEY);
beb75a40 1639 odp_key_from_dp_packet(buf, d_exec->packet);
758c456d
JR
1640 nl_msg_end_nested(buf, key_ofs);
1641
89625d1e
BP
1642 nl_msg_put_unspec(buf, OVS_PACKET_ATTR_ACTIONS,
1643 d_exec->actions, d_exec->actions_len);
43f9ac0a 1644 if (d_exec->probe) {
2e460098 1645 nl_msg_put_flag(buf, OVS_PACKET_ATTR_PROBE);
43f9ac0a 1646 }
27130224
AZ
1647 if (d_exec->mtu) {
1648 nl_msg_put_u16(buf, OVS_PACKET_ATTR_MRU, d_exec->mtu);
1649 }
6bc60024
BP
1650}
1651
0f3358ea
BP
1652/* Executes, against 'dpif', up to the first 'n_ops' operations in 'ops'.
1653 * Returns the number actually executed (at least 1, if 'n_ops' is
1654 * positive). */
1655static size_t
93451a0a
AS
1656dpif_netlink_operate__(struct dpif_netlink *dpif,
1657 struct dpif_op **ops, size_t n_ops)
6bc60024 1658{
0f3358ea
BP
1659 enum { MAX_OPS = 50 };
1660
eabe7c68
BP
1661 struct op_auxdata {
1662 struct nl_transaction txn;
72d32ac0 1663
eabe7c68
BP
1664 struct ofpbuf request;
1665 uint64_t request_stub[1024 / 8];
72d32ac0
BP
1666
1667 struct ofpbuf reply;
1668 uint64_t reply_stub[1024 / 8];
eabe7c68
BP
1669 } auxes[MAX_OPS];
1670
1671 struct nl_transaction *txnsp[MAX_OPS];
6bc60024
BP
1672 size_t i;
1673
0f3358ea 1674 n_ops = MIN(n_ops, MAX_OPS);
6bc60024 1675 for (i = 0; i < n_ops; i++) {
eabe7c68 1676 struct op_auxdata *aux = &auxes[i];
c2b565b5 1677 struct dpif_op *op = ops[i];
b99d3cee
BP
1678 struct dpif_flow_put *put;
1679 struct dpif_flow_del *del;
6fe09f8c 1680 struct dpif_flow_get *get;
93451a0a 1681 struct dpif_netlink_flow flow;
eabe7c68
BP
1682
1683 ofpbuf_use_stub(&aux->request,
1684 aux->request_stub, sizeof aux->request_stub);
1685 aux->txn.request = &aux->request;
b99d3cee 1686
72d32ac0
BP
1687 ofpbuf_use_stub(&aux->reply, aux->reply_stub, sizeof aux->reply_stub);
1688 aux->txn.reply = NULL;
1689
b99d3cee
BP
1690 switch (op->type) {
1691 case DPIF_OP_FLOW_PUT:
1692 put = &op->u.flow_put;
93451a0a 1693 dpif_netlink_init_flow_put(dpif, put, &flow);
6bc60024 1694 if (put->stats) {
eabe7c68 1695 flow.nlmsg_flags |= NLM_F_ECHO;
72d32ac0 1696 aux->txn.reply = &aux->reply;
6bc60024 1697 }
93451a0a 1698 dpif_netlink_flow_to_ofpbuf(&flow, &aux->request);
b99d3cee
BP
1699 break;
1700
1701 case DPIF_OP_FLOW_DEL:
1702 del = &op->u.flow_del;
93451a0a 1703 dpif_netlink_init_flow_del(dpif, del, &flow);
b99d3cee 1704 if (del->stats) {
eabe7c68 1705 flow.nlmsg_flags |= NLM_F_ECHO;
72d32ac0 1706 aux->txn.reply = &aux->reply;
b99d3cee 1707 }
93451a0a 1708 dpif_netlink_flow_to_ofpbuf(&flow, &aux->request);
b99d3cee 1709 break;
6bc60024 1710
b99d3cee 1711 case DPIF_OP_EXECUTE:
0f3358ea
BP
1712 /* Can't execute a packet that won't fit in a Netlink attribute. */
1713 if (OVS_UNLIKELY(nl_attr_oversized(
cf62fa4c 1714 dp_packet_size(op->u.execute.packet)))) {
0f3358ea
BP
1715 /* Report an error immediately if this is the first operation.
1716 * Otherwise the easiest thing to do is to postpone to the next
1717 * call (when this will be the first operation). */
1718 if (i == 0) {
1719 VLOG_ERR_RL(&error_rl,
1720 "dropping oversized %"PRIu32"-byte packet",
cf62fa4c 1721 dp_packet_size(op->u.execute.packet));
0f3358ea
BP
1722 op->error = ENOBUFS;
1723 return 1;
1724 }
1725 n_ops = i;
1726 } else {
1727 dpif_netlink_encode_execute(dpif->dp_ifindex, &op->u.execute,
1728 &aux->request);
1729 }
b99d3cee
BP
1730 break;
1731
6fe09f8c
JS
1732 case DPIF_OP_FLOW_GET:
1733 get = &op->u.flow_get;
70e5ed6f 1734 dpif_netlink_init_flow_get(dpif, get, &flow);
6fe09f8c 1735 aux->txn.reply = get->buffer;
93451a0a 1736 dpif_netlink_flow_to_ofpbuf(&flow, &aux->request);
6fe09f8c
JS
1737 break;
1738
b99d3cee 1739 default:
428b2edd 1740 OVS_NOT_REACHED();
6bc60024
BP
1741 }
1742 }
1743
6bc60024 1744 for (i = 0; i < n_ops; i++) {
eabe7c68 1745 txnsp[i] = &auxes[i].txn;
6bc60024 1746 }
a88b4e04 1747 nl_transact_multiple(NETLINK_GENERIC, txnsp, n_ops);
6bc60024 1748
6bc60024 1749 for (i = 0; i < n_ops; i++) {
72d32ac0 1750 struct op_auxdata *aux = &auxes[i];
eabe7c68 1751 struct nl_transaction *txn = &auxes[i].txn;
c2b565b5 1752 struct dpif_op *op = ops[i];
b99d3cee
BP
1753 struct dpif_flow_put *put;
1754 struct dpif_flow_del *del;
6fe09f8c 1755 struct dpif_flow_get *get;
6bc60024 1756
b99d3cee 1757 op->error = txn->error;
6bc60024 1758
b99d3cee
BP
1759 switch (op->type) {
1760 case DPIF_OP_FLOW_PUT:
1761 put = &op->u.flow_put;
cfceb2b5 1762 if (put->stats) {
b99d3cee 1763 if (!op->error) {
93451a0a 1764 struct dpif_netlink_flow reply;
cfceb2b5 1765
93451a0a
AS
1766 op->error = dpif_netlink_flow_from_ofpbuf(&reply,
1767 txn->reply);
cfceb2b5 1768 if (!op->error) {
93451a0a 1769 dpif_netlink_flow_get_stats(&reply, put->stats);
cfceb2b5
BP
1770 }
1771 }
6bc60024 1772 }
b99d3cee
BP
1773 break;
1774
1775 case DPIF_OP_FLOW_DEL:
1776 del = &op->u.flow_del;
cfceb2b5 1777 if (del->stats) {
b99d3cee 1778 if (!op->error) {
93451a0a 1779 struct dpif_netlink_flow reply;
cfceb2b5 1780
93451a0a
AS
1781 op->error = dpif_netlink_flow_from_ofpbuf(&reply,
1782 txn->reply);
cfceb2b5 1783 if (!op->error) {
93451a0a 1784 dpif_netlink_flow_get_stats(&reply, del->stats);
cfceb2b5
BP
1785 }
1786 }
b99d3cee
BP
1787 }
1788 break;
1789
1790 case DPIF_OP_EXECUTE:
1791 break;
1792
6fe09f8c
JS
1793 case DPIF_OP_FLOW_GET:
1794 get = &op->u.flow_get;
1795 if (!op->error) {
93451a0a 1796 struct dpif_netlink_flow reply;
6fe09f8c 1797
93451a0a 1798 op->error = dpif_netlink_flow_from_ofpbuf(&reply, txn->reply);
6fe09f8c 1799 if (!op->error) {
7af12bd7
JS
1800 dpif_netlink_flow_to_dpif_flow(&dpif->dpif, get->flow,
1801 &reply);
6fe09f8c
JS
1802 }
1803 }
1804 break;
1805
b99d3cee 1806 default:
428b2edd 1807 OVS_NOT_REACHED();
6bc60024
BP
1808 }
1809
72d32ac0
BP
1810 ofpbuf_uninit(&aux->request);
1811 ofpbuf_uninit(&aux->reply);
6bc60024 1812 }
0f3358ea
BP
1813
1814 return n_ops;
eabe7c68
BP
1815}
1816
1817static void
93451a0a 1818dpif_netlink_operate(struct dpif *dpif_, struct dpif_op **ops, size_t n_ops)
eabe7c68 1819{
93451a0a 1820 struct dpif_netlink *dpif = dpif_netlink_cast(dpif_);
9b00386b 1821
eabe7c68 1822 while (n_ops > 0) {
0f3358ea 1823 size_t chunk = dpif_netlink_operate__(dpif, ops, n_ops);
eabe7c68
BP
1824 ops += chunk;
1825 n_ops -= chunk;
1826 }
6bc60024
BP
1827}
1828
09cac43f
NR
1829#if _WIN32
1830static void
1831dpif_netlink_handler_uninit(struct dpif_handler *handler)
1832{
1833 vport_delete_sock_pool(handler);
1834}
1835
1836static int
1837dpif_netlink_handler_init(struct dpif_handler *handler)
1838{
1839 return vport_create_sock_pool(handler);
1840}
1841#else
1842
1843static int
1844dpif_netlink_handler_init(struct dpif_handler *handler)
1845{
1846 handler->epoll_fd = epoll_create(10);
1847 return handler->epoll_fd < 0 ? errno : 0;
1848}
1849
1850static void
1851dpif_netlink_handler_uninit(struct dpif_handler *handler)
1852{
1853 close(handler->epoll_fd);
1854}
1855#endif
1856
1579cf67
AW
1857/* Synchronizes 'channels' in 'dpif->handlers' with the set of vports
1858 * currently in 'dpif' in the kernel, by adding a new set of channels for
1859 * any kernel vport that lacks one and deleting any channels that have no
1860 * backing kernel vports. */
96fba48f 1861static int
93451a0a 1862dpif_netlink_refresh_channels(struct dpif_netlink *dpif, uint32_t n_handlers)
b90de034 1863 OVS_REQ_WRLOCK(dpif->upcall_lock)
96fba48f 1864{
8381a3d3 1865 unsigned long int *keep_channels;
93451a0a 1866 struct dpif_netlink_vport vport;
8381a3d3
BP
1867 size_t keep_channels_nbits;
1868 struct nl_dump dump;
d57695d7
JS
1869 uint64_t reply_stub[NL_DUMP_BUFSIZE / 8];
1870 struct ofpbuf buf;
8381a3d3
BP
1871 int retval = 0;
1872 size_t i;
982b8810 1873
09cac43f
NR
1874 ovs_assert(!WINDOWS || n_handlers <= 1);
1875 ovs_assert(!WINDOWS || dpif->n_handlers <= 1);
1876
1579cf67
AW
1877 if (dpif->n_handlers != n_handlers) {
1878 destroy_all_channels(dpif);
1879 dpif->handlers = xzalloc(n_handlers * sizeof *dpif->handlers);
1880 for (i = 0; i < n_handlers; i++) {
09cac43f 1881 int error;
1579cf67
AW
1882 struct dpif_handler *handler = &dpif->handlers[i];
1883
09cac43f
NR
1884 error = dpif_netlink_handler_init(handler);
1885 if (error) {
1579cf67
AW
1886 size_t j;
1887
1888 for (j = 0; j < i; j++) {
aa5c0216 1889 struct dpif_handler *tmp = &dpif->handlers[j];
09cac43f 1890 dpif_netlink_handler_uninit(tmp);
1579cf67
AW
1891 }
1892 free(dpif->handlers);
1893 dpif->handlers = NULL;
1894
09cac43f 1895 return error;
1579cf67 1896 }
8381a3d3 1897 }
1579cf67
AW
1898 dpif->n_handlers = n_handlers;
1899 }
1900
1901 for (i = 0; i < n_handlers; i++) {
1902 struct dpif_handler *handler = &dpif->handlers[i];
1903
1904 handler->event_offset = handler->n_events = 0;
17411ecf 1905 }
b063d9f0 1906
8381a3d3
BP
1907 keep_channels_nbits = dpif->uc_array_size;
1908 keep_channels = bitmap_allocate(keep_channels_nbits);
982b8810 1909
d57695d7 1910 ofpbuf_use_stub(&buf, reply_stub, sizeof reply_stub);
93451a0a
AS
1911 dpif_netlink_port_dump_start__(dpif, &dump);
1912 while (!dpif_netlink_port_dump_next__(dpif, &dump, &vport, &buf)) {
8381a3d3 1913 uint32_t port_no = odp_to_u32(vport.port_no);
1579cf67 1914 uint32_t *upcall_pids = NULL;
8381a3d3 1915 int error;
50f80534 1916
1579cf67
AW
1917 if (port_no >= dpif->uc_array_size
1918 || !vport_get_pids(dpif, port_no, &upcall_pids)) {
09cac43f 1919 struct nl_sock **socksp = vport_create_socksp(dpif, &error);
1579cf67
AW
1920
1921 if (!socksp) {
1922 goto error;
1923 }
1924
1925 error = vport_add_channels(dpif, vport.port_no, socksp);
b063d9f0 1926 if (error) {
1579cf67 1927 VLOG_INFO("%s: could not add channels for port %s",
9b00386b 1928 dpif_name(&dpif->dpif), vport.name);
09cac43f 1929 vport_del_socksp(dpif, socksp);
8381a3d3
BP
1930 retval = error;
1931 goto error;
982b8810 1932 }
1579cf67
AW
1933 upcall_pids = vport_socksp_to_pids(socksp, dpif->n_handlers);
1934 free(socksp);
8381a3d3 1935 }
50f80534 1936
8381a3d3 1937 /* Configure the vport to deliver misses to 'sock'. */
1579cf67
AW
1938 if (vport.upcall_pids[0] == 0
1939 || vport.n_upcall_pids != dpif->n_handlers
1940 || memcmp(upcall_pids, vport.upcall_pids, n_handlers * sizeof
1941 *upcall_pids)) {
93451a0a 1942 struct dpif_netlink_vport vport_request;
989fd548 1943
93451a0a 1944 dpif_netlink_vport_init(&vport_request);
989fd548
JP
1945 vport_request.cmd = OVS_VPORT_CMD_SET;
1946 vport_request.dp_ifindex = dpif->dp_ifindex;
8381a3d3 1947 vport_request.port_no = vport.port_no;
1579cf67
AW
1948 vport_request.n_upcall_pids = dpif->n_handlers;
1949 vport_request.upcall_pids = upcall_pids;
93451a0a 1950 error = dpif_netlink_vport_transact(&vport_request, NULL, NULL);
1579cf67 1951 if (error) {
989fd548
JP
1952 VLOG_WARN_RL(&error_rl,
1953 "%s: failed to set upcall pid on port: %s",
10a89ef0 1954 dpif_name(&dpif->dpif), ovs_strerror(error));
989fd548 1955
8381a3d3
BP
1956 if (error != ENODEV && error != ENOENT) {
1957 retval = error;
989fd548 1958 } else {
8381a3d3
BP
1959 /* The vport isn't really there, even though the dump says
1960 * it is. Probably we just hit a race after a port
1961 * disappeared. */
989fd548 1962 }
8381a3d3 1963 goto error;
50f80534 1964 }
8381a3d3 1965 }
14b4d2f9 1966
8381a3d3
BP
1967 if (port_no < keep_channels_nbits) {
1968 bitmap_set1(keep_channels, port_no);
1969 }
1579cf67 1970 free(upcall_pids);
8381a3d3
BP
1971 continue;
1972
1973 error:
1579cf67
AW
1974 free(upcall_pids);
1975 vport_del_channels(dpif, vport.port_no);
982b8810 1976 }
8381a3d3 1977 nl_dump_done(&dump);
d57695d7 1978 ofpbuf_uninit(&buf);
b063d9f0 1979
8381a3d3
BP
1980 /* Discard any saved channels that we didn't reuse. */
1981 for (i = 0; i < keep_channels_nbits; i++) {
1982 if (!bitmap_is_set(keep_channels, i)) {
1579cf67 1983 vport_del_channels(dpif, u32_to_odp(i));
8381a3d3
BP
1984 }
1985 }
1986 free(keep_channels);
1987
1988 return retval;
1989}
1990
1991static int
93451a0a 1992dpif_netlink_recv_set__(struct dpif_netlink *dpif, bool enable)
b90de034 1993 OVS_REQ_WRLOCK(dpif->upcall_lock)
8381a3d3 1994{
1579cf67 1995 if ((dpif->handlers != NULL) == enable) {
8381a3d3
BP
1996 return 0;
1997 } else if (!enable) {
1579cf67 1998 destroy_all_channels(dpif);
8381a3d3
BP
1999 return 0;
2000 } else {
93451a0a 2001 return dpif_netlink_refresh_channels(dpif, 1);
8381a3d3 2002 }
96fba48f
BP
2003}
2004
9fafa796 2005static int
93451a0a 2006dpif_netlink_recv_set(struct dpif *dpif_, bool enable)
9fafa796 2007{
93451a0a 2008 struct dpif_netlink *dpif = dpif_netlink_cast(dpif_);
9fafa796
BP
2009 int error;
2010
1579cf67 2011 fat_rwlock_wrlock(&dpif->upcall_lock);
93451a0a 2012 error = dpif_netlink_recv_set__(dpif, enable);
1579cf67 2013 fat_rwlock_unlock(&dpif->upcall_lock);
9fafa796
BP
2014
2015 return error;
2016}
2017
1954e6bb 2018static int
93451a0a 2019dpif_netlink_handlers_set(struct dpif *dpif_, uint32_t n_handlers)
1954e6bb 2020{
93451a0a 2021 struct dpif_netlink *dpif = dpif_netlink_cast(dpif_);
1579cf67
AW
2022 int error = 0;
2023
09cac43f
NR
2024#ifdef _WIN32
2025 /* Multiple upcall handlers will be supported once kernel datapath supports
2026 * it. */
2027 if (n_handlers > 1) {
2028 return error;
2029 }
2030#endif
2031
1579cf67
AW
2032 fat_rwlock_wrlock(&dpif->upcall_lock);
2033 if (dpif->handlers) {
93451a0a 2034 error = dpif_netlink_refresh_channels(dpif, n_handlers);
1579cf67
AW
2035 }
2036 fat_rwlock_unlock(&dpif->upcall_lock);
2037
2038 return error;
1954e6bb
AW
2039}
2040
aae51f53 2041static int
93451a0a 2042dpif_netlink_queue_to_priority(const struct dpif *dpif OVS_UNUSED,
aae51f53
BP
2043 uint32_t queue_id, uint32_t *priority)
2044{
2045 if (queue_id < 0xf000) {
17ee3c1f 2046 *priority = TC_H_MAKE(1 << 16, queue_id + 1);
aae51f53
BP
2047 return 0;
2048 } else {
2049 return EINVAL;
2050 }
2051}
2052
96fba48f 2053static int
7af12bd7
JS
2054parse_odp_packet(const struct dpif_netlink *dpif, struct ofpbuf *buf,
2055 struct dpif_upcall *upcall, int *dp_ifindex)
856081f6 2056{
df2c07f4 2057 static const struct nl_policy ovs_packet_policy[] = {
856081f6 2058 /* Always present. */
df2c07f4 2059 [OVS_PACKET_ATTR_PACKET] = { .type = NL_A_UNSPEC,
856081f6 2060 .min_len = ETH_HEADER_LEN },
df2c07f4 2061 [OVS_PACKET_ATTR_KEY] = { .type = NL_A_NESTED },
856081f6 2062
df2c07f4 2063 /* OVS_PACKET_CMD_ACTION only. */
e995e3df 2064 [OVS_PACKET_ATTR_USERDATA] = { .type = NL_A_UNSPEC, .optional = true },
8b7ea2d4 2065 [OVS_PACKET_ATTR_EGRESS_TUN_KEY] = { .type = NL_A_NESTED, .optional = true },
7321bda3 2066 [OVS_PACKET_ATTR_ACTIONS] = { .type = NL_A_NESTED, .optional = true },
27130224 2067 [OVS_PACKET_ATTR_MRU] = { .type = NL_A_U16, .optional = true }
856081f6
BP
2068 };
2069
0a2869d5
BP
2070 struct ofpbuf b = ofpbuf_const_initializer(buf->data, buf->size);
2071 struct nlmsghdr *nlmsg = ofpbuf_try_pull(&b, sizeof *nlmsg);
2072 struct genlmsghdr *genl = ofpbuf_try_pull(&b, sizeof *genl);
2073 struct ovs_header *ovs_header = ofpbuf_try_pull(&b, sizeof *ovs_header);
982b8810 2074
0a2869d5 2075 struct nlattr *a[ARRAY_SIZE(ovs_packet_policy)];
df2c07f4
JP
2076 if (!nlmsg || !genl || !ovs_header
2077 || nlmsg->nlmsg_type != ovs_packet_family
2078 || !nl_policy_parse(&b, 0, ovs_packet_policy, a,
2079 ARRAY_SIZE(ovs_packet_policy))) {
856081f6
BP
2080 return EINVAL;
2081 }
2082
0a2869d5
BP
2083 int type = (genl->cmd == OVS_PACKET_CMD_MISS ? DPIF_UC_MISS
2084 : genl->cmd == OVS_PACKET_CMD_ACTION ? DPIF_UC_ACTION
2085 : -1);
aaff4b55
BP
2086 if (type < 0) {
2087 return EINVAL;
2088 }
82272ede 2089
877c9270 2090 /* (Re)set ALL fields of '*upcall' on successful return. */
aaff4b55 2091 upcall->type = type;
ebc56baa
BP
2092 upcall->key = CONST_CAST(struct nlattr *,
2093 nl_attr_get(a[OVS_PACKET_ATTR_KEY]));
df2c07f4 2094 upcall->key_len = nl_attr_get_size(a[OVS_PACKET_ATTR_KEY]);
7af12bd7 2095 dpif_flow_hash(&dpif->dpif, upcall->key, upcall->key_len, &upcall->ufid);
e995e3df 2096 upcall->userdata = a[OVS_PACKET_ATTR_USERDATA];
8b7ea2d4 2097 upcall->out_tun_key = a[OVS_PACKET_ATTR_EGRESS_TUN_KEY];
7321bda3 2098 upcall->actions = a[OVS_PACKET_ATTR_ACTIONS];
27130224 2099 upcall->mru = a[OVS_PACKET_ATTR_MRU];
da546e07
JR
2100
2101 /* Allow overwriting the netlink attribute header without reallocating. */
cf62fa4c 2102 dp_packet_use_stub(&upcall->packet,
da546e07
JR
2103 CONST_CAST(struct nlattr *,
2104 nl_attr_get(a[OVS_PACKET_ATTR_PACKET])) - 1,
2105 nl_attr_get_size(a[OVS_PACKET_ATTR_PACKET]) +
2106 sizeof(struct nlattr));
cf62fa4c
PS
2107 dp_packet_set_data(&upcall->packet,
2108 (char *)dp_packet_data(&upcall->packet) + sizeof(struct nlattr));
2109 dp_packet_set_size(&upcall->packet, nl_attr_get_size(a[OVS_PACKET_ATTR_PACKET]));
da546e07 2110
2482b0b0
JS
2111 if (nl_attr_find__(upcall->key, upcall->key_len, OVS_KEY_ATTR_ETHERNET)) {
2112 /* Ethernet frame */
2113 upcall->packet.packet_type = htonl(PT_ETH);
2114 } else {
2115 /* Non-Ethernet packet. Get the Ethertype from the NL attributes */
2116 ovs_be16 ethertype = 0;
2117 const struct nlattr *et_nla = nl_attr_find__(upcall->key,
2118 upcall->key_len,
2119 OVS_KEY_ATTR_ETHERTYPE);
2120 if (et_nla) {
2121 ethertype = nl_attr_get_be16(et_nla);
2122 }
2123 upcall->packet.packet_type = PACKET_TYPE_BE(OFPHTN_ETHERTYPE,
2124 ntohs(ethertype));
2125 dp_packet_set_l3(&upcall->packet, dp_packet_data(&upcall->packet));
2126 }
2127
df2c07f4 2128 *dp_ifindex = ovs_header->dp_ifindex;
982b8810 2129
856081f6
BP
2130 return 0;
2131}
2132
09cac43f
NR
2133#ifdef _WIN32
2134#define PACKET_RECV_BATCH_SIZE 50
2135static int
2136dpif_netlink_recv_windows(struct dpif_netlink *dpif, uint32_t handler_id,
2137 struct dpif_upcall *upcall, struct ofpbuf *buf)
2138 OVS_REQ_RDLOCK(dpif->upcall_lock)
2139{
2140 struct dpif_handler *handler;
2141 int read_tries = 0;
2142 struct dpif_windows_vport_sock *sock_pool;
2143 uint32_t i;
2144
2145 if (!dpif->handlers) {
2146 return EAGAIN;
2147 }
2148
2149 /* Only one handler is supported currently. */
2150 if (handler_id >= 1) {
2151 return EAGAIN;
2152 }
2153
2154 if (handler_id >= dpif->n_handlers) {
2155 return EAGAIN;
2156 }
2157
2158 handler = &dpif->handlers[handler_id];
2159 sock_pool = handler->vport_sock_pool;
2160
2161 for (i = 0; i < VPORT_SOCK_POOL_SIZE; i++) {
2162 for (;;) {
2163 int dp_ifindex;
2164 int error;
2165
2166 if (++read_tries > PACKET_RECV_BATCH_SIZE) {
2167 return EAGAIN;
2168 }
2169
2170 error = nl_sock_recv(sock_pool[i].nl_sock, buf, false);
2171 if (error == ENOBUFS) {
2172 /* ENOBUFS typically means that we've received so many
2173 * packets that the buffer overflowed. Try again
2174 * immediately because there's almost certainly a packet
2175 * waiting for us. */
2176 /* XXX: report_loss(dpif, ch, idx, handler_id); */
2177 continue;
2178 }
2179
2180 /* XXX: ch->last_poll = time_msec(); */
2181 if (error) {
2182 if (error == EAGAIN) {
2183 break;
2184 }
2185 return error;
2186 }
2187
27edb4aa 2188 error = parse_odp_packet(dpif, buf, upcall, &dp_ifindex);
09cac43f
NR
2189 if (!error && dp_ifindex == dpif->dp_ifindex) {
2190 return 0;
2191 } else if (error) {
2192 return error;
2193 }
2194 }
2195 }
2196
2197 return EAGAIN;
2198}
2199#else
856081f6 2200static int
93451a0a
AS
2201dpif_netlink_recv__(struct dpif_netlink *dpif, uint32_t handler_id,
2202 struct dpif_upcall *upcall, struct ofpbuf *buf)
b90de034 2203 OVS_REQ_RDLOCK(dpif->upcall_lock)
96fba48f 2204{
1579cf67 2205 struct dpif_handler *handler;
17411ecf 2206 int read_tries = 0;
96fba48f 2207
1579cf67
AW
2208 if (!dpif->handlers || handler_id >= dpif->n_handlers) {
2209 return EAGAIN;
982b8810
BP
2210 }
2211
1579cf67
AW
2212 handler = &dpif->handlers[handler_id];
2213 if (handler->event_offset >= handler->n_events) {
8522ba09 2214 int retval;
989fd548 2215
1579cf67 2216 handler->event_offset = handler->n_events = 0;
f6d1465c 2217
8522ba09 2218 do {
1579cf67 2219 retval = epoll_wait(handler->epoll_fd, handler->epoll_events,
989fd548 2220 dpif->uc_array_size, 0);
8522ba09 2221 } while (retval < 0 && errno == EINTR);
09cac43f 2222
8522ba09
BP
2223 if (retval < 0) {
2224 static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
10a89ef0 2225 VLOG_WARN_RL(&rl, "epoll_wait failed (%s)", ovs_strerror(errno));
989fd548 2226 } else if (retval > 0) {
1579cf67 2227 handler->n_events = retval;
8522ba09 2228 }
8522ba09
BP
2229 }
2230
1579cf67
AW
2231 while (handler->event_offset < handler->n_events) {
2232 int idx = handler->epoll_events[handler->event_offset].data.u32;
2233 struct dpif_channel *ch = &dpif->handlers[handler_id].channels[idx];
8522ba09 2234
1579cf67 2235 handler->event_offset++;
17411ecf 2236
f6d1465c 2237 for (;;) {
8522ba09 2238 int dp_ifindex;
f6d1465c 2239 int error;
17411ecf 2240
f6d1465c
BP
2241 if (++read_tries > 50) {
2242 return EAGAIN;
2243 }
17411ecf 2244
fe3d61b3 2245 error = nl_sock_recv(ch->sock, buf, false);
14b4d2f9
BP
2246 if (error == ENOBUFS) {
2247 /* ENOBUFS typically means that we've received so many
2248 * packets that the buffer overflowed. Try again
2249 * immediately because there's almost certainly a packet
2250 * waiting for us. */
9b00386b 2251 report_loss(dpif, ch, idx, handler_id);
14b4d2f9
BP
2252 continue;
2253 }
2254
2255 ch->last_poll = time_msec();
72d32ac0 2256 if (error) {
72d32ac0
BP
2257 if (error == EAGAIN) {
2258 break;
2259 }
f6d1465c
BP
2260 return error;
2261 }
17411ecf 2262
7af12bd7 2263 error = parse_odp_packet(dpif, buf, upcall, &dp_ifindex);
a12b3ead 2264 if (!error && dp_ifindex == dpif->dp_ifindex) {
f6d1465c 2265 return 0;
989fd548 2266 } else if (error) {
f6d1465c 2267 return error;
17411ecf 2268 }
982b8810 2269 }
50f80534 2270 }
982b8810
BP
2271
2272 return EAGAIN;
96fba48f 2273}
09cac43f 2274#endif
96fba48f 2275
9fafa796 2276static int
93451a0a
AS
2277dpif_netlink_recv(struct dpif *dpif_, uint32_t handler_id,
2278 struct dpif_upcall *upcall, struct ofpbuf *buf)
9fafa796 2279{
93451a0a 2280 struct dpif_netlink *dpif = dpif_netlink_cast(dpif_);
9fafa796
BP
2281 int error;
2282
1579cf67 2283 fat_rwlock_rdlock(&dpif->upcall_lock);
09cac43f
NR
2284#ifdef _WIN32
2285 error = dpif_netlink_recv_windows(dpif, handler_id, upcall, buf);
2286#else
93451a0a 2287 error = dpif_netlink_recv__(dpif, handler_id, upcall, buf);
09cac43f 2288#endif
1579cf67 2289 fat_rwlock_unlock(&dpif->upcall_lock);
9fafa796
BP
2290
2291 return error;
2292}
2293
96fba48f 2294static void
93451a0a 2295dpif_netlink_recv_wait__(struct dpif_netlink *dpif, uint32_t handler_id)
b90de034 2296 OVS_REQ_RDLOCK(dpif->upcall_lock)
96fba48f 2297{
93451a0a 2298#ifdef _WIN32
09cac43f
NR
2299 uint32_t i;
2300 struct dpif_windows_vport_sock *sock_pool =
2301 dpif->handlers[handler_id].vport_sock_pool;
2302
2303 /* Only one handler is supported currently. */
2304 if (handler_id >= 1) {
2305 return;
2306 }
2307
2308 for (i = 0; i < VPORT_SOCK_POOL_SIZE; i++) {
2309 nl_sock_wait(sock_pool[i].nl_sock, POLLIN);
2310 }
93451a0a 2311#else
1579cf67
AW
2312 if (dpif->handlers && handler_id < dpif->n_handlers) {
2313 struct dpif_handler *handler = &dpif->handlers[handler_id];
2314
2315 poll_fd_wait(handler->epoll_fd, POLLIN);
17411ecf 2316 }
93451a0a 2317#endif
96fba48f
BP
2318}
2319
1ba530f4 2320static void
93451a0a 2321dpif_netlink_recv_wait(struct dpif *dpif_, uint32_t handler_id)
1ba530f4 2322{
93451a0a 2323 struct dpif_netlink *dpif = dpif_netlink_cast(dpif_);
17411ecf 2324
b90de034 2325 fat_rwlock_rdlock(&dpif->upcall_lock);
93451a0a 2326 dpif_netlink_recv_wait__(dpif, handler_id);
b90de034
AW
2327 fat_rwlock_unlock(&dpif->upcall_lock);
2328}
2329
2330static void
93451a0a 2331dpif_netlink_recv_purge__(struct dpif_netlink *dpif)
b90de034
AW
2332 OVS_REQ_WRLOCK(dpif->upcall_lock)
2333{
1579cf67
AW
2334 if (dpif->handlers) {
2335 size_t i, j;
2336
2337 for (i = 0; i < dpif->uc_array_size; i++ ) {
2338 if (!dpif->handlers[0].channels[i].sock) {
2339 continue;
2340 }
1ba530f4 2341
1579cf67
AW
2342 for (j = 0; j < dpif->n_handlers; j++) {
2343 nl_sock_drain(dpif->handlers[j].channels[i].sock);
9fafa796 2344 }
989fd548 2345 }
1ba530f4 2346 }
b90de034
AW
2347}
2348
2349static void
93451a0a 2350dpif_netlink_recv_purge(struct dpif *dpif_)
b90de034 2351{
93451a0a 2352 struct dpif_netlink *dpif = dpif_netlink_cast(dpif_);
b90de034
AW
2353
2354 fat_rwlock_wrlock(&dpif->upcall_lock);
93451a0a 2355 dpif_netlink_recv_purge__(dpif);
1579cf67 2356 fat_rwlock_unlock(&dpif->upcall_lock);
1ba530f4
BP
2357}
2358
b5cbbcf6
AZ
2359static char *
2360dpif_netlink_get_datapath_version(void)
2361{
2362 char *version_str = NULL;
2363
2364#ifdef __linux__
2365
2366#define MAX_VERSION_STR_SIZE 80
2367#define LINUX_DATAPATH_VERSION_FILE "/sys/module/openvswitch/version"
2368 FILE *f;
2369
2370 f = fopen(LINUX_DATAPATH_VERSION_FILE, "r");
2371 if (f) {
2372 char *newline;
2373 char version[MAX_VERSION_STR_SIZE];
2374
2375 if (fgets(version, MAX_VERSION_STR_SIZE, f)) {
2376 newline = strchr(version, '\n');
2377 if (newline) {
2378 *newline = '\0';
2379 }
2380 version_str = xstrdup(version);
2381 }
2382 fclose(f);
2383 }
2384#endif
2385
2386 return version_str;
2387}
2388
c11c9f4a
DDP
2389struct dpif_netlink_ct_dump_state {
2390 struct ct_dpif_dump_state up;
2391 struct nl_ct_dump_state *nl_ct_dump;
2392};
2393
2394static int
2395dpif_netlink_ct_dump_start(struct dpif *dpif OVS_UNUSED,
2396 struct ct_dpif_dump_state **dump_,
2397 const uint16_t *zone)
2398{
2399 struct dpif_netlink_ct_dump_state *dump;
2400 int err;
2401
2402 dump = xzalloc(sizeof *dump);
2403 err = nl_ct_dump_start(&dump->nl_ct_dump, zone);
2404 if (err) {
2405 free(dump);
2406 return err;
2407 }
2408
2409 *dump_ = &dump->up;
2410
2411 return 0;
2412}
2413
2414static int
2415dpif_netlink_ct_dump_next(struct dpif *dpif OVS_UNUSED,
2416 struct ct_dpif_dump_state *dump_,
2417 struct ct_dpif_entry *entry)
2418{
2419 struct dpif_netlink_ct_dump_state *dump;
2420
2421 INIT_CONTAINER(dump, dump_, up);
2422
2423 return nl_ct_dump_next(dump->nl_ct_dump, entry);
2424}
2425
2426static int
2427dpif_netlink_ct_dump_done(struct dpif *dpif OVS_UNUSED,
2428 struct ct_dpif_dump_state *dump_)
2429{
2430 struct dpif_netlink_ct_dump_state *dump;
2431 int err;
2432
2433 INIT_CONTAINER(dump, dump_, up);
2434
2435 err = nl_ct_dump_done(dump->nl_ct_dump);
2436 free(dump);
2437 return err;
2438}
15eabc97
DDP
2439
2440static int
2441dpif_netlink_ct_flush(struct dpif *dpif OVS_UNUSED, const uint16_t *zone)
2442{
2443 if (zone) {
2444 return nl_ct_flush_zone(*zone);
2445 } else {
2446 return nl_ct_flush();
2447 }
2448}
c11c9f4a 2449
5dddf960
JR
2450\f
2451/* Meters */
2452static void
2453dpif_netlink_meter_get_features(const struct dpif * dpif OVS_UNUSED,
2454 struct ofputil_meter_features *features)
2455{
2456 features->max_meters = 0;
2457 features->band_types = 0;
2458 features->capabilities = 0;
2459 features->max_bands = 0;
2460 features->max_color = 0;
2461}
2462
2463static int
2464dpif_netlink_meter_set(struct dpif *dpif OVS_UNUSED,
2465 ofproto_meter_id *meter_id OVS_UNUSED,
2466 struct ofputil_meter_config *config OVS_UNUSED)
2467{
2468 return EFBIG; /* meter_id out of range */
2469}
2470
2471static int
2472dpif_netlink_meter_get(const struct dpif *dpif OVS_UNUSED,
2473 ofproto_meter_id meter_id OVS_UNUSED,
2474 struct ofputil_meter_stats *stats OVS_UNUSED,
2475 uint16_t n_bands OVS_UNUSED)
2476{
2477 return EFBIG; /* meter_id out of range */
2478}
2479
2480static int
2481dpif_netlink_meter_del(struct dpif *dpif OVS_UNUSED,
2482 ofproto_meter_id meter_id OVS_UNUSED,
2483 struct ofputil_meter_stats *stats OVS_UNUSED,
2484 uint16_t n_bands OVS_UNUSED)
2485{
2486 return EFBIG; /* meter_id out of range */
2487}
2488
2489\f
93451a0a 2490const struct dpif_class dpif_netlink_class = {
1a6f1e2a 2491 "system",
c8973eb6 2492 NULL, /* init */
93451a0a 2493 dpif_netlink_enumerate,
0aeaabc8 2494 NULL,
93451a0a
AS
2495 dpif_netlink_open,
2496 dpif_netlink_close,
2497 dpif_netlink_destroy,
2498 dpif_netlink_run,
e4516b20 2499 NULL, /* wait */
93451a0a
AS
2500 dpif_netlink_get_stats,
2501 dpif_netlink_port_add,
2502 dpif_netlink_port_del,
91364d18 2503 NULL, /* port_set_config */
93451a0a
AS
2504 dpif_netlink_port_query_by_number,
2505 dpif_netlink_port_query_by_name,
2506 dpif_netlink_port_get_pid,
2507 dpif_netlink_port_dump_start,
2508 dpif_netlink_port_dump_next,
2509 dpif_netlink_port_dump_done,
2510 dpif_netlink_port_poll,
2511 dpif_netlink_port_poll_wait,
2512 dpif_netlink_flow_flush,
2513 dpif_netlink_flow_dump_create,
2514 dpif_netlink_flow_dump_destroy,
2515 dpif_netlink_flow_dump_thread_create,
2516 dpif_netlink_flow_dump_thread_destroy,
2517 dpif_netlink_flow_dump_next,
2518 dpif_netlink_operate,
2519 dpif_netlink_recv_set,
2520 dpif_netlink_handlers_set,
d4f6865c 2521 NULL, /* set_config */
93451a0a
AS
2522 dpif_netlink_queue_to_priority,
2523 dpif_netlink_recv,
2524 dpif_netlink_recv_wait,
2525 dpif_netlink_recv_purge,
e4e74c3a 2526 NULL, /* register_dp_purge_cb */
6b31e073
RW
2527 NULL, /* register_upcall_cb */
2528 NULL, /* enable_upcall */
2529 NULL, /* disable_upcall */
b5cbbcf6 2530 dpif_netlink_get_datapath_version, /* get_datapath_version */
c11c9f4a
DDP
2531 dpif_netlink_ct_dump_start,
2532 dpif_netlink_ct_dump_next,
2533 dpif_netlink_ct_dump_done,
5dddf960
JR
2534 dpif_netlink_ct_flush,
2535 dpif_netlink_meter_get_features,
2536 dpif_netlink_meter_set,
2537 dpif_netlink_meter_get,
2538 dpif_netlink_meter_del,
96fba48f 2539};
93451a0a 2540
96fba48f 2541static int
93451a0a 2542dpif_netlink_init(void)
96fba48f 2543{
eb8ed438
BP
2544 static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER;
2545 static int error;
982b8810 2546
eb8ed438 2547 if (ovsthread_once_start(&once)) {
df2c07f4
JP
2548 error = nl_lookup_genl_family(OVS_DATAPATH_FAMILY,
2549 &ovs_datapath_family);
37a1300c 2550 if (error) {
cae7529c
CL
2551 VLOG_WARN("Generic Netlink family '%s' does not exist. "
2552 "The Open vSwitch kernel module is probably not loaded.",
2553 OVS_DATAPATH_FAMILY);
37a1300c 2554 }
f0fef760 2555 if (!error) {
df2c07f4 2556 error = nl_lookup_genl_family(OVS_VPORT_FAMILY, &ovs_vport_family);
f0fef760 2557 }
37a1300c 2558 if (!error) {
df2c07f4 2559 error = nl_lookup_genl_family(OVS_FLOW_FAMILY, &ovs_flow_family);
37a1300c 2560 }
aaff4b55 2561 if (!error) {
df2c07f4
JP
2562 error = nl_lookup_genl_family(OVS_PACKET_FAMILY,
2563 &ovs_packet_family);
aaff4b55 2564 }
c7178a0b
EJ
2565 if (!error) {
2566 error = nl_lookup_genl_mcgroup(OVS_VPORT_FAMILY, OVS_VPORT_MCGROUP,
b3dcb73c 2567 &ovs_vport_mcgroup);
c7178a0b 2568 }
eb8ed438 2569
921c370a
EG
2570 ovs_tunnels_out_of_tree = dpif_netlink_rtnl_probe_oot_tunnels();
2571
eb8ed438 2572 ovsthread_once_done(&once);
982b8810
BP
2573 }
2574
2575 return error;
96fba48f
BP
2576}
2577
c19e6535 2578bool
93451a0a 2579dpif_netlink_is_internal_device(const char *name)
9fe3b9a2 2580{
93451a0a 2581 struct dpif_netlink_vport reply;
c19e6535 2582 struct ofpbuf *buf;
9fe3b9a2 2583 int error;
96fba48f 2584
93451a0a 2585 error = dpif_netlink_vport_get(name, &reply, &buf);
c19e6535
BP
2586 if (!error) {
2587 ofpbuf_delete(buf);
141d9ce4 2588 } else if (error != ENODEV && error != ENOENT) {
c19e6535 2589 VLOG_WARN_RL(&error_rl, "%s: vport query failed (%s)",
10a89ef0 2590 name, ovs_strerror(error));
96fba48f
BP
2591 }
2592
df2c07f4 2593 return reply.type == OVS_VPORT_TYPE_INTERNAL;
96fba48f 2594}
e0467f6d 2595
df2c07f4 2596/* Parses the contents of 'buf', which contains a "struct ovs_header" followed
c19e6535
BP
2597 * by Netlink attributes, into 'vport'. Returns 0 if successful, otherwise a
2598 * positive errno value.
2599 *
2600 * 'vport' will contain pointers into 'buf', so the caller should not free
2601 * 'buf' while 'vport' is still in use. */
2602static int
93451a0a 2603dpif_netlink_vport_from_ofpbuf(struct dpif_netlink_vport *vport,
c19e6535
BP
2604 const struct ofpbuf *buf)
2605{
df2c07f4
JP
2606 static const struct nl_policy ovs_vport_policy[] = {
2607 [OVS_VPORT_ATTR_PORT_NO] = { .type = NL_A_U32 },
2608 [OVS_VPORT_ATTR_TYPE] = { .type = NL_A_U32 },
2609 [OVS_VPORT_ATTR_NAME] = { .type = NL_A_STRING, .max_len = IFNAMSIZ },
1579cf67 2610 [OVS_VPORT_ATTR_UPCALL_PID] = { .type = NL_A_UNSPEC },
f7df9823 2611 [OVS_VPORT_ATTR_STATS] = { NL_POLICY_FOR(struct ovs_vport_stats),
c19e6535 2612 .optional = true },
df2c07f4 2613 [OVS_VPORT_ATTR_OPTIONS] = { .type = NL_A_NESTED, .optional = true },
c19e6535
BP
2614 };
2615
93451a0a 2616 dpif_netlink_vport_init(vport);
c19e6535 2617
0a2869d5
BP
2618 struct ofpbuf b = ofpbuf_const_initializer(buf->data, buf->size);
2619 struct nlmsghdr *nlmsg = ofpbuf_try_pull(&b, sizeof *nlmsg);
2620 struct genlmsghdr *genl = ofpbuf_try_pull(&b, sizeof *genl);
2621 struct ovs_header *ovs_header = ofpbuf_try_pull(&b, sizeof *ovs_header);
2622
2623 struct nlattr *a[ARRAY_SIZE(ovs_vport_policy)];
df2c07f4
JP
2624 if (!nlmsg || !genl || !ovs_header
2625 || nlmsg->nlmsg_type != ovs_vport_family
2626 || !nl_policy_parse(&b, 0, ovs_vport_policy, a,
2627 ARRAY_SIZE(ovs_vport_policy))) {
c19e6535
BP
2628 return EINVAL;
2629 }
c19e6535 2630
f0fef760 2631 vport->cmd = genl->cmd;
df2c07f4 2632 vport->dp_ifindex = ovs_header->dp_ifindex;
4e022ec0 2633 vport->port_no = nl_attr_get_odp_port(a[OVS_VPORT_ATTR_PORT_NO]);
df2c07f4
JP
2634 vport->type = nl_attr_get_u32(a[OVS_VPORT_ATTR_TYPE]);
2635 vport->name = nl_attr_get_string(a[OVS_VPORT_ATTR_NAME]);
b063d9f0 2636 if (a[OVS_VPORT_ATTR_UPCALL_PID]) {
1579cf67
AW
2637 vport->n_upcall_pids = nl_attr_get_size(a[OVS_VPORT_ATTR_UPCALL_PID])
2638 / (sizeof *vport->upcall_pids);
2639 vport->upcall_pids = nl_attr_get(a[OVS_VPORT_ATTR_UPCALL_PID]);
2640
b063d9f0 2641 }
df2c07f4
JP
2642 if (a[OVS_VPORT_ATTR_STATS]) {
2643 vport->stats = nl_attr_get(a[OVS_VPORT_ATTR_STATS]);
2644 }
df2c07f4
JP
2645 if (a[OVS_VPORT_ATTR_OPTIONS]) {
2646 vport->options = nl_attr_get(a[OVS_VPORT_ATTR_OPTIONS]);
2647 vport->options_len = nl_attr_get_size(a[OVS_VPORT_ATTR_OPTIONS]);
c19e6535 2648 }
c19e6535
BP
2649 return 0;
2650}
2651
df2c07f4 2652/* Appends to 'buf' (which must initially be empty) a "struct ovs_header"
c19e6535
BP
2653 * followed by Netlink attributes corresponding to 'vport'. */
2654static void
93451a0a
AS
2655dpif_netlink_vport_to_ofpbuf(const struct dpif_netlink_vport *vport,
2656 struct ofpbuf *buf)
c19e6535 2657{
df2c07f4 2658 struct ovs_header *ovs_header;
f0fef760 2659
df2c07f4 2660 nl_msg_put_genlmsghdr(buf, 0, ovs_vport_family, NLM_F_REQUEST | NLM_F_ECHO,
69685a88 2661 vport->cmd, OVS_VPORT_VERSION);
c19e6535 2662
df2c07f4
JP
2663 ovs_header = ofpbuf_put_uninit(buf, sizeof *ovs_header);
2664 ovs_header->dp_ifindex = vport->dp_ifindex;
c19e6535 2665
4e022ec0
AW
2666 if (vport->port_no != ODPP_NONE) {
2667 nl_msg_put_odp_port(buf, OVS_VPORT_ATTR_PORT_NO, vport->port_no);
c19e6535
BP
2668 }
2669
df2c07f4
JP
2670 if (vport->type != OVS_VPORT_TYPE_UNSPEC) {
2671 nl_msg_put_u32(buf, OVS_VPORT_ATTR_TYPE, vport->type);
c19e6535
BP
2672 }
2673
2674 if (vport->name) {
df2c07f4 2675 nl_msg_put_string(buf, OVS_VPORT_ATTR_NAME, vport->name);
c19e6535
BP
2676 }
2677
1579cf67
AW
2678 if (vport->upcall_pids) {
2679 nl_msg_put_unspec(buf, OVS_VPORT_ATTR_UPCALL_PID,
2680 vport->upcall_pids,
2681 vport->n_upcall_pids * sizeof *vport->upcall_pids);
a24a6574 2682 }
b063d9f0 2683
c19e6535 2684 if (vport->stats) {
df2c07f4 2685 nl_msg_put_unspec(buf, OVS_VPORT_ATTR_STATS,
c19e6535
BP
2686 vport->stats, sizeof *vport->stats);
2687 }
2688
c19e6535 2689 if (vport->options) {
df2c07f4 2690 nl_msg_put_nested(buf, OVS_VPORT_ATTR_OPTIONS,
c19e6535
BP
2691 vport->options, vport->options_len);
2692 }
c19e6535
BP
2693}
2694
2695/* Clears 'vport' to "empty" values. */
2696void
93451a0a 2697dpif_netlink_vport_init(struct dpif_netlink_vport *vport)
c19e6535
BP
2698{
2699 memset(vport, 0, sizeof *vport);
4e022ec0 2700 vport->port_no = ODPP_NONE;
c19e6535
BP
2701}
2702
2703/* Executes 'request' in the kernel datapath. If the command fails, returns a
2704 * positive errno value. Otherwise, if 'reply' and 'bufp' are null, returns 0
2705 * without doing anything else. If 'reply' and 'bufp' are nonnull, then the
df2c07f4 2706 * result of the command is expected to be an ovs_vport also, which is decoded
c19e6535
BP
2707 * and stored in '*reply' and '*bufp'. The caller must free '*bufp' when the
2708 * reply is no longer needed ('reply' will contain pointers into '*bufp'). */
2709int
93451a0a
AS
2710dpif_netlink_vport_transact(const struct dpif_netlink_vport *request,
2711 struct dpif_netlink_vport *reply,
2712 struct ofpbuf **bufp)
c19e6535 2713{
f0fef760 2714 struct ofpbuf *request_buf;
c19e6535
BP
2715 int error;
2716
cb22974d 2717 ovs_assert((reply != NULL) == (bufp != NULL));
c19e6535 2718
93451a0a 2719 error = dpif_netlink_init();
42bb6c72
BP
2720 if (error) {
2721 if (reply) {
2722 *bufp = NULL;
93451a0a 2723 dpif_netlink_vport_init(reply);
42bb6c72
BP
2724 }
2725 return error;
2726 }
2727
f0fef760 2728 request_buf = ofpbuf_new(1024);
93451a0a 2729 dpif_netlink_vport_to_ofpbuf(request, request_buf);
a88b4e04 2730 error = nl_transact(NETLINK_GENERIC, request_buf, bufp);
f0fef760 2731 ofpbuf_delete(request_buf);
c19e6535 2732
f0fef760
BP
2733 if (reply) {
2734 if (!error) {
93451a0a 2735 error = dpif_netlink_vport_from_ofpbuf(reply, *bufp);
f0fef760 2736 }
c19e6535 2737 if (error) {
93451a0a 2738 dpif_netlink_vport_init(reply);
f0fef760
BP
2739 ofpbuf_delete(*bufp);
2740 *bufp = NULL;
c19e6535 2741 }
c19e6535
BP
2742 }
2743 return error;
2744}
2745
2746/* Obtains information about the kernel vport named 'name' and stores it into
2747 * '*reply' and '*bufp'. The caller must free '*bufp' when the reply is no
2748 * longer needed ('reply' will contain pointers into '*bufp'). */
2749int
93451a0a
AS
2750dpif_netlink_vport_get(const char *name, struct dpif_netlink_vport *reply,
2751 struct ofpbuf **bufp)
c19e6535 2752{
93451a0a 2753 struct dpif_netlink_vport request;
c19e6535 2754
93451a0a 2755 dpif_netlink_vport_init(&request);
df2c07f4 2756 request.cmd = OVS_VPORT_CMD_GET;
c19e6535
BP
2757 request.name = name;
2758
93451a0a 2759 return dpif_netlink_vport_transact(&request, reply, bufp);
c19e6535 2760}
93451a0a 2761
df2c07f4 2762/* Parses the contents of 'buf', which contains a "struct ovs_header" followed
aaff4b55
BP
2763 * by Netlink attributes, into 'dp'. Returns 0 if successful, otherwise a
2764 * positive errno value.
d6569377
BP
2765 *
2766 * 'dp' will contain pointers into 'buf', so the caller should not free 'buf'
2767 * while 'dp' is still in use. */
2768static int
93451a0a 2769dpif_netlink_dp_from_ofpbuf(struct dpif_netlink_dp *dp, const struct ofpbuf *buf)
d6569377 2770{
df2c07f4
JP
2771 static const struct nl_policy ovs_datapath_policy[] = {
2772 [OVS_DP_ATTR_NAME] = { .type = NL_A_STRING, .max_len = IFNAMSIZ },
f7df9823 2773 [OVS_DP_ATTR_STATS] = { NL_POLICY_FOR(struct ovs_dp_stats),
d6569377 2774 .optional = true },
847108dc
AZ
2775 [OVS_DP_ATTR_MEGAFLOW_STATS] = {
2776 NL_POLICY_FOR(struct ovs_dp_megaflow_stats),
2777 .optional = true },
d6569377
BP
2778 };
2779
93451a0a 2780 dpif_netlink_dp_init(dp);
d6569377 2781
0a2869d5
BP
2782 struct ofpbuf b = ofpbuf_const_initializer(buf->data, buf->size);
2783 struct nlmsghdr *nlmsg = ofpbuf_try_pull(&b, sizeof *nlmsg);
2784 struct genlmsghdr *genl = ofpbuf_try_pull(&b, sizeof *genl);
2785 struct ovs_header *ovs_header = ofpbuf_try_pull(&b, sizeof *ovs_header);
2786
2787 struct nlattr *a[ARRAY_SIZE(ovs_datapath_policy)];
df2c07f4
JP
2788 if (!nlmsg || !genl || !ovs_header
2789 || nlmsg->nlmsg_type != ovs_datapath_family
2790 || !nl_policy_parse(&b, 0, ovs_datapath_policy, a,
2791 ARRAY_SIZE(ovs_datapath_policy))) {
d6569377
BP
2792 return EINVAL;
2793 }
d6569377 2794
aaff4b55 2795 dp->cmd = genl->cmd;
df2c07f4
JP
2796 dp->dp_ifindex = ovs_header->dp_ifindex;
2797 dp->name = nl_attr_get_string(a[OVS_DP_ATTR_NAME]);
2798 if (a[OVS_DP_ATTR_STATS]) {
6a54dedc 2799 dp->stats = nl_attr_get(a[OVS_DP_ATTR_STATS]);
d6569377 2800 }
982b8810 2801
847108dc 2802 if (a[OVS_DP_ATTR_MEGAFLOW_STATS]) {
6a54dedc 2803 dp->megaflow_stats = nl_attr_get(a[OVS_DP_ATTR_MEGAFLOW_STATS]);
847108dc
AZ
2804 }
2805
d6569377
BP
2806 return 0;
2807}
2808
aaff4b55 2809/* Appends to 'buf' the Generic Netlink message described by 'dp'. */
d6569377 2810static void
93451a0a 2811dpif_netlink_dp_to_ofpbuf(const struct dpif_netlink_dp *dp, struct ofpbuf *buf)
d6569377 2812{
df2c07f4 2813 struct ovs_header *ovs_header;
d6569377 2814
df2c07f4 2815 nl_msg_put_genlmsghdr(buf, 0, ovs_datapath_family,
69685a88
JG
2816 NLM_F_REQUEST | NLM_F_ECHO, dp->cmd,
2817 OVS_DATAPATH_VERSION);
aaff4b55 2818
df2c07f4
JP
2819 ovs_header = ofpbuf_put_uninit(buf, sizeof *ovs_header);
2820 ovs_header->dp_ifindex = dp->dp_ifindex;
d6569377
BP
2821
2822 if (dp->name) {
df2c07f4 2823 nl_msg_put_string(buf, OVS_DP_ATTR_NAME, dp->name);
d6569377
BP
2824 }
2825
a24a6574
BP
2826 if (dp->upcall_pid) {
2827 nl_msg_put_u32(buf, OVS_DP_ATTR_UPCALL_PID, *dp->upcall_pid);
2828 }
b063d9f0 2829
b7fd5e38
TG
2830 if (dp->user_features) {
2831 nl_msg_put_u32(buf, OVS_DP_ATTR_USER_FEATURES, dp->user_features);
2832 }
2833
df2c07f4 2834 /* Skip OVS_DP_ATTR_STATS since we never have a reason to serialize it. */
d6569377
BP
2835}
2836
2837/* Clears 'dp' to "empty" values. */
d3d8f1f7 2838static void
93451a0a 2839dpif_netlink_dp_init(struct dpif_netlink_dp *dp)
d6569377
BP
2840{
2841 memset(dp, 0, sizeof *dp);
d6569377
BP
2842}
2843
aaff4b55 2844static void
93451a0a 2845dpif_netlink_dp_dump_start(struct nl_dump *dump)
aaff4b55 2846{
93451a0a 2847 struct dpif_netlink_dp request;
aaff4b55
BP
2848 struct ofpbuf *buf;
2849
93451a0a 2850 dpif_netlink_dp_init(&request);
df2c07f4 2851 request.cmd = OVS_DP_CMD_GET;
aaff4b55
BP
2852
2853 buf = ofpbuf_new(1024);
93451a0a 2854 dpif_netlink_dp_to_ofpbuf(&request, buf);
a88b4e04 2855 nl_dump_start(dump, NETLINK_GENERIC, buf);
aaff4b55
BP
2856 ofpbuf_delete(buf);
2857}
2858
d6569377
BP
2859/* Executes 'request' in the kernel datapath. If the command fails, returns a
2860 * positive errno value. Otherwise, if 'reply' and 'bufp' are null, returns 0
2861 * without doing anything else. If 'reply' and 'bufp' are nonnull, then the
aaff4b55
BP
2862 * result of the command is expected to be of the same form, which is decoded
2863 * and stored in '*reply' and '*bufp'. The caller must free '*bufp' when the
2864 * reply is no longer needed ('reply' will contain pointers into '*bufp'). */
d3d8f1f7 2865static int
93451a0a
AS
2866dpif_netlink_dp_transact(const struct dpif_netlink_dp *request,
2867 struct dpif_netlink_dp *reply, struct ofpbuf **bufp)
d6569377 2868{
aaff4b55 2869 struct ofpbuf *request_buf;
d6569377 2870 int error;
d6569377 2871
cb22974d 2872 ovs_assert((reply != NULL) == (bufp != NULL));
d6569377 2873
aaff4b55 2874 request_buf = ofpbuf_new(1024);
93451a0a 2875 dpif_netlink_dp_to_ofpbuf(request, request_buf);
a88b4e04 2876 error = nl_transact(NETLINK_GENERIC, request_buf, bufp);
aaff4b55 2877 ofpbuf_delete(request_buf);
d6569377 2878
aaff4b55 2879 if (reply) {
93451a0a 2880 dpif_netlink_dp_init(reply);
aaff4b55 2881 if (!error) {
93451a0a 2882 error = dpif_netlink_dp_from_ofpbuf(reply, *bufp);
aaff4b55 2883 }
d6569377 2884 if (error) {
aaff4b55
BP
2885 ofpbuf_delete(*bufp);
2886 *bufp = NULL;
d6569377 2887 }
d6569377
BP
2888 }
2889 return error;
2890}
2891
2892/* Obtains information about 'dpif_' and stores it into '*reply' and '*bufp'.
2893 * The caller must free '*bufp' when the reply is no longer needed ('reply'
2894 * will contain pointers into '*bufp'). */
d3d8f1f7 2895static int
93451a0a
AS
2896dpif_netlink_dp_get(const struct dpif *dpif_, struct dpif_netlink_dp *reply,
2897 struct ofpbuf **bufp)
d6569377 2898{
93451a0a
AS
2899 struct dpif_netlink *dpif = dpif_netlink_cast(dpif_);
2900 struct dpif_netlink_dp request;
d6569377 2901
93451a0a 2902 dpif_netlink_dp_init(&request);
df2c07f4 2903 request.cmd = OVS_DP_CMD_GET;
254f2dc8 2904 request.dp_ifindex = dpif->dp_ifindex;
d6569377 2905
93451a0a 2906 return dpif_netlink_dp_transact(&request, reply, bufp);
d6569377 2907}
93451a0a 2908
df2c07f4 2909/* Parses the contents of 'buf', which contains a "struct ovs_header" followed
37a1300c 2910 * by Netlink attributes, into 'flow'. Returns 0 if successful, otherwise a
d6569377
BP
2911 * positive errno value.
2912 *
2913 * 'flow' will contain pointers into 'buf', so the caller should not free 'buf'
2914 * while 'flow' is still in use. */
2915static int
93451a0a
AS
2916dpif_netlink_flow_from_ofpbuf(struct dpif_netlink_flow *flow,
2917 const struct ofpbuf *buf)
d6569377 2918{
70e5ed6f
JS
2919 static const struct nl_policy ovs_flow_policy[__OVS_FLOW_ATTR_MAX] = {
2920 [OVS_FLOW_ATTR_KEY] = { .type = NL_A_NESTED, .optional = true },
e6cc0bab 2921 [OVS_FLOW_ATTR_MASK] = { .type = NL_A_NESTED, .optional = true },
df2c07f4 2922 [OVS_FLOW_ATTR_ACTIONS] = { .type = NL_A_NESTED, .optional = true },
f7df9823 2923 [OVS_FLOW_ATTR_STATS] = { NL_POLICY_FOR(struct ovs_flow_stats),
d6569377 2924 .optional = true },
df2c07f4
JP
2925 [OVS_FLOW_ATTR_TCP_FLAGS] = { .type = NL_A_U8, .optional = true },
2926 [OVS_FLOW_ATTR_USED] = { .type = NL_A_U64, .optional = true },
ab79d262 2927 [OVS_FLOW_ATTR_UFID] = { .type = NL_A_U128, .optional = true },
df2c07f4 2928 /* The kernel never uses OVS_FLOW_ATTR_CLEAR. */
43f9ac0a 2929 /* The kernel never uses OVS_FLOW_ATTR_PROBE. */
70e5ed6f 2930 /* The kernel never uses OVS_FLOW_ATTR_UFID_FLAGS. */
d6569377
BP
2931 };
2932
93451a0a 2933 dpif_netlink_flow_init(flow);
d6569377 2934
0a2869d5
BP
2935 struct ofpbuf b = ofpbuf_const_initializer(buf->data, buf->size);
2936 struct nlmsghdr *nlmsg = ofpbuf_try_pull(&b, sizeof *nlmsg);
2937 struct genlmsghdr *genl = ofpbuf_try_pull(&b, sizeof *genl);
2938 struct ovs_header *ovs_header = ofpbuf_try_pull(&b, sizeof *ovs_header);
2939
2940 struct nlattr *a[ARRAY_SIZE(ovs_flow_policy)];
df2c07f4
JP
2941 if (!nlmsg || !genl || !ovs_header
2942 || nlmsg->nlmsg_type != ovs_flow_family
2943 || !nl_policy_parse(&b, 0, ovs_flow_policy, a,
2944 ARRAY_SIZE(ovs_flow_policy))) {
d6569377
BP
2945 return EINVAL;
2946 }
70e5ed6f
JS
2947 if (!a[OVS_FLOW_ATTR_KEY] && !a[OVS_FLOW_ATTR_UFID]) {
2948 return EINVAL;
2949 }
d6569377 2950
37a1300c 2951 flow->nlmsg_flags = nlmsg->nlmsg_flags;
df2c07f4 2952 flow->dp_ifindex = ovs_header->dp_ifindex;
70e5ed6f
JS
2953 if (a[OVS_FLOW_ATTR_KEY]) {
2954 flow->key = nl_attr_get(a[OVS_FLOW_ATTR_KEY]);
2955 flow->key_len = nl_attr_get_size(a[OVS_FLOW_ATTR_KEY]);
2956 }
e6cc0bab 2957
70e5ed6f 2958 if (a[OVS_FLOW_ATTR_UFID]) {
ab79d262 2959 flow->ufid = nl_attr_get_u128(a[OVS_FLOW_ATTR_UFID]);
70e5ed6f
JS
2960 flow->ufid_present = true;
2961 }
e6cc0bab
AZ
2962 if (a[OVS_FLOW_ATTR_MASK]) {
2963 flow->mask = nl_attr_get(a[OVS_FLOW_ATTR_MASK]);
2964 flow->mask_len = nl_attr_get_size(a[OVS_FLOW_ATTR_MASK]);
2965 }
df2c07f4
JP
2966 if (a[OVS_FLOW_ATTR_ACTIONS]) {
2967 flow->actions = nl_attr_get(a[OVS_FLOW_ATTR_ACTIONS]);
2968 flow->actions_len = nl_attr_get_size(a[OVS_FLOW_ATTR_ACTIONS]);
d6569377 2969 }
df2c07f4
JP
2970 if (a[OVS_FLOW_ATTR_STATS]) {
2971 flow->stats = nl_attr_get(a[OVS_FLOW_ATTR_STATS]);
d6569377 2972 }
df2c07f4
JP
2973 if (a[OVS_FLOW_ATTR_TCP_FLAGS]) {
2974 flow->tcp_flags = nl_attr_get(a[OVS_FLOW_ATTR_TCP_FLAGS]);
d6569377 2975 }
df2c07f4
JP
2976 if (a[OVS_FLOW_ATTR_USED]) {
2977 flow->used = nl_attr_get(a[OVS_FLOW_ATTR_USED]);
9e980142 2978 }
d6569377
BP
2979 return 0;
2980}
2981
beb75a40
JS
2982
2983/*
2984 * If PACKET_TYPE attribute is present in 'data', it filters PACKET_TYPE out,
2985 * then puts 'data' to 'buf'.
2986 */
2987static void
2988put_exclude_packet_type(struct ofpbuf *buf, uint16_t type,
2989 const struct nlattr *data, uint16_t data_len)
2990{
2991 const struct nlattr *packet_type;
2992
2993 packet_type = nl_attr_find__(data, data_len, OVS_KEY_ATTR_PACKET_TYPE);
2994
2995 if (packet_type) {
2996 /* exclude PACKET_TYPE Netlink attribute. */
2997 ovs_assert(NLA_ALIGN(packet_type->nla_len) == NL_A_U32_SIZE);
2998 size_t packet_type_len = NL_A_U32_SIZE;
2999 size_t first_chunk_size = (uint8_t *)packet_type - (uint8_t *)data;
3000 size_t second_chunk_size = data_len - first_chunk_size
3001 - packet_type_len;
3002 uint8_t *first_attr = NULL;
3003 struct nlattr *next_attr = nl_attr_next(packet_type);
3004
3005 first_attr = nl_msg_put_unspec_uninit(buf, type,
3006 data_len - packet_type_len);
3007 memcpy(first_attr, data, first_chunk_size);
3008 memcpy(first_attr + first_chunk_size, next_attr, second_chunk_size);
3009 } else {
3010 nl_msg_put_unspec(buf, type, data, data_len);
3011 }
3012}
3013
df2c07f4 3014/* Appends to 'buf' (which must initially be empty) a "struct ovs_header"
d6569377
BP
3015 * followed by Netlink attributes corresponding to 'flow'. */
3016static void
93451a0a
AS
3017dpif_netlink_flow_to_ofpbuf(const struct dpif_netlink_flow *flow,
3018 struct ofpbuf *buf)
d6569377 3019{
df2c07f4 3020 struct ovs_header *ovs_header;
d6569377 3021
df2c07f4 3022 nl_msg_put_genlmsghdr(buf, 0, ovs_flow_family,
30b44744 3023 NLM_F_REQUEST | flow->nlmsg_flags,
69685a88 3024 flow->cmd, OVS_FLOW_VERSION);
37a1300c 3025
df2c07f4
JP
3026 ovs_header = ofpbuf_put_uninit(buf, sizeof *ovs_header);
3027 ovs_header->dp_ifindex = flow->dp_ifindex;
d6569377 3028
70e5ed6f 3029 if (flow->ufid_present) {
ab79d262 3030 nl_msg_put_u128(buf, OVS_FLOW_ATTR_UFID, flow->ufid);
70e5ed6f
JS
3031 }
3032 if (flow->ufid_terse) {
3033 nl_msg_put_u32(buf, OVS_FLOW_ATTR_UFID_FLAGS,
3034 OVS_UFID_F_OMIT_KEY | OVS_UFID_F_OMIT_MASK
3035 | OVS_UFID_F_OMIT_ACTIONS);
3036 }
64bb477f
JS
3037 if (!flow->ufid_terse || !flow->ufid_present) {
3038 if (flow->key_len) {
beb75a40
JS
3039 put_exclude_packet_type(buf, OVS_FLOW_ATTR_KEY, flow->key,
3040 flow->key_len);
64bb477f 3041 }
64bb477f 3042 if (flow->mask_len) {
beb75a40
JS
3043 put_exclude_packet_type(buf, OVS_FLOW_ATTR_MASK, flow->mask,
3044 flow->mask_len);
64bb477f
JS
3045 }
3046 if (flow->actions || flow->actions_len) {
3047 nl_msg_put_unspec(buf, OVS_FLOW_ATTR_ACTIONS,
3048 flow->actions, flow->actions_len);
3049 }
d6569377
BP
3050 }
3051
3052 /* We never need to send these to the kernel. */
cb22974d
BP
3053 ovs_assert(!flow->stats);
3054 ovs_assert(!flow->tcp_flags);
3055 ovs_assert(!flow->used);
d6569377
BP
3056
3057 if (flow->clear) {
df2c07f4 3058 nl_msg_put_flag(buf, OVS_FLOW_ATTR_CLEAR);
d6569377 3059 }
43f9ac0a
JR
3060 if (flow->probe) {
3061 nl_msg_put_flag(buf, OVS_FLOW_ATTR_PROBE);
3062 }
d6569377
BP
3063}
3064
3065/* Clears 'flow' to "empty" values. */
d3d8f1f7 3066static void
93451a0a 3067dpif_netlink_flow_init(struct dpif_netlink_flow *flow)
d6569377
BP
3068{
3069 memset(flow, 0, sizeof *flow);
3070}
3071
3072/* Executes 'request' in the kernel datapath. If the command fails, returns a
3073 * positive errno value. Otherwise, if 'reply' and 'bufp' are null, returns 0
3074 * without doing anything else. If 'reply' and 'bufp' are nonnull, then the
37a1300c
BP
3075 * result of the command is expected to be a flow also, which is decoded and
3076 * stored in '*reply' and '*bufp'. The caller must free '*bufp' when the reply
3077 * is no longer needed ('reply' will contain pointers into '*bufp'). */
d3d8f1f7 3078static int
93451a0a
AS
3079dpif_netlink_flow_transact(struct dpif_netlink_flow *request,
3080 struct dpif_netlink_flow *reply,
3081 struct ofpbuf **bufp)
d6569377 3082{
37a1300c 3083 struct ofpbuf *request_buf;
d6569377 3084 int error;
d6569377 3085
cb22974d 3086 ovs_assert((reply != NULL) == (bufp != NULL));
d6569377 3087
30b44744
BP
3088 if (reply) {
3089 request->nlmsg_flags |= NLM_F_ECHO;
3090 }
3091
37a1300c 3092 request_buf = ofpbuf_new(1024);
93451a0a 3093 dpif_netlink_flow_to_ofpbuf(request, request_buf);
a88b4e04 3094 error = nl_transact(NETLINK_GENERIC, request_buf, bufp);
37a1300c 3095 ofpbuf_delete(request_buf);
d6569377 3096
37a1300c
BP
3097 if (reply) {
3098 if (!error) {
93451a0a 3099 error = dpif_netlink_flow_from_ofpbuf(reply, *bufp);
37a1300c 3100 }
d6569377 3101 if (error) {
93451a0a 3102 dpif_netlink_flow_init(reply);
37a1300c
BP
3103 ofpbuf_delete(*bufp);
3104 *bufp = NULL;
d6569377 3105 }
d6569377
BP
3106 }
3107 return error;
3108}
3109
3110static void
93451a0a
AS
3111dpif_netlink_flow_get_stats(const struct dpif_netlink_flow *flow,
3112 struct dpif_flow_stats *stats)
d6569377
BP
3113{
3114 if (flow->stats) {
6a54dedc
BP
3115 stats->n_packets = get_32aligned_u64(&flow->stats->n_packets);
3116 stats->n_bytes = get_32aligned_u64(&flow->stats->n_bytes);
d6569377
BP
3117 } else {
3118 stats->n_packets = 0;
3119 stats->n_bytes = 0;
3120 }
0e70cdcb 3121 stats->used = flow->used ? get_32aligned_u64(flow->used) : 0;
d6569377
BP
3122 stats->tcp_flags = flow->tcp_flags ? *flow->tcp_flags : 0;
3123}
e0467f6d 3124
14b4d2f9
BP
3125/* Logs information about a packet that was recently lost in 'ch' (in
3126 * 'dpif_'). */
3127static void
93451a0a 3128report_loss(struct dpif_netlink *dpif, struct dpif_channel *ch, uint32_t ch_idx,
1579cf67 3129 uint32_t handler_id)
14b4d2f9 3130{
14b4d2f9 3131 static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 5);
14b4d2f9
BP
3132 struct ds s;
3133
8d675c5a 3134 if (VLOG_DROP_WARN(&rl)) {
14b4d2f9
BP
3135 return;
3136 }
3137
3138 ds_init(&s);
3139 if (ch->last_poll != LLONG_MIN) {
3140 ds_put_format(&s, " (last polled %lld ms ago)",
3141 time_msec() - ch->last_poll);
3142 }
14b4d2f9 3143
1579cf67 3144 VLOG_WARN("%s: lost packet on port channel %u of handler %u",
9b00386b 3145 dpif_name(&dpif->dpif), ch_idx, handler_id);
14b4d2f9
BP
3146 ds_destroy(&s);
3147}