diff options
author | Shannon Zhao <shannon.zhao@linaro.org> | 2015-05-21 17:44:48 +0800 |
---|---|---|
committer | Stefan Hajnoczi <stefanha@redhat.com> | 2015-05-27 10:34:07 +0100 |
commit | 2bc22a58e16f0650e56dccfac9495e5aef58e2ef (patch) | |
tree | 24f38de78463888de57d61aa76bac3639e7fc298 | |
parent | a308817743be5cc051d3379477f54027deb0befb (diff) |
net/net: Record usage status of mac address
Currently QEMU dynamically generates mac address for the NIC which
doesn't specify the mac address. But when we hotplug a NIC without
specifying mac address, the mac address will increase for the same NIC
along with hotplug and hot-unplug, and at last it will overflow. And if
we codeplug one NIC with mac address e.g. "52:54:00:12:34:56", then
hotplug one NIC without specifying mac address and the mac address of
the hotplugged NIC is duplicate of "52:54:00:12:34:56".
This patch add a mac_table to record the usage status and free the mac
address when the NIC is unrealized.
Signed-off-by: Shannon Zhao <zhaoshenglong@huawei.com>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
-rw-r--r-- | net/net.c | 59 |
1 files changed, 55 insertions, 4 deletions
@@ -167,19 +167,68 @@ void qemu_format_nic_info_str(NetClientState *nc, uint8_t macaddr[6]) macaddr[3], macaddr[4], macaddr[5]); } +static int mac_table[256] = {0}; + +static void qemu_macaddr_set_used(MACAddr *macaddr) +{ + int index; + + for (index = 0x56; index < 0xFF; index++) { + if (macaddr->a[5] == index) { + mac_table[index]++; + } + } +} + +static void qemu_macaddr_set_free(MACAddr *macaddr) +{ + int index; + static const MACAddr base = { .a = { 0x52, 0x54, 0x00, 0x12, 0x34, 0 } }; + + if (memcmp(macaddr->a, &base.a, (sizeof(base.a) - 1)) != 0) { + return; + } + for (index = 0x56; index < 0xFF; index++) { + if (macaddr->a[5] == index) { + mac_table[index]--; + } + } +} + +static int qemu_macaddr_get_free(void) +{ + int index; + + for (index = 0x56; index < 0xFF; index++) { + if (mac_table[index] == 0) { + return index; + } + } + + return -1; +} + void qemu_macaddr_default_if_unset(MACAddr *macaddr) { - static int index = 0; static const MACAddr zero = { .a = { 0,0,0,0,0,0 } }; + static const MACAddr base = { .a = { 0x52, 0x54, 0x00, 0x12, 0x34, 0 } }; + + if (memcmp(macaddr, &zero, sizeof(zero)) != 0) { + if (memcmp(macaddr->a, &base.a, (sizeof(base.a) - 1)) != 0) { + return; + } else { + qemu_macaddr_set_used(macaddr); + return; + } + } - if (memcmp(macaddr, &zero, sizeof(zero)) != 0) - return; macaddr->a[0] = 0x52; macaddr->a[1] = 0x54; macaddr->a[2] = 0x00; macaddr->a[3] = 0x12; macaddr->a[4] = 0x34; - macaddr->a[5] = 0x56 + index++; + macaddr->a[5] = qemu_macaddr_get_free(); + qemu_macaddr_set_used(macaddr); } /** @@ -374,6 +423,8 @@ void qemu_del_nic(NICState *nic) { int i, queues = MAX(nic->conf->peers.queues, 1); + qemu_macaddr_set_free(&nic->conf->macaddr); + /* If this is a peer NIC and peer has already been deleted, free it now. */ if (nic->peer_deleted) { for (i = 0; i < queues; i++) { |