[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
- Re: [Qemu-devel] [PATCH v2 1/2] net: introduce MAC_TABLE_CHANGED event, (continued)