IBM s390 QDIO 以太网驱动(qeth)的 OSA/HiperSockets 桥接端口支持与 udev 事件机制解析
【免费下载链接】linuxLinux kernel source tree项目地址: https://gitcode.com/GitHub_Trending/li/linux
导读
本文围绕 Linux 内核中 IBM s390 平台的 QDIO 以太网驱动(qeth)的 Bridge Port 支持展开,完整解析当 OSA 与 HiperSockets 桥接端口设备状态变化、主机地址/VLAN 注册注销时,驱动如何通过 udev(kobject uevent)事件将硬件信息传递给用户空间。读者将掌握BRIDGEPORT、BRIDGEDHOST、NTOK_*等事件属性的完整含义、触发条件,并结合仓库源码理解事件从硬件中断到用户空间的分发链路,从而能够编写精准的 udev 规则实现网络状态监控与自动化运维。
一、背景:qeth 驱动的 OSA 与 HiperSockets 桥接端口
qeth 是 Linux 内核中面向 IBM Z / s390 平台 QDIO(Queued Direct I/O)架构的以太网驱动程序,源码位于 drivers/s390/net/qeth_*.c。它支持两类典型硬件:
- OSA(Open Systems Adapter):s390 平台的以太网适配器,可承载 VLAN、多协议通道等特性;
- HiperSockets:基于内存的虚拟局域网(IQD 设备),用于 LPAR 内虚拟机之间的高速通信,无需物理网络。
在桥接场景下,qeth 设备可以作为Bridge Port参与虚拟交换:一个设备被配置为primary(主)桥接端口,其余为secondary(次)桥接端口,共同将物理网络桥接给多个 z/VM 或 LPAR 客户机。要产生下文所述事件,设备必须被分配为 primary 或 secondary 角色(详见 IBM 官方文档 "z/VM Connectivity, SC24-6174")。
从源码看,该能力由IPA_CMD_SETBRIDGEPORT_*命令族承载,见 drivers/s390/net/qeth_core_mpc.h:
IPA_CMD_SETBRIDGEPORT_OSA = 0x2b, /* OSA 硬件 */ IPA_CMD_SETBRIDGEPORT_IQD = 0xbe, /* HiperSockets 硬件 */在 drivers/s390/net/qeth_core_mpc.c 中二者被分别命名为"set_bridge_port(osa)"与"set_bridge_port(hs)";驱动运行时会根据设备类型选择对应命令:
/* drivers/s390/net/qeth_l2_main.c */ enum qeth_ipa_cmds ipa_cmd = IS_IQD(card) ? IPA_CMD_SETBRIDGEPORT_IQD : IPA_CMD_SETBRIDGEPORT_OSA;二、桥接端口状态变化事件(BRIDGEPORT=statechange)
当 qeth 设备运行在OSA 或 HiperSockets Bridge Capable Port硬件上,且通道上任意已配置 Bridge Port 设备的状态发生变化时,驱动会以对应 ccwgroup 设备的名义触发一个ACTION=CHANGE的 udev 事件。事件包含以下属性:
| 属性 | 取值 | 含义 |
|---|---|---|
BRIDGEPORT | statechange | 标识该 Bridge Port 设备发生了状态变更 |
ROLE | primary/secondary/none | 分配给该端口的角色 |
STATE | active/standby/inactive | 端口新进入的状态 |
2.1 触发链路源码印证
该事件的构造与发送位于 drivers/s390/net/qeth_l2_main.c 的qeth_bridge_state_change_worker():驱动收到硬件的 Bridge Port 状态变更异步通知后,取出qeth_sbp_port_data中第一项(本地端口)的role与state字段,通过kobject_uevent_env(&card->gdev->dev.kobj, KOBJ_CHANGE, env)发出内核事件:
scnprintf(env_locrem, sizeof(env_locrem), "BRIDGEPORT=statechange"); scnprintf(env_role, sizeof(env_role), "ROLE=%s", (data->role == QETH_SBP_ROLE_NONE) ? "none" : (data->role == QETH_SBP_ROLE_PRIMARY) ? "primary" : (data->role == QETH_SBP_ROLE_SECONDARY) ? "secondary" : "<INVALID>"); scnprintf(env_state, sizeof(env_state), "STATE=%s", (data->state == QETH_SBP_STATE_INACTIVE) ? "inactive" : (data->state == QETH_SBP_STATE_STANDBY) ? "standby" : (data->state == QETH_SBP_STATE_ACTIVE) ? "active" : "<INVALID>");事件先在硬件中断上下文中由qeth_bridge_state_change()(qeth_l2_main.c)解析、分配工作项,再交由card->event_wq工作队列异步投递,避免在原子上下文中直接触发 udev。工作项还校验num_entries == 0(记录 "BPempty")与entry_length合法性,防止异常报文触发事件。
三、HiperSockets 主机地址通知事件(BRIDGEDHOST)
当 qeth 设备运行在启用了主机地址通知(host address notifications)的 HiperSockets Bridge Capable Port硬件上时,一旦有主机或 VLAN 在设备服务的网络上注册/注销,驱动就会以对应 ccwgroup 设备的名义触发ACTION=CHANGE的 udev 事件。事件属性如下:
| 属性 | 取值 | 含义 |
|---|---|---|
BRIDGEDHOST | reset/register/deregister/abort | 主机地址通知重新开始、新主机/VLAN 注册、注销,或通知被中止 |
VLAN | 数字形式的 VLAN ID | 事件发生的 VLAN;若无 VLAN 参与则不包含该属性 |
MAC | xx:xx:xx:xx:xx:xx | 在 HiperSockets 通道上注册/注销的主机 MAC 地址;若事件仅涉及 VLAN 创建/销毁则不报告 |
NTOK_BUSID | x.y.zzzz | 设备总线 ID(CSSID、SSID 与设备号) |
NTOK_IID | xx | 设备 IID |
NTOK_CHPID | xx | 设备 CHPID |
NTOK_CHID | xxxx | 设备通道 ID |
⚠️ 注意:
NTOK_*属性描述的是网络上其他主机所连接的设备(即远端设备的物理位置信息),而非本机操作系统所连接的那台设备。
3.1 事件属性与变更码的对应关系
属性组合由硬件上报的change_code位掩码决定,其位定义位于 drivers/s390/net/qeth_core_mpc.h:
IPA_ADDR_CHANGE_CODE_VLANID = 0x01, /* 事件涉及 VLAN */ IPA_ADDR_CHANGE_CODE_MACADDR = 0x02, /* 事件涉及 MAC */ IPA_ADDR_CHANGE_CODE_REMOVAL = 0x80, /* 高位置位 = 注销,否则 = 注册 */在 qeth_l2_main.c 的qeth_bridge_emit_host_event()中:
code & IPA_ADDR_CHANGE_CODE_REMOVAL决定BRIDGEDHOST=deregister或register;code & IPA_ADDR_CHANGE_CODE_VLANID决定是否附加VLAN=;code & IPA_ADDR_CHANGE_CODE_MACADDR决定是否附加MAC=;- 只要事件有效,
NTOK_BUSID、NTOK_IID、NTOK_CHPID、NTOK_CHID四个网络令牌(net_if_token)属性总会输出,格式分别为%x.%x.%04x、%02x、%02x、%04x。
anev_abort与anev_reset两种特殊类型只携带BRIDGEDHOST=abort/BRIDGEDHOST=reset,不带 token 与地址信息(对应参数允许为 NULL)。
3.2 reset 与 abort 的触发场景
- reset:启用地址通知时,驱动先发出
BRIDGEDHOST=reset,随后对当前所有已注册地址逐个重放register事件(见qeth_bridgeport_an_set(),qeth_l2_main.c),让用户空间重建完整视图; - abort:当日志溢出(
lost_event_mask)或桥端口状态变更导致通知被硬件中止时,qeth_addr_change_event_worker()会设置hostnotification = 0、清空pnso_mode,并发出BRIDGEDHOST=abort,表示后续事件流中断(qeth_l2_main.c)。
四、从源码看事件分发与溢出恢复
两类事件统一由 IPA 异步命令入口qeth_addr_change_event()接收(qeth_l2_main.c),根据pnso_mode分流:
QETH_PNSO_BRIDGEPORT:走qeth_addr_change_event_worker(),逐条调用qeth_bridge_emit_host_event()发出 udev 事件;- 学习同步(learning_sync)模式:走
qeth_l2_dev2br_worker(),将地址变化同步进上层 Linux bridge 的 FDB。
若硬件报告lost_event_mask非零(事件溢出),驱动不会静默丢弃:它会打印 "Address change notification overflow" 之类告警、尝试重同步,并最终以abort事件告知用户空间。qeth_bridge_emit_host_event()的注释也明确指出:事件可能在通知启用时被批量重放,处理端应具备幂等性。
五、配套的 sysfs 配置接口
除事件消费外,Bridge Port 功能还通过 ccwgroup 设备上的 sysfs 属性进行配置(定义于 drivers/s390/net/qeth_l2_sys.c 的qeth_l2_bridgeport_attr_group):
| 属性 | 权限 | 说明 |
|---|---|---|
bridge_role | 0644 | 读写端口角色:primary/secondary/none,写操作经由qeth_bridgeport_setrole()下发IPA_SBP_SET_PRIMARY_BRIDGE_PORT/IPA_SBP_SET_SECONDARY_BRIDGE_PORT/IPA_SBP_RESET_BRIDGE_PORT_ROLE(qeth_l2_main.c) |
bridge_state | 0444 | 只读,显示端口当前状态(active/standby/inactive) |
bridge_hostnotify | 0644 | 读写,0/1控制 HiperSockets 主机地址通知的启用与关闭 |
bridge_reflect_promisc | 0644 | 读写,none/primary/secondary,配置混杂模式反射 |
配置示例(在设备实际承载系统上):
# 查看/设置端口角色 cat /sys/devices/.../ccwgroup/0.0.8000/bridge_role echo primary > /sys/devices/.../ccwgroup/0.0.8000/bridge_role # 启用 HiperSockets 主机地址通知 echo 1 > /sys/devices/.../ccwgroup/0.0.8000/bridge_hostnotify # 查看端口状态 cat /sys/devices/.../ccwgroup/0.0.8000/bridge_state需要说明的是:当bridge_reflect_promisc处于使能状态时,直接写bridge_role会返回-EPERM(禁止直接操纵);当硬件不可达(offline)时,角色/通知设置仅保存在card->options.sbp中,待设备上线时再应用(见 qeth_l2_sys.c)。若设备不具备 Bridge Port 能力,这些属性统一返回n/a (VNIC characteristics)。
六、编写 udev 规则消费这些事件
事件以ACTION=CHANGE形式挂在 ccwgroup 设备上,典型 udev 规则示例如下:
# 监听桥接端口角色/状态变化 SUBSYSTEM=="ccwgroup", ACTION=="change", ENV{BRIDGEPORT}=="statechange", \ RUN+="/usr/local/bin/bridge-port-watch.sh" # 监听 HiperSockets 主机/VLAN 注册注销 SUBSYSTEM=="ccwgroup", ACTION=="change", ENV{BRIDGEDHOST}=="register|deregister", \ RUN+="/usr/local/bin/host-notify.sh"在脚本中可通过$env{ROLE}、$env{STATE}、$env{BRIDGEDHOST}、$env{VLAN}、$env{MAC}等变量获得具体信息。需要特别注意的是:
MAC与VLAN属性是条件性出现的:VLAN 事件不含 MAC,纯 MAC 事件不含 VLAN,编写匹配规则时应使用可选判断而非硬性假设;NTOK_*指向远端设备,适合用来构建跨主机的物理拓扑感知能力,而非定位本机设备;- 事件可能在通知启用时成批重放(先
reset后逐个register),消费端应设计为"全量重建 + 增量更新"模型,并妥善处理abort之后的状态清理。
七、小结
qeth 驱动的 Bridge Port 支持把 OSA/HiperSockets 硬件底层的桥接状态与地址变化,通过标准 udev 事件机制暴露给用户空间:BRIDGEPORT=statechange描述端口角色与状态迁移,BRIDGEDHOST描述 HiperSockets 网络上的主机/VLAN 注册注销,NTOK_*则提供远端设备的物理定位信息。结合 qeth_l2_main.c 中qeth_bridge_emit_host_event()、qeth_bridgeport_setrole()、qeth_bridgeport_an_set()等实现,运维人员既可以精确监控虚拟网络拓扑变化,也可以据此实现地址簿同步、故障定位与自动化配置等上层应用。
【免费下载链接】linuxLinux kernel source tree项目地址: https://gitcode.com/GitHub_Trending/li/linux
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考