MCLAG 从原理到 SONiC 代码实现

摘要

MCLAG 的全称是 Multi-Chassis Link Aggregation,也就是跨设备的链路聚合。普通 LAG/PortChannel 只能把多条链路聚合到同一台交换机上;MCLAG 则让服务器或下游交换机把链路分别接到两台交换机,但在它看来仍然像接入了一个逻辑 PortChannel。

在 SONiC 中,MCLAG 不是一个独立函数完成的功能,而是由 iccpdmclagsyncd、CONFIG_DB、STATE_DB、APPL_DB、orchagent、FDB 编排、ARP/ND 同步以及可选的 BGP host route 发布共同组成。

最核心的两条线是:

  • 控制面:两台设备通过 ICCP/mLACP 交换角色、接口、MAC、ARP/ND 等信息。
  • 数据面:本地和远端学习到的 FDB、端口隔离、MAC 学习模式、流量开关等,最终通过 SWSS 编排到 ASIC。

一句话总结:

MCLAG 的本质不是“两个交换机都配置了 PortChannel”,而是“两台交换机通过 ICCP/mLACP 把自己协调成一个逻辑聚合系统,同时避免环路、重复学习和异常转发”。

关键词

MCLAG、MLAG、ICCP、mLACP、PortChannel、peer-link、active/standby、FDB sync、ARP sync、ND sync、SONiC、SWSS、mclagsyncd、iccpd


1. 先建立直觉:MCLAG 解决什么问题?

假设一台服务器有两张网卡,希望做链路聚合:

Server eth0 ---- Switch A
Server eth1 ---- Switch B

如果没有 MCLAG,服务器不能简单地把 eth0eth1 做成一个普通 LACP PortChannel,因为这两条链路接到了两台不同的交换机。对服务器来说,它希望对端是“一个逻辑交换机”;但真实网络里,对端其实是两台独立设备。

MCLAG 要解决的就是这个矛盾:

服务器视角:      Server <==== PortChannel ====> 一个逻辑交换机
真实物理视角:    Server eth0 -> Switch A
                 Server eth1 -> Switch B

为了做到这一点,两台交换机必须互相同步:

  • 谁是 Active,谁是 Standby。
  • 哪些 PortChannel 是 MCLAG 成员。
  • peer-link 是哪个接口。
  • 哪些 MAC 是本地学到的,哪些 MAC 是 peer 同步来的。
  • ARP/ND 表项如何同步。
  • 什么时候要隔离端口,避免流量环路。
  • peer 掉线、keepalive 超时、接口状态变化时怎么处理。

2. 没有 MCLAG 时会有什么问题?

如果服务器双上联到两台独立交换机,而交换机之间没有 MCLAG 协调机制,就会遇到几个典型问题。

2.1 LACP 视角不一致

服务器认为自己在和一个 LACP partner 建立聚合,但 Switch A 和 Switch B 是两个独立系统。它们的 system ID、端口状态、聚合状态不一致,普通 LACP 无法天然把它们合成一个 PortChannel。

2.2 MAC 学习冲突

同一个服务器 MAC 可能在 Switch A 和 Switch B 上同时出现。如果两台交换机不共享 MAC 信息,就可能出现 MAC 抖动、错误转发或重复下发。

2.3 环路和双发风险

两台设备都能转发同一个二层域的流量,如果没有 peer-link 隔离、成员端口隔离和角色协调,就可能形成环路或重复流量。

没有 MCLAG 协调时的风险可以简化成下面这张图:

在这里插入图片描述

图 1:没有 MCLAG 协调时的风险

MCLAG 的目标就是让 Switch A 和 Switch B 在控制面上达成一致,对外表现得像一个逻辑系统。


3. 有 MCLAG 时的基本逻辑

MCLAG 场景里,常见角色如下:

