qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH RFC V2] virtio-net: announce self by guest


From: Michael S. Tsirkin
Subject: Re: [Qemu-devel] [PATCH RFC V2] virtio-net: announce self by guest
Date: Mon, 12 May 2014 10:22:26 +0300

On Fri, Apr 11, 2014 at 10:54:47AM +0800, Jason Wang wrote:
> It's hard to track all mac addresses and their configurations (e.g
> vlan or ipv6) in qemu. Without those informations, it's impossible to
> build proper garp packet after migration. The only possible solution
> to this is let guest (who knew all configurations) to do this.
> 
> So, this patch introduces a new readonly config status bit of virtio-net,
> VIRTIO_NET_S_ANNOUNCE which is used to notify guest to announce
> presence of its link through config update interrupt.When guest has
> done the announcement, it should ack the notification through
> VIRTIO_NET_CTRL_ANNOUNCE_ACK cmd. This feature is negotiated by a new
> feature bit VIRTIO_NET_F_ANNOUNCE (which has already been supported by
> Linux guest).
> 
> During load, a counter of announcing rounds were set so that the after
> the vm is running it can trigger rounds of config interrupts to notify
> the guest to build and send the correct garps.
> 
> Reference:
> RFC v1: https://lists.gnu.org/archive/html/qemu-devel/2014-03/msg02648.html
> V7:     https://lists.gnu.org/archive/html/qemu-devel/2013-03/msg01127.html
> 
> Changes from RFC v1:
> - clean VIRTIO_NET_S_ANNOUNCE bit during reset
> - free announce timer during clean
> - make announce work for non-vhost case
> 
> Changes from V7:
> - Instead of introducing a global method for each kind of nic, this
>   version limits the changes to virtio-net itself.
> 
> Cc: Liuyongan <address@hidden>
> Cc: Amos Kong <address@hidden>
> Signed-off-by: Jason Wang <address@hidden>

Looks good to me, but I think you should use
QEMU_CLOCK_VIRTUAL: let's not change VM state
when emulation is not running.

