Revision 2d9aba39
b/hw/virtio-net.c | ||
---|---|---|
37 | 37 |
uint8_t allmulti; |
38 | 38 |
struct { |
39 | 39 |
int in_use; |
40 |
int first_multi; |
|
40 | 41 |
uint8_t multi_overflow; |
41 | 42 |
uint8_t uni_overflow; |
42 | 43 |
uint8_t *macs; |
... | ... | |
100 | 101 |
|
101 | 102 |
/* Flush any MAC and VLAN filter table state */ |
102 | 103 |
n->mac_table.in_use = 0; |
104 |
n->mac_table.first_multi = 0; |
|
103 | 105 |
n->mac_table.multi_overflow = 0; |
104 | 106 |
n->mac_table.uni_overflow = 0; |
105 | 107 |
memset(n->mac_table.macs, 0, MAC_TABLE_ENTRIES * ETH_ALEN); |
... | ... | |
172 | 174 |
return VIRTIO_NET_ERR; |
173 | 175 |
|
174 | 176 |
n->mac_table.in_use = 0; |
177 |
n->mac_table.first_multi = 0; |
|
175 | 178 |
n->mac_table.uni_overflow = 0; |
176 | 179 |
n->mac_table.multi_overflow = 0; |
177 | 180 |
memset(n->mac_table.macs, 0, MAC_TABLE_ENTRIES * ETH_ALEN); |
... | ... | |
190 | 193 |
n->mac_table.uni_overflow = 1; |
191 | 194 |
} |
192 | 195 |
|
196 |
n->mac_table.first_multi = n->mac_table.in_use; |
|
197 |
|
|
193 | 198 |
mac_data.entries = ldl_le_p(elem->out_sg[2].iov_base); |
194 | 199 |
|
195 | 200 |
if (sizeof(mac_data.entries) + |
... | ... | |
359 | 364 |
} else if (n->allmulti || n->mac_table.multi_overflow) { |
360 | 365 |
return 1; |
361 | 366 |
} |
367 |
|
|
368 |
for (i = n->mac_table.first_multi; i < n->mac_table.in_use; i++) { |
|
369 |
if (!memcmp(ptr, &n->mac_table.macs[i * ETH_ALEN], ETH_ALEN)) { |
|
370 |
return 1; |
|
371 |
} |
|
372 |
} |
|
362 | 373 |
} else { // unicast |
363 | 374 |
if (n->mac_table.uni_overflow) { |
364 | 375 |
return 1; |
365 | 376 |
} else if (!memcmp(ptr, n->mac, ETH_ALEN)) { |
366 | 377 |
return 1; |
367 | 378 |
} |
368 |
} |
|
369 | 379 |
|
370 |
for (i = 0; i < n->mac_table.in_use; i++) { |
|
371 |
if (!memcmp(ptr, &n->mac_table.macs[i * ETH_ALEN], ETH_ALEN)) |
|
372 |
return 1; |
|
380 |
for (i = 0; i < n->mac_table.first_multi; i++) { |
|
381 |
if (!memcmp(ptr, &n->mac_table.macs[i * ETH_ALEN], ETH_ALEN)) { |
|
382 |
return 1; |
|
383 |
} |
|
384 |
} |
|
373 | 385 |
} |
374 | 386 |
|
375 | 387 |
return 0; |
... | ... | |
547 | 559 |
static int virtio_net_load(QEMUFile *f, void *opaque, int version_id) |
548 | 560 |
{ |
549 | 561 |
VirtIONet *n = opaque; |
562 |
int i; |
|
550 | 563 |
|
551 | 564 |
if (version_id < 2 || version_id > VIRTIO_NET_VM_VERSION) |
552 | 565 |
return -EINVAL; |
... | ... | |
597 | 610 |
n->mac_table.uni_overflow = qemu_get_byte(f); |
598 | 611 |
} |
599 | 612 |
|
613 |
/* Find the first multicast entry in the saved MAC filter */ |
|
614 |
for (i = 0; i < n->mac_table.in_use; i++) { |
|
615 |
if (n->mac_table.macs[i * ETH_ALEN] & 1) { |
|
616 |
break; |
|
617 |
} |
|
618 |
} |
|
619 |
n->mac_table.first_multi = i; |
|
620 |
|
|
600 | 621 |
if (n->tx_timer_active) { |
601 | 622 |
qemu_mod_timer(n->tx_timer, |
602 | 623 |
qemu_get_clock(vm_clock) + TX_TIMER_INTERVAL); |
Also available in: Unified diff