From: "Cédric Le Goater" <clg@redhat.com>
To: qemu-devel@nongnu.org
Cc: "Akihiko Odaki" <odaki@rsg.ci.i.u-tokyo.ac.jp>,
"Sriram Yagnaraman" <sriram.yagnaraman@ericsson.com>,
"Jason Wang" <jasowangio@gmail.com>,
"Alex Williamson" <alex@shazbot.org>,
"Michael S . Tsirkin" <mst@redhat.com>,
"Peter Xu" <peterx@redhat.com>,
"Avihai Horon" <avihaih@nvidia.com>,
"Cédric Le Goater" <clg@redhat.com>
Subject: [RFC PATCH 09/11] igb: Send RARP after VF migration to update bridge FDB
Date: Mon, 27 Jul 2026 07:39:33 +0200 [thread overview]
Message-ID: <20260727053935.1392269-10-clg@redhat.com> (raw)
In-Reply-To: <20260727053935.1392269-1-clg@redhat.com>
After VF migration the L0 bridge FDB (Forwarding Database) still maps
the VF's MAC to the old tap port, causing a ~30 s connectivity stall
while peer ARP caches expire.
Add igb_core_vf_get_mac() to look up a VF's MAC address from the PF's
Receive Address registers, and use it to send a RARP broadcast from
the PF's network backend during VF unquiesce so the bridge relearns
the correct port immediately.
Assisted-by: Claude
Signed-off-by: Cédric Le Goater <clg@redhat.com>
---
hw/net/igb_core.h | 1 +
hw/net/igb_core.c | 28 ++++++++++++++++++++++++++++
hw/net/igb_migration.c | 33 +++++++++++++++++++++++++++++++++
hw/net/trace-events | 2 ++
4 files changed, 64 insertions(+)
diff --git a/hw/net/igb_core.h b/hw/net/igb_core.h
index 3db520048732..07b4270708c4 100644
--- a/hw/net/igb_core.h
+++ b/hw/net/igb_core.h
@@ -149,4 +149,5 @@ IGBCore *igb_pf_get_core(void *pf);
void igb_core_vf_propagate_irqs(IGBCore *core, uint16_t vfn);
void igb_core_vf_rearm_irqs(IGBCore *core, uint16_t vfn);
void igb_core_vf_propagate_ivar(IGBCore *core, uint16_t vfn);
+bool igb_core_vf_get_mac(IGBCore *core, uint16_t vfn, uint8_t *mac);
#endif
diff --git a/hw/net/igb_core.c b/hw/net/igb_core.c
index 1621ee6602d5..281f3a474392 100644
--- a/hw/net/igb_core.c
+++ b/hw/net/igb_core.c
@@ -4634,3 +4634,31 @@ void igb_core_vf_propagate_ivar(IGBCore *core, uint16_t vfn)
((uint32_t)ent << (8 * (n % 4)));
}
}
+
+bool igb_core_vf_get_mac(IGBCore *core, uint16_t vfn, uint8_t *mac)
+{
+ uint32_t vf_pool_bit = E1000_RAH_POOL_1 << vfn;
+ static const struct {
+ uint32_t base;
+ int count;
+ } ra_banks[] = {
+ { RA, 16 },
+ { RA2, 8 },
+ };
+ int i, j;
+
+ for (i = 0; i < ARRAY_SIZE(ra_banks); i++) {
+ for (j = 0; j < ra_banks[i].count; j++) {
+ uint32_t ral_off = ra_banks[i].base + j * 2;
+ uint32_t rah_off = ra_banks[i].base + j * 2 + 1;
+ uint32_t rah_val = core->mac[rah_off];
+
+ if ((rah_val & E1000_RAH_AV) && (rah_val & vf_pool_bit)) {
+ stl_le_p(mac, core->mac[ral_off]);
+ stw_le_p(mac + 4, rah_val & 0xffff);
+ return true;
+ }
+ }
+ }
+ return false;
+}
diff --git a/hw/net/igb_migration.c b/hw/net/igb_migration.c
index a0b4a52c865f..fce661f68e3d 100644
--- a/hw/net/igb_migration.c
+++ b/hw/net/igb_migration.c
@@ -609,6 +609,36 @@ static void igb_core_vf_quiesce(IgbVfState *s)
trace_igbvf_mig_quiesce(s->vfn, core->mac[VFRE], core->mac[VFTE]);
}
+/*
+ * Send a RARP broadcast so the network bridge relearns which port
+ * carries this VF's MAC after migration.
+ */
+static void igb_core_vf_send_rarp(IGBCore *core, uint16_t vfn)
+{
+ uint8_t mac[ETH_ALEN];
+ uint8_t buf[60];
+
+ if (!igb_core_vf_get_mac(core, vfn, mac)) {
+ trace_igbvf_mig_no_mac(vfn);
+ return;
+ }
+
+ trace_igbvf_mig_send_rarp(vfn, mac[0], mac[1], mac[2],
+ mac[3], mac[4], mac[5]);
+
+ memset(buf, 0xff, ETH_ALEN);
+ memcpy(buf + 6, mac, ETH_ALEN);
+ stw_be_p(buf + 12, 0x8035); /* ETH_P_RARP */
+ stw_be_p(buf + 14, 1); /* hw addr space: ethernet */
+ stw_be_p(buf + 16, ETH_P_IP); /* protocol addr space */
+ buf[18] = 6; buf[19] = 4; /* hw/proto addr lengths */
+ stw_be_p(buf + 20, 3); /* opcode: RARP request */
+ memcpy(buf + 22, mac, ETH_ALEN);
+ memset(buf + 28, 0, 32);
+
+ qemu_send_packet_raw(qemu_get_queue(core->owner_nic), buf, sizeof(buf));
+}
+
static void igb_core_vf_unquiesce(IgbVfState *s)
{
IgbVfMigState *ms = &s->mig;
@@ -632,6 +662,9 @@ static void igb_core_vf_unquiesce(IgbVfState *s)
if (re) {
igb_core_vf_rearm_irqs(core, s->vfn);
}
+
+ /* TODO : RARP should be sent only if resumed */
+ igb_core_vf_send_rarp(core, s->vfn);
}
/* ================================================================
diff --git a/hw/net/trace-events b/hw/net/trace-events
index f4940e3e176d..1e38d9ab3697 100644
--- a/hw/net/trace-events
+++ b/hw/net/trace-events
@@ -312,6 +312,8 @@ igb_core_dirty_track_dma(int vfn, uint64_t addr, uint64_t len) "VF%d: dirty DMA
igb_core_dirty_track_dma_drop(int vfn, uint64_t addr, uint64_t len) "VF%d: dirty DMA dropped addr=0x%"PRIx64" len=%"PRIu64" no matching range"
igbvf_mig_quiesce(uint16_t vfn, uint32_t vfre, uint32_t vfte) "VF%u: quiesce VFRE=0x%x VFTE=0x%x"
igbvf_mig_unquiesce(uint16_t vfn, uint32_t vfre, uint32_t vfte) "VF%u: unquiesce VFRE=0x%x VFTE=0x%x"
+igbvf_mig_no_mac(uint16_t vfn) "VF%u: no MAC address found, skipping RARP"
+igbvf_mig_send_rarp(uint16_t vfn, uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5) "VF%u: RARP %02x:%02x:%02x:%02x:%02x:%02x"
# spapr_llan.c
spapr_vlan_get_rx_bd_from_pool_found(int pool, int32_t count, uint32_t rx_bufs) "pool=%d count=%"PRId32" rxbufs=%"PRIu32
--
2.55.0
next prev parent reply other threads:[~2026-07-27 5:40 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-27 5:39 [RFC PATCH 00/11] igb: Add experimental VF live migration support Cédric Le Goater
2026-07-27 5:39 ` [RFC PATCH 01/11] pci: Add PCI_BASE_ADDRESS_MEM_ALWAYS_ON BAR flag Cédric Le Goater
2026-07-27 5:39 ` [RFC PATCH 02/11] igb: Add x-vf-migration property and vendor-specific capability for IGBVF Cédric Le Goater
2026-07-27 7:13 ` Akihiko Odaki
2026-07-27 5:39 ` [RFC PATCH 03/11] igb: Add migration BAR with state machine Cédric Le Goater
2026-07-27 7:16 ` Akihiko Odaki
2026-07-27 5:39 ` [RFC PATCH 04/11] igb: Add VF state serialization for live migration Cédric Le Goater
2026-07-27 7:31 ` Akihiko Odaki
2026-07-27 5:39 ` [RFC PATCH 05/11] igb: Add VF post-load fixups " Cédric Le Goater
2026-07-27 7:53 ` Akihiko Odaki
2026-07-27 5:39 ` [RFC PATCH 06/11] igb: Add dirty page tracking for IGBVF migration Cédric Le Goater
2026-07-27 8:15 ` Akihiko Odaki
2026-07-27 5:39 ` [RFC PATCH 07/11] igb: Quiesce VFs on STOP and include PF enable state in migration blob Cédric Le Goater
2026-07-27 8:19 ` Akihiko Odaki
2026-07-27 5:39 ` [RFC PATCH 08/11] igb: Fix post-migration RX ring deadlock Cédric Le Goater
2026-07-27 9:36 ` Akihiko Odaki
2026-07-27 5:39 ` Cédric Le Goater [this message]
2026-07-27 10:33 ` [RFC PATCH 09/11] igb: Send RARP after VF migration to update bridge FDB Akihiko Odaki
2026-07-27 5:39 ` [RFC PATCH 10/11] docs: Add igb VF migration testing setup guide Cédric Le Goater
2026-07-27 10:54 ` Akihiko Odaki
2026-07-27 5:39 ` [RFC PATCH 11/11] igb: Add migration statistics registers to VF migration BAR Cédric Le Goater
2026-07-27 11:05 ` Akihiko Odaki
2026-07-27 17:35 ` [RFC PATCH 00/11] igb: Add experimental VF live migration support Cédric Le Goater
2026-07-28 5:50 ` Akihiko Odaki
2026-07-28 10:03 ` Cédric Le Goater
2026-07-27 20:36 ` Alex Williamson
2026-07-28 8:25 ` Cédric Le Goater
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260727053935.1392269-10-clg@redhat.com \
--to=clg@redhat.com \
--cc=alex@shazbot.org \
--cc=avihaih@nvidia.com \
--cc=jasowangio@gmail.com \
--cc=mst@redhat.com \
--cc=odaki@rsg.ci.i.u-tokyo.ac.jp \
--cc=peterx@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=sriram.yagnaraman@ericsson.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.