Search code examples
awkns2

awk code to calculate throughput for some nodes


In ns-2 trace files for wireless nodes, I want to calculate throughput for some nodes at once. How to make if condition for specific nodes? The problem is because of "_" between node number. It is very time consuming if I check node one by one because of thousands number of nodes. Here the example of trace files :

r 1.092948833 _27_ MAC  --- 171 tcp 1560 [0 1a 19 0] ------- [4194333:0 4194334:0 32 4194334] [37 0] 1 0 [-]
r 1.092948833 _28_ MAC  --- 172 tcp 1560 [0 1a 19 0] ------- [4194333:0 4194334:0 32 4194334] [38 0] 1 0 [-]
r 1.092948833 _25_ MAC  --- 173 tcp 1560 [0 1a 19 0] ------- [4194333:0 4194334:0 32 4194334] [39 0] 1 0 [-]
r 1.092948833 _21_ MAC  --- 174 tcp 1560 [0 1a 19 0] ------- [4194333:0 4194334:0 32 4194334] [40 0] 1 0 [-]
r 1.092948833 _36_ MAC  --- 175 tcp 1560 [0 1a 19 0] ------- [4194333:0 4194334:0 32 4194334] [41 0] 1 0 [-]
r 1.092948833 _29_ MAC  --- 176 tcp 1560 [0 1a 19 0] ------- [4194333:0 4194334:0 32 4194334] [42 0] 1 0 [-]

My awk code :

action = $1;
sta = $3;
time = $2;
dest = $4;
app = $7;
pkt_size = $8;

    if ( action == "r" && dest == "MAC" && app == "tcp" && time > 1 && ((sta >= "_6_" 
    && sta <= "_30_") || (sta >= "_36_"))) {
        if (start_ == 0) start_ = time;
        if (time > end_) end_ = time;
        sum_ = sum_ + pkt_size;
    }

But it doesn't work


Solution

  • You appear to be doing something like:

    if ($1=="r" && $7=="cbr" && $3=="_1_") {
        sec[int($2)]+=$8;
    };
    

    from the fil2.awk in a paper titled "ns-2 for the impatient".

    Though you want to match on different fields, and match on a range of nodes, I'm going to assume you want output similar to:

    sec[i] throughput[i]
    

    from the same paper where sec[i] is the second and throughput[i] here would be like your sums for each second's worth of packet sizes.

    The sec array from that snippet is storing packet sums for rounded seconds (rounding provided by int()) which means you don't need a start_ or end_.

    Since you want to compare multiple nodes, _ can be added to FS to make comparisons easier. Here's a version of your script modified to produce an output over seconds for the nodes you want to compare binned by seconds:

    #!/usr/bin/awk -f
    
    BEGIN {FS="[[:space:]]|_"} # use posix space or underscore for FS
    
    {
    action = $1
    time = $2
    sta = $4   # shifted here because underscores are delimiters
    dest = $6
    app = $10
    pkt_size = $11
    
    if( action == "r" && dest == "MAC" && app == "tcp" &&
        time > 1 && ((sta >= 6 && sta <= 30) || (sta >= 36))) {
            sec[int(time)]+=pkt_size
        }
    }
    END { for( i in sec ) print i, sec[i] }
    

    Notice that the sta tests are numeric now instead of string comparisons. If I put that into an executable awk file called awko and run as awko data against your data I get:

    1 9360
    

    as the output.