zoukankan      html  css  js  c++  java
  • 【NS2】NS2修改MAC协议(转载)

    NS2版本:2.34
     
    涉及NS2代码文件:
    ns-2.34/mac/channel.h
    ns-2.34/mac/channel.cc
    ns-2.34/mac/wireless-phyExt.h
    ns-2.34/mac/wireless-phyExt.cc
    ns-2.34/mac/mac-802_11Ext.h
    ns-2.34/mac/mac-802_11Ext.cc
    ns-2.34/mac/mac-802_11.h
    ns-2.34/mac/mac-802_11.cc
    ns-2.34/common/packet.h
    ns-2.34/tcl/lib/ns-default.tcl
    ns-2.34/Makefile
     
     
    准备工作:
    1.复制mac-802_11Ext.{h,cc},wireless-phyExt.{h,cc}命名为mymac-802_11.{h,cc},mywireless-phy{h,cc}
    2.将mymac-802_11.{h,cc},mywireless-phy{h,cc}的代码置于自定义的命名空间MYMAC里
     
    代码修改:
     
    1.打开mymac-802_11.h找到
     
     

    // XXX This header does not have its header access function because it shares

    // the same header space with hdr_mac.

    struct hdr_mac802_11 {
        struct frame_control dh_fc;
        u_int16_t dh_duration;
        u_char dh_ra[ETHER_ADDR_LEN];
        u_char dh_ta[ETHER_ADDR_LEN];
        u_char dh_3a[ETHER_ADDR_LEN];
        u_int16_t dh_scontrol;
        u_char dh_body[0]; 
    // size of 1 for ANSI compatibility

    };

        这是NS2中对802.11mac头部的实现,按照NS2文档如果要定义一个新的协议头必须定义static int offset_以及inline static {some mac sturct}* access(const Packet* p)函数,以使NS2能在class Packet中定位到你的头部,这种方法不是很理想,有时候我们只是对已有的头部做一些修改,并不需要重新定义一个头部,按文档的做法会增加不必要的内存 开销,这里我们看上面的注释,翻译过来就是“头部并没有定义自己的头部访问函数,因为它和hdr_mac(定义在mac.h中)使用同样的空间”,这就给 我们提供了另一中添加自定义报头的方法,我们可以在上面的机构中加入我们的数据段,不需要考虑数据对齐的问题,因为上面的头部结构定义在NS2中只是用在 传输头部信息,而真实的数据长度在hdr_cmn.size_中,但是有一点要注意确保 sizeof(hdr_mac802_11)==sizeof(hdr_mac)。那怎么访问自定义头部呢?我们看到packet.h中,找 到#define HDR_MAC802_11(p) ((hdr_mac802_11 *)hdr_mac::access(p)),使用该宏就能定位到自己的头部了。

        头部数据已经定义好了,我们得告诉NS2头部数据的真正长度,以便NS2计算传输时间,打开mymac-802_11.cc找到

    void TXC::prepareMPDU(Packet *p) {
        hdr_cmn* ch = HDR_CMN(p);
        struct hdr_mymac802_11* dh = HDR_MYMAC802_11(p);
        ch->size() += mac_->phymib_.getHdrLen11();

        dh->dh_fc.fc_protocol_version = MAC_ProtocolVersion;
        dh->dh_fc.fc_type = MAC_Type_Data;
        dh->dh_fc.fc_subtype = MAC_Subtype_Data;
        dh->dh_fc.fc_to_ds = 0;
        dh->dh_fc.fc_from_ds = 0;
        dh->dh_fc.fc_more_frag = 0;
        dh->dh_fc.fc_retry = 0;
        dh->dh_fc.fc_pwr_mgt = 0;
        dh->dh_fc.fc_more_data = 0;
        dh->dh_fc.fc_wep = 0;
        dh->dh_fc.fc_order = 0;
        dh->dh_scontrol = mac_->sta_seqno_++;

        ch->txtime() = mac_->txtime(ch->size(), ch->mod_scheme_);

        if ((u_int32_t)ETHER_ADDR(dh->dh_ra) != MAC_BROADCAST) {
            dh->dh_duration = mac_->usec(mac_->txtime(mac_->phymib_.getACKlen(),
                    mac_->phymib_.getBasicModulationScheme())
                    + mac_->macmib_.getSIFS());
        } else {
            dh->dh_duration = 0;
        }
    }

    看到ch->size() += mac_->phymib_.getHdrLen11(),getHdrLen11定义如下
    getHdrLen11() {
    return(HDR_MYMAC_LEN
    + ETHER_FCS_LEN);
    }
     
    在mac-802_11Ext中原来实现如下
    getHdrLen11() {
    return(offsetof(struct hdr_mac802_11, dh_body[0])
    + ETHER_FCS_LEN);
    }
    使用求偏移得到hdr_mac802_11结构大小,由于我自己添加了3个字节数据在使用偏移会由于对齐问题得到的大小比我实际的大,所以这里不采用偏移
        接下来找到

    static class Mac802_11ExtClass : public TclClass {
    public:
        Mac802_11ExtClass() :
            TclClass("Mac/Mac802_11Ext") {
        }
        TclObject* create(int, const char*const*) {
            return (new Mac802_11Ext());
        }
    } class_mymac802_11;

    将TclClass("Mac/Mac802_11Ext")改为TclClass("Mac/MyMac802_11"),以在tcl中将Mac/MyMac802_11和自定义的mac协议绑定

    2.打开mywireless-phy.cc,将#include "wireless-phyExt.h",#include "mac-802_11Ext.h"改为#include "mywireless-phy.h",#include "mymac-802_11.h"

    找到

    static class WirelessPhyExtClass : public TclClass {
    public:
        WirelessPhyExtClass() :
            TclClass("Phy/WirelessPhyExt") {
        }
        TclObject* create(int, const char*const*) {
            return (new WirelessPhyExt);
        }
    } class_WirelessPhyExt;

    将TclClass("Phy/WirelessPhyExt")改为TclClass("Phy/MyWirelessPhy"),已以在tcl中将Phy/MyWirelessPhy与自定义的物理层协议绑定

     
    3.打开channel.cc,添加#include "mywireless-phy.h",找到

    void
    WirelessChannel::calcHighestAntennaZ(Phy *tifp)
    {
           double highestZ = 0;
           Phy *n;
     
           
    // HACK: the dynamic_cast is a workaround only!

           for(n = ifhead_.lh_first; n; n = n->nextchnl()) {
             if(dynamic_cast<MYMAC::WirelessPhyExt*>(n)) {
                 if(((MYMAC::WirelessPhyExt *)n)->getAntennaZ() > highestZ)
                     highestZ = ((MYMAC::WirelessPhyExt *)n)->getAntennaZ();
             } else if(dynamic_cast<WirelessPhyExt*>(n)) {
                 if(((WirelessPhyExt *)n)->getAntennaZ() > highestZ)
                     highestZ = ((WirelessPhyExt *)n)->getAntennaZ();
             } else if (dynamic_cast<WirelessPhy*>(n)) {
                 if(((WirelessPhy *)n)->getAntennaZ() > highestZ)
                     highestZ = ((WirelessPhy *)n)->getAntennaZ();
             } else highestZ = 0;
           }

           highestAntennaZ_ = highestZ;

           if (dynamic_cast<MYMAC::WirelessPhyExt*>(tifp)) {
             MYMAC::WirelessPhyExt *wifp = (MYMAC::WirelessPhyExt *)tifp;
             distCST_ = wifp->getDist(wifp->getPowerMonitorThresh(), wifp->getPt(),wifp->getAntennaRxGain(), wifp->getAntennaTxGain(),
                 highestZ , highestZ, wifp->getL(),
                 wifp->getLambda());
           } else if (dynamic_cast<WirelessPhyExt*>(tifp)) {
                 WirelessPhyExt *wifp = (WirelessPhyExt *)tifp;
                 distCST_ = wifp->getDist(wifp->getPowerMonitorThresh(), wifp->getPt(),wifp->getAntennaRxGain(), wifp->getAntennaTxGain(),
                     highestZ , highestZ, wifp->getL(),
                     wifp->getLambda());
               } else if (dynamic_cast<WirelessPhy*>(tifp)) {
             WirelessPhy *wifp = (WirelessPhy *)tifp;
             distCST_ = wifp->getDist(wifp->getCSThresh(), wifp->getPt(), 1.0, 1.0,
                     highestZ , highestZ, wifp->getL(),
                     wifp->getLambda());
           } else distCST_ = DBL_MAX;
    }

    这是用来计算天线高度的,上面的有MYMAC名空间的代码都是我添加的

     
    4.打开ns-default.tcl,在里面添加一些默认参数
     
    5.打开Makefile,在OBJ_CC后添加中mymac-802_11.o mywireless-phy.o
     

    最后重新编译自定义的mac协议就添加完成了。

    源地址:http://blog.myspace.cn/e/407621022.htm

  • 相关阅读:
    图像处理基本算法(整理)
    Java 数据校验自动化(validation)
    Java Web文件上传
    JavaScript中call、apply、bind、slice的使用
    在不借助其他工具的情况下破解Windows开机密码
    【Docker】iptables failed: iptables --wait -t nat -A DOCKER -p tcp -d 0/0 --dport 8480 -j DNAT --to-destination 172.17.0.2:80 ! -i docker0: iptables: No chain/target/match by that name
    【异常】Caused by: java.lang.IllegalStateException: RequestParam.value() was empty on parameter 0
    【Docker】docker的安装和常用命令
    【监控】jvisualvm之jmx远程连接 jar启动应用
    【监控】jvisualvm之jmx远程连接 tomcat war启动应用
  • 原文地址:https://www.cnblogs.com/helloWaston/p/4544883.html
Copyright © 2011-2022 走看看