| 1 | = How to design a TG for OTG software = |
| 2 | |
| 3 | ''Zhibin Wu'' |
| 4 | |
| 5 | == Introduction == |
| 6 | |
| 7 | The traffic generator component is current not an independent part of the OTG software. Therefore, whenever a new kind of traffic generator is to be designed, the new codes have to be compiled with other source files under a same Makefile. Thus, it has to obey some common interface requirements. |
| 8 | |
| 9 | == Interface between TG and OTG == |
| 10 | |
| 11 | The standard interface between TG and OTG is a member function of the Generator class called “'''nextPacket (Packet *p)'''”. The parameter is a pointer to an empty Packet object and the generator need to set following properties of this object: |
| 12 | * '''size''': packet's payload size which does not include any frame headers. |
| 13 | * '''timestamp''': this is the absolute timing value since the generator is created and initialized. The OTG program will check this timestamp and determine the exact time to transmit this packet into socket interface. In other words, the timing difference between the timestamp of current packet and previous packet is the packet arrival interval. This is a float-point number with unit in seconds. |
| 14 | * '''payload''' (optional) |
| 15 | |
| 16 | Whenever this function is called, a packet object is passed as the input parameter. And in the instantiation of this function, the generator should set the above parameters of this packet object. |
| 17 | |
| 18 | To introduce a new traffic generator, these following things have to be done: |
| 19 | |
| 20 | |
| 21 | === Generator Class === |
| 22 | |
| 23 | Every generator derives from the [source:otg/trunk/src/cpp/generator.h#latest Generator] class. This virtual class does not define any member variables. There are two functions the child class must override. |
| 24 | |
| 25 | 1. void init() |
| 26 | 1. bool nextPacket (Packet* p) |
| 27 | The exact implementation of init() function is up to you. This function will be called when the OTG program begins and before the generator creates the first packet. Therefore, some initial parameter setting could be done here. |
| 28 | |
| 29 | === Set Packet Property === |
| 30 | |
| 31 | As the nextPacket function will return a [source:otg/trunk/src/cpp/packet.h#latest Packet] point to the generated packet. The designed generator must (and only need) set two properties of this Packet object by using the following functions of the Packet class. |
| 32 | |
| 33 | 1. void setPayloadSize (int size) |
| 34 | 1. void setTimeStamp (double stamp) |
| 35 | 1. int fillPayload(int size, char *inputstream); |
| 36 | |
| 37 | The first two functions are self-evident. The third functino read a certain ''size'' of bytes from the ''inputstream'' into the payload of this packet. If successful, return value is 0. |
| 38 | |
| 39 | == Interface with POPT command line parser == |
| 40 | |
| 41 | To let the user to specify the parameters of this new generator from command-line, some interface functions need to be defined. Currently, the OTG software uses the POPT library to create user interface. The interface with POPT is usually conducted by a callback function which would call those parameter-setting interface functions of the generator. Please refer to [source:otg/trunk/src/cpp/auto/cbr_generator_helper.h#latest cbr_generator_helper.h] and [source:otg/trunk/src/cpp/auto/cbr_generator_helper.cpp#latest cbr_generator_helper.cpp] files for creating similar interface for your new generator. In the future, those interface functions will be automatically generated from an xml file which defines the generator. |
| 42 | |
| 43 | ''Important Note: if you allow user to change generator parameter on-the-fly. Design the interface functions carefully to be sure this change take effects in run-time.'' |
| 44 | |
| 45 | === getOptions Function === |
| 46 | |
| 47 | getOptions() function is to be defined as a member function of the new generator class. This function will be called in otg.cpp file to generate the available generator-specific options for user to choose. |
| 48 | |
| 49 | |
| 50 | == Compile with OTG == |
| 51 | |
| 52 | The new source files are going to be included in the Makefile. Then the '''make''' process would create the OTG with the new TG component. |
| 53 | In the future, a generator definition XML file has to be included in the make process to automatically download the codes for command-line interface. |
| 54 | |
| 55 | == Design Example == |
| 56 | |
| 57 | If you are implementing traffic generator "foo", you should do the following: |
| 58 | |
| 59 | 1. Create file "foo_generator.cpp" and "foo_generator.h" |
| 60 | 1. Create file "foo_generator_helper.cpp" and "foo_generator_helper.h" |
| 61 | 1. Modify "otg.cpp" file |
| 62 | 1. Modify "Makefile" |
| 63 | |
| 64 | |
| 65 | For example, in file foo_generator.h, define class: |
| 66 | |
| 67 | {{{ |
| 68 | #ifndef FOO_GENERATOR_H |
| 69 | #define FOO_GENERATOR_H |
| 70 | |
| 71 | #include <popt.h> |
| 72 | #include "packet.h" |
| 73 | #include "generator.h" |
| 74 | |
| 75 | |
| 76 | /** FOO GENERATOR Module |
| 77 | * |
| 78 | */ |
| 79 | |
| 80 | class FooGenerator: public Generator |
| 81 | { |
| 82 | public: |
| 83 | FooGenerator(int size=512); |
| 84 | |
| 85 | /** |
| 86 | * Function to initialize the generator |
| 87 | */ |
| 88 | void init(); |
| 89 | /* Implement virtual methods */ |
| 90 | bool nextPacket(Packet* p); |
| 91 | |
| 92 | // Function to set properties of this generator |
| 93 | void setPacketSize(int size); |
| 94 | /** |
| 95 | * Function to get POPT options for command-line interface |
| 96 | */ |
| 97 | const struct poptOption* getOptions(); |
| 98 | |
| 99 | private: |
| 100 | ... Some private variables |
| 101 | }; |
| 102 | |
| 103 | #endif |
| 104 | }}} |
| 105 | |
| 106 | In file foo_generator.cpp, the implementation of nextPacket () and getOptions() functions are |
| 107 | {{{ |
| 108 | |
| 109 | bool FooGenerator::nextPacket (Packet* p) |
| 110 | { |
| 111 | ... Some generation algorithm |
| 112 | } |
| 113 | |
| 114 | const struct poptOption* FooGenerator::getOptions() |
| 115 | { |
| 116 | return foo_generator_get_options(this, NULL); |
| 117 | } |
| 118 | }}} |
| 119 | |
| 120 | |
| 121 | In file foo_generator_helper.cpp, we design the functions to parse one parameter “packet size” from user input for the foo_generator. |
| 122 | |
| 123 | {{{ |
| 124 | static void |
| 125 | callback( |
| 126 | poptContext con, |
| 127 | enum poptCallbackReason reason, |
| 128 | const struct poptOption * opt, |
| 129 | char * arg, |
| 130 | void * data |
| 131 | ) { |
| 132 | FooGenerator* gen = (FooGenerator*)data; |
| 133 | |
| 134 | if (strcmp(opt->longName, "size") == 0) { |
| 135 | gen->setPktSize(atoi(arg)); |
| 136 | } |
| 137 | } |
| 138 | |
| 139 | |
| 140 | const struct poptOption* |
| 141 | foo_generator_get_options( |
| 142 | const FooGenerator* gen, |
| 143 | const char* prefix |
| 144 | ) { |
| 145 | struct poptOption* opts = (struct poptOption*)calloc(3, sizeof(struct poptOption)); |
| 146 | struct poptOption* p = opts; |
| 147 | popt_set(p++, NULL, NULL, '\0', POPT_ARG_CALLBACK, (void*)callback, 0, (char*)gen); |
| 148 | popt_set(p++, prefix, "size", '\0', POPT_ARG_INT, NULL, 0, "Size of packet", "bytes"); |
| 149 | |
| 150 | popt_set(p); |
| 151 | return opts; |
| 152 | } |
| 153 | }}} |
| 154 | |
| 155 | In the beginning of otg.cpp [[BR]] |
| 156 | See: |
| 157 | {{{ |
| 158 | struct poptOption options_phase1[] = { |
| 159 | POPT_AUTOHELP |
| 160 | { "protocol", '\0', POPT_ARG_STRING, NULL, 0, "Name of protocol", "[tcp|udp|raw_packet]"}, |
| 161 | { "generator", '\0', POPT_ARG_STRING, NULL, 0, "Name of generator", "[cbr|expoo]"}, |
| 162 | { NULL, 0, 0, NULL, 0 } |
| 163 | }; |
| 164 | }}} |
| 165 | |
| 166 | change the 4th line to |
| 167 | {{{ |
| 168 | { "generator", '\0', POPT_ARG_STRING, NULL, 0, "Name of generator", "[cbr|expoo|foo]"}, |
| 169 | }}} |
| 170 | Also, in |
| 171 | {{{ |
| 172 | Generator* |
| 173 | createGenerator( |
| 174 | char* generator_name |
| 175 | ) { |
| 176 | Generator* gen = NULL; |
| 177 | |
| 178 | if (strcmp(generator_name, "cbr") == 0 ){ |
| 179 | gen = new CBR_Generator(); |
| 180 | }else if(strcmp(generator_name, "expoo") == 0){ |
| 181 | gen = new Expo_Generator(); |
| 182 | }else { |
| 183 | cerr << "Error: Unknown Generator '" << generator_name << "'." << endl; |
| 184 | exit(-1); |
| 185 | } |
| 186 | return gen; |
| 187 | } |
| 188 | }}} |
| 189 | adding... |
| 190 | {{{ |
| 191 | ... |
| 192 | else if(strcmp(generator_name, "foo") == 0){ |
| 193 | gen = new FooGenerator(); |
| 194 | } |
| 195 | ... |
| 196 | }}} |
| 197 | In Makefile |
| 198 | |
| 199 | {{{ |
| 200 | CPP_FILES += ....foo_generator.cpp ….. auto/foo_generator_helper.cpp |
| 201 | }}} |