[ZZ]NS代码架构分析

NS代码分析 1.       NS的整体的实现固定网络的仿真是通过下面三层合作来实现的。Application这个层是实现数据流的层次。Agent这个层是实现所有各层协议的的层次。Node这个部分由多个分类器(Classifier)实现了所有接收数据包进行判断是否进行转发或接收到Agent的部分。Link实现了队列、时延、Agent、记录Trace等一系列的仿真问题。2.      阅读详情

 

原文链接:http://naonaoruby.bokee.com/viewdiary.11857286.html

1.       NS的整体的实现
固定网络的仿真是通过下面三层合作来实现的。

Application
Agent 

Node

Link

 

Application这个层是实现数据流的层次。Agent这个层是实现所有各层协议的的层次。Node这个部分由多个分类器(Classifier)实现了所有接收数据包进行判断是否进行转发或接收到Agent的部分。Link实现了队列、时延、Agent、记录Trace等一系列的仿真问题。

 

2.      NS内部类的继承关系

TclObject

Handler

ParentNode

Process

NsObject

Node

Application

Connector

Classifier

Delay

Queue

Agent

Trace

AddressClassifier

 

此图为NS内部类的继承关系,可以看出一些类是由那些类继承来的,这样相同的属性调用的函数就可以很方便的找到出处。

3.       NS中函数调用的分层

在用gdb跟踪NS发送一个cbr数据包的过程可以看到一下顺序:

CBR_Traffic::start

TrafficGenerator::timeout

Application::send

UdpAgent::sendmsg

Classifier::recv

Connect::recv

Connect::send

Trace::recv       写一条数据包加入队列的记录

Connector::send

Queue::recv

DropTail::enque

DequeTrace::recv     写一条数据包弹出队列的记录

Connector::send

LinkDelay::recv      插入事件到scheduler

Scheduler::dispatch   

Scheduler::run

从上面的顺序可以看出,数据包在发送以后先通过应用层(Application::send)进行发送;然后通过Agent层(UdpAgent::sendmsg),UdpAgent是在初始化Agent的时候确定的。UdpAgent还有一个作用是生成相应的数据包;然后进入Node部分的分类器Classifier(Classifier::recv),通过find()函数返回下一跳地址。这个函数是通过读取Packet的内容得到下一跳地址的,返回给recv函数后调用node->recv()进入connector;经过connector::recv和connector::send后确定数据包可发,进入Trace::recv,记录这个数据包加入队列的记录;之后通过connector::send,进入Queue::recv函数,将数据包正式加入发送队列,再根据已经设定好的方法确定加入队列是否成功,是否要被丢弃;再调用DequeTrace::recv记录数据包弹出队列的记录;再通过connector::send进入LinkDelay::recv,先判断目的节点是否可达,根据不同的结果将事件写入scheduler,等待按序执行。

上述的过程只是一个数据包从生成到发送出去的过程,因为NS是一个根据一个一个离散事件调度执行的,后面的过程用gdb跟不进去。但可以看出,数据包是发送给下一跳节点,可知数据包是通过每个中间节点的。

4.       NS中主要函数的分析

4.1.     CBR数据源

开始从下面函数进入CBR数据源发送:

void CBR_Traffic::start()

{

        init();   //初始化

        running_ = 1;

        timeout();  //进入发送数据的循环

}

void TrafficGenerator::timeout()

{

        if (! running_)   //判断是否要发送数据

             return;

 

      /* send a packet */

      send(size_);    //发送一个设定好大小的数据包

      /* figure out when to send the next one */

      nextPkttime_ = next_interval(size_);  

      /* schedule it */

      if (nextPkttime_ > 0)

             timer_.resched(nextPkttime_);

      else

             running_ = 0;

}

4.2.     中间几个函数只是体现分层

void Application::send(int nbytes)

{

      agent_->sendmsg(nbytes);

}

void Agent::sendmsg(int /*sz*/, AppData* /*data*/, const char* /*flags*/)

