2 * Copyright (c) 2010, 2011, 2012 Nicira Networks.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
20 #include <sys/socket.h>
21 #include <netinet/in.h>
22 #include <arpa/inet.h>
27 #include "netdev-provider.h"
29 #include "ofp-print.h"
32 #include "poll-loop.h"
36 #include "socket-util.h"
39 VLOG_DEFINE_THIS_MODULE(netdev_tunnel);
41 struct netdev_dev_tunnel {
43 uint8_t hwaddr[ETH_ADDR_LEN];
44 struct netdev_stats stats;
45 enum netdev_flags flags;
47 struct sockaddr_in local_addr;
48 struct sockaddr_in remote_addr;
50 bool valid_remote_port;
52 unsigned int change_seq;
55 struct netdev_tunnel {
59 struct netdev_rx_tunnel {
64 static const struct netdev_rx_class netdev_rx_tunnel_class;
66 static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 20);
68 static struct shash tunnel_netdev_devs = SHASH_INITIALIZER(&tunnel_netdev_devs);
70 static int netdev_tunnel_create(const struct netdev_class *, const char *,
71 struct netdev_dev **);
72 static void netdev_tunnel_update_seq(struct netdev_dev_tunnel *);
75 is_netdev_tunnel_class(const struct netdev_class *class)
77 return class->create == netdev_tunnel_create;
80 static struct netdev_dev_tunnel *
81 netdev_dev_tunnel_cast(const struct netdev_dev *netdev_dev)
83 ovs_assert(is_netdev_tunnel_class(netdev_dev_get_class(netdev_dev)));
84 return CONTAINER_OF(netdev_dev, struct netdev_dev_tunnel, up);
87 static struct netdev_tunnel *
88 netdev_tunnel_cast(const struct netdev *netdev)
90 struct netdev_dev *netdev_dev = netdev_get_dev(netdev);
91 ovs_assert(is_netdev_tunnel_class(netdev_dev_get_class(netdev_dev)));
92 return CONTAINER_OF(netdev, struct netdev_tunnel, up);
95 static struct netdev_rx_tunnel *
96 netdev_rx_tunnel_cast(const struct netdev_rx *rx)
98 netdev_rx_assert_class(rx, &netdev_rx_tunnel_class);
99 return CONTAINER_OF(rx, struct netdev_rx_tunnel, up);
103 netdev_tunnel_create(const struct netdev_class *class, const char *name,
104 struct netdev_dev **netdev_devp)
106 static unsigned int n = 0;
107 struct netdev_dev_tunnel *netdev_dev;
110 netdev_dev = xzalloc(sizeof *netdev_dev);
111 netdev_dev_init(&netdev_dev->up, name, class);
112 netdev_dev->hwaddr[0] = 0xfe;
113 netdev_dev->hwaddr[1] = 0xff;
114 netdev_dev->hwaddr[2] = 0xff;
115 netdev_dev->hwaddr[3] = n >> 16;
116 netdev_dev->hwaddr[4] = n >> 8;
117 netdev_dev->hwaddr[5] = n;
118 netdev_dev->flags = 0;
119 netdev_dev->change_seq = 1;
120 memset(&netdev_dev->remote_addr, 0, sizeof(netdev_dev->remote_addr));
121 netdev_dev->valid_remote_ip = false;
122 netdev_dev->valid_remote_port = false;
123 netdev_dev->connected = false;
126 netdev_dev->sockfd = inet_open_passive(SOCK_DGRAM, "", 0, &netdev_dev->local_addr, 0);
127 if (netdev_dev->sockfd < 0) {
128 error = netdev_dev->sockfd;
133 shash_add(&tunnel_netdev_devs, name, netdev_dev);
137 *netdev_devp = &netdev_dev->up;
139 VLOG_DBG("tunnel_create: name=%s, fd=%d, port=%d", name, netdev_dev->sockfd, netdev_dev->local_addr.sin_port);
149 netdev_tunnel_destroy(struct netdev_dev *netdev_dev_)
151 struct netdev_dev_tunnel *netdev_dev = netdev_dev_tunnel_cast(netdev_dev_);
153 if (netdev_dev->sockfd != -1)
154 close(netdev_dev->sockfd);
156 shash_find_and_delete(&tunnel_netdev_devs,
157 netdev_dev_get_name(netdev_dev_));
162 netdev_tunnel_open(struct netdev_dev *netdev_dev_, struct netdev **netdevp)
164 struct netdev_tunnel *netdev;
166 netdev = xmalloc(sizeof *netdev);
167 netdev_init(&netdev->up, netdev_dev_);
169 *netdevp = &netdev->up;
174 netdev_tunnel_close(struct netdev *netdev_)
176 struct netdev_tunnel *netdev = netdev_tunnel_cast(netdev_);
181 netdev_tunnel_get_config(struct netdev_dev *dev_, struct smap *args)
183 struct netdev_dev_tunnel *netdev_dev = netdev_dev_tunnel_cast(dev_);
185 if (netdev_dev->valid_remote_ip)
186 smap_add_format(args, "remote_ip", IP_FMT,
187 IP_ARGS(netdev_dev->remote_addr.sin_addr.s_addr));
188 if (netdev_dev->valid_remote_port)
189 smap_add_format(args, "remote_port", "%"PRIu16,
190 ntohs(netdev_dev->remote_addr.sin_port));
195 netdev_tunnel_connect(struct netdev_dev_tunnel *dev)
199 if (!dev->valid_remote_ip || !dev->valid_remote_port)
201 dev->remote_addr.sin_family = AF_INET;
202 if (connect(dev->sockfd, (struct sockaddr*) &dev->remote_addr, sizeof(dev->remote_addr)) < 0) {
205 dev->connected = true;
206 netdev_tunnel_update_seq(dev);
207 VLOG_DBG("%s: connected to (%s, %d)", netdev_dev_get_name(&dev->up),
208 inet_ntoa(dev->remote_addr.sin_addr), ntohs(dev->remote_addr.sin_port));
213 netdev_tunnel_set_config(struct netdev_dev *dev_, const struct smap *args)
215 struct netdev_dev_tunnel *netdev_dev = netdev_dev_tunnel_cast(dev_);
216 struct shash_node *node;
218 VLOG_DBG("tunnel_set_config(%s)", netdev_dev_get_name(dev_));
219 SMAP_FOR_EACH(node, args) {
220 VLOG_DBG("arg: %s->%s", node->name, (char*)node->data);
221 if (!strcmp(node->name, "remote_ip")) {
223 if (lookup_ip(node->data, &addr)) {
224 VLOG_WARN("%s: bad 'remote_ip'", node->name);
226 netdev_dev->remote_addr.sin_addr = addr;
227 netdev_dev->valid_remote_ip = true;
229 } else if (!strcmp(node->name, "remote_port")) {
230 netdev_dev->remote_addr.sin_port = htons(atoi(node->data));
231 netdev_dev->valid_remote_port = true;
233 VLOG_WARN("%s: unknown argument '%s'",
234 netdev_dev_get_name(dev_), node->name);
237 return netdev_tunnel_connect(netdev_dev);
241 netdev_tunnel_rx_open(struct netdev *netdev_, struct netdev_rx **rxp)
243 struct netdev_dev_tunnel *netdev_dev =
244 netdev_dev_tunnel_cast(netdev_get_dev(netdev_));
245 struct netdev_rx_tunnel *rx;
246 rx = xmalloc(sizeof *rx);
247 netdev_rx_init(&rx->up, netdev_get_dev(netdev_), &netdev_rx_tunnel_class);
248 rx->fd = netdev_dev->sockfd;
254 netdev_rx_tunnel_destroy(struct netdev_rx *rx_)
256 struct netdev_rx_tunnel *rx = netdev_rx_tunnel_cast(rx_);
261 netdev_rx_tunnel_recv(struct netdev_rx *rx_, void *buffer, size_t size)
263 struct netdev_rx_tunnel *rx = netdev_rx_tunnel_cast(rx_);
264 struct netdev_dev_tunnel *netdev_dev =
265 netdev_dev_tunnel_cast(rx_->netdev_dev);
266 if (!netdev_dev->connected)
270 retval = recv(rx->fd, buffer, size, MSG_TRUNC);
271 VLOG_DBG("%s: recv(%"PRIxPTR", %zu, MSG_TRUNC) = %zd",
272 netdev_rx_get_name(rx_), (uintptr_t)buffer, size, retval);
274 netdev_dev->stats.rx_packets++;
275 netdev_dev->stats.rx_bytes += retval;
276 if (retval <= size) {
279 netdev_dev->stats.rx_errors++;
280 netdev_dev->stats.rx_length_errors++;
283 } else if (errno != EINTR) {
284 if (errno != EAGAIN) {
285 VLOG_WARN_RL(&rl, "error receiveing Ethernet packet on %s: %s",
286 netdev_rx_get_name(rx_), strerror(errno));
287 netdev_dev->stats.rx_errors++;
295 netdev_rx_tunnel_wait(struct netdev_rx *rx_)
297 struct netdev_rx_tunnel *rx =
298 netdev_rx_tunnel_cast(rx_);
300 poll_fd_wait(rx->fd, POLLIN);
305 netdev_tunnel_send(struct netdev *netdev_, const void *buffer, size_t size)
307 struct netdev_dev_tunnel *dev =
308 netdev_dev_tunnel_cast(netdev_get_dev(netdev_));
313 retval = send(dev->sockfd, buffer, size, 0);
314 VLOG_DBG("%s: send(%"PRIxPTR", %zu) = %zd",
315 netdev_get_name(netdev_), (uintptr_t)buffer, size, retval);
317 dev->stats.tx_packets++;
318 dev->stats.tx_bytes += retval;
319 if (retval != size) {
320 VLOG_WARN_RL(&rl, "sent partial Ethernet packet (%zd bytes of "
321 "%zu) on %s", retval, size, netdev_get_name(netdev_));
322 dev->stats.tx_errors++;
325 } else if (errno != EINTR) {
326 if (errno != EAGAIN) {
327 VLOG_WARN_RL(&rl, "error sending Ethernet packet on %s: %s",
328 netdev_get_name(netdev_), strerror(errno));
329 dev->stats.tx_errors++;
337 netdev_tunnel_send_wait(struct netdev *netdev_)
339 struct netdev_dev_tunnel *dev =
340 netdev_dev_tunnel_cast(netdev_get_dev(netdev_));
341 if (dev->sockfd >= 0) {
342 poll_fd_wait(dev->sockfd, POLLOUT);
347 netdev_rx_tunnel_drain(struct netdev_rx *rx_)
349 struct netdev_dev_tunnel *netdev_dev =
350 netdev_dev_tunnel_cast(rx_->netdev_dev);
351 struct netdev_rx_tunnel *rx =
352 netdev_rx_tunnel_cast(rx_);
356 if (!netdev_dev->connected)
359 error = recv(rx->fd, buffer, 128, MSG_TRUNC);
361 if (error == -EAGAIN)
363 else if (error != -EMSGSIZE)
371 netdev_tunnel_set_etheraddr(struct netdev *netdev,
372 const uint8_t mac[ETH_ADDR_LEN])
374 struct netdev_dev_tunnel *dev =
375 netdev_dev_tunnel_cast(netdev_get_dev(netdev));
377 if (!eth_addr_equals(dev->hwaddr, mac)) {
378 memcpy(dev->hwaddr, mac, ETH_ADDR_LEN);
379 netdev_tunnel_update_seq(dev);
386 netdev_tunnel_get_etheraddr(const struct netdev *netdev,
387 uint8_t mac[ETH_ADDR_LEN])
389 const struct netdev_dev_tunnel *dev =
390 netdev_dev_tunnel_cast(netdev_get_dev(netdev));
392 memcpy(mac, dev->hwaddr, ETH_ADDR_LEN);
398 netdev_tunnel_get_stats(const struct netdev *netdev, struct netdev_stats *stats)
400 const struct netdev_dev_tunnel *dev =
401 netdev_dev_tunnel_cast(netdev_get_dev(netdev));
408 netdev_tunnel_set_stats(struct netdev *netdev, const struct netdev_stats *stats)
410 struct netdev_dev_tunnel *dev =
411 netdev_dev_tunnel_cast(netdev_get_dev(netdev));
418 netdev_tunnel_update_flags(struct netdev_dev *dev_,
419 enum netdev_flags off, enum netdev_flags on,
420 enum netdev_flags *old_flagsp)
422 struct netdev_dev_tunnel *netdev_dev =
423 netdev_dev_tunnel_cast(dev_);
425 if ((off | on) & ~(NETDEV_UP | NETDEV_PROMISC)) {
429 // XXX should we actually do something with these flags?
430 *old_flagsp = netdev_dev->flags;
431 netdev_dev->flags |= on;
432 netdev_dev->flags &= ~off;
433 if (*old_flagsp != netdev_dev->flags) {
434 netdev_tunnel_update_seq(netdev_dev);
440 netdev_tunnel_change_seq(const struct netdev *netdev)
442 return netdev_dev_tunnel_cast(netdev_get_dev(netdev))->change_seq;
445 /* Helper functions. */
448 netdev_tunnel_update_seq(struct netdev_dev_tunnel *dev)
451 if (!dev->change_seq) {
457 netdev_tunnel_get_port(struct unixctl_conn *conn,
458 int argc OVS_UNUSED, const char *argv[], void *aux OVS_UNUSED)
460 struct netdev_dev_tunnel *tunnel_dev;
463 tunnel_dev = shash_find_data(&tunnel_netdev_devs, argv[1]);
465 unixctl_command_reply_error(conn, "no such tunnel netdev");
469 sprintf(buf, "%d", ntohs(tunnel_dev->local_addr.sin_port));
470 unixctl_command_reply(conn, buf);
474 netdev_tunnel_get_tx_bytes(struct unixctl_conn *conn,
475 int argc OVS_UNUSED, const char *argv[], void *aux OVS_UNUSED)
477 struct netdev_dev_tunnel *tunnel_dev;
480 tunnel_dev = shash_find_data(&tunnel_netdev_devs, argv[1]);
482 unixctl_command_reply_error(conn, "no such tunnel netdev");
486 sprintf(buf, "%"PRIu64, tunnel_dev->stats.tx_bytes);
487 unixctl_command_reply(conn, buf);
491 netdev_tunnel_get_rx_bytes(struct unixctl_conn *conn,
492 int argc OVS_UNUSED, const char *argv[], void *aux OVS_UNUSED)
494 struct netdev_dev_tunnel *tunnel_dev;
497 tunnel_dev = shash_find_data(&tunnel_netdev_devs, argv[1]);
499 unixctl_command_reply_error(conn, "no such tunnel netdev");
503 sprintf(buf, "%"PRIu64, tunnel_dev->stats.rx_bytes);
504 unixctl_command_reply(conn, buf);
509 netdev_tunnel_init(void)
511 unixctl_command_register("netdev-tunnel/get-port", "NAME",
512 1, 1, netdev_tunnel_get_port, NULL);
513 unixctl_command_register("netdev-tunnel/get-tx-bytes", "NAME",
514 1, 1, netdev_tunnel_get_tx_bytes, NULL);
515 unixctl_command_register("netdev-tunnel/get-rx-bytes", "NAME",
516 1, 1, netdev_tunnel_get_rx_bytes, NULL);
520 const struct netdev_class netdev_tunnel_class = {
522 netdev_tunnel_init, /* init */
526 netdev_tunnel_create,
527 netdev_tunnel_destroy,
528 netdev_tunnel_get_config,
529 netdev_tunnel_set_config,
530 NULL, /* get_tunnel_config */
535 netdev_tunnel_rx_open,
538 netdev_tunnel_send_wait,
540 netdev_tunnel_set_etheraddr,
541 netdev_tunnel_get_etheraddr,
544 NULL, /* get_ifindex */
545 NULL, /* get_carrier */
546 NULL, /* get_carrier_resets */
547 NULL, /* get_miimon */
548 netdev_tunnel_get_stats,
549 netdev_tunnel_set_stats,
551 NULL, /* get_features */
552 NULL, /* set_advertisements */
554 NULL, /* set_policing */
555 NULL, /* get_qos_types */
556 NULL, /* get_qos_capabilities */
559 NULL, /* get_queue */
560 NULL, /* set_queue */
561 NULL, /* delete_queue */
562 NULL, /* get_queue_stats */
563 NULL, /* dump_queues */
564 NULL, /* dump_queue_stats */
569 NULL, /* add_router */
570 NULL, /* get_next_hop */
571 NULL, /* get_drv_info */
572 NULL, /* arp_lookup */
574 netdev_tunnel_update_flags,
576 netdev_tunnel_change_seq
580 static const struct netdev_rx_class netdev_rx_tunnel_class = {
581 netdev_rx_tunnel_destroy,
582 netdev_rx_tunnel_recv,
583 netdev_rx_tunnel_wait,
584 netdev_rx_tunnel_drain,