-static struct shash pltap_netdevs = SHASH_INITIALIZER(&pltap_netdevs);
+/* Protects 'pltap_netdevs' */
+static struct ovs_mutex pltap_netdevs_mutex = OVS_MUTEX_INITIALIZER;
+static struct shash pltap_netdevs OVS_GUARDED_BY(pltap_netdevs_mutex)
+ = SHASH_INITIALIZER(&pltap_netdevs);
-static void netdev_pltap_update_seq(struct netdev_pltap *);
-static int get_flags(struct netdev_pltap *dev, enum netdev_flags *flags);
+static void netdev_pltap_update_seq(struct netdev_pltap *)
+ OVS_REQUIRES(dev->mutex);
+static int get_flags(struct netdev_pltap *dev, enum netdev_flags *flags)
+ OVS_REQUIRES(dev->mutex);
- netdev_rx_assert_class(rx, &netdev_rx_pltap_class);
- return CONTAINER_OF(rx, struct netdev_rx_pltap, up);
+ ovs_assert(is_netdev_pltap_class(netdev_get_class(rx->netdev)));
+ return CONTAINER_OF(rx, struct netdev_rxq_pltap, up);
{
if (dev->sync_flags_needed)
return;
dev->sync_flags_needed = true;
list_insert(&sync_list, &dev->sync_list);
{
if (dev->sync_flags_needed)
return;
dev->sync_flags_needed = true;
list_insert(&sync_list, &dev->sync_list);
netdev->real_name = xzalloc(IFNAMSIZ + 1);
memset(&netdev->local_addr, 0, sizeof(netdev->local_addr));
netdev->valid_local_ip = false;
netdev->valid_local_netmask = false;
netdev->flags = 0;
netdev->sync_flags_needed = false;
netdev->real_name = xzalloc(IFNAMSIZ + 1);
memset(&netdev->local_addr, 0, sizeof(netdev->local_addr));
netdev->valid_local_ip = false;
netdev->valid_local_netmask = false;
netdev->flags = 0;
netdev->sync_flags_needed = false;
- VLOG_WARN("tun_alloc(IFF_TAP, %s) failed: %s", name, ovs_strerror(error));
- goto cleanup;
+ VLOG_WARN("tun_alloc(IFF_TAP, %s) failed: %s",
+ netdev_get_name(netdev_), ovs_strerror(error));
+ return error;
}
VLOG_DBG("real_name = %s", netdev->real_name);
/* Make non-blocking. */
error = set_nonblocking(netdev->fd);
if (error) {
}
VLOG_DBG("real_name = %s", netdev->real_name);
/* Make non-blocking. */
error = set_nonblocking(netdev->fd);
if (error) {
- netdev_init(&netdev->up, name, &netdev_pltap_class);
- shash_add(&pltap_netdevs, name, netdev);
- *netdevp = &netdev->up;
+ ovs_mutex_lock(&pltap_netdevs_mutex);
+ shash_add(&pltap_netdevs, netdev_get_name(netdev_), netdev);
+ ovs_mutex_unlock(&pltap_netdevs_mutex);
shash_find_and_delete(&pltap_netdevs,
netdev_get_name(netdev_));
shash_find_and_delete(&pltap_netdevs,
netdev_get_name(netdev_));
-static int netdev_pltap_up(struct netdev_pltap *dev);
+static int netdev_pltap_up(struct netdev_pltap *dev) OVS_REQUIRES(dev->mutex);
+
+static struct netdev_rxq *
+netdev_pltap_rxq_alloc(void)
+{
+ struct netdev_rxq_pltap *rx = xzalloc(sizeof *rx);
+ return &rx->up;
+}
if (netdev->valid_local_ip)
smap_add_format(args, "local_ip", IP_FMT,
IP_ARGS(netdev->local_addr.sin_addr.s_addr));
if (netdev->valid_local_netmask)
smap_add_format(args, "local_netmask", "%"PRIu32,
ntohs(netdev->local_netmask));
if (netdev->valid_local_ip)
smap_add_format(args, "local_ip", IP_FMT,
IP_ARGS(netdev->local_addr.sin_addr.s_addr));
if (netdev->valid_local_netmask)
smap_add_format(args, "local_netmask", "%"PRIu32,
ntohs(netdev->local_netmask));
VLOG_DBG("pltap_set_config(%s)", netdev_get_name(dev_));
SMAP_FOR_EACH(node, args) {
VLOG_DBG("arg: %s->%s", node->name, (char*)node->data);
VLOG_DBG("pltap_set_config(%s)", netdev_get_name(dev_));
SMAP_FOR_EACH(node, args) {
VLOG_DBG("arg: %s->%s", node->name, (char*)node->data);
+ struct ofpbuf *buffer = NULL;
+ size_t size;
+ int error = 0;
+
+ buffer = ofpbuf_new_with_headroom(VLAN_ETH_HEADER_LEN + ETH_PAYLOAD_MAX,
+ DP_NETDEV_HEADROOM);
+ size = ofpbuf_tailroom(buffer);
+ iov[1].iov_base = ofpbuf_data(buffer);
+ iov[1].iov_len = size;
}
} else if (errno != EINTR) {
if (errno != EAGAIN) {
VLOG_WARN_RL(&rl, "error receiveing Ethernet packet on %s: %s",
}
} else if (errno != EINTR) {
if (errno != EAGAIN) {
VLOG_WARN_RL(&rl, "error receiveing Ethernet packet on %s: %s",
struct netdev_pltap *netdev =
netdev_pltap_cast(rx->up.netdev);
if (rx->fd >= 0 && netdev_pltap_finalized(netdev)) {
struct netdev_pltap *netdev =
netdev_pltap_cast(rx->up.netdev);
if (rx->fd >= 0 && netdev_pltap_finalized(netdev)) {
struct tun_pi pi = { 0, 0x86 };
struct iovec iov[2] = {
{ .iov_base = &pi, .iov_len = sizeof(pi) },
struct tun_pi pi = { 0, 0x86 };
struct iovec iov[2] = {
{ .iov_base = &pi, .iov_len = sizeof(pi) },
- if (retval != size + 4) {
- VLOG_WARN_RL(&rl, "sent partial Ethernet packet (%zd bytes of %zu) on %s",
- retval, size + 4, netdev_get_name(netdev_));
- }
- return 0;
+ if (retval != size + sizeof(pi)) {
+ VLOG_WARN_RL(&rl, "sent partial Ethernet packet (%"PRIdSIZE" bytes of %"PRIuSIZE") on %s",
+ retval, size + sizeof(pi), netdev_get_name(netdev_));
+ }
+ goto out;
} else if (errno != EINTR) {
if (errno != EAGAIN) {
VLOG_WARN_RL(&rl, "error sending Ethernet packet on %s: %s",
} else if (errno != EINTR) {
if (errno != EAGAIN) {
VLOG_WARN_RL(&rl, "error sending Ethernet packet on %s: %s",
// XXX from netdev-linux.c
static int
get_etheraddr(struct netdev_pltap *dev, uint8_t ea[ETH_ADDR_LEN])
// XXX from netdev-linux.c
static int
get_etheraddr(struct netdev_pltap *dev, uint8_t ea[ETH_ADDR_LEN])
error = af_inet_ifreq_ioctl(dev->real_name, &ifr,
SIOCGIFHWADDR, "SIOCGIFHWADDR");
if (error) {
error = af_inet_ifreq_ioctl(dev->real_name, &ifr,
SIOCGIFHWADDR, "SIOCGIFHWADDR");
if (error) {
}
hwaddr_family = ifr.ifr_hwaddr.sa_family;
if (hwaddr_family != AF_UNSPEC && hwaddr_family != ARPHRD_ETHER) {
}
hwaddr_family = ifr.ifr_hwaddr.sa_family;
if (hwaddr_family != AF_UNSPEC && hwaddr_family != ARPHRD_ETHER) {
- if (dev->fd < 0)
- return EAGAIN;
- return get_etheraddr(dev, mac);
+ int error = 0;
+
+ ovs_mutex_lock(&dev->mutex);
+ if (dev->fd < 0) {
+ error = EAGAIN;
+ goto out;
+ }
+ error = get_etheraddr(dev, mac);
+
+out:
+ ovs_mutex_unlock(&dev->mutex);
+ return error;
- return netdev_pltap_cast(netdev)->change_seq;
+ struct netdev_pltap *dev =
+ netdev_pltap_cast(netdev);
+ unsigned int change_seq;
+
+ ovs_mutex_lock(&dev->mutex);
+ change_seq = dev->change_seq;
+ ovs_mutex_unlock(&dev->mutex);
+
+ return change_seq;
pltap_dev = shash_find_data(&pltap_netdevs, argv[1]);
if (!pltap_dev) {
unixctl_command_reply_error(conn, "no such pltap netdev");
pltap_dev = shash_find_data(&pltap_netdevs, argv[1]);
if (!pltap_dev) {
unixctl_command_reply_error(conn, "no such pltap netdev");
unixctl_command_register("netdev-pltap/get-tapname", "port",
1, 1, netdev_pltap_get_real_name, NULL);
return 0;
unixctl_command_register("netdev-pltap/get-tapname", "port",
1, 1, netdev_pltap_get_real_name, NULL);
return 0;
LIST_FOR_EACH_SAFE(iter, next, sync_list, &sync_list) {
netdev_pltap_sync_flags(iter);
}
LIST_FOR_EACH_SAFE(iter, next, sync_list, &sync_list) {
netdev_pltap_sync_flags(iter);
}
netdev_pltap_send,
netdev_pltap_send_wait,
netdev_pltap_set_etheraddr,
netdev_pltap_get_etheraddr,
netdev_pltap_send,
netdev_pltap_send_wait,
netdev_pltap_set_etheraddr,
netdev_pltap_get_etheraddr,
- NULL, /* dump_queues */
+ NULL, /* queue_dump_start */
+ NULL, /* queue_dump_next */
+ NULL, /* queue_dump_done */
- netdev_pltap_change_seq
-};
-
-static const struct netdev_rx_class netdev_rx_pltap_class = {
- netdev_rx_pltap_destroy,
- netdev_rx_pltap_recv,
- netdev_rx_pltap_wait,
- netdev_rx_pltap_drain,
-
+ netdev_pltap_rxq_alloc,
+ netdev_pltap_rxq_construct,
+ netdev_pltap_rxq_destruct,
+ netdev_pltap_rxq_dealloc,
+ netdev_pltap_rxq_recv,
+ netdev_pltap_rxq_wait,
+ netdev_pltap_rxq_drain,