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. | ... | ... |