Skip to content
Eddie Kohler edited this page Oct 17, 2017 · 5 revisions

Script Element Documentation

NAME

Script — Click element; script a Click router configuration

SYNOPSIS

Script(INSTRUCTIONS...)

Ports: normally none

DESCRIPTION

The Script element implements a simple scripting language useful for controlling Click configurations. Scripts can set variables, call handlers, wait for prodding from other elements, and stop the router.

INSTRUCTIONS

Each configuration argument is an instruction (except for optional keywords; see below). Script generally processes these instructions sequentially.

Handler Instructions

In all cases, text arguments are subject to substitutions; see below. Many instructions come in two forms, as in set and setq, read and readq, and write and writeq. The non-q forms perform substitutions on the text, but do not remove any quotes from the result, while the q forms perform substitutions and then remove a layer of quoting. For example, assuming the 'c.count' read handler returns 0:

   set x $(c.count)
   print $x             => 0
   set x "$(c.count)"
   print $x             => "0"
   setq x "$(c.count)"
   print $x             => 0
  • 'set VAR TEXT', 'setq VAR TEXT' — Sets the script variable $VAR to TEXT.

  • 'init VAR TEXT', 'initq VAR TEXT' — Initializes the script variable $VAR to TEXT. The assignment happens exactly once, when the Script element is initialized. Later the instruction has no effect.

  • 'export VAR [TEXT]', 'exportq VAR [TEXT]'

    Like init, but also makes the value of script variable VAR available via a read handler named VAR.

  • 'print [>FILE | >>FILE] [TEXT | HANDLER]' — Prints text, or the result of calling a read handler, followed by a newline. At user level, the text is written to the standard output, except that if the argument begins with > or >>, then the text is written or appended to the specified FILE. In the kernel, the text is written to the system log.

    If print's argument starts with a letter, '@', or '_', then it is treated as a read handler. Otherwise, a layer of quotes is removed and the result is printed. For example, assuming the 'c.count' read handler returns "0":

         print c.count     => 0
         print "c.count"   => c.count
         print '"c.count"' => "c.count"
         set x c.count
         print $x          => c.count
         print $($x)       => 0
    
  • 'printq [>FILE | >>FILE] [TEXT | HANDLER]'

    Like print, but unquotes HANDLER

  • 'printn [>FILE | >>FILE] [TEXT | HANDLER]'

    Like print, but does not append a newline.

  • 'printnq [>FILE | >>FILE] [TEXT | HANDLER]'

    Like printn, but unquotes HANDLER

  • 'read HANDLER [ARGS]', 'readq HANDLER [ARGS]'

    Call a read handler and print the handler name and result to standard error. (In the kernel, the result is printed to the system log.) For example, the configuration 'Idle -> c::Counter -> Idle; Script(read c.count)' would print print this to standard error:

         c.count:
         0
    

    Contrast the 'print' instruction.

  • 'write HANDLER [ARGS]', 'writeq HANDLER [ARGS]'

    Call a write handler. The handler's return status is available in following instructions as the '$?' variable.

Blocking Instructions

  • 'pause [COUNT]' — Block until the Script element's 'step' handler is called COUNT times. COUNT defaults to 1.
  • 'wait TIME' — Wait for TIME seconds, or until a step, whichever comes first; then go to the next instruction. TIME has microsecond precision.

