ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

OPNET Modeler中Ad Hoc MAC协议源码级修改与仿真验证指南

OPNET Modeler中Ad Hoc MAC协议源码级修改与仿真验证指南 简介面向自组织网络协议研究者与工程开发人员这份资源以OPNET仿真为平台提供媒体接入控制层协议修改与仿真的完整源程序。压缩包内共九个文件主体为六个以m为扩展名的源码文件用于描述无线局域网媒体接入控制接口、交互上下文信息配置与目标地址传递等模块另有一个c语言文件、一份txt说明文档和一个obj对象文件整体大小约为二十九KB。目前已有三百八十四人学习下载。通过阅读这些代码可以掌握在OPNET中自定义媒体接入控制层模型的方法并基于Useful65模型快速搭建自组织网络仿真场景分析信道利用率、吞吐量、丢包率与端到端延迟等性能指标。对于需要优化信道访问机制、降低冲突概率或提升能量效率的研究课题具有直接参考价值适合作为课程设计、毕业设计或科研入门阶段的学习素材。1. 想改Ad Hoc MAC协议就别只调参数usefull65工程里的源码才是主菜做Ad Hoc网络MAC层协议修改和仿真最磨人的不是算法本身而是改完之后如何在OPNET里把改动落实到进程模型、还能让仿真结果证明改动是有效的。这份usefull65仿真源程序把节点模型、进程模型、配置ICI、控制帧格式和移动性模块全部放在同一个工程里打开就能看到MAC接口处理信道接入、退避、重传和转发控制帧的完整动作。它解决的不是“怎么点按钮把仿真跑通”而是“MAC层协议改了自己说了算还要给评审和论文一个可复现的实验证据”。适合正在做Ad Hoc组网协议对比、毕业论文要做MAC优化、或者工作中要用OPNET Modeler验证新接入算法的研究生和工程师。拿到资源后先别急着运行把压缩包里的每个文件按类型拆出来过一遍后面少踩很多坑。2. 拆开压缩包到OPNET工程五个核心文件的分工与调用链2.1 文件类型自查一个OPNET工程不是只有单个.pr.mOPNET Modeler的工程文件不是一种格式包打天下。同一个目录下.pr.m是进程模型.nd.m是节点模型.pk.m是报文格式.ic.m是ICI接口控制信息格式而.pr.c是进程模型翻译出来的C语言源码。初次接触这个工程的人很容易只盯住.pr.m以为改协议就是把状态图里某个转移条件改一下实际改起来才发现属性读取失败、参数传不进去、编译对象没更新哪一个都能让仿真结果失真。先把文件类型弄明白再动手。这份资源里出现的文件主要分四类以gpr_wlan_开头的是无线局域网部分的模型文件以GPR_MAC_开头的是MAC模块相关的ICI格式以gpr_billard_开头的是移动性模型还有一个www.pudn.com.txt是来源站点的说明文本不属于仿真模型部分。下表把文件类型和它在工程里的作用列清楚方便对照。扩展名 / 类型代表文件在MAC仿真里的角色.pr.m进程模型gpr_wlan_mac_interface.pr.m状态转移逻辑信道接入、退避、重传、确认处理.pr.cC源码gpr_wlan_mac_interface.pr.c进程模型翻译出的可读C代码修改后可重新生成模型.nd.m节点模型gpr_wlan_station_adv.nd.m定义无线工作站的内部模块结构和包流走向.pk.m报文格式gpr_wlan_control.pk.m定义MAC控制帧RTS/CTS/ACK的字段布局.ic.mICI格式GPR_MAC_CFG_ICI.ic.m、GPR_MAC_Dest_ICI.ic.m跨层参数传递通道把配置和目标地址送进MAC进程.dev32.i0.pr.obj编译对象gpr_billard_mobility.dev32.i0.pr.obj移动性模型的预编译产物换环境后需要重编把这张表记住之后你再看压缩包就不会被文件后缀绕晕。gpr_wlan_mac_interface.pr.c和.pr.m本质上对应同一个进程模型.c是源代码形态.m是可以在OPNET进程模型编辑器中打开的状态图形态两者不一致时以你重新编译生成的版本为准。gpr_wlan_station_adv.nd.m是节点级装配图它决定上层协议栈怎么和MAC接口进程连起来。这里有个容易被忽略的细节.pr.c是导出的C代码并不一定在每次仿真时都被执行OPNET实际加载的是编译后的模型对象。所以修改完.c之后如果不重新编译改动对运行结果毫无影响这个坑后面的排查章节还会专门展开。2.2 五个核心文件怎么配合从建包到接入的一条调用链从通信时序看这五个文件的协作顺序大致是这样。初始化阶段节点模型gpr_wlan_station_adv.nd.m里的上层模块创建GPR_MAC_CFG_ICI.ic.m格式的配置ICI把时隙长度、退避上限、重传门限这类参数打包通过op_ici_install挂到MAC接口进程的事件里MAC进程在INIT状态读取并保存。进入数据发送阶段上层协议栈构造数据包创建GPR_MAC_Dest_ICI.ic.m格式的目标ICI标明接收节点的地址MAC接口进程拿到目标地址后先做载波监听和退避再决定直接发送还是先发RTS控制帧。gpr_wlan_control.pk.m定义的控制帧在这里起作用当节点走RTS/CTS流程时MAC进程先发送一个RTS帧收到对端CTS回应后才进入数据发送如果开启的只是基础CSMA/CA流程则控制帧只包含ACK确认。gpr_wlan_mac_interface进程做决策控制帧用gpr_wlan_control承载参数和目标地址由两个ICI传递最终所有模块通过gpr_wlan_station_adv节点模型组装在一起形成一个可运行的无线工作站。这就是为什么绝大多数MAC层修改都从gpr_wlan_mac_interface入手。节点模型是装配层面的改动通常只在你要给工作站增加新的模块比如再加一个物理收发信机、插入一个队列模块时才动报文格式和ICI格式属于数据结构层面的改动配合新协议增加字段时才会碰真正决定“节点在什么时候能发包、遇到冲突怎么退避、重传几次就放弃”的都在MAC接口进程模型内部。后面第3章的修改工作也是围绕这一点展开。如果你拿到工程后时间有限优先级排序应该是先读gpr_wlan_mac_interface的进程逻辑再用GPR_MAC_CFG_ICI做参数注入最后才考虑改节点模型和报文格式这条路径能让你在最短时间内看到协议修改对仿真结果的影响。3. 改MAC接口进程模型从退避逻辑到配置ICI注入的三个落点3.1 先读状态转移图退避、接入时序和确认处理是修改的主战场打开gpr_wlan_mac_interface.pr.m你首先看到的是状态转移图。典型的WLAN MAC进程模型会包含初始化态、空闲态、退避态、发送态和等待确认态节点从初始化态进入空闲态后一旦上层有数据到达就触发信道检测信道忙则进入退避态退避结束再次检测信道空闲就发送发送后进入等待确认态收不到ACK就重传。这整个循环对应的是CSMA/CA的核心流程也是Ad Hoc网络各节点在没有中心控制时公平竞争共享无线信道的根本机制。修改MAC协议时我一般会从三个位置下手。第一个是退避计算默认退避值由竞争窗口决定想让节点延迟更久或者引入额外随机量就在退避态里改。第二个是接入时序DIFS或帧间间隔决定了发送前必须等待的静默时间调长DIFS等于给低优先级节点增加接入难度。第三个是重传和确认超时重传上限决定冲突后的最大尝试次数确认超时决定节点多快判断一帧丢失并进入重传。这三个位置的共同特点是它们都写在进程模型的函数体里而不是写在GUI属性面板里属性面板只暴露少数参数真正控制逻辑走向的是状态转移函数。以退避修改为例常见做法是在退避态的处理函数里读入一个自定义的额外时隙数给原退避值叠加随机量。下面是按OPNET的Proto-C语法写出的大致实现/* 在退避态处理函数里给backoff增加自定义扩展时隙 */ static void gpr_wlan_mac_handle_backoff (GprWlanMacT* mac_ptr) { int cw_current; int extra_slot 0; double rand_value 0.0; Objid node_obj op_topo_parent (op_id_self ()); /* 读取节点属性属性名要和节点模型里定义的完全一致 */ if (op_ima_obj_attr_get (node_obj, GPR_Extra_Slot, extra_slot) OPC_COMPCODE_SUCCESS) { /* op_dist_uniform(x) 返回 (0, x) 范围内的随机数 */ rand_value op_dist_uniform (extra_slot); } cw_current mac_ptr-backoff_remain; mac_ptr-backoff_remain cw_current (int) rand_value; if (mac_ptr-backoff_remain 0) mac_ptr-backoff_remain 0; /* 退避结束回到信道检测逻辑检查信道是否空闲 */ gpr_wlan_mac_check_channel (mac_ptr); }这段代码里的op_ima_obj_attr_get是OPNET读取节点属性的标准接口第一个参数是节点对象ID第二个是属性名第三个是存放结果的地址。这里用op_topo_parent(op_id_self())取到当前进程所属的节点对象因为MAC进程是节点内部的一个模块进程直接使用op_id_self()会得到模块而不是节点取父节点才能正确读取节点级属性。返回值OPC_COMPCODE_SUCCESS表示读到了属性如果节点模型里没有定义GPR_Extra_Slot这个属性函数返回失败码代码不会进入扩展分支退避行为保持原样。这一点很关键后续避坑章节里改成参数无效的问题多半就出在属性名对不上但代码没有报错上。op_dist_uniform(extra_slot)生成的是(0, extra_slot)区间的随机数注意不包含0所以extra_slot取0时这个调用没有意义调用前应做一个大于0的判断。在实际使用里我会额外加一个上限保护避免随机数过大导致退避时间被拉高到秒级否则整网时延会异常恶化。退避逻辑改完之后DIFS和重传的修改思路相同先定位对应状态函数把固定常量改成可配置变量再从属性或ICI里读取新值覆盖默认值。这里的“可配置变量”建议统一放进一个结构体里管理方便仿真参数扫描时批量修改也方便回溯一组实验到底用了哪些参数。3.2 配置ICI把修改后的参数越过层间边界送进MAC进程退避参数改在代码里但仿真每次跑完要调整这些值总不能每换一组参数就重新编译一次进程模型。OPNET里常见做法是把这类参数通过ICI在初始化阶段注入这样只需在配置场景时修改ICI字段的值进程模型代码不用重新编译。这份资源里的GPR_MAC_CFG_ICI.ic.m就是干这个用的。在进程模型的INIT状态里可以主动安装ICI实例并从当前事件中读取其中字段。参考实现如下/* 在初始化状态读取配置ICI把字段值写入MAC状态变量 */ static void gpr_wlan_mac_init_config (GprWlanMacT* mac_ptr) { Ici* cfg_ici; double slot_time 0.0; int max_backoff 0; /* 安装一个ICI实例用于从当前事件读取接口控制信息 */ cfg_ici op_ici_install (OPC_ICI_TYPE); if (cfg_ici OPC_NIL) return; /* 字段名必须与 .ic.m 文件定义一致注意大小写敏感 */ if (op_ici_attr_get (cfg_ici, Slot_Time, slot_time) OPC_COMPCODE_SUCCESS) { mac_ptr-slot_time slot_time; } if (op_ici_attr_get (cfg_ici, Max_Backoff, max_backoff) OPC_COMPCODE_SUCCESS) { mac_ptr-max_backoff max_backoff; } /* 读取失败时保留默认值保证仿真不会因参数缺失而中断 */ }这里有几个需要注意的参数细节。op_ici_install(OPC_ICI_TYPE)创建一个ICI实例返回值是ICI指针一般情况下它会在当前事件处理结束后由OPNET自动回收不需要手动释放。op_ici_attr_get的字段名必须和.ic.m文件里定义的字段名完全一致包括大小写和前缀比如Slot_Time和slot_time在OPNET看来是两个不同的字段。读取失败时代码只保留默认值不会中断仿真但这也意味着你辛辛苦苦配置的参数可能根本没生效——这是后面排查“改了没反应”的常见根源。实际项目里我会在初始化完成后输出一句调试日志把读到的slot_time和max_backoff打出来。这样每次启动仿真先在运行日志里确认参数确实是按预期注入的再做后续统计对比。如果没有这一行日志参数传没传到MAC进程只能靠猜等于把一个本来可控的环节变成了黑匣子。除了参数注入还要提防ICI实例被重复安装同一个事件处理过程中如果多次调用op_ici_install创建同名实例后创建的会覆盖前一个可能把前面的配置冲掉。我一般会先判断当前事件是否已经带有了ICI有就用现成的没有再新建。与之配套的GPR_MAC_Dest_ICI.ic.m作用类似但它承载的是目标地址信息在Ad Hoc多跳转发场景里它决定数据帧在MAC层的投递目标要改广播转发或组播行为动的是这个ICI的字段。4. 让Ad Hoc仿真跑起来挂载节点模型、移动性脚本与参数表设置4.1 搭一个最小可复现的仿真场景拿到这份资源后建议先搭一个节点数量在10到20之间的Ad Hoc场景而不是一上来就复现论文里的百节点网络。因为MAC层修改验证的核心是退避和冲突行为节点太少看不出信道竞争节点太多又难定位问题是出在MAC还是路由。常见做法是先在OPNET项目编辑器里新建一个空场景再从节点对象列表中选择自定义的gpr_wlan_station_adv节点模型把它放置在场景中。配置无线工作站时有几个点需要和MAC修改配合。物理层的数据速率决定了单帧传输时间速率越高相同负载下信道占用时间越短退避行为对整体时延的影响越明显建议在同一组对比实验里固定数据速率只改变MAC层的退避参数。应用层流量尽量使用恒定比特率报文大小512字节、发送间隔0.1秒这样统计曲线更平滑不会因为流量源自身的突发性干扰对MAC行为的判断。无线信道参数里传输功率和接收门限直接决定节点之间的干扰范围Ad Hoc仿真中节点密度和覆盖范围的比值要合理否则会出现大面积隐藏终端退避算法再改也看不出效果。场景搭好之后把节点协议栈改为Ad Hoc模式关闭接入点相关功能。因为gpr_wlan_station_adv是一个自组织工作站节点模型它本身没有中心控制节点参与所有节点平等竞争信道这一步要确认节点属性里的工作模式不是Infrastructure模式。MAC地址、IP地址可以按节点编号顺序配置方便后续按地址抓统计量。如果你打算跑多跳场景还要给节点配置路由协议AODV或DSR都可以但注意路由协议本身就带一部分控制开销会和MAC层退避互相影响我的做法是先跑两跳以内的简单场景验证MAC修改再扩展到多跳。4.2 移动性模型对MAC退避仿真结果的显性影响Ad Hoc仿真里移动性模型很容易被忽略但实际上它对MAC层的退避统计影响很大。节点静止时信道状态相对稳定退避事件的触发较规律节点移动时链路距离变化导致接收信号强度波动丢包和重传会增加退避次数和时延都会跟着变。这份工程里的gpr_billard_mobility移动性模型从命名就能猜出它的行为逻辑节点像台球一样在场景边界反弹撞墙之后改变运动方向继续移动避免节点长时间停留在一个固定位置。在OPNET中挂载这个模型的方法是在节点的移动性属性里选择自定义的进程模型然后配置速度和初始方向。模型内部会按仿真时间周期更新节点位置移动边界默认与场景尺寸相关。示例代码如下/* 台球式移动性的初始化设定速度、方向与边界 */ static void billard_mobility_init (GprBillardState* ms, Objid node_obj) { double speed 5.0; /* 默认移动速度单位m/s */ double direction 0.0; /* 初始方向单位度 */ int scene_x 1500; /* 场景宽度单位m */ int scene_y 1500; /* 场景高度单位m */ /* 读取节点属性覆盖默认速度与方向 */ op_ima_obj_attr_get (node_obj, Speed, speed); op_ima_obj_attr_get (node_obj, Initial_Direction, direction); /* 把极坐标方向换算成平面速度分量 */ ms-vx speed * cos (direction * M_PI / 180.0); ms-vy speed * sin (direction * M_PI / 180.0); ms-bound_x scene_x; ms-bound_y scene_y; }这里op_ima_obj_attr_get同样是标准属性读取接口Speed和Initial_Direction如果没在节点模型里定义读取失败后就会沿用代码里的默认值。速度一般取1到10 m/s对应步行到车载的移动场景速度太高会导致链路频繁断裂MAC层统计结果里重传占比会大幅上升导致退避参数的影响被噪声淹没。M_PI在部分编译环境里需要自行定义比如#define M_PI 3.14159265358979323846遇到编译报错时先检查这一点这属于移植过程中很常见的低级但麻烦的问题。把移动性模型挂上之后记得要确认每个节点都用同一个进程模型实例而且仿真时间要足够长。移动对统计结果的影响会随时间累积仿真时间只跑几十秒的模拟节点还没移动几步移动性配置等于白设。我一般会让仿真时间跑到300秒以上统计区间从第50秒之后开始取把冷启动阶段的异常排除在外。4.3 参数表把你改的MAC参数和场景参数对应起来为了让新手能直接对照着配置这里给出一张我在Ad Hoc MAC仿真里常用的参数表。它不是标准答案但对复现这个工程、验证退避修改非常有用。参数项推荐取值作用与说明节点数量10 ~ 20节点越多信道竞争越激烈退避行为越明显场景尺寸1500m × 1500m决定节点分布密度影响隐藏终端概率数据速率2 Mbps 或 11 Mbps固定不变保证MAC层修改是唯一变量应用流量CBR 512B / 0.1s负载恒定便于统计曲线平滑对比移动速度1 ~ 10 m/s低速对应步行高速对应车载场景GPR_Extra_Slot0 ~ 3自定义退避扩展时隙数是本工程的核心修改入口Max_Backoff3 ~ 7退避上限控制重传带来的时延上限这张表里的GPR_Extra_Slot和Max_Backoff是进程模型自加的属性如果节点模型里没有定义这两个属性需要先回到gpr_wlan_station_adv.nd.m中把它们补上或者在gpr_wlan_mac_interface的读取失败分支里保持默认值。参数扫描时建议一次只改一个维度的参数比如固定场景和流量只改变GPR_Extra_Slot的取值这样统计结果的变化才能归因于退避修改本身。多参数同时改动最后定位不了是哪一项引起的差异等于浪费了一整轮仿真时间。5. 避坑排查Ad Hoc MAC仿真的五个经典翻车点5.1 现象模型编译通过仿真一运行就中途退出OPNET对进程模型的编译检查和运行期行为是两回事。编译通过只说明语法没有致命错误运行期崩溃往往出现在属性读取和空指针防护上。我在这个工程里见过最多的情况是gpr_wlan_mac_interface进程代码里读取了GPR_Extra_Slot但gpr_wlan_station_adv.nd.m节点模型里根本没有定义这个属性。op_ima_obj_attr_get返回失败码后代码仍继续使用未初始化的变量后续引用空状态变量直接导致进程异常退出。解决方法是三步走。先在节点模型编辑器的属性列表里确认GPR_Extra_Slot是否存在属性名是否和进程代码里完全一致如果不存在在节点模型上添加该属性并设置默认值。然后在进程代码的读取分支里加入返回值判断读取失败时就给默认值。最后在初始化状态加一条调试日志每次仿真启动时把读到的参数值打印出来确认属性真的进了状态变量。这三步做完之后这类崩溃基本不会再出现。记住一个原则OPNET里属性读取的失败不会像普通C语言那样当场报段错误它只会安静地返回一个错误码真正的崩溃往往发生在后面很远的地方。5.2 现象改了退避参数统计曲线纹丝不动这是最让人怀疑人生的现象代码改得很好参数也配了仿真跑完吞吐量和时延曲线与修改前完全重合。原因多半不在逻辑而在编译对象。OPNET进程模型在运行时调用的是编译后的目标对象如果你修改了.pr.c但没有重新生成进程模型或者进程模型编辑器里改了状态图但没有执行Rebuild仿真实际调用的还是旧代码你的修改自然毫无痕迹。解决方法是进入进程模型编辑器确认当前模型已保存然后在编译菜单里重新生成目标对象。更稳妥的做法是把旧的.dev32.i0.pr.obj文件删掉让OPNET强制全量重建。还要检查一个容易忽略的点节点模型里引用的进程模型名是否正确。如果gpr_wlan_station_adv.nd.m里引用的是另一个进程名你改的gpr_wlan_mac_interface根本就没被装入仿真。检查方式是打开节点模型里MAC模块的属性设置看进程模型字段指向的名字和工程文件名是否一致。养成修改后立即Rebuild的习惯可以省掉无数排查时间。5.3 现象节点模型和ICI字段对不上报出attribute not foundGPR_MAC_CFG_ICI.ic.m定义了Slot_Time和Max_Backoff字段进程代码里用op_ici_attr_get读取时却报了attribute not found这是ICI字段名不一致导致的。OPNET的ICI字段名对大小写敏感Slot_Time写成slot_time就会读取失败而且这个失败不中断仿真只是字段保持默认值。最坑的是它在启动阶段不会弹窗只有在认真对比结果时你才发现参数根本没传进去。解决方法是打开ICI格式定义文件把字段列表逐字复制到代码里不要手动敲。如果不想让参数缺失悄悄发生可以在初始化时用op_ici_attr_get的返回值做一次判断读取失败就直接打印警告日志。日志里带上期望字段名和实际ICI格式名排查时一眼就能看出是哪里对不上。字段名对不上这个问题在多人协作或者从网上找来的工程里尤其高发因为原作者命名习惯和你习惯的命名方式很可能不同。5.4 现象billard移动性模型在64位环境下运行异常这份工程里带了一个gpr_billard_mobility.dev32.i0.pr.obj编译对象注意它的dev32后缀这是32位平台编译产物的记号。如果当前环境是64位操作系统、或者OPNET版本和原编译环境不一致直接沿用这个对象文件可能导致模型加载失败或运行时行为异常。我在换机器验证工程时遇到过不止一次现象是节点移动状态完全不更新或仿真启动时提示对象文件无法解析符号总之节点位置像被钉死了一样。解决办法很简单删除.dev32.i0.pr.obj让OPNET从.pr.m源码重新生成当前平台的目标文件。如果你的进程模型引用了系统库之外的第三方库重新编译前要把库路径加进OPNET的编译配置里。一条值得养成的习惯是每次换环境后在正式跑统计之前先跑一个5秒的小场景确认节点是否按预期移动避免把问题拖到统计完成之后才发现。对象文件是平台相关的这个常识在仿真工程里同样适用。5.5 现象仿真结果剧烈摆动像“发散”一样失去解释性有些参数配置下统计曲线会异常剧烈地摆动端到端时延在低值和高值之间来回跳吞吐量波形也没有稳定趋势这通常不是随机噪声而是参数组合把系统推到了不稳定区。常见原因是退避上限设得过大或重传次数过多退避时间过长时节点长时间不发送缓存堆积后又在某个时刻集中释放形成周期性的突发和空窗统计曲线自然发散。另一种情况是节点密度过高同时移动速度过快链路频繁断裂重传雪上加霜整个网络陷入持续冲突状态。解决方法是先把参数拉回常规区间比如退避上限取3到5重传次数取默认值确认曲线稳定后再逐步调高。在做多参数扫描时先固定其他维度只动一个MAC参数观察曲线从稳定到发散的分界点这个分界点本身就是MAC协议性能的有效信息。把发散当成仿真的正常输出往往会让后续统计分析完全失真。仿真发散不是失败它在告诉你参数组合越过了稳定边界这正是研究MAC协议极限性能最有价值的部分。6. 验证MAC修改是否生效抓三个统计量做对比实验6.1 三个统计量怎么抓MAC层修改的效果不能靠“感觉节点变慢了”来下结论。我习惯每次实验固定抓三个统计量网络吞吐量、端到端平均时延、重传次数或丢包率。吞吐量看整体传输能力有没有因为退避修改而下降端到端时延看接入等待和排队延迟的变化重传次数直接反映冲突控制的效果。在OPNET的结果面板里勾选这三个指标跑完仿真导出CSV后续用脚本处理均值。对比实验要做的事是保持场景完全一致只改变MAC进程模型的版本。推荐把基线工程和修改后工程分别保存成两个项目文件流量模型、节点位置、随机种子全部相同只更换gpr_wlan_mac_interface的实现这是排除变量干扰最干净的做法。跑完三轮随机种子取平均再绘制曲线对比# 对比基线与修改版的吞吐量均值用于验证MAC修改是否生效 import csv def throughput_mean(path): with open(path, newline) as f: rows list(csv.reader(f)) vals [float(r[1]) for r in rows[1:] if float(r[1]) 0] return sum(vals) / len(vals) if vals else 0.0 base throughput_mean(baseline_throughput.csv) mod throughput_mean(modified_throughput.csv) print(fbaseline: {base:.1f} bps, modified: {mod:.1f} bps)脚本里过滤掉值为0的采样点是为了把仿真初始阶段没建立连接的空档排除在外。取均值之前先看一眼曲线是否平稳如果前段明显偏高或偏低就丢弃前几秒的数据再做均值这个习惯能避免冷启动阶段把整个统计带偏。6.2 对比实验的另一种验证方式如果你改的是退避时序类参数除了看均值还要关注时延的分布特性。拿一组修改前后的端到端时延采样计算P50和P90分位数能看出新协议是整体抬高了时延还是只把尾部高时延降下来了。这两种情况对应的接入策略完全不同只看均值容易掩盖问题。举例来说如果P50基本不变但P90明显下降说明修改主要改善了高负载下的排队和冲突这是很典型的退避优化效果如果P50和P90同步抬升则说明新协议付出的接入代价偏大需要权衡公平性和吞吐量。从那以后我每次改完MAC层模型都强制走一遍固定流程确认属性名和ICI字段名逐字匹配、检查编译对象已重建、跑一次5秒小场景验证节点移动和参数注入正常、再跑三轮随机种子统计。这套流程救过我很多次因为大量“协议没改对”的结论最后都发现是编译未生效或参数未注入这些低级问题。如果这份工程也让你在Ad Hoc MAC仿真上少绕两个弯那就值了。希望帮到你。本文还有配套的精品资源点击获取
返回列表