{

      fprintf(stderr,

      "Agent::sendmsg(int, AppData*, const char*) not implemented/n");

      abort();

}

上述两个函数其实并没有什么实质的操作,只是这样可以看出其经过了应用层和Agent层。

4.3.     Classifier的函数

void Classifier::recv(Packet* p, Handler*h)

{

      NsObject* node = find(p);  //查找目的节点

      if (node == NULL) {  //只要返回了目的节点就调用节点的recv函数

             /*

              * 这个将被丢弃,不用记录在trace文件中

              */

             Packet::free(p);

             return;

      }

      node->recv(p,h); 

}

NsObject* Classifier::find(Packet* p)

{

      NsObject* node = NULL;

      int cl = classify(p);  //根据发送的packet的记录找到slot

      if (cl < 0 || cl >= nslot_ || (node = slot_[cl]) == 0) { //根据slot得到下一跳node

             if (default_target_)

                    return default_target_;

             /*

              * 不能将数据包发送出去,因为返回结果不是一个对象.

              */

             Tcl::instance().evalf("%s no-slot %ld", name(), cl);

             if (cl == TWICE) {

                    /*

                     * Try again.  Maybe callback patched up the table.

                     */

                    cl = classify(p);

                    if (cl < 0 || cl >= nslot_ || (node = slot_[cl]) == 0)

                           return (NULL);

             }

      }

      return (node); //返回给classifier::recv得到的node的值

}

这个地址分类器就是根据数据包的内容,通过偏移查找接收的节点,然后调用接收节点的recv函数。而find函数是根据数据包的内容得到slot的值从而查询出谁是接收方的node。

4.4.     Connector的函数

void Connector::recv(Packet* p, Handler* h)

{

      send(p, h);

}

inline void send(Packet* p, Handler* h) { target_->recv(p, h); }

connector的recv和send函数是一个接口。这个函数中最重要的是target_这个值,这个值的不同会不同的调用Trace::recv、Queue::recv、LinkDelay::recv等等,但是这个值在那确定还没有看出来。

4.5.     Queue的函数

void Queue::recv(Packet* p, Handler*)

{

      double now = Scheduler::instance().clock();

      enque(p);   //根据规定的规则加入队列

      if (!blocked_) {

             /*

              * 这里没有堵塞.  将一个数据包发送出去.

              * 我们执行一个附加的检查,因为这个队列可能丢弃这个数据包

              * 即使它前面是空的。  (例如, RED队列就可能发生.)

              */

             p = deque();

             if (p != 0) {

                    utilUpdate(last_change_, now, blocked_);

                    last_change_ = now;

                    blocked_ = 1;

                    target_->recv(p, &qh_);  //调用dequetrace

             }

      }

}

Queue::recv这个函数调用DropTail规则将数据包加入队列,然后判断是否堵塞,如果没有则发送一个数据包,之前判断是认定这个包是否要被发送出去。这里也使用了target_->recv(),这里调用的是DequeTrace::recv函数,将记录一个数据包出队列的记录。

4.6.     LinkDelay的函数

void LinkDelay::recv(Packet* p, Handler* h)

{

      double txt = txtime(p);

      Scheduler& s = Scheduler::instance();

      if (dynamic_) { //这个是动态链路的标志,判断这个值确定链路是否为动态链

             Event* e = (Event*)p;

             e->time_= txt + delay_;

             itq_->enque(p); // 用一个队列来储存数据包

             s.schedule(this, p, txt + delay_);

      } else if (avoidReordering_) {

             // 预防重新安排带宽或时延改变

            double now_ = Scheduler::instance().clock();

            if (txt + delay_ < latest_time_ - now_ && latest_time_ > 0) {

                   latest_time_+=txt;

                   s.schedule(target_, p, latest_time_ - now_ );//在schedule里面加入事件

            } else {

                   latest_time_ = now_ + txt + delay_;

                   s.schedule(target_, p, txt + delay_); //在schedule里面加入事件

            }

 

      } else {

             s.schedule(target_, p, txt + delay_); //在schedule里面加入事件

      }

      s.schedule(h, &intr_, txt); //在schedule里面加入事件

}

