openvswitch: Userspace tunneling.
[cascardo/ovs.git] / lib / netdev-bsd.c
index cb4f5e8..473c0f6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2013 Gaetano Catalli.
+ * Copyright (c) 2011, 2013, 2014 Gaetano Catalli.
  * Copyright (c) 2013, 2014 YAMAMOTO Takashi.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -47,7 +47,6 @@
 #endif
 
 #include "rtbsd.h"
-#include "connectivity.h"
 #include "coverage.h"
 #include "dpif-netdev.h"
 #include "dynamic-string.h"
@@ -55,9 +54,9 @@
 #include "ofpbuf.h"
 #include "openflow/openflow.h"
 #include "ovs-thread.h"
+#include "packet-dpif.h"
 #include "packets.h"
 #include "poll-loop.h"
-#include "seq.h"
 #include "shash.h"
 #include "socket-util.h"
 #include "svec.h"
@@ -217,7 +216,7 @@ netdev_bsd_cache_cb(const struct rtbsd_change *change,
             if (is_netdev_bsd_class(netdev_class)) {
                 dev = netdev_bsd_cast(base_dev);
                 dev->cache_valid = 0;
-                seq_change(connectivity_seq_get());
+                netdev_change_seq_changed(base_dev);
             }
             netdev_close(base_dev);
         }
@@ -235,7 +234,7 @@ netdev_bsd_cache_cb(const struct rtbsd_change *change,
             struct netdev *netdev = node->data;
             dev = netdev_bsd_cast(netdev);
             dev->cache_valid = 0;
-            seq_change(connectivity_seq_get());
+            netdev_change_seq_changed(netdev);
             netdev_close(netdev);
         }
         shash_destroy(&device_shash);
@@ -249,7 +248,7 @@ cache_notifier_ref(void)
 
     if (!cache_notifier_refcount) {
         ret = rtbsd_notifier_register(&netdev_bsd_cache_notifier,
-                                                netdev_bsd_cache_cb, NULL);
+                                      netdev_bsd_cache_cb, NULL);
         if (ret) {
             return ret;
         }
