跳到主要内容

Selective Address Mobility

Selective Address Mobility (SAM) 不是 full L2 extension。routerd CloudEdge 不把 Ethernet segment 延伸到 public cloud,而是只移动选定的 IPv4 /32。source/destination address 会保留;firewall 与 NAT 是单独的 routerd layer。

SAM transport 图:MobilityPool 与 SAMTransportProfile 作为 authoring surface,生成 IPIP delivery、BGP peer、ECMP next hop,并由 secondary IP 或 proxy ARP capture

primary resource model

当前 CloudEdge Mobility 的 operator-authored surface 是:

  • SAMNodeSet: 一次性声明完整共享的 node identity、topology、placement 与 SAM endpoint。
  • MobilityPool: 声明 mobility prefix、EventGroup、BGP delivery、以及本 node 的 capture/discovery/provider trap local overlay。
  • SAMTransportProfile: 声明 router-to-router transport、selfNodeRefinnerPrefix、 underlay interface、BGP router,以及从 SAMNodeSet 选择的 peer source。

MobilityPool 通过 membersFrom 导入共享 SAMNodeSet,并且只保留 self-member overlay。不要在 Pool 内重复 remote identity、placement 或 maintenance。provider、capture 与 discovery detail 只能属于 self-member overlay。所有 node 应获得相同的 SAMNodeSet,以便 deterministic projection。

SAMNodeSet.spec.nodes[].macAddresses 可静态列出同一 fabric 中 member 的 MAC 地址。on-prem ARP observer 会把所有 member MAC 的并集作为 ignore set,避免 routerd member 发出的 ARP frame 被当作 mobile /32 的 ownership signal。macAddresses 的编辑是声明式 intent:routerd 会导出 observer ignore set,并通过 observer socket 自动收敛,不需要重启 observer 或 routerd。observer status 会显示当前生效的 ignore set 和被忽略的 observation 计数,便于确认收敛状态。

transport

当前 SAM transport 默认使用 IPIP delivery plane。WireGuard 如存在,只作为加密 underlay; WireGuard peer 的 AllowedIPs 应只包含 transport endpoint prefix,不应包含 mobile /32

SAMTransportProfile 会生成 per-peer TunnelInterface、endpoint /32 IPv4RouteBGPPeer。所有 profile 通过 peersFrom 使用相同的 SAMNodeSet,因此每条 node pair edge 都能导出相同的 /31nodeRefs 可将 peer 限制为实际 adjacency;省略时会选择带 samEndpoint 的所有非 self node。

已签名的 enrollment 可以在同一个 runtime snapshot 中额外返回一个 SAMPeerGroup,并在 peersFrom 中标记为 direct: true。它只是在可达 leaf 之间尝试 一条可选的 L3 直连路径;前面的非 optional SAMRRSet 仍是启动和故障时的回退路径。 direct source 必须使用 addressingMode: pair-stable,并且不能把 peer 配成 route reflector client。

当 direct BGP session 建立后,routerd 会给它导入的路由设置比 RR 更高的 BGP LOCAL_PREF。这不是根据 AS_PATH 长度或 administrative distance 选择:iBGP 的 RR 反射不会可靠地把额外的转发 hop 写入 AS_PATH。profile 必须显式设置 RR 的 bgp.importPolicy.localPreferencebgp.directLocalPreference 必须更高。每个 direct leaf 还只能通告其签名 claim 中列出的 IPv4 /32;没有、过期、不兼容或不可达的 direct group 会被忽略,RR 路径继续工作。

RR import 的 nextHopRewrite 请保持默认的 peer-address,或显式写出该值。direct profile 应使用 peer-address 而不是 unchanged:RR 反射的路由可能来自另一台 leaf,但真正可达的下一跳是 直接相连的 RR tunnel。若旧的 direct profile 明确保留了 unchanged,routerd 会在运行时 安全地将有效策略规范化为 peer-address,以便 daemon 启动后可以替换 YAML。请把 YAML 更新为显式形式;non-direct profile 原有的 unchanged 语义不变。它只决定学习到路由后的 转发下一跳,不会改变是否接纳 direct peer。

dynamic RR sync fail-static

RR 可以发布 SAMPeerGroup,leaf 通过 TCP 19652 获取缺失的 transport peer group。 SAMPeerGroup 仅是运行时同步 payload,不能作为 top-level spec.resources 声明。 获取成功后,leaf 会把它保存为带 TTL 的 dynamic config part:

  • peer-group-sync/<name> 对应 SAMPeerGroup

TTL 过期或 RR publisher 消失时,leaf 不会删除已经生成的 tunnel 或 BGP peer。routerd 会继续使用 last-known-good 记录,并把来源标记为 Stale,同时在 status 中输出 warning。MobilityPool membership 直接从静态 SAMNodeSet 配置解析,不依赖成员资格 同步端点。

