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,7 +16,7 @@ | ||
16 | #include "qemu-timer.h" | 16 | #include "qemu-timer.h" |
17 | #include "virtio-net.h" | 17 | #include "virtio-net.h" |
18 | 18 | ||
19 | -#define VIRTIO_NET_VM_VERSION 9 | 19 | +#define VIRTIO_NET_VM_VERSION 10 |
20 | 20 | ||
21 | #define MAC_TABLE_ENTRIES 32 | 21 | #define MAC_TABLE_ENTRIES 32 |
22 | #define MAX_VLAN (1 << 12) /* Per 802.1Q definition */ | 22 | #define MAX_VLAN (1 << 12) /* Per 802.1Q definition */ |
@@ -35,6 +35,10 @@ typedef struct VirtIONet | @@ -35,6 +35,10 @@ typedef struct VirtIONet | ||
35 | int mergeable_rx_bufs; | 35 | int mergeable_rx_bufs; |
36 | uint8_t promisc; | 36 | uint8_t promisc; |
37 | uint8_t allmulti; | 37 | uint8_t allmulti; |
38 | + uint8_t alluni; | ||
39 | + uint8_t nomulti; | ||
40 | + uint8_t nouni; | ||
41 | + uint8_t nobcast; | ||
38 | struct { | 42 | struct { |
39 | int in_use; | 43 | int in_use; |
40 | int first_multi; | 44 | int first_multi; |
@@ -98,6 +102,10 @@ static void virtio_net_reset(VirtIODevice *vdev) | @@ -98,6 +102,10 @@ static void virtio_net_reset(VirtIODevice *vdev) | ||
98 | /* Reset back to compatibility mode */ | 102 | /* Reset back to compatibility mode */ |
99 | n->promisc = 1; | 103 | n->promisc = 1; |
100 | n->allmulti = 0; | 104 | n->allmulti = 0; |
105 | + n->alluni = 0; | ||
106 | + n->nomulti = 0; | ||
107 | + n->nouni = 0; | ||
108 | + n->nobcast = 0; | ||
101 | 109 | ||
102 | /* Flush any MAC and VLAN filter table state */ | 110 | /* Flush any MAC and VLAN filter table state */ |
103 | n->mac_table.in_use = 0; | 111 | n->mac_table.in_use = 0; |
@@ -114,7 +122,8 @@ static uint32_t virtio_net_get_features(VirtIODevice *vdev) | @@ -114,7 +122,8 @@ static uint32_t virtio_net_get_features(VirtIODevice *vdev) | ||
114 | (1 << VIRTIO_NET_F_STATUS) | | 122 | (1 << VIRTIO_NET_F_STATUS) | |
115 | (1 << VIRTIO_NET_F_CTRL_VQ) | | 123 | (1 << VIRTIO_NET_F_CTRL_VQ) | |
116 | (1 << VIRTIO_NET_F_CTRL_RX) | | 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 | return features; | 128 | return features; |
120 | } | 129 | } |
@@ -157,6 +166,14 @@ static int virtio_net_handle_rx_mode(VirtIONet *n, uint8_t cmd, | @@ -157,6 +166,14 @@ static int virtio_net_handle_rx_mode(VirtIONet *n, uint8_t cmd, | ||
157 | n->promisc = on; | 166 | n->promisc = on; |
158 | else if (cmd == VIRTIO_NET_CTRL_RX_MODE_ALLMULTI) | 167 | else if (cmd == VIRTIO_NET_CTRL_RX_MODE_ALLMULTI) |
159 | n->allmulti = on; | 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 | else | 177 | else |
161 | return VIRTIO_NET_ERR; | 178 | return VIRTIO_NET_ERR; |
162 | 179 | ||
@@ -360,7 +377,9 @@ static int receive_filter(VirtIONet *n, const uint8_t *buf, int size) | @@ -360,7 +377,9 @@ static int receive_filter(VirtIONet *n, const uint8_t *buf, int size) | ||
360 | 377 | ||
361 | if (ptr[0] & 1) { // multicast | 378 | if (ptr[0] & 1) { // multicast |
362 | if (!memcmp(ptr, bcast, sizeof(bcast))) { | 379 | if (!memcmp(ptr, bcast, sizeof(bcast))) { |
363 | - return 1; | 380 | + return !n->nobcast; |
381 | + } else if (n->nomulti) { | ||
382 | + return 0; | ||
364 | } else if (n->allmulti || n->mac_table.multi_overflow) { | 383 | } else if (n->allmulti || n->mac_table.multi_overflow) { |
365 | return 1; | 384 | return 1; |
366 | } | 385 | } |
@@ -371,7 +390,9 @@ static int receive_filter(VirtIONet *n, const uint8_t *buf, int size) | @@ -371,7 +390,9 @@ static int receive_filter(VirtIONet *n, const uint8_t *buf, int size) | ||
371 | } | 390 | } |
372 | } | 391 | } |
373 | } else { // unicast | 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 | return 1; | 396 | return 1; |
376 | } else if (!memcmp(ptr, n->mac, ETH_ALEN)) { | 397 | } else if (!memcmp(ptr, n->mac, ETH_ALEN)) { |
377 | return 1; | 398 | return 1; |
@@ -554,6 +575,10 @@ static void virtio_net_save(QEMUFile *f, void *opaque) | @@ -554,6 +575,10 @@ static void virtio_net_save(QEMUFile *f, void *opaque) | ||
554 | qemu_put_be32(f, 0); /* vnet-hdr placeholder */ | 575 | qemu_put_be32(f, 0); /* vnet-hdr placeholder */ |
555 | qemu_put_byte(f, n->mac_table.multi_overflow); | 576 | qemu_put_byte(f, n->mac_table.multi_overflow); |
556 | qemu_put_byte(f, n->mac_table.uni_overflow); | 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 | static int virtio_net_load(QEMUFile *f, void *opaque, int version_id) | 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,6 +635,13 @@ static int virtio_net_load(QEMUFile *f, void *opaque, int version_id) | ||
610 | n->mac_table.uni_overflow = qemu_get_byte(f); | 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 | /* Find the first multicast entry in the saved MAC filter */ | 645 | /* Find the first multicast entry in the saved MAC filter */ |
614 | for (i = 0; i < n->mac_table.in_use; i++) { | 646 | for (i = 0; i < n->mac_table.in_use; i++) { |
615 | if (n->mac_table.macs[i * ETH_ALEN] & 1) { | 647 | if (n->mac_table.macs[i * ETH_ALEN] & 1) { |
hw/virtio-net.h
@@ -43,6 +43,7 @@ | @@ -43,6 +43,7 @@ | ||
43 | #define VIRTIO_NET_F_CTRL_VQ 17 /* Control channel available */ | 43 | #define VIRTIO_NET_F_CTRL_VQ 17 /* Control channel available */ |
44 | #define VIRTIO_NET_F_CTRL_RX 18 /* Control channel RX mode support */ | 44 | #define VIRTIO_NET_F_CTRL_RX 18 /* Control channel RX mode support */ |
45 | #define VIRTIO_NET_F_CTRL_VLAN 19 /* Control channel VLAN filtering */ | 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 | #define VIRTIO_NET_S_LINK_UP 1 /* Link is up */ | 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,14 +104,19 @@ typedef uint8_t virtio_net_ctrl_ack; | ||
103 | #define VIRTIO_NET_ERR 1 | 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 | #define VIRTIO_NET_CTRL_RX_MODE 0 | 113 | #define VIRTIO_NET_CTRL_RX_MODE 0 |
112 | #define VIRTIO_NET_CTRL_RX_MODE_PROMISC 0 | 114 | #define VIRTIO_NET_CTRL_RX_MODE_PROMISC 0 |
113 | #define VIRTIO_NET_CTRL_RX_MODE_ALLMULTI 1 | 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 | * Control the MAC filter table. | 122 | * Control the MAC filter table. |