这个函数非常重要,这个是数据包最后离开这个节点的出口,由这个函数写一个事件加入schedule,在一定的时间后调用。

s.schedule(target_, p, txt)这个的含义是在txt的时间以后调用target_的事件,处理p这个数据包。

 

SUMO与NS3联合仿真分析 利用sumo和NS3进行联合仿真分析 阅读详情

相关推荐

ns-3 仿真器简介

ns-3 仿真器是一款离散事件网络仿真工具,主要面向科研与教学场景使用。ns-3 项目始于 2006 年,是一款用于开发 ns-3 的开源项目。本教程旨在以条理化的方式向 ns-3 新用户完整介绍这套工具。新手往往很难从厚重的参考手册中提炼关键信息,并将其转化为可运行的仿真程序。本教程会带领读者搭建多个仿真示例,在实操过程中讲解、阐释核心概念与功能特性。随着教程内容逐步展开,我们会完整介绍 ns-3 全套文档,并为希望深入探究仿真器底层运行原理的读者提供源码查阅指引。

Long_像风一样自由 21

NS3 用户自定义数据包packet中的内容

参考链接: https://www.nsnam.org/docs/release/3.12/doxygen/classns3_1_1_packet.html#details NS-3如何把字符串写入到数据包内_Kevin Wang的博客-优快云博客 ASCII码字符对照表 https://blog.youkuaiyun.com/wz947324/article/details/80076496#commentBox 其他相关链接 https://blog.youkuaiyun.com/Mary1992041.

hanweixiao的博客 1939

基于ns-3的Wi-Fi与无线传感器网络模拟项目实战

ns-3(Network Simulator 3)是一款面向研究和教育的离散事件网络模拟器,主要用于有线与无线网络协议的开发与性能分析。其模块化架构支持多种网络技术,包括Wi-Fi、LTE、MANET、WSN等。与ns-2相比,ns-3采用了C++面向对象设计,并提供了更丰富的API接口与Python绑定,便于扩展与二次开发。核心组件包括节点(Node)、设备(Device)、信道(Channel)、协议栈(InternetStackHelper)等,通过组合这些模块可构建复杂的网络场景。

weixin_29323977的博客 1182

java soa 分层_分层架构&SOA架构

一、分层架构的类型​ 分层架构是很长见的架构模式,它也可以称之为N层架构;通常情况下,N至少是两层,例如我们常见的C/S架构和B/S架构。在我们开发web应用或者android的应用是常用的是三层架构,例如MVC(javaWeb)、MVP(android);当然除此之外,还有4层架构和5层架构、5层架构较为少见;分层架构​ 我们常说的四层架构的分法,就是想把软件设计师工作量降下来,减少重复性的代码...

weixin_39640687的博客 588

MATLAB版NS元胞自动机交通流模拟工具:单车道车辆演化与流量密度分析

一套开箱即用的MATLAB交通流仿真工具,基于经典的Nagel-Schreckenberg(NS)元胞自动机模型,实现单车道车辆运动的动态模拟。包含核心算法文件ns.m和主控脚本main.m,运行后自动生成车辆位置随时间演化的热力图、流量-密度散点图、密度-速度关系图等关键可视化结果。支持灵活调节最大车速、慢化概率、随机减速率等核心参数,便于观察不同条件下拥堵形成、走停波传播等典型交通现象。同步提供Python版本(ns.py/main.py)及依赖清单,兼顾MATLAB教学场景与跨平台复现需求。代码结构清

i8j9k0l1的博客 192

ns3-scratch: 掌握ns-3网络仿真代码

ns-3 是一款开源的网络仿真软件,主要面向研究人员和教育工作者,用于模拟计算机网络系统。其设计理念强调模块化和可扩展性,允许开发者在不同的抽象层次上构建复杂的网络拓扑和场景。由于其出色的性能和灵活的模拟能力,ns-3 在学术界和工业界被广泛使用,特别适合于进行大规模的网络实验和协议开发测试。与NS2等其他仿真器相比,ns-3 支持更高层次的网络协议,如LTE和Wi-Fi,以及更精确的时序和事件处理,使其在研究无线网络和现代互联网协议时具有明显优势。