Control Instructions

  • 'label LABEL' — Defines a label named LABEL.

  • 'goto LABEL [CONDITION]' — Transfers control to the named label. Script elements detect loops; if an element's script appears to be looping (it executes 1000 goto instructions without blocking), the script is disabled. If CONDITION is supplied, then the branch executes only when CONDITION is true.

    Also, 'goto exit [CONDITION]' and 'goto end [CONDITION]' end execution of the script, like 'exit' and 'end' respectively. 'goto loop [CONDITION]' transfers control to the first instruction, like 'loop'. 'goto error [CONDITION]' ends execution of the script with an error, like 'error'. 'goto stop [CONDITION]' ends execution of the script and asks the driver to stop, like 'stop'.

  • 'loop' — Transfers control to the first instruction.

  • 'end' — End execution of this script. In signal scripts, 'end' causes the script to be reinstalled as a signal handler. In packet scripts, 'end' emits the packet on output 0. An implicit 'end' is executed if execution falls off the end of a script.

  • 'exit' — End execution of this script. In signal scripts, 'exit' will not reinstall the script as a signal handler. In packet scripts, 'exit' will drop the packet.

  • 'stop' — End execution of this script as by 'end', and additionally ask the driver to stop. (A TYPE DRIVER Script, or DriverManager element, can intercept this request.)

  • 'return [VALUE]', 'returnq [VALUE]'

    End execution of this script. In passive scripts, VALUE is returned as the value of the run handler. In packet scripts, VALUE is the port on which the packet should be emitted.

  • 'error [MSG]', 'errorq [MSG]'

    End execution of the script and indicate an error. The optional error message MSG is reported if given.

SCRIPT TYPES

Scripts come in several types, including active scripts, which start running as soon as the configuration is loaded; passive scripts, which run only when prodded; signal scripts, which run in response to a signal; and driver scripts, which are active scripts that also control when the driver stops.

