Monday, October 18, 2010

"init" function of OTCL

The constructor function of a class (object) is: Init


The init instproc is used to initialize a freshly allocated object that is a direct or indirect instance of the class Object. It is normally called by the system (perhaps from more specialized init instprocs) as part of object creation, but may be called by the user.
init interprets its arguments as pairs of option keys and option values. Each option key should be the name of a valid method for the object, preceded by a dash. The method should take one argument. For each option key and option value pair, init calls the method on the object, with the option value as its argument. It returns the empty string.
To customize object creation, write an init instproc for a class, not an alloc proc. If the option key and option value creation syntax is still desired, then call the Object init instproc by using next. This is discussed in the create instproc in OTcl Classes.
% Class Bagel
Bagel
% foreach i {1 2 3 4} {                    
  Bagel instproc $i {v} {puts $v}
}
% Bagel abagel
abagel
% abagel init -1 one -2 two -3 three -4 four!
one
two
three
four!
init is conceptually equivalent to the following.
Object instproc init {args} {                   
  if {[llength $args]%2 != 0} then {            
    error {uneven number of arguments}          
  }                                             
  while {$args != {}} {                         
    set key [lindex $args 0]                    
    if {[string match {-*} $key]} then {        
      set key [string range $key 1 end]         
    }                                           
    set val [lindex $args 1]                    
    if {[catch {$self $key $val} msg]!=0} then {
      set opt [list $self $key $val]            
      error "$msg during $opt"                
    }                                           
    set args [lrange $args 2 end]               
  }                                             
  return {}                                     
}

Demystify TwoRayGround propagation model

In this model, the shadowing fading factor is not considered. Therefore, for a unique distance, the Pr is a determinstic value. Usually, tworayground has two formulas:
  • when d is less than the crossing distance: Free Space model is used.
  • when d is larger than the crossing distance: the follownig formula is applied:
Pr =   PtGtGrht2hr2 / (Ld4)
Based on the default settings in ns-2, we can derive a relationship between Pr and distance
Default parameter in ns-2:
  • Pt = 0.28183815
  • L = 1
  • Antenna Gain : 1
  • Antanna height 1.5m
DistancePr
15m2.81838e-5
20m8.91754e-6
22m6.0908e-6
30m1.7615e-6
60m1.1009e-7
120m6.8808e-9
200m8.9175e-10
210m7.3365e-10
220m6.908e-10
230m5.0986e-10
240m4.3005e-10
250m3.6526e-10
300m1.7615e-10
350m9.5081e-11
400m5.5735e-11
450m3.4795e-11
500m2.2829e-11
550m1.5592e-11
600m1.1009e-11
650m7.993e-12
700m5.9425e-12
750m4.5094e-12

Cross-distnace Effect

In reality, path loss index is only 2 in near distance. Therefore, for near-distance (<25m) , the above formula does not apply. When distance is less than ~25 meter, the Friss model will be used. Check tworayground.cc for detail

Friday, October 8, 2010

Introduction to packet headers and addresses in ns-2

Headers & Addresses in ns-2


 Notice that by default, all packet headers are included.A diagram:

