Colorful SeaSon's profileNS2 & SeaSonBlogLists Tools Help

Blog


    August 26

    层次地址的设定

    在无线和有线网络的混合仿真中为了使数据包能在有线和无线网之间找到路由需要用

    hierarchical 地址,hierarchical 地址分三层结构:

    ABC

    A:所处的网络地址

    B:所处的子网地址

    C:节点地址

    2、设定网络的数量,即不同的A的数量

    AddrParams set domain_num_ 5

    设定网络数量为5,即上面图中从0~4

    3、设定每个网络中子网的数量。要同下图的网络对应,即对应0的子网数量,1的子网数量...

    lappend cluster_num 2 1 1 2 2

    即设定:

    网络号(A)

    0

    1

    2

    3

    4

    子网数量(B)

    2

    1

    1

    2

    2

    AddrParams set cluster_num_ $cluster_num

     

    4、设定每个子网中节点的数量,也严格按照顺序

    lappend eilastlevel 1 1 2 1 1 1 1 1

    AddrParams set nodes_num_ $eilastlevel

    顺序为对于不同的网络按照网络号由小到大,而相同的网络地址,按照子网号从小到大排序,然后按照排序结果顺序写出每个子网中节点的数量。如对应下图(单击看大图)的设定结果为

    网络号(A)

              0

          1

       2

            3

           4

    子网数量(B)

            2

         1

      1

            2

           2

    子网节点数量

    1

    (0.0.0)

    1

    (0.1.0)

    2

     (1.0.0  \1.0.1)

    1

    (2.0.0)

    1

    (3.0.0)

    1

    (3.1.0)

    1

    (4.0.0)

    1

    4.1.0)

     

     

     

    February 09

    公告

           因为长时间不接触NS了,也没什么可写了,这里就停止更新了,等我以后接着做的时候,会将我的经验与大家分享。
          为了大家方便,我把我的经验总结成了《NS29问之SeaSon解答》放在了我的共享信箱里面,有一些因为仓促未整理进去,我会在以后的工作中继续完善的:)
      db.hit.edu.cn/~season
                                                     SeaSon 2006-2-9
     
    注意:用下载工具下载的时候一定要保留备份,以方便他人继续下载,谢谢了
     
    July 15

    tcldebug的安装完美版

    1.下载 tcl-debug( 地址 http://expect.nist.gov/tcl-debug/tcl-debug.tar.gz),以版本2.28为例,解压到ns-allinone-2.28目录下面。
    2. 编译tcl-debug,并且将产生的可加载的库文件复制到NS-2的库目录里面,具体步骤如下:
       1) 进入到tcl-debug目录下面
                $ cd tcl-debug-2.0
       2)  配置并且编译tcl-debug
            $ ./configure
            $ make
     
        3)检查可加载的库文件(*.a) 在编译之后是否被创建。
            查看是否产生了一个"libtcldbg.a" 文件。他是一个tcl的库文件。
            
        4) 复制这个库文件到NS-2 库目录里面,即 /home/UserID/ns-allinone-2.28/ns-2.28/lib or ~ns/lib
            $ cp *.a ../ns-2.28/lib
         注:编译之后不会产生一个可执行的文件,而是一个可加载的库文件。
    3. 编译NS-2
       1) 进入~ns/lib目录里面,查看库文件libtcldbg.a是否存在。
              $ cd ../ns-2.28/lib
              $ ls
       2) 进入ns-2.28目录下面,即 /home/UserID/ns-allinone-2.28/ns-2.28
            cd ..
     
        3) 重新配置NS-2以便启用tcl-debug.
            $ ./configure --with-tcldebug
       注意:你可以从屏幕输出的信息查看到tcl-debug是否被验证了。
               如果你没有看到以下的文字,你需要重复以前的步骤。
            Checking for libtcldbg... -L/home/UserID/ns-allinone-2.28/ns-2.28/ ../tcl-debug-2.0 -ltcldbg
               上面的文字在下面这句话之后出现     
                  checking dmallc... not requested with --with-dmalloc 
       4)删除以前的编译纪录
               $ make clean
            注:这一步骤非常重要!
       5)重新编译NS-2
              $ make   
             现在tcl-debug已经嵌入到NS-2的可执行文件"ns.exe"中去了
       6)检查NS-2是否能够正常运行。随便选择一个脚本测试一下就可以了
             $ ns  example.tcl
       7) 拷贝ns.exe到ns-allinone-2.28/bin 目录里面(我觉得设置了环境变量就不用了)
    4. 检查tcl-debug是否能够正常工作。
        你可以通过添加debug 1在你的脚本中设置断点。示例如下:
        1)从目录~ns/tcl/ex directory 里面选择一个脚本, 如:wireless-test.tcl,
            利用文本编辑器编辑该脚本:
         
            set ns_  [new Simulator]
            debug 1;  # 在这个位置添加这么一行代码
            set chan [new $opt(chan)]

         2) 运行 wireless-test.tcl
             $ ns wireless-test.tcl

              运行脚本之后,如果你成功安装,将会出现以下信息提示:
             2: lappend auto_path $dbg_library
             dbg2.0>

    如果还有错误信息,你就重复检查以上各个过程是否正确,好运!

    注:以上为翻译ns mail-list内容,作者为:Tae-hyung Kim,最后对他表示深深的感谢!

    DSR源代码分析[转载]

    DSR in ns-2


    Source code :

        Not all flies in ./dsr/ directory are used by the ns-2. the routing agent is implemented as Agent/DSRAgent.
        Thus, the source codes include:
    • dsragent.cc (h):  DSR agent class. major state machine handling routings. Important variables; net_id, mac_id in ID type. (IP and MAC address), both of them are initialzied by tcl commands to set the initla valie, the commads are "addr" amd "mac_addr"
    • hdr_sr.cc(h): define hdr_sr class.
    • request_table.cc(h)
    • Path.h(cc):  Path class. First, define struct  ID, it has an unsigned long addr a enum of ID_type, and a time stamp t. and then in Path class, ID[] is the key members of the path, and operator [] is defined to return an element of ID array. thus whenever the SRPacket.route[n] will return to the reference of ID[n]. Other member variables include cur_index, len,
    • srpacket.h:    Just define SRPacket class which enclose the hdr_sr as a full packet. The SRPacket construct has two parameters, a normal packet and a SR (Source Route) Header (a path variable). The constructor of "path" class makes a path from the bits of an NS source route header. And the other two variables of the SR packet are "dst" and "src" IP addresses.
    Data Structure for Route

    It is found that srh->addr and p.route are two different structures. srh() is always along with the packet. however, when DSR agent received a packet, it will
           SRPacket p(packet, srh);

     This generate a "p" which is frequently used by all other functions. remember p does not go along with the packet leaving dsr agent. Before the packet was sent out of the agent, another statement will be used to update "SRH" in sendOutPacketwithRoute
       
     p.route.fillSR(srh);

    Also, the tap() entry is also generate a p for its use. however, another entry point of agent "xmitFailed" use srh() directly.

    Special tcl interface.

    Unless other routing protocol, the ns-2.1b9a,has a special node type named as "SRNodeNew". From those routines in the ns-lib.tcl. We can see that speical. Also, there is a tcl file in mobiloty/dsr.tcl is also related.
    Simulator instproc create-node-instance args {
    $self instvar routingAgent_
    # DSR is a special case
    if {$routingAgent_ == "DSR"} {
    set nodeclass [$self set-dsr-nodetype]
    } else {
    set nodeclass Node/MobileNode
    }
    return [eval new $nodeclass $args]
    }

    Simulator instproc set-dsr-nodetype {} {
    $self instvar wiredRouting_
    set nodetype SRNodeNew
    # MIP mobilenode
    if [Simulator set mobile_ip_] {
    set nodetype SRNodeNew/MIPMH
    }
    # basestation dsr node
    if { [info exists wiredRouting_] && $wiredRouting_ == "ON"} {
    set nodetype Node/MobileNode/BaseStationNode
    }
    return $nodetype
    }

    DSR Signaling Packets in Brief:
    • route-request. the packet itself is a layer 3 packet with a unique destination address, but MAC_Broadcast (labeled in common header's next_hop())
    • route-reply: unicasting in both layer 2 and 3.
    • route-error. unicasting in both layer 2 and 3. Generated when tx_failure in lower layer.

    Entry Points for DSR agent:
    1. first, as normal, the recv() function which means a packet with a address destine to this node or from upper-target.
    2. xmitFailed(). This is the callback function when a MAC transmission failes. Based on this chance, route-error message generated
    3. tap(). This is a hidden entry when you turn promiscuous on. snooping the route and shorten the path.

    Basic functions:

    • recv(), the entry for a receving packet. depends on the ip address of the packet and the SR (Source Route) header, call different functions to handle it. like the diagram below:

      The route-reply, route-request messages need special handling routines written in the
      handlePacketReceipt() funciton. Note that if the RRequest message reached the destination, the receiptent should send a RReply message, this is done by a function named  returnSrcRouteToRequestor(p) which is called in handlePacketReceipt(). Otherwise, if the route-request and route-err
    • or are not destined to us, for route-request, the function handleRouteRequest() is called
    • handlePacketReceipt(). A signaling reached its destination. There are two case:
      • if it is a route-request and "not processed",  sends back a route-reply, pkt "p" is forged in this function and returnSrcRouteToRequestor(p)
      • if it is a route-reply, call functiuon  acceptRouteReply(p);
    • handleRouteRequest(): From the version 2.27, we see some unused codes but probably under develop for future versions. It includes more close mac-routing cooperation, such as neighbor identity (is_neighnor()), and channel status (air_time_free()).
       Basically, this function has three branches:
      1. already processed, checked by function ignoreRouteRequestp(p).
      2. has a cached route, done by replyFromRouteCache(p), and "cached route" is enabled by the flag dsragent_reply_from_cache_on_propagating.
      3. append myself in route with p.route.appendToPath(net_id); and sendOutPacketWithRoute(p, false);
    • handleForwarding. Forward packet on to next host in source route and  snooping as appropriate. So, a route-reply message is not treat as exceptional. It is a normal packet with sr header and be snooped by this node. The snooping is enabled by the flag "dsragent_snoop_source_routes" .
      handleForwarding is dcallin "handleDefaultforwarding" for doing some simple operations for DSR rules. At last, the packet will be sent by
      sendOutPacketWithRoute
    • sendOutPacketWithRoute:  The function is used as  for send packets, Take packet and send it out, packet must a have a route in it. return value is not very meaningful. if fresh is true then reset the path before using it, if fresh is false then our caller wants us use a path with the index set as it currently is. Basically,
      • cmn header's failure callback functon and data are set
      • cmn header 's next hop is set to  addr of  next-hop in dsr header. address type are also set.
      • move the pointer in SR header to the next (increase 1).
      Actually, the third operation is not valid in real DSR implementations. To undo this effect in error-handing, we'd better find current Ip address first and locate the position of this address in SR header. The other two operations are also invalid, because there are no common headers in a real packet. For the "next_hop()" in common header, it is used by DSR only for those packets without valid SR header, refer to recv().
    • returnSrcRouteToRequestor(); this function 
    • xmitFailed(): when the common header->xmit_failure_ point to a callback function, thus, when the packet cannot be delivered, the callback function is used, and finally will generate a route-error messages. There is always a pointer in the SR header curr() . ( Refer to manet-ietf-dsr draft, there is no such a pointer in DSR Source Route Option, but has a "segments left" field to indicate how many nodes still to visit to reach the destination. ). Thus, an innovation needs to be done to re-interprete the "srh->cur_addr()" as a index number of the position in the path where fail happens.  So,  when not all nodes along the path handle the SR header, we need find the ip address of the node from srh. and set that index as cur_addr();
    • processBrokenRouteError(p); This should be another branch under the main recv() entry. It gives what to do when a Route Error message is receoived or heard (snooped). Snoop means the message was sent to another node but it passes myself, so i heard it.
    • tap(const Packet *packet): This is another entry point for DSR. When dsragent_use_tap flag is true. the mac is working in promiscuous mode and all overhearing packets will be processed if there is a SR header in it.

    Other:
    The longest route we can handle is defined in : define MAX_SR_LEN 16           // longest source route we can handle

    Possible Reason for xmit_failure below IP layer:
    • arp failure
    • interface queue is full
    • mac transmission failure ( exceed the retry-limit)
    DSR scheme options:
    In the beginning of dsragent.cc, it define many bool selectors of some options like:


    /*************** selectors ******************/
    bool dsragent_snoop_forwarded_errors = true;
    // give errors we forward to our cache?
    bool dsragent_snoop_source_routes = true;
    // should we snoop on any source routes we see?
    bool dsragent_reply_only_to_first_rtreq = false;
    // should we only respond to the first route request we receive from a host?
    bool dsragent_propagate_last_error = true;
    // should we take the data from the last route error msg sent to us
    // and propagate it around on the next propagating route request we do?
    // this is aka grat route error propagation
    bool dsragent_send_grat_replies = true;
    // should we send gratuitous replies to effect route shortening?
    bool dsragent_salvage_with_cache = true;
    // should we consult our cache for a route if we get a xmitfailure
    // and salvage the packet using the route if possible
    bool dsragent_use_tap = true;
    // should we listen to a promiscuous tap?
    bool dsragent_reply_from_cache_on_propagating = true;
    // should we consult the route cache before propagating rt req's and
    // answer if possible?
    bool dsragent_ring_zero_search = true;
    // should we send a non-propagating route request as the first action
    // in each route discovery action?

    // NOTE: to completely turn off replying from cache, you should
    // set both dsragent_ring_zero_search and
    // dsragent_reply_from_cache_on_propagating to false

    bool dsragent_dont_salvage_bad_replies = true;
    // if we have an xmit failure on a packet, and the packet contains a
    // route reply, should we scan the reply to see if contains the dead link?
    // if it does, we won't salvage the packet unless there's something aside
    // from a reply in it (in which case we salvage, but cut out the rt reply)
    bool dsragent_require_bi_routes = true;
    // do we need to have bidirectional source routes?
    // [XXX this flag doesn't control all the behaviors and code that assume
    // bidirectional links -dam 5/14/98]

    #if 0
    bool lsnode_holdoff_rt_reply = true;
    // if we have a cached route to reply to route_request with, should we
    // hold off and not send it for a while?
    bool lsnode_require_use = true;
    // do we require ourselves to hear a route requestor use a route
    // before we withold our route, or is merely hearing another (better)
    // route reply enough?
    #endif



    About Flow State:

    It is also desirable to disable the flow state stuff. it make the dsr code messy. flow state is not an orginal idea.
    static const bool dsragent_enable_flowstate = false;
    static const bool dsragent_prefer_default_flow = false;


    About Packet Salvage

    it's unknown how to complete disable the packet retransmission in layer 3. Even you change three expressions in dsragent.cc.

    1. salvage_with_cache = false (from true)
    2. salvage_max_request =0 (from 1)
    3. salvage_times = 0 (from 15)

    The trace file still show that the routing agent send a undeliverable packet again. See xmitFail() function. I guess, it is necessary to disable "GOD" also.

     

    July 14

    怎样使用gdb调试ns中c++代码

    参见NS29问或者可老师网站上的,gdb调试说明

    1.安装:cygwin下面安装就行了,注意我测试的gdb-20020411-1和gdb-20010428-3都是图形界面,而版本gdb-20041228-3我发现是命令行的,所以推荐前两个版本,毕竟图形界面方便很多,如果你热衷于新的版本,那看到这里你就可以停止了:)下面以ns-allinone-2.27为例说明

    注:现在直接从网上安装的版本好像没有那么老的版本,我是从网上找到一个本地安装版本“ Cygwin0528”(可以用baidu或者google搜一下),然后利用它安装gdb-20020411-1,注意你只需要安装这一个就行了,其他的所有都选择为keep(已经安装的)或者skip(未安装的),否则会出现问题的,一定要切记这点儿。
    2.在代码里面添加调试信息:修改Makefile(没有任何后缀的)将里面
    CCOPT =     #如果是ns-allinone-2.28,这里是CCOPT = -O2
    STATIC =
    LDFLAGS = $(STATIC)
    LDOUT = -o $(BLANK)
    改变为:
    CCOPT = -g   #如果是ns-allinone-2.28,这里修改为 CCOPT = -O2 -g
    STATIC =
    LDFLAGS = $(STATIC)
    LDOUT = -o $(BLANK)
    修改的东西是粉红色字体所示
    3.然后重新编译

    注意:以下步骤一个都不能少
    Make clean
    Make depend
    Make
    4.调试过程如下
    进入工作目录:推荐ns-2.27
    操作:打开xwindows之后,
    a.输入 cd ns-allinone-2.27/ns-2.27(必须)
    b.输入gdb ns进入gdb工作界面,如果不是图形界面的版本可能就直接在xwindows进入Gdb调试过程,这样的话具体命令参见《NS仿真软件》精华区,不要问我!!!!!!!!!!
    如果按照我的要求安装的图形界面gdb,出现如下图形界面,如下所示:

    c.在左上角红色标记的地方输入你要调适的程序。如:mflood.cc
        设置断点,注意只有最左边有“-”符号(如下图中1所示)的可以设置断点,将鼠标放在行号上就会出现变成一个圆形的符号,单击即设了一个断点,原来的“-”地方变成了一个红色的方框,如下图中标号2所示。

     然后输入Ctrl+N进入命令行窗口,如下图所示:

    在上图中命令行窗口进入你的tcl脚本所在的目录:
      我的在ns-2.27/mytcl
    因为当前的工作目录在ns-2.27,所以我直接输入cd mytcl就行了
    输入命令run mytcl.tcl就进入调试,具体调试根vc差不多,呵呵,不用我罗嗦了,一些常用的如下图所示,其他的你看英文就知道意思了。祝好运

    June 22

    在xwindows里面怎样复制

    直接单击鼠标左键从左向右选择就是复制了,然后可以粘贴到其他地方。:)是不是很简单

    June 15

    NS技巧18

    怎样从trace文件中获得从节点a发送到b的数据报经历的路径?

    当然你也可以利用这种方法查找你数据报在什么地方丢了,方便你解决类似问题。

    命令如下面所示:

    $ gawk ' $14=="[a:0" && $15~/b:0/ {print}' dasele.tr

     

    其中$14,$15代表dasele.tr文件中的第14列和15列(以空格分开),如:

    s 69.530259667 _115_ AGT  --- 326 Mrpqos 0 [0 0 0 0] ------- [115:0 23:0 32 0]中s是第一列,69.530259667时第二列... ...[115:0时第14列,以空格分开各列

     

    举例:

    Candy@CandySeaSon /cygdrive/d/my_programs/ns2/test/mrpqos

    $ gawk ' $14=="[115:0" && $15~/23:0/ {print}' dasele.tr

    s 69.530259667 _115_ AGT  --- 326 Mrpqos 0 [0 0 0 0] ------- [115:0 23:0 32 0]

    r 69.530259667 _115_ RTR  --- 326 Mrpqos 0 [0 0 0 0] ------- [115:0 23:0 32 0]

    s 69.530259667 _115_ RTR  --- 326 Mrpqos 20 [0 0 0 0] ------- [115:0 23:0 30 44]

     

    r 69.535174494 _44_ RTR  --- 326 Mrpqos 20 [13a 2c 73 800] ------- [115:0 23:0 3

    0 44]

    f 69.535174494 _44_ RTR  --- 326 Mrpqos 20 [13a 2c 73 800] ------- [115:0 23:0 2

    9 90]

    r 69.537091728 _90_ RTR  --- 326 Mrpqos 20 [13a 5a 2c 800] ------- [115:0 23:0 2

    9 90]

    f 69.537091728 _90_ RTR  --- 326 Mrpqos 20 [13a 5a 2c 800] ------- [115:0 23:0 2

    8 23]

    r 69.538990075 _23_ AGT  --- 326 Mrpqos 20 [13a 17 5a 800] ------- [115:0 23:0 2

    8 23]

     

     从上面的代码可知道从节点115到节电23的路径是:115-〉44-〉90-〉23。

    June 09

    我的实验中间结果

    这是我实验中间一过程的图形,这部分功能将网络中的节点动态的划分为若干个域,每一个域有一个相当于服务器的代理统一管理,节点如果移动到一个域中便自动注册到相应的服务器上。其中不同颜色和形状代表属于不同的域,节点上面的标号为其服务器代理的编号,是动态变化的。服务器代理的颜色是黑色的。

     

    June 03

    NS2分析17

    setdest的参数说明

    <original 1999 CMU version (version 1)>
     ./setdest      -v <1> -n <nodes> -p <pause time> -M <max speed>
                    -t <simulation time> -x <max X> -y <max Y>

    OR
    <modified 2003 U.Michigan version (version 2)>
     ./setdest      -v <2> -n <nodes> -s <speed type> -m <min speed> -M <max speed>
                    -t <simulation time> -P <pause type> -p <pause time> -x <max X>
    -y <max Y>
                  其中M参数必不可少,不然出现错误;如果你要是用pause type和speed type一定要加上 -v 2,不然的话可是要报错的。具体参数的意义参见setdest.cc里面有具体介绍

    还有就是如果你要生成的节点较多,你就要有足够的耐性,因为昨天我生成了一个scen-150n-0p-3m-20M-400t-1000-1000的场景用了足足3个半小时,而且cpu利用率始终是100%,我的电脑配置迅驰1.5G,768M,几乎什么别的都干不了,郁闷

                                                                                     Web Counter

    June 02

    NS分析16

       模拟过程中突然退出的一种解决办法

         我在我的程序调试过程中曾经遇到过程序运行过程中异常退出的问题,就是什么提示也没有就突然结束了,后来经过分析我的问题是recv函数中,对于接收到的有些类型的数据包没有进行任何处理导致的,如果你要是遇到这样的问题,可以具体分析一下是不是所有类型的数据包你都考虑到了,或许会能解决你的问题:)

      如果你按照上面的方法你的问题没有得到解决,也很正常,毕竟我的是一种特殊的情况:(也希望把你的问题的解决方法告诉我,谢谢

    NS分析15

    路由层怎样上传数据的

    参见aodv.cc

      1.在aodv.h中声明

    PortClassifier *dmux_;

    2.if (ch->ptype() != PT_AODV && ch->direction() == hdr_cmn::UP &&

           ((u_int32_t)ih->daddr() == IP_BROADCAST)

                  || ((u_int32_t)ih->daddr() == here_.addr_)) {

           dmux_->recv(p,0);  //传递给分类器

           return;

    3. 分类器处理数据包

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

    {

           NsObject* node = find(p);//查找节点的是否存在

           if (node == NULL) {

                  /*

                   * XXX this should be "dropped" somehow.  Right now,

                   * these events aren't traced.

                   */

                  Packet::free(p);

                  return;

           }

           node->recv(p,h);//让节点接受

    4.节点接受后

    . void NsObject::recv(Packet *p, const char*)

    {

           Packet::free(p);

    }

    NS技巧14

    怎么调用无线节点的路由协议(如AODV)中的command()里面的函数

     

    例如,我的路由协议myrtagent的command()里面有 seta方法如下面红色字体所示。则在tcl脚本中可以用一下方式调用这个方法;

    [$node_(0) agent 255] seta 10

    [$node_(0) agent 255]表示获得node_(0)的255端口的代理(协议)

    然后再调用这个代理的seta函数。

    Flood::command(int argc, const char*const* argv) {

        Tcl& tcl = Tcl::instance();

        if(argc == 2) {     

           if(strncasecmp(argv[1], "id", 2) == 0) {

               cout<<"The ip addr is "<<argv[4]<<endl;

               tcl.resultf("mflood:%d", index_);

               return TCL_OK;

           }

           else if (strcmp(argv[1], "geta") == 0){

                cout<<"haha geta :"<<a<<endl;

                return TCL_OK;

           }

           else if (strcmp(argv[1], "uptarget") == 0) {

               if (uptarget_ != 0)

                  tcl.result(uptarget_->name());

               return (TCL_OK);

           }

        } else if(argc == 3) {

           if(strcmp(argv[1], "index_") == 0) {

               index_ = atoi(argv[2]);

               return TCL_OK;

           } else if(strcmp(argv[1], "log-target") == 0 || strcmp(argv[1], "tracetarget") == 0) {

               logtarget = (Trace*) TclObject::lookup(argv[2]);

               if(logtarget == 0) return TCL_ERROR;

               return TCL_OK;

           }

           else if (strcmp(argv[1], "seta") == 0){

               a=atoi(argv[2]);            

               return TCL_OK;

           }

           else if (strcmp(argv[1], "uptarget") == 0) {

               if (*argv[2] == '0') {

                  target_ = 0;

                  return (TCL_OK);

               }

               uptarget_ = (NsObject*)TclObject::lookup(argv[2]);

               if (uptarget_ == 0) {

                  tcl.resultf("no such object %s", argv[2]);

                  return (TCL_ERROR);

               }

               return (TCL_OK);

           }

        else if (strcasecmp (argv[1], "port-dmux") == 0) {

                     TclObject *obj;

                      port_dmux_ = (NsObject *) obj;

                     return TCL_OK;

            } 

        }

        return Agent::command(argc, argv);

    }

    NS技巧13

    九.怎样使用ns自己的链表

    1.头文件  #include<lib/bsd-list.h>

    2.初始化

    1). 在节点中添加,包括了指向前驱和后继的节点。

    #define LIST_ENTRY(type)                                    

    struct {                                                      

        type *le_next;      /* next element */                    

        type **le_prev;     /* address of previous next element */    

    }

      2).定义一个链表,链表的类型为type,表头为lh_first

        #define LIST_HEAD(name, type)                                       

    struct name {                                                       

           type *lh_first;      /* first element */       

    }

    3)初始化链表

    #define     LIST_INIT(head) {                                 

        (head)->lh_first = NULL;                               

    }

    4)插入节点

    #define LIST_INSERT_AFTER(listelm, elm, field) {               

        if (((elm)->field.le_next = (listelm)->field.le_next) != NULL)     

               (listelm)->field.le_next->field.le_prev =         

                   &(elm)->field.le_next;                           

        (listelm)->field.le_next = (elm);                           

        (elm)->field.le_prev = &(listelm)->field.le_next;         

    }

     

    #define LIST_INSERT_BEFORE(listelm, elm, field) {                   

        (elm)->field.le_prev = (listelm)->field.le_prev;            

        (elm)->field.le_next = (listelm);                           

        *(listelm)->field.le_prev = (elm);                          

        (listelm)->field.le_prev = &(elm)->field.le_next;         

    }

     

    #define LIST_INSERT_HEAD(head, elm, field) {                           

        if (((elm)->field.le_next = (head)->lh_first) != NULL)         

               (head)->lh_first->field.le_prev = &(elm)->field.le_next;\

        (head)->lh_first = (elm);                               

        (elm)->field.le_prev = &(head)->lh_first;                    

    }

    5)删除节点

    #define LIST_REMOVE(elm, field) {                                \

        if ((elm)->field.le_next != NULL)                           \

               (elm)->field.le_next->field.le_prev =                     \

                   (elm)->field.le_prev;                        \

        *(elm)->field.le_prev = (elm)->field.le_next;                \

    }

    6)一个例子

      1)定义节点类型

    class MFlood_RTEntry {

        friend class MFlood_RTable;

        friend class MFlood;

     

    public:

        MFlood_RTEntry();

        MFlood_RTEntry(nsaddr_t src,u_int32_t seq);

        bool       isNewSeq(u_int32_t seq);    // old -> false, new->true

        void        addSeq(u_int32_t seq);       // add a seqno to seqno array(rt_seqnos)

       

    protected:

        LIST_ENTRY(MFlood_RTEntry) rt_link;

     

        nsaddr_t src_;

    //  u_int32_t seq_;

     

        u_int32_t              rt_seqnos[REM_SEQ_COUNT]; //seqno array

        u_int32_t       max_seqno;   //max seqno

        u_int32_t       min_seqno;   //max seqno

        u_int16_t              seq_it;    // seqno's iterator

    };

    2)建立一个链表节点类型为MFlood_RTEntry的链表 rthead

      LIST_HEAD(, MFlood_RTEntry) rthead;

    3)初始化链表rheadNULL

    LIST_INIT(&rthead)

    (4) 怎样使用

    MFlood_RTEntry* 

    MFlood_Rtable::rt_lookup(nsaddr_t id) {

      Mflood_RTEntry *rt = rthead.lh_first;//获取链表表头

      for(; rt; rt = rt->rt_link.le_next) {

             if(rt->src_ == id)

                    break;

      }

      return rt;

    }

    5)删除节点

    void

    MFlood_RTable::rt_delete(nsaddr_t id) {

      MFlood_RTEntry *rt = rt_lookup(id);

      if(rt) {

             LIST_REMOVE(rt, rt_link);

             delete rt;

      }

    }

    6)插入节点

    rt = new MFlood_RTEntry(ih->saddr(), fh->seq_);

                  LIST_INSERT_HEAD(&rtable_.rthead,rt,rt_link);      

     

    NS技巧12

     tr文件中的CBK错误最根求源(路由层协议以aodv为例)

    tr文件中的纪录:

    D 122.040067803 _4_ RTR  CBK 257 Mrpqos 20 [13a 21 4 800] ------- [4:0 0:0 30 33]

    D 122.073627803 _4_ RTR  CBK 258 Mrpqos 20 [13a 20 4 800] ------- [4:0 27:0 30 32]

    1.追根求源,问题所在分析

    经过查找CBK在aodv.cc的下列函数中使用,下面 printf("%%%%drop typen\n");语句是为了判断错误的类型。

    AODV::rt_ll_failed(Packet *p) {

    struct hdr_cmn *ch = HDR_CMN(p);

    struct hdr_ip *ih = HDR_IP(p);

    aodv_rt_entry *rt;

    nsaddr_t broken_nbr = ch->next_hop_;

     

    #ifndef AODV_LINK_LAYER_DETECTION

    printf("%%%%drop type1\n");

     drop(p, DROP_RTR_MAC_CALLBACK);

    #else

     

     /*

      * Non-data packets and Broadcast Packets can be dropped.

      */

    //因为我的数据包不含有实际数据所以在下面DARA_PACKET()函数的判断中被丢弃了

    //所以关键就是修改者个函数,具体修改参见 2.修改DATA_PACKET(ch->ptype())

      if(! DATA_PACKET(ch->ptype()) ||

         (u_int32_t) ih->daddr() == IP_BROADCAST) {

         printf("%%%%drop type2\n %d",ch->ptype());//测试丢包具体原因所在。

        drop(p, DROP_RTR_MAC_CALLBACK);

        return;

      }

      log_link_broke(p);

        if((rt = rtable.rt_lookup(ih->daddr())) == 0) {

           printf("%%%%drop type3\n");

        drop(p, DROP_RTR_MAC_CALLBACK);

        return;

      }

      log_link_del(ch->next_hop_);

     

    #ifdef AODV_LOCAL_REPAIR

      /* if the broken link is closer to the dest than source,

         attempt a local repair. Otherwise, bring down the route. */

     

     

      if (ch->num_forwards() > rt->rt_hops) {

        local_rt_repair(rt, p); // local repair

        // retrieve all the packets in the ifq using this link,

        // queue the packets for which local repair is done,

        return;

      }

      else 

    #endif // LOCAL REPAIR  

     

      {

      printf("%%%%drop type4\n");

        drop(p, DROP_RTR_MAC_CALLBACK);

        // Do the same thing for other packets in the interface queue using the

        // broken link -Mahesh

    while((p = ifqueue->filter(broken_nbr))) {

        printf("%%%%drop type5\n");

         drop(p, DROP_RTR_MAC_CALLBACK);

        }  

        nb_delete(broken_nbr);

      }

     

    #endif // LINK LAYER DETECTION

    }

     

    2.修改DATA_PACKET(ch->ptype())

     

     

    #define DATA_PACKET(type) ( (type) == PT_TCP || \

                                (type) == PT_TELNET || \

                                (type) == PT_CBR || \

                                (type) == PT_AUDIO || \

                                (type) == PT_VIDEO || \

                                (type) == PT_ACK || \

                                (type) == PT_SCTP || \

                                (type) == PT_SCTP_APP1 || \

                                //解决问题的关键所在!!!!

                                (type) == PT_MRPQOS \

                                )

     3.通过上述方法就解决了我的丢包问题,你的可能不一样,但可以通过类似的方法找出问题的原因,并加以解决。

     

    May 26

    NS技巧11

    转发数据包都需要设置什么?

        我们需要改变一下参数

            ch->addr_type()=NS_AF_INET;

           ch->direction()=hdr_cmn::DOWN;

           send(p);

    NS-tcl奇怪问题

    谁对谁错?你能看出他们的区别吗?

    set hda 10

    1./错误代码??就是编译通不过的代码

    if {$hda==0} {

         $node_ color  red

       }

       elseif {$hda==1} {

         $node_ color  blue

       } elseif {$hda==2} {

         $node_ color  yellow

       }

       elseif {$hda==3} {

         $node_ color  brown

       }

       elseif {$hda==4} {

         $node_ color  tan

       }

       else{

         $node_ color  gold

       }

    2./////////////////////下面是正确代码

    if {$hda == 0} {

          $node_ color  red

       } elseif {$hda == 1} {

         $node_ color  blue

       } elseif {$hda == 2} {

         $node_ color  yellow

       } elseif {$hda == 3} {

         $node_ color  brown

       } elseif {$hda == 4} {

         $node_ color  tan

       }  else {

         $node_ color  gold

       }

    NS技巧10

    怎样在c++中获得节点地址(ID)?

     

     

    Tcl& tcl = Tcl::instance();

    tcl.evalc("$node set id");

    const char* addr = tcl.result();

    int node_id = atoi(addr));

     节点的id便保存到了node_id中.

    NS技巧9

    怎样改变无线网络中802.11的能量状态?

     

    # Power vs. Range

     

    # Assume AT&T's Wavelan PCMCIA card -- Chalermek

     

    # Pt_ = 8.5872e-4; // For 40m transmission range.

     

    # Pt_ = 7.214e-3; // For 100m transmission range.

     

    # Pt_ = 0.2818; // For 250m transmission range.

     

    # Pt_ = pow(10, 2.45) * 1e-3; // 24.5 dbm, ~ 281.8mw

     

    Phy/WirelessPhy set Pt_ 8.5872e-4

    NS技巧8

    一.怎么样广播数据

    根据AODV中recv()函数的代码,我们可以知道,只需要将IP包头的目的地址设为广播地址即可,ih->daddr() != IP_BROADCAST

    void

    AODV::recv(Packet *p, Handler*) {

    //访问通用以及IP包头

    struct hdr_cmn *ch = HDR_CMN(p);

    struct hdr_ip *ih = HDR_IP(p);

     

     assert(initialized());

     //assert(p->incoming == 0);

     // XXXXX NOTE: use of incoming flag has been depracated; In order to track direction of pkt flow, direction_ in hdr_cmn is used instead. see packet.h for details.

     

     if(ch->ptype() == PT_AODV) {

       ih->ttl_ -= 1;

       recvAODV(p);

       return;

     }

     

     

     /*

      *  Must be a packet I'm originating...

      */

    if((ih->saddr() == index) && (ch->num_forwards() == 0)) {

     /*

      * Add the IP Header

      */

       ch->size() += IP_HDR_LEN;

       // Added by Parag Dadhania && John Novatnack to handle broadcasting

       if ( (u_int32_t)ih->daddr() != IP_BROADCAST)

         ih->ttl_ = NETWORK_DIAMETER;

    }

     /*

      *  I received a packet that I sent.  Probably

      *  a routing loop.

      */

    else if(ih->saddr() == index) {

       drop(p, DROP_RTR_ROUTE_LOOP);

       return;

     }

     /*

      *  Packet I'm forwarding...

      */

     else {

     /*

      *  Check the TTL.  If it is zero, then discard.

      */

       if(--ih->ttl_ == 0) {

         drop(p, DROP_RTR_TTL);

         return;

       }

     }

    // Added by Parag Dadhania && John Novatnack to handle broadcasting

     if ( (u_int32_t)ih->daddr() != IP_BROADCAST)

       rt_resolve(p);

     else

       forward((aodv_rt_entry*) 0, p, NO_DELAY);

    }