The optional TYPE keyword argument selects a script type. The types are:

  • ACTIVE — The script starts running as soon as the router is initialized. ACTIVE is the default for Script elements without ports.

  • PASSIVE — The script runs in response to a handler, namely the run handler. Passive scripts can help build complex handlers from existing simple ones; for example, here's a passive script whose s.run read handler returns the sum of two Counter handlers.

         ... c1 :: Counter ... c2 :: Counter ...
         s :: Script(TYPE PASSIVE,
                return $(add $(c1.count) $(c2.count)))
    

    Within the script, the $args variable equals the run handler's arguments. $1, $2, etc. equal the first, second, etc. space-separated portions of $args, and $# equals the number of space-separated arguments.

  • PACKET — The script runs in response to a packet push or pull event. Within the script, the $input variable equals the packet input port. The script's return value is used as the output port number. PACKET is the default for Script elements with ports.

  • PROXY — The script runs in response to any handler (except Script's predefined handlers). Within the script, the $0 variable equals the handler's name, and the $write variable is "true" if the handler was called as a write handler. For example, consider:

         s :: Script(TYPE PROXY,
                goto nota $(ne $0 a),
                returnq "you called 'a'",
                label nota,
                goto notb $(ne $0 b),
                returnq "you called 'b'",
                label notb,
                error bad handler);
    

    Calling the read handler "s.a" will return "you called 'a'", calling "s.b" will return "you called 'b'", and anything else will produce a "bad handler" error.

  • DRIVER — The script manages the Click driver's stop events. See DriverManager for more information.

  • SIGNAL SIGNO... — User-level only: The script runs in response to the signal(s) specified by the SIGNO argument(s). Each SIGNO can be an integer or a signal name, such as INT or HUP. Soon after the driver receives a named signal, this script will run. The signal handler is automatically blocked until the script runs. The signal script will be reinstalled atomically as long as the script completes without blocking. If it blocks, however, the signal script will not be installed from the blocking point until the script completes. If multiple Script elements select the same signal, all the scripts will run.

SUBSTITUTIONS

Text in most Script instructions undergoes variable substitution. References to script variables, such as '$x', are replaced by the variable text. Additionally, the form '$(HANDLER [ARG...])' can be used to interpolate a read handler's value. Variable and handler references can be nested inside a '$(...)' block. For example, the following script will print 0, 1, 2, 3, and 4 on separate lines, then exit. Note the use of Script's arithmetic handlers.

   s :: Script(set x 0,
               label begin_loop,
               print $x,
               set x $(s.add $x 1),
               goto begin_loop $(s.lt $x 5),
               stop);

This can be further shortened since local handler references do not require the element name. Thus, "$(s.add ...)" can be written "$(add ...)", as below.

   Script(set x 0,
          label begin_loop,
          print $x,
          set x $(add $x 1),
          goto begin_loop $(lt $x 5),
          stop);

ELEMENT HANDLERS

  • step (write-only) — Advance the instruction pointer past the current blocking instruction (pause or wait). A numeric argument will step past that many blocking instructions.
  • goto (write-only) — Move the instruction pointer to the specified label.
  • run (read/write) — Run the script. If the script ends with a 'return' instruction, then the handler returns with that value.
  • add (read with parameters) — Useful for arithmetic. Adds a space-separated list of integers; for example, 'add 10 5 2' returns "17". (At user level, the arithmetic and comparison operators can parse floating-point numbers as well as integers.)
  • sub (read with parameters) — Subtracts a space-separated list of numbers; for example, 'sub 10 5 2' returns "3".
  • min, max (read with parameters) — Finds the minimum or maximum of a space-separated list of numbers; for example, 'max 5 10 2' returns "10".
  • mul, div, idiv (read with parameters) — Multiplies or divides a space-separated list of numbers and returns the result. At user level, the 'idiv' handler truncates its result to an integer and returns that, whereas the 'div' handler returns a floating-point number; in the kernel, 'idiv' and 'div' both perform integer division.
  • mod, rem (read with parameters) — Returns the remainder of two space-separated numbers; for example, 'mod 7 3' returns "1". 'mod' expects integer operands and returns the integer modulus. At user level, 'rem' implements floating-point remainder; in the kernel, it is the same as 'mod'.
  • neg (read with parameters) — Returns the negative of its numeric parameter.
  • abs (read with parameters) — Returns the absolute value of its numeric parameter.
  • eq, ne, lt, gt, le, ge (read with parameters) — Compares two parameters and returns the result. For example, 'eq 10 0xA' returns "true", and 'le 9 8' returns "false". If either parameter cannot be interpreted as a number, performs a string comparison in bytewise lexicographic order. For example, 'eq 10x 10x' returns "true".
  • not (read with parameters) — Useful for true/false operations. Parses its parameter as a Boolean and returns its negation.
  • and, or (read with parameters) — Useful for true/false operations. Parses all parameters as Booleans and returns their conjunction or disjunction, respectively.
  • nand, nor (read with parameters) — Like "not (and ...)" and "not (or ...)", respectively.
  • if (read with parameters) — Expects three space-separated parameters, the first a Boolean. Returns the second parameter if the Boolean is true, or the third parameter if the Boolean is false.
  • in (read with parameters) — Returns true if the first space-separated argument equals any of the other arguments, using string comparison. For example, 'in foo bar foo' returns "true".
  • sprintf (read with parameters) — Parses its parameters as a space-separated list of arguments. The first argument is a format string; the remaining arguments are formatted accordingly. For example, 'sprintf "%05x" 127' returns "0007F".
  • random (read with parameters) — Given zero arguments, returns a random integer between 0 and RAND_MAX. Given one argument N, returns a random integer between 0 and N-1. Given two arguments N1 and N2, returns a random integer between N1 and N2.
  • length (read with parameters) — Returns the length of its parameter string as a decimal number. For example, 'read abcdef' returns "5".
  • unquote (read with parameters) — Returns its parameter string with one layer of quotes removed.
  • readable, writable (read with parameters) — Parses its parameters as a space-separated list of handler names. Returns true if all the named handlers exist and are readable (or writable).
  • now (read-only) — Returns the current timestamp.
  • cat (read with parameters) — User-level only. Argument is a filename; reads and returns the file's contents. This handler is not accessible via ControlSocket.
  • catq (read with parameters) — User-level only. Like cat, but returns a quoted version of the file.
  • kill (read with parameters) — User-level only. Argument is a signal ID followed by one or more process IDs. Those processes are killed by that signal. This handler is not accessible via ControlSocket. The "$$" variable may be useful when calling kill; it expands to the driver's process ID.
  • get (read with parameters) — The argument is a variable name. Returns the value of that script variable.
  • set (write-only) — The argument is a variable name, followed by a value. Sets the named variable to that value.
  • shift (write-only) — The argument is a variable name, which defaults to args. Shifts the first space-separated argument off the named variable and returns the result.

SEE ALSO

DriverManager

Generated by click-elem2man from ../elements/standard/script.hh:9 on 2017/10/17.

Clone this wiki locally