uint8_t allmulti;
struct {
int in_use;
+ int first_multi;
uint8_t multi_overflow;
uint8_t uni_overflow;
uint8_t *macs;
/* Flush any MAC and VLAN filter table state */
n->mac_table.in_use = 0;
+ n->mac_table.first_multi = 0;
n->mac_table.multi_overflow = 0;
n->mac_table.uni_overflow = 0;
memset(n->mac_table.macs, 0, MAC_TABLE_ENTRIES * ETH_ALEN);
return VIRTIO_NET_ERR;
n->mac_table.in_use = 0;
+ n->mac_table.first_multi = 0;
n->mac_table.uni_overflow = 0;
n->mac_table.multi_overflow = 0;
memset(n->mac_table.macs, 0, MAC_TABLE_ENTRIES * ETH_ALEN);
n->mac_table.uni_overflow = 1;
}
+ n->mac_table.first_multi = n->mac_table.in_use;
+
mac_data.entries = ldl_le_p(elem->out_sg[2].iov_base);
if (sizeof(mac_data.entries) +
} else if (n->allmulti || n->mac_table.multi_overflow) {
return 1;
}
+
+ for (i = n->mac_table.first_multi; i < n->mac_table.in_use; i++) {
+ if (!memcmp(ptr, &n->mac_table.macs[i * ETH_ALEN], ETH_ALEN)) {
+ return 1;
+ }
+ }
} else { // unicast
if (n->mac_table.uni_overflow) {
return 1;
} else if (!memcmp(ptr, n->mac, ETH_ALEN)) {
return 1;
}
- }
- for (i = 0; i < n->mac_table.in_use; i++) {
- if (!memcmp(ptr, &n->mac_table.macs[i * ETH_ALEN], ETH_ALEN))
- return 1;
+ for (i = 0; i < n->mac_table.first_multi; i++) {
+ if (!memcmp(ptr, &n->mac_table.macs[i * ETH_ALEN], ETH_ALEN)) {
+ return 1;
+ }
+ }
}
return 0;
static int virtio_net_load(QEMUFile *f, void *opaque, int version_id)
{
VirtIONet *n = opaque;
+ int i;
if (version_id < 2 || version_id > VIRTIO_NET_VM_VERSION)
return -EINVAL;
n->mac_table.uni_overflow = qemu_get_byte(f);
}
+ /* Find the first multicast entry in the saved MAC filter */
+ for (i = 0; i < n->mac_table.in_use; i++) {
+ if (n->mac_table.macs[i * ETH_ALEN] & 1) {
+ break;
+ }
+ }
+ n->mac_table.first_multi = i;
+
if (n->tx_timer_active) {
qemu_mod_timer(n->tx_timer,
qemu_get_clock(vm_clock) + TX_TIMER_INTERVAL);