capture and delivery

MobilityPool 始终使用 BGP delivery。owner advertise selected /32,non-owner 将 BGP best path import 到 local FIB。

支持的 capture type:

TypeMeaning
provider-secondary-ipcloud fabric 通过 provider secondary address object 或等价机制 capture /32
proxy-arpsite router 在本地对 selected address 回答 ARP。

cloud provider-secondary-ip capture 可选择 capture strategy。当前 release lab 认证仅覆盖 secondary-ip capture。route-table strategy 目前为 uncertified: 在 Azure 上它通过 UDR 指向 holder,并要求 routerd 等待 provider inventory 观测到 该 UDR 指向本地 router 后,才将已 capture 的 /32 广告到 BGP。这个 provider 观测 gate 是 route-table strategy 特有的;secondary-ip capture 不使用 route-table 观测来决定何时广告 overlay holder。由于该设计会把 ARM/provider API 延迟传递到 overlay 收敛,route-table strategy 需要在 release lab 中完成 provider 观测、BGP 广告耦合和 provider API 延迟行为验证后才能认证。

on-prem proxy-arp capture 可使用 activeWhen.type: single-router 作为单 router always-active capture,也可使用 vrrp-master 由 HA pair 的 VRRP master gate 控制。 activeWhen 仅支持此 on-prem proxy-arp capture;cloud provider-secondary-ip capture 设置该字段会被拒绝,因此本地 VRRP 状态变化 不会在缺少对应 BGP 和本地数据平面计划时创建 provider assignment。

on-demand-arp source 会以低速 proactive sweep 探测 mobility prefix:每个 scanInterval 探测一个 target,使已启动但安静的 L2 client 也能被观测到。

provider actions

provider capture planner 可输出 assign-secondary-ipensure-forwarding-enabled 等 provider ActionPlan。planner 本身不调用 provider API。action plan 只有在导入 provider-action journal 并通过 ProviderActionPolicy、approval、allowlist 与 executor plugin gate 后才可能执行。

RR admission filters

Generated route-reflector client BGP peers derive an import admission policy from the SAM topology and importPolicy.allowedPrefixes; if that prefix list is omitted, routerd defaults it from declared MobilityPool prefixes. Imported routes must be /32s under the permitted prefixes, must carry the advertising leaf's own node-identity community, and must not carry another topology node's identity. This prevents a leaf from claiming another node identity or advertising a broad mobility prefix through the generated RR session. A compromised leaf can still advertise a pool-local /32 with its own identity; constraining per-node ownership requires a separate authorization signal beyond this route filter.

ownership inspection

MobilityPool status exposes one per-address operational view: ownershipResolverControlPlaneOwnerTable. doctor sam, FIB checks, and operators use this control-plane table. It keeps one deterministic row per observed mobility address and includes owner provider/NIC/subnet/resource, local evidence, capture state and final captureDisposition/captureReason, advertise/suppression state, and conflict details.

Use routerctl mobility explain --pool <pool> --address <ipv4/32> to render an owner-table row together with pool-level provider status. OwnershipResolved comes from the row. providerActionFailedAddresses makes ProviderActionApplied=False only for a named address, and providerObservationPendingAddresses makes ProviderObserved=False only for a named address. Those conditions remain Unknown for all other addresses; the pool-level provider phase is not projected as a failure for every address.

When two fresh provider owners claim the same /32, the row state is Conflict with conflictReason=duplicate-provider-home-owners. The row also includes conflictWinnerNode and conflictResolution: the healed BGP owner wins when present; otherwise the lowest stable owner key wins (nodeRef, provider ref, resource ref, NIC ref, subnet ref, then address), independent of provider scan recency. A losing node that still observes a local provider-secondary capture reports loser-release-local-capture and releases only that local capture after the stale-capture hold-down.

firewall and NAT

SAM 不包含 natpreserveSource、firewall 或 zone 字段。若要 firewall/NAT mobile address,请在现有 FirewallZoneFirewallRuleNAT44Rule 中引用 literal /32。 SAM forwarded traffic 仍会经过普通 forwarding/firewall/conntrack path。

conntrack cleanup design note

routerd 曾短暂公开 BGP mode SAM failover 的手动 opt-in scoped conntrack cleanup hook。 该功能已经移除。 在参考 SAM leaf 构成中,routerd 不会绘制让 delivered overlay flow 进入 conntrack 的 dataplane rule,因此 leaf 侧 scoped cleanup 是 no-op,也不能解决 failover flow anomaly。

这个问题陈述对未来 stateful SAM leaf 设计仍然成立:如果某个 router 有意追踪 forwarded mobile /32 flow,它在成为 holder 时可能需要 scoped recovery hook。重新引入时应检测 routerd-managed ct-engage dataplane,并只在该场景自动启用 cleanup。不要以手动 opt-in flag 的形式重新引入。