@@ -550,7 +549,7 @@ struct pcap_arg {
 static void
 proc_pkt(u_char *args_, const struct pcap_pkthdr *hdr, const u_char *packet)
 {
-    struct pcap_arg *args = (struct pcap_arg *)args_;
+    struct pcap_arg *args = ALIGNED_CAST(struct pcap_arg *, args_);
 
     if (args->size < hdr->len) {
         VLOG_WARN_RL(&rl, "packet truncated");
@@ -622,10 +621,12 @@ netdev_rxq_bsd_recv_tap(struct netdev_rxq_bsd *rxq, struct ofpbuf *buffer)
 }
 
 static int
-netdev_bsd_rxq_recv(struct netdev_rxq *rxq_, struct ofpbuf **packet, int *c)
+netdev_bsd_rxq_recv(struct netdev_rxq *rxq_, struct dpif_packet **packets,
+                    int *c)
 {
     struct netdev_rxq_bsd *rxq = netdev_rxq_bsd_cast(rxq_);
     struct netdev *netdev = rxq->up.netdev;
+    struct dpif_packet *packet;
     struct ofpbuf *buffer;
     ssize_t retval;
     int mtu;
@@ -634,17 +635,20 @@ netdev_bsd_rxq_recv(struct netdev_rxq *rxq_, struct ofpbuf **packet, int *c)
         mtu = ETH_PAYLOAD_MAX;
     }
 
-    buffer = ofpbuf_new_with_headroom(VLAN_ETH_HEADER_LEN + mtu, DP_NETDEV_HEADROOM);
+    packet = dpif_packet_new_with_headroom(VLAN_ETH_HEADER_LEN + mtu,
+                                           DP_NETDEV_HEADROOM);
+    buffer = &packet->ofpbuf;
 
     retval = (rxq->pcap_handle
             ? netdev_rxq_bsd_recv_pcap(rxq, buffer)
             : netdev_rxq_bsd_recv_tap(rxq, buffer));
 
     if (retval) {
-        ofpbuf_delete(buffer);
+        dpif_packet_delete(packet);
     } else {
         dp_packet_pad(buffer);
-        packet[0] = buffer;
+        dpif_packet_set_dp_hash(packet, 0);
+        packets[0] = packet;
         *c = 1;
     }
     return retval;
@@ -683,13 +687,13 @@ netdev_bsd_rxq_drain(struct netdev_rxq *rxq_)
  * system or a tap device.
  */
 static int
-netdev_bsd_send(struct netdev *netdev_, struct ofpbuf *pkt, bool may_steal)
+netdev_bsd_send(struct netdev *netdev_, int qid OVS_UNUSED,
+                struct dpif_packet **pkts, int cnt, bool may_steal)
 {
     struct netdev_bsd *dev = netdev_bsd_cast(netdev_);
     const char *name = netdev_get_name(netdev_);
-    const void *data = ofpbuf_data(pkt);
-    size_t size = ofpbuf_size(pkt);
     int error;
+    int i;
 
     ovs_mutex_lock(&dev->mutex);
     if (dev->tap_fd < 0 && !dev->pcap) {
@@ -698,35 +702,43 @@ netdev_bsd_send(struct netdev *netdev_, struct ofpbuf *pkt, bool may_steal)
         error = 0;
     }
 
-    while (!error) {
-        ssize_t retval;
-        if (dev->tap_fd >= 0) {
-            retval = write(dev->tap_fd, data, size);
-        } else {
-            retval = pcap_inject(dev->pcap, data, size);
-        }
-        if (retval < 0) {
-            if (errno == EINTR) {
-                continue;
+    for (i = 0; i < cnt; i++) {
+        const void *data = ofpbuf_data(&pkts[i]->ofpbuf);
+        size_t size = ofpbuf_size(&pkts[i]->ofpbuf);
+
+        while (!error) {
+            ssize_t retval;
+            if (dev->tap_fd >= 0) {
+                retval = write(dev->tap_fd, data, size);
             } else {
-                error = errno;
-                if (error != EAGAIN) {
-                    VLOG_WARN_RL(&rl, "error sending Ethernet packet on %s: "
-                                 "%s", name, ovs_strerror(error));
+                retval = pcap_inject(dev->pcap, data, size);
+            }
+            if (retval < 0) {
+                if (errno == EINTR) {
+                    continue;
+                } else {
+                    error = errno;
+                    if (error != EAGAIN) {
+                        VLOG_WARN_RL(&rl, "error sending Ethernet packet on"
+                                     " %s: %s", name, ovs_strerror(error));
+                    }
                 }
+            } else if (retval != size) {
+                VLOG_WARN_RL(&rl, "sent partial Ethernet packet "
+                                  "(%"PRIuSIZE" bytes of "
+                                  "%"PRIuSIZE") on %s", retval, size, name);
+                error = EMSGSIZE;
+            } else {
+                break;
             }
-        } else if (retval != size) {
-            VLOG_WARN_RL(&rl, "sent partial Ethernet packet (%"PRIuSIZE"d bytes of "
-                         "%"PRIuSIZE") on %s", retval, size, name);
-            error = EMSGSIZE;
-        } else {
-            break;
         }
     }
 
     ovs_mutex_unlock(&dev->mutex);
     if (may_steal) {
-        ofpbuf_delete(pkt);
+        for (i = 0; i < cnt; i++) {
+            dpif_packet_delete(pkts[i]);
+        }
     }
 
     return error;
@@ -738,7 +750,7 @@ netdev_bsd_send(struct netdev *netdev_, struct ofpbuf *pkt, bool may_steal)
  * with netdev_send().
  */
 static void
-netdev_bsd_send_wait(struct netdev *netdev_)
+netdev_bsd_send_wait(struct netdev *netdev_, int qid OVS_UNUSED)
 {
     struct netdev_bsd *dev = netdev_bsd_cast(netdev_);
 
@@ -774,7 +786,7 @@ netdev_bsd_set_etheraddr(struct netdev *netdev_,
         if (!error) {
             netdev->cache_valid |= VALID_ETHERADDR;
             memcpy(netdev->etheraddr, mac, ETH_ADDR_LEN);
-            seq_change(connectivity_seq_get());
+            netdev_change_seq_changed(netdev_);
         }
     }
     ovs_mutex_unlock(&netdev->mutex);
@@ -998,7 +1010,7 @@ netdev_bsd_get_stats(const struct netdev *netdev_, struct netdev_stats *stats)
                         netdev_get_name(netdev_), ovs_strerror(errno));
             return errno;
         } else if (!strcmp(ifmd.ifmd_name, netdev_get_name(netdev_))) {
-            convert_stats(netdev, stats, &ifdr.ifdr_data);
+            convert_stats(netdev_, stats, &ifmd.ifmd_data);
             break;
         }
     }
@@ -1185,7 +1197,7 @@ netdev_bsd_get_in4(const struct netdev *netdev_, struct in_addr *in4,
         if (!error) {
             const struct sockaddr_in *sin;
 
-            sin = (struct sockaddr_in *) &ifr.ifr_addr;
+            sin = ALIGNED_CAST(struct sockaddr_in *, &ifr.ifr_addr);
             netdev->in4 = sin->sin_addr;
             netdev->cache_valid |= VALID_IN4;
             error = af_inet_ifreq_ioctl(netdev_get_kernel_name(netdev_), &ifr,
@@ -1228,7 +1240,7 @@ netdev_bsd_set_in4(struct netdev *netdev_, struct in_addr addr,
                 netdev->netmask = mask;
             }
         }
-        seq_change(connectivity_seq_get());
+        netdev_change_seq_changed(netdev_);
     }
     ovs_mutex_unlock(&netdev->mutex);
 
@@ -1253,7 +1265,7 @@ netdev_bsd_get_in6(const struct netdev *netdev_, struct in6_addr *in6)
         for (ifa = head; ifa; ifa = ifa->ifa_next) {
             if (ifa->ifa_addr->sa_family == AF_INET6 &&
                     !strcmp(ifa->ifa_name, netdev_name)) {
-                sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
+                sin6 = ALIGNED_CAST(struct sockaddr_in6 *, ifa->ifa_addr);
                 if (sin6) {
                     memcpy(&netdev->in6, &sin6->sin6_addr, sin6->sin6_len);
                     netdev->cache_valid |= VALID_IN6;
@@ -1365,14 +1377,14 @@ netdev_bsd_get_next_hop(const struct in_addr *host OVS_UNUSED,
 
             if ((i == RTA_GATEWAY) && sa->sa_family == AF_INET) {
                 const struct sockaddr_in * const sin =
-                  (const struct sockaddr_in *)sa;
+                  ALIGNED_CAST(const struct sockaddr_in *, sa);
 
                 *next_hop = sin->sin_addr;
                 gateway = true;
             }
             if ((i == RTA_IFP) && sa->sa_family == AF_LINK) {
                 const struct sockaddr_dl * const sdl =
-                  (const struct sockaddr_dl *)sa;
+                  ALIGNED_CAST(const struct sockaddr_dl *, sa);
                 char *kernel_name;
 
                 kernel_name = xmemdup0(sdl->sdl_data, sdl->sdl_nlen);
@@ -1526,7 +1538,7 @@ netdev_bsd_update_flags(struct netdev *netdev_, enum netdev_flags off,
         new_flags = (old_flags & ~nd_to_iff_flags(off)) | nd_to_iff_flags(on);
         if (new_flags != old_flags) {
             error = set_flags(netdev_get_kernel_name(netdev_), new_flags);
-            seq_change(connectivity_seq_get());
+            netdev_change_seq_changed(netdev_);
         }
     }
     return error;
@@ -1550,6 +1562,11 @@ netdev_bsd_update_flags(struct netdev *netdev_, enum netdev_flags off,
     NULL, /* get_config */                           \
     NULL, /* set_config */                           \
     NULL, /* get_tunnel_config */                    \
+    NULL, /* build header */                         \
+    NULL, /* push header */                          \
+    NULL, /* pop header */                           \
+    NULL, /* get_numa_id */                          \
+    NULL, /* set_multiq */                           \
                                                      \
     netdev_bsd_send,                                 \
     netdev_bsd_send_wait,                            \
@@ -1563,7 +1580,6 @@ netdev_bsd_update_flags(struct netdev *netdev_, enum netdev_flags off,
     NULL, /* get_carrier_resets */                   \
     NULL, /* set_miimon_interval */                  \
     netdev_bsd_get_stats,                            \
-    NULL, /* set_stats */                            \
                                                      \
     GET_FEATURES,                                    \
     NULL, /* set_advertisement */                    \
@@ -1681,7 +1697,7 @@ get_etheraddr(const char *netdev_name, uint8_t ea[ETH_ADDR_LEN])
     for (ifa = head; ifa; ifa = ifa->ifa_next) {
         if (ifa->ifa_addr->sa_family == AF_LINK) {
             if (!strcmp(ifa->ifa_name, netdev_name)) {
-                sdl = (struct sockaddr_dl *)ifa->ifa_addr;
+                sdl = ALIGNED_CAST(struct sockaddr_dl *, ifa->ifa_addr);
                 if (sdl) {
                     memcpy(ea, LLADDR(sdl), sdl->sdl_alen);
                     freeifaddrs(head);
@@ -1788,6 +1804,7 @@ ifr_set_flags(struct ifreq *ifr, int flags)
 #endif
 }
 
+#if defined(__NetBSD__)
 /* Calls ioctl() on an AF_LINK sock, passing the specified 'command' and
  * 'arg'.  Returns 0 if successful, otherwise a positive errno value. */
 int
@@ -1809,3 +1826,4 @@ af_link_ioctl(unsigned long command, const void *arg)
             : ioctl(sock, command, arg) == -1 ? errno
             : 0);
 }
+#endif