> ---
>  hw/net/virtio-net.c            |   48 
> ++++++++++++++++++++++++++++++++++++++++
>  include/hw/virtio/virtio-net.h |   16 +++++++++++++
>  2 files changed, 64 insertions(+), 0 deletions(-)
> 
> diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
> index 3626608..e2f0519 100644
> --- a/hw/net/virtio-net.c
> +++ b/hw/net/virtio-net.c
> @@ -25,6 +25,7 @@
>  #include "monitor/monitor.h"
>  
>  #define VIRTIO_NET_VM_VERSION    11
> +#define VIRTIO_NET_ANNOUNCE_ROUNDS    3
>  
>  #define MAC_TABLE_ENTRIES    64
>  #define MAX_VLAN    (1 << 12)   /* Per 802.1Q definition */
> @@ -99,6 +100,25 @@ static bool virtio_net_started(VirtIONet *n, uint8_t 
> status)
>          (n->status & VIRTIO_NET_S_LINK_UP) && vdev->vm_running;
>  }
>  
> +static void virtio_net_announce_timer(void *opaque)
> +{
> +    VirtIONet *n = opaque;
> +    VirtIODevice *vdev = VIRTIO_DEVICE(n);
> +
> +    if (n->announce &&
> +        virtio_net_started(n, vdev->status) &&
> +        vdev->guest_features & (0x1 << VIRTIO_NET_F_GUEST_ANNOUNCE) &&
> +        vdev->guest_features & (0x1 << VIRTIO_NET_F_CTRL_VQ)) {
> +
> +        n->announce--;
> +        n->status |= VIRTIO_NET_S_ANNOUNCE;
> +        virtio_notify_config(vdev);
> +    } else {
> +        timer_del(n->announce_timer);
> +        n->announce = 0;
> +    }
> +}
> +
>  static void virtio_net_vhost_status(VirtIONet *n, uint8_t status)
>  {
>      VirtIODevice *vdev = VIRTIO_DEVICE(n);
> @@ -147,6 +167,8 @@ static void virtio_net_set_status(struct VirtIODevice 
> *vdev, uint8_t status)
>  
>      virtio_net_vhost_status(n, status);
>  
> +    virtio_net_announce_timer(n);
> +
>      for (i = 0; i < n->max_queues; i++) {
>          q = &n->vqs[i];
>  
> @@ -306,6 +328,9 @@ static void virtio_net_reset(VirtIODevice *vdev)
>      n->nobcast = 0;
>      /* multiqueue is disabled by default */
>      n->curr_queues = 1;
> +    timer_del(n->announce_timer);
> +    n->announce = 0;
> +    n->status &= ~VIRTIO_NET_S_ANNOUNCE;
>  
>      /* Flush any MAC and VLAN filter table state */
>      n->mac_table.in_use = 0;
> @@ -710,6 +735,22 @@ static int virtio_net_handle_vlan_table(VirtIONet *n, 
> uint8_t cmd,
>      return VIRTIO_NET_OK;
>  }
>  
> +static int virtio_net_handle_announce(VirtIONet *n, uint8_t cmd,
> +                                      struct iovec *iov, unsigned int 
> iov_cnt)
> +{
> +    if (cmd == VIRTIO_NET_CTRL_ANNOUNCE_ACK) {
> +        n->status &= ~VIRTIO_NET_S_ANNOUNCE;
> +        if (n->announce) {
> +            timer_mod(n->announce_timer,
> +                      qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + 50 +
> +                      (VIRTIO_NET_ANNOUNCE_ROUNDS - n->announce - 1) * 100);
> +        }
> +        return VIRTIO_NET_OK;
> +    } else {
> +        return VIRTIO_NET_ERR;
> +    }
> +}
> +
>  static int virtio_net_handle_mq(VirtIONet *n, uint8_t cmd,
>                                  struct iovec *iov, unsigned int iov_cnt)
>  {
> @@ -773,6 +814,8 @@ static void virtio_net_handle_ctrl(VirtIODevice *vdev, 
> VirtQueue *vq)
>              status = virtio_net_handle_mac(n, ctrl.cmd, iov, iov_cnt);
>          } else if (ctrl.class == VIRTIO_NET_CTRL_VLAN) {
>              status = virtio_net_handle_vlan_table(n, ctrl.cmd, iov, iov_cnt);
> +        } else if (ctrl.class == VIRTIO_NET_CTRL_ANNOUNCE) {
> +            status = virtio_net_handle_announce(n, ctrl.cmd, iov, iov_cnt);
>          } else if (ctrl.class == VIRTIO_NET_CTRL_MQ) {
>              status = virtio_net_handle_mq(n, ctrl.cmd, iov, iov_cnt);
>          } else if (ctrl.class == VIRTIO_NET_CTRL_GUEST_OFFLOADS) {
> @@ -1418,6 +1461,7 @@ static int virtio_net_load(QEMUFile *f, void *opaque, 
> int version_id)
>          qemu_get_subqueue(n->nic, i)->link_down = link_down;
>      }
>  
> +    n->announce = VIRTIO_NET_ANNOUNCE_ROUNDS;
>      return 0;
>  }
>  
> @@ -1529,6 +1573,8 @@ static void virtio_net_device_realize(DeviceState *dev, 
> Error **errp)
>      qemu_macaddr_default_if_unset(&n->nic_conf.macaddr);
>      memcpy(&n->mac[0], &n->nic_conf.macaddr, sizeof(n->mac));
>      n->status = VIRTIO_NET_S_LINK_UP;
> +    n->announce_timer = timer_new_ns(QEMU_CLOCK_REALTIME,
> +                                     virtio_net_announce_timer, n);
>  
>      if (n->netclient_type) {
>          /*
> @@ -1609,6 +1655,8 @@ static void virtio_net_device_unrealize(DeviceState 
> *dev, Error **errp)
>          }
>      }
>  
> +    timer_del(n->announce_timer);
> +    timer_free(n->announce_timer);
>      g_free(n->vqs);
>      qemu_del_nic(n->nic);
>      virtio_cleanup(vdev);
> diff --git a/include/hw/virtio/virtio-net.h b/include/hw/virtio/virtio-net.h
> index df60f16..e53b2c4 100644
> --- a/include/hw/virtio/virtio-net.h
> +++ b/include/hw/virtio/virtio-net.h
> @@ -49,12 +49,14 @@
>  #define VIRTIO_NET_F_CTRL_RX    18      /* Control channel RX mode support */
>  #define VIRTIO_NET_F_CTRL_VLAN  19      /* Control channel VLAN filtering */
>  #define VIRTIO_NET_F_CTRL_RX_EXTRA 20   /* Extra RX mode control support */
> +#define VIRTIO_NET_F_GUEST_ANNOUNCE 21  /* Guest can announce itself */
>  #define VIRTIO_NET_F_MQ         22      /* Device supports Receive Flow
>                                           * Steering */
>  
>  #define VIRTIO_NET_F_CTRL_MAC_ADDR   23 /* Set MAC address */
>  
>  #define VIRTIO_NET_S_LINK_UP    1       /* Link is up */
> +#define VIRTIO_NET_S_ANNOUNCE   2       /* Announcement is needed */
>  
>  #define TX_TIMER_INTERVAL 150000 /* 150 us */
>  
> @@ -193,6 +195,8 @@ typedef struct VirtIONet {
>      char *netclient_name;
>      char *netclient_type;
>      uint64_t curr_guest_offloads;
> +    QEMUTimer *announce_timer;
> +    int announce;
>  } VirtIONet;
>  
>  #define VIRTIO_NET_CTRL_MAC    1
> @@ -213,6 +217,17 @@ typedef struct VirtIONet {
>   #define VIRTIO_NET_CTRL_VLAN_DEL             1
>  
>  /*
> + * Control link announce acknowledgement
> + *
> + * The command VIRTIO_NET_CTRL_ANNOUNCE_ACK is used to indicate that
> + * driver has recevied the notification and device would clear the
> + * VIRTIO_NET_S_ANNOUNCE bit in the status filed after it received
> + * this command.
> + */
> +#define VIRTIO_NET_CTRL_ANNOUNCE       3
> + #define VIRTIO_NET_CTRL_ANNOUNCE_ACK         0
> +
> +/*
>   * Control Multiqueue
>   *
>   * The command VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET
> @@ -251,6 +266,7 @@ struct virtio_net_ctrl_mq {
>          DEFINE_PROP_BIT("guest_tso6", _state, _field, 
> VIRTIO_NET_F_GUEST_TSO6, true), \
>          DEFINE_PROP_BIT("guest_ecn", _state, _field, VIRTIO_NET_F_GUEST_ECN, 
> true), \
>          DEFINE_PROP_BIT("guest_ufo", _state, _field, VIRTIO_NET_F_GUEST_UFO, 
> true), \
> +        DEFINE_PROP_BIT("guest_announce", _state, _field, 
> VIRTIO_NET_F_GUEST_ANNOUNCE, true), \
>          DEFINE_PROP_BIT("host_tso4", _state, _field, VIRTIO_NET_F_HOST_TSO4, 
> true), \
>          DEFINE_PROP_BIT("host_tso6", _state, _field, VIRTIO_NET_F_HOST_TSO6, 
> true), \
>          DEFINE_PROP_BIT("host_ecn", _state, _field, VIRTIO_NET_F_HOST_ECN, 
> true), \
> -- 
> 1.7.1



reply via email to

[Prev in Thread] Current Thread [Next in Thread]