Commit 3831ab2094f6b573617b0f53b663bba1f036dc45
1 parent
002437cd
qemu:virtio-net: Enable filtering based on MAC, promisc, broadcast and allmulti (Alex Williamson)
Make use of the new RX_MODE control virtqueue class by dropping packets the guest doesn't want to see. Signed-off-by: Alex Williamson <alex.williamson@hp.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6538 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
28 additions
and
0 deletions
hw/virtio-net.c
| @@ -222,6 +222,31 @@ static int receive_header(VirtIONet *n, struct iovec *iov, int iovcnt, | @@ -222,6 +222,31 @@ static int receive_header(VirtIONet *n, struct iovec *iov, int iovcnt, | ||
| 222 | return offset; | 222 | return offset; |
| 223 | } | 223 | } |
| 224 | 224 | ||
| 225 | +static int receive_filter(VirtIONet *n, const uint8_t *buf, int size) | ||
| 226 | +{ | ||
| 227 | + static const uint8_t bcast[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; | ||
| 228 | + uint8_t *ptr = (uint8_t *)buf; | ||
| 229 | + | ||
| 230 | + if (n->promisc) | ||
| 231 | + return 1; | ||
| 232 | + | ||
| 233 | +#ifdef TAP_VNET_HDR | ||
| 234 | + if (tap_has_vnet_hdr(n->vc->vlan->first_client)) | ||
| 235 | + ptr += sizeof(struct virtio_net_hdr); | ||
| 236 | +#endif | ||
| 237 | + | ||
| 238 | + if ((ptr[0] & 1) && n->allmulti) | ||
| 239 | + return 1; | ||
| 240 | + | ||
| 241 | + if (!memcmp(ptr, bcast, sizeof(bcast))) | ||
| 242 | + return 1; | ||
| 243 | + | ||
| 244 | + if (!memcmp(ptr, n->mac, ETH_ALEN)) | ||
| 245 | + return 1; | ||
| 246 | + | ||
| 247 | + return 0; | ||
| 248 | +} | ||
| 249 | + | ||
| 225 | static void virtio_net_receive(void *opaque, const uint8_t *buf, int size) | 250 | static void virtio_net_receive(void *opaque, const uint8_t *buf, int size) |
| 226 | { | 251 | { |
| 227 | VirtIONet *n = opaque; | 252 | VirtIONet *n = opaque; |
| @@ -231,6 +256,9 @@ static void virtio_net_receive(void *opaque, const uint8_t *buf, int size) | @@ -231,6 +256,9 @@ static void virtio_net_receive(void *opaque, const uint8_t *buf, int size) | ||
| 231 | if (!do_virtio_net_can_receive(n, size)) | 256 | if (!do_virtio_net_can_receive(n, size)) |
| 232 | return; | 257 | return; |
| 233 | 258 | ||
| 259 | + if (!receive_filter(n, buf, size)) | ||
| 260 | + return; | ||
| 261 | + | ||
| 234 | /* hdr_len refers to the header we supply to the guest */ | 262 | /* hdr_len refers to the header we supply to the guest */ |
| 235 | hdr_len = n->mergeable_rx_bufs ? | 263 | hdr_len = n->mergeable_rx_bufs ? |
| 236 | sizeof(struct virtio_net_hdr_mrg_rxbuf) : sizeof(struct virtio_net_hdr); | 264 | sizeof(struct virtio_net_hdr_mrg_rxbuf) : sizeof(struct virtio_net_hdr); |