#include "flow.h"
#include "list.h"
+#include "dpif-netdev.h"
#include "netdev-provider.h"
#include "odp-util.h"
#include "ofp-print.h"
struct netdev_stats stats;
enum netdev_flags flags;
int sockfd;
- struct sockaddr_in local_addr;
- struct sockaddr_in remote_addr;
+ struct sockaddr_storage local_addr;
+ struct sockaddr_storage remote_addr;
bool valid_remote_ip;
bool valid_remote_port;
bool connected;
unsigned int change_seq;
};
-struct netdev_rx_tunnel {
- struct netdev_rx up;
+struct netdev_rxq_tunnel {
+ struct netdev_rxq up;
int fd;
};
return CONTAINER_OF(netdev, struct netdev_tunnel, up);
}
-static struct netdev_rx_tunnel *
-netdev_rx_tunnel_cast(const struct netdev_rx *rx)
+static struct netdev_rxq_tunnel *
+netdev_rxq_tunnel_cast(const struct netdev_rxq *rx)
{
ovs_assert(is_netdev_tunnel_class(netdev_get_class(rx->netdev)));
- return CONTAINER_OF(rx, struct netdev_rx_tunnel, up);
+ return CONTAINER_OF(rx, struct netdev_rxq_tunnel, up);
}
static struct netdev *
netdev->connected = false;
- netdev->sockfd = inet_open_passive(SOCK_DGRAM, "", 0, &netdev->local_addr, 0);
+ netdev->sockfd = inet_open_passive(SOCK_DGRAM, "", 0,
+ &netdev->local_addr, 0);
if (netdev->sockfd < 0) {
return netdev->sockfd;
}
n++;
VLOG_DBG("tunnel_create: name=%s, fd=%d, port=%d",
- netdev_get_name(netdev_), netdev->sockfd, netdev->local_addr.sin_port);
+ netdev_get_name(netdev_), netdev->sockfd, ss_get_port(&netdev->local_addr));
return 0;
struct netdev_tunnel *netdev = netdev_tunnel_cast(dev_);
ovs_mutex_lock(&netdev->mutex);
- if (netdev->valid_remote_ip)
- smap_add_format(args, "remote_ip", IP_FMT,
- IP_ARGS(netdev->remote_addr.sin_addr.s_addr));
+ if (netdev->valid_remote_ip) {
+ const struct sockaddr_in *sin =
+ ALIGNED_CAST(const struct sockaddr_in *, &netdev->remote_addr);
+ smap_add_format(args, "remote_ip", IP_FMT,
+ IP_ARGS(sin->sin_addr.s_addr));
+ }
if (netdev->valid_remote_port)
smap_add_format(args, "remote_port", "%"PRIu16,
- ntohs(netdev->remote_addr.sin_port));
+ ss_get_port(&netdev->remote_addr));
ovs_mutex_unlock(&netdev->mutex);
return 0;
}
OVS_REQUIRES(dev->mutex)
{
char buf[1024];
+ struct sockaddr_in *sin =
+ ALIGNED_CAST(struct sockaddr_in *, &dev->remote_addr);
if (dev->sockfd < 0)
return EBADF;
if (!dev->valid_remote_ip || !dev->valid_remote_port)
return 0;
- dev->remote_addr.sin_family = AF_INET;
- if (connect(dev->sockfd, (struct sockaddr*) &dev->remote_addr, sizeof(dev->remote_addr)) < 0) {
+ if (connect(dev->sockfd, (struct sockaddr*) sin, sizeof(*sin)) < 0) {
+ VLOG_DBG("%s: connect returned %s", netdev_get_name(&dev->up),
+ ovs_strerror(errno));
return errno;
}
dev->connected = true;
netdev_tunnel_update_seq(dev);
VLOG_DBG("%s: connected to (%s, %d)", netdev_get_name(&dev->up),
- inet_ntop(AF_INET, &dev->remote_addr.sin_addr, buf, 1024), ntohs(dev->remote_addr.sin_port));
+ inet_ntop(AF_INET, &sin->sin_addr.s_addr, buf, 1024),
+ ss_get_port(&dev->remote_addr));
return 0;
}
struct netdev_tunnel *netdev = netdev_tunnel_cast(dev_);
struct shash_node *node;
int error;
+ struct sockaddr_in *sin =
+ ALIGNED_CAST(struct sockaddr_in *, &netdev->remote_addr);
ovs_mutex_lock(&netdev->mutex);
VLOG_DBG("tunnel_set_config(%s)", netdev_get_name(dev_));
SMAP_FOR_EACH(node, args) {
VLOG_DBG("arg: %s->%s", node->name, (char*)node->data);
- if (!strcmp(node->name, "remote_ip")) {
- struct in_addr addr;
- if (lookup_ip(node->data, &addr)) {
- VLOG_WARN("%s: bad 'remote_ip'", node->name);
- } else {
- netdev->remote_addr.sin_addr = addr;
- netdev->valid_remote_ip = true;
- }
- } else if (!strcmp(node->name, "remote_port")) {
- netdev->remote_addr.sin_port = htons(atoi(node->data));
- netdev->valid_remote_port = true;
- } else {
- VLOG_WARN("%s: unknown argument '%s'",
- netdev_get_name(dev_), node->name);
- }
+ if (!strcmp(node->name, "remote_ip")) {
+ struct in_addr addr;
+ if (lookup_ip(node->data, &addr)) {
+ VLOG_WARN("%s: bad 'remote_ip'", node->name);
+ } else {
+ sin->sin_family = AF_INET;
+ sin->sin_addr = addr;
+ netdev->valid_remote_ip = true;
+ }
+ } else if (!strcmp(node->name, "remote_port")) {
+ sin->sin_port = htons(atoi(node->data));
+ netdev->valid_remote_port = true;
+ } else {
+ VLOG_WARN("%s: unknown argument '%s'",
+ netdev_get_name(dev_), node->name);
+ }
}
error = netdev_tunnel_connect(netdev);
ovs_mutex_unlock(&netdev->mutex);
return error;
}
-static struct netdev_rx *
-netdev_tunnel_rx_alloc(void)
+static struct netdev_rxq *
+netdev_tunnel_rxq_alloc(void)
{
- struct netdev_rx_tunnel *rx = xzalloc(sizeof *rx);
+ struct netdev_rxq_tunnel *rx = xzalloc(sizeof *rx);
return &rx->up;
}
static int
-netdev_tunnel_rx_construct(struct netdev_rx *rx_)
+netdev_tunnel_rxq_construct(struct netdev_rxq *rx_)
{
- struct netdev_rx_tunnel *rx = netdev_rx_tunnel_cast(rx_);
+ struct netdev_rxq_tunnel *rx = netdev_rxq_tunnel_cast(rx_);
struct netdev *netdev_ = rx->up.netdev;
struct netdev_tunnel *netdev = netdev_tunnel_cast(netdev_);
}
static void
-netdev_tunnel_rx_destruct(struct netdev_rx *rx_ OVS_UNUSED)
+netdev_tunnel_rxq_destruct(struct netdev_rxq *rx_ OVS_UNUSED)
{
}
static void
-netdev_tunnel_rx_dealloc(struct netdev_rx *rx_)
+netdev_tunnel_rxq_dealloc(struct netdev_rxq *rx_)
{
- struct netdev_rx_tunnel *rx = netdev_rx_tunnel_cast(rx_);
+ struct netdev_rxq_tunnel *rx = netdev_rxq_tunnel_cast(rx_);
free(rx);
}
static int
-netdev_tunnel_rx_recv(struct netdev_rx *rx_, void *buffer, size_t size)
+netdev_tunnel_rxq_recv(struct netdev_rxq *rx_, struct ofpbuf **packet, int *c)
{
- struct netdev_rx_tunnel *rx = netdev_rx_tunnel_cast(rx_);
+ struct netdev_rxq_tunnel *rx = netdev_rxq_tunnel_cast(rx_);
struct netdev_tunnel *netdev =
netdev_tunnel_cast(rx_->netdev);
+ struct ofpbuf *buffer = NULL;
+ void *data;
+ size_t size;
+ int error = 0;
+
if (!netdev->connected)
- return -EAGAIN;
+ return EAGAIN;
+ buffer = ofpbuf_new_with_headroom(VLAN_ETH_HEADER_LEN + ETH_PAYLOAD_MAX,
+ DP_NETDEV_HEADROOM);
+ data = ofpbuf_data(buffer);
+ size = ofpbuf_tailroom(buffer);
+
for (;;) {
ssize_t retval;
- retval = recv(rx->fd, buffer, size, MSG_TRUNC);
- VLOG_DBG("%s: recv(%"PRIxPTR", %zu, MSG_TRUNC) = %zd",
- netdev_rx_get_name(rx_), (uintptr_t)buffer, size, retval);
+ retval = recv(rx->fd, data, size, MSG_TRUNC);
+ VLOG_DBG("%s: recv(%"PRIxPTR", %"PRIuSIZE", MSG_TRUNC) = %"PRIdSIZE,
+ netdev_rxq_get_name(rx_), (uintptr_t)data, size, retval);
if (retval >= 0) {
- netdev->stats.rx_packets++;
- netdev->stats.rx_bytes += retval;
+ netdev->stats.rx_packets++;
+ netdev->stats.rx_bytes += retval;
if (retval <= size) {
- return retval;
+ ofpbuf_set_size(buffer, ofpbuf_size(buffer) + retval);
+ goto out;
} else {
netdev->stats.rx_errors++;
netdev->stats.rx_length_errors++;
- return -EMSGSIZE;
+ error = EMSGSIZE;
+ goto out;
}
} else if (errno != EINTR) {
if (errno != EAGAIN) {
VLOG_WARN_RL(&rl, "error receiveing Ethernet packet on %s: %s",
- netdev_rx_get_name(rx_), ovs_strerror(errno));
- netdev->stats.rx_errors++;
+ netdev_rxq_get_name(rx_), ovs_strerror(errno));
+ netdev->stats.rx_errors++;
}
- return -errno;
+ error = errno;
+ goto out;
}
}
+out:
+ if (error) {
+ ofpbuf_delete(buffer);
+ } else {
+ dp_packet_pad(buffer);
+ packet[0] = buffer;
+ *c = 1;
+ }
+
+ return error;
}
static void
-netdev_tunnel_rx_wait(struct netdev_rx *rx_)
+netdev_tunnel_rxq_wait(struct netdev_rxq *rx_)
{
- struct netdev_rx_tunnel *rx =
- netdev_rx_tunnel_cast(rx_);
+ struct netdev_rxq_tunnel *rx =
+ netdev_rxq_tunnel_cast(rx_);
if (rx->fd >= 0) {
poll_fd_wait(rx->fd, POLLIN);
}
}
static int
-netdev_tunnel_send(struct netdev *netdev_, const void *buffer, size_t size)
+netdev_tunnel_send(struct netdev *netdev_, struct ofpbuf *pkt, bool may_steal)
{
+ const void *buffer = ofpbuf_data(pkt);
+ size_t size = ofpbuf_size(pkt);
struct netdev_tunnel *dev =
- netdev_tunnel_cast(netdev_);
- if (!dev->connected)
- return EAGAIN;
+ netdev_tunnel_cast(netdev_);
+ int error = 0;
+ if (!dev->connected) {
+ error = EAGAIN;
+ goto out;
+ }
for (;;) {
ssize_t retval;
retval = send(dev->sockfd, buffer, size, 0);
- VLOG_DBG("%s: send(%"PRIxPTR", %zu) = %zd",
- netdev_get_name(netdev_), (uintptr_t)buffer, size, retval);
+ VLOG_DBG("%s: send(%"PRIxPTR", %"PRIuSIZE") = %"PRIdSIZE,
+ netdev_get_name(netdev_), (uintptr_t)buffer, size, retval);
if (retval >= 0) {
- dev->stats.tx_packets++;
- dev->stats.tx_bytes += retval;
- if (retval != size) {
- VLOG_WARN_RL(&rl, "sent partial Ethernet packet (%zd bytes of "
- "%zu) on %s", retval, size, netdev_get_name(netdev_));
- dev->stats.tx_errors++;
- }
- return 0;
+ dev->stats.tx_packets++;
+ dev->stats.tx_bytes += retval;
+ if (retval != size) {
+ VLOG_WARN_RL(&rl, "sent partial Ethernet packet (%"PRIdSIZE" bytes of "
+ "%"PRIuSIZE") on %s", retval, size, netdev_get_name(netdev_));
+ dev->stats.tx_errors++;
+ }
+ goto out;
} else if (errno != EINTR) {
if (errno != EAGAIN) {
VLOG_WARN_RL(&rl, "error sending Ethernet packet on %s: %s",
- netdev_get_name(netdev_), ovs_strerror(errno));
- dev->stats.tx_errors++;
+ netdev_get_name(netdev_), ovs_strerror(errno));
+ dev->stats.tx_errors++;
}
- return errno;
+ error = errno;
+ goto out;
}
}
+out:
+ if (may_steal) {
+ ofpbuf_delete(pkt);
+ }
+
+ return error;
}
static void
}
static int
-netdev_tunnel_rx_drain(struct netdev_rx *rx_)
+netdev_tunnel_rxq_drain(struct netdev_rxq *rx_)
{
struct netdev_tunnel *netdev =
netdev_tunnel_cast(rx_->netdev);
- struct netdev_rx_tunnel *rx =
- netdev_rx_tunnel_cast(rx_);
+ struct netdev_rxq_tunnel *rx =
+ netdev_rxq_tunnel_cast(rx_);
char buffer[128];
int error;
if (!netdev->connected)
- return 0;
+ return 0;
for (;;) {
- error = recv(rx->fd, buffer, 128, MSG_TRUNC);
- if (error) {
+ error = recv(rx->fd, buffer, 128, MSG_TRUNC);
+ if (error) {
if (error == -EAGAIN)
- break;
+ break;
else if (error != -EMSGSIZE)
- return error;
- }
+ return error;
+ }
}
return 0;
}
return error;
}
-static unsigned int
-netdev_tunnel_change_seq(const struct netdev *netdev_)
-{
- struct netdev_tunnel *netdev = netdev_tunnel_cast(netdev_);
- unsigned int change_seq;
-
-
- ovs_mutex_lock(&netdev->mutex);
- change_seq = netdev->change_seq;
- ovs_mutex_unlock(&netdev->mutex);
- return change_seq;
-}
\f
/* Helper functions. */
}
ovs_mutex_lock(&tunnel_dev->mutex);
- sprintf(buf, "%d", ntohs(tunnel_dev->local_addr.sin_port));
+ sprintf(buf, "%d", ss_get_port(&tunnel_dev->local_addr));
ovs_mutex_unlock(&tunnel_dev->mutex);
unixctl_command_reply(conn, buf);
NULL, /* get_in6 */
NULL, /* add_router */
NULL, /* get_next_hop */
- NULL, /* get_drv_info */
+ NULL, /* get_status */
NULL, /* arp_lookup */
netdev_tunnel_update_flags,
- netdev_tunnel_change_seq,
-
- netdev_tunnel_rx_alloc,
- netdev_tunnel_rx_construct,
- netdev_tunnel_rx_destruct,
- netdev_tunnel_rx_dealloc,
- netdev_tunnel_rx_recv,
- netdev_tunnel_rx_wait,
- netdev_tunnel_rx_drain,
+ netdev_tunnel_rxq_alloc,
+ netdev_tunnel_rxq_construct,
+ netdev_tunnel_rxq_destruct,
+ netdev_tunnel_rxq_dealloc,
+ netdev_tunnel_rxq_recv,
+ netdev_tunnel_rxq_wait,
+ netdev_tunnel_rxq_drain,
};