⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 script.hh

📁 Click is a modular router toolkit. To use it you ll need to know how to compile and install the sof
💻 HH
字号:
// -*- c-basic-offset: 4 -*-#ifndef CLICK_SCRIPT_HH#define CLICK_SCRIPT_HH#include <click/element.hh>#include <click/timer.hh>#include <click/variableenv.hh>CLICK_DECLS/*=cScript(INSTRUCTIONS...)=s controlscript a Click router configuration=ionormally none=dThe Script element implements a simple scripting language useful forcontrolling Click configurations.  Scripts can set variables, call handlers,wait for prodding from other elements, and stop the router.=head1 INSTRUCTIONSEach configuration argument is an I<instruction> (except for optionalkeywords; see below).  Script generally processes these instructionssequentially.=head2 Handler InstructionsIn all cases, text arguments are subject to substitutions; see below.  Manyinstructions come in two forms, as in C<set> and C<setq>, C<read> andC<readq>, and C<write> and C<writeq>.  The non-C<q> forms performsubstitutions on the text, but do not remove any quotes from the result, whilethe C<q> forms perform substitutions and then remove a layer of quoting.  Forexample, 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=over 8=item 'C<set> VAR TEXT', 'C<setq> VAR TEXT'Sets the script variable $VAR to TEXT.=item 'C<init> VAR TEXT', 'C<initq> VAR TEXT'Initializes the script variable $VAR to TEXT.  The assignment happens exactlyonce, when the Script element is initialized.  Later the instruction has noeffect.=item 'C<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 theargument begins with > or >>, then the text is written or appended to thespecified FILE.  In the kernel, the text is written to the system log.If C<print>'s argument starts with a letter, '@', or '_', then it is treatedas a read handler.  Otherwise, a layer of quotes is removed and the result isprinted.  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=item 'C<printn> [>FILE | >>FILE] [TEXT | HANDLER]'Like C<print>, but does not append a newline.=item 'C<read> HANDLER [ARGS]', 'C<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, theconfiguration 'Idle -> c::Counter -> Idle; Script(read c.count)' would printprint this to standard error:   c.count:   0Contrast the 'C<print>' instruction.=item 'C<write> HANDLER [ARGS]', 'C<writeq> HANDLER [ARGS]'Call a write handler.  The handler's return status is available in followinginstructions as the '$?' variable.=back=head2 Blocking Instructions=over 8=item 'C<pause> [COUNT]'Block until the Script element's 'step' handler is called COUNT times.  COUNTdefaults to 1.=item 'C<wait> TIME'Wait for TIME seconds, or until a step, whichever comes first; then go to thenext instruction.  TIME has microsecond precision.=back=head2 Control Instructions=over 8=item 'C<label> LABEL'Defines a label named LABEL.=item 'C<goto> LABEL [CONDITION]'Transfers control to the named label.  Script elements detect loops; if anelement's script appears to be looping (it executes 1000 goto instructionswithout blocking), the script is disabled.  If CONDITION is supplied, then thebranch executes only when CONDITION is true.Also, 'C<goto exit [CONDITION]>' and 'C<goto end [CONDITION]>' end executionof the script, like 'C<exit>' and 'C<end>' respectively.  'C<goto begin[CONDITION]>' transfers control to the first instruction, like 'C<loop>'.'C<goto error [CONDITION]>' ends execution of the script with an error, like'C<error>'.=item 'C<loop>'Transfers control to the first instruction.=item 'C<end>'End execution of this script.  In signal scripts, 'C<end>' causes the scriptto be reinstalled as a signal handler.  In packet scripts, 'C<end>' emitsthe packet on output 0.=item 'C<exit>'End execution of this script.=item 'C<return> [VALUE]', 'C<returnq> [VALUE]'End execution of this script.  In passive scripts, VALUE is returned as thevalue of the C<run> handler.  In packet scripts, VALUE is the port on whichthe packet should be emitted.=item 'C<error> [MSG]', 'C<errorq> [MSG]'End execution of the script and indicate an error.  The optional error messageMSG is reported if given.=back=head1 SCRIPT TYPESScripts come in several types, including active scripts, which start runningas soon as the configuration is loaded; passive scripts, which run only whenprodded; signal scripts, which run in response to a signal; and driverscripts, which are active scripts that also control when the driver stops.The optional TYPE keyword argument is used to select a script type.  The typesare:=over 8=item C<ACTIVE>The script starts running as soon as the router is initialized.  This isthe default.=item C<PASSIVE>The script runs in response to a handler, namely the C<run> handler.Passive scripts can help build complex handlers from existing simple ones; forexample, here's a passive script whose C<s.run> read handler returns the sumof two Counter handlers.   ... c1 :: Counter ... c2 :: Counter ...   s :: Script(TYPE PASSIVE,          return $(add $(c1.count) $(c2.count)))Within the script, the C<$args> variable equals the C<run> handler'sarguments.  C<$1>, C<$2>, etc. equal the first, second, etc. space-separatedportions of C<$args>, and C<$#> equals the number of space-separatedarguments.=item C<PACKET>The script runs in response to a packet push event.  Within the script, theC<$input> variable equals the packet input port.  The script's return valueis used as the output port number.=item C<PROXY>The script runs in response to I<any> handler (except Script's predefinedhandlers).  Within the script, the C<$0> variable equals the handler's name.Also, the C<$write> variable is "true" if the handler was called as a writehandler.  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.=item C<DRIVER>The script manages the Click driver's stop events.  See DriverManager formore information.=item C<SIGNAL> SIGNO...User-level only: The script runs in response to the signal(s) specifiedby the SIGNO argument(s).  Each SIGNO can be an integer or a signal name, suchas INT or HUP.  Soon after the driver receives a named signal, this scriptwill run.  The signal handler is automatically blocked until the script runs.The signal script will be reinstalled atomically as long as the scriptcompletes without blocking.  If it blocks, however, the signal script will notbe installed from the blocking point until the script completes.  If multipleScript elements select the same signal, all the scripts will run.=back=head1 SUBSTITUTIONSText in most Script instructions undergoes variable substitution.  Referencesto script variables, such as 'C<$x>', are replaced by the variable text.Additionally, the form 'C<$(HANDLER [ARG...])>' can be used to interpolate aread handler's value.  Variable and handler references can be nested insidea 'C<$(...)>' 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 arithmetichandlers.   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 requirethe 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);=h step write-onlyAdvance the instruction pointer past the current blocking instruction (C<pause> or C<wait>).  A numeric argument will step past that many blocking instructions.=h goto write-onlyMove the instruction pointer to the specified label.=h run read/writeRun the script.  If the script ends with a 'C<return>' instruction, then thehandler returns with that value.=h add "read with parameters"Useful for arithmetic.  Adds a space-separated list of integers; for example,'C<add 10 5 2>' returns "C<17>".  (At user level, the arithmetic andcomparison operators can parse floating-point numbers as well as integers.)=h sub "read with parameters"Subtracts a space-separated list ofnumbers; for example, 'C<sub 10 5 2>' returns"C<3>".=h mul, div, idiv "read with parameters"Multiplies or divides a space-separated list of numbers and returns theresult.  At user level, the 'C<idiv>' handler truncates its result to aninteger and returns that, whereas the 'C<div>' handler returns afloating-point number; in the kernel, 'C<idiv>' and 'C<div>' both performinteger division.=h mod, rem "read with parameters"Returns the remainder of two space-separated numbers; for example, 'C<mod 7 3>'returns "C<1>".  'C<mod>' expects integer operands and returns the integermodulus.  At user level, 'C<rem>' implements floating-point remainder; in thekernel, it is the same as 'C<mod>'.=h eq, ne, lt, gt, le, ge "read with parameters"Compares two parameters and returns the result.  For example, 'C<eq 10 0xA>'returns "C<true>", and 'C<le 9 8>' returns "C<false>".  If either parametercannot be interpreted as a number, performs a string comparison in bytewiselexicographic order.  For example, 'C<eq 10x 10x>' returns "C<true>".=h not "read with parameters"Useful for true/false operations.  Parses its parameter as a Boolean andreturns its negation.=h and, or "read with parameters"Useful for true/false operations.  Parses all parameters as Booleans andreturns their conjunction or disjunction, respectively.=h if "read with parameters"Expects three space-separated parameters, the first a Boolean.  Returns thesecond parameter if the Boolean is true, or the third parameter if the Booleanis false.=h in "read with parameters"Returns true if the first space-separated argument equals any of the otherarguments, using string comparison.  For example, 'C<in foo bar foo>'returns "C<true>".=h sprintf "read with parameters"Parses its parameters as a space-separated list of arguments.  The firstargument is a format string; the remaining arguments are formattedaccordingly.  For example, 'C<sprintf "%05x" 127>' returns "C<0007F>".=h random "read with parameters"Given zero arguments, returns a random integer between 0 and RAND_MAX.  Givenone argument N, returns a random integer between 0 and N-1.  Given twoarguments N1 and N2, returns a random integer between N1 and N2.=h readable, writable "read with parameters"Parses its parameters as a space-separated list of handler names.  Returnstrue if all the named handlers exist and are readable (or writable).=h now rReturns the current timestamp.=h cat "read with parameters"User-level only.  Argument is a filename; reads and returns the file'scontents.  This handler is "private," meaning that it is not accessible viaControlSocket.=a DriverManager*/class Script : public Element { public:    Script();    ~Script();    static void static_initialize();    static void static_cleanup();    const char *class_name() const	{ return "Script"; }    const char *port_count() const	{ return "-/-"; }    const char *processing() const	{ return PUSH; }    int configure(Vector<String> &, ErrorHandler *);    int initialize(ErrorHandler *);    void add_handlers();    void push(int port, Packet *p);    void run_timer(Timer *);    enum Insn {	INSN_INITIAL, INSN_WAIT_STEP, INSN_WAIT_TIME, // order required	INSN_PRINT, INSN_PRINTN, INSN_READ, INSN_READQ, INSN_WRITE, INSN_WRITEQ,	INSN_SET, insn_setq, INSN_INIT, insn_initq, INSN_SAVE, INSN_APPEND,	INSN_STOP, INSN_END, INSN_EXIT, INSN_LABEL, INSN_GOTO, INSN_RETURN,	insn_returnq, insn_error, insn_errorq,	INSN_WAIT_PSEUDO, INSN_LOOP_PSEUDO    };  private:    enum Type {	type_active, type_driver, type_signal, type_passive, type_proxy,	type_push    };    enum {	max_jumps = 1000, STEP_NORMAL = 0, STEP_ROUTER, STEP_TIMER, STEP_JUMP,	LABEL_EXIT = -1, LABEL_END = -2, label_error = -3, LABEL_BEGIN = 0    };    Vector<int> _insns;    Vector<int> _args;    Vector<int> _args2;    Vector<String> _args3;    Vector<String> _vars;    String _run_handler_name;    String _run_args;    int _run_op;    int _insn_pos;    int _step_count;    int _type;    int _write_status;#if CLICK_USERLEVEL    Vector<int> _signos;#endif    Timer _timer;    int *_cur_steps;    struct Expander : public VariableExpander {	Script *script;	ErrorHandler *errh;	bool expand(const String &, int vartype, int quote, StringAccum &) const;    };    enum {	ST_STEP = 0, ST_RUN, ST_GOTO,	AR_ADD = 0, AR_SUB, AR_MUL, AR_DIV, AR_IDIV, ar_mod, ar_rem,	AR_LT, AR_EQ, AR_GT, AR_GE, AR_NE, AR_LE, // order is important	AR_FIRST, AR_NOT, AR_SPRINTF, ar_random, ar_cat,	ar_and, ar_or, ar_now, ar_if, ar_in, ar_readable, ar_writable    };    void add_insn(int, int, int = 0, const String & = String());    int step(int nsteps, int step_type, int njumps, ErrorHandler *errh);    int complete_step(String *retval);    int find_label(const String &) const;    int find_variable(const String &name, bool add);    static int step_handler(int, String&, Element*, const Handler*, ErrorHandler*);    static int arithmetic_handler(int, String&, Element*, const Handler*, ErrorHandler*);    static int star_write_handler(const String&, Element*, void*, ErrorHandler*);    friend class DriverManager;    friend class Expander;};CLICK_ENDDECLS#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -