qemu-devel
[Top][All Lists]
Advanced

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

Re: [Qemu-devel] [PATCH v12 02/10] init/cleanup of netfilter object


From: Markus Armbruster
Subject: Re: [Qemu-devel] [PATCH v12 02/10] init/cleanup of netfilter object
Date: Wed, 30 Sep 2015 19:41:35 +0200
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/24.5 (gnu/linux)

Markus Armbruster <address@hidden> writes:

> Yang Hongyang <address@hidden> writes:
>
>> Add a netfilter object based on QOM.
>>
>> A netfilter is attached to a netdev, captures all network packets
>> that pass through the netdev. When we delete the netdev, we also
>> delete the netfilter object attached to it, because if the netdev is
>> removed, the filter which attached to it is useless.
>>
>> QTAILQ_ENTRY next used by netdev, filter belongs to the specific netdev is
>> in this queue.
>
> I'm afraid this paragraph is incomprehensible.  What are you trying to
> say?
>
>> Signed-off-by: Yang Hongyang <address@hidden>
>> ---
>>  include/net/filter.h    |  62 ++++++++++++++++++++++
>>  include/net/net.h       |   1 +
>>  include/qemu/typedefs.h |   1 +
>>  net/Makefile.objs       |   1 +
>>  net/filter.c | 138 ++++++++++++++++++++++++++++++++++++++++++++++++
>>  net/net.c               |   7 +++
>>  qapi-schema.json        |  19 +++++++
>>  7 files changed, 229 insertions(+)
>>  create mode 100644 include/net/filter.h
>>  create mode 100644 net/filter.c
>>
>> diff --git a/include/net/filter.h b/include/net/filter.h
>> new file mode 100644
>> index 0000000..e3e14ea
>> --- /dev/null
>> +++ b/include/net/filter.h
>> @@ -0,0 +1,62 @@
>> +/*
>> + * Copyright (c) 2015 FUJITSU LIMITED
>> + * Author: Yang Hongyang <address@hidden>
>> + *
>> + * This work is licensed under the terms of the GNU GPL, version 2 or
>> + * later.  See the COPYING file in the top-level directory.
>> + */
>> +
>> +#ifndef QEMU_NET_FILTER_H
>> +#define QEMU_NET_FILTER_H
>> +
>> +#include "qom/object.h"
>> +#include "qemu-common.h"
>> +#include "qemu/typedefs.h"
>> +#include "net/queue.h"
>> +
>> +#define TYPE_NETFILTER "netfilter"
>> +#define NETFILTER(obj) \
>> +    OBJECT_CHECK(NetFilterState, (obj), TYPE_NETFILTER)
>> +#define NETFILTER_GET_CLASS(obj) \
>> +    OBJECT_GET_CLASS(NetFilterClass, (obj), TYPE_NETFILTER)
>> +#define NETFILTER_CLASS(klass) \
>> +    OBJECT_CLASS_CHECK(NetFilterClass, (klass), TYPE_NETFILTER)
>> +
>> +typedef void (FilterSetup) (NetFilterState *nf, Error **errp);
>> +typedef void (FilterCleanup) (NetFilterState *nf);
>> +/*
>> + * Return:
>> + *   0: finished handling the packet, we should continue
>> + *   size: filter stolen this packet, we stop pass this packet further
>> + */
>> +typedef ssize_t (FilterReceiveIOV)(NetFilterState *nc,
>> +                                   NetClientState *sender,
>> +                                   unsigned flags,
>> +                                   const struct iovec *iov,
>> +                                   int iovcnt,
>> +                                   NetPacketSent *sent_cb);
>> +
>> +struct NetFilterClass {
>> +    ObjectClass parent_class;
>> +
>> +    /* optional */
>> +    FilterSetup *setup;
>> +    FilterCleanup *cleanup;
>> +    /* mandatory */
>> +    FilterReceiveIOV *receive_iov;
>> +};
>> +typedef struct NetFilterClass NetFilterClass;
>
> No separate typedef, please.
>
>> +
>> +
>> +struct NetFilterState {
>> +    /* private */
>> +    Object parent;
>> +
>> +    /* protected */
>> +    char *netdev_id;
>> +    NetClientState *netdev;
>> +    NetFilterDirection direction;
>> +    QTAILQ_ENTRY(NetFilterState) next;
>> +};
>> +
>> +#endif /* QEMU_NET_FILTER_H */
>> diff --git a/include/net/net.h b/include/net/net.h
>> index 6a6cbef..36e5fab 100644
>> --- a/include/net/net.h
>> +++ b/include/net/net.h
>> @@ -92,6 +92,7 @@ struct NetClientState {
>>      NetClientDestructor *destructor;
>>      unsigned int queue_index;
>>      unsigned rxfilter_notify_enabled:1;
>> +    QTAILQ_HEAD(, NetFilterState) filters;
>>  };
>>  
>>  typedef struct NICState {
>> diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h
>> index 3a835ff..ee1ce1d 100644
>> --- a/include/qemu/typedefs.h
>> +++ b/include/qemu/typedefs.h
>> @@ -45,6 +45,7 @@ typedef struct Monitor Monitor;
>>  typedef struct MouseTransformInfo MouseTransformInfo;
>>  typedef struct MSIMessage MSIMessage;
>>  typedef struct NetClientState NetClientState;
>> +typedef struct NetFilterState NetFilterState;
>>  typedef struct NICInfo NICInfo;
>>  typedef struct PcGuestInfo PcGuestInfo;
>>  typedef struct PCIBridge PCIBridge;
>> diff --git a/net/Makefile.objs b/net/Makefile.objs
>> index ec19cb3..914aec0 100644
>> --- a/net/Makefile.objs
>> +++ b/net/Makefile.objs
>> @@ -13,3 +13,4 @@ common-obj-$(CONFIG_HAIKU) += tap-haiku.o
>>  common-obj-$(CONFIG_SLIRP) += slirp.o
>>  common-obj-$(CONFIG_VDE) += vde.o
>>  common-obj-$(CONFIG_NETMAP) += netmap.o
>> +common-obj-y += filter.o
>> diff --git a/net/filter.c b/net/filter.c
>> new file mode 100644
>> index 0000000..34e32cd
>> --- /dev/null
>> +++ b/net/filter.c
>> @@ -0,0 +1,138 @@
>> +/*
>> + * Copyright (c) 2015 FUJITSU LIMITED
>> + * Author: Yang Hongyang <address@hidden>
>> + *
>> + * This work is licensed under the terms of the GNU GPL, version 2 or
>> + * later.  See the COPYING file in the top-level directory.
>> + */
>> +
>> +#include "qemu-common.h"
>> +#include "qapi/qmp/qerror.h"
>> +#include "qemu/error-report.h"
>> +
>> +#include "net/filter.h"
>> +#include "net/net.h"
>> +#include "net/vhost_net.h"
>> +#include "qom/object_interfaces.h"
>> +
>> +static char *netfilter_get_netdev_id(Object *obj, Error **errp)
>> +{
>> +    NetFilterState *nf = NETFILTER(obj);
>> +
>> +    return g_strdup(nf->netdev_id);
>> +}
>> +
>> +static void netfilter_set_netdev_id(Object *obj, const char *str, Error 
>> **errp)
>> +{
>> +    NetFilterState *nf = NETFILTER(obj);
>> +
>> +    nf->netdev_id = g_strdup(str);
>> +}
>> +
>> +static int netfilter_get_direction(Object *obj, Error **errp G_GNUC_UNUSED)
>> +{
>> +    NetFilterState *nf = NETFILTER(obj);
>> +    return nf->direction;
>> +}
>> +
>> +static void netfilter_set_direction(Object *obj, int direction, Error 
>> **errp)
>> +{
>> +    NetFilterState *nf = NETFILTER(obj);
>> +    nf->direction = direction;
>> +}
>> +
>> +static void netfilter_init(Object *obj)
>> +{
>> +    object_property_add_str(obj, "netdev",
>> +                            netfilter_get_netdev_id, 
>> netfilter_set_netdev_id,
>> +                            NULL);
>> +    object_property_add_enum(obj, "queue", "NetFilterDirection",
>> +                             NetFilterDirection_lookup,
>> +                             netfilter_get_direction, 
>> netfilter_set_direction,
>> +                             NULL);
>> +}
>> +
>> +static void netfilter_finalize(Object *obj)
>> +{
>> +    NetFilterState *nf = NETFILTER(obj);
>> +    NetFilterClass *nfc = NETFILTER_GET_CLASS(obj);
>> +
>> +    if (nfc->cleanup) {
>> +        nfc->cleanup(nf);
>> +    }
>> +
>> +    if (nf->netdev && !QTAILQ_EMPTY(&nf->netdev->filters)) {
>> +        QTAILQ_REMOVE(&nf->netdev->filters, nf, next);
>> +    }
>> +}
>
> I still recommend to put netfilter_finalize() after
> netfilter_complete(), because that's how we order creation and
> destruction elsewhere.
>
>> +
>> +static void netfilter_complete(UserCreatable *uc, Error **errp)
>> +{
>> +    NetFilterState *nf = NETFILTER(uc);
>> +    NetClientState *ncs[MAX_QUEUE_NUM];
>> +    NetFilterClass *nfc = NETFILTER_GET_CLASS(uc);
>> +    int queues;
>> +    Error *local_err = NULL;
>> +
>> +    if (!nf->netdev_id) {
>> +        error_setg(errp, "Parameter 'netdev' is required");
>> +        return;
>> +    }
>> +
>> +    queues = qemu_find_net_clients_except(nf->netdev_id, ncs,
>> +                                          NET_CLIENT_OPTIONS_KIND_NIC,
>> +                                          MAX_QUEUE_NUM);
>> +    if (queues < 1) {
>> +        error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "netdev",
>> +                   "a network backend id");
>> +        return;
>> +    } else if (queues > 1) {
>> +        error_setg(errp, "multiqueue is not supported");
>> +        return;
>> +    }
>> +
>> +    if (get_vhost_net(ncs[0])) {
>> +        error_setg(errp, "Vhost is not supported");
>> +        return;
>> +    }
>> +
>> +    nf->netdev = ncs[0];
>> +
>> +    if (nfc->setup) {
>> +        nfc->setup(nf, &local_err);
>> +        if (local_err) {
>> +            error_propagate(errp, local_err);
>> +            return;
>> +        }
>> +    }
>> +    QTAILQ_INSERT_TAIL(&nf->netdev->filters, nf, next);
>> +}
>> +
>> +static void netfilter_class_init(ObjectClass *oc, void *data)
>> +{
>> +    UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
>> +
>> +    ucc->complete = netfilter_complete;
>> +}
>> +
>> +static const TypeInfo netfilter_info = {
>> +    .name = TYPE_NETFILTER,
>> +    .parent = TYPE_OBJECT,
>> +    .abstract = true,
>> +    .class_size = sizeof(NetFilterClass),
>> +    .class_init = netfilter_class_init,
>> +    .instance_size = sizeof(NetFilterState),
>> +    .instance_init = netfilter_init,
>> +    .instance_finalize = netfilter_finalize,
>> +    .interfaces = (InterfaceInfo[]) {
>> +        { TYPE_USER_CREATABLE },
>> +        { }
>> +    }
>> +};
>> +
>> +static void register_types(void)
>> +{
>> +    type_register_static(&netfilter_info);
>> +}
>> +
>> +type_init(register_types);
>> diff --git a/net/net.c b/net/net.c
>> index 28a5597..033f4f3 100644
>> --- a/net/net.c
>> +++ b/net/net.c
>> @@ -44,6 +44,7 @@
>>  #include "qapi/opts-visitor.h"
>>  #include "qapi/dealloc-visitor.h"
>>  #include "sysemu/sysemu.h"
>> +#include "net/filter.h"
>>  
>>  /* Net bridge is currently not supported for W32. */
>>  #if !defined(_WIN32)
>> @@ -287,6 +288,7 @@ static void qemu_net_client_setup(NetClientState *nc,
>>  
>>      nc->incoming_queue = qemu_new_net_queue(nc);
>>      nc->destructor = destructor;
>> +    QTAILQ_INIT(&nc->filters);
>>  }
>>  
>>  NetClientState *qemu_new_net_client(NetClientInfo *info,
>> @@ -384,6 +386,7 @@ void qemu_del_net_client(NetClientState *nc)
>>  {
>>      NetClientState *ncs[MAX_QUEUE_NUM];
>>      int queues, i;
>> +    NetFilterState *nf, *next;
>>  
>>      assert(nc->info->type != NET_CLIENT_OPTIONS_KIND_NIC);
>>  
>> @@ -395,6 +398,10 @@ void qemu_del_net_client(NetClientState *nc)
>>                                            MAX_QUEUE_NUM);
>>      assert(queues != 0);
>>  
>> +    QTAILQ_FOREACH_SAFE(nf, &nc->filters, next, next) {
>> +        object_unparent(OBJECT(nf));
>> +    }
>> +
>>      /* If there is a peer NIC, delete and cleanup client, but do not free. 
>> */
>>      if (nc->peer && nc->peer->info->type == NET_CLIENT_OPTIONS_KIND_NIC) {
>>          NICState *nic = qemu_get_nic(nc->peer);
>> diff --git a/qapi-schema.json b/qapi-schema.json
>> index 582a817..a58e8f4 100644
>> --- a/qapi-schema.json
>> +++ b/qapi-schema.json
>> @@ -2556,6 +2556,25 @@
>>      'opts': 'NetClientOptions' } }
>>  
>>  ##
>> +# @NetFilterDirection
>> +#
>> +# Indicates whether a netfilter is attached to a netdev's transmit queue or
>> +# receive queue or both.
>> +#
>> +# @all: the filter will receive packets both sent to/by the netdev 
>> (default).
>
> Make this
>
>     @all: the filter is attached both to the receive and the transmit
>     queue of the netdev.
>
>> +#
>> +# @rx: the filter is attached to the receive queue of the netdev,
>> +#      will receive packets sent to the netdev.

where it will receive

>> +#
>> +# @tx: the filter is attached to the transmit queue of the netdev,
>> +#      will receive packets sent by the netdev.

Likewise.

>> +#
>> +# Since 2.5
>> +##
>> +{ 'enum': 'NetFilterDirection',
>> +  'data': [ 'all', 'rx', 'tx' ] }
>> +
>> +##
>>  # @InetSocketAddress
>>  #
>>  # Captures a socket address or address range in the Internet namespace.



reply via email to

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