Il 24/05/2012 19:59, zwu.ker...@gmail.com ha scritto:
> From: Zhi Yong Wu <wu...@linux.vnet.ibm.com>
> 
> Signed-off-by: Zhi Yong Wu <wu...@linux.vnet.ibm.com>
> ---
>  net/hub.c   |   35 ++++++++++++++++++++++++++++++++---
>  net/hub.h   |    2 ++
>  net/queue.c |    5 +++++
>  3 files changed, 39 insertions(+), 3 deletions(-)
> 
> diff --git a/net/hub.c b/net/hub.c
> index 8a583ab..d27c52a 100644
> --- a/net/hub.c
> +++ b/net/hub.c
> @@ -28,6 +28,7 @@ typedef struct NetHubPort {
>      QLIST_ENTRY(NetHubPort) next;
>      NetHub *hub;
>      unsigned int id;
> +    uint64_t nr_packets;
>  } NetHubPort;
>  
>  struct NetHub {
> @@ -39,19 +40,37 @@ struct NetHub {
>  
>  static QLIST_HEAD(, NetHub) hubs = QLIST_HEAD_INITIALIZER(&hubs);
>  
> +static void net_hub_receive_completed(NetClientState *nc, ssize_t len)
> +{
> +    NetHubPort *port = DO_UPCAST(NetHubPort, nc, nc);
> +    port->nr_packets--;
> +    if (!port->nr_packets) {
> +        qemu_net_queue_flush(nc->peer->send_queue);
> +    }
> +}
> +
> +void net_hub_port_packet_stats(NetClientState *nc)
> +{
> +    NetHubPort *port = DO_UPCAST(NetHubPort, nc, nc);
> +
> +    port->nr_packets++;
> +}

Isn't this being called also for non-hubport clients?

>  static ssize_t net_hub_receive(NetHub *hub, NetHubPort *source_port,
>                                 const uint8_t *buf, size_t len)
>  {
>      NetHubPort *port;
> +    ssize_t ret = 0;
>  
>      QLIST_FOREACH(port, &hub->ports, next) {
>          if (port == source_port) {
>              continue;
>          }
>  
> -        qemu_send_packet(&port->nc, buf, len);
> +       ret = qemu_send_packet_async(&port->nc, buf, len,
> +                                    net_hub_receive_completed);

Just increment nr_packets here:

    ret = qemu_send_packet_async
    if (ret == 0) {
        port->nr_packets++;
    }

>      }
> -    return len;
> +    return ret;

You can return len here.  In fact returning ret is wrong because the
value comes from a random port (the last one).

>  }
>  
>  static ssize_t net_hub_receive_iov(NetHub *hub, NetHubPort *source_port,
> @@ -65,7 +84,8 @@ static ssize_t net_hub_receive_iov(NetHub *hub, NetHubPort 
> *source_port,
>              continue;
>          }
>  
> -        ret = qemu_sendv_packet(&port->nc, iov, iovcnt);
> +        ret = qemu_sendv_packet_async(&port->nc, iov, iovcnt,
> +                                      net_hub_receive_completed);

Same here (increment nr_packets)

>      }
>      return ret;

Same here (return len).

>  }
> @@ -84,6 +104,13 @@ static NetHub *net_hub_new(unsigned int id)
>      return hub;
>  }
>  
> +static int net_hub_port_can_receive(NetClientState *nc)
> +{
> +    NetHubPort *port = DO_UPCAST(NetHubPort, nc, nc);
> +
> +    return port->nr_packets ? 0 : 1;
> +}

This is "return port->nr_packets == 0;".

But I think you need to implement this on the hub rather than on the
port, and return true only if port->nr_packets == 0 for all ports.
Probably you can move nr_packets to the hub itself rather than the port?

>  static ssize_t net_hub_port_receive(NetClientState *nc,
>                                      const uint8_t *buf, size_t len)
>  {
> @@ -110,6 +137,7 @@ static void net_hub_port_cleanup(NetClientState *nc)
>  static NetClientInfo net_hub_port_info = {
>      .type = NET_CLIENT_TYPE_HUB,
>      .size = sizeof(NetHubPort),
> +    .can_receive = net_hub_port_can_receive,
>      .receive = net_hub_port_receive,
>      .receive_iov = net_hub_port_receive_iov,
>      .cleanup = net_hub_port_cleanup,
> @@ -128,6 +156,7 @@ static NetHubPort *net_hub_port_new(NetHub *hub)
>      port = DO_UPCAST(NetHubPort, nc, nc);
>      port->id = id;
>      port->hub = hub;
> +    port->nr_packets = 0;
>  
>      QLIST_INSERT_HEAD(&hub->ports, port, next);
>  

Everything below this has to go away (sender is not necessarily a hub
port!).

> diff --git a/net/hub.h b/net/hub.h
> index d04f1b1..542e657 100644
> --- a/net/hub.h
> +++ b/net/hub.h
> @@ -23,4 +23,6 @@ void net_hub_info(Monitor *mon);
>  int net_hub_id_for_client(NetClientState *nc, unsigned int *id);
>  void net_hub_check_clients(void);
>  
> +void net_hub_port_packet_stats(NetClientState *nc);
> +
>  #endif /* NET_HUB_H */
> diff --git a/net/queue.c b/net/queue.c
> index 7484d2a..ebf18aa 100644
> --- a/net/queue.c
> +++ b/net/queue.c
> @@ -22,6 +22,7 @@
>   */
>  
>  #include "net/queue.h"
> +#include "net/hub.h"
>  #include "qemu-queue.h"
>  #include "net.h"
>  
> @@ -101,6 +102,8 @@ static ssize_t qemu_net_queue_append(NetQueue *queue,
>  
>      QTAILQ_INSERT_TAIL(&queue->packets, packet, entry);
>  
> +    net_hub_port_packet_stats(sender);
> +
>      return size;
>  }
>  
> @@ -134,6 +137,8 @@ static ssize_t qemu_net_queue_append_iov(NetQueue *queue,
>  
>      QTAILQ_INSERT_TAIL(&queue->packets, packet, entry);
>  
> +    net_hub_port_packet_stats(sender);
> +    
>      return packet->size;
>  }
>  


Reply via email to