weixin_28681379的博客 1348

NS元胞自动机模型--python实现

实现: ]# -*- coding: utf-8 -*- ''' NS模型 场景: 周期型边界 道路长度:cell=1000个元胞 车辆初始分布为均匀分布 初始速度:v0=vmax=5 随机慢化概率:p=0.1 仿真时步为2000时步,从500时步开始采样 -1表示元胞,其他值表示车辆 要求:绘制车辆加速度的分布图(密度:0.05, 0.2, 0.4, 0.6) ''' #im.

qq_39768922的博客 4705

NS中数据包Packet分析

NS中数据包Packet分析

Responder代码架构解析:深入理解服务器与投毒器模块设计

Responder是一个功能强大的LLMNR、NBT-NS和MDNS投毒工具,内置多种认证服务器支持NTLMv1/NTLMv2/LMv2等多种认证方式。本文将从代码架构角度深入分析其核心模块设计原理。 ## 🔍 核心架构概览 Responder采用模块化设计,主要分为两大核心组件: ### 投毒器模块(Poisoners) 位于 `poisoners/` 目录,负责网络协议层面的欺骗攻击:

gitblog_01020的博客 943

自己写的元胞自动机NS模型

用C++写的元胞自动机NS模型,可以在程序中对规则修改,得到新的模型。方面初学者的学习运用。

元胞自动机的NS模型

元胞自动机的NS模型的C++代码实现 可用 结构清晰

使用SourceInsight阅读NS源代码

ns2的源码底层是C++,采用了C++/Tcl分裂对象模型,架构完善,堪称OOP编程的典范。但是NS源码体系庞大,源文件有2千多个,阅读起来不是特别方便,推荐使用SourceInsight。具体的配置如下:   1.  下载安装SourceInsight。   2.  安装后,先进行一些配置,以便使得SourceInsight能够正确得识别NS的源文件类型,也就是添加.

CS 801

在NS下进行新协议开发的一般流程.doc

在NS下进行新协议开发的一般流程.doc 来自网络,仅供参考。

LSPatch 免 Root 使用指南:3 步给任意应用装上 Xposed 模块

LSPatch 是一个基于 LSPosed 核心的免 Root 安卓框架。它把 Xposed 模块直接打进你想改的那个 APK 里,不碰系统、不用 Root,就能让某个应用按你的意思跑。这篇从装应用到出补丁走一遍最短路径,顺带讲清两种模式怎么挑、卡住时往哪查。 ## 🧩 它省掉了哪些步骤 传统玩法要先 Root,再刷一套全局框架,靠开机时加载才生效。LSPatch 把这条路换掉了:它只做一件

gitblog_00690的博客 800

深入解析STM32定时器中央对齐模式3的双中断机制

本文深入解析了STM32定时器中央对齐模式3的双中断机制。该模式在一个PWM周期内,会在计数器到达ARR(上溢)和0(下溢)时各触发一次更新中断,实现更精细的实时控制。文章详细阐述了其工作原理、配置方法,并指导如何在中断服务函数中通过DIR位区分中断来源,同时探讨了其在电机控制、数字电源等场景下的应用优势与CPU负载挑战。

weixin_29164185的博客 493

【R语言-生存分析之观察生存率计算】

全人群肿瘤登记资料常用的统计分析指标包括发病率、死亡率、现患率以及生存率等,其中肿瘤生存率是评估肿瘤治疗效果和肿瘤负担的必要指标,其计算涉及肿瘤患者的发病、 死亡和随访三个方面的资料, 数据整理和计算过程均较为复杂, 如何及时、 准确地计算肿瘤生存率, 并使其可以在不同地区、 不同人群、不同时期间被客观公正地比较和评价,仍然是统计学家们一直在研究的主题。

weixin_46579654的博客 5441

NS3快速入门(使用VScode查看、编译代码)