Server / 下游设备:双上联,配置 bond/PortChannel
Switch A:MCLAG peer 之一
Switch B:MCLAG peer 之一
Peer Link:Switch A 与 Switch B 之间用于同步和转发的链路
ICCP:两台交换机之间的控制协议通道
mLACP:在 ICCP 之上同步 LACP/聚合相关状态

典型拓扑:

在这里插入图片描述

图 2:MCLAG 双归接入拓扑

可以把 MCLAG 理解成四件事:

  1. 配置一个 MCLAG domain,告诉设备本端 IP、peer IP、peer-link 等信息。
  2. 把某些 PortChannel 加入这个 domain,成为 MCLAG 成员。
  3. 两台设备通过 ICCP/mLACP 建立会话,同步角色、接口、MAC、ARP/ND 等信息。
  4. 本地 SWSS 根据同步结果设置 FDB、端口隔离、MAC 学习模式、流量开关等数据面状态。

4. SONiC 代码中的关键模块

下面是本文涉及的本地代码索引:

模块 关键文件 作用
构建开关 rules/config INCLUDE_ICCPD = y 控制是否构建 MCLAG 支持
Debian 包 rules/iccpd.mk 定义 iccpd 包版本、源码路径和依赖
Docker 镜像 rules/docker-iccpd.mk 定义 docker-iccpd 镜像和容器包
容器脚本 dockers/docker-iccpd/start.sh, iccpd.sh, iccpd.j2 生成配置并启动 mclagsyncdiccpd
CLI src/sonic-utilities/config/mclag.py 提供 config mclag ... 命令
YANG src/sonic-yang-models/yang-models/sonic-mclag.yang 定义 MCLAG_DOMAINMCLAG_INTERFACEMCLAG_UNIQUE_IP
mclagsyncd src/sonic-swss/mclagsyncd/mclagsyncd.cpp, mclaglink.cpp, mclag.h 在 Redis DB 和 iccpd 之间转发配置、FDB、状态消息
iccpd src/iccpd/src/*.c, src/iccpd/include/*.h 维护 ICCP 会话、mLACP 状态机、MAC/ARP/ND 同步
MlagOrch src/sonic-swss/orchagent/mlagorch.cpp 让 orchagent 感知 peer-link 和 MCLAG 成员接口
FdbOrch src/sonic-swss/orchagent/fdborch.cpp 消费 MCLAG FDB 表项,处理远端/本地 MAC 学习关系
BGP 发布 src/sonic-bgpcfgd/bgpcfgd/managers_advertise_rt.py 将 MCLAG host route 转成 FRR BGP network 配置
诊断工具 src/iccpd/src/mclagdctl/mclagdctl.c 查询 MCLAG 状态、ARP/ND/MAC、端口列表和 debug counters

5. 配置面:从 config mclag 到 CONFIG_DB

SONiC 的 MCLAG CLI 入口在:

src/sonic-utilities/config/mclag.py

常见命令和写入的数据如下:

命令 写入/修改的表 说明
config mclag add <domain_id> <source_ip> <peer_ip> [peer_link] CONFIG_DB:MCLAG_DOMAIN 创建或修改 MCLAG domain
config mclag del <domain_id> CONFIG_DB:MCLAG_DOMAIN, MCLAG_INTERFACE 删除 domain,并清理成员接口
config mclag keepalive-interval <domain_id> <seconds> CONFIG_DB:MCLAG_DOMAIN.keepalive_interval 设置 keepalive 周期
config mclag session-timeout <domain_id> <seconds> CONFIG_DB:MCLAG_DOMAIN.session_timeout 设置会话超时时间
config mclag member add <domain_id> <PortChannel...> CONFIG_DB:MCLAG_INTERFACE 添加 MCLAG 成员 PortChannel
config mclag member del <domain_id> <PortChannel...> CONFIG_DB:MCLAG_INTERFACE 删除 MCLAG 成员 PortChannel
config mclag unique-ip add <Vlan...> CONFIG_DB:MCLAG_UNIQUE_IP 开启 VLAN unique-ip
config mclag unique-ip del <Vlan...> CONFIG_DB:MCLAG_UNIQUE_IP 删除 VLAN unique-ip

配置流如下:

在这里插入图片描述

图 3:从 config mclag 到 CONFIG_DB 和 iccpd

一个最小配置例子:

config mclag add 1 10.0.0.1 10.0.0.2 PortChannel100
config mclag keepalive-interval 1 5
config mclag session-timeout 1 30
config mclag member add 1 PortChannel10

含义是:

domain_id = 1
本端 ICCP IP = 10.0.0.1
对端 ICCP IP = 10.0.0.2
peer-link = PortChannel100
MCLAG 成员接口 = PortChannel10

6. YANG 模型:哪些配置是合法的?

MCLAG 配置模型定义在:

src/sonic-yang-models/yang-models/sonic-mclag.yang

6.1 MCLAG_DOMAIN

MCLAG_DOMAIN 描述一个 MCLAG domain。代码中 YANG 使用 max-elements 1,因此当前模型最多允许一个 domain。

字段 类型/约束 说明
domain_id uint16, 范围 1..4095 MCLAG domain ID,表 key
source_ip IPv4 address 本端 ICCP 源地址
peer_ip IPv4 address 对端 ICCP 地址
peer_link Port 或 PortChannel leafref peer-link 接口
keepalive_interval uint16, 范围 1..60, 默认 1 keepalive 周期
session_timeout uint16, 范围 1..3600, 默认 30 会话超时时间
arp_to_bgp_host_route boolean, 默认 false 是否将 ARP 学习到的主机路由发布给 BGP

YANG 约束:

keepalive_interval * 3 <= session_timeout

CLI 中还有额外检查:session_timeout 需要是 keepalive_interval 的整数倍。这个整数倍约束来自 CLI 逻辑,不是 YANG must 条件。

6.2 MCLAG_INTERFACE

MCLAG_INTERFACE 描述加入 MCLAG domain 的 PortChannel 成员。

字段 类型/约束 说明
domain_id leafref 到 MCLAG_DOMAIN 所属 domain
if_name leafref 到 PORTCHANNEL MCLAG 成员接口
if_type string CLI 写入 PortChannel

Redis key 形态:

MCLAG_INTERFACE|<domain_id>|<PortChannelName>

6.3 MCLAG_UNIQUE_IP

MCLAG_UNIQUE_IP 用于配置 VLAN 接口 unique-ip。

字段 类型/约束 说明
if_name VLAN 名称,例如 Vlan100 表 key
unique_ip enum,仅支持 enable 开启 unique-ip

YANG 要求已经存在 MCLAG domain,并且接口名必须符合 VLAN 命名格式。CLI 还会检查 VLAN 接口不能绑定非 default VRF,且不能已经配置 IP 地址。

Redis key 形态:

MCLAG_UNIQUE_IP|<VlanName>

7. 容器启动:mclagsyncdiccpd 是怎么起来的?

MCLAG 运行在 iccpd 容器里。构建和启动相关文件主要是:

rules/iccpd.mk
rules/docker-iccpd.mk
dockers/docker-iccpd/start.sh
dockers/docker-iccpd/iccpd.sh
dockers/docker-iccpd/iccpd.j2

启动流程可以简化为:

在这里插入图片描述

图 4:docker-iccpd 容器启动流程

这里要注意一个容易踩坑的点:

  • iccpd.j2 模板读取的是 MC_LAG 字段,用来生成 /etc/iccpd/iccpd.conf
  • 当前 CLI/YANG 运行态主要使用 MCLAG_DOMAINMCLAG_INTERFACEMCLAG_UNIQUE_IP

所以看问题时要先确认配置到底来自启动模板,还是来自运行态 CONFIG_DB。


8. mclagsyncd:Redis DB 和 iccpd 之间的翻译层

mclagsyncd 的入口在:

src/sonic-swss/mclagsyncd/mclagsyncd.cpp

它做的事可以理解成“翻译”:

CONFIG_DB / STATE_DB / APPL_DB  <-->  mclagsyncd  <-->  iccpd

启动后,mclagsyncd 会创建 DB 连接,等待 iccpd 连上 127.0.0.6:2626。连接建立后,它会读取当前 MCLAG 配置,并把相关表加入事件循环。

核心监听表包括:

DB 作用
MCLAG_DOMAIN CONFIG_DB domain 配置变化
MCLAG_INTERFACE CONFIG_DB MCLAG 成员接口变化
MCLAG_UNIQUE_IP CONFIG_DB unique-ip 配置变化
STATE_FDB_TABLE STATE_DB 本地 FDB 变化
STATE_MCLAG_REMOTE_FDB_TABLE STATE_DB 远端 MCLAG FDB 状态
STATE_VLAN_MEMBER_TABLE STATE_DB VLAN member 变化

整体流程图:

在这里插入图片描述

图 5:mclagsyncd 在 DB 与 iccpd 之间的作用

消息类型定义在:

src/sonic-swss/mclagsyncd/mclag.h

mclagsyncd 发给 iccpd 的典型消息包括:

消息 含义
MCLAG_MSG_TYPE_CFG_MCLAG_DOMAIN domain 配置
MCLAG_MSG_TYPE_CFG_MCLAG_IFACE 成员接口配置
MCLAG_MSG_TYPE_CFG_MCLAG_UNIQUE_IP unique-ip 配置
MCLAG_MSG_TYPE_FDB_OPERATION 本地 FDB 变化
MCLAG_MSG_TYPE_VLAN_MBR_UPDATES VLAN member 变化

iccpd 发给 mclagsyncd 的典型消息包括:

消息 含义
MCLAG_MSG_TYPE_SET_FDB 设置或删除 MCLAG FDB
MCLAG_MSG_TYPE_PORT_ISOLATE 设置端口隔离
MCLAG_MSG_TYPE_PORT_MAC_LEARN_MODE 设置 MAC 学习模式
MCLAG_MSG_TYPE_SET_ICCP_STATE 更新 ICCP 状态
MCLAG_MSG_TYPE_SET_ICCP_ROLE 更新 Active/Standby 角色
MCLAG_MSG_TYPE_SET_REMOTE_IF_STATE 更新远端接口状态
MCLAG_MSG_TYPE_SET_HOST_ROUTE 设置或删除 BGP host route
MCLAG_MSG_TYPE_SYNC_HOST_ROUTES 同步 host route

9. iccpd:ICCP 会话和 mLACP 状态机

iccpd 是 MCLAG 控制面的核心。它负责:

  • 读取配置。
  • 建立设备间 ICCP 会话。
  • 维护 Active/Standby 角色。
  • 运行 mLACP 状态机。
  • 同步 MAC、ARP、ND、接口状态。
  • mclagsyncd 下发 FDB、隔离、host route 等结果。

关键文件:

文件 作用
src/iccpd/src/system.c 初始化全局 System、日志路径、配置路径、控制 socket 路径
src/iccpd/src/scheduler.c 主调度循环,读取配置、初始化 socket/netlink、检查 heartbeat
src/iccpd/include/iccp_csm.h ICCP CSM 状态、端口、domain 字段定义
src/iccpd/src/iccp_csm.c CSM 状态、Active/Standby 角色相关逻辑
src/iccpd/include/mlacp_fsm.h mLACP 状态机和同步阶段定义
src/iccpd/src/mlacp_fsm.c mLACP 状态机实现
src/iccpd/src/mlacp_link_handler.c mclagsyncd 的消息处理、host route、接口状态等

ICCP 会话状态包括:

NONEXISTENT
INITIALIZED
CAPSENT
CAPREC
CONNECTING
OPERATIONAL

mLACP 主状态可以简化为:

INIT -> STAGE1 -> STAGE2 -> EXCHANGE

状态机流程图:

在这里插入图片描述

图 6:mLACP 状态机主流程

角色选择也很重要。代码中按本端 IP 和 peer IP 比较:

source_ip 更小的一侧:Active,并主动连接 peer
source_ip 更大的一侧:Standby,等待 peer 连接
source_ip 等于 peer_ip:错误配置

对应流程:

在这里插入图片描述

图 7:ICCP Active/Standby 角色判断


MCLAG 中有两类接口要分清:

接口 含义
peer-link 两台 MCLAG peer 之间的互联链路
MCLAG member 面向服务器或下游设备的双归 PortChannel

CLI 添加成员接口:

config mclag member add 1 PortChannel10

写入 CONFIG_DB 后,链路如下:

在这里插入图片描述

图 8:MCLAG 成员接口配置流转

mclagsyncd 在处理成员 SET 时,会写入本地接口状态:

MCLAG_LOCAL_INTF_TABLE|<PortChannelName>
  port_isolate_peer_link=true

MlagOrch 会监听:

  • MCLAG_DOMAIN:主要关注 peer_link
  • MCLAG_INTERFACE:维护 MCLAG 成员接口集合。

MlagOrch 不负责建立 ICCP 会话,它更像 orchagent 内部的“接口身份识别器”:告诉其他模块某个接口是不是 MCLAG 成员,某个接口是不是 peer-link。


11. FDB 同步:MAC 是怎么跨设备同步的?

FDB 同步是理解 MCLAG 的重点。可以从两个方向看。

11.1 本地学习的 MAC 发给 peer

当本机学习到 MAC 后,FDB 变化会进入 STATE_FDB_TABLEmclagsyncdprocessStateFdb() 读取这些变化,转换为 MCLAG FDB 消息发给 iccpd,再由 iccpd 同步给 peer。

流程图:

在这里插入图片描述

图 9:FDB 同步流程

代码中 FDB 类型映射如下:

DB 字段 MCLAG 消息类型
dynamic MCLAG_FDB_TYPE_DYNAMIC
dynamic_local MCLAG_FDB_TYPE_DYNAMIC
static MCLAG_FDB_TYPE_STATIC

DEL 事件可能不带完整字段,所以 mclagsyncd 会缓存 FDB 对应的 port/type,删除时仍能发出完整信息。

11.2 peer 同步来的 MAC 写入本机

peer 同步来的 FDB 由 iccpd 发给 mclagsyncdmclagsyncd 再写入 APPL_DB:

APPL_DB 表 用途
MCLAG_FDB_TABLE 普通 MCLAG 同步 FDB
MCLAG_CTRL_FDB_TABLE 控制类 MCLAG FDB

key 格式:

Vlan<vid>:<mac>

fdborch 消费这两张表,并用不同 origin 标记区分:

origin 标记
APP_MCLAG_FDB_TABLE_NAME FDB_ORIGIN_MCLAG_ADVERTIZED
APP_MCLAG_CTRL_FDB_TABLE_NAME FDB_ORIGIN_MCLAG_CTRL_ADVERTIZED

还有一个细节:mclagsyncd 会读取 STATE_MCLAG_REMOTE_FDB_TABLE,但代码中避免将 remote MCLAG FDB 再发回 iccpd,防止重复同步或加删循环。


12. ARP/ND 同步与 BGP host route

MCLAG 不只同步 MAC,也会处理 ARP/ND。iccpd 通过 netlink 维护本机 ARP/ND 信息,并在 mLACP EXCHANGE 阶段与 peer 同步。

如果 MCLAG_DOMAIN 中启用:

arp_to_bgp_host_route=true

那么本地 ARP 产生的 IPv4 /32 主机路由可以被发布给 BGP。

流程图:

在这里插入图片描述

图 10:ARP 到 BGP host route 的流程

mclagsyncd 写入 STATE_DB 的形态:

ADVERTISE_NETWORK_TABLE|<ip>/32
  source=mclag

如果带 VRF,key 会格式化为:

ADVERTISE_NETWORK_TABLE|<vrf>|<ip>/32

src/sonic-bgpcfgd/bgpcfgd/managers_advertise_rt.py 中的 AdvertiseRouteMgr 监听 STATE_DB:ADVERTISE_NETWORK_TABLE,把 source=mclag 的前缀转换成 FRR BGP address-family 下的 network <prefix> 配置。

代码限制也很明确:这里只处理 IPv4 /32 host route,非 /32 前缀会被拒绝。


13. 端口隔离、MAC 学习和流量开关

MCLAG 必须避免双归场景中的环路和错误转发。因此 iccpd 会通过 mclagsyncd 设置一些数据面状态。

功能 代码行为
端口隔离 setPortIsolate() 更新 APP_ISOLATION_GROUP_TABLEAPP_ISOLATION_GROUP_MEMBER_TABLE
保留隔离组 使用保留组名 MCLAG_ISO_GRP
MAC 学习模式 setPortMacLearnMode() 向 PORT/LAG APP 表写入 learn_mode
FDB flush setFdbFlush() 发送 FLUSHFDBREQUEST 通知
接口 MAC setIntfMac() 设置接口 mac_addr
流量开关 mclagsyncdSetTrafficDisable() 写入 LAG 表 traffic_disable=true/false
远端接口状态 写入 MCLAG_REMOTE_INTF_TABLE

隔离相关流程:

在这里插入图片描述

图 11:端口隔离下发流程

src/sonic-utilities/config/isolation_group.py 中保留了 MCLAG_ISO_GRP,普通用户配置隔离组时不能使用这个名字。


14. 常用查看与排障命令

14.1 查看 CONFIG_DB

sonic-db-cli CONFIG_DB hgetall "MCLAG_DOMAIN|1"
sonic-db-cli CONFIG_DB hgetall "MCLAG_INTERFACE|1|PortChannel10"
sonic-db-cli CONFIG_DB hgetall "MCLAG_UNIQUE_IP|Vlan100"

14.2 查看 STATE_DB

sonic-db-cli STATE_DB hgetall "MCLAG_TABLE|1"
sonic-db-cli STATE_DB hgetall "MCLAG_LOCAL_INTF_TABLE|PortChannel10"
sonic-db-cli STATE_DB hgetall "MCLAG_REMOTE_INTF_TABLE|1|PortChannel10"
sonic-db-cli STATE_DB keys "ADVERTISE_NETWORK_TABLE*"

14.3 查看 APPL_DB

sonic-db-cli APPL_DB keys "MCLAG_FDB_TABLE*"
sonic-db-cli APPL_DB keys "MCLAG_CTRL_FDB_TABLE*"
sonic-db-cli APPL_DB keys "ISOLATION_GROUP*"
sonic-db-cli APPL_DB hgetall "LAG_TABLE:PortChannel10"

14.4 使用 mclagdctl

mclagdctl 的 host 侧包装脚本会通过 docker exec 进入 iccpd 容器执行真实命令。

常用命令:

mclagdctl -i 1 dump state
mclagdctl -i 1 dump arp
mclagdctl -i 1 dump nd
mclagdctl -i 1 dump mac
mclagdctl -i 1 dump unique_ip
mclagdctl -i 1 dump portlist local
mclagdctl -i 1 dump portlist peer
mclagdctl -i 1 dump debug counters
mclagdctl -l debug config loglevel

dump state 里可以看到:

  • keepalive 状态。
  • 信息同步是否完成。
  • domain id。
  • local IP / peer IP。
  • peer-link。
  • keepalive time / session timeout。
  • Active 或 Standby 角色。
  • MCLAG interface。
  • 当前 loglevel。

14.5 核心故障案例:ICCP 会话建立失败,MAC/ARP/FDB 无法同步

现象

两台设备已经写入 MCLAG domain 和成员接口配置,但业务侧看不到跨设备同步的 MAC、ARP/ND,dump state 持续显示:

The MCLAG's keepalive is: ERROR
MCLAG info sync is: incomplete

在本端 IP 较小、负责主动连接 peer 的设备上,/var/log/iccpd.log 反复出现类似错误:

Bind socket failed. Error = -1 errno = 99

这里以 Linux 常见的 errno=99 为例;不同失败原因的 errno 可能不同,首先应抓住 Bind socket failed 这个关键信号。

定位

先确认两端 CONFIG_DB 中的本端和对端地址没有写反:

sonic-db-cli CONFIG_DB hgetall "MCLAG_DOMAIN|1"

再确认 source_ip 确实配置在本机,而不是只存在于 MCLAG 配置中:

ip -4 addr show
ip route get <peer_ip> from <source_ip>
ping -I <source_ip> <peer_ip>

最后检查对端 iccpd 是否监听 ICCP 使用的 TCP/8888:

docker ps --filter name=iccpd
docker exec iccpd ss -lntp | grep ':8888'

当前本地代码中,src/iccpd/src/scheduler.c 会先把出站 socket 绑定到 csm->sender_ip,然后才连接 csm->peer_ip:8888。如果 source_ip 不是本机地址,bind() 就会失败,后续 connect() 根本不会执行。src/iccpd/include/iccp_csm.h 则明确将 ICCP_TCP_PORT 定义为 8888

根因

本例的根因是 MCLAG domain 中的 source_ip 填错,或者该地址尚未配置到本机接口。CONFIG_DB 里虽然存在字符串形式的 source_ip,但这不代表 Linux 已经拥有这个地址。

由于低 IP 一侧无法绑定本地源地址,它不能向 peer 发起 TCP/8888 连接,ICCP 状态无法进入 OPERATIONAL;mLACP 也无法进入 EXCHANGE,因此 MAC、ARP/ND 和接口状态同步都不会正常开始。

解决

先通过持久化接口配置把 ICCP 源地址配置到正确的本机接口,或改正写反的 MCLAG 地址。两台设备的地址必须互为 local/peer。例如:

# Switch A
config mclag add 1 10.0.0.1 10.0.0.2 PortChannel100

# Switch B
config mclag add 1 10.0.0.2 10.0.0.1 PortChannel100

config mclag add 对已存在的同一 domain 会修改 MCLAG_DOMAIN。生产环境变更会触发会话重新建立,应在维护窗口执行,并先确认 peer-link 和承载 ICCP 地址的三层接口都已就绪。不要只临时执行 ip addr add 后就认为问题永久解决,因为重启后临时地址可能丢失。

验证

修复后按下面顺序形成闭环:

  1. ip -4 addr show 能在本机看到正确的 source_ip
  2. ping -I <source_ip> <peer_ip> 成功,对端能看到 TCP/8888 监听。
  3. 日志不再出现 Bind socket failed,并出现连接成功记录。
  4. mclagdctl -i 1 dump state 显示 The MCLAG's keepalive is: OKMCLAG info sync is: completed
  5. 再用 dump macdump arp 和 STATE_DB/APPL_DB 验证同步结果;表项为空不一定是故障,还要先确认网络中确实产生了对应学习事件。

14.6 查看日志

docker logs iccpd

iccpd 代码中的默认日志路径:

/var/log/iccpd.log

因为 iccpd.sh 同时启动了 mclagsyncdiccpd,所以排查时要同时关注这两个进程的日志。


15. 一次完整配置后的代码链路

以这组配置为例:

config mclag add 1 10.0.0.1 10.0.0.2 PortChannel100
config mclag keepalive-interval 1 5
config mclag session-timeout 1 30
config mclag member add 1 PortChannel10

完整链路可以这样理解:

在这里插入图片描述

图 12:一次完整配置后的代码链路

对应文字版:

  1. config mclag 写 CONFIG_DB。
  2. mclagsyncd 监听 CONFIG_DB,把 domain/member 配置发给 iccpd
  3. iccpd 创建或更新 ICCP CSM。
  4. 低 IP 一侧主动连接 peer,高 IP 一侧等待连接。
  5. 双方使用 TCP/8888 建立 ICCP 会话。
  6. mLACP FSM 进入同步阶段,交换系统、聚合口、peer-link、ARP/ND、MAC 等信息。
  7. 本地 FDB 变化经 STATE_FDB_TABLE -> mclagsyncd -> iccpd -> peer 同步。
  8. peer FDB 经 peer iccpd -> local iccpd -> mclagsyncd -> APPL_DB MCLAG_FDB_TABLE 下发给 orchagent。
  9. MlagOrchFdbOrch 识别 peer-link、MCLAG 成员和 MCLAG FDB,最终影响 ASIC 编程。
  10. 如果启用 arp_to_bgp_host_route,ARP 产生的 IPv4 /32 会进入 STATE_DB:ADVERTISE_NETWORK_TABLE,由 bgpcfgd 发布到 BGP。

16. 新手排查思路

如果 MCLAG 不工作,可以按下面顺序看,不要一上来就直接抓复杂报文。

在这里插入图片描述

图 13:新手排查顺序

建议顺序:

  1. 先查 CONFIG_DB,确认配置有没有写进去。
  2. 再查 docker logs iccpdmclagdctl -i 1 dump state,确认 ICCP 会话。
  3. 再查 STATE_DB,确认本地/远端接口状态。
  4. 再查 APPL_DB,确认 FDB、隔离组、LAG 状态是否被写入。
  5. 最后再看 orchagent、syncd、ASIC 层。

17. 代码层面的注意事项

  1. 当前 YANG 和 CLI 都体现了单 domain 设计,MCLAG_DOMAIN 最多一个实例。

  2. keepalive_interval 的 YANG 默认值是 1session_timeout 的 YANG 默认值是 30。但 CLI 辅助逻辑中,部分字段缺省时使用自己的 fallback 值,例如 keepalive 设置逻辑里对缺省 session_timeout 使用了 15。线上建议显式配置 keepalive 和 timeout。

  3. src/sonic-utilities/config/mclag.pyADHOC_VALIDATION = False,实际写库通常依赖 ValidatedConfigDBConnector/CVL/YANG 做校验。阅读 CLI 里的手工校验函数时,要注意它们不一定在默认路径全部启用。

  4. 启动模板 iccpd.j2 使用 MC_LAG,而当前配置 CLI 写入 MCLAG_DOMAINMCLAG_INTERFACEMCLAG_UNIQUE_IP。两套入口在代码中同时存在,分析问题时要确认目标版本实际使用的是哪条路径。

  5. src/sonic-swss/mclagsyncd/mclaglink.cppmclagsyncdSendMclagUniqueIpCfg() 对 key 的解析看起来按包含 | 的复合 key 处理;而 YANG/CLI 中 MCLAG_UNIQUE_IP 的 key 是 VLAN 接口名。如果发现 unique-ip 运行态不生效,应优先在目标分支上确认这段 key 解析与实际 Redis key 是否一致。

  6. arp_to_bgp_host_route 只会发布 IPv4 /32 host route。mclagsyncd 写入 STATE_DB 的 ADVERTISE_NETWORK_TABLE,再由 bgpcfgd 转换为 FRR BGP network 配置。

  7. MCLAG_ISO_GRP 是 MCLAG 内部使用的隔离组名,普通隔离组配置不应使用该名字。

posted @ 2026-09-10 15:35  码上观网  阅读(2)  评论(0)    收藏  举报