cfm: Immediately signal fault on bad CCM reception.
[sliver-openvswitch.git] / lib / netdev-vport.c
1 /*
2  * Copyright (c) 2010, 2011 Nicira Networks.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <config.h>
18
19 #include "netdev-vport.h"
20
21 #include <errno.h>
22 #include <fcntl.h>
23 #include <sys/socket.h>
24 #include <linux/rtnetlink.h>
25 #include <net/if.h>
26 #include <sys/ioctl.h>
27
28 #include "byte-order.h"
29 #include "daemon.h"
30 #include "dirs.h"
31 #include "dpif-linux.h"
32 #include "hash.h"
33 #include "hmap.h"
34 #include "list.h"
35 #include "netdev-provider.h"
36 #include "netlink.h"
37 #include "netlink-socket.h"
38 #include "ofpbuf.h"
39 #include "openvswitch/datapath-protocol.h"
40 #include "openvswitch/tunnel.h"
41 #include "packets.h"
42 #include "route-table.h"
43 #include "rtnetlink.h"
44 #include "shash.h"
45 #include "socket-util.h"
46 #include "vlog.h"
47
48 VLOG_DEFINE_THIS_MODULE(netdev_vport);
49
50 struct netdev_vport_notifier {
51     struct netdev_notifier notifier;
52     struct list list_node;
53     struct shash_node *shash_node;
54 };
55
56 struct netdev_dev_vport {
57     struct netdev_dev netdev_dev;
58     struct ofpbuf *options;
59 };
60
61 struct netdev_vport {
62     struct netdev netdev;
63 };
64
65 struct vport_class {
66     enum odp_vport_type type;
67     struct netdev_class netdev_class;
68     int (*parse_config)(const char *name, const char *type,
69                         const struct shash *args, struct ofpbuf *options);
70     int (*unparse_config)(const char *name, const char *type,
71                           const struct nlattr *options, size_t options_len,
72                           struct shash *args);
73 };
74
75 static struct shash netdev_vport_notifiers =
76                                     SHASH_INITIALIZER(&netdev_vport_notifiers);
77
78 static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 20);
79
80 static int netdev_vport_create(const struct netdev_class *, const char *,
81                                const struct shash *, struct netdev_dev **);
82 static void netdev_vport_poll_notify(const struct netdev *);
83 static int tnl_port_config_from_nlattr(const struct nlattr *options,
84                                        size_t options_len,
85                                        struct nlattr *a[ODP_TUNNEL_ATTR_MAX + 1]);
86
87 static const char *netdev_vport_get_tnl_iface(const struct netdev *netdev);
88
89 static bool
90 is_vport_class(const struct netdev_class *class)
91 {
92     return class->create == netdev_vport_create;
93 }
94
95 static const struct vport_class *
96 vport_class_cast(const struct netdev_class *class)
97 {
98     assert(is_vport_class(class));
99     return CONTAINER_OF(class, struct vport_class, netdev_class);
100 }
101
102 static struct netdev_dev_vport *
103 netdev_dev_vport_cast(const struct netdev_dev *netdev_dev)
104 {
105     assert(is_vport_class(netdev_dev_get_class(netdev_dev)));
106     return CONTAINER_OF(netdev_dev, struct netdev_dev_vport, netdev_dev);
107 }
108
109 static struct netdev_vport *
110 netdev_vport_cast(const struct netdev *netdev)
111 {
112     struct netdev_dev *netdev_dev = netdev_get_dev(netdev);
113     assert(is_vport_class(netdev_dev_get_class(netdev_dev)));
114     return CONTAINER_OF(netdev, struct netdev_vport, netdev);
115 }
116
117 /* If 'netdev' is a vport netdev, returns an ofpbuf that contains Netlink
118  * options to include in ODP_VPORT_ATTR_OPTIONS for configuring that vport.
119  * Otherwise returns NULL. */
120 const struct ofpbuf *
121 netdev_vport_get_options(const struct netdev *netdev)
122 {
123     const struct netdev_dev *dev = netdev_get_dev(netdev);
124
125     return (is_vport_class(netdev_dev_get_class(dev))
126             ? netdev_dev_vport_cast(dev)->options
127             : NULL);
128 }
129
130 enum odp_vport_type
131 netdev_vport_get_vport_type(const struct netdev *netdev)
132 {
133     const struct netdev_dev *dev = netdev_get_dev(netdev);
134     const struct netdev_class *class = netdev_dev_get_class(dev);
135
136     return (is_vport_class(class) ? vport_class_cast(class)->type
137             : class == &netdev_internal_class ? ODP_VPORT_TYPE_INTERNAL
138             : class == &netdev_linux_class ? ODP_VPORT_TYPE_NETDEV
139             : ODP_VPORT_TYPE_UNSPEC);
140 }
141
142 const char *
143 netdev_vport_get_netdev_type(const struct dpif_linux_vport *vport)
144 {
145     struct nlattr *a[ODP_TUNNEL_ATTR_MAX + 1];
146
147     switch (vport->type) {
148     case ODP_VPORT_TYPE_UNSPEC:
149         break;
150
151     case ODP_VPORT_TYPE_NETDEV:
152         return "system";
153
154     case ODP_VPORT_TYPE_INTERNAL:
155         return "internal";
156
157     case ODP_VPORT_TYPE_PATCH:
158         return "patch";
159
160     case ODP_VPORT_TYPE_GRE:
161         if (tnl_port_config_from_nlattr(vport->options, vport->options_len,
162                                         a)) {
163             break;
164         }
165         return (nl_attr_get_u32(a[ODP_TUNNEL_ATTR_FLAGS]) & TNL_F_IPSEC
166                 ? "ipsec_gre" : "gre");
167
168     case ODP_VPORT_TYPE_CAPWAP:
169         return "capwap";
170
171     case __ODP_VPORT_TYPE_MAX:
172         break;
173     }
174
175     VLOG_WARN_RL(&rl, "dp%d: port `%s' has unsupported type %u",
176                  vport->dp_ifindex, vport->name, (unsigned int) vport->type);
177     return "unknown";
178 }
179
180 static int
181 netdev_vport_create(const struct netdev_class *netdev_class, const char *name,
182                     const struct shash *args,
183                     struct netdev_dev **netdev_devp)
184 {
185     const struct vport_class *vport_class = vport_class_cast(netdev_class);
186     struct ofpbuf *options = NULL;
187     struct shash fetched_args;
188     int error;
189
190     shash_init(&fetched_args);
191
192     if (!shash_is_empty(args)) {
193         /* Parse the provided configuration. */
194         options = ofpbuf_new(64);
195         error = vport_class->parse_config(name, netdev_class->type,
196                                           args, options);
197     } else {
198         /* Fetch an existing configuration from the kernel.
199          *
200          * This case could be ambiguous with initializing a new vport with an
201          * empty configuration, but none of the existing vport classes accept
202          * an empty configuration. */
203         struct dpif_linux_vport reply;
204         struct ofpbuf *buf;
205
206         error = dpif_linux_vport_get(name, &reply, &buf);
207         if (!error) {
208             /* XXX verify correct type */
209             error = vport_class->unparse_config(name, netdev_class->type,
210                                                 reply.options,
211                                                 reply.options_len,
212                                                 &fetched_args);
213             if (error) {
214                 VLOG_ERR_RL(&rl, "%s: failed to parse kernel config (%s)",
215                             name, strerror(error));
216             } else {
217                 options = ofpbuf_clone_data(reply.options, reply.options_len);
218             }
219             ofpbuf_delete(buf);
220         } else {
221             VLOG_ERR_RL(&rl, "%s: vport query failed (%s)",
222                         name, strerror(error));
223         }
224     }
225
226     if (!error) {
227         struct netdev_dev_vport *dev;
228
229         dev = xmalloc(sizeof *dev);
230         netdev_dev_init(&dev->netdev_dev, name,
231                         shash_is_empty(&fetched_args) ? args : &fetched_args,
232                         netdev_class);
233         dev->options = options;
234
235         *netdev_devp = &dev->netdev_dev;
236         route_table_register();
237     } else {
238         ofpbuf_delete(options);
239     }
240
241     shash_destroy(&fetched_args);
242
243     return error;
244 }
245
246 static void
247 netdev_vport_destroy(struct netdev_dev *netdev_dev_)
248 {
249     struct netdev_dev_vport *netdev_dev = netdev_dev_vport_cast(netdev_dev_);
250
251     route_table_unregister();
252     free(netdev_dev);
253 }
254
255 static int
256 netdev_vport_open(struct netdev_dev *netdev_dev_, int ethertype OVS_UNUSED,
257                 struct netdev **netdevp)
258 {
259     struct netdev_vport *netdev;
260
261     netdev = xmalloc(sizeof *netdev);
262     netdev_init(&netdev->netdev, netdev_dev_);
263
264     *netdevp = &netdev->netdev;
265     return 0;
266 }
267
268 static void
269 netdev_vport_close(struct netdev *netdev_)
270 {
271     struct netdev_vport *netdev = netdev_vport_cast(netdev_);
272     free(netdev);
273 }
274
275 static int
276 netdev_vport_set_config(struct netdev_dev *dev_, const struct shash *args)
277 {
278     const struct netdev_class *netdev_class = netdev_dev_get_class(dev_);
279     const struct vport_class *vport_class = vport_class_cast(netdev_class);
280     struct netdev_dev_vport *dev = netdev_dev_vport_cast(dev_);
281     const char *name = netdev_dev_get_name(dev_);
282     struct ofpbuf *options;
283     int error;
284
285     options = ofpbuf_new(64);
286     error = vport_class->parse_config(name, netdev_dev_get_type(dev_),
287                                       args, options);
288     if (!error
289         && (options->size != dev->options->size
290             || memcmp(options->data, dev->options->data, options->size))) {
291         struct dpif_linux_vport vport;
292
293         dpif_linux_vport_init(&vport);
294         vport.cmd = ODP_VPORT_CMD_SET;
295         vport.name = name;
296         vport.options = options->data;
297         vport.options_len = options->size;
298         error = dpif_linux_vport_transact(&vport, NULL, NULL);
299         if (!error || error == ENODEV) {
300             /* Either reconfiguration succeeded or this vport is not installed
301              * in the kernel (e.g. it hasn't been added to a dpif yet with
302              * dpif_port_add()). */
303             ofpbuf_delete(dev->options);
304             dev->options = options;
305             options = NULL;
306             error = 0;
307         }
308     }
309     ofpbuf_delete(options);
310
311     return error;
312 }
313
314 static int
315 netdev_vport_set_etheraddr(struct netdev *netdev,
316                            const uint8_t mac[ETH_ADDR_LEN])
317 {
318     struct dpif_linux_vport vport;
319     int error;
320
321     dpif_linux_vport_init(&vport);
322     vport.cmd = ODP_VPORT_CMD_SET;
323     vport.name = netdev_get_name(netdev);
324     vport.address = mac;
325
326     error = dpif_linux_vport_transact(&vport, NULL, NULL);
327     if (!error) {
328         netdev_vport_poll_notify(netdev);
329     }
330     return error;
331 }
332
333 static int
334 netdev_vport_get_etheraddr(const struct netdev *netdev,
335                            uint8_t mac[ETH_ADDR_LEN])
336 {
337     struct dpif_linux_vport reply;
338     struct ofpbuf *buf;
339     int error;
340
341     error = dpif_linux_vport_get(netdev_get_name(netdev), &reply, &buf);
342     if (!error) {
343         if (reply.address) {
344             memcpy(mac, reply.address, ETH_ADDR_LEN);
345         } else {
346             error = EOPNOTSUPP;
347         }
348         ofpbuf_delete(buf);
349     }
350     return error;
351 }
352
353 static int
354 netdev_vport_get_mtu(const struct netdev *netdev, int *mtup)
355 {
356     struct dpif_linux_vport reply;
357     struct ofpbuf *buf;
358     int error;
359
360     error = dpif_linux_vport_get(netdev_get_name(netdev), &reply, &buf);
361     if (!error) {
362         *mtup = reply.mtu;
363         ofpbuf_delete(buf);
364     }
365     return error;
366 }
367
368 int
369 netdev_vport_get_stats(const struct netdev *netdev, struct netdev_stats *stats)
370 {
371     struct dpif_linux_vport reply;
372     struct ofpbuf *buf;
373     int error;
374
375     error = dpif_linux_vport_get(netdev_get_name(netdev), &reply, &buf);
376     if (error) {
377         return error;
378     } else if (!reply.stats) {
379         ofpbuf_delete(buf);
380         return EOPNOTSUPP;
381     }
382
383     stats->rx_packets = reply.stats->rx_packets;
384     stats->tx_packets = reply.stats->tx_packets;
385     stats->rx_bytes = reply.stats->rx_bytes;
386     stats->tx_bytes = reply.stats->tx_bytes;
387     stats->rx_errors = reply.stats->rx_errors;
388     stats->tx_errors = reply.stats->tx_errors;
389     stats->rx_dropped = reply.stats->rx_dropped;
390     stats->tx_dropped = reply.stats->tx_dropped;
391     stats->multicast = reply.stats->multicast;
392     stats->collisions = reply.stats->collisions;
393     stats->rx_length_errors = reply.stats->rx_length_errors;
394     stats->rx_over_errors = reply.stats->rx_over_errors;
395     stats->rx_crc_errors = reply.stats->rx_crc_errors;
396     stats->rx_frame_errors = reply.stats->rx_frame_errors;
397     stats->rx_fifo_errors = reply.stats->rx_fifo_errors;
398     stats->rx_missed_errors = reply.stats->rx_missed_errors;
399     stats->tx_aborted_errors = reply.stats->tx_aborted_errors;
400     stats->tx_carrier_errors = reply.stats->tx_carrier_errors;
401     stats->tx_fifo_errors = reply.stats->tx_fifo_errors;
402     stats->tx_heartbeat_errors = reply.stats->tx_heartbeat_errors;
403     stats->tx_window_errors = reply.stats->tx_window_errors;
404
405     ofpbuf_delete(buf);
406
407     return 0;
408 }
409
410 int
411 netdev_vport_set_stats(struct netdev *netdev, const struct netdev_stats *stats)
412 {
413     struct rtnl_link_stats64 rtnl_stats;
414     struct dpif_linux_vport vport;
415     int err;
416
417     rtnl_stats.rx_packets = stats->rx_packets;
418     rtnl_stats.tx_packets = stats->tx_packets;
419     rtnl_stats.rx_bytes = stats->rx_bytes;
420     rtnl_stats.tx_bytes = stats->tx_bytes;
421     rtnl_stats.rx_errors = stats->rx_errors;
422     rtnl_stats.tx_errors = stats->tx_errors;
423     rtnl_stats.rx_dropped = stats->rx_dropped;
424     rtnl_stats.tx_dropped = stats->tx_dropped;
425     rtnl_stats.multicast = stats->multicast;
426     rtnl_stats.collisions = stats->collisions;
427     rtnl_stats.rx_length_errors = stats->rx_length_errors;
428     rtnl_stats.rx_over_errors = stats->rx_over_errors;
429     rtnl_stats.rx_crc_errors = stats->rx_crc_errors;
430     rtnl_stats.rx_frame_errors = stats->rx_frame_errors;
431     rtnl_stats.rx_fifo_errors = stats->rx_fifo_errors;
432     rtnl_stats.rx_missed_errors = stats->rx_missed_errors;
433     rtnl_stats.tx_aborted_errors = stats->tx_aborted_errors;
434     rtnl_stats.tx_carrier_errors = stats->tx_carrier_errors;
435     rtnl_stats.tx_fifo_errors = stats->tx_fifo_errors;
436     rtnl_stats.tx_heartbeat_errors = stats->tx_heartbeat_errors;
437     rtnl_stats.tx_window_errors = stats->tx_window_errors;
438
439     dpif_linux_vport_init(&vport);
440     vport.cmd = ODP_VPORT_CMD_SET;
441     vport.name = netdev_get_name(netdev);
442     vport.stats = &rtnl_stats;
443
444     err = dpif_linux_vport_transact(&vport, NULL, NULL);
445
446     /* If the vport layer doesn't know about the device, that doesn't mean it
447      * doesn't exist (after all were able to open it when netdev_open() was
448      * called), it just means that it isn't attached and we'll be getting
449      * stats a different way. */
450     if (err == ENODEV) {
451         err = EOPNOTSUPP;
452     }
453
454     return err;
455 }
456
457 static int
458 netdev_vport_get_status(const struct netdev *netdev, struct shash *sh)
459 {
460     const char *iface = netdev_vport_get_tnl_iface(netdev);
461
462     if (iface) {
463         struct netdev *egress_netdev;
464
465         shash_add(sh, "tunnel_egress_iface", xstrdup(iface));
466
467         if (!netdev_open_default(iface, &egress_netdev)) {
468             shash_add(sh, "tunnel_egress_iface_carrier",
469                       xstrdup(netdev_get_carrier(egress_netdev)
470                               ? "up" : "down"));
471             netdev_close(egress_netdev);
472         }
473     }
474
475     return 0;
476 }
477
478 static int
479 netdev_vport_update_flags(struct netdev *netdev OVS_UNUSED,
480                         enum netdev_flags off, enum netdev_flags on OVS_UNUSED,
481                         enum netdev_flags *old_flagsp)
482 {
483     if (off & (NETDEV_UP | NETDEV_PROMISC)) {
484         return EOPNOTSUPP;
485     }
486
487     *old_flagsp = NETDEV_UP | NETDEV_PROMISC;
488     return 0;
489 }
490
491 static char *
492 make_poll_name(const struct netdev *netdev)
493 {
494     return xasprintf("%s:%s", netdev_get_type(netdev), netdev_get_name(netdev));
495 }
496
497 static int
498 netdev_vport_poll_add(struct netdev *netdev,
499                       void (*cb)(struct netdev_notifier *), void *aux,
500                       struct netdev_notifier **notifierp)
501 {
502     char *poll_name = make_poll_name(netdev);
503     struct netdev_vport_notifier *notifier;
504     struct list *list;
505     struct shash_node *shash_node;
506
507     shash_node = shash_find(&netdev_vport_notifiers, poll_name);
508     if (!shash_node) {
509         list = xmalloc(sizeof *list);
510         list_init(list);
511         shash_node = shash_add(&netdev_vport_notifiers, poll_name, list);
512     } else {
513         list = shash_node->data;
514     }
515
516     notifier = xmalloc(sizeof *notifier);
517     netdev_notifier_init(&notifier->notifier, netdev, cb, aux);
518     list_push_back(list, &notifier->list_node);
519     notifier->shash_node = shash_node;
520
521     *notifierp = &notifier->notifier;
522     free(poll_name);
523
524     return 0;
525 }
526
527 static void
528 netdev_vport_poll_remove(struct netdev_notifier *notifier_)
529 {
530     struct netdev_vport_notifier *notifier =
531                 CONTAINER_OF(notifier_, struct netdev_vport_notifier, notifier);
532
533     struct list *list;
534
535     list = list_remove(&notifier->list_node);
536     if (list_is_empty(list)) {
537         shash_delete(&netdev_vport_notifiers, notifier->shash_node);
538         free(list);
539     }
540
541     free(notifier);
542 }
543
544 static void
545 netdev_vport_run(void)
546 {
547     route_table_run();
548 }
549
550 static void
551 netdev_vport_wait(void)
552 {
553     route_table_wait();
554 }
555 \f
556 /* get_tnl_iface() implementation. */
557 static const char *
558 netdev_vport_get_tnl_iface(const struct netdev *netdev)
559 {
560     struct nlattr *a[ODP_TUNNEL_ATTR_MAX + 1];
561     uint32_t route;
562     struct netdev_dev_vport *ndv;
563     static char name[IFNAMSIZ];
564
565     ndv = netdev_dev_vport_cast(netdev_get_dev(netdev));
566     if (tnl_port_config_from_nlattr(ndv->options->data, ndv->options->size,
567                                     a)) {
568         return NULL;
569     }
570     route = nl_attr_get_be32(a[ODP_TUNNEL_ATTR_DST_IPV4]);
571
572     if (route_table_get_name(route, name)) {
573         return name;
574     }
575
576     return NULL;
577 }
578 \f
579 /* Helper functions. */
580
581 static void
582 netdev_vport_poll_notify(const struct netdev *netdev)
583 {
584     char *poll_name = make_poll_name(netdev);
585     struct list *list = shash_find_data(&netdev_vport_notifiers,
586                                         poll_name);
587
588     if (list) {
589         struct netdev_vport_notifier *notifier;
590
591         LIST_FOR_EACH (notifier, list_node, list) {
592             struct netdev_notifier *n = &notifier->notifier;
593             n->cb(n);
594         }
595     }
596
597     free(poll_name);
598 }
599 \f
600 /* Code specific to individual vport types. */
601
602 static void
603 set_key(const struct shash *args, const char *name, uint16_t type,
604         struct ofpbuf *options)
605 {
606     const char *s;
607
608     s = shash_find_data(args, name);
609     if (!s) {
610         s = shash_find_data(args, "key");
611         if (!s) {
612             s = "0";
613         }
614     }
615
616     if (!strcmp(s, "flow")) {
617         /* This is the default if no attribute is present. */
618     } else {
619         nl_msg_put_be64(options, type, htonll(strtoull(s, NULL, 0)));
620     }
621 }
622
623 static int
624 parse_tunnel_config(const char *name, const char *type,
625                     const struct shash *args, struct ofpbuf *options)
626 {
627     bool is_gre = false;
628     bool is_ipsec = false;
629     struct shash_node *node;
630     bool ipsec_mech_set = false;
631     ovs_be32 daddr = htonl(0);
632     uint32_t flags;
633
634     flags = TNL_F_PMTUD | TNL_F_HDR_CACHE;
635     if (!strcmp(type, "gre")) {
636         is_gre = true;
637     } else if (!strcmp(type, "ipsec_gre")) {
638         is_gre = true;
639         is_ipsec = true;
640         flags |= TNL_F_IPSEC;
641         flags &= ~TNL_F_HDR_CACHE;
642     }
643
644     SHASH_FOR_EACH (node, args) {
645         if (!strcmp(node->name, "remote_ip")) {
646             struct in_addr in_addr;
647             if (lookup_ip(node->data, &in_addr)) {
648                 VLOG_WARN("%s: bad %s 'remote_ip'", name, type);
649             } else {
650                 daddr = in_addr.s_addr;
651             }
652         } else if (!strcmp(node->name, "local_ip")) {
653             struct in_addr in_addr;
654             if (lookup_ip(node->data, &in_addr)) {
655                 VLOG_WARN("%s: bad %s 'local_ip'", name, type);
656             } else {
657                 nl_msg_put_be32(options, ODP_TUNNEL_ATTR_SRC_IPV4,
658                                 in_addr.s_addr);
659             }
660         } else if (!strcmp(node->name, "tos")) {
661             if (!strcmp(node->data, "inherit")) {
662                 flags |= TNL_F_TOS_INHERIT;
663             } else {
664                 nl_msg_put_u8(options, ODP_TUNNEL_ATTR_TOS, atoi(node->data));
665             }
666         } else if (!strcmp(node->name, "ttl")) {
667             if (!strcmp(node->data, "inherit")) {
668                 flags |= TNL_F_TTL_INHERIT;
669             } else {
670                 nl_msg_put_u8(options, ODP_TUNNEL_ATTR_TTL, atoi(node->data));
671             }
672         } else if (!strcmp(node->name, "csum") && is_gre) {
673             if (!strcmp(node->data, "true")) {
674                 flags |= TNL_F_CSUM;
675             }
676         } else if (!strcmp(node->name, "pmtud")) {
677             if (!strcmp(node->data, "false")) {
678                 flags &= ~TNL_F_PMTUD;
679             }
680         } else if (!strcmp(node->name, "header_cache")) {
681             if (!strcmp(node->data, "false")) {
682                 flags &= ~TNL_F_HDR_CACHE;
683             }
684         } else if (!strcmp(node->name, "peer_cert") && is_ipsec) {
685             if (shash_find(args, "certificate")) {
686                 ipsec_mech_set = true;
687             } else {
688                 const char *use_ssl_cert;
689
690                 /* If the "use_ssl_cert" is true, then "certificate" and
691                  * "private_key" will be pulled from the SSL table.  The
692                  * use of this option is strongly discouraged, since it
693                  * will like be removed when multiple SSL configurations
694                  * are supported by OVS.
695                  */
696                 use_ssl_cert = shash_find_data(args, "use_ssl_cert");
697                 if (!use_ssl_cert || strcmp(use_ssl_cert, "true")) {
698                     VLOG_ERR("%s: 'peer_cert' requires 'certificate' argument",
699                              name);
700                     return EINVAL;
701                 }
702                 ipsec_mech_set = true;
703             }
704         } else if (!strcmp(node->name, "psk") && is_ipsec) {
705             ipsec_mech_set = true;
706         } else if (is_ipsec
707                 && (!strcmp(node->name, "certificate")
708                     || !strcmp(node->name, "private_key")
709                     || !strcmp(node->name, "use_ssl_cert"))) {
710             /* Ignore options not used by the netdev. */
711         } else if (is_gre && (!strcmp(node->name, "key") ||
712                               !strcmp(node->name, "in_key") ||
713                               !strcmp(node->name, "out_key"))) {
714             /* Handled separately below. */
715         } else {
716             VLOG_WARN("%s: unknown %s argument '%s'", name, type, node->name);
717         }
718     }
719
720     if (is_ipsec) {
721         char *file_name = xasprintf("%s/%s", ovs_rundir(),
722                 "ovs-monitor-ipsec.pid");
723         pid_t pid = read_pidfile(file_name);
724         free(file_name);
725         if (pid < 0) {
726             VLOG_ERR("%s: IPsec requires the ovs-monitor-ipsec daemon",
727                      name);
728             return EINVAL;
729         }
730
731         if (shash_find(args, "peer_cert") && shash_find(args, "psk")) {
732             VLOG_ERR("%s: cannot define both 'peer_cert' and 'psk'", name);
733             return EINVAL;
734         }
735
736         if (!ipsec_mech_set) {
737             VLOG_ERR("%s: IPsec requires an 'peer_cert' or psk' argument",
738                      name);
739             return EINVAL;
740         }
741     }
742
743     if (is_gre) {
744         set_key(args, "in_key", ODP_TUNNEL_ATTR_IN_KEY, options);
745         set_key(args, "out_key", ODP_TUNNEL_ATTR_OUT_KEY, options);
746     }
747
748     if (!daddr) {
749         VLOG_ERR("%s: %s type requires valid 'remote_ip' argument",
750                  name, type);
751         return EINVAL;
752     }
753     nl_msg_put_be32(options, ODP_TUNNEL_ATTR_DST_IPV4, daddr);
754
755     nl_msg_put_u32(options, ODP_TUNNEL_ATTR_FLAGS, flags);
756
757     return 0;
758 }
759
760 static int
761 tnl_port_config_from_nlattr(const struct nlattr *options, size_t options_len,
762                             struct nlattr *a[ODP_TUNNEL_ATTR_MAX + 1])
763 {
764     static const struct nl_policy odp_tunnel_policy[] = {
765         [ODP_TUNNEL_ATTR_FLAGS] = { .type = NL_A_U32 },
766         [ODP_TUNNEL_ATTR_DST_IPV4] = { .type = NL_A_BE32 },
767         [ODP_TUNNEL_ATTR_SRC_IPV4] = { .type = NL_A_BE32, .optional = true },
768         [ODP_TUNNEL_ATTR_IN_KEY] = { .type = NL_A_BE64, .optional = true },
769         [ODP_TUNNEL_ATTR_OUT_KEY] = { .type = NL_A_BE64, .optional = true },
770         [ODP_TUNNEL_ATTR_TOS] = { .type = NL_A_U8, .optional = true },
771         [ODP_TUNNEL_ATTR_TTL] = { .type = NL_A_U8, .optional = true },
772     };
773     struct ofpbuf buf;
774
775     ofpbuf_use_const(&buf, options, options_len);
776     if (!nl_policy_parse(&buf, 0, odp_tunnel_policy,
777                          a, ARRAY_SIZE(odp_tunnel_policy))) {
778         return EINVAL;
779     }
780     return 0;
781 }
782
783 static uint64_t
784 get_be64_or_zero(const struct nlattr *a)
785 {
786     return a ? ntohll(nl_attr_get_be64(a)) : 0;
787 }
788
789 static int
790 unparse_tunnel_config(const char *name OVS_UNUSED, const char *type OVS_UNUSED,
791                       const struct nlattr *options, size_t options_len,
792                       struct shash *args)
793 {
794     struct nlattr *a[ODP_TUNNEL_ATTR_MAX + 1];
795     ovs_be32 daddr;
796     uint32_t flags;
797     int error;
798
799     error = tnl_port_config_from_nlattr(options, options_len, a);
800     if (error) {
801         return error;
802     }
803
804     flags = nl_attr_get_u32(a[ODP_TUNNEL_ATTR_FLAGS]);
805     if (!(flags & TNL_F_HDR_CACHE) == !(flags & TNL_F_IPSEC)) {
806         smap_add(args, "header_cache",
807                  flags & TNL_F_HDR_CACHE ? "true" : "false");
808     }
809
810     daddr = nl_attr_get_be32(a[ODP_TUNNEL_ATTR_DST_IPV4]);
811     shash_add(args, "remote_ip", xasprintf(IP_FMT, IP_ARGS(&daddr)));
812
813     if (a[ODP_TUNNEL_ATTR_SRC_IPV4]) {
814         ovs_be32 saddr = nl_attr_get_be32(a[ODP_TUNNEL_ATTR_SRC_IPV4]);
815         shash_add(args, "local_ip", xasprintf(IP_FMT, IP_ARGS(&saddr)));
816     }
817
818     if (!a[ODP_TUNNEL_ATTR_IN_KEY] && !a[ODP_TUNNEL_ATTR_OUT_KEY]) {
819         smap_add(args, "key", "flow");
820     } else {
821         uint64_t in_key = get_be64_or_zero(a[ODP_TUNNEL_ATTR_IN_KEY]);
822         uint64_t out_key = get_be64_or_zero(a[ODP_TUNNEL_ATTR_OUT_KEY]);
823
824         if (in_key && in_key == out_key) {
825             shash_add(args, "key", xasprintf("%"PRIu64, in_key));
826         } else {
827             if (!a[ODP_TUNNEL_ATTR_IN_KEY]) {
828                 smap_add(args, "in_key", "flow");
829             } else if (in_key) {
830                 shash_add(args, "in_key", xasprintf("%"PRIu64, in_key));
831             }
832
833             if (!a[ODP_TUNNEL_ATTR_OUT_KEY]) {
834                 smap_add(args, "out_key", "flow");
835             } else if (out_key) {
836                 shash_add(args, "out_key", xasprintf("%"PRIu64, out_key));
837             }
838         }
839     }
840
841     if (flags & TNL_F_TTL_INHERIT) {
842         smap_add(args, "tos", "inherit");
843     } else if (a[ODP_TUNNEL_ATTR_TTL]) {
844         int ttl = nl_attr_get_u8(a[ODP_TUNNEL_ATTR_TTL]);
845         shash_add(args, "tos", xasprintf("%d", ttl));
846     }
847
848     if (flags & TNL_F_TOS_INHERIT) {
849         smap_add(args, "tos", "inherit");
850     } else if (a[ODP_TUNNEL_ATTR_TOS]) {
851         int tos = nl_attr_get_u8(a[ODP_TUNNEL_ATTR_TOS]);
852         shash_add(args, "tos", xasprintf("%d", tos));
853     }
854
855     if (flags & TNL_F_CSUM) {
856         smap_add(args, "csum", "true");
857     }
858     if (!(flags & TNL_F_PMTUD)) {
859         smap_add(args, "pmtud", "false");
860     }
861
862     return 0;
863 }
864
865 static int
866 parse_patch_config(const char *name, const char *type OVS_UNUSED,
867                    const struct shash *args, struct ofpbuf *options)
868 {
869     const char *peer;
870
871     peer = shash_find_data(args, "peer");
872     if (!peer) {
873         VLOG_ERR("%s: patch type requires valid 'peer' argument", name);
874         return EINVAL;
875     }
876
877     if (shash_count(args) > 1) {
878         VLOG_ERR("%s: patch type takes only a 'peer' argument", name);
879         return EINVAL;
880     }
881
882     if (strlen(peer) >= IFNAMSIZ) {
883         VLOG_ERR("%s: patch 'peer' arg too long", name);
884         return EINVAL;
885     }
886
887     if (!strcmp(name, peer)) {
888         VLOG_ERR("%s: patch peer must not be self", name);
889         return EINVAL;
890     }
891
892     nl_msg_put_string(options, ODP_PATCH_ATTR_PEER, peer);
893
894     return 0;
895 }
896
897 static int
898 unparse_patch_config(const char *name OVS_UNUSED, const char *type OVS_UNUSED,
899                      const struct nlattr *options, size_t options_len,
900                      struct shash *args)
901 {
902     static const struct nl_policy odp_patch_policy[] = {
903         [ODP_PATCH_ATTR_PEER] = { .type = NL_A_STRING,
904                                .max_len = IFNAMSIZ,
905                                .optional = false }
906     };
907
908     struct nlattr *a[ARRAY_SIZE(odp_patch_policy)];
909     struct ofpbuf buf;
910
911     ofpbuf_use_const(&buf, options, options_len);
912     if (!nl_policy_parse(&buf, 0, odp_patch_policy,
913                          a, ARRAY_SIZE(odp_patch_policy))) {
914         return EINVAL;
915     }
916
917     smap_add(args, "peer", nl_attr_get_string(a[ODP_PATCH_ATTR_PEER]));
918     return 0;
919 }
920 \f
921 #define VPORT_FUNCTIONS(GET_STATUS)                         \
922     NULL,                                                   \
923     netdev_vport_run,                                       \
924     netdev_vport_wait,                                      \
925                                                             \
926     netdev_vport_create,                                    \
927     netdev_vport_destroy,                                   \
928     netdev_vport_set_config,                                \
929                                                             \
930     netdev_vport_open,                                      \
931     netdev_vport_close,                                     \
932                                                             \
933     NULL,                       /* enumerate */             \
934                                                             \
935     NULL,                       /* recv */                  \
936     NULL,                       /* recv_wait */             \
937     NULL,                       /* drain */                 \
938                                                             \
939     NULL,                       /* send */                  \
940     NULL,                       /* send_wait */             \
941                                                             \
942     netdev_vport_set_etheraddr,                             \
943     netdev_vport_get_etheraddr,                             \
944     netdev_vport_get_mtu,                                   \
945     NULL,                       /* get_ifindex */           \
946     NULL,                       /* get_carrier */           \
947     NULL,                       /* get_miimon */            \
948     netdev_vport_get_stats,                                 \
949     netdev_vport_set_stats,                                 \
950                                                             \
951     NULL,                       /* get_features */          \
952     NULL,                       /* set_advertisements */    \
953     NULL,                       /* get_vlan_vid */          \
954                                                             \
955     NULL,                       /* set_policing */          \
956     NULL,                       /* get_qos_types */         \
957     NULL,                       /* get_qos_capabilities */  \
958     NULL,                       /* get_qos */               \
959     NULL,                       /* set_qos */               \
960     NULL,                       /* get_queue */             \
961     NULL,                       /* set_queue */             \
962     NULL,                       /* delete_queue */          \
963     NULL,                       /* get_queue_stats */       \
964     NULL,                       /* dump_queues */           \
965     NULL,                       /* dump_queue_stats */      \
966                                                             \
967     NULL,                       /* get_in4 */               \
968     NULL,                       /* set_in4 */               \
969     NULL,                       /* get_in6 */               \
970     NULL,                       /* add_router */            \
971     NULL,                       /* get_next_hop */          \
972     GET_STATUS,                                             \
973     NULL,                       /* arp_lookup */            \
974                                                             \
975     netdev_vport_update_flags,                              \
976                                                             \
977     netdev_vport_poll_add,                                  \
978     netdev_vport_poll_remove,
979
980 void
981 netdev_vport_register(void)
982 {
983     static const struct vport_class vport_classes[] = {
984         { ODP_VPORT_TYPE_GRE,
985           { "gre", VPORT_FUNCTIONS(netdev_vport_get_status) },
986           parse_tunnel_config, unparse_tunnel_config },
987
988         { ODP_VPORT_TYPE_GRE,
989           { "ipsec_gre", VPORT_FUNCTIONS(netdev_vport_get_status) },
990           parse_tunnel_config, unparse_tunnel_config },
991
992         { ODP_VPORT_TYPE_CAPWAP,
993           { "capwap", VPORT_FUNCTIONS(netdev_vport_get_status) },
994           parse_tunnel_config, unparse_tunnel_config },
995
996         { ODP_VPORT_TYPE_PATCH,
997           { "patch", VPORT_FUNCTIONS(NULL) },
998           parse_patch_config, unparse_patch_config }
999     };
1000
1001     int i;
1002
1003     for (i = 0; i < ARRAY_SIZE(vport_classes); i++) {
1004         netdev_register_provider(&vport_classes[i].netdev_class);
1005     }
1006 }