====== Element and Configure Parsing ====== See [[http://www.read.cs.ucla.edu/click/doxygen/classElement.html|the Doxygen documentation on class Element]] for information on moving packets, handling packets, running tasks. ===== Handlers ===== Handlers are access points through which users can interact with elements in a running Click router, or with the router as a whole. Read and write handlers behave like files in a file system, while LLRPCs provide a remote procedure call interface. ==== Read and Write Handler Overview ==== Read and write handlers appear to the user like files in a file system, or alternatively, like a limited RPC mechanism that uses ASCII strings for data transfer. To the element programmer, a read handler is simply a function that takes an element and returns a String; a write handler is a function that takes an element and a String and returns an error code. ''String (*ReadHandler) (Element *element, void *thunk) '' Function Type Read handler functions have this type. When the user accesses a read handler on an element, Click calls some ReadHandler function and passes the element as an argument. The thunk argument contains callback data specified when the handler was added. The function's String return value is passed back to the user. '' int (*WriteHandler) (const String &data, Element *element, void *thunk, ErrorHandler *errh) '' Function Type Write handler functions have this type. When the user accesses some element write handler by passing in a string, Click calls some WriteHandler function and passes the data and the relevant element as arguments. The thunk argument contains callback data specified when the handler was added. The return value is an error code: zero when there are no errors, and the negative of some errno value when there is an error. More detailed information about any errors should be reported to the errh argument. Each handler has an ASCII name. Handler names must be unique within each element; for example, there can be at most one x read handler in a given element. A given name can be shared by a read handler and a write handler, however. Such a handler pair is colloquially called a "read/write handler", although its two components need not have anything to do with one another. There is currently no way to pass data to a read handler or return data from a write handler. Use LLRPCs if you need a more RPC-like read-write interface. Note that read and write handler functions are regular functions, not virtual functions. Often, therefore, handler functions are defined as private static member functions in the relevant element class. Read and write handlers need not use ASCII-formatted data. Most existing handlers do format their data in ASCII, however, and use cp_uncomment to ignore leading and trailing whitespace and comments (see Quoting and Unquoting). You may want to do the same for consistency's sake. Be careful when writing handlers that modify element state, or read state that packet processing can modify. On an SMP machine, a handler may be called on one processor while packets are passing through the router on another processor. Furthermore, multiple read handlers and safe LLRPCs (see LLRPC Overview) may be active simultaneously on different processors. Write handlers are serialized with respect to other handlers and LLRPCs (but not packet processing). That is, no other handler or LLRPC will proceed while a write handler is active. ==== Adding Handlers ==== Use Element's add_read_handler and add_write_handler methods to add handlers for an element. You will generally call these methods only from within your element's add_handlers method, although nothing prevents you from adding handlers at any time. ''void add_read_handler (const String &name, ReadHandler func, void *thunk) '' Method on Element Adds a read handler named name for this element. When the handler is accessed, func will be called with this and thunk as parameters. '' void add_write_handler (const String &name, WriteHandler func, void *thunk) '' Method on Element Adds a write handler named name for this element. When the handler is accessed, func will be called with the relevant data, this, thunk, and an ErrorHandler as parameters. To create a read/write handler, call add_read_handler and add_write_handler and supply the same handler name. These methods simply forward their requests to static add_read_handler and add_write_handler methods on the Router class. Call those methods directly to add handlers to other elements, or to add global handlers. ''void add_read_handler (const Element *element, const String &name, ReadHandler func, void *thunk) '' Static Method on Router '' void add_write_handler (const Element *element, const String &name, WriteHandler func, void *thunk) '' Static Method on Router Adds a read or write handler for element, or a global read or write handler if element is null. The handler is named name. The change_handler_flags method lets you change a handler's flags word (see Handler Objects). ''void change_handler_flags (Element *element, const String &name, uint32_t clear_flags, uint32_t set_flags) '' Static Method on Router Changes the flags for element's name handler, or the global name handler if element is null. The flags are changed by first clearing the bits set in clear_flags, then setting the bits set in set_flags. This method fails and returns -1 when the specified handler does not exist; otherwise, it returns 0. ==== Default Read and Write Handlers ==== Every element automatically provides five handlers, `class', `name', `config', `ports', and `handlers'. There is no need to add these handlers yourself. The default handlers behave as follows: `class' Returns the element's class name, as returned by class_name(), followed by a newline. Example result: "ARPQueriern". `name' Returns the element's name, as returned by id(), followed by a newline. Example result: "arpq_0n". `config' Returns the element's configuration string. If the configuration string does not end in newline, the hander appends a newline itself. Example result: "18.26.7.1, 00:00:C0:4F:71:EFn". If can_live_reconfigure returns true, `config' is also a write handler, and writing to it reconfigures the element. `ports' Returns a multi-line string describing the element's ports and what they are connected to. The string has the form M input[s] ... M input port descriptions, one per line ... N output[s] ... N output port descriptions, one per line ... Each port description lists the port's processing type, a dash, and then a comma-separated list of all the ports to which this port is connected. The processing type is either push or pull; formerly agnostic ports are indicated by a trailing tilde (push~ or pull~). Example result: 1 input push~ - Strip@2 [0] 2 outputs push~ - [0] GetIPAddress@4 push - [0] Print@7 If Click was compiled with statistics collection enabled, the dash on each line is replaced by a packet count. `handlers' Returns a string listing the element's visible handlers, one per line. Each line contains the handler name, a tab, and then either r, w, or rw, depending on whether the handler is read-only, write-only, or read/write. Example result for an InfiniteSource element, which has many handlers: scheduled r tickets r reset w count r active rw burstsize rw limit rw data rw handlers r ports r config rw name r class r ==== Accessing Handlers Internally ==== Element handlers are stored in the relevant Router as objects of type Router::Handler. (This design allows handler objects to be shared between elements when possible.) Handlers are often referred to by index; indexes between 0 and Router::FIRST_GLOBAL_HANDLER - 1 refer to element handlers, while indexes above Router::FIRST_GLOBAL_HANDLER refer to global handlers. Indexes less than 0 are used for error returns, such as nonexistent handlers. Router methods translate between handler indexes and Router::Handler objects, and find handlers or handler indexes given handler names. === The Router::Handler Type === The Router::Handler type allows you to check a handler's properties and call the handler. All of its methods are const; you must go through Router to change a handler's properties. Router::Handler objects do not contain element references, since they are shared among elements. That means you can't easily find the element (if any) to which a particular Router::Handler is attached. ''const String & name () const '' Method on Router::Handler Returns the handler's name. '' uint32_t flags () const '' Method on Router::Handler Returns the handler's flags as an integer. The lower bits of the flags word are reserved for the system, and four bits are reserved for drivers, but the upper bits (at least 16) are left uninterpreted, and may be used by elements. The first user flag bit is called Router::Handler::USER_FLAG_0; its position in the word equals Router::Handler::USER_FLAG_SHIFT. To change a handler's flags, use the Router::change_handler_flags method (see Changing Handler Flags). ''bool readable () const '' Method on Router::Handler Returns true iff this handler is readable. ''bool read_visible () const '' Method on Router::Handler Returns true iff this handler is readable, and that read handler should be externally visible. Drivers and the ControlSocket element use read_visible rather than readable when deciding whether to tell the user that a read handler exists. Inter-element communication within the router, however, may use readable rather than read_visible. ''bool writable () const '' Method on Router::Handler ''bool write_visible () const '' Method on Router::Handler The analogous methods for write handlers. ''bool visible () const '' Method on Router::Handler Equivalent to read_visible() || write_visible(). ''String unparse_name (Element *element) const '' Method on Router::Handler Returns the handler's name, including its attached element's name if element is non-null. For example, calling unparse_name on element e's foo handler would return e.foo, while calling it on a global bar handler would return bar. ''String unparse_name (Element *element, const String &name) '' Static Method on Router::Handler Returns a string representing element's hypothetical name handler, or the global name handler if element is null. ''String call_read (Element *element) const '' Method on Router::Handler Calls this read handler on element and returns the result. Do not use this method unless you know the handler is readable(). ''int call_write (const String &data, Element *element, ErrorHandler *errh) const '' Method on Router::Handler Calls this write handler on element, passing it data and errh, and returns the result. Do not use this method unless you know the handler is writable(). === Handlers By Name or Index === These Router methods locate handlers by name, returning either a pointer to a handler object or a handler index. The methods are static to allow access to global handlers outside the context of a running router. ''const Router::Handler * handler (const Element *element, const String &name) '' Static Method on Router Returns a pointer to the handler object for element's handler named name, or null if no such handler exists. Element may be null, in which case the method looks for a global handler named name. Caution: Handler pointers returned by Router::handler and similar methods should be treated as transient, since they may become invalid when new handlers are added. ''int hindex (const Element *element, const String &name) '' Static Method on Router Like Router::handler, above, but returns an integer handler index for the named handler, or a negative number if no such handler exists. All valid handler indexes are nonnegative. ''const Router::Handler * handler (const Router *router, int hindex) '' Static Method on Router Returns router's handler object corresponding to hindex, or a null pointer if hindex is invalid with respect to router. There are three possibilities: (1) hindex coresponds to a valid global handler, which is returned. In this case, router need not be valid. (2) hindex corresponds to a valid local handler in class router, which is returned. (3) Otherwise, a null pointer is returned. ''const Router::Handler * handler (const Element *element, int hindex) '' Static Method on Router Convenience function equivalent to handler(element->router(), hindex). Note that hindex need not refer to one of element's handlers. ''const Router::Handler * handler (int hindex) const '' Method on Router Convenience function equivalent to handler(this, hindex). Finally, the element_hindexes static method returns all the handler indices that apply to a given element. ''void element_hindexes (const Element *element, Vector &results) '' Static Method on Router Appends to results all the handler indexes for element's handlers, or all global handlers if element is null.