Common-header:
Access method:
 struct hdr_cmn {
        enum dir_t { DOWN= -1, NONE= 0, UP= 1 };
        packet_t ptype_;        // packet type (see above)
        int     size_;          // simulated packet size
        int     uid_;           // unique id
        int     error_;         // error flag
        int     errbitcnt_;     // # of corrupted bits jahn
        int     fecsize_;
        double  ts_;            // timestamp: for q-delay measurement
        int     iface_;         // receiving interface (label)
        dir_t   direction_;     // direction: 0=none, 1=up, -1=down
        // source routing
        char src_rt_valid;

        //Monarch extn begins
        nsaddr_t prev_hop_;     // IP addr of forwarding hop
        nsaddr_t next_hop_;     // next hop for this packet
        int      addr_type_;    // type of next_hop_ addr
        nsaddr_t last_hop_;     // for tracing on multi-user channels

        // called if pkt can't obtain media or isn't ack'd. not called if
        // droped by a queue
        FailureCallback xmit_failure_;
        void *xmit_failure_data_;

        /*
         * MONARCH wants to know if the MAC layer is passing this back because
         * it could not get the RTS through or because it did not receive
         * an ACK.
         */
        int     xmit_reason_;

#define XMIT_REASON_RTS 0x01
#define XMIT_REASON_ACK 0x02

        // filled in by GOD on first transmission, used for trace analysis
        int num_forwards_;      // how many times this pkt was forwarded
        int opt_num_forwards_;   // optimal #forwards
        // Monarch extn ends;

        // tx time for this packet in sec
        double txtime_;
        inline double& txtime() { return(txtime_); }

        static int offset_;     // offset for this header
        inline static int& offset() { return offset_; }
        inline static hdr_cmn* access(const Packet* p) {
                return (hdr_cmn*) p->access(offset_);
        }

       .....
}

hdr_cmn *ch= hdr_cmn::access(pkt); //common header
 What's in common header (refer to  ./common/packet.h)
  • ch->ptype()   :   protocl type. e.g. PT_DSR shows this is a signaling message for DSR protocol, not a normal DATA packet
  • ch->size();
  • ch->direction() : Up or Down
  • ch->uid()
  • ch->iface():  Interface
  • ch->next_hop():    next hop for this packet. IP address in format nsaddr_t*. So, it is amazing to see some codes like, ch->next_hop=MAC_BRPADCST . MAC_BROADCST is defined as #define MAC_BROADCAST ((u_int32_t) 0xffffffff) and nsaddr_t is also deined as int32_t in config.h (typedef int32_t nsaddr_t;   ). Basically, ns2 use 32bit addressing support.


