dpif-netlink: add GENEVE creation support
[cascardo/ovs.git] / lib / netdev-vport.c
1 /*
2  * Copyright (c) 2010, 2011, 2012, 2013, 2014 Nicira, Inc.
3  * Copyright (c) 2016 Red Hat, Inc.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at:
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 #include <config.h>
19
20 #include "netdev-vport.h"
21
22 #include <errno.h>
23 #include <fcntl.h>
24 #include <sys/socket.h>
25 #include <net/if.h>
26 #include <netinet/in.h>
27 #include <netinet/ip6.h>
28 #include <sys/ioctl.h>
29
30 #include "byte-order.h"
31 #include "daemon.h"
32 #include "dirs.h"
33 #include "dpif.h"
34 #include "netdev.h"
35 #include "netdev-native-tnl.h"
36 #include "netdev-provider.h"
37 #include "netdev-vport-private.h"
38 #include "ovs-router.h"
39 #include "packets.h"
40 #include "poll-loop.h"
41 #include "route-table.h"
42 #include "smap.h"
43 #include "socket-util.h"
44 #include "unaligned.h"
45 #include "unixctl.h"
46 #include "openvswitch/vlog.h"
47
48 VLOG_DEFINE_THIS_MODULE(netdev_vport);
49
50 #define GENEVE_DST_PORT 6081
51 #define VXLAN_DST_PORT 4789
52 #define LISP_DST_PORT 4341
53 #define STT_DST_PORT 7471
54
55 #define DEFAULT_TTL 64
56
57 /* Last read of the route-table's change number. */
58 static uint64_t rt_change_seqno;
59
60 static int get_patch_config(const struct netdev *netdev, struct smap *args);
61 static int get_tunnel_config(const struct netdev *, struct smap *args);
62 static bool tunnel_check_status_change__(struct netdev_vport *);
63
64 struct vport_class {
65     const char *dpif_port;
66     struct netdev_class netdev_class;
67 };
68
69 bool
70 netdev_vport_is_vport_class(const struct netdev_class *class)
71 {
72     return is_vport_class(class);
73 }
74
75 static const struct vport_class *
76 vport_class_cast(const struct netdev_class *class)
77 {
78     ovs_assert(is_vport_class(class));
79     return CONTAINER_OF(class, struct vport_class, netdev_class);
80 }
81
82 static const struct netdev_tunnel_config *
83 get_netdev_tunnel_config(const struct netdev *netdev)
84 {
85     return &netdev_vport_cast(netdev)->tnl_cfg;
86 }
87
88 bool
89 netdev_vport_is_patch(const struct netdev *netdev)
90 {
91     const struct netdev_class *class = netdev_get_class(netdev);
92
93     return class->get_config == get_patch_config;
94 }
95
96 bool
97 netdev_vport_is_layer3(const struct netdev *dev)
98 {
99     const char *type = netdev_get_type(dev);
100
101     return (!strcmp("lisp", type));
102 }
103
104 static bool
105 netdev_vport_needs_dst_port(const struct netdev *dev)
106 {
107     const struct netdev_class *class = netdev_get_class(dev);
108     const char *type = netdev_get_type(dev);
109
110     return (class->get_config == get_tunnel_config &&
111             (!strcmp("geneve", type) || !strcmp("vxlan", type) ||
112              !strcmp("lisp", type) || !strcmp("stt", type)) );
113 }
114
115 const char *
116 netdev_vport_class_get_dpif_port(const struct netdev_class *class)
117 {
118     return is_vport_class(class) ? vport_class_cast(class)->dpif_port : NULL;
119 }
120
121 const char *
122 netdev_vport_get_dpif_port(const struct netdev *netdev,
123                            char namebuf[], size_t bufsize)
124 {
125     const struct netdev_class *class = netdev_get_class(netdev);
126     const char *dpif_port = netdev_vport_class_get_dpif_port(class);
127
128     if (!dpif_port) {
129         return netdev_get_name(netdev);
130     }
131
132     if (netdev_vport_needs_dst_port(netdev)) {
133         const struct netdev_vport *vport = netdev_vport_cast(netdev);
134
135         /*
136          * Note: IFNAMSIZ is 16 bytes long. Implementations should choose
137          * a dpif port name that is short enough to fit including any
138          * port numbers but assert just in case.
139          */
140         BUILD_ASSERT(NETDEV_VPORT_NAME_BUFSIZE >= IFNAMSIZ);
141         ovs_assert(strlen(dpif_port) + 6 < IFNAMSIZ);
142         snprintf(namebuf, bufsize, "%s_%d", dpif_port,
143                  ntohs(vport->tnl_cfg.dst_port));
144         return namebuf;
145     } else {
146         return dpif_port;
147     }
148 }
149
150 char *
151 netdev_vport_get_dpif_port_strdup(const struct netdev *netdev)
152 {
153     char namebuf[NETDEV_VPORT_NAME_BUFSIZE];
154
155     return xstrdup(netdev_vport_get_dpif_port(netdev, namebuf,
156                                               sizeof namebuf));
157 }
158
159 /* Whenever the route-table change number is incremented,
160  * netdev_vport_route_changed() should be called to update
161  * the corresponding tunnel interface status. */
162 static void
163 netdev_vport_route_changed(void)
164 {
165     struct netdev **vports;
166     size_t i, n_vports;
167
168     vports = netdev_get_vports(&n_vports);
169     for (i = 0; i < n_vports; i++) {
170         struct netdev *netdev_ = vports[i];
171         struct netdev_vport *netdev = netdev_vport_cast(netdev_);
172
173         ovs_mutex_lock(&netdev->mutex);
174         /* Finds all tunnel vports. */
175         if (ipv6_addr_is_set(&netdev->tnl_cfg.ipv6_dst)) {
176             if (tunnel_check_status_change__(netdev)) {
177                 netdev_change_seq_changed(netdev_);
178             }
179         }
180         ovs_mutex_unlock(&netdev->mutex);
181
182         netdev_close(netdev_);
183     }
184
185     free(vports);
186 }
187
188 static struct netdev *
189 netdev_vport_alloc(void)
190 {
191     struct netdev_vport *netdev = xzalloc(sizeof *netdev);
192     return &netdev->up;
193 }
194
195 int
196 netdev_vport_construct(struct netdev *netdev_)
197 {
198     struct netdev_vport *dev = netdev_vport_cast(netdev_);
199     const char *type = netdev_get_type(netdev_);
200
201     ovs_mutex_init(&dev->mutex);
202     eth_addr_random(&dev->etheraddr);
203
204     /* Add a default destination port for tunnel ports if none specified. */
205     if (!strcmp(type, "geneve")) {
206         dev->tnl_cfg.dst_port = htons(GENEVE_DST_PORT);
207     } else if (!strcmp(type, "vxlan")) {
208         dev->tnl_cfg.dst_port = htons(VXLAN_DST_PORT);
209     } else if (!strcmp(type, "lisp")) {
210         dev->tnl_cfg.dst_port = htons(LISP_DST_PORT);
211     } else if (!strcmp(type, "stt")) {
212         dev->tnl_cfg.dst_port = htons(STT_DST_PORT);
213     }
214
215     dev->tnl_cfg.dont_fragment = true;
216     dev->tnl_cfg.ttl = DEFAULT_TTL;
217     return 0;
218 }
219
220 static void
221 netdev_vport_destruct(struct netdev *netdev_)
222 {
223     struct netdev_vport *netdev = netdev_vport_cast(netdev_);
224
225     free(netdev->peer);
226     ovs_mutex_destroy(&netdev->mutex);
227 }
228
229 static void
230 netdev_vport_dealloc(struct netdev *netdev_)
231 {
232     struct netdev_vport *netdev = netdev_vport_cast(netdev_);
233     free(netdev);
234 }
235
236 static int
237 netdev_vport_set_etheraddr(struct netdev *netdev_, const struct eth_addr mac)
238 {
239     struct netdev_vport *netdev = netdev_vport_cast(netdev_);
240
241     ovs_mutex_lock(&netdev->mutex);
242     netdev->etheraddr = mac;
243     ovs_mutex_unlock(&netdev->mutex);
244     netdev_change_seq_changed(netdev_);
245
246     return 0;
247 }
248
249 static int
250 netdev_vport_get_etheraddr(const struct netdev *netdev_, struct eth_addr *mac)
251 {
252     struct netdev_vport *netdev = netdev_vport_cast(netdev_);
253
254     ovs_mutex_lock(&netdev->mutex);
255     *mac = netdev->etheraddr;
256     ovs_mutex_unlock(&netdev->mutex);
257
258     return 0;
259 }
260
261 /* Checks if the tunnel status has changed and returns a boolean.
262  * Updates the tunnel status if it has changed. */
263 static bool
264 tunnel_check_status_change__(struct netdev_vport *netdev)
265     OVS_REQUIRES(netdev->mutex)
266 {
267     char iface[IFNAMSIZ];
268     bool status = false;
269     struct in6_addr *route;
270     struct in6_addr gw;
271
272     iface[0] = '\0';
273     route = &netdev->tnl_cfg.ipv6_dst;
274     if (ovs_router_lookup(route, iface, NULL, &gw)) {
275         struct netdev *egress_netdev;
276
277         if (!netdev_open(iface, "system", &egress_netdev)) {
278             status = netdev_get_carrier(egress_netdev);
279             netdev_close(egress_netdev);
280         }
281     }
282
283     if (strcmp(netdev->egress_iface, iface)
284         || netdev->carrier_status != status) {
285         ovs_strlcpy(netdev->egress_iface, iface, IFNAMSIZ);
286         netdev->carrier_status = status;
287
288         return true;
289     }
290
291     return false;
292 }
293
294 static int
295 tunnel_get_status(const struct netdev *netdev_, struct smap *smap)
296 {
297     struct netdev_vport *netdev = netdev_vport_cast(netdev_);
298
299     if (netdev->egress_iface[0]) {
300         smap_add(smap, "tunnel_egress_iface", netdev->egress_iface);
301
302         smap_add(smap, "tunnel_egress_iface_carrier",
303                  netdev->carrier_status ? "up" : "down");
304     }
305
306     return 0;
307 }
308
309 static int
310 netdev_vport_update_flags(struct netdev *netdev OVS_UNUSED,
311                           enum netdev_flags off,
312                           enum netdev_flags on OVS_UNUSED,
313                           enum netdev_flags *old_flagsp)
314 {
315     if (off & (NETDEV_UP | NETDEV_PROMISC)) {
316         return EOPNOTSUPP;
317     }
318
319     *old_flagsp = NETDEV_UP | NETDEV_PROMISC;
320     return 0;
321 }
322
323 static void
324 netdev_vport_run(void)
325 {
326     uint64_t seq;
327
328     route_table_run();
329     seq = route_table_get_change_seq();
330     if (rt_change_seqno != seq) {
331         rt_change_seqno = seq;
332         netdev_vport_route_changed();
333     }
334 }
335
336 static void
337 netdev_vport_wait(void)
338 {
339     uint64_t seq;
340
341     route_table_wait();
342     seq = route_table_get_change_seq();
343     if (rt_change_seqno != seq) {
344         poll_immediate_wake();
345     }
346 }
347 \f
348 /* Code specific to tunnel types. */
349
350 static ovs_be64
351 parse_key(const struct smap *args, const char *name,
352           bool *present, bool *flow)
353 {
354     const char *s;
355
356     *present = false;
357     *flow = false;
358
359     s = smap_get(args, name);
360     if (!s) {
361         s = smap_get(args, "key");
362         if (!s) {
363             return 0;
364         }
365     }
366
367     *present = true;
368
369     if (!strcmp(s, "flow")) {
370         *flow = true;
371         return 0;
372     } else {
373         return htonll(strtoull(s, NULL, 0));
374     }
375 }
376
377 static int
378 parse_tunnel_ip(const char *value, bool accept_mcast, bool *flow,
379                 struct in6_addr *ipv6, uint16_t *protocol)
380 {
381     if (!strcmp(value, "flow")) {
382         *flow = true;
383         *protocol = 0;
384         return 0;
385     }
386     if (addr_is_ipv6(value)) {
387         if (lookup_ipv6(value, ipv6)) {
388             return ENOENT;
389         }
390         if (!accept_mcast && ipv6_addr_is_multicast(ipv6)) {
391             return EINVAL;
392         }
393         *protocol = ETH_TYPE_IPV6;
394     } else {
395         struct in_addr ip;
396         if (lookup_ip(value, &ip)) {
397             return ENOENT;
398         }
399         if (!accept_mcast && ip_is_multicast(ip.s_addr)) {
400             return EINVAL;
401         }
402         in6_addr_set_mapped_ipv4(ipv6, ip.s_addr);
403         *protocol = ETH_TYPE_IP;
404     }
405     return 0;
406 }
407
408 static int
409 set_tunnel_config(struct netdev *dev_, const struct smap *args)
410 {
411     struct netdev_vport *dev = netdev_vport_cast(dev_);
412     const char *name = netdev_get_name(dev_);
413     const char *type = netdev_get_type(dev_);
414     bool ipsec_mech_set, needs_dst_port, has_csum;
415     uint16_t dst_proto = 0, src_proto = 0;
416     struct netdev_tunnel_config tnl_cfg;
417     struct smap_node *node;
418
419     has_csum = strstr(type, "gre") || strstr(type, "geneve") ||
420                strstr(type, "stt") || strstr(type, "vxlan");
421     ipsec_mech_set = false;
422     memset(&tnl_cfg, 0, sizeof tnl_cfg);
423
424     /* Add a default destination port for tunnel ports if none specified. */
425     if (!strcmp(type, "geneve")) {
426         tnl_cfg.dst_port = htons(GENEVE_DST_PORT);
427     }
428
429     if (!strcmp(type, "vxlan")) {
430         tnl_cfg.dst_port = htons(VXLAN_DST_PORT);
431     }
432
433     if (!strcmp(type, "lisp")) {
434         tnl_cfg.dst_port = htons(LISP_DST_PORT);
435     }
436
437     if (!strcmp(type, "stt")) {
438         tnl_cfg.dst_port = htons(STT_DST_PORT);
439     }
440
441     needs_dst_port = netdev_vport_needs_dst_port(dev_);
442     tnl_cfg.ipsec = strstr(type, "ipsec");
443     tnl_cfg.dont_fragment = true;
444
445     SMAP_FOR_EACH (node, args) {
446         if (!strcmp(node->key, "remote_ip")) {
447             int err;
448             err = parse_tunnel_ip(node->value, false, &tnl_cfg.ip_dst_flow,
449                                   &tnl_cfg.ipv6_dst, &dst_proto);
450             switch (err) {
451             case ENOENT:
452                 VLOG_WARN("%s: bad %s 'remote_ip'", name, type);
453                 break;
454             case EINVAL:
455                 VLOG_WARN("%s: multicast remote_ip=%s not allowed",
456                           name, node->value);
457                 return EINVAL;
458             }
459         } else if (!strcmp(node->key, "local_ip")) {
460             int err;
461             err = parse_tunnel_ip(node->value, true, &tnl_cfg.ip_src_flow,
462                                   &tnl_cfg.ipv6_src, &src_proto);
463             switch (err) {
464             case ENOENT:
465                 VLOG_WARN("%s: bad %s 'local_ip'", name, type);
466                 break;
467             }
468         } else if (!strcmp(node->key, "tos")) {
469             if (!strcmp(node->value, "inherit")) {
470                 tnl_cfg.tos_inherit = true;
471             } else {
472                 char *endptr;
473                 int tos;
474                 tos = strtol(node->value, &endptr, 0);
475                 if (*endptr == '\0' && tos == (tos & IP_DSCP_MASK)) {
476                     tnl_cfg.tos = tos;
477                 } else {
478                     VLOG_WARN("%s: invalid TOS %s", name, node->value);
479                 }
480             }
481         } else if (!strcmp(node->key, "ttl")) {
482             if (!strcmp(node->value, "inherit")) {
483                 tnl_cfg.ttl_inherit = true;
484             } else {
485                 tnl_cfg.ttl = atoi(node->value);
486             }
487         } else if (!strcmp(node->key, "dst_port") && needs_dst_port) {
488             tnl_cfg.dst_port = htons(atoi(node->value));
489         } else if (!strcmp(node->key, "csum") && has_csum) {
490             if (!strcmp(node->value, "true")) {
491                 tnl_cfg.csum = true;
492             }
493         } else if (!strcmp(node->key, "df_default")) {
494             if (!strcmp(node->value, "false")) {
495                 tnl_cfg.dont_fragment = false;
496             }
497         } else if (!strcmp(node->key, "peer_cert") && tnl_cfg.ipsec) {
498             if (smap_get(args, "certificate")) {
499                 ipsec_mech_set = true;
500             } else {
501                 const char *use_ssl_cert;
502
503                 /* If the "use_ssl_cert" is true, then "certificate" and
504                  * "private_key" will be pulled from the SSL table.  The
505                  * use of this option is strongly discouraged, since it
506                  * will like be removed when multiple SSL configurations
507                  * are supported by OVS.
508                  */
509                 use_ssl_cert = smap_get(args, "use_ssl_cert");
510                 if (!use_ssl_cert || strcmp(use_ssl_cert, "true")) {
511                     VLOG_ERR("%s: 'peer_cert' requires 'certificate' argument",
512                              name);
513                     return EINVAL;
514                 }
515                 ipsec_mech_set = true;
516             }
517         } else if (!strcmp(node->key, "psk") && tnl_cfg.ipsec) {
518             ipsec_mech_set = true;
519         } else if (tnl_cfg.ipsec
520                 && (!strcmp(node->key, "certificate")
521                     || !strcmp(node->key, "private_key")
522                     || !strcmp(node->key, "use_ssl_cert"))) {
523             /* Ignore options not used by the netdev. */
524         } else if (!strcmp(node->key, "key") ||
525                    !strcmp(node->key, "in_key") ||
526                    !strcmp(node->key, "out_key")) {
527             /* Handled separately below. */
528         } else if (!strcmp(node->key, "exts")) {
529             char *str = xstrdup(node->value);
530             char *ext, *save_ptr = NULL;
531
532             tnl_cfg.exts = 0;
533
534             ext = strtok_r(str, ",", &save_ptr);
535             while (ext) {
536                 if (!strcmp(type, "vxlan") && !strcmp(ext, "gbp")) {
537                     tnl_cfg.exts |= (1 << OVS_VXLAN_EXT_GBP);
538                 } else {
539                     VLOG_WARN("%s: unknown extension '%s'", name, ext);
540                 }
541
542                 ext = strtok_r(NULL, ",", &save_ptr);
543             }
544
545             free(str);
546         } else {
547             VLOG_WARN("%s: unknown %s argument '%s'", name, type, node->key);
548         }
549     }
550
551     if (tnl_cfg.ipsec) {
552         static struct ovs_mutex mutex = OVS_MUTEX_INITIALIZER;
553         static pid_t pid = 0;
554
555 #ifndef _WIN32
556         ovs_mutex_lock(&mutex);
557         if (pid <= 0) {
558             char *file_name = xasprintf("%s/%s", ovs_rundir(),
559                                         "ovs-monitor-ipsec.pid");
560             pid = read_pidfile(file_name);
561             free(file_name);
562         }
563         ovs_mutex_unlock(&mutex);
564 #endif
565
566         if (pid < 0) {
567             VLOG_ERR("%s: IPsec requires the ovs-monitor-ipsec daemon",
568                      name);
569             return EINVAL;
570         }
571
572         if (smap_get(args, "peer_cert") && smap_get(args, "psk")) {
573             VLOG_ERR("%s: cannot define both 'peer_cert' and 'psk'", name);
574             return EINVAL;
575         }
576
577         if (!ipsec_mech_set) {
578             VLOG_ERR("%s: IPsec requires an 'peer_cert' or psk' argument",
579                      name);
580             return EINVAL;
581         }
582     }
583
584     if (!ipv6_addr_is_set(&tnl_cfg.ipv6_dst) && !tnl_cfg.ip_dst_flow) {
585         VLOG_ERR("%s: %s type requires valid 'remote_ip' argument",
586                  name, type);
587         return EINVAL;
588     }
589     if (tnl_cfg.ip_src_flow && !tnl_cfg.ip_dst_flow) {
590         VLOG_ERR("%s: %s type requires 'remote_ip=flow' with 'local_ip=flow'",
591                  name, type);
592         return EINVAL;
593     }
594     if (src_proto && dst_proto && src_proto != dst_proto) {
595         VLOG_ERR("%s: 'remote_ip' and 'local_ip' has to be of the same address family",
596                  name);
597         return EINVAL;
598     }
599     if (!tnl_cfg.ttl) {
600         tnl_cfg.ttl = DEFAULT_TTL;
601     }
602
603     tnl_cfg.in_key = parse_key(args, "in_key",
604                                &tnl_cfg.in_key_present,
605                                &tnl_cfg.in_key_flow);
606
607     tnl_cfg.out_key = parse_key(args, "out_key",
608                                &tnl_cfg.out_key_present,
609                                &tnl_cfg.out_key_flow);
610
611     ovs_mutex_lock(&dev->mutex);
612     if (memcmp(&dev->tnl_cfg, &tnl_cfg, sizeof tnl_cfg)) {
613         dev->tnl_cfg = tnl_cfg;
614         tunnel_check_status_change__(dev);
615         netdev_change_seq_changed(dev_);
616     }
617     ovs_mutex_unlock(&dev->mutex);
618
619     return 0;
620 }
621
622 static int
623 get_tunnel_config(const struct netdev *dev, struct smap *args)
624 {
625     struct netdev_vport *netdev = netdev_vport_cast(dev);
626     struct netdev_tunnel_config tnl_cfg;
627
628     ovs_mutex_lock(&netdev->mutex);
629     tnl_cfg = netdev->tnl_cfg;
630     ovs_mutex_unlock(&netdev->mutex);
631
632     if (ipv6_addr_is_set(&tnl_cfg.ipv6_dst)) {
633         smap_add_ipv6(args, "remote_ip", &tnl_cfg.ipv6_dst);
634     } else if (tnl_cfg.ip_dst_flow) {
635         smap_add(args, "remote_ip", "flow");
636     }
637
638     if (ipv6_addr_is_set(&tnl_cfg.ipv6_src)) {
639         smap_add_ipv6(args, "local_ip", &tnl_cfg.ipv6_src);
640     } else if (tnl_cfg.ip_src_flow) {
641         smap_add(args, "local_ip", "flow");
642     }
643
644     if (tnl_cfg.in_key_flow && tnl_cfg.out_key_flow) {
645         smap_add(args, "key", "flow");
646     } else if (tnl_cfg.in_key_present && tnl_cfg.out_key_present
647                && tnl_cfg.in_key == tnl_cfg.out_key) {
648         smap_add_format(args, "key", "%"PRIu64, ntohll(tnl_cfg.in_key));
649     } else {
650         if (tnl_cfg.in_key_flow) {
651             smap_add(args, "in_key", "flow");
652         } else if (tnl_cfg.in_key_present) {
653             smap_add_format(args, "in_key", "%"PRIu64,
654                             ntohll(tnl_cfg.in_key));
655         }
656
657         if (tnl_cfg.out_key_flow) {
658             smap_add(args, "out_key", "flow");
659         } else if (tnl_cfg.out_key_present) {
660             smap_add_format(args, "out_key", "%"PRIu64,
661                             ntohll(tnl_cfg.out_key));
662         }
663     }
664
665     if (tnl_cfg.ttl_inherit) {
666         smap_add(args, "ttl", "inherit");
667     } else if (tnl_cfg.ttl != DEFAULT_TTL) {
668         smap_add_format(args, "ttl", "%"PRIu8, tnl_cfg.ttl);
669     }
670
671     if (tnl_cfg.tos_inherit) {
672         smap_add(args, "tos", "inherit");
673     } else if (tnl_cfg.tos) {
674         smap_add_format(args, "tos", "0x%x", tnl_cfg.tos);
675     }
676
677     if (tnl_cfg.dst_port) {
678         uint16_t dst_port = ntohs(tnl_cfg.dst_port);
679         const char *type = netdev_get_type(dev);
680
681         if ((!strcmp("geneve", type) && dst_port != GENEVE_DST_PORT) ||
682             (!strcmp("vxlan", type) && dst_port != VXLAN_DST_PORT) ||
683             (!strcmp("lisp", type) && dst_port != LISP_DST_PORT) ||
684             (!strcmp("stt", type) && dst_port != STT_DST_PORT)) {
685             smap_add_format(args, "dst_port", "%d", dst_port);
686         }
687     }
688
689     if (tnl_cfg.csum) {
690         smap_add(args, "csum", "true");
691     }
692
693     if (!tnl_cfg.dont_fragment) {
694         smap_add(args, "df_default", "false");
695     }
696
697     return 0;
698 }
699 \f
700 /* Code specific to patch ports. */
701
702 /* If 'netdev' is a patch port, returns the name of its peer as a malloc()'d
703  * string that the caller must free.
704  *
705  * If 'netdev' is not a patch port, returns NULL. */
706 char *
707 netdev_vport_patch_peer(const struct netdev *netdev_)
708 {
709     char *peer = NULL;
710
711     if (netdev_vport_is_patch(netdev_)) {
712         struct netdev_vport *netdev = netdev_vport_cast(netdev_);
713
714         ovs_mutex_lock(&netdev->mutex);
715         if (netdev->peer) {
716             peer = xstrdup(netdev->peer);
717         }
718         ovs_mutex_unlock(&netdev->mutex);
719     }
720
721     return peer;
722 }
723
724 void
725 netdev_vport_inc_rx(const struct netdev *netdev,
726                     const struct dpif_flow_stats *stats)
727 {
728     if (is_vport_class(netdev_get_class(netdev))) {
729         struct netdev_vport *dev = netdev_vport_cast(netdev);
730
731         ovs_mutex_lock(&dev->mutex);
732         dev->stats.rx_packets += stats->n_packets;
733         dev->stats.rx_bytes += stats->n_bytes;
734         ovs_mutex_unlock(&dev->mutex);
735     }
736 }
737
738 void
739 netdev_vport_inc_tx(const struct netdev *netdev,
740                     const struct dpif_flow_stats *stats)
741 {
742     if (is_vport_class(netdev_get_class(netdev))) {
743         struct netdev_vport *dev = netdev_vport_cast(netdev);
744
745         ovs_mutex_lock(&dev->mutex);
746         dev->stats.tx_packets += stats->n_packets;
747         dev->stats.tx_bytes += stats->n_bytes;
748         ovs_mutex_unlock(&dev->mutex);
749     }
750 }
751
752 static int
753 get_patch_config(const struct netdev *dev_, struct smap *args)
754 {
755     struct netdev_vport *dev = netdev_vport_cast(dev_);
756
757     ovs_mutex_lock(&dev->mutex);
758     if (dev->peer) {
759         smap_add(args, "peer", dev->peer);
760     }
761     ovs_mutex_unlock(&dev->mutex);
762
763     return 0;
764 }
765
766 static int
767 set_patch_config(struct netdev *dev_, const struct smap *args)
768 {
769     struct netdev_vport *dev = netdev_vport_cast(dev_);
770     const char *name = netdev_get_name(dev_);
771     const char *peer;
772
773     peer = smap_get(args, "peer");
774     if (!peer) {
775         VLOG_ERR("%s: patch type requires valid 'peer' argument", name);
776         return EINVAL;
777     }
778
779     if (smap_count(args) > 1) {
780         VLOG_ERR("%s: patch type takes only a 'peer' argument", name);
781         return EINVAL;
782     }
783
784     if (!strcmp(name, peer)) {
785         VLOG_ERR("%s: patch peer must not be self", name);
786         return EINVAL;
787     }
788
789     ovs_mutex_lock(&dev->mutex);
790     if (!dev->peer || strcmp(dev->peer, peer)) {
791         free(dev->peer);
792         dev->peer = xstrdup(peer);
793         netdev_change_seq_changed(dev_);
794     }
795     ovs_mutex_unlock(&dev->mutex);
796
797     return 0;
798 }
799
800 static int
801 get_stats(const struct netdev *netdev, struct netdev_stats *stats)
802 {
803     struct netdev_vport *dev = netdev_vport_cast(netdev);
804
805     ovs_mutex_lock(&dev->mutex);
806     /* Passing only collected counters */
807     stats->tx_packets = dev->stats.tx_packets;
808     stats->tx_bytes = dev->stats.tx_bytes;
809     stats->rx_packets = dev->stats.rx_packets;
810     stats->rx_bytes = dev->stats.rx_bytes;
811     ovs_mutex_unlock(&dev->mutex);
812
813     return 0;
814 }
815
816 \f
817 #define VPORT_FUNCTIONS(GET_CONFIG, SET_CONFIG,             \
818                         GET_TUNNEL_CONFIG, GET_STATUS,      \
819                         BUILD_HEADER,                       \
820                         PUSH_HEADER, POP_HEADER)            \
821     NULL,                                                   \
822     netdev_vport_run,                                       \
823     netdev_vport_wait,                                      \
824                                                             \
825     netdev_vport_alloc,                                     \
826     netdev_vport_construct,                                 \
827     netdev_vport_destruct,                                  \
828     netdev_vport_dealloc,                                   \
829     GET_CONFIG,                                             \
830     SET_CONFIG,                                             \
831     GET_TUNNEL_CONFIG,                                      \
832     BUILD_HEADER,                                           \
833     PUSH_HEADER,                                            \
834     POP_HEADER,                                             \
835     NULL,                       /* get_numa_id */           \
836     NULL,                       /* set_tx_multiq */         \
837                                                             \
838     NULL,                       /* send */                  \
839     NULL,                       /* send_wait */             \
840                                                             \
841     netdev_vport_set_etheraddr,                             \
842     netdev_vport_get_etheraddr,                             \
843     NULL,                       /* get_mtu */               \
844     NULL,                       /* set_mtu */               \
845     NULL,                       /* get_ifindex */           \
846     NULL,                       /* get_carrier */           \
847     NULL,                       /* get_carrier_resets */    \
848     NULL,                       /* get_miimon */            \
849     get_stats,                                              \
850                                                             \
851     NULL,                       /* get_features */          \
852     NULL,                       /* set_advertisements */    \
853                                                             \
854     NULL,                       /* set_policing */          \
855     NULL,                       /* get_qos_types */         \
856     NULL,                       /* get_qos_capabilities */  \
857     NULL,                       /* get_qos */               \
858     NULL,                       /* set_qos */               \
859     NULL,                       /* get_queue */             \
860     NULL,                       /* set_queue */             \
861     NULL,                       /* delete_queue */          \
862     NULL,                       /* get_queue_stats */       \
863     NULL,                       /* queue_dump_start */      \
864     NULL,                       /* queue_dump_next */       \
865     NULL,                       /* queue_dump_done */       \
866     NULL,                       /* dump_queue_stats */      \
867                                                             \
868     NULL,                       /* set_in4 */               \
869     NULL,                       /* get_addr_list */         \
870     NULL,                       /* add_router */            \
871     NULL,                       /* get_next_hop */          \
872     GET_STATUS,                                             \
873     NULL,                       /* arp_lookup */            \
874                                                             \
875     netdev_vport_update_flags,                              \
876     NULL,                       /* reconfigure */           \
877                                                             \
878     NULL,                   /* rx_alloc */                  \
879     NULL,                   /* rx_construct */              \
880     NULL,                   /* rx_destruct */               \
881     NULL,                   /* rx_dealloc */                \
882     NULL,                   /* rx_recv */                   \
883     NULL,                   /* rx_wait */                   \
884     NULL,                   /* rx_drain */
885
886
887 #define TUNNEL_CLASS(NAME, DPIF_PORT, BUILD_HEADER, PUSH_HEADER, POP_HEADER)   \
888     { DPIF_PORT,                                                               \
889         { NAME, false,                                                         \
890           VPORT_FUNCTIONS(get_tunnel_config,                                   \
891                           set_tunnel_config,                                   \
892                           get_netdev_tunnel_config,                            \
893                           tunnel_get_status,                                   \
894                           BUILD_HEADER, PUSH_HEADER, POP_HEADER) }}
895
896 void
897 netdev_vport_tunnel_register(void)
898 {
899     /* The name of the dpif_port should be short enough to accomodate adding
900      * a port number to the end if one is necessary. */
901     static const struct vport_class vport_classes[] = {
902         TUNNEL_CLASS("geneve", "genev_sys", netdev_geneve_build_header,
903                                             netdev_tnl_push_udp_header,
904                                             netdev_geneve_pop_header),
905         TUNNEL_CLASS("gre", "gre_sys", netdev_gre_build_header,
906                                        netdev_gre_push_header,
907                                        netdev_gre_pop_header),
908         TUNNEL_CLASS("ipsec_gre", "gre_sys", NULL, NULL, NULL),
909         TUNNEL_CLASS("vxlan", "vxlan_sys", netdev_vxlan_build_header,
910                                            netdev_tnl_push_udp_header,
911                                            netdev_vxlan_pop_header),
912         TUNNEL_CLASS("lisp", "lisp_sys", NULL, NULL, NULL),
913         TUNNEL_CLASS("stt", "stt_sys", NULL, NULL, NULL),
914     };
915     static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER;
916
917     if (ovsthread_once_start(&once)) {
918         int i;
919
920         for (i = 0; i < ARRAY_SIZE(vport_classes); i++) {
921             netdev_register_provider(&vport_classes[i].netdev_class);
922         }
923
924         unixctl_command_register("tnl/egress_port_range", "min max", 0, 2,
925                                  netdev_tnl_egress_port_range, NULL);
926
927         ovsthread_once_done(&once);
928     }
929 }
930
931 void
932 netdev_vport_patch_register(void)
933 {
934     static const struct vport_class patch_class =
935         { NULL,
936             { "patch", false,
937               VPORT_FUNCTIONS(get_patch_config,
938                               set_patch_config,
939                               NULL,
940                               NULL, NULL, NULL, NULL) }};
941     netdev_register_provider(&patch_class.netdev_class);
942 }