mirror of https://gitee.com/openkylin/qemu.git
pci,net,pc enhancements
This includes some fixes and enhancements that accumulated in my tree: pci fixes by dkoch, virtio-net enhancements by akong and mst, and a fix for xen pc by mst. Signed-off-by: Michael S. Tsirkin <mst@redhat.com> -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.13 (GNU/Linux) iQEcBAABAgAGBQJR5meNAAoJECgfDbjSjVRp24IIAMOkxbb85FJ323G/x5cQBzA/ gjFDmvB6geIMBorX1YZRnIM+RFhx+mkXtBTu2raWVTNTt5G2u3vAQQWW2zSiOTBL gH4BhzJnUoqLHOydWql2MsGS7DMQo4Fq8OnzRBkZ119AEEqNMad1w2LykwFWs4ra k3bsPNCZM+ZNiLMWtQLOcD3FYvoiISinqFd81KOnxvDiT90rczk4dLWqjv8smNif WqZ7aCD1hGJ5yD7JI2YjCbhVvu4F7tBK+fWkT/O3oYslh/o241lyxUriOXMKdKML 04sNXa5eWue9cOKlbo1G+yfFwFg1JDsAMe/Usg0KXz1MMK91wiWE763ESPbFBK0= =P+pr -----END PGP SIGNATURE----- Merge remote-tracking branch 'mst/tags/for_anthony' into staging pci,net,pc enhancements This includes some fixes and enhancements that accumulated in my tree: pci fixes by dkoch, virtio-net enhancements by akong and mst, and a fix for xen pc by mst. Signed-off-by: Michael S. Tsirkin <mst@redhat.com> # gpg: Signature made Wed 17 Jul 2013 04:44:45 AM CDT using RSA key ID D28D5469 # gpg: Can't check signature: public key not found # By Don Koch (2) and others # Via Michael S. Tsirkin * mst/tags/for_anthony: pc: don't access fw cfg if NULL virtio-net: add feature bit for any header s/g net: add support of mac-programming over macvtap in QEMU side pci: fix BRDIGE typo pci-bridge: update mappings for migration/restore Message-id: 1374054430-21966-1-git-send-email-mst@redhat.com Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
commit
e9acb8cea9
|
@ -172,6 +172,23 @@ Data:
|
|||
},
|
||||
"timestamp": { "seconds": 1265044230, "microseconds": 450486 } }
|
||||
|
||||
NIC_RX_FILTER_CHANGED
|
||||
-----------------
|
||||
|
||||
The event is emitted once until the query command is executed,
|
||||
the first event will always be emitted.
|
||||
|
||||
Data:
|
||||
|
||||
- "name": net client name (json-string)
|
||||
- "path": device path (json-string)
|
||||
|
||||
{ "event": "NIC_RX_FILTER_CHANGED",
|
||||
"data": { "name": "vnet0",
|
||||
"path": "/machine/peripheral/vnet0/virtio-backend" },
|
||||
"timestamp": { "seconds": 1368697518, "microseconds": 326866 } }
|
||||
}
|
||||
|
||||
RESET
|
||||
-----
|
||||
|
||||
|
|
|
@ -1005,7 +1005,7 @@ typedef struct PcRomPciInfo {
|
|||
static void pc_fw_cfg_guest_info(PcGuestInfo *guest_info)
|
||||
{
|
||||
PcRomPciInfo *info;
|
||||
if (!guest_info->has_pci_info) {
|
||||
if (!guest_info->has_pci_info || !guest_info->fw_cfg) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
#include "hw/virtio/virtio-net.h"
|
||||
#include "net/vhost_net.h"
|
||||
#include "hw/virtio/virtio-bus.h"
|
||||
#include "qapi/qmp/qjson.h"
|
||||
#include "monitor/monitor.h"
|
||||
|
||||
#define VIRTIO_NET_VM_VERSION 11
|
||||
|
||||
|
@ -192,6 +194,105 @@ static void virtio_net_set_link_status(NetClientState *nc)
|
|||
virtio_net_set_status(vdev, vdev->status);
|
||||
}
|
||||
|
||||
static void rxfilter_notify(NetClientState *nc)
|
||||
{
|
||||
QObject *event_data;
|
||||
VirtIONet *n = qemu_get_nic_opaque(nc);
|
||||
|
||||
if (nc->rxfilter_notify_enabled) {
|
||||
if (n->netclient_name) {
|
||||
event_data = qobject_from_jsonf("{ 'name': %s, 'path': %s }",
|
||||
n->netclient_name,
|
||||
object_get_canonical_path(OBJECT(n->qdev)));
|
||||
} else {
|
||||
event_data = qobject_from_jsonf("{ 'path': %s }",
|
||||
object_get_canonical_path(OBJECT(n->qdev)));
|
||||
}
|
||||
monitor_protocol_event(QEVENT_NIC_RX_FILTER_CHANGED, event_data);
|
||||
qobject_decref(event_data);
|
||||
|
||||
/* disable event notification to avoid events flooding */
|
||||
nc->rxfilter_notify_enabled = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static char *mac_strdup_printf(const uint8_t *mac)
|
||||
{
|
||||
return g_strdup_printf("%.2x:%.2x:%.2x:%.2x:%.2x:%.2x", mac[0],
|
||||
mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||
}
|
||||
|
||||
static RxFilterInfo *virtio_net_query_rxfilter(NetClientState *nc)
|
||||
{
|
||||
VirtIONet *n = qemu_get_nic_opaque(nc);
|
||||
RxFilterInfo *info;
|
||||
strList *str_list, *entry;
|
||||
intList *int_list, *int_entry;
|
||||
int i, j;
|
||||
|
||||
info = g_malloc0(sizeof(*info));
|
||||
info->name = g_strdup(nc->name);
|
||||
info->promiscuous = n->promisc;
|
||||
|
||||
if (n->nouni) {
|
||||
info->unicast = RX_STATE_NONE;
|
||||
} else if (n->alluni) {
|
||||
info->unicast = RX_STATE_ALL;
|
||||
} else {
|
||||
info->unicast = RX_STATE_NORMAL;
|
||||
}
|
||||
|
||||
if (n->nomulti) {
|
||||
info->multicast = RX_STATE_NONE;
|
||||
} else if (n->allmulti) {
|
||||
info->multicast = RX_STATE_ALL;
|
||||
} else {
|
||||
info->multicast = RX_STATE_NORMAL;
|
||||
}
|
||||
|
||||
info->broadcast_allowed = n->nobcast;
|
||||
info->multicast_overflow = n->mac_table.multi_overflow;
|
||||
info->unicast_overflow = n->mac_table.uni_overflow;
|
||||
|
||||
info->main_mac = mac_strdup_printf(n->mac);
|
||||
|
||||
str_list = NULL;
|
||||
for (i = 0; i < n->mac_table.first_multi; i++) {
|
||||
entry = g_malloc0(sizeof(*entry));
|
||||
entry->value = mac_strdup_printf(n->mac_table.macs + i * ETH_ALEN);
|
||||
entry->next = str_list;
|
||||
str_list = entry;
|
||||
}
|
||||
info->unicast_table = str_list;
|
||||
|
||||
str_list = NULL;
|
||||
for (i = n->mac_table.first_multi; i < n->mac_table.in_use; i++) {
|
||||
entry = g_malloc0(sizeof(*entry));
|
||||
entry->value = mac_strdup_printf(n->mac_table.macs + i * ETH_ALEN);
|
||||
entry->next = str_list;
|
||||
str_list = entry;
|
||||
}
|
||||
info->multicast_table = str_list;
|
||||
|
||||
int_list = NULL;
|
||||
for (i = 0; i < MAX_VLAN >> 5; i++) {
|
||||
for (j = 0; n->vlans[i] && j < 0x1f; j++) {
|
||||
if (n->vlans[i] & (1U << j)) {
|
||||
int_entry = g_malloc0(sizeof(*int_entry));
|
||||
int_entry->value = (i << 5) + j;
|
||||
int_entry->next = int_list;
|
||||
int_list = int_entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
info->vlan_table = int_list;
|
||||
|
||||
/* enable event notification after query */
|
||||
nc->rxfilter_notify_enabled = 1;
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
static void virtio_net_reset(VirtIODevice *vdev)
|
||||
{
|
||||
VirtIONet *n = VIRTIO_NET(vdev);
|
||||
|
@ -420,6 +521,7 @@ static int virtio_net_handle_rx_mode(VirtIONet *n, uint8_t cmd,
|
|||
{
|
||||
uint8_t on;
|
||||
size_t s;
|
||||
NetClientState *nc = qemu_get_queue(n->nic);
|
||||
|
||||
s = iov_to_buf(iov, iov_cnt, 0, &on, sizeof(on));
|
||||
if (s != sizeof(on)) {
|
||||
|
@ -442,6 +544,8 @@ static int virtio_net_handle_rx_mode(VirtIONet *n, uint8_t cmd,
|
|||
return VIRTIO_NET_ERR;
|
||||
}
|
||||
|
||||
rxfilter_notify(nc);
|
||||
|
||||
return VIRTIO_NET_OK;
|
||||
}
|
||||
|
||||
|
@ -487,6 +591,7 @@ static int virtio_net_handle_mac(VirtIONet *n, uint8_t cmd,
|
|||
{
|
||||
struct virtio_net_ctrl_mac mac_data;
|
||||
size_t s;
|
||||
NetClientState *nc = qemu_get_queue(n->nic);
|
||||
|
||||
if (cmd == VIRTIO_NET_CTRL_MAC_ADDR_SET) {
|
||||
if (iov_size(iov, iov_cnt) != sizeof(n->mac)) {
|
||||
|
@ -495,6 +600,8 @@ static int virtio_net_handle_mac(VirtIONet *n, uint8_t cmd,
|
|||
s = iov_to_buf(iov, iov_cnt, 0, &n->mac, sizeof(n->mac));
|
||||
assert(s == sizeof(n->mac));
|
||||
qemu_format_nic_info_str(qemu_get_queue(n->nic), n->mac);
|
||||
rxfilter_notify(nc);
|
||||
|
||||
return VIRTIO_NET_OK;
|
||||
}
|
||||
|
||||
|
@ -512,19 +619,19 @@ static int virtio_net_handle_mac(VirtIONet *n, uint8_t cmd,
|
|||
sizeof(mac_data.entries));
|
||||
mac_data.entries = ldl_p(&mac_data.entries);
|
||||
if (s != sizeof(mac_data.entries)) {
|
||||
return VIRTIO_NET_ERR;
|
||||
goto error;
|
||||
}
|
||||
iov_discard_front(&iov, &iov_cnt, s);
|
||||
|
||||
if (mac_data.entries * ETH_ALEN > iov_size(iov, iov_cnt)) {
|
||||
return VIRTIO_NET_ERR;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (mac_data.entries <= MAC_TABLE_ENTRIES) {
|
||||
s = iov_to_buf(iov, iov_cnt, 0, n->mac_table.macs,
|
||||
mac_data.entries * ETH_ALEN);
|
||||
if (s != mac_data.entries * ETH_ALEN) {
|
||||
return VIRTIO_NET_ERR;
|
||||
goto error;
|
||||
}
|
||||
n->mac_table.in_use += mac_data.entries;
|
||||
} else {
|
||||
|
@ -539,27 +646,33 @@ static int virtio_net_handle_mac(VirtIONet *n, uint8_t cmd,
|
|||
sizeof(mac_data.entries));
|
||||
mac_data.entries = ldl_p(&mac_data.entries);
|
||||
if (s != sizeof(mac_data.entries)) {
|
||||
return VIRTIO_NET_ERR;
|
||||
goto error;
|
||||
}
|
||||
|
||||
iov_discard_front(&iov, &iov_cnt, s);
|
||||
|
||||
if (mac_data.entries * ETH_ALEN != iov_size(iov, iov_cnt)) {
|
||||
return VIRTIO_NET_ERR;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (n->mac_table.in_use + mac_data.entries <= MAC_TABLE_ENTRIES) {
|
||||
s = iov_to_buf(iov, iov_cnt, 0, n->mac_table.macs,
|
||||
mac_data.entries * ETH_ALEN);
|
||||
if (s != mac_data.entries * ETH_ALEN) {
|
||||
return VIRTIO_NET_ERR;
|
||||
goto error;
|
||||
}
|
||||
n->mac_table.in_use += mac_data.entries;
|
||||
} else {
|
||||
n->mac_table.multi_overflow = 1;
|
||||
}
|
||||
|
||||
rxfilter_notify(nc);
|
||||
|
||||
return VIRTIO_NET_OK;
|
||||
|
||||
error:
|
||||
rxfilter_notify(nc);
|
||||
return VIRTIO_NET_ERR;
|
||||
}
|
||||
|
||||
static int virtio_net_handle_vlan_table(VirtIONet *n, uint8_t cmd,
|
||||
|
@ -567,6 +680,7 @@ static int virtio_net_handle_vlan_table(VirtIONet *n, uint8_t cmd,
|
|||
{
|
||||
uint16_t vid;
|
||||
size_t s;
|
||||
NetClientState *nc = qemu_get_queue(n->nic);
|
||||
|
||||
s = iov_to_buf(iov, iov_cnt, 0, &vid, sizeof(vid));
|
||||
vid = lduw_p(&vid);
|
||||
|
@ -584,6 +698,8 @@ static int virtio_net_handle_vlan_table(VirtIONet *n, uint8_t cmd,
|
|||
else
|
||||
return VIRTIO_NET_ERR;
|
||||
|
||||
rxfilter_notify(nc);
|
||||
|
||||
return VIRTIO_NET_OK;
|
||||
}
|
||||
|
||||
|
@ -1312,6 +1428,7 @@ static NetClientInfo net_virtio_info = {
|
|||
.receive = virtio_net_receive,
|
||||
.cleanup = virtio_net_cleanup,
|
||||
.link_status_changed = virtio_net_set_link_status,
|
||||
.query_rx_filter = virtio_net_query_rxfilter,
|
||||
};
|
||||
|
||||
static bool virtio_net_guest_notifier_pending(VirtIODevice *vdev, int idx)
|
||||
|
@ -1373,6 +1490,7 @@ static int virtio_net_device_init(VirtIODevice *vdev)
|
|||
|
||||
DeviceState *qdev = DEVICE(vdev);
|
||||
VirtIONet *n = VIRTIO_NET(vdev);
|
||||
NetClientState *nc;
|
||||
|
||||
virtio_init(VIRTIO_DEVICE(n), "virtio-net", VIRTIO_ID_NET,
|
||||
n->config_size);
|
||||
|
@ -1439,6 +1557,9 @@ static int virtio_net_device_init(VirtIODevice *vdev)
|
|||
|
||||
n->vlans = g_malloc0(MAX_VLAN >> 3);
|
||||
|
||||
nc = qemu_get_queue(n->nic);
|
||||
nc->rxfilter_notify_enabled = 1;
|
||||
|
||||
n->qdev = qdev;
|
||||
register_savevm(qdev, "virtio-net", -1, VIRTIO_NET_VM_VERSION,
|
||||
virtio_net_save, virtio_net_load, n);
|
||||
|
|
|
@ -69,7 +69,7 @@ static int i82801b11_bridge_initfn(PCIDevice *d)
|
|||
if (rc < 0) {
|
||||
goto err_bridge;
|
||||
}
|
||||
pci_config_set_prog_interface(d->config, PCI_CLASS_BRDIGE_PCI_INF_SUB);
|
||||
pci_config_set_prog_interface(d->config, PCI_CLASS_BRIDGE_PCI_INF_SUB);
|
||||
return 0;
|
||||
|
||||
err_bridge:
|
||||
|
|
|
@ -378,6 +378,7 @@ int pci_bus_num(PCIBus *s)
|
|||
static int get_pci_config_device(QEMUFile *f, void *pv, size_t size)
|
||||
{
|
||||
PCIDevice *s = container_of(pv, PCIDevice, config);
|
||||
PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(s);
|
||||
uint8_t *config;
|
||||
int i;
|
||||
|
||||
|
@ -395,6 +396,10 @@ static int get_pci_config_device(QEMUFile *f, void *pv, size_t size)
|
|||
memcpy(s->config, config, size);
|
||||
|
||||
pci_update_mappings(s);
|
||||
if (pc->is_bridge) {
|
||||
PCIBridge *b = container_of(s, PCIBridge, dev);
|
||||
pci_bridge_update_mappings(b);
|
||||
}
|
||||
|
||||
memory_region_set_enabled(&s->bus_master_enable_region,
|
||||
pci_get_word(s->config + PCI_COMMAND)
|
||||
|
|
|
@ -224,7 +224,7 @@ static void pci_bridge_region_cleanup(PCIBridge *br, PCIBridgeWindows *w)
|
|||
g_free(w);
|
||||
}
|
||||
|
||||
static void pci_bridge_update_mappings(PCIBridge *br)
|
||||
void pci_bridge_update_mappings(PCIBridge *br)
|
||||
{
|
||||
PCIBridgeWindows *w = br->windows;
|
||||
|
||||
|
|
|
@ -231,6 +231,10 @@ int e820_add_entry(uint64_t, uint64_t, uint32_t);
|
|||
.driver = "Nehalem-" TYPE_X86_CPU,\
|
||||
.property = "level",\
|
||||
.value = stringify(2),\
|
||||
},{\
|
||||
.driver = "virtio-net-pci",\
|
||||
.property = "any_layout",\
|
||||
.value = "off",\
|
||||
}
|
||||
|
||||
#define PC_COMPAT_1_4 \
|
||||
|
|
|
@ -37,6 +37,7 @@ PCIBus *pci_bridge_get_sec_bus(PCIBridge *br);
|
|||
pcibus_t pci_bridge_get_base(const PCIDevice *bridge, uint8_t type);
|
||||
pcibus_t pci_bridge_get_limit(const PCIDevice *bridge, uint8_t type);
|
||||
|
||||
void pci_bridge_update_mappings(PCIBridge *br);
|
||||
void pci_bridge_write_config(PCIDevice *d,
|
||||
uint32_t address, uint32_t val, int len);
|
||||
void pci_bridge_disable_base_limit(PCIDevice *dev);
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
#define PCI_CLASS_BRIDGE_HOST 0x0600
|
||||
#define PCI_CLASS_BRIDGE_ISA 0x0601
|
||||
#define PCI_CLASS_BRIDGE_PCI 0x0604
|
||||
#define PCI_CLASS_BRDIGE_PCI_INF_SUB 0x01
|
||||
#define PCI_CLASS_BRIDGE_PCI_INF_SUB 0x01
|
||||
#define PCI_CLASS_BRIDGE_OTHER 0x0680
|
||||
|
||||
#define PCI_CLASS_COMMUNICATION_SERIAL 0x0700
|
||||
|
|
|
@ -243,6 +243,7 @@ struct virtio_net_ctrl_mq {
|
|||
|
||||
#define DEFINE_VIRTIO_NET_FEATURES(_state, _field) \
|
||||
DEFINE_VIRTIO_COMMON_FEATURES(_state, _field), \
|
||||
DEFINE_PROP_BIT("any_layout", _state, _field, VIRTIO_F_ANY_LAYOUT, true), \
|
||||
DEFINE_PROP_BIT("csum", _state, _field, VIRTIO_NET_F_CSUM, true), \
|
||||
DEFINE_PROP_BIT("guest_csum", _state, _field, VIRTIO_NET_F_GUEST_CSUM, true), \
|
||||
DEFINE_PROP_BIT("gso", _state, _field, VIRTIO_NET_F_GSO, true), \
|
||||
|
|
|
@ -43,6 +43,8 @@
|
|||
/* We notify when the ring is completely used, even if the guest is suppressing
|
||||
* callbacks */
|
||||
#define VIRTIO_F_NOTIFY_ON_EMPTY 24
|
||||
/* Can the device handle any descriptor layout? */
|
||||
#define VIRTIO_F_ANY_LAYOUT 27
|
||||
/* We support indirect buffer descriptors */
|
||||
#define VIRTIO_RING_F_INDIRECT_DESC 28
|
||||
/* The Guest publishes the used index for which it expects an interrupt
|
||||
|
|
|
@ -41,6 +41,7 @@ typedef enum MonitorEvent {
|
|||
QEVENT_BLOCK_JOB_READY,
|
||||
QEVENT_DEVICE_DELETED,
|
||||
QEVENT_DEVICE_TRAY_MOVED,
|
||||
QEVENT_NIC_RX_FILTER_CHANGED,
|
||||
QEVENT_SUSPEND,
|
||||
QEVENT_SUSPEND_DISK,
|
||||
QEVENT_WAKEUP,
|
||||
|
|
|
@ -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 RxFilterInfo *(QueryRxFilter)(NetClientState *);
|
||||
|
||||
typedef struct NetClientInfo {
|
||||
NetClientOptionsKind type;
|
||||
|
@ -59,6 +60,7 @@ typedef struct NetClientInfo {
|
|||
NetCanReceive *can_receive;
|
||||
NetCleanup *cleanup;
|
||||
LinkStatusChanged *link_status_changed;
|
||||
QueryRxFilter *query_rx_filter;
|
||||
NetPoll *poll;
|
||||
} NetClientInfo;
|
||||
|
||||
|
@ -74,6 +76,7 @@ struct NetClientState {
|
|||
unsigned receive_disabled : 1;
|
||||
NetClientDestructor *destructor;
|
||||
unsigned int queue_index;
|
||||
unsigned rxfilter_notify_enabled:1;
|
||||
};
|
||||
|
||||
typedef struct NICState {
|
||||
|
|
|
@ -490,6 +490,7 @@ static const char *monitor_event_names[] = {
|
|||
[QEVENT_BLOCK_JOB_READY] = "BLOCK_JOB_READY",
|
||||
[QEVENT_DEVICE_DELETED] = "DEVICE_DELETED",
|
||||
[QEVENT_DEVICE_TRAY_MOVED] = "DEVICE_TRAY_MOVED",
|
||||
[QEVENT_NIC_RX_FILTER_CHANGED] = "NIC_RX_FILTER_CHANGED",
|
||||
[QEVENT_SUSPEND] = "SUSPEND",
|
||||
[QEVENT_SUSPEND_DISK] = "SUSPEND_DISK",
|
||||
[QEVENT_WAKEUP] = "WAKEUP",
|
||||
|
|
48
net/net.c
48
net/net.c
|
@ -961,6 +961,54 @@ void print_net_client(Monitor *mon, NetClientState *nc)
|
|||
nc->info_str);
|
||||
}
|
||||
|
||||
RxFilterInfoList *qmp_query_rx_filter(bool has_name, const char *name,
|
||||
Error **errp)
|
||||
{
|
||||
NetClientState *nc;
|
||||
RxFilterInfoList *filter_list = NULL, *last_entry = NULL;
|
||||
|
||||
QTAILQ_FOREACH(nc, &net_clients, next) {
|
||||
RxFilterInfoList *entry;
|
||||
RxFilterInfo *info;
|
||||
|
||||
if (has_name && strcmp(nc->name, name) != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* only query rx-filter information of NIC */
|
||||
if (nc->info->type != NET_CLIENT_OPTIONS_KIND_NIC) {
|
||||
if (has_name) {
|
||||
error_setg(errp, "net client(%s) isn't a NIC", name);
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (nc->info->query_rx_filter) {
|
||||
info = nc->info->query_rx_filter(nc);
|
||||
entry = g_malloc0(sizeof(*entry));
|
||||
entry->value = info;
|
||||
|
||||
if (!filter_list) {
|
||||
filter_list = entry;
|
||||
} else {
|
||||
last_entry->next = entry;
|
||||
}
|
||||
last_entry = entry;
|
||||
} else if (has_name) {
|
||||
error_setg(errp, "net client(%s) doesn't support"
|
||||
" rx-filter querying", name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (filter_list == NULL && !error_is_set(errp) && has_name) {
|
||||
error_setg(errp, "invalid net client name: %s", name);
|
||||
}
|
||||
|
||||
return filter_list;
|
||||
}
|
||||
|
||||
void do_info_network(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
NetClientState *nc, *peer;
|
||||
|
|
|
@ -3679,3 +3679,79 @@
|
|||
'*cpuid-input-ecx': 'int',
|
||||
'cpuid-register': 'X86CPURegister32',
|
||||
'features': 'int' } }
|
||||
|
||||
##
|
||||
# @RxState:
|
||||
#
|
||||
# Packets receiving state
|
||||
#
|
||||
# @normal: filter assigned packets according to the mac-table
|
||||
#
|
||||
# @none: don't receive any assigned packet
|
||||
#
|
||||
# @all: receive all assigned packets
|
||||
#
|
||||
# Since: 1.6
|
||||
##
|
||||
{ 'enum': 'RxState', 'data': [ 'normal', 'none', 'all' ] }
|
||||
|
||||
##
|
||||
# @RxFilterInfo:
|
||||
#
|
||||
# Rx-filter information for a NIC.
|
||||
#
|
||||
# @name: net client name
|
||||
#
|
||||
# @promiscuous: whether promiscuous mode is enabled
|
||||
#
|
||||
# @multicast: multicast receive state
|
||||
#
|
||||
# @unicast: unicast receive state
|
||||
#
|
||||
# @broadcast-allowed: whether to receive broadcast
|
||||
#
|
||||
# @multicast-overflow: multicast table is overflowed or not
|
||||
#
|
||||
# @unicast-overflow: unicast table is overflowed or not
|
||||
#
|
||||
# @main-mac: the main macaddr string
|
||||
#
|
||||
# @vlan-table: a list of active vlan id
|
||||
#
|
||||
# @unicast-table: a list of unicast macaddr string
|
||||
#
|
||||
# @multicast-table: a list of multicast macaddr string
|
||||
#
|
||||
# Since 1.6
|
||||
##
|
||||
|
||||
{ 'type': 'RxFilterInfo',
|
||||
'data': {
|
||||
'name': 'str',
|
||||
'promiscuous': 'bool',
|
||||
'multicast': 'RxState',
|
||||
'unicast': 'RxState',
|
||||
'broadcast-allowed': 'bool',
|
||||
'multicast-overflow': 'bool',
|
||||
'unicast-overflow': 'bool',
|
||||
'main-mac': 'str',
|
||||
'vlan-table': ['int'],
|
||||
'unicast-table': ['str'],
|
||||
'multicast-table': ['str'] }}
|
||||
|
||||
##
|
||||
# @query-rx-filter:
|
||||
#
|
||||
# Return rx-filter information for all NICs (or for the given NIC).
|
||||
#
|
||||
# @name: #optional net client name
|
||||
#
|
||||
# Returns: list of @RxFilterInfo for all NICs (or for the given NIC).
|
||||
# Returns an error if the given @name doesn't exist, or given
|
||||
# NIC doesn't support rx-filter querying, or given net client
|
||||
# isn't a NIC.
|
||||
#
|
||||
# Since: 1.6
|
||||
##
|
||||
{ 'command': 'query-rx-filter', 'data': { '*name': 'str' },
|
||||
'returns': ['RxFilterInfo'] }
|
||||
|
|
|
@ -3046,4 +3046,67 @@ Example:
|
|||
-> { "execute": "chardev-remove", "arguments": { "id" : "foo" } }
|
||||
<- { "return": {} }
|
||||
|
||||
EQMP
|
||||
{
|
||||
.name = "query-rx-filter",
|
||||
.args_type = "name:s?",
|
||||
.mhandler.cmd_new = qmp_marshal_input_query_rx_filter,
|
||||
},
|
||||
|
||||
SQMP
|
||||
query-rx-filter
|
||||
---------------
|
||||
|
||||
Show rx-filter information.
|
||||
|
||||
Returns a json-array of rx-filter information for all NICs (or for the
|
||||
given NIC), returning an error if the given NIC doesn't exist, or
|
||||
given NIC doesn't support rx-filter querying, or given net client
|
||||
isn't a NIC.
|
||||
|
||||
The query will clear the event notification flag of each NIC, then qemu
|
||||
will start to emit event to QMP monitor.
|
||||
|
||||
Each array entry contains the following:
|
||||
|
||||
- "name": net client name (json-string)
|
||||
- "promiscuous": promiscuous mode is enabled (json-bool)
|
||||
- "multicast": multicast receive state (one of 'normal', 'none', 'all')
|
||||
- "unicast": unicast receive state (one of 'normal', 'none', 'all')
|
||||
- "broadcast-allowed": allow to receive broadcast (json-bool)
|
||||
- "multicast-overflow": multicast table is overflowed (json-bool)
|
||||
- "unicast-overflow": unicast table is overflowed (json-bool)
|
||||
- "main-mac": main macaddr string (json-string)
|
||||
- "vlan-table": a json-array of active vlan id
|
||||
- "unicast-table": a json-array of unicast macaddr string
|
||||
- "multicast-table": a json-array of multicast macaddr string
|
||||
|
||||
Example:
|
||||
|
||||
-> { "execute": "query-rx-filter", "arguments": { "name": "vnet0" } }
|
||||
<- { "return": [
|
||||
{
|
||||
"promiscuous": true,
|
||||
"name": "vnet0",
|
||||
"main-mac": "52:54:00:12:34:56",
|
||||
"unicast": "normal",
|
||||
"vlan-table": [
|
||||
4,
|
||||
0
|
||||
],
|
||||
"unicast-table": [
|
||||
],
|
||||
"multicast": "normal",
|
||||
"multicast-overflow": false,
|
||||
"unicast-overflow": false,
|
||||
"multicast-table": [
|
||||
"01:00:5e:00:00:01",
|
||||
"33:33:00:00:00:01",
|
||||
"33:33:ff:12:34:56"
|
||||
],
|
||||
"broadcast-allowed": false
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
EQMP
|
||||
|
|
Loading…
Reference in New Issue