Infiniband子网管理

882 阅读17分钟

一、Infiniband子网管理

  • 子网管理基础
  • 子网探测
  • LID分配
  • 路由计算

二、Infiniband子网管理器OpenSM分析

  • OpenSM总体介绍
  • OpenSM数据模型
  • OpenSM运行模型
  • 拓扑探测实现分析
  • LID分配实现分析
  • 路由计算实现分析

子网管理基础-子网管理模型

  • 物理模型(physical model)
    • 子网管理器SM可以存在于任何一个CA、交换机或路由器的任何一个端口, 一个子网中可以存在多个 SM, 但在子网运行时只能有一个主SM, 其它的成为备份SM。
    • 子网管理代理SMA存在于每一个CA、交换机或路由器中。
  • 逻辑模型(logical model)
    • 子网管理的实质是子网管理器和子网管理代理之间的信息交换。信息交换通过子网管理数据包完成。
    • 子网管理器通过查询子网管理代理, 得到节点的部分信息。子网管理器综合所有从子网管理代理获得的信息后, 可以生成每个节点的部分信息。子网管理代理也可以直接发送信息给子网管理器。
    • 子网管理数据包是信息交换的标准数据格式, 还包括一套标准操作。

子网管理基础-子网管理数据包

  • 子网管理数据包SMP为子网管理提供基础通信机制。为子网管理提供子网配置、检测和查询子网节点信息的功能。有两类SMP: LID路由SMP和直接路由SMP。
    • LID路由SMP: 交换机在转发这些SMP是根据其目的LID确定要转发的端口。使用LID路由SMP需要节点已经分配LID, 经过的交换机必须已经配置正确的转发表。

    • 直接路由SMP: 交换机转发这些SMP时根据SMP自带的路径字段确定要转发的端口。

    • LID路由SMP: 用于子网初始化以后 字段名 长度 描述 通用MAD报头 24字节 通用MAD报头, 具体见13章 M_key 8字节 一个用于SM认证的64位密钥 保留 32字节 用于和直接路由SMP的SMP数据字段对齐 SMP数据 64字节 用于容纳方法的属性 保留 128字节 保留

    • 直接路由SMP: 主要用于子网在初始化以前, 发现子网拓扑结构

    • 直接路由可以包含LID路由段,

    • 直接路由在路由的每一个中间节点都要经过子网管理接口SMI的处理, LID路由在路由的中间过程不需要经过SMI

    • 直接路由SMP有关的算法

      • 发起的直接路由SMP初始化
      • SMI处理发起的直接路由SMP, 需要填写返回路径字段
      • 响应直接路由SMP的初始化
      • SMI处理响应直接路由SMP

子网管理基础-子网管理代理

  • 如果将每个节点(CA, 交换机或路由器)看成是一个对象: 子网管理代理SMA可以理解成节点对象的公共接口。SM通过这个接口可以设置(Set方法)或查询(Get方法)节点对象的属性(节点的信息)。

  • SMA还可以主动向SM报告节点上的异常事件。

  • 主要操作

    • SubnGet():
      • 由SM发起, 用于获取节点属性
    • SubnSet():
      • 由SM发起, 用于设置节点属性
    • SubnGetResp():
      • SMA对SM的响应
    • SubnTrap():
      • SMA主动向SM报告异常事件
    • SubnTrapRepress():
      • SM对SMA报告异常事件的响应
  • 主要属性

    • 节点信息,
    • 交换机信息,
    • GUID信息,
    • 端口信息,
    • SM信息,
    • 密钥信息
    • SL到VL的映射表,
    • VL仲裁表,
    • 线性转发表,
    • 随机转发表,
    • 组播转发表
    • 事件类型,
    • 节点描述,
    • 厂家信息

子网管理基础-子网管理器

  • 相对于以太网的分布式管理, 在Infiniband网络中, SM通过SMA对子网进行集中管理。
  • 这种方式结构简单易于管理。
  • 为了防止单点失效问题, 在Infiniband中可存在多个SM, 一个主SM, 多个备份SM。备份SM检测到主SM死亡时, 会选择一个备份SM成为主SM, 接管子网管理权。
  • SM状态机
  • 主SM是IB子网初始化和配置的关键因素。主SM的选择也是初始化过程的一部分。主SM的主要作用是:
    • 发现子网的物理拓扑结构。
    • 为每个端节点, 交换机和路由器分配本地标识符LID。
    • 确定各端节点之间的合理路径。
    • 扫描子网, 发现拓扑改变处理节点加入和节点删除。

子网探测

  • 子网探测主要是指在Infiniband子网初始化时, SM通过SMA获得子网内各节点信息。主要的信息就是各个节点的GUID, 节点类型, 端口信息以及各节点之间的连接关系。
  • 在子网初始化完毕后, SM还会定时的检查网络拓扑是否发生变化(某个交换机端口的状态发生改变)。
  • 交换机检测到自己的某个端口状态发生改变, 可以通过Trap机制主动向SM报告拓扑改变。

子网探测 - 子网发现

  • 子网发现的过程: 子网启动时, SM发送包含Get方法的直接路由SMP, SMA收到后会响应一个SMP, 从而找到一个新的节点, 然后SM通过这个新节点向外辐射只到找到所有的设备。

子网探测 - 增加设备

  • 对于一个已经初始化的子网, 如果SM发现某一个交换机的一个端口的状态从DOWN变为UP, 则说明有设备加入到子网中。

子网探测 - 删除设备

  • 对于一个已经初始化的子网, 如果SM发现某一个交换机的一个端口的状态从UP 变为DOWN , 则说明有设备从子网中移除。

LID性质

  • LID(16位)由SM分配, 在子网内唯一, 不能在子网间使用
  • LID地址空间分为保留空间, 单播地址空间, 组播地址空间
  • LID在LRH(本地路由报头)中使用
  • 由于子网中两个节点中存在多条路径, 可以通过在目的节点上绑定多个LID实现, 每条路径使用一个 LID。为了简化实现方式, LID的分配采用base lid+LMC的方式, base lid最后LMC位必须为0 例: base lid=4, LMC=2, 则分配的LID[4,7]

LID分配

  • 在规范中, 并没有规定LID的分配规则, 只要满足上述的性质即可。具体实现时, LID的分配与特定的路由算法有关。
  • 最简单的分配方式是按照设备的发现顺序, 从1开始连续分配。

路由计算

  • 路由计算主要是指SM在得到子网拓扑以后, 确定每两个节点之间的路径的过程。SM将这个计算结果以转发表的形式发布给交换机, 使数据包沿着计算好的路径传递。
  • 转发表是一个[LID,PORT]组成的表, 交换机接收到一个LID路由的数据包时, 通过查找目的LID对应的表项, 从而确定应该从那个端口转发这个数据包。

OpenSM总体介绍

  • OpenSM支持的功能特点
  • 开放源代码
  • 代码使用C语言编写, 面向对象的思想且具有可扩展性
  • 程序内含由Robodoc编写的说明文档
  • 可方便用于其他平台和InfiniBand接口, 当前运行在linux用户空间之上
  • 支持SM的主要特性, 包括多路径传输、子网分区、多点传送组和SM选举机制等
  • 在任何拓扑结构中, 保证两个端节点间的最佳路径
  • 支持通用的子网查询
  • 方便传送各个层的各种类型的管理数据报MAD
  • OpenSM不支持的功能特点
  • 不支持交换机的随机路由转发表
  • 不支持子网间的路由
  • 不支持完整的SA询问机制
  • 不支持虚拟通道机制
  • 不支持GUI

OpenSM数据模型 - 对象模型

  • OpenSM采用面向对象的思想, 将Infiniband网络中的现实事物抽象成程序中的一系列类(结构), 例如节点, 交换机, 端口, SM, 分区等。
  • 这些现实事物之间的关联在通过类与类之间的关系反映出来。例如, 在一个节点对象中包含若干个端口对象, 每个端口对象又指向另一个端口对象, 另一个端口对象可能是属于某各交换机对象的。

OpenSM数据模型 - subnet类

  • Subnet类是OpenSM中保存子网信息的一个类, 最重要的就是子网的拓扑信息。在Subnet类中保存了子网中所有CA, 交换机, 路由器的信息, 以及这些节点的端口的连接信息(拓扑)。
  • 子网的初始化和运行一个重要部分就是构造和维护 Subnet类: 子网启动以后, SM每发现一个设备, 就构造一个对应的类, 并将这个类加入到Subnet类中;子网运行过程中, SM也会根据子网的变化同步Subnet类, 使得Subnet类中的拓扑和实际拓扑保持一致。
  • 子网的配置也是根据Subnet类中保存的信息综合以后进行的, 例如每个交换机的转发表就是根据Subnet中的拓扑信息生成的。

OpenSM运行模型

程序基本流程

  • 从外界获取程序运行所需的配置参数
  • 创建各种数据结构, 如日志对象, Opensm对象, sm对象, 子网对象, 以及用于保存程序运行信息的图表, 如节点表, 交换机表等。
  • 初始化各对象, 如根据参数设置对象属性, 初始化相关的定时器, 线程, 信号等。
  • 创建发送线程, 接收线程, 扫描线程, 分配器工作线程等。
  • 循环等待, 直到程序遇到结束标志。

子网配置过程

  • 发现子网
  • 分配LID
  • 构造每个交换机的LID矩阵
  • 构造每个交换机的转发表
  • 将转发表分发到对应的交换机
  • 将端口置为准备状态
  • 将端口置为活动状态

发现子网 - 子网启动

  • 发送一个直接路径长度为0的SMP, 获取本地的节点信息。
  • 发送直接路径长度为1的SMP, 如果SM所在节点为 CA或路由器, 则只需要发送一个, 如果节点为交换机, 则需要构造多个SMP, 每个SMP的直接路径为交换机的一个活动端口。
  • 当收到响应时, 判断响应节点是否是新设备, 如果是新设备, 则继续向外探测, 直到没有新的设备发现为止(子网发现完成)。

子网探测- 子网启动后

  • 向每个交换机发送包含Get函数的SMP, 更新每个交换机的信息。
  • 对于每个交换机的每个端口: 如果端口的状态不是 down, 但是这个端口不指向一个端口, 说明子网中新加入了设备, 构造一个直接路由SMP(包含一段LID路由)获取这个端口连接的节点信息。
  • 如果发现有交换机的端口状态发生改变(拓扑改变), 程序会重新扫描整个网络。
  • 扫描完成后, 还会删除一些丢失的节点。

LID分配

  • 所有已分配的LID保存在PORT_LID_TBL表中, 端口的GUID和LID的映射表保存在 GUID_TO_LID_TBL表中。
  • 若端口的GUID在GUID_TO_LID_TBL表中已经存在, 则表明已经分配过LID, 不需要再分配LID。
  • 在PORT_LID_TBL中寻找一个足够大小的区间(如果LMC>0,每一个端口需要分配多于一个 LID), 分配这一段LID, 更新PORT_LID_TBL和 GUID_TO_LID_TBL, 然后设置端口的 PORTINFO中的LID字段。

OpenSM支持的路由算法

  • Minhop最小跳数算法(默认路由算法)
  • Updn Up/down 算法
  • Ftree胖树算法
  • Lash算法
  • 从文件中加载路由表
  • Dor算法

LID矩阵&路由算法

  • 每个交换机对象中都存有一个LID MATRIX 对象, LID MATRIX中保存交换机从它的某个端口到达某个LID的最小距离
  • LID MATRIX中只表示交换机和交换机之间的连接, 先忽略CA和路由器。
  • 在OpenSM中LID MATRIX使用一个二维的hops[][]矩阵表示
  • 路由算法分两步执行:
    • 构造LID矩阵 build_lid_matrices
    • 构造转发表 ucast_build_fwd_tables

LID矩阵的构造(以minhop为例)

  • LID矩阵的内容在最初都是NO_PATH, 即通过交换机的任何一个端口不能到达任何一个LID

  • 交换机到达自身的端口0(管理端口)的LID的距离是0, 交换机到达和自己相连的交换机的端口0的 LID的距离是1.

  • 交换机通过邻居交换机学习到更远的邻居的信息

  • 类似于路由协议中的距离矢量算法, LID矩阵的构造需要经过若干次迭代才能达到稳定状态(收敛)。

  • Sw1的LID矩阵中保存的通过端口1到sw3的距离是10跳

  • 然后sw1通过邻居sw2, 知道sw2到达sw3最少可以只要5跳

  • 因此sw1实际上之需要6跳就可以到达sw3

  • 此时sw1会更新它的LID矩阵

实际例子

  • 每个物理端口都有一个LID
  • 每个交换机也有一个LID
  • 每个交换机的LID矩阵中的LID只有3个交换机的LID
  • 例如交换机2的LID矩阵:
    • 经端口1不能到达任何交换机
    • 经端口2到达LID_SW1的距离是1, 到达自身的距离是0, 不能到达交换机3
    • 经端口3到达LID_SW3的距离是1, 到达自身的距离是0, 不能到达交换机1

转发表的构造

  • 物理端口数总共有10个, 每个端口对应一个LID
  • 每个交换机的转发表中都要给出如何转发这10个LID
    • 例如, 交换机2如何转发CA3的端口1对应的LID
      • CA3不是交换机, 所以其 LID不在LID矩阵中, 而CA3连接的交换机是交换机3, 交换机3的LID是LID_SW3(不是交换机某个端口的LID)
      • 在交换机的LID矩阵中可以知道到达交换机3最近的端口是端口3

设置交换机的转发表

  • 得到从SM到交换机的直接路径
  • 上一步得到的是交换机的整个转发表, 每次set方法只能传输64字节, 需要多次set
  • 交换机内部的转发表按照64字节的大小分块, 因此实际上每次set方法都是设置交换机转发表的一个块

