next up previous contents
Next: recv() Up: Agent Previous: Constructor   Contents


command()

The next piece of code is a little bit more complicated. It consists of the implementation of the command() method that our agent inherites from the Agent class.

protoname/protoname.cc

1:  int
2:  Protoname::command(int argc, const char*const* argv) {
3:      if (argc == 2) {
4:          if (strcasecmp(argv[1], "start") == 0) {
5:              pkt_timer_.resched(0.0);
6:              return TCL_OK;
7:          }
8:          else if (strcasecmp(argv[1], "print_rtable") == 0) {
9:              if (logtarget_ != 0) {
10:                 sprintf(logtarget_->pt_->buffer(), "P %f _%d_ Routing Table",
11:                     CURRENT_TIME,
12:                     ra_addr());
13:                 logtarget_->pt_->dump();
14:                 rtable_.print(logtarget_);
15:             }
16:             else {
17:                 fprintf(stdout, "%f _%d_ If you want to print this routing table "
18:                     "you must create a trace file in your tcl script",
19:                     CURRENT_TIME,
20:                     ra_addr());
21:             }
22:             return TCL_OK;
23:         }
24:     }
25:     else if (argc == 3) {
26:         // Obtains corresponding dmux to carry packets to upper layers
27:         if (strcmp(argv[1], "port-dmux") == 0) {
28:             dmux_ = (PortClassifier*)TclObject::lookup(argv[2]);
29:             if (dmux_ == 0) {
30:                 fprintf(stderr, "%s: %s lookup of %s failed\n",
31:                     __FILE__,
32:                     argv[1],
33:                     argv[2]);
34:                 return TCL_ERROR;
35:             }
36:             return TCL_OK;
37:         }
38:         // Obtains corresponding tracer
39:         else if (strcmp(argv[1], "log-target") == 0 ||
40:             strcmp(argv[1], "tracetarget") == 0) {
41:             logtarget_ = (Trace*)TclObject::lookup(argv[2]);
42:             if (logtarget_ == 0)
43:                 return TCL_ERROR;
44:             return TCL_OK;
45:         }
46:     }
47:     // Pass the command to the base class
48:     return Agent::command(argc, argv);
49: }

argv[0] contains the name of the method (always ``cmd'', see chapter 3 [2]) being invoked, argv[1] is the requested operation, and argv[2..argc-1] are the rest of the arguments which were passed. Within this function we must code some mandatory operations as well as any other operation that we want to make accesible from Tcl. As an example we will code an operation called print_rtable which dumps the contents of the routing table's to the trace file.

We focus our code only in cases where we have two or three arguments, so that you can see how to process them. Each case must finish its execution returning either TCL_OK (if everything was fine) or TCL_ERROR (if any error happened).

Lines 4-7 describe a mandatory command that we always have to implement:start. The expected behaviour of this command is to configure the agent to begin its execution. In our case it starts its packet sending timer. We should implement here all the required actions that the routing agent must perform in order to begin its operation.

Lines 8-23 implement our print_rtable command. We firstly check if logtarget_ is initialized (line 9). Then we dump the table into the trace file as is showed in lines 10-13. To understand this piece of code it would be useful that you take a look into the trace/trace.h header file. There is where the Trace class is defined. It has a reference to pt_ of the BaseTrace class. This last class implements buffer() and dump() functions which are used to get the variable where output is buffered and to flush that buffer to the output file respectively. Finally, line 14 calls the print() function of our routing table for writing into trace file its own content. The TCL code below shows how to execute the print_rtable operation at a certain time from a simulation script. It assumes that ns_ contains an instance of Simulator and node_ is a Node created by ns_. We are passing 255 as argument because this is the number of the port where a routing agent is attached to.

simulation.tcl

1: $ns_ at 15.0 "[$node_ agent 255] print_rtable"

Another mandatory command to implement is port-dmux. Its implementation is provided in lines 27-37. As explained in chapter 3 of [2], NS stores a reference to every compiled object (C++ object) in a hash table to provide a fast access to each of them given its name. We make use of that facility in line 28 to obtain a PortClassifier object given its name.

Similarly, there is another mandatory operation called tracetarget (note that we a allow it to be called log-target as well) which simply obtains a Trace object given its name.

If we don't know how to process the requested command, we delegate this responsability to base class, as we do in line 48.


next up previous contents
Next: recv() Up: Agent Previous: Constructor   Contents
Francisco J. Ros 2004-12-30