| 36 | In this step, we define an application definition (i.e. a "wrapper") for our original application. In this example, we take "ping" as our original application. |
| 37 | |
| 38 | The following code should be saved into a file "pingWrapper.rb" in the same directory as the experiment scripts that would use it: |
| 39 | {{{ |
| 40 | # Define a new application |
| 41 | # The following declaration defines a new application which as a URI 'pingWrapper' |
| 42 | # and the name 'pingApp' |
| 43 | |
| 44 | defApplication('pingWrapper', 'pingApp') {|app| |
| 45 | |
| 46 | app.shortDescription = "This is a simple wrapper application around tcpdump" |
| 47 | app.path="/bin/ping" |
| 48 | |
| 49 | # Here we define the "properties" of this application, i.e. the parameters that |
| 50 | # it supports and which we would like to access |
| 51 | # Ping has many parameters, however in this example, we are only interested in |
| 52 | # the following four ones. |
| 53 | |
| 54 | # defProperty has the following signature: |
| 55 | # defProperty ( name, description, mnemonic, options ) |
| 56 | # - 'name' is interpreted as the long parameter for the command (e.g. "--help") |
| 57 | # - 'mnemonic' is the short parameter call (e.g. ?h will result in "-h") |
| 58 | # - 'options' is a Hash of options for this parameter: |
| 59 | # :type => <type> |
| 60 | # is the parameter types, any of ':string' or ':integer' |
| 61 | # or ':boolean' or 'nil' |
| 62 | # :dynamic => true | false |
| 63 | # true property can be changed at run-time |
| 64 | # :use_name => true | false |
| 65 | # if false then print only the parameter value and do |
| 66 | # not print either 'name' or 'mnemonic' when calling the command |
| 67 | # :order => integer |
| 68 | # Order the property according to integer when calling the command |
| 69 | |
| 70 | # This is the ping destination. It is a string and its value is not prefixed by any |
| 71 | # "--options" or "-X", thus we set ':use_name' to false |
| 72 | # |
| 73 | app.defProperty("dst", "Destination Address or Name", nil, |
| 74 | {:dynamic => false, :type => :string, :use_name => false}) |
| 75 | |
| 76 | # This is the number of ping packet to send. It is an integer, and on the command line |
| 77 | # it should be prefixed by "-c", hence the use of '?c' |
| 78 | # |
| 79 | app.defProperty("count", "Number of probe packet to send", ?c, |
| 80 | {:dynamic => false, :type => :integer}) |
| 81 | |
| 82 | # similar as previous comment... |
| 83 | app.defProperty("flood", "Flood packets", ?f, |
| 84 | {:dynamic => false, :type => :boolean}) |
| 85 | app.defProperty("interval", "Time interval between packets in a flood", ?i, |
| 86 | {:dynamic => false, :type => :integer}) |
| 87 | } |
| 88 | }}} |
| 89 | |
| 91 | |
| 92 | In this step, we define a prototype that would use and specialize the above "pingWrapper" application. For the purpose of this example, we will define two independent different prototype. |
| 93 | |
| 94 | The first one is "agressivePing". It specializes the "pingWrapper" application into one that sends by default a fixed high amount of probes with minimal interval between them, thus effectively flooding the destination. This application could be used to get a coarse quick estimation of the packet drop rate on a link. |
| 95 | |
| 96 | The second one is "gentlePing". It specializes the "pingWrapper" application into one that sends by default 5 probes with 1s interval (default ping interval). This application could be used to test reachability between two nodes with minimal link disruption. |
| 97 | |
| 98 | The following two code blocks should be saved into two separate files "agressivePing.rb" and "gentlePing.rb" in the same directory as the previous application definition: |
| 99 | {{{ |
| 100 | # Define a new prototype |
| 101 | # This prototype is an instance/specialization of the above 'pingWrapper' application |
| 102 | # |
| 103 | |
| 104 | defPrototype("aggressivePing") { |proto| |
| 105 | |
| 106 | proto.name = "aggressivePing" |
| 107 | proto.description = "A node that flood packets to a destination to quiclky determine packet drop rates" |
| 108 | |
| 109 | # Here we specify which property of the base application we would like to use |
| 110 | # AND what are the default value we would like to give them. |
| 111 | |
| 112 | # 'destination' is a mandatory parameter of ping, thus we do not set any default value |
| 113 | proto.defProperty('destination', 'Name or IP address of the destination') |
| 114 | |
| 115 | # This is a agressive ping, so we set the default probe number to 1000, we also set the |
| 116 | # flooding behavior as 'true' by default, along with an interval of 0 |
| 117 | # |
| 118 | proto.defProperty('numPacket', 'Number of probe packets to flood', 1000) |
| 119 | proto.defProperty('enableFlood', 'Enable packet flooding', true) |
| 120 | proto.defProperty('pktInterval', 'Time interval between packets in a flood', 0) |
| 121 | |
| 122 | # Here we bind this prototype with the "pingWrapper" application definition |
| 123 | # And we also bind the properties that we decided to use and gave default values to |
| 124 | # |
| 125 | proto.addApplication("pingApp", "pingWrapper") { |listener| |
| 126 | listener.bindProperty('dst', 'destination') |
| 127 | listener.bindProperty('count', 'numPacket') |
| 128 | listener.bindProperty('flood', 'enableFlood') |
| 129 | listener.bindProperty('interval', 'pktInterval') |
| 130 | } |
| 131 | } |
| 132 | }}} |
| 133 | |
| 134 | and |
| 135 | |
| 136 | {{{ |
| 137 | # Define another prototype |
| 138 | # This prototype is another instance/specialization of the above 'pingWrapper' application |
| 139 | # |
| 140 | |
| 141 | defPrototype("gentlePing") { |proto| |
| 142 | |
| 143 | proto.name = "gentlePing" |
| 144 | proto.description = "A node that pings a destination to quiclky assess its reachability" |
| 145 | |
| 146 | # This is a gentle ping, so we set the default probe number to 5, we also set the |
| 147 | # flooding behavior as 'false' by default, and we ignore the 'interval' parameter |
| 148 | # |
| 149 | proto.defProperty('destination', 'Name or IP address of the destination') |
| 150 | proto.defProperty('numPacket', 'Number of probe packets to flood', 5) |
| 151 | proto.defProperty('enableFlood', 'Enable packet flooding', false) |
| 152 | |
| 153 | proto.addApplication("pingApp", "pingWrapper") { |listener| |
| 154 | listener.bindProperty('dst', 'destination') |
| 155 | listener.bindProperty('count', 'numPacket') |
| 156 | listener.bindProperty('flood', 'enableFlood') |
| 157 | } |
| 158 | } |
| 159 | }}} |