| | 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 | }}} |