前言 工欲善其工,必先利其器。 最近在学习ns3,于是折腾了好几天的环境。终于可以自己动手了。如果你也是刚准备学习ns3,你可以借鉴我博客的文章, 先把应该有的环境配置好,才能更好的去学习ns3。 Ubuntu的安装与配置 Ubuntu的优化 NS3环境搭建 搞定了环境之后,还没有进入正题去入门我们的NS3。 在我们学习ns3的时候,大部分时候我们都是在终端中输入命令./waf和./war --run的方式来编译和运行项目,对于代码文件的更改也只是称“使用你喜欢的IDE将代码修改”。虽然说理论上我们可以通过

Viper的程序员修炼手册 8586

Vivado 2018.3 SDK烧写bin文件避坑指南:如何解决QSPI模式下的常见错误

本文深入解析了在Vivado 2018.3 SDK中为Zynq FPGA烧写QSPI Flash时遇到的常见问题,特别是启动模式为QSPI时出现的警告与失败。文章从Zynq启动机制入手,提供了修改FSBL代码以强制使用JTAG模式、调整硬件配置等核心解决方案,并分享了实战案例与最佳实践,帮助开发者高效避坑,确保bin文件烧写成功。

arduino9maker的博客 389

NS2与NS3

一.NS2与NS3简介 NS2(Network Simulator,version 2)是一种面向对象的网络仿真器,本质上是一个离散事件模拟器,由UC Berkeley开发而成。它本身有一个虚拟时钟,所有的仿真都由离散事件驱动的。目前NS2可以用于仿真各种不同的IP网,已经实现的一些仿真有网络传输协议,比如TCP和UDP,业务源流量产生器。 NS3是一个离散事件模拟器,旨在满足学术研究和教学的需求...

qq_43046095的博客 6850

基于 parallels ubuntu 20.04 LTS (focal) 的ros+px4+gazebo 安装

基于 parallels ubuntu 20.04 LTS (focal) 的ros+px4+gazebo 安装。

weixin_40132006的博客 2241

MemSeg:一种差异和共性来检测图像表面缺陷的半监督方法

本文认为人为创建类内差异和保持类内共性可以帮助模型实现更好的缺陷检测能力,从而更好地区分非正常图像。如图一所示。差异(differences):MemSeg引入人工模拟的异常图像在训练阶段使模型能够区分正常和异常的图像,减轻了半监督学习只能用正常样本进行训练的不足,然后在推理阶段可以直接输入图像无需做任何后处理。共性(commonalities):MemSeg引入了一个记忆池来记录正常样本的通用模式,在训练和推理阶段,比较输入图像和记忆池中的样本之间的差异,为异常区域的定位提供有用的信息。

斯人若彩虹,遇上方知有! 4841

NS3初探

NS3初探 文章目录NS3初探一、简介NS3和NS2的不同二、NS3的编译运行1.waf编译器三、NS3重要概念1 节点——Node类2 信道——Channel类3 网络设备——NetDevice类4 应用程序——Application类5 拓扑帮助-topology helper6 节点容器--NodeContainer7 设备容器--NetDeviceContainer四、分析例子程序first.cc的源代码 一、简介 NS3是一款离散事件驱动的网络仿真器,主要应用于研究和教育领域,旨在满足学术和教学的

南瑾与春风的博客 5916

Ubuntu 22.04 LTS下Xenomai 3.3实时内核配置全攻略(附常见错误排查)

本文详细介绍了在Ubuntu 22.04 LTS系统上配置Xenomai 3.3实时内核的完整流程,包括环境准备、内核补丁应用、编译优化及常见错误排查。特别针对工业自动化和机器人控制场景,提供了性能优化建议和故障解决方案,帮助开发者实现毫秒级精度的实时任务处理。

weixin_29268385的博客 464
上一篇: [ZZ]Ubuntu Linux 9.10 安装NS2笔记
下一篇: [ZZ]NS2的DSR源代码分析
leonsc
博客等级 码龄18年 29粉丝 22原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值