MAC Ethernet Address in 802.11 MAC Header:
Access method:
 struct hdr_mac802_11 {
        struct frame_control    dh_fc;                                       // 2 byte
        u_int16_t               dh_duration;                                 // 2
        u_char                  dh_da[ETHER_ADDR_LEN];                       // 6
        u_char                  dh_sa[ETHER_ADDR_LEN];                       // 6
        u_char                  dh_bssid[ETHER_ADDR_LEN];                    // 6
        u_int16_t               dh_scontrol;                                 // 2
        u_char                  dh_body[0]; // XXX Non-ANSI                  // 1   //not allocate, the address of ....};
 .....

 u_int32_t src,dst;

 struct hdr_mac802_11 *dh = HDR_MAC802_11(p);

//method to get a 32bit general descriptor of address
 dst = ETHER_ADDR(dh->dh_ra);
 src = ETHER_ADDR(dh->dh_ta);

//method to set ....
      int src, dst;
      STORE4BYTE(&dst, (dh->dh_ra));
      STORE4BYTE(&src, (dh->dh_ta));

Ethernet Address is specified in mac.h as (#define ETHER_ADDR_LEN 6 ). Thus, dh_ra and dh_ta are both six-unsinged-character array. Also, there is another defintion for this operation:  #define ETHER_ADDR(x)     (GET4BYTE(x)), so only the last 4 bytes are reassembled for a 32-bit address.
How MAC address is set? The addr() function is defined in the Class MAC, and the index_ is corresponding internal member ( type is integer).

static int MacIndex = 0;

Mac::Mac() :
        BiConnector(), abstract_(0), netif_(0), tap_(0), ll_(0), channel_(0), callback_(0),
        hRes_(this), hSend_(this), state_(MAC_IDLE), pktRx_(0), pktTx_(0)
{
        index_ = MacIndex++;
        bind_bw("bandwidth_", &bandwidth_);
        bind_time("delay_", &delay_);
        bind_bool("abstract_", &abstract_);
}

class Mac : public BiConnector {
public:
   ....  
   inline int addr() { return index_; }
protected:
   ....
   int index_;             // MAC address
   ....

} 

//alos, the  mac-802.11 use index as its mac address to form MAC frames: (see in mac-802_11.cc)
....
STORE4BYTE(&index_, (rf->rf_ta));



Space Sharing in MAC-802.11 header


As in packet.h

#define HDR_MAC802_11(p) ((hdr_mac802_11 *)hdr_mac::access(p))
There is no define of access function of struct hdr_mac802_11. The problem is that, we acccess the header use the struct mac_hdr, and then convert it to a 802.11 header. Thus, the frame space and frame format should have some realtion:
See.

size of mac header is 36 bytes, but size of mac-802.11 header in ns-2 is only 24 bytes.



IP Addr in IP header
Access Method: (refer to ./common/ip.h )

 struct hdr_ip {
        /* common to IPv{4,6} */
        ns_addr_t       src_;
        ns_addr_t       dst_;
        int             ttl_;

        /* Monarch extn */
//      u_int16_t       sport_;
//      u_int16_t       dport_;

        /* IPv6 */
        int             fid_;   /* flow id */
        int             prio_;

        static int offset_;
        inline static int& offset() { return offset_; }
        inline static hdr_ip* access(const Packet* p) {
                return (hdr_ip*) p->access(offset_);
        }

    /* per-field member acces functions */
        ns_addr_t& src() { return (src_); }
        nsaddr_t& saddr() { return (src_.addr_); }
        int32_t& sport() { return src_.port_;}

        ns_addr_t& dst() { return (dst_); }
        nsaddr_t& daddr() { return (dst_.addr_); }
        int32_t& dport() { return dst_.port_;}
        int& ttl() { return (ttl_); }
        /* ipv6 fields */
        int& flowid() { return (fid_); }
        int& prio() { return (prio_); }
};

......

struct ns_addr_t {
        int32_t addr_;
        int32_t port_;
#ifdef __cplusplus p.dest = ID((Address::instance().get_nodeaddr(iph->daddr())),::IP);
  p.src = ID((
        ns_addr_t& operator= (const ns_addr_t& n) {
                addr_ = n.addr_;
                port_ = n.port_;
                return (*this);
        }
        int operator== (const ns_addr_t& n) {
                return ((addr_ == n.addr_) && (port_ == n.port_));
        } p.dest = ID((Address::instance().get_nodeaddr(iph->daddr())),::IP);
  p.src = ID((
#endif // __cplusplus
};


hdr_ip *iph =  hdr_ip::access(packet);

//method to set address
  iph->saddr() = Address::instance().create_ipaddr(p.src.addr, RT_PORT); p.dest = ID((Address::instance().get_nodeaddr(iph->daddr())),::IP);
  p.src = ID((
  iph->sport() = RT_PORT;
  iph->daddr() = Address::instance().create_ipaddr(p.dest.addr, RT_PORT);
  iph->dport() = RT_PORT;
  iph->ttl() = 255;
// method to read address ??
   iph->saddr()
   iph->daddr()
   p.dest = ID((Address::instance().get_nodeaddr(iph->daddr())),::IP);
   p.src = ID((Address::instance().get_nodeaddr(iph->saddr())),::IP);
As seen, ns_addr_t is different from nsaddr_t, it has ip address and port infomation. Just 32 bit is suitable for ip address.

Very Important! All things above IP ( Routing, TCP are) are implemented as Agent. Any agent's message must include an IP header.
The class Agent has functions like addr() and daddr() to get the address of IP header.
 class Agent : public Connector {
 public:
    ....
        inline nsaddr_t& addr() { return here_.addr_; }
        inline nsaddr_t& port() { return here_.port_; }
        inline nsaddr_t& daddr() { return dst_.addr_; }
        inline nsaddr_t& dport() { return dst_.port_; }
  protected:
        ...
        ns_addr_t here_;                // address of this agent
        ns_addr_t dst_;                 // destination address for pkt flow
        ...
}


int
Agent::delay_bind_dispatch(const char *varName, const char *localName, TclObject *tracer)
{
        if (delay_bind(varName, localName, "agent_addr_", (int*)&(here_.addr_), tracer)) return TCL_OK;
        if (delay_bind(varName, localName, "agent_port_", (int*)&(here_.port_), tracer)) return TCL_OK;
        if (delay_bind(varName, localName, "dst_addr_", (int*)&(dst_.addr_), tracer)) return TCL_OK;
        if (delay_bind(varName, localName, "dst_port_", (int*)&(dst_.port_), tracer)) return TCL_OK;

......

Class Hierarchy :  TclObject --->  NSObject ----> Agent


DSR's SR (Source Route) Header
the SR has a path informaton from source to a destination, an SR should have following basic information for a baseline version of DSR protocol:
  • a path of IP or other addressses
  • a type to show this is route-request, route-reply or route-error
  • an ID to distinguish duplicate requests.
struct sr_addr {
        int addr_type;          /* same as hdr_cmn in packet.h */ 
        nsaddr_t addr;

        /*
         * Metrics that I want to collect at each node
         */
        double  Pt_;
};

struct route_request {
        int     req_valid_;     /* request header is valid? */
        int     req_id_;        /* unique request identifier */
        int     req_ttl_;       /* max propagation */
};

struct route_reply {
        int     rep_valid_;     /* reply header is valid? */
        int     rep_rtlen_;     /* # hops in route reply */
        struct sr_addr  rep_addrs_[MAX_SR_LEN];
};

struct route_error {
        int     err_valid_;     /* error header is valid? */
        int     err_count_;     /* number of route errors */
        struct link_down err_links_[MAX_ROUTE_ERRORS];
};

......
class hdr_sr {
private:
        int valid_;             /* is this header actually in the packet?
                                   and initialized? */
        int salvaged_;  /* packet has been salvaged? */

        int num_addrs_;
        int cur_addr_;
        struct sr_addr addrs_[MAX_SR_LEN];

        struct route_request    sr_request_;
        struct route_reply      sr_reply_;
        struct route_error      sr_error_;
...

         inline struct sr_addr* addrs() { return addrs_; }
...
}

//Constructor of Path, convert a SR header into a PATH object
Path::Path(struct hdr_sr *srh)
{ /* make a path from the bits of an NS source route header */
        path = new ID[MAX_SR_LEN];

        if (! srh->valid()) {
                len = 0;
                cur_index = 0;
                return;
        }

        len = srh->num_addrs();
        cur_index = srh->cur_addr();

        assert(len <= MAX_SR_LEN);

        for (int i = 0 ; i < len ; i++)
                path[i] = ID(srh->addrs()[i]);  //note : both type and addr are copied
}


hdr_sr *srh =  hdr_sr::access(packet);
SRPacket p(packet, srh);
p.dest = ID((Address::instance().get_nodeaddr(iph->daddr())),::IP);
p.src = ID((Address::instance().get_nodeaddr(iph->saddr())),::IP);


To get and set SR header, first we need to turn things into a packet of type SRPacket, in this class, route[n] is use to access ID[n], for each ID[n], use   inline nsaddr_t getNSAddr_t() to get this addr;
Normally, all SR-related operation are use "ID" not direct 32bit integer to refer.
How the address get set at the very beginning of the DSR Agent, use those :
SRNodeNew instproc init args {
 ...... 
 $dsr_agent_ addr $address_
 ......

}

Analyze ns-2 trace file

Ns-2 has two options to generate traces with different fomats. Basically, you could use
$ns use-newtrace
to generate the new trace and the detailed explanation could be found in Ns Manual. A very good reference about the trace is the ns-2 wiki page. See: http://nsnam.isi.edu/nsnam/index.php/NS-2_Trace_Formats

By default, old trace format is used. The source code ./trace/cmu-trace.cc needs to be read to understand it completely. For instance, the function format_ip will explain the trace of IP part.
void
CMUTrace::format_ip(Packet *p, int offset)
{
        struct hdr_cmn *ch = HDR_CMN(p);
        struct hdr_ip *ih = HDR_IP(p);

        // hack the IP address to convert pkt format to hostid format
        // for now until port ids are removed from IP address. -Padma.
        int src = Address::instance().get_nodeaddr(ih->saddr());
        int dst = Address::instance().get_nodeaddr(ih->daddr());

    ............

}

void
CMUTrace::format_mac(Packet *p, int offset)
{

else {
                sprintf(pt_->buffer() + offset,
                        " [%x %x %x %x] ",
                        //*((u_int16_t*) &mh->dh_fc),
                        mh->dh_duration,

                        ETHER_ADDR(mh->dh_ra),
                        ETHER_ADDR(mh->dh_ta),


                        GET_ETHER_TYPE(mh->dh_body));
        }
......

}


A typical trace for a CBR traffic is:

s 20.000000000 _0_ AGT  --- 6 cbr 512 [0 0 0 0] ------- [0:0 1:0 32 0] [0] 0 0
r 20.000000000 _0_ RTR  --- 6 cbr 512 [0 0 0 0] ------- [0:0 1:0 32 0] [0] 0 0
s 20.000000000 _0_ RTR  --- 6 cbr 532 [0 0 0 0] ------- [0:0 1:0 32 1] [0] 0 0
s 20.000275000 _0_ MAC  --- 6 cbr 584 [13a 1 0 800] ------- [0:0 1:0 32 1] [0] 0 0
r 20.004947063 _1_ MAC  --- 6 cbr 532 [13a 1 0 800] ------- [0:0 1:0 32 1] [0] 1 0
s 20.004957063 _1_ MAC  --- 0 ACK 38 [0 0 0 0]
r 20.004972063 _1_ AGT  --- 6 cbr 532 [13a 1 0 800] ------- [0:0 1:0 32 1] [0] 1 0
r 20.005261125 _0_ MAC  --- 0 ACK 38 [0 0 0 0]

An AWK script example to analyze the trace and calculate throughput
 
For a topology involve 4 flows with distinguishing source and destination nodes, this following awk script gets throughout data and put in wu.dat file
BEGIN {counter1 = 0; counter2 = 0; counter3 = 0; counter4 = 0;}
$1~/r/ && $2>50 && $2< 100  && /_12_/ && /AGT/  {   counter1 += ($8- 20)
                        size = $8 - 20 }
$1~/r/ && $2>50 && $2 <100 && /_13_/ && /AGT/  {   counter2 += ($8- 20)
                        size = $8 - 20 }
$1~/r/ && $2>50 && $2<100 && /_14_/ && /AGT/  {   counter3 += ($8- 20)
                        size = $8 - 20 }
$1~/r/ && $2>50 && $2<100 && /_15_/ && /AGT/  {   counter4 += ($8- 20)
                        size = $8 - 20 } throughout

END {
      print (size , counter1*8/(50), counter2*8/50, counter3*8/(50), counter4*8/50,
                  (counter1+counter2+counter3+counter4)*8/50 )  >> "wu.dat"}

To analyze the throughout or delay in a finite time duration, we need extract sending and receiving time from the trace file

$2>100 && $2 < 150 && (/_6_/ || /_2_/)  &&  /AGT/    {  print $1, $2, $6  > "dst2.tr" }
$2>100 && $2 <150 && (/_0_/ || /_9_/)  &&  /AGT/    {   print $1, $2, $6  > "dst9.tr" }
$2>100 && $2 <150 && (/_12_/ || /_3_/)  &&  /AGT/    {   print $1, $2, $6  > "dst3.tr" }
$2>100 && $2 <150 && (/_10_/ || /_4_/)  &&  /AGT/    {   print $1, $2, $6  > "dst4.tr" }
$2>100 && $2 <150 && (/_11_/ || /_8_/)  &&  /AGT/    {   print $1, $2, $6  > "dst8.tr" }

The respective new trace files such as "dst2.tr" will keep the sending or receiving time, "s'" or "r" label and, node's MAC address. From those data, we could use a program to calculate the average throughputor mean value of end-to-end delay of the flow.

The C source file (delay.c) to calculate delay is given as below:



#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
  FILE *fin, *fout, *fout2;
  int pkt_index[1000]; 
  double pkt_send_time[1000];
  int head;
  //int tail;
  /* make sure it is large enough to hold all temprary data! */
  int i,j,num;
  double tm, tm_delay, total_delay, avg_delay, var_delay;
  int idx;
  char type;
  int flag;
  int num_sent;
  
  head = 0;
  for ( i=0; i<1000; i++)
  {
     pkt_index[i]  = -1;
     pkt_send_time[i] = 0.0f;
  }
  
  fin = fopen(argv[1], "r");
  fout = fopen (argv[2], "w");
  fout2 = fopen ( argv[3],"a");
  
  if(fin==NULL) {
    printf("Error: can't open file.\n");
    return 1;
  }
  else {
    printf("File opened successfully.\n");

    i = 0 ;  
    num  = 0;  
    num_sent = 0;
    while(!feof(fin)) 
    { 
      /* loop through and store the numbers into the array */
      fscanf(fin, "%c %lf %d \n", &type,&tm, &idx);
      //printf( "%f\n", tm);
      
  if ( type == 's' )
  {
   //addentry(idx, tm);
   pkt_index[head] = idx;
   pkt_send_time[head] = tm;
   head++;
   if ( head == 1000 ) head = 0;
   num_sent++;
     
     
  }
  else if ( type == 'r' )
  {
   flag = 0;
   for ( j=0; j< 1000; j++)
   {
    
    if (  pkt_index[j] == idx )
    {
    //printf("match,%f, %f\n!" ,tm, pkt_send_time[j]);
    tm_delay =  tm - pkt_send_time[j];
    flag = 1;
    break;
    } 
   }
   //addentry to output
   if ( flag == 1)
   {
   fprintf( fout,"%d %lf \n", idx, tm_delay ); 
   total_delay += tm_delay;    
   num++;
   }
  }
      i++;
    }
    avg_delay = total_delay / num ;
    fprintf(fout2,"Number of entries read: %d\n", i);
    fprintf(fout2,"Number of entries sent: %d\n", num_sent);
    fprintf(fout2,"Number of entries received:  %d\n", num);
    fprintf(fout2,"average delay of entries :  %lf\n", avg_delay);
    
    fclose(fin);
    fclose(fout);
  
    
    //finally, calcualte variance
    fout = fopen ( argv[2], "r") ;
    if ( fout == NULL ) return -1;
    var_delay = 0;
    while (!feof(fout))
    {
       fscanf(fout, "%d %lf\n", &idx ,&tm);
       var_delay += ( tm - avg_delay  ) * (tm - avg_delay);    
    }
    var_delay /= num;     
    fprintf(fout2, "variance of  delay is :  %lf\n", var_delay);
    fclose (fout);
    fclose (fout2);
    
    return 0;
  }
} 

To use this C code:
$ gcc delay.c -o delaycal
$ ./delaycal dst2.tr wu0.dat wu1.dat

NS-2 Tutorials

Ns-2 is a widely used tool to simulate the behavior of wired and wireless networks. Useful information about ns-2 can be found at:

Thursday, October 7, 2010

Traffic Pattern Generation

cbrgen


Random traffic connections of TCP and CBR can be setup between mobilenodes using a traffic-scenario generator script. This traffic generator script is available under ~ns/indep-utils/cmu-scen-gen and is called cbrgen.tcl. It can be used to create CBR and TCP traffics connections between wireless mobilenodes. In order to create a traffic-connection file, we need to define the type of traffic connection (CBR or TCP), the number of nodes and maximum number of connections to be setup between them, a random seed and incase of CBR connections, a rate whose inverse value is used to compute the interval time between the CBR pkts. So the command line looks like the following:

ns cbrgen.tcl [-type cbr|tcp] [-nn nodes] [-seed seed] [-mc connections][-rate rate] >output.tcl

The start times for the TCP/CBR connections are randomly generated with a maximum value set at 180.0s, thus the simulation time is at least 180 seconds. And the number of nodes has no relationship to the maximum number of connections (mc), we can have 10 nodes, also 10 connections as one node could have multiple simultaneous connections to other nodes. The parameter "rate" means how many packets per second, thus, for CBR traffic, the packet intervel is the reversal of this parameter. And for TCP traffic, we don't have to specify rate, ftp connections are going to be used. the default packet size is 512B. Actully, we can change all this in the "output.tcl" file.Note that there is no guarantee that the number of connections are created and the actual nodes involved as source and sink. A typical generated CBR traffic file looks like:
#
# 2 connecting to 3 at time 82.557023746220864
#
set udp_(0) [new Agent/UDP]
$ns_ attach-agent $node_(2) $udp_(0)
set null_(0) [new Agent/Null]
$ns_ attach-agent $node_(3) $null_(0)
set cbr_(0) [new Application/Traffic/CBR]
$cbr_(0) set packetSize_ 512
$cbr_(0) set interval_ 0.25
$cbr_(0) set random_ 1
$cbr_(0) set maxpkts_ 10000
$cbr_(0) attach-agent $udp_(0)
$ns_ connect $udp_(0) $null_(0)
$ns_ at 82.557023746220864 "$cbr_(0) start"
......
# 
#Total sources/connections: 4/6
#
The last lines shows how many actual connections are created and how many nodes are used for the source.

Node Movement and Topology Generation

To simulate a mobility scenario, the nodes' positions at every time instant need to be determined.


Instead of specifying and controlling each nodes' position and movement pattern, we may use a CMU tool "setdest" to generate large number of nodes and there movements. The tool use a random waypoint model.
Setdest
Setdest tool is used to generate the positions of nodes and their moving speed and moving directions.
The syntax is:

 setdest -v 1 -n $numnodes -p $pt -M $maxspeed -t $simtime -x $maxx -y $maxy
for example: 

    setdest -v 1 -n 50 -p 0 -M 20 -t 900 -x 1500 -y 300
will generate a 1500*300 topology with 50 nodes random distributed labeled by a XY(Z) coordinates.  

(Note that, there is a bug in the README file, which gives a wrong option for specifying the speed, we should use "-M" instead of "-s" ).
In the output, you can find that: after the initial positions are given, the nodes are specified with their movement destination and speed. Then, the initial distance (hop counts) information are counted by a GOD. 
Currently, the god object is used only to store an array of the shortest number of hops required to reach from one node to an other. The god object does not calculate this on the fly during simulation runs, since it can be quite time consuming. The information is loaded into the god object from the movement pattern file (this file)..
Then, the nodes are going to move during this 900-second simulation scenario. During this, the distance (hop-counts) information is going to change, thus, the following lines are going to show this recent change. Note that the distance is calculated based on a nominal radio range as "250" meters. The god information should not be available to any of the node. Thus, for a routing protocol, it has to discover the distance by itself with some mechanism.
It's possible that a node reaches its destination before the simulation timer ends. Thus, it needs to re-specify a new direction and speed for it. Also, the average pause time is a parameter to allow a node stop to move in a destination before moving again.
Finally, there are some statistics about this movement file? During the simulation, some nodes get isolated from all other nodes which results one count of "destination unreachable". Also, all route changes and link changes are calculated.
# nodes: 50, pause: 0.00, max speed: 20.00, max x: 1500.00, max y: 300.00
#
$node_(0) set X_ 1472.239335818631
$node_(0) set Y_ 218.102475038104
$node_(0) set Z_ 0.000000000000
$node_(1) set X_ 266.329091949493
$node_(1) set Y_ 188.988756134562
$node_(1) set Z_ 0.000000000000
.....
$ns_ at 0.000000000000 "$node_(0) setdest 298.258250355189 34.553480936942 5.763540789209"
$ns_ at 0.000000000000 "$node_(1) setdest 783.793876303622 280.181784294036 16.832727003192"
$ns_ at 0.000000000000 "$node_(2) setdest 978.836090908830 151.467060345492 19.354908025316"
$ns_ at 0.000000000000 "$node_(3) setdest 376.126888262665 139.747808400435 11.497476206039"
$ns_ at 0.000000000000 "$node_(4) setdest 370.541780738321 185.032792269909 8.002013555825"
$ns_ at 0.000000000000 "$node_(5) setdest 1463.652810766312 132.618506062927 17.607998988233"
$ns_ at 0.000000000000 "$node_(6) setdest 1020.046295404814 40.982731716802 15.434148765705"
......
$god_ set-dist 0 1 6
$god_ set-dist 0 2 1
$god_ set-dist 0 3 4
$god_ set-dist 0 4 2
$god_ set-dist 0 5 4
$god_ set-dist 0 6 8
$god_ set-dist 0 7 6
......
$ns_ at 0.141920608238 "$god_ set-dist 17 24 2"
$ns_ at 0.165720133690 "$god_ set-dist 3 15 1" 
$ns_ at 0.263269271549 "$god_ set-dist 1 46 2" 
$ns_ at 0.263269271549 "$god_ set-dist 7 46 2" 
$ns_ at 0.263269271549 "$god_ set-dist 12 46 1"
$ns_ at 0.263269271549 "$god_ set-dist 25 46 3"
$ns_ at 0.263269271549 "$god_ set-dist 46 47 3"
$ns_ at 0.314230786054 "$god_ set-dist 5 42 5" 
......
$ns_ at 12.602131706040 "$god_ set-dist 16 36 2"
$ns_ at 12.623221733243 "$node_(12) setdest 424.679916546080 186.581540202946 5.803287072825"
$ns_ at 12.682532746855 "$god_ set-dist 18 40 3"
.....
$ns_ at 899.907548331028 "$god_ set-dist 32 40 1"
$ns_ at 899.932142983319 "$god_ set-dist 22 40 1"
$ns_ at 899.991403308054 "$god_ set-dist 3 29 1"
#
# Destination Unreachables: 429
#
# Route Changes: 72037
#
# Link Changes: 11892
#
# Node | Route Changes | Link Changes
# 0 | 2709 | 433
# 1 | 3098 | 467
# 2 | 2651 | 496
# 3 | 3398 | 642Setdest
# 4 | 3036 | 548
# 5 | 2755 | 252
# 6 | 3471 | 601
for generate scenarios in a patch, we could use following shell scripts.
#!/bin/csh
unset noclobber
set outdir = wzb-scen

set maxspeed = 1
set numnodes = 50
set maxx = 1500
set maxy = 300
set simtime = 900

foreach pt (5 10 15 20 25 30 40 50)
foreach scen ( 1 2 3 4 5)
echo scen $scen : setdest -n $numnodes -p $pt -M $maxspeed -t $simtime \
      -x $maxx -y $maxy
time ./setdest -n $numnodes -p $pt -M $maxspeed -t $simtime \
      -x $maxx -y $maxy \
      >$outdir/scen-${maxx}x${maxy}-${numnodes}-${pt}-${maxspeed}-${scen}
echo
end
end