qemu-devel
[Top][All Lists]
Advanced

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

Re: [Qemu-devel] [PATCH v2 2/2] net: introduce command to query mac-tabl


From: Jason Wang
Subject: Re: [Qemu-devel] [PATCH v2 2/2] net: introduce command to query mac-table information
Date: Wed, 29 May 2013 13:31:12 +0800
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20130510 Thunderbird/17.0.6

On 05/16/2013 07:07 PM, Amos Kong wrote:
> We want to implement mac programming over macvtap through Libvirt.
> The previous patch adds QMP event to notify management of mac-table
> change. This patch adds a monitor command to query rx mode information
> of mac-tables.
>
> (qemu) info mac-table vnet0
> vnet0:
>  \ promisc: on
>  \ allmulti: off
>  \ alluni: off
>  \ nomulti: off
>  \ nouni: off
>  \ nobcast: off
>  \ multi_overflow: off
>  \ uni_overflow: off
>  \ multicast:
>     01:00:5e:00:00:01
>     33:33:00:00:00:01
>     33:33:ff:12:34:56
>
> Signed-off-by: Amos Kong <address@hidden>

Maybe you also need a command to query the vlan table, or rename the
command as "info filter" and do it here.
> ---
>  hmp-commands.hx     |  2 ++
>  hmp.c               | 71 
> +++++++++++++++++++++++++++++++++++++++++++++++++++++
>  hmp.h               |  1 +
>  hw/net/virtio-net.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++
>  include/net/net.h   |  2 ++
>  monitor.c           |  8 ++++++
>  net/net.c           | 38 ++++++++++++++++++++++++++++
>  qapi-schema.json    | 57 ++++++++++++++++++++++++++++++++++++++++++
>  qmp-commands.hx     | 53 +++++++++++++++++++++++++++++++++++++++
>  9 files changed, 295 insertions(+)
>
> diff --git a/hmp-commands.hx b/hmp-commands.hx
> index 9cea415..e5c1b14 100644
> --- a/hmp-commands.hx
> +++ b/hmp-commands.hx
> @@ -1639,6 +1639,8 @@ show qdev device model list
>  show roms
>  @item info tpm
>  show the TPM device
> address@hidden info mac-table [net client name]
> +show the mac-table information for all nics (or for the given nic)
>  @end table
>  ETEXI
>  
> diff --git a/hmp.c b/hmp.c
> index 4fb76ec..3e19df0 100644
> --- a/hmp.c
> +++ b/hmp.c
> @@ -653,6 +653,77 @@ void hmp_info_tpm(Monitor *mon, const QDict *qdict)
>      qapi_free_TPMInfoList(info_list);
>  }
>  
> +void hmp_info_mac_table(Monitor *mon, const QDict *qdict)
> +{
> +    MacTableInfoList *table_list, *entry;
> +    strList *str_entry;
> +    bool has_name = qdict_haskey(qdict, "name");
> +    const char *name = NULL;
> +
> +    if (has_name) {
> +        name = qdict_get_str(qdict, "name");
> +    }
> +
> +    table_list = qmp_query_mac_table(has_name, name, NULL);
> +    entry = table_list;
> +
> +    while (entry) {
> +        monitor_printf(mon, "%s:\n", entry->value->name);
> +        if (entry->value->has_promisc) {
> +            monitor_printf(mon, " \\ promisc: %s\n",
> +                           entry->value->promisc ? "on" : "off");
> +        }
> +        if (entry->value->has_allmulti) {
> +            monitor_printf(mon, " \\ allmulti: %s\n",
> +                           entry->value->allmulti ? "on" : "off");
> +        }
> +        if (entry->value->has_alluni) {
> +            monitor_printf(mon, " \\ alluni: %s\n",
> +                           entry->value->alluni ? "on" : "off");
> +        }
> +        if (entry->value->has_nomulti) {
> +            monitor_printf(mon, " \\ nomulti: %s\n",
> +                           entry->value->nomulti ? "on" : "off");
> +        }
> +        if (entry->value->has_nouni) {
> +            monitor_printf(mon, " \\ nouni: %s\n",
> +                           entry->value->nouni ? "on" : "off");
> +        }
> +        if (entry->value->has_nobcast) {
> +            monitor_printf(mon, " \\ nobcast: %s\n",
> +                           entry->value->nobcast ? "on" : "off");
> +        }
> +        if (entry->value->has_multi_overflow) {
> +            monitor_printf(mon, " \\ multi_overflow: %s\n",
> +                           entry->value->multi_overflow ? "on" : "off");
> +        }
> +        if (entry->value->has_uni_overflow) {
> +            monitor_printf(mon, " \\ uni_overflow: %s\n",
> +                           entry->value->uni_overflow ? "on" : "off");
> +        }
> +
> +        if (entry->value->has_unicast) {
> +            str_entry = entry->value->unicast;
> +            monitor_printf(mon, " \\ unicast:\n");
> +            while (str_entry) {
> +                monitor_printf(mon, "    %s\n", str_entry->value);
> +                str_entry = str_entry->next;
> +            }
> +        }
> +        if (entry->value->has_multicast) {
> +            str_entry = entry->value->multicast;
> +            monitor_printf(mon, " \\ multicast:\n");
> +            while (str_entry) {
> +                monitor_printf(mon, "    %s\n", str_entry->value);
> +                str_entry = str_entry->next;
> +            }
> +        }
> +
> +        entry = entry->next;
> +    }
> +    qapi_free_MacTableInfoList(table_list);
> +}
> +
>  void hmp_quit(Monitor *mon, const QDict *qdict)
>  {
>      monitor_suspend(mon);
> diff --git a/hmp.h b/hmp.h
> index 95fe76e..278c722 100644
> --- a/hmp.h
> +++ b/hmp.h
> @@ -37,6 +37,7 @@ void hmp_info_balloon(Monitor *mon, const QDict *qdict);
>  void hmp_info_pci(Monitor *mon, const QDict *qdict);
>  void hmp_info_block_jobs(Monitor *mon, const QDict *qdict);
>  void hmp_info_tpm(Monitor *mon, const QDict *qdict);
> +void hmp_info_mac_table(Monitor *mon, const QDict *qdict);
>  void hmp_quit(Monitor *mon, const QDict *qdict);
>  void hmp_stop(Monitor *mon, const QDict *qdict);
>  void hmp_system_reset(Monitor *mon, const QDict *qdict);
> diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
> index a9b8f53..e4b2358 100644
> --- a/hw/net/virtio-net.c
> +++ b/hw/net/virtio-net.c
> @@ -194,6 +194,68 @@ static void virtio_net_set_link_status(NetClientState 
> *nc)
>      virtio_net_set_status(vdev, vdev->status);
>  }
>  
> +static MacTableInfo *virtio_net_query_mactable(NetClientState *nc)
> +{
> +    VirtIONet *n = qemu_get_nic_opaque(nc);
> +    MacTableInfo *info;
> +    strList *str_list = NULL;
> +    strList *entry;
> +    int i;
> +
> +    info = g_malloc0(sizeof(*info));
> +    info->name = g_strdup(nc->name);
> +
> +    info->promisc = n->promisc;
> +    info->has_promisc = true;
> +    info->allmulti = n->allmulti;
> +    info->has_allmulti = true;
> +    info->alluni = n->alluni;
> +    info->has_alluni = true;
> +    info->nomulti = n->nomulti;
> +    info->has_nomulti = true;
> +    info->nouni = n->nouni;
> +    info->has_nouni = true;
> +    info->nobcast = n->nobcast;
> +    info->has_nobcast = true;
> +    info->multi_overflow = n->mac_table.multi_overflow;
> +    info->has_multi_overflow = true;
> +    info->uni_overflow = n->mac_table.uni_overflow;
> +    info->has_uni_overflow = true;
> +
> +    for (i = 0; i < n->mac_table.first_multi; i++) {
> +        info->has_unicast = true;
> +        entry = g_malloc0(sizeof(*entry));
> +        entry->value = g_strdup_printf("%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
> +                                       n->mac_table.macs[i * ETH_ALEN],
> +                                       n->mac_table.macs[i * ETH_ALEN + 1],
> +                                       n->mac_table.macs[i * ETH_ALEN + 2],
> +                                       n->mac_table.macs[i * ETH_ALEN + 3],
> +                                       n->mac_table.macs[i * ETH_ALEN + 4],
> +                                       n->mac_table.macs[i * ETH_ALEN + 5]);
> +        entry->next = str_list;
> +        str_list = entry;
> +    }
> +    info->unicast = str_list;
> +
> +    str_list = NULL;
> +    for (i = n->mac_table.first_multi; i < n->mac_table.in_use; i++) {
> +        info->has_multicast = true;
> +        entry = g_malloc0(sizeof(*entry));
> +        entry->value = g_strdup_printf("%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
> +                                       n->mac_table.macs[i * ETH_ALEN],
> +                                       n->mac_table.macs[i * ETH_ALEN + 1],
> +                                       n->mac_table.macs[i * ETH_ALEN + 2],
> +                                       n->mac_table.macs[i * ETH_ALEN + 3],
> +                                       n->mac_table.macs[i * ETH_ALEN + 4],
> +                                       n->mac_table.macs[i * ETH_ALEN + 5]);
> +        entry->next = str_list;
> +        str_list = entry;
> +    }
> +    info->multicast = str_list;
> +
> +    return info;
> +}
> +
>  static void virtio_net_reset(VirtIODevice *vdev)
>  {
>      VirtIONet *n = VIRTIO_NET(vdev);
> @@ -1255,6 +1317,7 @@ static NetClientInfo net_virtio_info = {
>      .receive = virtio_net_receive,
>          .cleanup = virtio_net_cleanup,
>      .link_status_changed = virtio_net_set_link_status,
> +    .query_mac_table = virtio_net_query_mactable,
>  };
>  
>  static bool virtio_net_guest_notifier_pending(VirtIODevice *vdev, int idx)
> diff --git a/include/net/net.h b/include/net/net.h
> index 43d85a1..c3ca4ea 100644
> --- a/include/net/net.h
> +++ b/include/net/net.h
> @@ -49,6 +49,7 @@ typedef ssize_t (NetReceiveIOV)(NetClientState *, const 
> struct iovec *, int);
>  typedef void (NetCleanup) (NetClientState *);
>  typedef void (LinkStatusChanged)(NetClientState *);
>  typedef void (NetClientDestructor)(NetClientState *);
> +typedef MacTableInfo *(QueryMacTable)(NetClientState *);
>  
>  typedef struct NetClientInfo {
>      NetClientOptionsKind type;
> @@ -59,6 +60,7 @@ typedef struct NetClientInfo {
>      NetCanReceive *can_receive;
>      NetCleanup *cleanup;
>      LinkStatusChanged *link_status_changed;
> +    QueryMacTable *query_mac_table;
>      NetPoll *poll;
>  } NetClientInfo;
>  
> diff --git a/monitor.c b/monitor.c
> index 9e51545..a01cdbd 100644
> --- a/monitor.c
> +++ b/monitor.c
> @@ -2765,6 +2765,14 @@ static mon_cmd_t info_cmds[] = {
>          .mhandler.cmd = hmp_info_tpm,
>      },
>      {
> +        .name       = "mac-table",
> +        .args_type  = "name:s?",
> +        .params     = "[net client name]",
> +        .help       = "show the mac-table information for all nics (or"
> +                      " for the given nic)",
> +        .mhandler.cmd = hmp_info_mac_table,
> +    },
> +    {
>          .name       = NULL,
>      },
>  };
> diff --git a/net/net.c b/net/net.c
> index 43a74e4..9ff3006 100644
> --- a/net/net.c
> +++ b/net/net.c
> @@ -961,6 +961,44 @@ void print_net_client(Monitor *mon, NetClientState *nc)
>                     nc->info_str);
>  }
>  
> +MacTableInfoList *qmp_query_mac_table(bool has_name, const char *name,
> +                                      Error **errp)
> +{
> +    NetClientState *nc;
> +    MacTableInfoList *table_list = NULL, *last_entry = NULL;
> +
> +    QTAILQ_FOREACH(nc, &net_clients, next) {
> +        MacTableInfoList *entry;
> +        MacTableInfo *info;
> +
> +        if (nc->info->type != NET_CLIENT_OPTIONS_KIND_NIC) {
> +            continue;
> +        }
> +        if (has_name && strcmp(nc->name, name) != 0) {
> +            continue;
> +        }
> +
> +        if (nc->info->query_mac_table) {
> +            info = nc->info->query_mac_table(nc);
> +            entry = g_malloc0(sizeof(*entry));
> +            entry->value = info;
> +
> +            if (!table_list) {
> +                table_list = entry;
> +            } else {
> +                last_entry->next = entry;
> +            }
> +            last_entry = entry;
> +        }
> +    }
> +
> +    if (table_list == NULL) {
> +        error_setg(errp, "invalid net client name: %s", name);
> +    }
> +
> +    return table_list;
> +}
> +
>  void do_info_network(Monitor *mon, const QDict *qdict)
>  {
>      NetClientState *nc, *peer;
> diff --git a/qapi-schema.json b/qapi-schema.json
> index 199744a..866650c 100644
> --- a/qapi-schema.json
> +++ b/qapi-schema.json
> @@ -3619,3 +3619,60 @@
>              '*cpuid-input-ecx': 'int',
>              'cpuid-register': 'X86CPURegister32',
>              'features': 'int' } }
> +
> +# @MacTableInfo:
> +#
> +# Rx-mode information of mac-table for a net client.
> +#
> +# @name: the net client name
> +#
> +# @promisc: #optional promiscuous mode (default: false)
> +#
> +# @allmulti: #optional all multicast mode (default: false)
> +#
> +# @alluni: #optional all unicast mode (default: false)
> +#
> +# @nomulti: #optional no multicast mode (default: false)
> +#
> +# @nouni: #optional no unicast mode (default: false)
> +#
> +# @nobcast: #optional no broadcast mode (default: false)
> +#
> +# @multi_overflow: #optional multicast overflow mode (default: false)
> +#
> +# @uni_overflow: #optional unicast overflow mode (default: false)
> +#
> +# @unicast: #optional a list of unicast macaddr string
> +#
> +# @multicast: #optional a list of multicast macaddr string
> +#
> +# Since 1.6
> +##
> +{ 'type': 'MacTableInfo',
> +  'data': {
> +    'name':            'str',
> +    '*promisc':        'bool',
> +    '*allmulti':       'bool',
> +    '*alluni':         'bool',
> +    '*nomulti':        'bool',
> +    '*nouni':          'bool',
> +    '*nobcast':        'bool',
> +    '*multi-overflow': 'bool',
> +    '*uni-overflow':   'bool',
> +    '*unicast':        ['str'],
> +    '*multicast':      ['str'] }}
> +
> +##
> +# @query-mac-table:
> +#
> +# Return mac-table information for all nics (or for the given nic).
> +#
> +# @name: #optional net client name
> +#
> +# Returns: list of @MacTableInfo for all nics (or for the given nic).
> +#          Returns an error if the given @name doesn't exist.
> +#
> +# Since: 1.6
> +##
> +{ 'command': 'query-mac-table', 'data': { '*name': 'str' },
> +  'returns': ['MacTableInfo'] }
> diff --git a/qmp-commands.hx b/qmp-commands.hx
> index ffd130e..66826ab 100644
> --- a/qmp-commands.hx
> +++ b/qmp-commands.hx
> @@ -2932,3 +2932,56 @@ Example:
>  <- { "return": {} }
>  
>  EQMP
> +    {
> +        .name       = "query-mac-table",
> +        .args_type  = "name:s?",
> +        .mhandler.cmd_new = qmp_marshal_input_query_mac_table,
> +    },
> +
> +SQMP
> +query-mac-table
> +---------------
> +
> +Show mac-table information.
> +
> +Returns a json-array of mac-table information for all nics (or for the
> +given nic), returning an error if the given nic doesn't exist.
> +
> +Each array entry contains the following:
> +
> +- "name": net client name (jaso-string)
> +- "promisc": promiscuous mode (json-bool, optional)
> +- "allmulti": all multicast mode (json-bool, optional)
> +- "alluni": all unicast mode (json-bool, optional)
> +- "nomulti":no multicast mode (json-bool, optional)
> +- "nouni": no unicast mode (json-bool, optional)
> +- "nobcast": no broadcast mode (json-bool, optional)
> +- "multi-overflow": multicast overflow mode (json-bool, optional)
> +- "uni-overflow": unicast overflow mode (json-bool, optional)
> +- "unicast": a jason-array of unicast macaddr string (optional)
> +- "multicast": a jason-array of multicast macaddr string (optional)
> +
> +Example:
> +
> +-> { "execute": "query-mac-table", "arguments": { "name": "vnet0" }}
> +<- { "return": [
> +        {
> +            "multi-overflow": false,
> +            "name": "vnet0",
> +            "uni-overflow": false,
> +            "nobcast": false,
> +            "promisc": true,
> +            "multicast": [
> +                "01:00:5e:00:00:01",
> +                "33:33:00:00:00:01",
> +                "33:33:ff:12:34:56"
> +            ],
> +            "nouni": false,
> +            "nomulti": false,
> +            "allmulti": false,
> +            "alluni": false
> +        }
> +      ]
> +   }
> +
> +EQMP




reply via email to

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