Skip to content

[dualtor][intfsorch] Preserve port MAC when updating router interface MAC - #4816

Open
lolyu wants to merge 1 commit into
sonic-net:masterfrom
lolyu:fix_intfsorch_vlan_rif_mac
Open

[dualtor][intfsorch] Preserve port MAC when updating router interface MAC#4816
lolyu wants to merge 1 commit into
sonic-net:masterfrom
lolyu:fix_intfsorch_vlan_rif_mac

Conversation

@lolyu

@lolyu lolyu commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

What I did

Made IntfsOrch::doTask() prefer the port's own MAC (port.m_mac) when reconciling a router interface's SAI_ROUTER_INTERFACE_ATTR_SRC_MAC_ADDRESS, only falling back to the switch MAC (gMacAddress) when the port has no MAC — mirroring what the create path in setIntf() already does.

Why I did it

#4615 ([EVPN-MH] Integrate EVPN-MH with existing modules, f0c53b9) added an "update mac if it is changed" block to IntfsOrch::doTask() that reconciles the RIF's SRC_MAC on every interface update. When the MAC parsed from INTF_TABLE is empty (the 00:00:00:00:00:00 sentinel that intfmgr writes for interfaces without a per-interface MAC), it falls back to gMacAddress and, if that differs from the tracked MAC, issues a set_router_interface_attribute(SRC_MAC).

The problem is an asymmetry between the create and update paths:

  • Create (setIntf() → intfs_entry.mac): port.m_mac ? port.m_mac : gMacAddress — so the RIF is created with the port's MAC (line 514/518).
  • Update (doTask()): fell back straight to gMacAddress (line 1080).

For a VLAN SVI whose gateway MAC is configured on the VLAN (populated into port.m_mac from VLAN_TABLE), the two never agree:

  1. The RIF is created with the VLAN's gateway MAC (e.g. dual-ToR shared MAC 00:aa:bb:cc:dd:ee).
  2. The update path immediately recomputes the MAC as gMacAddress (the per-device switch MAC) because INTF_TABLE.mac_addr is the zero sentinel.
  3. m_syncdIntfses[alias].mac (shared) != mac (device) → a spurious SET SRC_MAC = is issued, overwriting the shared gateway MAC.

On dual-ToR, replacing the shared VLAN gateway MAC with a per-device MAC breaks seamless mux failover (each ToR would answer the server's gateway ARP with a different MAC, so a switchover stales the server's ARP cache). This is a regression introduced in #4615; releases predating it never issued the set (the old code was guarded by if (mac), so the zero sentinel simply meant "don't touch the MAC").

The fix makes the update path fall back exactly like the create path, so the reconciliation MAC matches what the RIF was created with and no spurious set is generated.

How I verified it
Build and validate on dualtor device.

Details if related

IntfsOrch::doTask() reconciles a router interface's SRC_MAC on every
update: if the mac parsed from INTF_TABLE is empty (the zero sentinel
written by intfmgr for interfaces without a per-interface MAC), it falls
back to gMacAddress and, when that differs from the tracked MAC, issues a
set_router_interface_attribute(SRC_MAC).

The create path in setIntf() derives the tracked MAC from port.m_mac
(falling back to gMacAddress only when the port has none), but the update
path fell back straight to gMacAddress. For a VLAN SVI whose gateway MAC
is configured on the VLAN (e.g. a dual-ToR shared MAC populated into
port.m_mac from VLAN_TABLE), the two never agree: the RIF is created with
the VLAN MAC, then the update immediately overwrites it with the switch
MAC. On dual-ToR this replaces the shared gateway MAC with a per-device
MAC and breaks seamless mux failover.

Mirror the create path by preferring port.m_mac and only falling back to
gMacAddress when the port has no MAC. This keeps the update symmetric with
create so no spurious SRC_MAC set is generated. Behavior is unchanged for
routed PHY/LAG interfaces (port.m_mac empty -> gMacAddress) and for SAG
interfaces (intfmgr writes a non-zero anycast MAC, so the fallback is not
taken).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Longxiang Lyu <lolv@microsoft.com>
@lolyu
lolyu requested a review from prsunny as a code owner August 5, 2026 04:11
Copilot AI lite review requested due to automatic review settings August 5, 2026 04:11
@mssonicbld

Copy link
Copy Markdown
Collaborator

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
There may be pipelines that require an authorized user to comment /azp run to run.

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates orchagent’s interface reconciliation logic to ensure IntfsOrch::doTask() preserves a port/VLAN’s configured MAC when updating a router interface’s SAI_ROUTER_INTERFACE_ATTR_SRC_MAC_ADDRESS, avoiding unintended overwrites with the switch MAC (notably impacting dual-ToR VLAN SVI gateway MAC behavior).

Changes:

  • Update IntfsOrch::doTask() to prefer port.m_mac when mac_addr from INTF_TABLE is unset/zero, falling back to gMacAddress only when the port has no MAC.
  • Align the interface update path behavior with the existing create path logic in setIntf().

Comment thread orchagent/intfsorch.cpp
Comment on lines +1081 to +1084
// Prefer the port's own MAC (e.g. a VLAN SVI's gateway MAC populated
// from VLAN_TABLE) and only fall back to the switch MAC when the port
// has none.
mac = port.m_mac ? port.m_mac : gMacAddress;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants