当前位置: 首页 > news >正文

NS3中的路由模型-5 OLSR路由协议

目录

  • 1. OLSR工作原理
    • **1.1. 关键机制**
    • **1.2. 消息类型**
    • **1.3. 工作流程**
      • 1.3.1 路由建立过程
      • 1.3.2 数据包转发过程
    • 1.4. NS3中的关键函数和流程
    • 1.5. 示例:数据包转发的代码路径
  • **2. OLSR 在 NS-3 中的实现**
    • **2.1. 核心类**
    • **2.2. 路由建立过程**
      • **1. 邻居发现(HELLO 消息处理)**
      • **2. MPR 选择(多点中继计算)**
      • **3. 拓扑扩散(TC 消息洪泛)**
      • **4. 路由表计算**
    • **2.3. 数据包转发过程**
      • **1. 数据包进入网络层**
      • **2. 路由查询**
      • **3. 数据包转发**
    • **2.4. 动态维护机制**
      • **1. 链路失效处理**
      • **2. 定时器驱动事件**
    • **2.5. 示例:NS-3 中查看 OLSR 路由表**
      • **四、与其它协议的对比**


NS3中的路由模型-5 OLSR路由协议

1. OLSR工作原理

核心思想:通过选择多点中继(MPR, MultiPoint Relays) 来优化控制消息(尤其是拓扑信息)的传播范围,减少冗余广播。

1.1. 关键机制

  • 邻居发现(Neighbor Detection):

    • 每个节点定期广播 HELLO 消息(小范围广播,TTL=1)。
    • HELLO 消息包含:邻居列表、链路状态(对称/非对称)、MPR 选择器状态等。
    • 用于维护一跳邻居两跳邻居信息。
  • 多点中继(MPR)选择:

    • 每个节点独立选择自己的 MPR 集合。
    • 目标:选出一组最小的一跳邻居,使得通过这些邻居可以覆盖所有两跳邻居。
    • 作用:只有 MPR 节点有权转发 TC(Topology Control)消息,减少洪泛开销。
  • 拓扑扩散(Topology Dissemination):

    • MPR 节点定期广播 TC 消息(Topology Control)。
    • TC 消息包含:该 MPR 的邻居信息(即 MPR Selector 列表)。
    • 非 MPR 节点不转发 TC 消息,极大减少控制开销。
  • 路由表计算:

    • 节点利用收集到的 TC 消息构建全网拓扑图。
    • 使用 Dijkstra 算法计算到所有节点的最短路径。
    • 路由表包含:目的地址、下一跳地址、跳数等。

1.2. 消息类型

消息类型作用发送范围
HELLO邻居发现与维护一跳 (TTL=1)
TC扩散拓扑信息全网 (由 MPR 转发)
MID多接口声明(可选)全网
HNA主机与网络关联(连接外部网络)全网

1.3. 工作流程

节点启动
广播HELLO消息
收集邻居信息
选择MPR集合
广播TC消息
收集全网拓扑
计算路由表
转发数据包

NS3中OLSR的具体实现细节,包括路由建立(邻居发现、MPR选择、拓扑扩散和路由计算)以及数据包如何根据路由表进行转发。

1.3.1 路由建立过程

在NS3中,OLSR的路由建立过程遵循RFC 3626,并通过几个周期性的事件来驱动:

  1. Hello消息的发送与邻居发现
    • 每个节点会周期性地(默认2秒)广播Hello消息(通过SendHello()函数实现)。Hello消息只在一跳范围内传播(TTL=1)。
    • Hello消息包含以下信息:
      • 邻居接口地址列表(包括链路类型:对称链路、非对称链路或丢失链路)
      • 该节点选择的MPR集合(MPR Set)
      • MPR选择器集合(即哪些邻居选择本节点作为MPR)
    • 当节点收到邻居的Hello消息,它会更新邻居表(Neighbor Set)和两跳邻居表(Two-hop Neighbor Set)。这些表存储在OlsrState对象中。
  2. MPR选择
    • 在收到Hello消息后(或者当邻居信息发生变化时),节点会触发MPR计算(MprComputation()函数)。
    • MPR选择的目标是选择最小数量的一跳邻居,使得这些邻居可以覆盖所有的两跳邻居(即每个两跳邻居至少有一个一跳邻居是所选MPR)。
    • 在NS3中,MPR选择算法在RoutingProtocol::MprComputation()中实现,它使用贪心算法来求解。
  3. TC消息的发送与拓扑扩散
    • 被选为MPR的节点会周期性地(默认5秒)广播TC消息(通过SendTc()函数)。
    • TC消息包含该节点的MPR选择器集合(即哪些邻居选择本节点作为MPR)。这样,其他节点就可以通过这些信息构建全网拓扑。
    • TC消息会被MPR节点转发(但每个节点只转发一次),从而在整个网络内扩散。在NS3中,TC消息的转发通过RoutingProtocol::ForwardDefault()处理。
  4. 路由表计算
    • 节点在以下情况下会触发路由表计算(RoutingProtocol::RoutingTableComputation()):
      • 收到TC消息(拓扑信息更新)
      • 邻居表发生变化(如链路断开)
      • 路由表过期(默认周期为5秒)
    • 路由计算使用Dijkstra算法,基于收集到的拓扑信息(存储在拓扑表中)计算到所有节点的最短路径。
    • 计算出的路由存储在节点的路由表中(m_table)。

1.3.2 数据包转发过程

一旦路由表建立,数据包的转发过程如下:

  1. 数据包到达网络层
    • 当节点需要发送数据包时,它会查询路由表(通过RouteOutput()函数)。
    • 对于转发的数据包(即目的地址不是本节点),节点会调用RouteInput()函数来决定如何处理。
  2. 路由查询
    • RouteInput()中,节点首先检查数据包的目的地址是否为本节点或广播地址。如果不是,则查询路由表(Lookup()函数)以确定下一跳。
    • 路由表查询返回一个Ipv4Route对象,其中包含下一跳地址和输出接口。
  3. 数据包转发
    • 如果找到有效路由,节点会将数据包发送到下一跳节点(通过SendPacket()函数)。
    • 如果没有找到路由,数据包会被丢弃,并可能触发ICMP目的不可达消息。
  4. 路由维护
    • OLSR会持续维护路由信息。当链路断开时(通过Hello消息检测到邻居丢失),节点会更新邻居表,重新计算MPR,并触发新的TC消息广播,从而更新全网路由。

1.4. NS3中的关键函数和流程

  • 周期性事件
    • HelloTimerExpire():触发Hello消息的发送。
    • TcTimerExpire():触发TC消息的发送(如果是MPR)。
    • MidTimerExpire():处理多接口声明(可选)。
    • HnaTimerExpire():处理主机和网络关联(连接外部网络)。
    • RoutingTableCalculationTimerExpire():周期性触发路由表计算。
  • 消息处理函数
    • RecvOlsr():接收OLSR消息的总入口,根据消息类型分发给ProcessHello()ProcessTc()等函数。
    • ProcessHello():处理收到的Hello消息,更新邻居信息。
    • ProcessTc():处理收到的TC消息,更新拓扑表。
  • 路由计算
    • RoutingTableComputation():执行Dijkstra算法,计算最短路径。

1.5. 示例:数据包转发的代码路径

假设节点A要发送一个数据包给节点D:

  1. 节点A的应用层产生数据包,传递给网络层。
  2. 网络层调用Ipv4L3Protocol::Send(),进而调用路由协议的RouteOutput()
  3. OlsrRoutingProtocol::RouteOutput()查询路由表(m_table),找到到D的下一跳(比如节点B)。
  4. 节点A将数据包封装成IP包,目的IP为D,下一跳MAC地址为节点B的MAC地址。
  5. 节点B收到数据包后,同样调用RouteInput(),查询路由表,找到下一跳(比如节点C)。
  6. 如此继续,直到数据包到达节点D。

2. OLSR 在 NS-3 中的实现

NS-3 通过 olsr 模块实现了完整的 OLSR 协议(RFC 3626),位于 src/olsr 目录。

2.1. 核心类

类名功能
ns3::OlsrHelper集成 OLSR 到仿真环境的辅助类
ns3::OlsrRoutingOLSR 主逻辑实现(路由表计算、消息处理)
ns3::OlsrState维护 OLSR 状态(邻居表、拓扑表等)
ns3::OlsrPacketHeaderOLSR 消息包头定义

2.2. 路由建立过程

路由建立通过周期性消息交换完成,分为四个关键阶段:

1. 邻居发现(HELLO 消息处理)

源码函数: ProcessHello()
工作流程:

NodeANodeB广播 HELLO (TTL=1)解析 HELLO更新邻居表m_neighborSet更新两跳邻居表m_twoHopNeighborSet触发 MPR 计算NodeANodeB

NS-3 实现细节:

  • HELLO 消息包含邻居地址和链路状态 (LinkType):
    // 消息结构 (olsr-packet-header.cc)
    struct HelloMessage {uint8_t linkCode;    // 链路类型: ASYMMETRIC/SYMMETRIC/MPR_LINKIpv4Address neighbor;
    };
    
  • 邻居表更新逻辑:
    // olsr-routing-protocol.cc
    void RoutingProtocol::ProcessHello(...) {if (linkType == SYMMETRIC) { m_neighborSet.insert(neighborAddr); // 添加对称邻居} else if (linkType == LOST_LINK) {m_neighborSet.erase(neighborAddr);  // 删除失效邻居}
    }
    

2. MPR 选择(多点中继计算)

源码函数: MprComputation()
算法逻辑:

graph TDA[获取两跳邻居集合] --> B[筛选未覆盖的邻居]B --> C{是否有未覆盖邻居?}C -->|是| D[选择覆盖最多邻居的一跳节点]D --> E[标记为 MPR]E --> BC -->|否| F[结束]

NS-3 实现:

  • 使用贪心算法选择最小 MPR 集合:
    void RoutingProtocol::MprComputation() {while (!twoHopNeighbors.empty()) {// 选择覆盖最多两跳邻居的一跳节点auto bestNeighbor = SelectMaxCoverageNode();m_mprSet.insert(bestNeighbor); RemoveCoveredNeighbors(bestNeighbor);}
    }
    

3. 拓扑扩散(TC 消息洪泛)

源码函数: SendTc(), ProcessTc()
关键流程:

广播TC
是MPR?
非MPR
MPR节点
邻居节点
转发TC
丢弃
下一跳

NS-3 特性:

  • TC 消息包含 MPR Selector 列表:
    struct TcMessage {uint16_t ansn;           // 序列号std::vector<Ipv4Address> mprSelectors; // 选择本节点的MPR列表
    };
    
  • 转发规则 (olsr-routing-protocol.cc):
    bool RoutingProtocol::ForwardDefault(Ptr<Packet> p) {if (!IsMpr(originator)) return false; // 非MPR不转发if (m_dupSet.find(p->GetUid()) != m_dupSet.end()) return false; // 重复检测SendPacket(p); // 广播转发
    }
    

4. 路由表计算

源码函数: RoutingTableComputation()
算法:

  • 基于 Dijkstra 最短路径算法
  • 输入:拓扑表 (m_topologySet)
  • 输出:路由表 (m_table)

NS-3 实现:

void RoutingProtocol::RoutingTableComputation() {// 1. 初始化距离向量std::map<Ipv4Address, uint32_t> dist;for (auto& node : allNodes) dist[node] = INFINITY;// 2. Dijkstra 核心while (!unvisited.empty()) {Ipv4Address u = ExtractMin(unvisited);for (auto& v : GetNeighbors(u)) {uint32_t alt = dist[u] + 1; // OLSR 跳数=1if (alt < dist[v]) {dist[v] = alt;m_table[v] = u; // 记录下一跳}}}
}

2.3. 数据包转发过程

当路由表建立后,数据包转发流程如下:

1. 数据包进入网络层

源码入口: Ipv4L3Protocol::Receive()RouteInput()

NetDeviceIpv4LayerOlsrRouting接收数据包RouteInput(packet)NetDeviceIpv4LayerOlsrRouting

2. 路由查询

源码函数: RouteOutput()
逻辑:

// olsr-routing-protocol.cc
Ptr<Ipv4Route> RoutingProtocol::RouteOutput(...) {auto it = m_table.find(dest);if (it != m_table.end()) {// 找到路由:构建 Ipv4Route 对象rt->SetDestination(dest);rt->SetGateway(it->second); // 下一跳地址rt->SetOutputInterface(interface);return rt;}return nullptr; // 无路由则丢弃
}

3. 数据包转发

转发路径:

flowchart LRA[源节点] -->|查询路由表| B{路由存在?}B -->|是| C[发送到下一跳]B -->|否| D[丢弃并发送ICMP错误]C --> E[下一跳节点]E --> F[重复路由查询]F --> G[目标节点]

关键约束:

  • TTL 递减: 每跳 TTL 减 1,为 0 时丢弃
  • 链路层广播: 无线网络中使用 MAC 广播地址 FF:FF:FF:FF:FF:FF
  • MPR 无关性: 数据转发不依赖 MPR,仅使用路由表

2.4. 动态维护机制

OLSR 在 NS-3 中持续维护路由状态:

1. 链路失效处理

  • 检测机制: 3 次未收到 HELLO 则判定邻居失效
  • 响应动作:
    void RoutingProtocol::NeighborLoss(Ipv4Address neighbor) {m_neighborSet.erase(neighbor);RecomputeMpr();        // 重新计算MPRRebuildRoutingTable(); // 重建路由表
    }
    

2. 定时器驱动事件

定时器类型默认间隔触发动作
HelloTimer2s广播 HELLO
TcTimer5sMPR 节点广播 TC
RoutingTimer5s重新计算路由表
NeighborTimer6s检查邻居超时

2.5. 示例:NS-3 中查看 OLSR 路由表

在仿真脚本中添加以下代码打印路由表:

// 仿真结束后打印节点0的路由表
Ptr<OutputStreamWrapper> stream = Create<OutputStreamWrapper>("olsr_routes.txt", std::ios::out);
olsrProto->PrintRoutingTable(stream);

输出示例:

节点 0 路由表:
目的网络      下一跳        接口    跳数
10.1.1.3     10.1.1.3      1       1
10.1.1.12    10.1.1.4      1       2
10.1.1.25    10.1.1.7      1       3
...

四、与其它协议的对比

特性OLSRAODVDSDV
路由类型主动式按需式主动式
控制开销中等(周期TC)低(按需)高(全洪泛)
时延低(路由已存)较高(需发现)
适用场景中型稳定网络动态小型网络小型静态网络

http://www.dtcms.com/a/325182.html

相关文章:

  • 疏老师-python训练营-Day42Grad-CAM与Hook函数
  • MySQL 基础操作教程
  • 学习嵌入式第二十五天
  • 机器学习——K-means聚类
  • 个人效能是一个系统
  • 【YOLO11改进 - C3k2融合】C3k2融合EBlock(Encoder Block):低光增强编码器块,利用傅里叶信息增强图像的低光条件
  • 学习嵌入式的第十六天——C语言——位运算
  • tlias智能学习辅助系统--原理篇-SpringBoot原理-自动配置-自定义starter
  • 【走进Docker的世界】深入理解Docker网络:从模式选择到实战配置
  • #Datawhale AI夏令营#第三期全球AI攻防挑战赛(AIGC技术-图像方向)
  • [Shell编程] Shell的正则表达式
  • P3232 [HNOI2013] 游走,solution
  • Python 程序设计讲义(68):Python 的文件操作——使用os模块操作文件
  • 整数规划-分支定界
  • Win10清理C盘步骤
  • 展锐平台(Android15)WLAN热点名称修改不生效问题分析
  • 最大子数组和-一维动态规划
  • C++ 黑马 引用
  • 一款轻量、免费、无广告,强大的演示工具,支持屏幕放大、涂鸦、截图、录屏
  • PostgreSQL因为A/B switch以及group表过多导致WAL full的情况讨论
  • 托福单词词组积累 2025-08-10
  • 大模型 MCP服务案例详细讲解
  • 线程池的核心线程数与最大线程数怎么设置
  • NVIDIA Jetson AGX Orin 全景解析——边缘计算的高性能选择
  • 攻击实验(ARP欺骗、MAC洪范、TCP SYN Flood攻击、DNS欺骗、DHCP饿死)
  • VGG改进(1):基于Global Attention模块的详解与实战
  • RL代码实践 02——策略迭代
  • ai生成完成后语音通知
  • Starlink卫星终端对星策略是终端自主执行的还是网管中心调度的?
  • 如何部署图床系统 完整教程