Commit 015cb16699199b7c062f02a0b89a869fdb18330f
Committed by
Mark McLoughlin
1 parent
2d9aba39
virtio-net: Add new RX filter controls
Add a few new RX modes to better control the receive_filter. These are all fairly obvious features that hardware could provide. Signed-off-by: Alex Williamson <alex.williamson@hp.com> Signed-off-by: Mark McLoughlin <markmc@redhat.com>
Showing
2 changed files
with
46 additions
and
8 deletions
hw/virtio-net.c
| ... | ... | @@ -16,7 +16,7 @@ |
| 16 | 16 | #include "qemu-timer.h" |
| 17 | 17 | #include "virtio-net.h" |
| 18 | 18 | |
| 19 | -#define VIRTIO_NET_VM_VERSION 9 | |
| 19 | +#define VIRTIO_NET_VM_VERSION 10 | |
| 20 | 20 | |
| 21 | 21 | #define MAC_TABLE_ENTRIES 32 |
| 22 | 22 | #define MAX_VLAN (1 << 12) /* Per 802.1Q definition */ |
| ... | ... | @@ -35,6 +35,10 @@ typedef struct VirtIONet |
| 35 | 35 | int mergeable_rx_bufs; |
| 36 | 36 | uint8_t promisc; |
| 37 | 37 | uint8_t allmulti; |
| 38 | + uint8_t alluni; | |
| 39 | + uint8_t nomulti; | |
| 40 | + uint8_t nouni; | |
| 41 | + uint8_t nobcast; | |
| 38 | 42 | struct { |
| 39 | 43 | int in_use; |
| 40 | 44 | int first_multi; |
| ... | ... | @@ -98,6 +102,10 @@ static void virtio_net_reset(VirtIODevice *vdev) |
| 98 | 102 | /* Reset back to compatibility mode */ |
| 99 | 103 | n->promisc = 1; |
| 100 | 104 | n->allmulti = 0; |
| 105 | + n->alluni = 0; | |
| 106 | + n->nomulti = 0; | |
| 107 | + n->nouni = 0; | |
| 108 | + n->nobcast = 0; | |
| 101 | 109 | |
| 102 | 110 | /* Flush any MAC and VLAN filter table state */ |
| 103 | 111 | n->mac_table.in_use = 0; |
| ... | ... | @@ -114,7 +122,8 @@ static uint32_t virtio_net_get_features(VirtIODevice *vdev) |
| 114 | 122 | (1 << VIRTIO_NET_F_STATUS) | |
| 115 | 123 | (1 << VIRTIO_NET_F_CTRL_VQ) | |
| 116 | 124 | (1 << VIRTIO_NET_F_CTRL_RX) | |
| 117 | - (1 << VIRTIO_NET_F_CTRL_VLAN); | |
| 125 | + (1 << VIRTIO_NET_F_CTRL_VLAN) | | |
| 126 | + (1 << VIRTIO_NET_F_CTRL_RX_EXTRA); | |
| 118 | 127 | |
| 119 | 128 | return features; |
| 120 | 129 | } |
| ... | ... | @@ -157,6 +166,14 @@ static int virtio_net_handle_rx_mode(VirtIONet *n, uint8_t cmd, |
| 157 | 166 | n->promisc = on; |
| 158 | 167 | else if (cmd == VIRTIO_NET_CTRL_RX_MODE_ALLMULTI) |
| 159 | 168 | n->allmulti = on; |
| 169 | + else if (cmd == VIRTIO_NET_CTRL_RX_MODE_ALLUNI) | |
| 170 | + n->alluni = on; | |
| 171 | + else if (cmd == VIRTIO_NET_CTRL_RX_MODE_NOMULTI) | |
| 172 | + n->nomulti = on; | |
| 173 | + else if (cmd == VIRTIO_NET_CTRL_RX_MODE_NOUNI) | |
| 174 | + n->nouni = on; | |
| 175 | + else if (cmd == VIRTIO_NET_CTRL_RX_MODE_NOBCAST) | |
| 176 | + n->nobcast = on; | |
| 160 | 177 | else |
| 161 | 178 | return VIRTIO_NET_ERR; |
| 162 | 179 | |
| ... | ... | @@ -360,7 +377,9 @@ static int receive_filter(VirtIONet *n, const uint8_t *buf, int size) |
| 360 | 377 | |
| 361 | 378 | if (ptr[0] & 1) { // multicast |
| 362 | 379 | if (!memcmp(ptr, bcast, sizeof(bcast))) { |
| 363 | - return 1; | |
| 380 | + return !n->nobcast; | |
| 381 | + } else if (n->nomulti) { | |
| 382 | + return 0; | |
| 364 | 383 | } else if (n->allmulti || n->mac_table.multi_overflow) { |
| 365 | 384 | return 1; |
| 366 | 385 | } |
| ... | ... | @@ -371,7 +390,9 @@ static int receive_filter(VirtIONet *n, const uint8_t *buf, int size) |
| 371 | 390 | } |
| 372 | 391 | } |
| 373 | 392 | } else { // unicast |
| 374 | - if (n->mac_table.uni_overflow) { | |
| 393 | + if (n->nouni) { | |
| 394 | + return 0; | |
| 395 | + } else if (n->alluni || n->mac_table.uni_overflow) { | |
| 375 | 396 | return 1; |
| 376 | 397 | } else if (!memcmp(ptr, n->mac, ETH_ALEN)) { |
| 377 | 398 | return 1; |
| ... | ... | @@ -554,6 +575,10 @@ static void virtio_net_save(QEMUFile *f, void *opaque) |
| 554 | 575 | qemu_put_be32(f, 0); /* vnet-hdr placeholder */ |
| 555 | 576 | qemu_put_byte(f, n->mac_table.multi_overflow); |
| 556 | 577 | qemu_put_byte(f, n->mac_table.uni_overflow); |
| 578 | + qemu_put_byte(f, n->alluni); | |
| 579 | + qemu_put_byte(f, n->nomulti); | |
| 580 | + qemu_put_byte(f, n->nouni); | |
| 581 | + qemu_put_byte(f, n->nobcast); | |
| 557 | 582 | } |
| 558 | 583 | |
| 559 | 584 | static int virtio_net_load(QEMUFile *f, void *opaque, int version_id) |
| ... | ... | @@ -610,6 +635,13 @@ static int virtio_net_load(QEMUFile *f, void *opaque, int version_id) |
| 610 | 635 | n->mac_table.uni_overflow = qemu_get_byte(f); |
| 611 | 636 | } |
| 612 | 637 | |
| 638 | + if (version_id >= 10) { | |
| 639 | + n->alluni = qemu_get_byte(f); | |
| 640 | + n->nomulti = qemu_get_byte(f); | |
| 641 | + n->nouni = qemu_get_byte(f); | |
| 642 | + n->nobcast = qemu_get_byte(f); | |
| 643 | + } | |
| 644 | + | |
| 613 | 645 | /* Find the first multicast entry in the saved MAC filter */ |
| 614 | 646 | for (i = 0; i < n->mac_table.in_use; i++) { |
| 615 | 647 | if (n->mac_table.macs[i * ETH_ALEN] & 1) { | ... | ... |
hw/virtio-net.h
| ... | ... | @@ -43,6 +43,7 @@ |
| 43 | 43 | #define VIRTIO_NET_F_CTRL_VQ 17 /* Control channel available */ |
| 44 | 44 | #define VIRTIO_NET_F_CTRL_RX 18 /* Control channel RX mode support */ |
| 45 | 45 | #define VIRTIO_NET_F_CTRL_VLAN 19 /* Control channel VLAN filtering */ |
| 46 | +#define VIRTIO_NET_F_CTRL_RX_EXTRA 20 /* Extra RX mode control support */ | |
| 46 | 47 | |
| 47 | 48 | #define VIRTIO_NET_S_LINK_UP 1 /* Link is up */ |
| 48 | 49 | |
| ... | ... | @@ -103,14 +104,19 @@ typedef uint8_t virtio_net_ctrl_ack; |
| 103 | 104 | #define VIRTIO_NET_ERR 1 |
| 104 | 105 | |
| 105 | 106 | /* |
| 106 | - * Control the RX mode, ie. promisucous and allmulti. PROMISC and | |
| 107 | - * ALLMULTI commands require an "out" sg entry containing a 1 byte | |
| 108 | - * state value, zero = disable, non-zero = enable. These commands | |
| 109 | - * are supported with the VIRTIO_NET_F_CTRL_RX feature. | |
| 107 | + * Control the RX mode, ie. promisucous, allmulti, etc... | |
| 108 | + * All commands require an "out" sg entry containing a 1 byte | |
| 109 | + * state value, zero = disable, non-zero = enable. Commands | |
| 110 | + * 0 and 1 are supported with the VIRTIO_NET_F_CTRL_RX feature. | |
| 111 | + * Commands 2-5 are added with VIRTIO_NET_F_CTRL_RX_EXTRA. | |
| 110 | 112 | */ |
| 111 | 113 | #define VIRTIO_NET_CTRL_RX_MODE 0 |
| 112 | 114 | #define VIRTIO_NET_CTRL_RX_MODE_PROMISC 0 |
| 113 | 115 | #define VIRTIO_NET_CTRL_RX_MODE_ALLMULTI 1 |
| 116 | + #define VIRTIO_NET_CTRL_RX_MODE_ALLUNI 2 | |
| 117 | + #define VIRTIO_NET_CTRL_RX_MODE_NOMULTI 3 | |
| 118 | + #define VIRTIO_NET_CTRL_RX_MODE_NOUNI 4 | |
| 119 | + #define VIRTIO_NET_CTRL_RX_MODE_NOBCAST 5 | |
| 114 | 120 | |
| 115 | 121 | /* |
| 116 | 122 | * Control the MAC filter table. | ... | ... |