胖树结构

  • 胖树结构是互连已知硬件数量的一种通用方法。
  • 胖树相对传统树, 越靠近根部带宽越大。如果要使网络是非阻塞的, 每层的总带宽都要相同。
  • 在OpenSM中, 任何路由算法都由两步完成, 建立LID矩阵和构造转发表。
  • 在Ftree算法中:
    • LID矩阵的建立过程实际上就是胖树的构造过程。
    • 构造转发表过程是根据已经构造好的胖树结构生成各个交换机的转发表, 然后设置各个交换机的转发表属性。

胖树的构造

  • 1.初始化数据结构(初始化胖树网络结构)
  • 2.向胖树中加入交换机和CA
  • 3.读取GUID文件
  • 4.开始将胖树中的交换机进行排名
  • 5.向胖树中加入端口
  • 6.建立交换机索引表
  • 7.建立叶交换机数组(按索引)

OpenSM: 胖树网络结构

  • 主要属性:
    • HCA表
    • 交换机表
    • 计算节点CN的GUID表
    • 叶交换机等级
    • 每个叶交换机最多连接的计算节点数目

加入交换机和CA

  • 对于Node_GUID表中的任何一个元素:
  • 如果Node的类型为CA, 则将这个节点加入到CA表中
  • 如果类型是交换机, 则将这个节点加入到SW表中

交换机排名 - 从HCA开始排名

  • 对于HCA表中的每个CA:
    • 如果与这个CA相连的是一个交换机(叶交换机), 则更新这个交换机的rank值为0, 并将这个交换机加入到广度优先的队列中(供以后为其它交换机排名时使用)。
  • 再从广度优先队列中的交换机开始继续排名:
    • 采用广度优先算法遍历胖树, 不断将没有排名的交换机加入到广度优先队列中;rank值按层次递增
    • 遍历完成后, 得到最大的rank值
  • 最后修正rank值: 0->max_rank, max_rank->0

加入端口

  • HCA维护到每个相连交换机LID的up_port_group(连接几个交换机, 就有几个up_port_group), HCA上连接到同一个交换机的多个端口在同一个 up_port_group中。
  • 对于每个HCA:
    • 对于每个物理端口:
    • 如果这个端口连接的是一个交换机节点: 将这个端口加入到HCA的某个端口组中。
  • 每个交换机维护到每个相连的上层节点的 up_port_group,每个相连的下层节点的 down_port_group, 每个端口加入到相应的端口组中
  • 对于每个交换机:
    • 对于每个物理端口:
      • 如果这个端口连接的是一个HCA:
        • 则这个端口加入到某个down_port_group中
      • 如果这个端口连接的是一个交换机:
        • 如果本地交换机的rank值较大(下层连上层), 则这个端口加入到某个up_port_group中
        • 反之(上层连下层)。

建立交换机索引表

  • 在交换机表中找到第一个叶交换机, 作为算法的起点, 给这个交换机初始化一个元组。
  • 使用广度优先算法遍历胖树
  • 对于每一个交换机:
    • 指向下层的端口: 如果端口连接的是一个没有分配元组的交换机, 则给这个交换机分配一个元组, 然后根据这个元组生成一个索引值, 再将交换机加入索引表中。
    • 将交换机的down_port_group按照连接的交换机的索引排序。
    • 指向上层的端口: 类似。
    • 在这个过程中不断的发现新的交换机, 将这些交换机加入到广度优先队列中。

构造转发表

  • 计算到计算节点CN的路由
    • 对于每个叶交换机(按索引排序):
      • 对于每个叶交换机所连接的HCA:
      • 得到HCA的LID, 设置交换机到这个LID的转发表缓存, 更新交换机的LID矩阵
      • Assign downgoing ports by stepping up.
    • 通过逐层向上分配下行端口
  • 计算交换机到交换机的路由
    • 对交换机表中的每个交换机:
      • 设置交换机到自身LID的转发表缓存, 更新交换机的LID矩阵
      • Assign downgoing ports by stepping up.
      • 通过逐层向上分配下行端口
  • 设置每个交换机的转发表

路径选择问题

  • Opensm的胖树算法不支持LMC>0, 因此使用胖树算法后子网中不支持多路径特性。
  • 在上图中, 路径的选择(红色线表示)可能会有多种, 即可以从多个端口转发。在opensm胖树算法中的端口的选择是先在多个候选的port_group中选择一个负载最小的组, 然后在这个组中选择负载最小的端口。
  • 负载是根据一个端口被选择的次数衡量。被选择的次数越多, 表明有更多的数据包可能会通过这个端口, 负载越大, 但是这种方法并不一定能反映真实的负载情况。