On 02/25/2016 12:05 PM, zhanghailiang wrote:
> With this property, users can control if this filter is 'enable'
> or 'disable'. The default behavior for filter is enabled.
>
> For buffer filter, we need to release all the buffered packets
> while disabled it. Here we use the 'disable' callback of NetFilterClass
> to realize this capability. We register it with filter_buffer_flush().
> The other types of filters can realize their own 'disable' callback.
>
> We will skip the disabled filter when delivering packets in net layer.
>
> Signed-off-by: zhanghailiang <zhang.zhanghaili...@huawei.com>
> Cc: Jason Wang <jasow...@redhat.com>
> Cc: Yang Hongyang <hongyang.y...@easystack.cn>
> ---
> This is picked from COLO series, which is to realize the new 'status'
> property for filter.

Looks good overall, just few nits. And let's split this into two patches.

> ---
>  include/net/filter.h |  4 ++++
>  net/filter-buffer.c  |  1 +
>  net/filter.c         | 44 ++++++++++++++++++++++++++++++++++++++++++++
>  qemu-options.hx      |  4 +++-
>  4 files changed, 52 insertions(+), 1 deletion(-)
>
> diff --git a/include/net/filter.h b/include/net/filter.h
> index 5639976..bd27074 100644
> --- a/include/net/filter.h
> +++ b/include/net/filter.h
> @@ -36,12 +36,15 @@ typedef ssize_t (FilterReceiveIOV)(NetFilterState *nc,
>                                     int iovcnt,
>                                     NetPacketSent *sent_cb);
>  
> +typedef void (FilterDisable) (NetFilterState *nf);

Let's rename this to 'FilterStatusChanged' to be aligned with link status.

> +
>  typedef struct NetFilterClass {
>      ObjectClass parent_class;
>  
>      /* optional */
>      FilterSetup *setup;
>      FilterCleanup *cleanup;
> +    FilterDisable *disable;

So we can use 'status_changed' instead of 'disable' here.

>      /* mandatory */
>      FilterReceiveIOV *receive_iov;
>  } NetFilterClass;
> @@ -55,6 +58,7 @@ struct NetFilterState {
>      char *netdev_id;
>      NetClientState *netdev;
>      NetFilterDirection direction;
> +    bool enabled;

'status' is much better.

>      QTAILQ_ENTRY(NetFilterState) next;
>  };
>  
> diff --git a/net/filter-buffer.c b/net/filter-buffer.c
> index 12ad2e3..b1464c9 100644
> --- a/net/filter-buffer.c
> +++ b/net/filter-buffer.c
> @@ -131,6 +131,7 @@ static void filter_buffer_class_init(ObjectClass *oc, 
> void *data)
>      nfc->setup = filter_buffer_setup;
>      nfc->cleanup = filter_buffer_cleanup;
>      nfc->receive_iov = filter_buffer_receive_iov;
> +    nfc->disable = filter_buffer_flush;

I believe we should start and stop the timer during status changed.

>  }
>  
>  static void filter_buffer_get_interval(Object *obj, Visitor *v,
> diff --git a/net/filter.c b/net/filter.c
> index d2a514e..edd18c4 100644
> --- a/net/filter.c
> +++ b/net/filter.c
> @@ -17,6 +17,11 @@
>  #include "qom/object_interfaces.h"
>  #include "qemu/iov.h"
>  
> +static inline bool qemu_can_skip_netfilter(NetFilterState *nf)
> +{
> +    return nf->enabled ? false : true;
> +}
> +
>  ssize_t qemu_netfilter_receive(NetFilterState *nf,
>                                 NetFilterDirection direction,
>                                 NetClientState *sender,
> @@ -25,6 +30,9 @@ ssize_t qemu_netfilter_receive(NetFilterState *nf,
>                                 int iovcnt,
>                                 NetPacketSent *sent_cb)
>  {
> +    if (qemu_can_skip_netfilter(nf)) {
> +        return 0;
> +    }
>      if (nf->direction == direction ||
>          nf->direction == NET_FILTER_DIRECTION_ALL) {
>          return NETFILTER_GET_CLASS(OBJECT(nf))->receive_iov(
> @@ -134,8 +142,41 @@ static void netfilter_set_direction(Object *obj, int 
> direction, Error **errp)
>      nf->direction = direction;
>  }
>  
> +static char *netfilter_get_status(Object *obj, Error **errp)
> +{
> +    NetFilterState *nf = NETFILTER(obj);
> +
> +    if (nf->enabled) {
> +        return g_strdup("enable");

Let's use "on" and "off" here.

> +    } else {
> +        return g_strdup("disable");
> +    }
> +}
> +
> +static void netfilter_set_status(Object *obj, const char *str, Error **errp)
> +{
> +    NetFilterState *nf = NETFILTER(obj);
> +    NetFilterClass *nfc = NETFILTER_GET_CLASS(obj);
> +
> +    if (!strcmp(str, "enable")) {
> +        nf->enabled = true;

We'd better also call status changed here, in case the filter (e.g
future implementation) need some setup.

> +    } else if (!strcmp(str, "disable")) {
> +        nf->enabled = false;
> +        if (nfc->disable) {
> +            nfc->disable(nf);
> +        }
> +    } else {
> +        error_setg(errp, "Invalid value for netfilter status, "
> +                         "should be 'enable' or 'disable'");
> +    }
> +}
> +
>  static void netfilter_init(Object *obj)
>  {
> +    NetFilterState *nf = NETFILTER(obj);
> +
> +    nf->enabled = true;
> +
>      object_property_add_str(obj, "netdev",
>                              netfilter_get_netdev_id, netfilter_set_netdev_id,
>                              NULL);
> @@ -143,6 +184,9 @@ static void netfilter_init(Object *obj)
>                               NetFilterDirection_lookup,
>                               netfilter_get_direction, 
> netfilter_set_direction,
>                               NULL);
> +    object_property_add_str(obj, "status",
> +                            netfilter_get_status, netfilter_set_status,
> +                            NULL);
>  }
>  
>  static void netfilter_complete(UserCreatable *uc, Error **errp)
> diff --git a/qemu-options.hx b/qemu-options.hx
> index f528405..15b8e48 100644
> --- a/qemu-options.hx
> +++ b/qemu-options.hx
> @@ -3746,11 +3746,13 @@ version by providing the @var{passwordid} parameter. 
> This provides
>  the ID of a previously created @code{secret} object containing the
>  password for decryption.
>  
> -@item -object 
> filter-buffer,id=@var{id},netdev=@var{netdevid},interval=@var{t}[,queue=@var{all|rx|tx}]
> +@item -object 
> filter-buffer,id=@var{id},netdev=@var{netdevid},interval=@var{t}[,queue=@var{all|rx|tx}][,status=@var{enable|disable}]
>  
>  Interval @var{t} can't be 0, this filter batches the packet delivery: all
>  packets arriving in a given interval on netdev @var{netdevid} are delayed
>  until the end of the interval. Interval is in microseconds.
> +@option{status} is optional that indicate whether the netfilter is enabled
> +or disabled, the default status for netfilter will be enabled.
>  
>  queue @var{all|rx|tx} is an option that can be applied to any netfilter.
>  


Reply via email to