]> git.proxmox.com Git - ovs.git/blame - lib/netdev-vport.c
json: Fix error message for corner case in json_string_unescape().
[ovs.git] / lib / netdev-vport.c
CommitLineData
777ece09 1/*
b2f771ef 2 * Copyright (c) 2010, 2011, 2012, 2013, 2014 Nicira, Inc.
777ece09
JG
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 *
6fcfff1b 10 * Unless required by applicable law or agreed to in writing, software
777ece09
JG
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>
2b9d6589
BP
18
19#include "netdev-vport.h"
20
777ece09
JG
21#include <errno.h>
22#include <fcntl.h>
ea83a2fc 23#include <sys/socket.h>
2b9d6589 24#include <net/if.h>
777ece09
JG
25#include <sys/ioctl.h>
26
b9298d3f 27#include "byte-order.h"
a36de779 28#include "csum.h"
5059eff3
JP
29#include "daemon.h"
30#include "dirs.h"
0a740f48 31#include "dpif.h"
e14deea0 32#include "dp-packet.h"
a36de779
PS
33#include "dynamic-string.h"
34#include "flow.h"
ea83a2fc
EJ
35#include "hash.h"
36#include "hmap.h"
777ece09 37#include "list.h"
2b9d6589 38#include "netdev-provider.h"
a36de779 39#include "odp-netlink.h"
cf62fa4c 40#include "dp-packet.h"
d9b4ebc5 41#include "ovs-router.h"
2b9d6589 42#include "packets.h"
41ca1e0a 43#include "poll-loop.h"
a132aa96 44#include "route-table.h"
777ece09
JG
45#include "shash.h"
46#include "socket-util.h"
e6211adc 47#include "openvswitch/vlog.h"
a36de779
PS
48#include "unaligned.h"
49#include "unixctl.h"
50#include "util.h"
777ece09 51
d98e6007 52VLOG_DEFINE_THIS_MODULE(netdev_vport);
a36de779 53static struct vlog_rate_limit err_rl = VLOG_RATE_LIMIT_INIT(60, 5);
5136ce49 54
c1fc1411 55#define GENEVE_DST_PORT 6081
4f2abb7b 56#define VXLAN_DST_PORT 4789
a6ae068b 57#define LISP_DST_PORT 4341
4237026e 58#define STT_DST_PORT 7471
a6ae068b 59
a36de779
PS
60#define VXLAN_HLEN (sizeof(struct eth_header) + \
61 sizeof(struct ip_header) + \
62 sizeof(struct udp_header) + \
63 sizeof(struct vxlanhdr))
64
e5a1caee
JG
65#define GENEVE_BASE_HLEN (sizeof(struct eth_header) + \
66 sizeof(struct ip_header) + \
67 sizeof(struct udp_header) + \
68 sizeof(struct genevehdr))
69
f431bf7d
EJ
70#define DEFAULT_TTL 64
71
b5d57fc8
BP
72struct netdev_vport {
73 struct netdev up;
86383816
BP
74
75 /* Protects all members below. */
76 struct ovs_mutex mutex;
77
35b769cb 78 uint8_t etheraddr[ETH_ADDR_LEN];
b9ad7294 79 struct netdev_stats stats;
0a740f48
EJ
80
81 /* Tunnels. */
f431bf7d 82 struct netdev_tunnel_config tnl_cfg;
41ca1e0a
AW
83 char egress_iface[IFNAMSIZ];
84 bool carrier_status;
0a740f48
EJ
85
86 /* Patch Ports. */
0a740f48 87 char *peer;
2b9d6589
BP
88};
89
2b9d6589 90struct vport_class {
b9ad7294 91 const char *dpif_port;
c3827f61 92 struct netdev_class netdev_class;
2b9d6589
BP
93};
94
41ca1e0a
AW
95/* Last read of the route-table's change number. */
96static uint64_t rt_change_seqno;
97
9dc63482 98static int netdev_vport_construct(struct netdev *);
86383816 99static int get_patch_config(const struct netdev *netdev, struct smap *args);
b5d57fc8 100static int get_tunnel_config(const struct netdev *, struct smap *args);
41ca1e0a 101static bool tunnel_check_status_change__(struct netdev_vport *);
2b9d6589 102
a36de779
PS
103static uint16_t tnl_udp_port_min = 32768;
104static uint16_t tnl_udp_port_max = 61000;
105
2b9d6589
BP
106static bool
107is_vport_class(const struct netdev_class *class)
777ece09 108{
9dc63482 109 return class->construct == netdev_vport_construct;
2b9d6589 110}
777ece09 111
41ca1e0a
AW
112bool
113netdev_vport_is_vport_class(const struct netdev_class *class)
114{
115 return is_vport_class(class);
116}
117
2b9d6589
BP
118static const struct vport_class *
119vport_class_cast(const struct netdev_class *class)
120{
cb22974d 121 ovs_assert(is_vport_class(class));
2b9d6589
BP
122 return CONTAINER_OF(class, struct vport_class, netdev_class);
123}
124
b5d57fc8
BP
125static struct netdev_vport *
126netdev_vport_cast(const struct netdev *netdev)
2b9d6589 127{
b5d57fc8
BP
128 ovs_assert(is_vport_class(netdev_get_class(netdev)));
129 return CONTAINER_OF(netdev, struct netdev_vport, up);
df67d7ae
EJ
130}
131
f431bf7d 132static const struct netdev_tunnel_config *
b5d57fc8 133get_netdev_tunnel_config(const struct netdev *netdev)
f431bf7d 134{
b5d57fc8 135 return &netdev_vport_cast(netdev)->tnl_cfg;
f431bf7d
EJ
136}
137
0a740f48
EJ
138bool
139netdev_vport_is_patch(const struct netdev *netdev)
140{
b5d57fc8 141 const struct netdev_class *class = netdev_get_class(netdev);
f18a39b7 142
c060c4cf 143 return class->get_config == get_patch_config;
0a740f48
EJ
144}
145
a6363cfd
LJ
146bool
147netdev_vport_is_layer3(const struct netdev *dev)
148{
149 const char *type = netdev_get_type(dev);
150
151 return (!strcmp("lisp", type));
152}
153
56b11f0b 154static bool
b5d57fc8 155netdev_vport_needs_dst_port(const struct netdev *dev)
56b11f0b 156{
b5d57fc8
BP
157 const struct netdev_class *class = netdev_get_class(dev);
158 const char *type = netdev_get_type(dev);
56b11f0b 159
a6ae068b 160 return (class->get_config == get_tunnel_config &&
c1fc1411 161 (!strcmp("geneve", type) || !strcmp("vxlan", type) ||
4237026e 162 !strcmp("lisp", type) || !strcmp("stt", type)) );
56b11f0b
KM
163}
164
94a53842
AW
165const char *
166netdev_vport_class_get_dpif_port(const struct netdev_class *class)
167{
168 return is_vport_class(class) ? vport_class_cast(class)->dpif_port : NULL;
169}
170
de281153 171const char *
3aa30359
BP
172netdev_vport_get_dpif_port(const struct netdev *netdev,
173 char namebuf[], size_t bufsize)
de281153 174{
a5d4fadd
JG
175 const struct netdev_class *class = netdev_get_class(netdev);
176 const char *dpif_port = netdev_vport_class_get_dpif_port(class);
177
178 if (!dpif_port) {
179 return netdev_get_name(netdev);
180 }
181
b5d57fc8
BP
182 if (netdev_vport_needs_dst_port(netdev)) {
183 const struct netdev_vport *vport = netdev_vport_cast(netdev);
56b11f0b
KM
184
185 /*
a5d4fadd
JG
186 * Note: IFNAMSIZ is 16 bytes long. Implementations should choose
187 * a dpif port name that is short enough to fit including any
188 * port numbers but assert just in case.
56b11f0b 189 */
3aa30359 190 BUILD_ASSERT(NETDEV_VPORT_NAME_BUFSIZE >= IFNAMSIZ);
a5d4fadd
JG
191 ovs_assert(strlen(dpif_port) + 6 < IFNAMSIZ);
192 snprintf(namebuf, bufsize, "%s_%d", dpif_port,
56b11f0b 193 ntohs(vport->tnl_cfg.dst_port));
3aa30359 194 return namebuf;
56b11f0b 195 } else {
a5d4fadd 196 return dpif_port;
56b11f0b 197 }
2b9d6589 198}
777ece09 199
3aa30359
BP
200char *
201netdev_vport_get_dpif_port_strdup(const struct netdev *netdev)
202{
203 char namebuf[NETDEV_VPORT_NAME_BUFSIZE];
204
205 return xstrdup(netdev_vport_get_dpif_port(netdev, namebuf,
206 sizeof namebuf));
207}
208
41ca1e0a
AW
209/* Whenever the route-table change number is incremented,
210 * netdev_vport_route_changed() should be called to update
211 * the corresponding tunnel interface status. */
212static void
213netdev_vport_route_changed(void)
214{
215 struct netdev **vports;
216 size_t i, n_vports;
217
218 vports = netdev_get_vports(&n_vports);
219 for (i = 0; i < n_vports; i++) {
220 struct netdev *netdev_ = vports[i];
221 struct netdev_vport *netdev = netdev_vport_cast(netdev_);
222
223 ovs_mutex_lock(&netdev->mutex);
224 /* Finds all tunnel vports. */
225 if (netdev->tnl_cfg.ip_dst) {
226 if (tunnel_check_status_change__(netdev)) {
227 netdev_change_seq_changed(netdev_);
228 }
229 }
41ca1e0a 230 ovs_mutex_unlock(&netdev->mutex);
b2f771ef
BP
231
232 netdev_close(netdev_);
41ca1e0a
AW
233 }
234
235 free(vports);
236}
237
9dc63482
BP
238static struct netdev *
239netdev_vport_alloc(void)
240{
241 struct netdev_vport *netdev = xzalloc(sizeof *netdev);
242 return &netdev->up;
243}
244
2b9d6589 245static int
9dc63482 246netdev_vport_construct(struct netdev *netdev_)
2b9d6589 247{
a36de779
PS
248 struct netdev_vport *dev = netdev_vport_cast(netdev_);
249 const char *type = netdev_get_type(netdev_);
6d9e6eb4 250
a36de779
PS
251 ovs_mutex_init(&dev->mutex);
252 eth_addr_random(dev->etheraddr);
253
254 /* Add a default destination port for tunnel ports if none specified. */
255 if (!strcmp(type, "geneve")) {
256 dev->tnl_cfg.dst_port = htons(GENEVE_DST_PORT);
257 } else if (!strcmp(type, "vxlan")) {
258 dev->tnl_cfg.dst_port = htons(VXLAN_DST_PORT);
259 } else if (!strcmp(type, "lisp")) {
260 dev->tnl_cfg.dst_port = htons(LISP_DST_PORT);
4237026e
PS
261 } else if (!strcmp(type, "stt")) {
262 dev->tnl_cfg.dst_port = htons(STT_DST_PORT);
a36de779 263 }
6d9e6eb4 264
0890056e
PS
265 dev->tnl_cfg.dont_fragment = true;
266 dev->tnl_cfg.ttl = DEFAULT_TTL;
de5cdb90 267 return 0;
777ece09
JG
268}
269
2b9d6589 270static void
9dc63482 271netdev_vport_destruct(struct netdev *netdev_)
2b9d6589 272{
b5d57fc8 273 struct netdev_vport *netdev = netdev_vport_cast(netdev_);
2b9d6589 274
b5d57fc8 275 free(netdev->peer);
86383816 276 ovs_mutex_destroy(&netdev->mutex);
9dc63482
BP
277}
278
279static void
280netdev_vport_dealloc(struct netdev *netdev_)
281{
282 struct netdev_vport *netdev = netdev_vport_cast(netdev_);
2b9d6589
BP
283 free(netdev);
284}
285
2b9d6589 286static int
b5d57fc8 287netdev_vport_set_etheraddr(struct netdev *netdev_,
777ece09
JG
288 const uint8_t mac[ETH_ADDR_LEN])
289{
b5d57fc8 290 struct netdev_vport *netdev = netdev_vport_cast(netdev_);
86383816
BP
291
292 ovs_mutex_lock(&netdev->mutex);
b5d57fc8 293 memcpy(netdev->etheraddr, mac, ETH_ADDR_LEN);
86383816 294 ovs_mutex_unlock(&netdev->mutex);
3e912ffc 295 netdev_change_seq_changed(netdev_);
86383816 296
35b769cb 297 return 0;
777ece09
JG
298}
299
2b9d6589 300static int
86383816 301netdev_vport_get_etheraddr(const struct netdev *netdev_,
777ece09
JG
302 uint8_t mac[ETH_ADDR_LEN])
303{
86383816
BP
304 struct netdev_vport *netdev = netdev_vport_cast(netdev_);
305
306 ovs_mutex_lock(&netdev->mutex);
307 memcpy(mac, netdev->etheraddr, ETH_ADDR_LEN);
308 ovs_mutex_unlock(&netdev->mutex);
309
35b769cb 310 return 0;
777ece09
JG
311}
312
41ca1e0a
AW
313/* Checks if the tunnel status has changed and returns a boolean.
314 * Updates the tunnel status if it has changed. */
315static bool
316tunnel_check_status_change__(struct netdev_vport *netdev)
317 OVS_REQUIRES(netdev->mutex)
ea763e0e 318{
3dea0874 319 char iface[IFNAMSIZ];
41ca1e0a 320 bool status = false;
275707c3 321 ovs_be32 route;
d9b4ebc5 322 ovs_be32 gw;
ea763e0e 323
41ca1e0a 324 iface[0] = '\0';
86383816 325 route = netdev->tnl_cfg.ip_dst;
d9b4ebc5 326 if (ovs_router_lookup(route, iface, &gw)) {
a404826e
AE
327 struct netdev *egress_netdev;
328
18812dff 329 if (!netdev_open(iface, "system", &egress_netdev)) {
41ca1e0a 330 status = netdev_get_carrier(egress_netdev);
a404826e
AE
331 netdev_close(egress_netdev);
332 }
ea763e0e
EJ
333 }
334
41ca1e0a
AW
335 if (strcmp(netdev->egress_iface, iface)
336 || netdev->carrier_status != status) {
337 ovs_strlcpy(netdev->egress_iface, iface, IFNAMSIZ);
338 netdev->carrier_status = status;
339
340 return true;
341 }
342
343 return false;
344}
345
346static int
347tunnel_get_status(const struct netdev *netdev_, struct smap *smap)
348{
349 struct netdev_vport *netdev = netdev_vport_cast(netdev_);
350
351 if (netdev->egress_iface[0]) {
352 smap_add(smap, "tunnel_egress_iface", netdev->egress_iface);
353
354 smap_add(smap, "tunnel_egress_iface_carrier",
355 netdev->carrier_status ? "up" : "down");
356 }
357
ea763e0e
EJ
358 return 0;
359}
360
2b9d6589 361static int
b5d57fc8
BP
362netdev_vport_update_flags(struct netdev *netdev OVS_UNUSED,
363 enum netdev_flags off,
364 enum netdev_flags on OVS_UNUSED,
365 enum netdev_flags *old_flagsp)
777ece09
JG
366{
367 if (off & (NETDEV_UP | NETDEV_PROMISC)) {
368 return EOPNOTSUPP;
369 }
370
371 *old_flagsp = NETDEV_UP | NETDEV_PROMISC;
372 return 0;
373}
374
ea83a2fc
EJ
375static void
376netdev_vport_run(void)
377{
41ca1e0a
AW
378 uint64_t seq;
379
a132aa96 380 route_table_run();
41ca1e0a
AW
381 seq = route_table_get_change_seq();
382 if (rt_change_seqno != seq) {
383 rt_change_seqno = seq;
384 netdev_vport_route_changed();
385 }
ea83a2fc
EJ
386}
387
388static void
389netdev_vport_wait(void)
390{
41ca1e0a
AW
391 uint64_t seq;
392
a132aa96 393 route_table_wait();
41ca1e0a
AW
394 seq = route_table_get_change_seq();
395 if (rt_change_seqno != seq) {
396 poll_immediate_wake();
397 }
ea83a2fc
EJ
398}
399\f
0a740f48 400/* Code specific to tunnel types. */
2b9d6589 401
f431bf7d
EJ
402static ovs_be64
403parse_key(const struct smap *args, const char *name,
404 bool *present, bool *flow)
c19e6535
BP
405{
406 const char *s;
407
f431bf7d
EJ
408 *present = false;
409 *flow = false;
410
79f1cbe9 411 s = smap_get(args, name);
c19e6535 412 if (!s) {
79f1cbe9 413 s = smap_get(args, "key");
c19e6535 414 if (!s) {
f431bf7d 415 return 0;
c19e6535
BP
416 }
417 }
418
f431bf7d
EJ
419 *present = true;
420
c19e6535 421 if (!strcmp(s, "flow")) {
f431bf7d
EJ
422 *flow = true;
423 return 0;
c19e6535 424 } else {
f431bf7d 425 return htonll(strtoull(s, NULL, 0));
c19e6535
BP
426 }
427}
428
2b9d6589 429static int
b5d57fc8 430set_tunnel_config(struct netdev *dev_, const struct smap *args)
2b9d6589 431{
b5d57fc8
BP
432 struct netdev_vport *dev = netdev_vport_cast(dev_);
433 const char *name = netdev_get_name(dev_);
434 const char *type = netdev_get_type(dev_);
f431bf7d
EJ
435 bool ipsec_mech_set, needs_dst_port, has_csum;
436 struct netdev_tunnel_config tnl_cfg;
79f1cbe9 437 struct smap_node *node;
f431bf7d 438
4752cc0c 439 has_csum = strstr(type, "gre") || strstr(type, "geneve") ||
4237026e 440 strstr(type, "stt") || strstr(type, "vxlan");
f431bf7d
EJ
441 ipsec_mech_set = false;
442 memset(&tnl_cfg, 0, sizeof tnl_cfg);
2b9d6589 443
a36de779
PS
444 /* Add a default destination port for tunnel ports if none specified. */
445 if (!strcmp(type, "geneve")) {
446 tnl_cfg.dst_port = htons(GENEVE_DST_PORT);
447 }
448
449 if (!strcmp(type, "vxlan")) {
450 tnl_cfg.dst_port = htons(VXLAN_DST_PORT);
451 }
452
453 if (!strcmp(type, "lisp")) {
454 tnl_cfg.dst_port = htons(LISP_DST_PORT);
455 }
456
4237026e
PS
457 if (!strcmp(type, "stt")) {
458 tnl_cfg.dst_port = htons(STT_DST_PORT);
459 }
460
a6ae068b 461 needs_dst_port = netdev_vport_needs_dst_port(dev_);
f431bf7d 462 tnl_cfg.ipsec = strstr(type, "ipsec");
f431bf7d 463 tnl_cfg.dont_fragment = true;
e16a28b5 464
79f1cbe9
EJ
465 SMAP_FOR_EACH (node, args) {
466 if (!strcmp(node->key, "remote_ip")) {
2b9d6589 467 struct in_addr in_addr;
0ad90c84
JR
468 if (!strcmp(node->value, "flow")) {
469 tnl_cfg.ip_dst_flow = true;
470 tnl_cfg.ip_dst = htonl(0);
471 } else if (lookup_ip(node->value, &in_addr)) {
c3827f61 472 VLOG_WARN("%s: bad %s 'remote_ip'", name, type);
85c9de19
PS
473 } else if (ip_is_multicast(in_addr.s_addr)) {
474 VLOG_WARN("%s: multicast remote_ip="IP_FMT" not allowed",
475 name, IP_ARGS(in_addr.s_addr));
476 return EINVAL;
2b9d6589 477 } else {
f431bf7d 478 tnl_cfg.ip_dst = in_addr.s_addr;
2b9d6589 479 }
79f1cbe9 480 } else if (!strcmp(node->key, "local_ip")) {
2b9d6589 481 struct in_addr in_addr;
0ad90c84
JR
482 if (!strcmp(node->value, "flow")) {
483 tnl_cfg.ip_src_flow = true;
484 tnl_cfg.ip_src = htonl(0);
485 } else if (lookup_ip(node->value, &in_addr)) {
c3827f61 486 VLOG_WARN("%s: bad %s 'local_ip'", name, type);
2b9d6589 487 } else {
f431bf7d 488 tnl_cfg.ip_src = in_addr.s_addr;
2b9d6589 489 }
79f1cbe9
EJ
490 } else if (!strcmp(node->key, "tos")) {
491 if (!strcmp(node->value, "inherit")) {
f431bf7d 492 tnl_cfg.tos_inherit = true;
2b9d6589 493 } else {
3fca7064
PS
494 char *endptr;
495 int tos;
79f1cbe9 496 tos = strtol(node->value, &endptr, 0);
91aff446 497 if (*endptr == '\0' && tos == (tos & IP_DSCP_MASK)) {
f431bf7d 498 tnl_cfg.tos = tos;
91aff446
BP
499 } else {
500 VLOG_WARN("%s: invalid TOS %s", name, node->value);
3fca7064 501 }
2b9d6589 502 }
79f1cbe9
EJ
503 } else if (!strcmp(node->key, "ttl")) {
504 if (!strcmp(node->value, "inherit")) {
f431bf7d 505 tnl_cfg.ttl_inherit = true;
2b9d6589 506 } else {
f431bf7d 507 tnl_cfg.ttl = atoi(node->value);
2b9d6589 508 }
79f827fa 509 } else if (!strcmp(node->key, "dst_port") && needs_dst_port) {
f431bf7d 510 tnl_cfg.dst_port = htons(atoi(node->value));
f431bf7d 511 } else if (!strcmp(node->key, "csum") && has_csum) {
79f1cbe9 512 if (!strcmp(node->value, "true")) {
f431bf7d 513 tnl_cfg.csum = true;
2b9d6589 514 }
79f1cbe9
EJ
515 } else if (!strcmp(node->key, "df_default")) {
516 if (!strcmp(node->value, "false")) {
f431bf7d 517 tnl_cfg.dont_fragment = false;
66409d1b 518 }
f431bf7d 519 } else if (!strcmp(node->key, "peer_cert") && tnl_cfg.ipsec) {
79f1cbe9 520 if (smap_get(args, "certificate")) {
3c52fa7b
JP
521 ipsec_mech_set = true;
522 } else {
ef7ee76a
JP
523 const char *use_ssl_cert;
524
525 /* If the "use_ssl_cert" is true, then "certificate" and
526 * "private_key" will be pulled from the SSL table. The
527 * use of this option is strongly discouraged, since it
528 * will like be removed when multiple SSL configurations
529 * are supported by OVS.
530 */
79f1cbe9 531 use_ssl_cert = smap_get(args, "use_ssl_cert");
ef7ee76a 532 if (!use_ssl_cert || strcmp(use_ssl_cert, "true")) {
8283e514
JP
533 VLOG_ERR("%s: 'peer_cert' requires 'certificate' argument",
534 name);
b9ad7294 535 return EINVAL;
ef7ee76a
JP
536 }
537 ipsec_mech_set = true;
3c52fa7b 538 }
f431bf7d 539 } else if (!strcmp(node->key, "psk") && tnl_cfg.ipsec) {
2b9d6589 540 ipsec_mech_set = true;
f431bf7d 541 } else if (tnl_cfg.ipsec
79f1cbe9
EJ
542 && (!strcmp(node->key, "certificate")
543 || !strcmp(node->key, "private_key")
544 || !strcmp(node->key, "use_ssl_cert"))) {
3c52fa7b 545 /* Ignore options not used by the netdev. */
79f1cbe9
EJ
546 } else if (!strcmp(node->key, "key") ||
547 !strcmp(node->key, "in_key") ||
548 !strcmp(node->key, "out_key")) {
c19e6535 549 /* Handled separately below. */
526df7d8
TG
550 } else if (!strcmp(node->key, "exts")) {
551 char *str = xstrdup(node->value);
552 char *ext, *save_ptr = NULL;
553
554 tnl_cfg.exts = 0;
555
556 ext = strtok_r(str, ",", &save_ptr);
557 while (ext) {
558 if (!strcmp(type, "vxlan") && !strcmp(ext, "gbp")) {
559 tnl_cfg.exts |= (1 << OVS_VXLAN_EXT_GBP);
560 } else {
561 VLOG_WARN("%s: unknown extension '%s'", name, ext);
562 }
563
564 ext = strtok_r(NULL, ",", &save_ptr);
565 }
566
567 free(str);
2b9d6589 568 } else {
79f1cbe9 569 VLOG_WARN("%s: unknown %s argument '%s'", name, type, node->key);
2b9d6589
BP
570 }
571 }
572
f431bf7d 573 if (tnl_cfg.ipsec) {
9366380a 574 static struct ovs_mutex mutex = OVS_MUTEX_INITIALIZER;
2a586a5c 575 static pid_t pid = 0;
6027d03d 576
c89809c9 577#ifndef _WIN32
9366380a 578 ovs_mutex_lock(&mutex);
900f7601 579 if (pid <= 0) {
2a586a5c
AS
580 char *file_name = xasprintf("%s/%s", ovs_rundir(),
581 "ovs-monitor-ipsec.pid");
582 pid = read_pidfile(file_name);
583 free(file_name);
584 }
9366380a 585 ovs_mutex_unlock(&mutex);
c89809c9 586#endif
2a586a5c 587
e7009c36 588 if (pid < 0) {
8283e514
JP
589 VLOG_ERR("%s: IPsec requires the ovs-monitor-ipsec daemon",
590 name);
b9ad7294 591 return EINVAL;
e7009c36 592 }
5059eff3 593
79f1cbe9 594 if (smap_get(args, "peer_cert") && smap_get(args, "psk")) {
8283e514 595 VLOG_ERR("%s: cannot define both 'peer_cert' and 'psk'", name);
b9ad7294 596 return EINVAL;
3c52fa7b
JP
597 }
598
599 if (!ipsec_mech_set) {
8283e514
JP
600 VLOG_ERR("%s: IPsec requires an 'peer_cert' or psk' argument",
601 name);
b9ad7294 602 return EINVAL;
3c52fa7b 603 }
2b9d6589
BP
604 }
605
0ad90c84 606 if (!tnl_cfg.ip_dst && !tnl_cfg.ip_dst_flow) {
8283e514
JP
607 VLOG_ERR("%s: %s type requires valid 'remote_ip' argument",
608 name, type);
b9ad7294 609 return EINVAL;
2b9d6589 610 }
0ad90c84
JR
611 if (tnl_cfg.ip_src_flow && !tnl_cfg.ip_dst_flow) {
612 VLOG_ERR("%s: %s type requires 'remote_ip=flow' with 'local_ip=flow'",
613 name, type);
614 return EINVAL;
615 }
f431bf7d
EJ
616 if (!tnl_cfg.ttl) {
617 tnl_cfg.ttl = DEFAULT_TTL;
618 }
619
620 tnl_cfg.in_key = parse_key(args, "in_key",
621 &tnl_cfg.in_key_present,
622 &tnl_cfg.in_key_flow);
f431bf7d
EJ
623
624 tnl_cfg.out_key = parse_key(args, "out_key",
625 &tnl_cfg.out_key_present,
626 &tnl_cfg.out_key_flow);
2b9d6589 627
86383816 628 ovs_mutex_lock(&dev->mutex);
a1908399
AW
629 if (memcmp(&dev->tnl_cfg, &tnl_cfg, sizeof tnl_cfg)) {
630 dev->tnl_cfg = tnl_cfg;
631 tunnel_check_status_change__(dev);
632 netdev_change_seq_changed(dev_);
633 }
86383816 634 ovs_mutex_unlock(&dev->mutex);
f431bf7d 635
c19e6535
BP
636 return 0;
637}
638
2b9d6589 639static int
b5d57fc8 640get_tunnel_config(const struct netdev *dev, struct smap *args)
6d9e6eb4 641{
86383816
BP
642 struct netdev_vport *netdev = netdev_vport_cast(dev);
643 struct netdev_tunnel_config tnl_cfg;
644
645 ovs_mutex_lock(&netdev->mutex);
646 tnl_cfg = netdev->tnl_cfg;
647 ovs_mutex_unlock(&netdev->mutex);
6d9e6eb4 648
86383816
BP
649 if (tnl_cfg.ip_dst) {
650 smap_add_format(args, "remote_ip", IP_FMT, IP_ARGS(tnl_cfg.ip_dst));
651 } else if (tnl_cfg.ip_dst_flow) {
0ad90c84 652 smap_add(args, "remote_ip", "flow");
0a740f48
EJ
653 }
654
86383816
BP
655 if (tnl_cfg.ip_src) {
656 smap_add_format(args, "local_ip", IP_FMT, IP_ARGS(tnl_cfg.ip_src));
657 } else if (tnl_cfg.ip_src_flow) {
0ad90c84 658 smap_add(args, "local_ip", "flow");
7f804ea5 659 }
c19e6535 660
86383816 661 if (tnl_cfg.in_key_flow && tnl_cfg.out_key_flow) {
6d9e6eb4 662 smap_add(args, "key", "flow");
86383816
BP
663 } else if (tnl_cfg.in_key_present && tnl_cfg.out_key_present
664 && tnl_cfg.in_key == tnl_cfg.out_key) {
665 smap_add_format(args, "key", "%"PRIu64, ntohll(tnl_cfg.in_key));
6d9e6eb4 666 } else {
86383816 667 if (tnl_cfg.in_key_flow) {
b9ad7294 668 smap_add(args, "in_key", "flow");
86383816 669 } else if (tnl_cfg.in_key_present) {
b9ad7294 670 smap_add_format(args, "in_key", "%"PRIu64,
86383816 671 ntohll(tnl_cfg.in_key));
b9ad7294 672 }
6d9e6eb4 673
86383816 674 if (tnl_cfg.out_key_flow) {
b9ad7294 675 smap_add(args, "out_key", "flow");
86383816 676 } else if (tnl_cfg.out_key_present) {
b9ad7294 677 smap_add_format(args, "out_key", "%"PRIu64,
86383816 678 ntohll(tnl_cfg.out_key));
6d9e6eb4
BP
679 }
680 }
681
86383816 682 if (tnl_cfg.ttl_inherit) {
62827e6a 683 smap_add(args, "ttl", "inherit");
86383816
BP
684 } else if (tnl_cfg.ttl != DEFAULT_TTL) {
685 smap_add_format(args, "ttl", "%"PRIu8, tnl_cfg.ttl);
c19e6535
BP
686 }
687
86383816 688 if (tnl_cfg.tos_inherit) {
6d9e6eb4 689 smap_add(args, "tos", "inherit");
86383816
BP
690 } else if (tnl_cfg.tos) {
691 smap_add_format(args, "tos", "0x%x", tnl_cfg.tos);
6d9e6eb4
BP
692 }
693
86383816
BP
694 if (tnl_cfg.dst_port) {
695 uint16_t dst_port = ntohs(tnl_cfg.dst_port);
b5d57fc8 696 const char *type = netdev_get_type(dev);
9eeb949b 697
c1fc1411
JG
698 if ((!strcmp("geneve", type) && dst_port != GENEVE_DST_PORT) ||
699 (!strcmp("vxlan", type) && dst_port != VXLAN_DST_PORT) ||
4237026e
PS
700 (!strcmp("lisp", type) && dst_port != LISP_DST_PORT) ||
701 (!strcmp("stt", type) && dst_port != STT_DST_PORT)) {
79f827fa
KM
702 smap_add_format(args, "dst_port", "%d", dst_port);
703 }
704 }
705
86383816 706 if (tnl_cfg.csum) {
6d9e6eb4
BP
707 smap_add(args, "csum", "true");
708 }
8a9ff93a 709
86383816 710 if (!tnl_cfg.dont_fragment) {
66409d1b
AE
711 smap_add(args, "df_default", "false");
712 }
6d9e6eb4
BP
713
714 return 0;
715}
0a740f48
EJ
716\f
717/* Code specific to patch ports. */
718
161b6042
BP
719/* If 'netdev' is a patch port, returns the name of its peer as a malloc()'d
720 * string that the caller must free.
721 *
722 * If 'netdev' is not a patch port, returns NULL. */
723char *
724netdev_vport_patch_peer(const struct netdev *netdev_)
0a740f48 725{
161b6042
BP
726 char *peer = NULL;
727
728 if (netdev_vport_is_patch(netdev_)) {
729 struct netdev_vport *netdev = netdev_vport_cast(netdev_);
86383816
BP
730
731 ovs_mutex_lock(&netdev->mutex);
161b6042
BP
732 if (netdev->peer) {
733 peer = xstrdup(netdev->peer);
734 }
86383816 735 ovs_mutex_unlock(&netdev->mutex);
161b6042
BP
736 }
737
738 return peer;
0a740f48
EJ
739}
740
741void
b9ad7294 742netdev_vport_inc_rx(const struct netdev *netdev,
9e04d6f6 743 const struct dpif_flow_stats *stats)
0a740f48 744{
b5d57fc8
BP
745 if (is_vport_class(netdev_get_class(netdev))) {
746 struct netdev_vport *dev = netdev_vport_cast(netdev);
86383816
BP
747
748 ovs_mutex_lock(&dev->mutex);
0a740f48
EJ
749 dev->stats.rx_packets += stats->n_packets;
750 dev->stats.rx_bytes += stats->n_bytes;
86383816 751 ovs_mutex_unlock(&dev->mutex);
0a740f48
EJ
752 }
753}
754
755void
b9ad7294
EJ
756netdev_vport_inc_tx(const struct netdev *netdev,
757 const struct dpif_flow_stats *stats)
0a740f48 758{
b5d57fc8
BP
759 if (is_vport_class(netdev_get_class(netdev))) {
760 struct netdev_vport *dev = netdev_vport_cast(netdev);
86383816
BP
761
762 ovs_mutex_lock(&dev->mutex);
0a740f48
EJ
763 dev->stats.tx_packets += stats->n_packets;
764 dev->stats.tx_bytes += stats->n_bytes;
86383816 765 ovs_mutex_unlock(&dev->mutex);
0a740f48
EJ
766 }
767}
768
769static int
b5d57fc8 770get_patch_config(const struct netdev *dev_, struct smap *args)
0a740f48 771{
b5d57fc8 772 struct netdev_vport *dev = netdev_vport_cast(dev_);
0a740f48 773
86383816 774 ovs_mutex_lock(&dev->mutex);
0a740f48
EJ
775 if (dev->peer) {
776 smap_add(args, "peer", dev->peer);
777 }
86383816
BP
778 ovs_mutex_unlock(&dev->mutex);
779
0a740f48
EJ
780 return 0;
781}
6d9e6eb4
BP
782
783static int
b5d57fc8 784set_patch_config(struct netdev *dev_, const struct smap *args)
2b9d6589 785{
b5d57fc8
BP
786 struct netdev_vport *dev = netdev_vport_cast(dev_);
787 const char *name = netdev_get_name(dev_);
2b9d6589
BP
788 const char *peer;
789
79f1cbe9 790 peer = smap_get(args, "peer");
2b9d6589 791 if (!peer) {
8283e514 792 VLOG_ERR("%s: patch type requires valid 'peer' argument", name);
2b9d6589
BP
793 return EINVAL;
794 }
795
79f1cbe9 796 if (smap_count(args) > 1) {
8283e514 797 VLOG_ERR("%s: patch type takes only a 'peer' argument", name);
2b9d6589
BP
798 return EINVAL;
799 }
800
2b9d6589 801 if (!strcmp(name, peer)) {
8283e514 802 VLOG_ERR("%s: patch peer must not be self", name);
2b9d6589
BP
803 return EINVAL;
804 }
805
86383816 806 ovs_mutex_lock(&dev->mutex);
a1908399
AW
807 if (!dev->peer || strcmp(dev->peer, peer)) {
808 free(dev->peer);
809 dev->peer = xstrdup(peer);
810 netdev_change_seq_changed(dev_);
811 }
86383816
BP
812 ovs_mutex_unlock(&dev->mutex);
813
2b9d6589
BP
814 return 0;
815}
6d9e6eb4
BP
816
817static int
b9ad7294 818get_stats(const struct netdev *netdev, struct netdev_stats *stats)
0a740f48 819{
b5d57fc8 820 struct netdev_vport *dev = netdev_vport_cast(netdev);
86383816
BP
821
822 ovs_mutex_lock(&dev->mutex);
823 *stats = dev->stats;
824 ovs_mutex_unlock(&dev->mutex);
825
6d9e6eb4
BP
826 return 0;
827}
a36de779
PS
828
829\f
830/* Tunnel push pop ops. */
831
832static struct ip_header *
833ip_hdr(void *eth)
834{
835 return (void *)((char *)eth + sizeof (struct eth_header));
836}
837
838static struct gre_base_hdr *
839gre_hdr(struct ip_header *ip)
840{
841 return (void *)((char *)ip + sizeof (struct ip_header));
842}
843
844static void *
cf62fa4c 845ip_extract_tnl_md(struct dp_packet *packet, struct flow_tnl *tnl)
a36de779
PS
846{
847 struct ip_header *nh;
848 void *l4;
849
cf62fa4c
PS
850 nh = dp_packet_l3(packet);
851 l4 = dp_packet_l4(packet);
a36de779
PS
852
853 if (!nh || !l4) {
854 return NULL;
855 }
856
857 tnl->ip_src = get_16aligned_be32(&nh->ip_src);
858 tnl->ip_dst = get_16aligned_be32(&nh->ip_dst);
859 tnl->ip_tos = nh->ip_tos;
66252457 860 tnl->ip_ttl = nh->ip_ttl;
a36de779
PS
861
862 return l4;
863}
864
865/* Pushes the 'size' bytes of 'header' into the headroom of 'packet',
866 * reallocating the packet if necessary. 'header' should contain an Ethernet
867 * header, followed by an IPv4 header (without options), and an L4 header.
868 *
869 * This function sets the IP header's ip_tot_len field (which should be zeroed
870 * as part of 'header') and puts its value into '*ip_tot_size' as well. Also
871 * updates IP header checksum.
872 *
873 * Return pointer to the L4 header added to 'packet'. */
874static void *
cf62fa4c 875push_ip_header(struct dp_packet *packet,
a36de779
PS
876 const void *header, int size, int *ip_tot_size)
877{
878 struct eth_header *eth;
879 struct ip_header *ip;
880
cf62fa4c
PS
881 eth = dp_packet_push_uninit(packet, size);
882 *ip_tot_size = dp_packet_size(packet) - sizeof (struct eth_header);
a36de779
PS
883
884 memcpy(eth, header, size);
885 ip = ip_hdr(eth);
886 ip->ip_tot_len = htons(*ip_tot_size);
887
888
889 ip->ip_csum = recalc_csum16(ip->ip_csum, 0, ip->ip_tot_len);
890
891 return ip + 1;
892}
893
e066f78f
JG
894static void *
895udp_extract_tnl_md(struct dp_packet *packet, struct flow_tnl *tnl)
896{
897 struct udp_header *udp;
898
899 udp = ip_extract_tnl_md(packet, tnl);
900 if (!udp) {
901 return NULL;
902 }
903
8e45fe7c
JG
904 if (udp->udp_csum) {
905 uint32_t csum = packet_csum_pseudoheader(dp_packet_l3(packet));
906
907 csum = csum_continue(csum, udp, dp_packet_size(packet) -
908 ((const unsigned char *)udp -
909 (const unsigned char *)dp_packet_l2(packet)));
910 if (csum_finish(csum)) {
911 return NULL;
912 }
913 tnl->flags |= FLOW_TNL_F_CSUM;
914 }
915
e066f78f
JG
916 tnl->tp_src = udp->udp_src;
917 tnl->tp_dst = udp->udp_dst;
918
919 return udp + 1;
920}
921
922static ovs_be16
923get_src_port(struct dp_packet *packet)
924{
925 uint32_t hash;
926
2bc1bbd2 927 hash = dp_packet_get_rss_hash(packet);
e066f78f
JG
928
929 return htons((((uint64_t) hash * (tnl_udp_port_max - tnl_udp_port_min)) >> 32) +
930 tnl_udp_port_min);
931}
932
d625fbd1
JG
933static void
934push_udp_header(struct dp_packet *packet,
935 const struct ovs_action_push_tnl *data)
e066f78f
JG
936{
937 struct udp_header *udp;
938 int ip_tot_size;
939
d625fbd1 940 udp = push_ip_header(packet, data->header, data->header_len, &ip_tot_size);
e066f78f
JG
941
942 /* set udp src port */
943 udp->udp_src = get_src_port(packet);
944 udp->udp_len = htons(ip_tot_size - sizeof (struct ip_header));
8e45fe7c
JG
945
946 if (udp->udp_csum) {
947 uint32_t csum = packet_csum_pseudoheader(ip_hdr(dp_packet_data(packet)));
948
949 csum = csum_continue(csum, udp,
950 ip_tot_size - sizeof (struct ip_header));
951 udp->udp_csum = csum_finish(csum);
952
953 if (!udp->udp_csum) {
954 udp->udp_csum = htons(0xffff);
955 }
956 }
e066f78f
JG
957}
958
959static void *
960udp_build_header(struct netdev_tunnel_config *tnl_cfg,
8e45fe7c 961 const struct flow *tnl_flow,
e066f78f
JG
962 struct ovs_action_push_tnl *data)
963{
964 struct ip_header *ip;
965 struct udp_header *udp;
966
967 ip = ip_hdr(data->header);
968 ip->ip_proto = IPPROTO_UDP;
969
970 udp = (struct udp_header *) (ip + 1);
971 udp->udp_dst = tnl_cfg->dst_port;
972
8e45fe7c
JG
973 if (tnl_flow->tunnel.flags & FLOW_TNL_F_CSUM) {
974 /* Write a value in now to mark that we should compute the checksum
975 * later. 0xffff is handy because it is transparent to the
976 * calculation. */
977 udp->udp_csum = htons(0xffff);
978 }
979
e066f78f
JG
980 return udp + 1;
981}
982
a36de779
PS
983static int
984gre_header_len(ovs_be16 flags)
985{
986 int hlen = sizeof(struct eth_header) +
987 sizeof(struct ip_header) + 4;
988
989 if (flags & htons(GRE_CSUM)) {
990 hlen += 4;
991 }
992 if (flags & htons(GRE_KEY)) {
993 hlen += 4;
994 }
995 if (flags & htons(GRE_SEQ)) {
996 hlen += 4;
997 }
998 return hlen;
999}
1000
1001static int
cf62fa4c 1002parse_gre_header(struct dp_packet *packet,
a36de779
PS
1003 struct flow_tnl *tnl)
1004{
1005 const struct gre_base_hdr *greh;
1006 ovs_16aligned_be32 *options;
1007 int hlen;
1008
1009 greh = ip_extract_tnl_md(packet, tnl);
1010 if (!greh) {
1011 return -EINVAL;
1012 }
1013
1014 if (greh->flags & ~(htons(GRE_CSUM | GRE_KEY | GRE_SEQ))) {
1015 return -EINVAL;
1016 }
1017
6432e527
JG
1018 if (greh->protocol != htons(ETH_TYPE_TEB)) {
1019 return -EINVAL;
1020 }
1021
a36de779 1022 hlen = gre_header_len(greh->flags);
cf62fa4c 1023 if (hlen > dp_packet_size(packet)) {
a36de779
PS
1024 return -EINVAL;
1025 }
1026
1027 options = (ovs_16aligned_be32 *)(greh + 1);
1028 if (greh->flags & htons(GRE_CSUM)) {
1029 ovs_be16 pkt_csum;
1030
cf62fa4c 1031 pkt_csum = csum(greh, dp_packet_size(packet) -
a36de779 1032 ((const unsigned char *)greh -
cf62fa4c 1033 (const unsigned char *)dp_packet_l2(packet)));
a36de779
PS
1034 if (pkt_csum) {
1035 return -EINVAL;
1036 }
1037 tnl->flags = FLOW_TNL_F_CSUM;
1038 options++;
1039 }
1040
1041 if (greh->flags & htons(GRE_KEY)) {
1042 tnl->tun_id = (OVS_FORCE ovs_be64) ((OVS_FORCE uint64_t)(get_16aligned_be32(options)) << 32);
1043 tnl->flags |= FLOW_TNL_F_KEY;
1044 options++;
1045 }
1046
1047 if (greh->flags & htons(GRE_SEQ)) {
1048 options++;
1049 }
1050
1051 return hlen;
1052}
1053
d625fbd1
JG
1054static int
1055netdev_gre_pop_header(struct dp_packet *packet)
a36de779 1056{
cf62fa4c 1057 struct pkt_metadata *md = &packet->md;
a36de779
PS
1058 struct flow_tnl *tnl = &md->tunnel;
1059 int hlen = sizeof(struct eth_header) +
1060 sizeof(struct ip_header) + 4;
1061
1062 memset(md, 0, sizeof *md);
cf62fa4c 1063 if (hlen > dp_packet_size(packet)) {
d625fbd1 1064 return EINVAL;
a36de779
PS
1065 }
1066
1067 hlen = parse_gre_header(packet, tnl);
1068 if (hlen < 0) {
d625fbd1 1069 return -hlen;
a36de779
PS
1070 }
1071
cf62fa4c 1072 dp_packet_reset_packet(packet, hlen);
a36de779 1073
a36de779
PS
1074 return 0;
1075}
1076
1077static void
d625fbd1
JG
1078netdev_gre_push_header(struct dp_packet *packet,
1079 const struct ovs_action_push_tnl *data)
a36de779
PS
1080{
1081 struct gre_base_hdr *greh;
1082 int ip_tot_size;
1083
d625fbd1 1084 greh = push_ip_header(packet, data->header, data->header_len, &ip_tot_size);
a36de779
PS
1085
1086 if (greh->flags & htons(GRE_CSUM)) {
d804d31e
JG
1087 ovs_be16 *csum_opt = (ovs_be16 *) (greh + 1);
1088 *csum_opt = csum(greh, ip_tot_size - sizeof (struct ip_header));
a36de779
PS
1089 }
1090}
1091
a36de779
PS
1092static int
1093netdev_gre_build_header(const struct netdev *netdev,
c876a4bb
RL
1094 struct ovs_action_push_tnl *data,
1095 const struct flow *tnl_flow)
a36de779
PS
1096{
1097 struct netdev_vport *dev = netdev_vport_cast(netdev);
1098 struct netdev_tunnel_config *tnl_cfg;
1099 struct ip_header *ip;
1100 struct gre_base_hdr *greh;
1101 ovs_16aligned_be32 *options;
1102 int hlen;
1103
1104 /* XXX: RCUfy tnl_cfg. */
1105 ovs_mutex_lock(&dev->mutex);
1106 tnl_cfg = &dev->tnl_cfg;
1107
1108 ip = ip_hdr(data->header);
1109 ip->ip_proto = IPPROTO_GRE;
1110
1111 greh = gre_hdr(ip);
1112 greh->protocol = htons(ETH_TYPE_TEB);
1113 greh->flags = 0;
1114
1115 options = (ovs_16aligned_be32 *) (greh + 1);
61cf6b70 1116 if (tnl_flow->tunnel.flags & FLOW_TNL_F_CSUM) {
a36de779
PS
1117 greh->flags |= htons(GRE_CSUM);
1118 put_16aligned_be32(options, 0);
1119 options++;
1120 }
1121
1122 if (tnl_cfg->out_key_present) {
1123 greh->flags |= htons(GRE_KEY);
1124 put_16aligned_be32(options, (OVS_FORCE ovs_be32)
c876a4bb 1125 ((OVS_FORCE uint64_t) tnl_flow->tunnel.tun_id >> 32));
a36de779
PS
1126 options++;
1127 }
1128
1129 ovs_mutex_unlock(&dev->mutex);
1130
1131 hlen = (uint8_t *) options - (uint8_t *) greh;
1132
1133 data->header_len = sizeof(struct eth_header) +
1134 sizeof(struct ip_header) + hlen;
1135 data->tnl_type = OVS_VPORT_TYPE_GRE;
1136 return 0;
1137}
1138
d625fbd1
JG
1139static int
1140netdev_vxlan_pop_header(struct dp_packet *packet)
a36de779 1141{
cf62fa4c 1142 struct pkt_metadata *md = &packet->md;
a36de779 1143 struct flow_tnl *tnl = &md->tunnel;
a36de779
PS
1144 struct vxlanhdr *vxh;
1145
1146 memset(md, 0, sizeof *md);
cf62fa4c 1147 if (VXLAN_HLEN > dp_packet_size(packet)) {
d625fbd1 1148 return EINVAL;
a36de779
PS
1149 }
1150
e066f78f
JG
1151 vxh = udp_extract_tnl_md(packet, tnl);
1152 if (!vxh) {
d625fbd1 1153 return EINVAL;
a36de779 1154 }
a36de779
PS
1155
1156 if (get_16aligned_be32(&vxh->vx_flags) != htonl(VXLAN_FLAGS) ||
1157 (get_16aligned_be32(&vxh->vx_vni) & htonl(0xff))) {
1158 VLOG_WARN_RL(&err_rl, "invalid vxlan flags=%#x vni=%#x\n",
1159 ntohl(get_16aligned_be32(&vxh->vx_flags)),
1160 ntohl(get_16aligned_be32(&vxh->vx_vni)));
d625fbd1 1161 return EINVAL;
a36de779 1162 }
a36de779 1163 tnl->tun_id = htonll(ntohl(get_16aligned_be32(&vxh->vx_vni)) >> 8);
83fbb69b 1164 tnl->flags |= FLOW_TNL_F_KEY;
a36de779 1165
cf62fa4c 1166 dp_packet_reset_packet(packet, VXLAN_HLEN);
a36de779 1167
a36de779
PS
1168 return 0;
1169}
1170
1171static int
1172netdev_vxlan_build_header(const struct netdev *netdev,
c876a4bb
RL
1173 struct ovs_action_push_tnl *data,
1174 const struct flow *tnl_flow)
a36de779
PS
1175{
1176 struct netdev_vport *dev = netdev_vport_cast(netdev);
1177 struct netdev_tunnel_config *tnl_cfg;
a36de779
PS
1178 struct vxlanhdr *vxh;
1179
1180 /* XXX: RCUfy tnl_cfg. */
1181 ovs_mutex_lock(&dev->mutex);
1182 tnl_cfg = &dev->tnl_cfg;
1183
8e45fe7c 1184 vxh = udp_build_header(tnl_cfg, tnl_flow, data);
a36de779 1185
a36de779 1186 put_16aligned_be32(&vxh->vx_flags, htonl(VXLAN_FLAGS));
c876a4bb 1187 put_16aligned_be32(&vxh->vx_vni, htonl(ntohll(tnl_flow->tunnel.tun_id) << 8));
a36de779
PS
1188
1189 ovs_mutex_unlock(&dev->mutex);
1190 data->header_len = VXLAN_HLEN;
1191 data->tnl_type = OVS_VPORT_TYPE_VXLAN;
1192 return 0;
1193}
1194
a36de779 1195static int
d625fbd1 1196netdev_geneve_pop_header(struct dp_packet *packet)
e5a1caee
JG
1197{
1198 struct pkt_metadata *md = &packet->md;
1199 struct flow_tnl *tnl = &md->tunnel;
1200 struct genevehdr *gnh;
1201 unsigned int hlen;
1202
1203 memset(md, 0, sizeof *md);
1204 if (GENEVE_BASE_HLEN > dp_packet_size(packet)) {
1205 VLOG_WARN_RL(&err_rl, "geneve packet too small: min header=%u packet size=%u\n",
1206 (unsigned int)GENEVE_BASE_HLEN, dp_packet_size(packet));
d625fbd1 1207 return EINVAL;
e5a1caee
JG
1208 }
1209
1210 gnh = udp_extract_tnl_md(packet, tnl);
1211 if (!gnh) {
d625fbd1 1212 return EINVAL;
e5a1caee
JG
1213 }
1214
1215 hlen = GENEVE_BASE_HLEN + gnh->opt_len * 4;
1216 if (hlen > dp_packet_size(packet)) {
1217 VLOG_WARN_RL(&err_rl, "geneve packet too small: header len=%u packet size=%u\n",
1218 hlen, dp_packet_size(packet));
d625fbd1 1219 return EINVAL;
e5a1caee
JG
1220 }
1221
1222 if (gnh->ver != 0) {
1223 VLOG_WARN_RL(&err_rl, "unknown geneve version: %"PRIu8"\n", gnh->ver);
d625fbd1 1224 return EINVAL;
e5a1caee
JG
1225 }
1226
1227 if (gnh->opt_len && gnh->critical) {
1228 VLOG_WARN_RL(&err_rl, "unknown geneve critical options: %"PRIu8" bytes\n",
1229 gnh->opt_len * 4);
d625fbd1 1230 return EINVAL;
e5a1caee
JG
1231 }
1232
1233 if (gnh->proto_type != htons(ETH_TYPE_TEB)) {
1234 VLOG_WARN_RL(&err_rl, "unknown geneve encapsulated protocol: %#x\n",
1235 ntohs(gnh->proto_type));
d625fbd1 1236 return EINVAL;
e5a1caee
JG
1237 }
1238
1239 tnl->flags |= gnh->oam ? FLOW_TNL_F_OAM : 0;
1240 tnl->tun_id = htonll(ntohl(get_16aligned_be32(&gnh->vni)) >> 8);
1241 tnl->flags |= FLOW_TNL_F_KEY;
1242
1243 dp_packet_reset_packet(packet, hlen);
e5a1caee 1244
e5a1caee
JG
1245 return 0;
1246}
1247
1248static int
1249netdev_geneve_build_header(const struct netdev *netdev,
1250 struct ovs_action_push_tnl *data,
1251 const struct flow *tnl_flow)
1252{
1253 struct netdev_vport *dev = netdev_vport_cast(netdev);
1254 struct netdev_tunnel_config *tnl_cfg;
1255 struct genevehdr *gnh;
1256
1257 /* XXX: RCUfy tnl_cfg. */
1258 ovs_mutex_lock(&dev->mutex);
1259 tnl_cfg = &dev->tnl_cfg;
1260
8e45fe7c 1261 gnh = udp_build_header(tnl_cfg, tnl_flow, data);
e5a1caee
JG
1262
1263 gnh->oam = !!(tnl_flow->tunnel.flags & FLOW_TNL_F_OAM);
1264 gnh->proto_type = htons(ETH_TYPE_TEB);
1265 put_16aligned_be32(&gnh->vni, htonl(ntohll(tnl_flow->tunnel.tun_id) << 8));
1266
1267 ovs_mutex_unlock(&dev->mutex);
1268 data->header_len = GENEVE_BASE_HLEN;
1269 data->tnl_type = OVS_VPORT_TYPE_GENEVE;
1270 return 0;
1271}
1272
a36de779
PS
1273static void
1274netdev_vport_range(struct unixctl_conn *conn, int argc,
1275 const char *argv[], void *aux OVS_UNUSED)
1276{
1277 int val1, val2;
1278
1279 if (argc < 3) {
1280 struct ds ds = DS_EMPTY_INITIALIZER;
1281
1282 ds_put_format(&ds, "Tunnel UDP source port range: %"PRIu16"-%"PRIu16"\n",
1283 tnl_udp_port_min, tnl_udp_port_max);
1284
1285 unixctl_command_reply(conn, ds_cstr(&ds));
1286 ds_destroy(&ds);
1287 return;
1288 }
1289
1290 if (argc != 3) {
1291 return;
1292 }
1293
1294 val1 = atoi(argv[1]);
1295 if (val1 <= 0 || val1 > UINT16_MAX) {
1296 unixctl_command_reply(conn, "Invalid min.");
1297 return;
1298 }
1299 val2 = atoi(argv[2]);
1300 if (val2 <= 0 || val2 > UINT16_MAX) {
1301 unixctl_command_reply(conn, "Invalid max.");
1302 return;
1303 }
1304
1305 if (val1 > val2) {
1306 tnl_udp_port_min = val2;
1307 tnl_udp_port_max = val1;
1308 } else {
1309 tnl_udp_port_min = val1;
1310 tnl_udp_port_max = val2;
1311 }
1312 seq_change(tnl_conf_seq);
1313
1314 unixctl_command_reply(conn, "OK");
1315}
1316
2b9d6589 1317\f
0a740f48 1318#define VPORT_FUNCTIONS(GET_CONFIG, SET_CONFIG, \
a36de779
PS
1319 GET_TUNNEL_CONFIG, GET_STATUS, \
1320 BUILD_HEADER, \
1321 PUSH_HEADER, POP_HEADER) \
b46ccdf5 1322 NULL, \
ea83a2fc
EJ
1323 netdev_vport_run, \
1324 netdev_vport_wait, \
2b9d6589 1325 \
9dc63482
BP
1326 netdev_vport_alloc, \
1327 netdev_vport_construct, \
1328 netdev_vport_destruct, \
1329 netdev_vport_dealloc, \
0a740f48
EJ
1330 GET_CONFIG, \
1331 SET_CONFIG, \
f431bf7d 1332 GET_TUNNEL_CONFIG, \
a36de779
PS
1333 BUILD_HEADER, \
1334 PUSH_HEADER, \
1335 POP_HEADER, \
7dec44fe 1336 NULL, /* get_numa_id */ \
5496878c 1337 NULL, /* set_multiq */ \
2b9d6589 1338 \
552e20d0 1339 NULL, /* send */ \
2b9d6589
BP
1340 NULL, /* send_wait */ \
1341 \
1342 netdev_vport_set_etheraddr, \
1343 netdev_vport_get_etheraddr, \
14622f22
BP
1344 NULL, /* get_mtu */ \
1345 NULL, /* set_mtu */ \
2b9d6589 1346 NULL, /* get_ifindex */ \
85da620e 1347 NULL, /* get_carrier */ \
65c3058c 1348 NULL, /* get_carrier_resets */ \
63331829 1349 NULL, /* get_miimon */ \
b9ad7294 1350 get_stats, \
2b9d6589
BP
1351 \
1352 NULL, /* get_features */ \
1353 NULL, /* set_advertisements */ \
2b9d6589
BP
1354 \
1355 NULL, /* set_policing */ \
1356 NULL, /* get_qos_types */ \
1357 NULL, /* get_qos_capabilities */ \
1358 NULL, /* get_qos */ \
1359 NULL, /* set_qos */ \
1360 NULL, /* get_queue */ \
1361 NULL, /* set_queue */ \
1362 NULL, /* delete_queue */ \
1363 NULL, /* get_queue_stats */ \
89454bf4
BP
1364 NULL, /* queue_dump_start */ \
1365 NULL, /* queue_dump_next */ \
1366 NULL, /* queue_dump_done */ \
2b9d6589
BP
1367 NULL, /* dump_queue_stats */ \
1368 \
1369 NULL, /* get_in4 */ \
1370 NULL, /* set_in4 */ \
1371 NULL, /* get_in6 */ \
1372 NULL, /* add_router */ \
1373 NULL, /* get_next_hop */ \
ea763e0e 1374 GET_STATUS, \
2b9d6589
BP
1375 NULL, /* arp_lookup */ \
1376 \
1377 netdev_vport_update_flags, \
1378 \
9dc63482
BP
1379 NULL, /* rx_alloc */ \
1380 NULL, /* rx_construct */ \
1381 NULL, /* rx_destruct */ \
1382 NULL, /* rx_dealloc */ \
1383 NULL, /* rx_recv */ \
1384 NULL, /* rx_wait */ \
1385 NULL, /* rx_drain */
2b9d6589 1386
a36de779
PS
1387
1388#define TUNNEL_CLASS(NAME, DPIF_PORT, BUILD_HEADER, PUSH_HEADER, POP_HEADER) \
1389 { DPIF_PORT, \
1390 { NAME, VPORT_FUNCTIONS(get_tunnel_config, \
1391 set_tunnel_config, \
1392 get_netdev_tunnel_config, \
1393 tunnel_get_status, \
1394 BUILD_HEADER, PUSH_HEADER, POP_HEADER) }}
db078f85 1395
2b9d6589 1396void
c060c4cf 1397netdev_vport_tunnel_register(void)
2b9d6589 1398{
a5d4fadd
JG
1399 /* The name of the dpif_port should be short enough to accomodate adding
1400 * a port number to the end if one is necessary. */
c3827f61 1401 static const struct vport_class vport_classes[] = {
e5a1caee 1402 TUNNEL_CLASS("geneve", "genev_sys", netdev_geneve_build_header,
d625fbd1 1403 push_udp_header,
e5a1caee 1404 netdev_geneve_pop_header),
a36de779
PS
1405 TUNNEL_CLASS("gre", "gre_sys", netdev_gre_build_header,
1406 netdev_gre_push_header,
1407 netdev_gre_pop_header),
1408 TUNNEL_CLASS("ipsec_gre", "gre_sys", NULL, NULL, NULL),
1409 TUNNEL_CLASS("gre64", "gre64_sys", NULL, NULL, NULL),
1410 TUNNEL_CLASS("ipsec_gre64", "gre64_sys", NULL, NULL, NULL),
1411 TUNNEL_CLASS("vxlan", "vxlan_sys", netdev_vxlan_build_header,
d625fbd1 1412 push_udp_header,
a36de779 1413 netdev_vxlan_pop_header),
4237026e
PS
1414 TUNNEL_CLASS("lisp", "lisp_sys", NULL, NULL, NULL),
1415 TUNNEL_CLASS("stt", "stt_sys", NULL, NULL, NULL),
c3827f61 1416 };
86383816 1417 static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER;
c3827f61 1418
86383816
BP
1419 if (ovsthread_once_start(&once)) {
1420 int i;
c3827f61 1421
7c54c27f
BP
1422 for (i = 0; i < ARRAY_SIZE(vport_classes); i++) {
1423 netdev_register_provider(&vport_classes[i].netdev_class);
1424 }
a36de779
PS
1425
1426 unixctl_command_register("tnl/egress_port_range", "min max", 0, 2,
1427 netdev_vport_range, NULL);
1428
86383816 1429 ovsthread_once_done(&once);
c3827f61 1430 }
2b9d6589 1431}
c060c4cf
EJ
1432
1433void
1434netdev_vport_patch_register(void)
1435{
1436 static const struct vport_class patch_class =
1437 { NULL,
1438 { "patch", VPORT_FUNCTIONS(get_patch_config,
1439 set_patch_config,
1440 NULL,
a36de779 1441 NULL, NULL, NULL, NULL) }};
c060c4cf
EJ
1442 netdev_register_provider(&patch_class.netdev_class);
1443}