Index: rna/CHANGES.RNA
diff -u /dev/null rna/CHANGES.RNA:1.9
--- /dev/null	Sun Jan 25 11:47:00 2009
+++ rna/CHANGES.RNA	Mon Jan  5 15:38:46 2009
@@ -0,0 +1,32 @@
+Changes since v0.9
+------------------
+
+1. Port to Click 1.6.0 release 
+
+   RNA still has minor changes to the Click core functions. The
+   changes are identical to those in 1.5.0 version.
+
+2. Support for in-band pattern learning. 
+
+   Metaprotocol peers can exchange their templates, i.e.,
+   patterns-related information.
+
+3. Pattern language extension 
+
+   Metaprotocol can selectively load namespaces - each of which identifies
+   a template. The namespace can be passed as argument to the metaprotocol. 
+
+4. FlexLink 
+
+   A simple link module that can be used to emulate lossy links 
+
+5. Rexmit 
+   
+   A new module that provides an order, reliable packet stream
+   abstraction to the higher layer. 
+
+Changes since v0.0
+-------------------
+
+    Initial implementation 
+
Index: rna/ChangeLog.1
diff -u rna/ChangeLog.1:1.1.10.1 rna/ChangeLog.1:1.2
--- rna/ChangeLog.1:1.1.10.1	Mon Sep  8 11:35:13 2008
+++ rna/ChangeLog.1	Mon Sep  8 10:49:48 2008
@@ -10086,7 +10086,7 @@
 Commit deeab1451cd8f68d4ef470a7dd93a811222508c7
 
 	* etc/linux-2.2.16-patch: oops: do I feel like an idiot (previous
-	patch had $Id: ChangeLog.1,v 1.1.10.1 2008/09/08 18:35:13 pingali Exp $ strings all wrong)
+	patch had $Id: ChangeLog.1,v 1.2 2008/09/08 17:49:48 pingali Exp $ strings all wrong)
 
 2000-10-31 Tue 22:35:19 +0000  Eddie Kohler <eddietwo@pdos.lcs.mit.edu>
 Commit b771bae8a869ee225a5b46ec67a5a117bff0dd59
Index: rna/LICENSE.RNA
diff -u /dev/null rna/LICENSE.RNA:1.1
--- /dev/null	Sun Jan 25 11:47:01 2009
+++ rna/LICENSE.RNA	Fri Jun 27 10:40:55 2008
@@ -0,0 +1,42 @@
+#
+# -------------------------------------------------------------------
+#                                   RNA
+#
+#                          http://www.isi.edu/rnd
+#                USC Information Sciences Institute (USC/ISI)
+#                   Marina del Rey, California 90292, USA
+#                          Copyright (c) 2007-2009
+# 
+# -------------------------------------------------------------------
+#
+# Copyright (c) 2007-2009 by the University of Southern California.
+# All rights reserved.
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation in source and binary forms for non-commercial
+# purposes and without fee is hereby granted, provided that the above
+# copyright notice appear in all copies and that both the copyright
+# notice and this permission notice appear in supporting
+# documentation, and that any documentation, advertising materials,
+# and other materials related to such distribution and use acknowledge
+# that the software was developed by the University of Southern
+# California, Information Sciences Institute.  The name of the
+# University may not be used to endorse or promote products derived
+# from this software without specific prior written permission.
+# 
+# THE UNIVERSITY OF SOUTHERN CALIFORNIA MAKES NO REPRESENTATIONS ABOUT
+# THE SUITABILITY OF THIS SOFTWARE FOR ANY PURPOSE.  THIS SOFTWARE IS
+# PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
+# INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+#
+# -------------------------------------------------------------------
+#
+#
+# This work was partly supported by the NSF (Grant No. CNS-0626788)
+# project. Any opinions, findings, and conclusions or recommendations
+# expressed in this material are those of the authors and do not
+# necessarily reflect the views of the National Science Foundation.
+#
+# Other copyrights might apply to parts of this software and are so
+# noted when applicable.
Index: rna/Makefile.RNA
diff -u /dev/null rna/Makefile.RNA:1.4
--- /dev/null	Sun Jan 25 11:47:01 2009
+++ rna/Makefile.RNA	Fri Dec 26 16:56:58 2008
@@ -0,0 +1,55 @@
+#!/bin/sh
+
+################################################################
+#                                                              #
+# (c) University of Southern California                        #
+#                                                              #
+#  See LICENSE.RNA for the complete license                    #
+#                                                              #
+################################################################
+
+INCPATH=$(PWD)/include
+PORTS=/usr/ports
+MODULES=devel/p5-Parse-RecDescent
+
+RNADIR=elements/rna
+
+PATTERNS_FILE=${RNADIR}/metaprotocol_patterns_db.txt 
+PROCESSED_PATTERNS=${RNADIR}/metaprotocol_patterns_db.cc 
+SHARED_NAMESPACES=${RNADIR}/shared_namespaces.txt
+PATTERNS_PARSER=${RNADIR}/patterns_parser.pl 
+
+all: build
+
+help: 
+	@echo "make [compile|clean|patch]"
+
+configure-rna: 
+	sh configure --disable-analysis --enable-ppp --enable-gre \
+	--enable-userlevel --disable-linuxmodule --enable-rna \
+	--enable-local CPPFLAGS="-DRNA" LIBS="-lcrypto" \
+	--disable-int64 
+
+# Compile twice to deal with Error **2 message
+compile: ${PROCESSED_PATTERNS} 
+	cd userlevel && gmake 
+	cd userlevel && gmake 
+
+build: configure-rna compile
+
+clean:
+	make clean
+
+patterns: ${PROCESSED_PATTERNS} 
+
+${PROCESSED_PATTERNS} : ${PATTERNS_PARSER} ${PATTERNS_FILE} ${SHARED_NAMESPACES}
+	perl ${PATTERNS_PARSER} ${PATTERNS_FILE} ${SHARED_NAMESPACES} ${PROCESSED_PATTERNS};
+	if [ "x$$?" != "x0" ]; then \
+	    rm ${PROCESSED_PATTERNS}; \
+	fi;
+
+
+perl-modules: 
+	for i in ${MODULES} do; \
+		cd ${PORTS}/$i && make && make install;\
+	done
Index: rna/README.RNA
diff -u /dev/null rna/README.RNA:1.16
--- /dev/null	Sun Jan 25 11:47:01 2009
+++ rna/README.RNA	Mon Jan  5 15:38:46 2009
@@ -0,0 +1,725 @@
+==================================================================
+
+          RNA METAPROTOCOL (v1.0)  
+          http://www.isi.edu/rna
+
+               $Revision: 1.16 $
+        $Date: 2009/01/05 23:38:46 $
+
+==================================================================
+
+This is the README for the source release of RNA Metaprotocol
+software. See http://www.isi.edu/rna for more information on RNA.
+
+RNA Metaprotocol is a stem cell-like protocol that adapts to a given
+context of operation. The aim of RNA Metaprotocol software is to take
+a step in that direction. This implementation of RNA Metaprotocol
+extends Click modular router software with additional modules and
+runtime composition capabilities.
+
+CONTENTS
+=========
+
+1  DISTRIBUTION     
+	Summary of the files that are part of this distribution 
+2  INSTALLATION & EXECUTION
+	Instructions on installing RNA-extensions and execution 
+3  CONFIGURATION    	
+	Discusses configuration file format 
+4  CODE             
+   4.1 FILES 
+   4.2 DESCRIPTION OF MODULES 
+	Summary of the code in the various files 
+   4.3 MODIFICATIONS TO CLICK 
+	Changes made to Click router 
+5  METAPROTOCOL PATTERN LANGUAGE AND COMPILATION: 
+	Description of the language of the metaprotocol template
+	and the parser written in Perl
+6  INSTRUCTIONS FOR DEVELOPERS
+7  BUGS/LIMITATIONS 	
+8  FUTURE WORK 
+	Possible extensions
+
+=======================================================================
+
+1. DISTRIBUTION
+---------------
+
+RNA is distributed a set of new files and modifications to Click
+modular router (http://read.cs.ucla.edu/click).
+
+CLICKDIR/LICENSE.RNA              USC/ISI Licence for RNA-specific code 
+CLICKDIR/Makefile.RNA             Build Click to use RNA 
+CLICKDIR/README.RNA               This file 
+CLICKDIR/CHANGES.RNA              Changes since the last revision 
+CLICKDIR/elements/rna/            RNA elements and metaprotocol
+CLICKDIR/conf/rna*                Click configuration files that use 
+				  RNA capabilities 
+
+This release has been tested only on FreeBSD though it should work
+without minor modification on other UNIX platforms. 
+
+=======================================================================
+
+2. INSTALLATION & EXECUTION 
+---------------------------
+
+Download the click source (version 1.5.0) and apply the metaprotocol
+match. Click source may be downloaded from the cvs site or from the
+standard distribution.
+
+$ fetch http://read.cs.ucla.edu/click/click-1.6.0.tar.gz
+$ tar zxvf click-1.6.0.tar.gz 
+
+$ fetch http://www.isi.edu/rna/rna-metaprotocol-v1.0.patch
+$cd <clickdir>
+$patch -p1 < ../rna-metaprotocol-v1.0.patch 
+
+$ make -f Makefile.RNA configure-rna 
+$ make -f Makefile.RNA compile 
+
+Execution is simple: 
+
+$cd <clickdir>
+$./userlevel/click ./conf/<config-file> 
+
+Often multiple configuration files may have to run to simulate
+multiple stacks.
+
+Most examples have a "right" and "left" click configuration files. The
+left process initiates the communication to the right. So 
+
+[Terminal 1] 
+$./userlevel/click ./conf/rna-XXX-right.click 
+
+[Terminal 2] 
+$./userlevel/click ./conf/rna-XXX-left.click 
+
+Note the testing has been limited and that this is experimental
+capability.
+
+=======================================================================
+
+3. CONFIGURATION FILE
+---------------------
+
+The configuration files use the same language as that of Click but
+with minor modifications.A fragment of the configuration file is shown
+below:
+
+~~~~~~~~~ 
+b1 :: Buffer(NAME 'B1 MODULE');
+b2 :: Buffer(NAME 'B2 MODULE');
+d1 :: Demultiplexor(NAME 'DEMUX 1');
+m1 :: Multiplexor(NAME 'MUX 1');
+
+r1 :: Metaprotocol(NAME 'MP1',
+		   ELEMENTS b1 b2 d1 m1, 
+                   CONN false,
+	           PATTERN 'MIN',
+		   AUTONEGOTIATE true);
+
+... -> [0] r1 [1] ->....
+
+~~~~
+
+Several modules of various kinds are instantiated and provided to the
+Metaprotocol. The Metaprotocol may compose any subset or none of the
+element provided. The elements are not explicitly connected using the
+language provided by Click except the metaprotocol. 
+
+The Metaprotocol has several parameters some of which are
+module-independent. These parameters are supported by the base class
+RNAElement and supported by all modules. They include:
+
+	NAME   : String         - Human readable name for each module 
+	DEBUG  : Bool           - Enable debug messages for this module
+				  (default is true) 
+	PROCESS: Bool           - Should initiate the composition process
+        	                  True by default with metaprotocol, false by 
+                                  default for other modules 
+	CONN   : Bool           - Mark this protocol as being connection-oriented 
+	                          (helps mostly with testing) 
+	ELEMENTS: Element list  - Elements available for composition 
+	UPSTREAM: Element list  - Upstream elements 
+	DOWNSTREAM: Element list- Downstream elements 
+        	                  Helpful when there are loops (caused by the 
+				  composition) and compound elements. 
+
+Beyond these each module supports modules-specific parameters. Some of
+these are listed below. 
+
+>> Metaprotocol: Basic implementation of the metaprotocol 
+	
+	PATTERN: String		- Initial pattern 
+	AUTONEGOTIATE: Bool	- Enable automatic negotiation 
+
+The PATTERN parameter specifies the initial pattern that must be
+executed by the metaprotocol. It does not, however, specify a
+particular final composition that must be reached. So this
+metaprotocol instantiates a subset of patterns selected from the many
+based on some internal strategy. The autonegotiate parameter tells the
+metaprotocol to negotiate with the peer once the protocol is instantiated. 
+
+>> Buffer: Multi-purpose buffering module
+
+	COPIES     Send packet copies repeated?
+  	DELAY      Enable delayed send
+		   (default = false; each packet delayed for a random time < some max )
+  	MANAGEMENT Enable sending management packets
+		   (default = false) 
+  	SKIP       The number of packets between successive management packets
+		   (default = 5) 
+
+>> Crypt: Symmetric cryptographic module 
+	
+	KEY	   Symmetric key (32 characters in Hex with optional 
+		   "0x" at the beginning)
+
+>> Multiplexor: Distribute incoming message from upstream into several streams 
+	
+	STRATEGY    Algorithm for distribution of packets
+
+>> FlexLink: Simulates a link with a specific loss ratio; can be used
+             as a stand alone module or as part of a meta-protocol
+             composition.
+
+	LOSSRATE   Fraction of packets lost 
+
+>> Rexmit: Reliable ordered delivery service 
+	
+=======================================================================
+
+4 CODE
+------
+
+RNAElement is the base class from which most modules are
+derived. RNAElement itself is derived from the Element class of
+Click. In addition there are helper class to enable storage and
+retrieval of link and node state, and track the status of the
+composition. Metaprotocol and the modules that are composed by the
+metaprotocol are subclasses of RNAElement. Metaprotocol uses a
+template that consists of the pattern language and state objects. 
+
+4.1 FILES
+
+This section lists various files in the elements/rna directory and
+summarizes the content of each. 
+
+// Basic RNA Element 
+rnaelement.hh           - Specifies the RNAElement class (derived from 
+                          Click's Element class)
+rnaelement.cc           - Main file that includes other RNA Element files 
+rnaelement_links.cc     - Management of creation and deletion of connections
+                          between modules 
+rnaelement_messages.cc  - Handle incoming messages (both data, control and 
+			  management) 
+rnaelement_neighbors.cc - Discover upstream and downstream elements 
+rnaelement_parse.cc     - Parse the input parameters
+rnaelement_handlers.cc  - Call backs from Click router. 
+rnaelement_control.cc   - Control interface between modules (effectively 
+			  between the protocol layers) 
+rnaelement_ctlmsg.cc    - Data structure passed between module while performing
+                          the control operations. 
+rnaelement_linkstate.cc - Stores state associated with each link from a 
+			  particular module instance has to other modules. 
+			  This is internal to each module. The link may 
+			  be intra-layer or cross layer. 
+rnalement_connstate.cc  - Connection state that is exchanged between
+			  layers and included in messages 
+
+// Metaprotocol 
+metaprotocol.cc         - Metaprotocol implemented as a class derived from 
+			  RNAElement class 
+metaprotocol_state.cc   - Stores and retrieves patterns 
+metaprotocol_patterns.cc- Implementation of patterns 
+metaprotocol_patterns_db.txt - Stored patterns file 
+metaprotocol_patterns_db.cc  - Output of the patterns file parser 
+
+patterns_parser.pl      - Patterns file parser (written in perl) 
+
+
+// Modules that are composed by the metaprotocol 
+shared_namespace.txt    - Enums containing namespaces that are shared between protocols
+                          and across hosts. 
+modules_crypt.cc        - Implements a module that encrypts and decrypts 
+			  traffic. Assumes a symmetric key and key specified 
+			  using configuration interface. 
+modules_buffer.cc       - Implements a simple buffer that can optionally delay 
+			  packets and generate management packets to the layers
+			  below 
+modules_reorderbuffer.cc- Buffer extended with support for sequence numbers in header 
+modules_multiplexor.cc  - Multiplexor and demultiplexor of packets based on the
+modules_demultiplexor.cc  packet header. Demultiplexor that supports registration 
+			  of the demux patterns from the downstream modules. Mux 
+			  can support multiple strategies for muxing (in theory)
+modules_pktsrc.cc       - Wrapper around the packet generator that adds a RNA 
+                          message header
+
+modules_flexlink.cc     - Flexible link. A primitive module that can be configured 
+                          to be lossy at a certain level 
+modules_rexmit.cc       - Reliable ordered packet delivery service.
+
+4.2 DESCRIPTION OF MODULES 
+--------------------------
+
+This section summarizes the structure and function of various classes
+in the elements/rna directory.
+
+RNAElement: 
+----------
+
+The RNAElement is the base class from which the metaprotocol and other
+modules are derived. It implements the shared
+functionality. RNAElement is a wrapper around the basic element
+structure provided by Click Element class. RNAElement adds:
+
+* Type - type of RNA element (e.g., BUFFER) 
+
+* Configuration - parses commonly used  parameters and arguments 
+
+* Control interface - to communicate between RNAElements for discovery
+  and state modification
+
+* Link management - addition/deletion of the links on the fly 
+
+* Message flow - default algorithms to move data across modules; do
+  pre and post processing of the messages. 
+
+* Element management - maintain the list of elements 
+
+* Template - the state and pattern management. Only metaprotocols use
+this capability. 
+
+RNAElement supports an explicit control interface within and across
+protocols. The purpose is to allow discovery and coordination across
+layers. The coordination could be locally driven or driven by an
+entity performing the coordination. There are two control interfaces -
+synchronous and asynchronous. The synchronous interface is useful when
+the programming environment for the protocol is shared across
+layers. The asynchronous interface based on messages is useful when
+the programming environment is not shared. It provides a message based
+abstraction. Both are equivalent.
+
+The synchronous control interface consists of a generic control()
+function. Each control request consists of a message type (command and
+reply), operation type (configuration, connection, discover etc.),
+operation (link add, connection close etc.), and optional data. If the
+default control handler in RNAElement cannot handle the request, the
+request is handled by module-specific control handler. 
+
+Link State: 
+----------
+
+Each RNAElement, including the metaprotocol, maintains a list of links
+to other elements. This is necessary to foward message within and
+across protocols. A LinkState object is instantiated upon addition of
+a link during initialization period or later. The datastructure
+maintains information about the following:
+
+* Ports - the local and remote Click element ports
+
+* Element - a pointer to the element structure at the remote end of
+the link
+
+* Direction - the direction of traffic flow because Click links are
+unidirectional (they flow from the output port of a given element to
+the input port of another element)
+
+* [Optional] Linktype - which tells whether the link from the module
+goes to the metaprotocol element or another data processing element. 
+
+* [Optional] Connection-orientedness : Whether the next layer is
+connection-oriented or not and if yes, whether the connection state
+has been obtained or not
+
+* Connection state - exported connection state from the next
+layer. Ideally this should be per-connection and not per-link. May be
+this should be an array.
+
+Messages: 
+--------
+
+There are three kinds of messages - data, control and
+management. Data messages flow between peers within the same
+layer. Control messages also flow across hosts between endpoints
+within the same layer but the data is intended for control and
+coordination purposes. Management messages flow within a single host
+between layers. The management messages are used to implement the
+asynchronous control interface between layers.
+
+There is no explicit new class associated with the messages. The
+Packet class of Click is reused. The header in the packet is used to
+carry the message type information. The header of each metaprotcol
+message includes the type of message (control, data or management),
+the sub-type (e.g., test and normal for data messages), and sub-type
+specific content such as length and pattern name.
+
+Packet annotation is used to convey connection state information
+across layers. The connection state is structured as a set of
+(variable, value) tuples that is discovered across layers. 
+
+Metaprotocol: 
+------------
+
+The Metaprotocol class is derived from RNAElement class and uses all
+of its capabilities. The main code rests in two files
+(metaprotocol.cc/hh). The metaprotocol implements: 
+
+* Composition - execution of a selected pattern 
+
+* Negotiation - exchange of control messages with a peer 
+
+* Testing - testing the outcome of a composition 
+
+The content of the negotiation (patterns) are managed by the
+metaprotocol state object (metaprotocol_state.cc/hh). The pattern
+functionality is implemented by a separate object
+(metaprotocol_patterns.cc/hh).
+
+State: This should be rightly called pattern manager. This state
+specifies:
+
+* Initial pattern 
+
+* Possible next patterns given a position 
+
+* Execute or cleanup an executed pattern 
+
+* Tests the feasibility of a specific pattern 
+
+The state is populated during compile time (for now). The patterns are
+specified in a separate file (metaprotocol_patterns_db.txt) that are
+precompiled (metaprotocol_patterns_db.cc) and incorporated into the
+state object at compile time. 
+
+The objective of the negotiation process is to enable two endpoint
+within the same layer to agree upon a composition. This is achieved
+incrementally adding one feature at a time. The patterns are organized
+as DAG (directed acyclic graph) and the negotiation process walks down
+the patterns DAG in a synchronized fashion. The negotiation might
+result in backtracking as well. Undoing a pattern may be necessary in
+addition to doing. This in general requires several round trips but a
+production implementation may be able to make larger functional jumps.
+The main file (metaprotocol.cc/hh) implements the negotiation
+(initiate_negotiation(),negotiate_request(), and negotiate_reply()). 
+
+In future the negotiation will be separated out because multiple
+negotiation strategies may have to be supported over time. 
+
+4.3 MODIFICATIONS TO CLICK
+--------------------------
+
+Click is a powerful framework and the modifications are minimal. They
+are in two basic classes. First, click assumes that once the modules
+loaded and connected to each other, they remain unmodified with
+respect to internal structure. Click has extra tools to manipulate
+compositions once made but do not have that support in the core
+code. Minor changes were necessary to enable one module to be
+'disconnected' from another module. A second function was written that
+tries to update the internal state of all the modules so that the
+modifications of the composition are 'committed'. This poses an
+interesting problem in that the composition is being modified by the
+composed elements. This naturally creates recursion and potential
+problems. Ideally Click should provide an interface to control the
+composition process but until then this is a stop gap arrangement.
+
+The files modified include lib/router.cc, lib/element.cc,
+include/click/element.hh and include/click/router.hh. 
+
+Some changes to lib/* and elements/userlevel/* are intended to fix
+compilation issues that arose when the Click code is compiled without
+64-bit support. 
+
+5 METAPROTOCOL PATTERN LANGUAGE AND COMPILATION
+-----------------------------------------------
+
+A key challenge is to deal with the semantics of the inter-connection
+between modules. This information is specified in the patterns file
+provided to the meta-protocol. Why a certain protocol should be
+connected a particular way is related to the question of function and
+semantics that is beyond the scope of the pattern language. 
+
+The pattern language specifies the patterns that are accepted by the
+metaprotocol. : 
+
+# There are multiple namespaces and each namespace is a collection of
+# patterns. You can choose a given pattern as a starting point. 
+COMMAND:       NAMESPACE_CMD
+NAMESPACE_CMD: 'NAMESPACE' IDENTIFIER 
+START_CMD:     'START' IDENTIFIER 
+PATTERN_CMD:   'PATTERN' IDENTIFIER RULES
+COMMENT:       <skip: '^\s*'> ( /#/ | /^$/ ) <resync>
+
+# Rules form a given pattern 
+RULES:         RULE(s?)
+RULE:          ( REQ_CMD | FOLLOWS_CMD | RENAME_CMD | CONF_CMD | CAPABILITY_CMD )
+
+# Various types of rules 
+REQ_CMD:       'REQ'  ('MUST') IDENTIFIER VALUE(?) OP(?) 
+FOLLOWS_CMD:   'FOLLOWS' IDENTIFIER 
+CAPABILITY_CMD:'CAPABILITY' CAPABILITY_CHECK  CAPABILITY_VAR TEXT
+CONF_CMD:      ('CONFIG' | 'UNCONFIG') (ARG_CMD | LINK_CMD | CAPABILITY_CMD )
+ARG_CMD:       'ARG' IDENTIFIER  VALUE(?)  TEXT   TEXT 
+LINK_CMD:      'LINK' ('ADD'|'DEL') IDENTIFIER VALUE(?) VALUE(?) IDENTIFIER VALUE(?)  VALUE(?) KEYWORD(s?)
+CAPABILITY_CHECK: ( 'PRESENT' | 'ABSENT' | 'MATCH' | 'PROVIDE' | 'NOTPROVIDE' )
+RENAME_CMD:    'RENAME' IDENTIFIER  VALUE TEXT 
+
+# Misc 
+OP:            ('>='|'<='|'='|'<'|'>')
+LOGICAL_OP:    ('XOR'|'AND'|'OR') 
+CAPABILITY_VAR:IDENTIFIER 
+IDENTIFIER:    /[A-Za-z_][A-Za-z0-9_]*/
+KEYWORD:       (SIMPLE_KEYWORD|RANGE_KEYWORD)
+SIMPLE_KEYWORD:('BIDIRECTIONAL'|'ALL')
+RANGE_KEYWORD: 'RANGE' VALUE '-' VALUE 
+TEXT:          /\S+/
+VALUE:         /\d+/ 
+
+The perl script CLICKDIR/elements/rna/process_patterns.pl implements a
+simple recursive descent parser for the pattern language. 
+
+This process may be invoked through the Makefile.RNA
+
+$ make -f Makefile.RNA patterns 
+
+                                   module namespace 
+                                         |
+                                         |
+                                         V
+metaprotocol_patterns_db.txt ----> patterns_parser.pl---->metaprotocol_patterns_db.cc
+
+The output is included during the initialization process of the
+metaprotocol template state. 
+
+metaprotocol_state.cc: 
+     ...
+     State::State(RNAElement *control_in, ....) {
+     ...
+         #include "metaprotocol_patterns_db.cc" 
+     ...
+     }
+     ...
+
+
+
+=======================================================================
+
+6. INSTRUCTIONS FOR DEVELOPERS
+------------------------------
+
+In order to understand/extend the code: 
+
+1. Experiment with basic Click (1.6.0) 
+
+2. Apply the 1.6.0 patch 
+
+3. Configure and compile the code again - this time using Makefile.RNA 
+   itself as mentioned above 
+
+4. Look through the rnaelement which is the base class for all other 
+   modules and metaprotocol. It handles the default control and data
+   path functions of the modules. 
+
+5. Next look at metaprotocol.c, metaprotocol_state.cc and metaprotocol_patterns.cc 
+
+6. The patterns are stored in metaprotocol_patterns.db.txt that is processed
+   by patterns_parser.pl. The result is metaprotocol_patterns_db.cc that 
+   is included in the metaprotocol_state.cc 
+
+7. Once the compilation is done, run an instance of click with 'right'
+   and 'left' click configuration files from conf 
+
+8. The output will track the packets as they go up and down the 
+   metaprotocol. Some are control packets and other are data. It allows 
+   you to follow the activity as it is happening. You can map the output
+   entries to specific modules and specific actions being taken. This 
+   is useful mostly for debugging purposes. The application is still 
+   under development. 
+
+9. A new module can be added by copying and editing the code from an
+   existing module. Make sure that the name is also added to the
+   shared_namespace.txt and rnaelement_ctlmsg.c. 
+
+10. Follow the composition process closely - to the debug messages
+    that indicate how one module is linked to another module. The 
+    message forwarding logic also prints out the incoming and outgoing 
+    links between modules. Thats the place to look. 
+
+11. Edit metaprotocol_patterns_db.txt if you would like options for 
+    composition. If multiple compositions are feasible, note that
+    there is no way in the existing system to force one path being
+    picked. 
+
+=======================================================================
+
+7. BUGS/LIMITATIONS
+----------------
+
+>> Error message: <class-name>::class_name method malformed
+
+This warning is printed by click-buildtool that parses the files for
+sanity check. It assumes that class_name() method returns a fixed
+string. RNA elements call the default_class_name() function in the
+base class. This is not a critical error. The work around is to 
+try compiling again. 
+
+>> The compilation process terminates with "*** Error code 2"
+
+Workaround: Try compiling again. 
+
+$make -f Makefile.RNA compile 
+
+>> Only push interface supported 
+
+Only push interface is supported right now. Pull interface is not
+fundamentally different in terms of the functionality except the
+RNAElement structure must be generalized a little more.
+
+>> When I execute ./click ./conf/<some rna configuration file> I see
+>> messages like this: 
+
+[MP2] RNAElement::push:   29 | b02000b0 2000b020 00080000 00b02000 b02000b0 2000aaaa aaaaaaaa aa
+[MP2] Metaprotocol::push_data - received a data message
+[MP2] Metaprotocol::push_data - Normal data. Pushing to intra-layer module.
+[MP2] RNAElement::push_data(port = 1)
+[LINK] <<INIT=YES, INCOMING, cross-layer link, From DOWNSTREAM >> [MP2 local, 1 port] <- [UNKNOWN remote, -1 port]]
+[MP2] RNAElement::push_data inter-layer message 
+[MP2] RNAElement::select_outgoing_link (upstream, layer sensitive, intra-layer, agnostic remote, remote unknown, conn state not required)
+[MP2] open_connection Entry 
+[LINK] <<INIT=NO , OUTGOING, intra-layer link, To   UPSTREAM   >> [RNAElement::open_connection local, 3 port] -> [B2 MODULE remote, 1 port]]
+[MP2] open_connection: Found 0 downstream elements
+[MP2] open_connection Exit
+[12] Sending packet to: 
+[LINK] <<INIT=NO , OUTGOING, intra-layer link, To   UPSTREAM   >> [MP2 local, 3 port] -> [B2 MODULE remote, 1 port]]
+
+The current release has debug messages enabled mostly because the
+runtime construction of the metaprotocol and message flow is being
+debugged. This is not a "production" release in that sense.
+
+>> Static template 
+
+Patterns are included during compilation. Future work will make the
+patterns loadable at runtime.
+
+>> Explicit specification of upstream/downstream nodes 
+
+The nodes may require an explicit specification of upstream and
+downstream elements. This is useful because the metaprotocol may
+create loops - depending on the programming framework.
+
+>> Limited wild card support 
+
+Only one wild card is supported in any pattern. Support for multiple
+wild cards will be added in future.  For example if multiple buffers
+must be incorporated into a mux-demux system, then the meaning of the
+following line is that two buffers must be connected to the
+multiplexor.
+
+    CONFIG LINK ADD MULTIPLEXOR 0 BUFFER 0 2
+
+On the other hand, the following instruction means that first two
+buffers must be disconnected from the multiplexor. 
+
+    UNCONFIG LINK DEL MULTIPLEXOR 0 BUFFER 0 2 
+
+Fine grained control and multiple wildcards will be supported in
+future. 
+
+>> UNCONFIG ARG not effective
+
+UNCONFIG supports only LINK commands for now. UNCONFIG ARG will be
+added in future. 
+
+>> When sending test reply and intra-layer links are found, the message 
+   is sent on the cross-layer links. 
+
+A check is required to see if the protocol has not composed any
+elements at all or if that composition has failed for some reason.
+
+>> When the patterns specifies a prerequisite but does not use it, in
+   the example shown below, negotiation fails. 
+
+    PATTERN MIN
+      REQ MUST BUFFER 1 
+      CAPABILITY PRESENT CONNECTION_LESS
+
+The test messages look for intra-layer path through the buffer. When
+no such path is found, the packet is dropped. A sanity check must be
+added to the parser to check for the consistency of the pattern
+specification. The same consistency check must be performed while
+loading in the pattern. 
+
+=======================================================================
+
+8. FUTURE WORK
+--------------
+
+1. Runtime parsing. 
+
+The parsing of the patterns is currently a compile-time operation. The
+parser has been written in Perl. Making this process a runtime
+operation by embedding a parser into the metaprotocol enables dynamic
+loading of the patterns file and learning of the patterns across
+hosts.
+
+2. Extensions to the language
+
+The language described above is still primitive. Possible extensions
+include more expressive patterns with support for notions such as
+atleast or atmost, a language for testing,
+
+3. Context-driven composition
+
+A decision process is required to bridge the information about the
+context of operations and the final goal of the protocol.
+
+4. Multiple host configurations 
+
+Multiple peers e.g., any kind of algorithm that involves multiple
+parties such as routing, filtering etc. In this case the design point
+is obtained from the peer and it is relatively fixed. New design
+points may be propagated accounting for disruption. 
+
+5. Check multiple possible compositions 
+
+Exchange a set of possible next compositions instead of one at a
+time. This is a simple extension and should be supported in future. 
+
+6. Support for multiple negotiation strategies 
+
+Currently the metaprotocol supports only one kind of negotiation style
+(simple two-way negotiate + test). Others may be necessary/interesting
+such as those with multilevel backtracking and with memory.
+
+7. Dynamic instantiation of modules
+
+This enables further simplification of the configuration files but
+requires modifications to the Click core. 
+
+8. Add consistency checks in the pattern parser as discussed in the
+bugs section.
+
+Also add consistency checks across patterns. If a previous pattern
+does not have the links that are being manipulated by a given pattern,
+an error should be flagged. The parser must have an internal model of
+protocol and verify the model as it parses the modules. 
+
+9. Patterns learnt from peers are not stored. 
+
+For now, the metaprotocol patterns are incorporated into the
+metaprotocol during the compile time. Patterns can be transferred
+during negotiation or later but 
+
+10. Negotiation in each instantiation is inefficient. 
+
+The result of past exchanges may be stored and retrieved to improve
+the efficiency of the exchange. 
+
+11. Support for multihop 
+ 
+For now the implementation supports only two protocol endpoints. It
+can be extended to add support for multiple hops. There are two
+challenges in multi-hop. First, the metaprotocol becomes multiported
+making the outgoing link selection dependent on the content. Second,
+endpoints will be at different starting points during negotiation. 
Index: rna/conf/click-mkclgw.pl
diff -u rna/conf/click-mkclgw.pl:1.1.10.1 rna/conf/click-mkclgw.pl:1.2
--- rna/conf/click-mkclgw.pl:1.1.10.1	Mon Sep  8 11:35:35 2008
+++ rna/conf/click-mkclgw.pl	Mon Sep  8 10:50:08 2008
@@ -2,7 +2,7 @@
 
 #
 #
-# $Id: click-mkclgw.pl,v 1.1.10.1 2008/09/08 18:35:35 pingali Exp $
+# $Id: click-mkclgw.pl,v 1.2 2008/09/08 17:50:08 pingali Exp $
 #
 # click-mkclgw
 #
Index: rna/conf/example.clgw
diff -u rna/conf/example.clgw:1.1.10.1 rna/conf/example.clgw:1.2
--- rna/conf/example.clgw:1.1.10.1	Mon Sep  8 11:35:36 2008
+++ rna/conf/example.clgw	Mon Sep  8 10:50:08 2008
@@ -1,5 +1,5 @@
 # 
-# $Id: example.clgw,v 1.1.10.1 2008/09/08 18:35:36 pingali Exp $
+# $Id: example.clgw,v 1.2 2008/09/08 17:50:08 pingali Exp $
 #
 #  Script to be processed with click-mkclgw.pl, to make a click configuration
 #
Index: rna/conf/rna-flexlink-left.click
diff -u /dev/null rna/conf/rna-flexlink-left.click:1.1
--- /dev/null	Sun Jan 25 11:47:02 2009
+++ rna/conf/rna-flexlink-left.click	Fri Dec 26 16:56:59 2008
@@ -0,0 +1,72 @@
+//
+//
+//
+//           PKTSRC1 (RNAPktSrc) 
+//              |
+//              V     
+//           PKTSRCBUF1 (Buffer) 
+//              |
+//              V     
+//      +------------------+
+//      |        \     MP1 |
+//      |         \        |
+//      |          |       |
+//      |          V       |
+//      |         FLEXLINK1 (FlexLink) 
+//      |          |       |
+//      |          V       |
+//      |         B1 MODULE (Buffer) 
+//      |         /        |
+//      |        /         |
+//      |       |          |
+//      |       V          |
+//      +------------------+
+//              |
+//              V
+//                 
+//        To the rightstack
+//
+// Execute 
+//     cd <clickdir>/userlevel 
+//     ./click ../conf/rna-flexlink-left.click 
+//
+
+e1 :: Buffer(NAME 'B1 MODULE');
+
+e2 :: Demultiplexor(NAME 'DEMUX 1');
+
+e3 :: FlexLink(NAME 'FLEXLINK 1',
+               LOSSRATE 0.5);
+
+
+r1 :: Metaprotocol(NAME 'MP1',
+		   ELEMENTS e1 e2 e3, 
+	           PROCESS true, 
+                   AUTONEGOTIATE true);
+
+p1 :: RNAPktSrc(NAME 'PKTSRC1', 
+		PROCESS true); 
+
+b1 :: Buffer(NAME 'PKTSRCBUF1', 
+             PROCESS true,
+             COPIES true,
+	     DELAY true);
+
+src :: InfiniteSource(\<aaaaaaaaaaaaaa>, 2) 
+
+// Loopback the data that has been sent out. 
+elementclass loopback {
+	input[0]                    ->  Socket(UDP, 0.0.0.0, 20001)
+	Socket(UDP, 0.0.0.0, 20000) ->  [0] output 
+}
+
+l  :: loopback 
+
+// WAIT!!!!  
+
+// Make sure that Bufferelem has input ports 0/0 going upstream and
+// 1/1 going downstream when being used as stand alone protocol 
+// module
+
+src -> [0] p1 [0] -> [0] b1 [1] -> [0] r1 [1] -> Print -> [0] l
+l[0] -> Print -> [1] r1 [0] -> [1] b1 [0] -> Print -> Discard
Index: rna/conf/rna-flexlink-right.click
diff -u /dev/null rna/conf/rna-flexlink-right.click:1.1
--- /dev/null	Sun Jan 25 11:47:02 2009
+++ rna/conf/rna-flexlink-right.click	Fri Dec 26 16:56:59 2008
@@ -0,0 +1,54 @@
+//
+// Execute 
+//     cd <clickdir>/userlevel 
+//     ./click ../conf/rna-flexlink-right.click 
+//
+//
+//
+//           PKTSRC2 (RNAPktSrc) 
+//              |
+//              V     
+//      +------------------+
+//      |        \     MP2 |
+//      |         \        |
+//      |          |       |
+//      |          V       |
+//      |         FLEXLINK2 (FlexLink) 
+//      |          |       |
+//      |          V       |
+//      |         B2 MODULE (Buffer) 
+//      |         /        |
+//      |        /         |
+//      |       |          |
+//      |       V          |
+//      +------------------+
+//              |
+//              V
+//        To the left stack
+
+e1 :: Buffer(NAME 'B2 MODULE');
+
+e2 :: Demultiplexor(NAME 'DEMUX 2');
+
+e3 :: FlexLink(NAME 'FLEXLINK 2');
+
+r1 :: Metaprotocol(NAME 'MP2',
+		   ELEMENTS e1 e2 e3,
+	           PROCESS true)
+
+p1 :: RNAPktSrc(NAME 'PKTSRC2', 
+		PROCESS true); 
+
+
+src :: InfiniteSource(\<aaaaaaaaaaaaaa>, 0) 
+
+// Loopback the data that has been sent out. 
+elementclass loopback {
+	input[0]                    ->  Socket(UDP, 0.0.0.0, 20000)
+	Socket(UDP, 0.0.0.0, 20001) ->  [0] output 
+}
+
+l  :: loopback 
+
+src -> Print -> [0] p1 [0] -> [0] r1 [1] -> Print -> [0] l
+l[0] -> Print -> [1] r1 [0] -> Print -> Discard
Index: rna/conf/rna-muxdemux-left.click
diff -u /dev/null rna/conf/rna-muxdemux-left.click:1.3
--- /dev/null	Sun Jan 25 11:47:02 2009
+++ rna/conf/rna-muxdemux-left.click	Mon Sep  8 10:50:08 2008
@@ -0,0 +1,76 @@
+
+// RNA Test Configuration File: MuxDemux
+//
+// This script instantiates the left stack and the negotiation between 
+// the endpoints is supposed to result in a mux-demux like arrangement. 
+// Other patterns may be added but they do not succeed (failed 
+// prerequiresites). 
+//
+//
+//            PktSrc            PktSrc
+//              |                 |
+//              V                 V
+//            Buffer            Buffer
+//              |                 |
+//              V                 V               
+//      +----------------+ +------+---------+
+//      | [Metaprotocol] | | [Metaprotocol] |
+//      |      Mux       | |     Mux        |  
+//      |     /   \      | |    /   \       |
+//      |  Buf1   Buf2   | | Buf1   Buf2    |
+//      |     \    /     | |    \    /      |
+//      |     Demux      | |    Demux       |
+//      |       |        | |      |         |
+//      +-------+--------+ +------+---------+
+//              |                 |
+//              V                 V
+//              +-----------------+
+//            Left stack       Right stack
+//
+// Execute 
+//     cd <clickdir>/userlevel 
+//     ./click ../conf/rna-muxdemux-left.click 
+//
+
+
+// Generate copies of the packets coming from above 
+// at regular intervals...
+b1 :: Buffer(NAME 'B1 MODULE', 
+	     COPIES true, 
+	     PROCESS true);
+
+// Modules  that must be composed 
+e1 :: Buffer(NAME 'E1 MODULE');
+e2 :: Buffer(NAME 'E2 MODULE');
+m1 :: Multiplexor(NAME 'MUX 1');
+d1 :: Demultiplexor(NAME 'DEMUX 1');
+
+// Set the goal of the metaprotocol as muxdemux. Enable automatic 
+// negotiation between the endpoints. 
+r1 :: Metaprotocol(NAME 'MP1',
+		   ELEMENTS e1 e2 d1 m1, 
+	           PROCESS true, 
+                   CONN false,
+	           PATTERN 'MUXDEMUX',
+		   AUTONEGOTIATE true);
+
+// Packet generator...
+src :: InfiniteSource(\<aaaaaaaaaaaaaa>, 2) 
+p1 :: RNAPktSrc(NAME 'PKTSRC1', 
+		PROCESS true); 
+
+// Create a loopback on the machine to another instance of the
+// metaprotocol
+AddressInfo(
+	nik		128.9.168.58,
+)
+
+elementclass loopback {
+	input[0]                    ->  Socket(UDP, 0.0.0.0, 20001)
+	Socket(UDP, 0.0.0.0, 20000) ->  [0] output 
+}
+
+l  :: loopback 
+
+src -> [0] p1 [0] -> [0] b1 [1] -> [0] r1 [1] -> Print -> [0] l
+l[0] -> Print -> [1] r1 [0] -> [1] b1 [0] -> Print -> Discard
Index: rna/conf/rna-muxdemux-right.click
diff -u /dev/null rna/conf/rna-muxdemux-right.click:1.3
--- /dev/null	Sun Jan 25 11:47:02 2009
+++ rna/conf/rna-muxdemux-right.click	Mon Sep  8 10:50:08 2008
@@ -0,0 +1,76 @@
+
+// RNA Test Configuration File: MuxDemux
+//
+// This script instantiates the right stack and the negotiation between 
+// the endpoints is supposed to result in a mux-demux like arrangement. 
+// Other patterns may be added but they do not succeed (failed 
+// prerequiresites). 
+//
+//
+//            PktSrc            PktSrc
+//              |                 |
+//              V                 V
+//            Buffer            Buffer
+//              |                 |
+//              V                 V               
+//      +----------------+ +------+---------+
+//      | [Metaprotocol] | | [Metaprotocol] |
+//      |      Mux       | |     Mux        |  
+//      |     /   \      | |    /   \       |
+//      |  Buf1   Buf2   | | Buf1   Buf2    |
+//      |     \    /     | |    \    /      |
+//      |     Demux      | |    Demux       |
+//      |       |        | |      |         |
+//      +-------+--------+ +------+---------+
+//              |                 |
+//              V                 V
+//              +-----------------+
+//            Left stack       Right stack
+//
+// Execute 
+//     cd <clickdir>/userlevel 
+//     ./click ../conf/rna-muxdemux-right.click 
+//
+
+// Generate copies of the packets coming from above 
+// at regular intervals...
+//b1 :: Buffer(NAME 'B1 MODULE', 
+//	     COPIES true, 
+//	     PROCESS true);
+
+// Modules  that must be composed 
+e1 :: Buffer(NAME 'E1 MODULE');
+e2 :: Buffer(NAME 'E2 MODULE');
+m1 :: Multiplexor(NAME 'MUX 1');
+d1 :: Demultiplexor(NAME 'DEMUX 1');
+
+// Set the goal of the metaprotocol as muxdemux. 
+r1 :: Metaprotocol(NAME 'MP1',
+		   ELEMENTS e1 e2 d1 m1, 
+	           PROCESS true, 
+                   CONN false,
+	           PATTERN 'MUXDEMUX');
+
+p1 :: RNAPktSrc(NAME 'PKTSRC2', 
+		PROCESS true); 
+
+AddressInfo(
+	nik		128.9.168.58,
+)
+
+src :: InfiniteSource(\<aaaaaaaaaaaaaa>, 0) 
+
+// Loopback the data that has been sent out. 
+elementclass loopback {
+	input[0]                    ->  Socket(UDP, 0.0.0.0, 20000)
+	Socket(UDP, 0.0.0.0, 20001) ->  [0] output 
+}
+
+l  :: loopback 
+
+// Create the minimal composition. Still looks like 
+// existing Click program but will be eventually simplified to 
+// just "r1"
+
+src -> Print -> [0] p1 [0] -> [0] r1 [1] -> Print -> [0] l
+l[0] -> Print -> [1] r1 [0] -> Print -> Discard
Index: rna/conf/rna-patternlearning-left.click
diff -u /dev/null rna/conf/rna-patternlearning-left.click:1.2
--- /dev/null	Sun Jan 25 11:47:02 2009
+++ rna/conf/rna-patternlearning-left.click	Fri Dec 26 16:56:59 2008
@@ -0,0 +1,83 @@
+//
+// The elements are specified such that pattern ORDERED_DELIVERY 
+// is supported (see elements/rna/metaprotocol_patterns_db.txt) 
+//
+// Autonegotiate is necessary to enable execution of pattern MIN first
+// followed by ORDERED_DELIVERY. Prerequisites are not satisfied for
+// other patterns such as ENCRYPTED_ORDERED_DELIVERY, TUNNEL and
+// MUXDEMUX to be executed.
+//
+//
+//           PKTSRC1 (RNAPktSrc) 
+//              |
+//              V     
+//           PKTSRCBUF1 (Buffer) 
+//              |
+//              V     
+//      +------------------+
+//      |        \     MP1 |
+//      |         \        |
+//      |          |       |
+//      |          V       |
+//      |         REORDER1 (ReorderBuffer) 
+//      |          |       |
+//      |          V       |
+//      |         B1 MODULE (Buffer) 
+//      |         /        |
+//      |        /         |
+//      |       |          |
+//      |       V          |
+//      +------------------+
+//              |
+//              V
+//                 
+//        To the rightstack
+//
+// Execute 
+//     cd <clickdir>/userlevel 
+//     ./click ../conf/rna-reorderbuffer-left.click 
+//
+
+e1 :: Buffer(NAME 'B1 MODULE');
+
+e2 :: Demultiplexor(NAME 'DEMUX 1');
+
+e3 :: ReorderBuffer(NAME 'REORDER 1');
+
+
+r1 :: Metaprotocol(NAME 'MP1',
+		   ELEMENTS e1 e2 e3,
+	           PROCESS true,
+                   AUTONEGOTIATE true,
+                   NAMESPACE DEFAULT);
+
+p1 :: RNAPktSrc(NAME 'PKTSRC1', 
+		PROCESS true); 
+
+b1 :: Buffer(NAME 'PKTSRCBUF1', 
+             PROCESS true,
+             COPIES true,
+	     DELAY true);
+
+AddressInfo(
+	nik		128.9.168.58,
+)
+
+src :: InfiniteSource(\<aaaaaaaaaaaaaa>, 2) 
+
+// Loopback the data that has been sent out. 
+elementclass loopback {
+	input[0]                    ->  Socket(UDP, 0.0.0.0, 20001)
+	Socket(UDP, 0.0.0.0, 20000) ->  [0] output 
+}
+
+l  :: loopback 
+
+// WAIT!!!!  
+
+// Make sure that Bufferelem has input ports 0/0 going upstream and
+// 1/1 going downstream when being used as stand alone protocol 
+// module
+
+src -> [0] p1 [0] -> [0] b1 [1] -> [0] r1 [1] -> Print -> [0] l
+l[0] -> Print -> [1] r1 [0] -> [1] b1 [0] -> Print -> Discard
Index: rna/conf/rna-patternlearning-right.click
diff -u /dev/null rna/conf/rna-patternlearning-right.click:1.1
--- /dev/null	Sun Jan 25 11:47:02 2009
+++ rna/conf/rna-patternlearning-right.click	Thu Sep 11 14:41:40 2008
@@ -0,0 +1,68 @@
+//
+// The elements are specified such that pattern ORDERED_DELIVERY 
+// is supported (see elements/rna/metaprotocol_patterns_db.txt) 
+//
+// Autonegotiate is necessary to enable execution of pattern MIN first
+// followed by ORDERED_DELIVERY. Prerequisites are not satisfied for
+// other patterns such as ENCRYPTED_ORDERED_DELIVERY, TUNNEL and
+// MUXDEMUX to be executed.
+//
+//
+//           PKTSRC2 (RNAPktSrc) 
+//              |
+//              V     
+//      +------------------+
+//      |        \     MP2 |
+//      |         \        |
+//      |          |       |
+//      |          V       |
+//      |         REORDER2 (ReorderBuffer) 
+//      |          |       |
+//      |          V       |
+//      |         B2 MODULE (Buffer) 
+//      |         /        |
+//      |        /         |
+//      |       |          |
+//      |       V          |
+//      +------------------+
+//              |
+//              V
+//        To the left stack
+//
+// Execute 
+//     cd <clickdir>/userlevel 
+//     ./click ../conf/rna-reorderbuffer-right.click 
+//
+
+e1 :: Buffer(NAME 'B2 MODULE');
+
+e2 :: Demultiplexor(NAME 'DEMUX 2');
+
+e3 :: ReorderBuffer(NAME 'REORDER 2');
+
+r1 :: Metaprotocol(NAME 'MP2',
+		   ELEMENTS e1 e2 e3,
+	           PROCESS true,
+                   CONN false,
+	           LEARNING true, 
+                   NAMESPACE DEFAULT_SIMPLIFIED);
+
+p1 :: RNAPktSrc(NAME 'PKTSRC2', 
+		PROCESS true); 
+
+AddressInfo(
+	nik		128.9.168.58,
+)
+
+src :: InfiniteSource(\<aaaaaaaaaaaaaa>, 0) 
+
+// Loopback the data that has been sent out. 
+elementclass loopback {
+	input[0]                    ->  Socket(UDP, 0.0.0.0, 20000)
+	Socket(UDP, 0.0.0.0, 20001) ->  [0] output 
+}
+
+l  :: loopback 
+
+src -> Print -> [0] p1 [0] -> [0] r1 [1] -> Print -> [0] l
+l[0] -> Print -> [1] r1 [0] -> Print -> Discard
Index: rna/conf/rna-reorderbuffer-left.click
diff -u /dev/null rna/conf/rna-reorderbuffer-left.click:1.3
--- /dev/null	Sun Jan 25 11:47:02 2009
+++ rna/conf/rna-reorderbuffer-left.click	Thu Sep 11 14:41:40 2008
@@ -0,0 +1,83 @@
+//
+// The elements are specified such that pattern ORDERED_DELIVERY 
+// is supported (see elements/rna/metaprotocol_patterns_db.txt) 
+//
+// Autonegotiate is necessary to enable execution of pattern MIN first
+// followed by ORDERED_DELIVERY. Prerequisites are not satisfied for
+// other patterns such as ENCRYPTED_ORDERED_DELIVERY, TUNNEL and
+// MUXDEMUX to be executed.
+//
+//
+//           PKTSRC1 (RNAPktSrc) 
+//              |
+//              V     
+//           PKTSRCBUF1 (Buffer) 
+//              |
+//              V     
+//      +------------------+
+//      |        \     MP1 |
+//      |         \        |
+//      |          |       |
+//      |          V       |
+//      |         REORDER1 (ReorderBuffer) 
+//      |          |       |
+//      |          V       |
+//      |         B1 MODULE (Buffer) 
+//      |         /        |
+//      |        /         |
+//      |       |          |
+//      |       V          |
+//      +------------------+
+//              |
+//              V
+//                 
+//        To the rightstack
+//
+// Execute 
+//     cd <clickdir>/userlevel 
+//     ./click ../conf/rna-reorderbuffer-left.click 
+//
+
+e1 :: Buffer(NAME 'B1 MODULE');
+
+e2 :: Demultiplexor(NAME 'DEMUX 1');
+
+e3 :: ReorderBuffer(NAME 'REORDER 1');
+
+
+r1 :: Metaprotocol(NAME 'MP1',
+		   ELEMENTS e1 e2 e3, 
+	           PROCESS true, 
+                   CONN false,
+                   AUTONEGOTIATE true);
+
+p1 :: RNAPktSrc(NAME 'PKTSRC1', 
+		PROCESS true); 
+
+b1 :: Buffer(NAME 'PKTSRCBUF1', 
+             PROCESS true,
+             COPIES true,
+	     DELAY true);
+
+AddressInfo(
+	nik		128.9.168.58,
+)
+
+src :: InfiniteSource(\<aaaaaaaaaaaaaa>, 2) 
+
+// Loopback the data that has been sent out. 
+elementclass loopback {
+	input[0]                    ->  Socket(UDP, 0.0.0.0, 20001)
+	Socket(UDP, 0.0.0.0, 20000) ->  [0] output 
+}
+
+l  :: loopback 
+
+// WAIT!!!!  
+
+// Make sure that Bufferelem has input ports 0/0 going upstream and
+// 1/1 going downstream when being used as stand alone protocol 
+// module
+
+src -> [0] p1 [0] -> [0] b1 [1] -> [0] r1 [1] -> Print -> [0] l
+l[0] -> Print -> [1] r1 [0] -> [1] b1 [0] -> Print -> Discard
Index: rna/conf/rna-reorderbuffer-right.click
diff -u /dev/null rna/conf/rna-reorderbuffer-right.click:1.3
--- /dev/null	Sun Jan 25 11:47:02 2009
+++ rna/conf/rna-reorderbuffer-right.click	Thu Sep 11 14:41:40 2008
@@ -0,0 +1,66 @@
+//
+// The elements are specified such that pattern ORDERED_DELIVERY 
+// is supported (see elements/rna/metaprotocol_patterns_db.txt) 
+//
+// Autonegotiate is necessary to enable execution of pattern MIN first
+// followed by ORDERED_DELIVERY. Prerequisites are not satisfied for
+// other patterns such as ENCRYPTED_ORDERED_DELIVERY, TUNNEL and
+// MUXDEMUX to be executed.
+//
+//
+//           PKTSRC2 (RNAPktSrc) 
+//              |
+//              V     
+//      +------------------+
+//      |        \     MP2 |
+//      |         \        |
+//      |          |       |
+//      |          V       |
+//      |         REORDER2 (ReorderBuffer) 
+//      |          |       |
+//      |          V       |
+//      |         B2 MODULE (Buffer) 
+//      |         /        |
+//      |        /         |
+//      |       |          |
+//      |       V          |
+//      +------------------+
+//              |
+//              V
+//        To the left stack
+//
+// Execute 
+//     cd <clickdir>/userlevel 
+//     ./click ../conf/rna-reorderbuffer-right.click 
+//
+
+e1 :: Buffer(NAME 'B2 MODULE');
+
+e2 :: Demultiplexor(NAME 'DEMUX 2');
+
+e3 :: ReorderBuffer(NAME 'REORDER 2');
+
+r1 :: Metaprotocol(NAME 'MP2',
+		   ELEMENTS e1 e2 e3,
+	           PROCESS true,
+                   CONN false);
+
+p1 :: RNAPktSrc(NAME 'PKTSRC2', 
+		PROCESS true); 
+
+AddressInfo(
+	nik		128.9.168.58,
+)
+
+src :: InfiniteSource(\<aaaaaaaaaaaaaa>, 0) 
+
+// Loopback the data that has been sent out. 
+elementclass loopback {
+	input[0]                    ->  Socket(UDP, 0.0.0.0, 20000)
+	Socket(UDP, 0.0.0.0, 20001) ->  [0] output 
+}
+
+l  :: loopback 
+
+src -> Print -> [0] p1 [0] -> [0] r1 [1] -> Print -> [0] l
+l[0] -> Print -> [1] r1 [0] -> Print -> Discard
Index: rna/conf/rna-rexmit-left.click
diff -u /dev/null rna/conf/rna-rexmit-left.click:1.2
--- /dev/null	Sun Jan 25 11:47:02 2009
+++ rna/conf/rna-rexmit-left.click	Fri Jan  2 14:06:58 2009
@@ -0,0 +1,78 @@
+//
+// Execute 
+//     cd <clickdir>/userlevel 
+//     ./click ../conf/rna-rexmit-left.click 
+//
+//  This works with rna-rexmit-right.click (another click process) 
+//
+//
+//           PKTSRC1 (RNAPktSrc) 
+//              |
+//              V     
+//           PKTSRCBUF1 (Buffer) 
+//              |
+//              V     
+//      +------------------+
+//      |        \     MP1 |
+//      |         \        |
+//      |          |       |
+//      |          V       |
+//      |         REXMIT1 (Rexmit) 
+//      |          |       |
+//      |          V       |
+//      |         FLEXLINK1 (FlexLink) 
+//      |          |       |
+//      |          V       |
+//      |         B1 MODULE (Buffer) 
+//      |         /        |
+//      |        /         |
+//      |       |          |
+//      |       V          |
+//      +------------------+
+//              |
+//              V
+//                 
+//        To the rightstack
+//
+
+
+e1 :: Buffer(NAME 'B1 MODULE');
+
+e2 :: Demultiplexor(NAME 'DEMUX 1');
+
+e3 :: FlexLink(NAME 'FLEXLINK 1',
+               LOSSRATE 0.1);
+
+e4 :: Rexmit(NAME 'REXMIT 1'); 
+
+r1 :: Metaprotocol(NAME 'MP1',
+		   ELEMENTS e1 e2 e3 e4, 
+	           PROCESS true, 
+                   AUTONEGOTIATE true);
+
+p1 :: RNAPktSrc(NAME 'PKTSRC1', 
+		PROCESS true); 
+
+b1 :: Buffer(NAME 'PKTSRCBUF1', 
+             PROCESS true,
+             COPIES true,
+	     DELAY true);
+
+src :: InfiniteSource(\<aaaaaaaaaaaaaa>, 2) 
+
+// Loopback the data that has been sent out. 
+elementclass loopback {
+	input[0]                    ->  Socket(UDP, 0.0.0.0, 20001)
+	Socket(UDP, 0.0.0.0, 20000) ->  [0] output 
+}
+
+l  :: loopback 
+
+// WAIT!!!!  
+
+// Make sure that Bufferelem has input ports 0/0 going upstream and
+// 1/1 going downstream when being used as stand alone protocol 
+// module
+
+src -> [0] p1 [0] -> [0] b1 [1] -> [0] r1 [1] -> Print -> [0] l
+l[0] -> Print -> [1] r1 [0] -> [1] b1 [0] -> Print -> Discard
Index: rna/conf/rna-rexmit-right.click
diff -u /dev/null rna/conf/rna-rexmit-right.click:1.2
--- /dev/null	Sun Jan 25 11:47:02 2009
+++ rna/conf/rna-rexmit-right.click	Fri Jan  2 14:06:58 2009
@@ -0,0 +1,61 @@
+//
+// Execute 
+//     cd <clickdir>/userlevel 
+//     ./click ../conf/rna-rexmit-right.click 
+// 
+// This will work only with rna-rexmit-left
+//
+//
+//
+//           PKTSRC2 (RNAPktSrc) 
+//              |
+//              V     
+//      +------------------+
+//      |        \     MP2 |
+//      |         \        |
+//      |          |       |
+//      |          V       |
+//      |         REXMIT2 (Rexmit) 
+//      |          |       |
+//      |          V       |
+//      |         FLEXLINK2 (FlexLink) 
+//      |          |       |
+//      |          V       |
+//      |         B2 MODULE (Buffer) 
+//      |         /        |
+//      |        /         |
+//      |       |          |
+//      |       V          |
+//      +------------------+
+//              |
+//              V
+//        To the left stack
+
+e1 :: Buffer(NAME 'B2 MODULE');
+
+e2 :: Demultiplexor(NAME 'DEMUX 2');
+
+e3 :: FlexLink(NAME 'FLEXLINK 2');
+
+e4 :: Rexmit(NAME 'REXMIT 2');
+
+r1 :: Metaprotocol(NAME 'MP2',
+		   ELEMENTS e1 e2 e3 e4,
+	           PROCESS true)
+
+p1 :: RNAPktSrc(NAME 'PKTSRC2', 
+		PROCESS true); 
+
+
+src :: InfiniteSource(\<aaaaaaaaaaaaaa>, 0) 
+
+// Loopback the data that has been sent out. 
+elementclass loopback {
+	input[0]                    ->  Socket(UDP, 0.0.0.0, 20000)
+	Socket(UDP, 0.0.0.0, 20001) ->  [0] output 
+}
+
+l  :: loopback 
+
+src -> Print -> [0] p1 [0] -> [0] r1 [1] -> Print -> [0] l
+l[0] -> Print -> [1] r1 [0] -> Print -> Discard
Index: rna/conf/test-ping.click
diff -u rna/conf/test-ping.click:1.1.10.1 rna/conf/test-ping.click:1.1.3.2
--- rna/conf/test-ping.click:1.1.10.1	Mon Sep  8 11:35:36 2008
+++ rna/conf/test-ping.click	Mon Sep  8 10:34:33 2008
@@ -29,3 +29,34 @@
 t[1]	-> host :: ToHost;
 c[2]	-> host;
 ip[1]	-> host;
+// test-ping.click
+
+// This kernel configuration tests the FromDevice and ToDevice elements
+// by sending pings to host 131.179.80.139 (read.cs.ucla.edu) via 'eth0'.
+// Change the 'define' statement to use another device or address, or run
+// e.g. "click-install test-ping.click DEV=eth1" to change a parameter at the
+// command line.
+//
+// You should see, in 'dmesg' or /var/log/messages, a sequence of "icmp echo"
+// printouts intermixed with "ping :: ICMPPingSource" receive reports.  Also
+// check out the contents of /click/ping/summary.
+
+define($DEV eth0, $DADDR 131.179.80.139, $GW 131.179.33.1)
+
+FromDevice($DEV)
+	-> c :: Classifier(12/0800, 12/0806 20/0002, -)
+	-> CheckIPHeader(14)
+	-> ip :: IPClassifier(icmp echo-reply, -)
+	-> ping :: ICMPPingSource($DEV, $DADDR)
+	-> SetIPAddress($GW)
+	-> arpq :: ARPQuerier($DEV)
+	-> IPPrint
+	-> q :: Queue
+	-> { input -> t :: PullTee -> output; t [1] -> ToHostSniffers($DEV) }
+	-> ToDevice($DEV);
+arpq[1]	-> q;
+c[1]	-> t :: Tee
+	-> [1] arpq;
+t[1]	-> host :: ToHost;
+c[2]	-> host;
+ip[1]	-> host;
Index: rna/elements/ip/siphmapper.cc
diff -u rna/elements/ip/siphmapper.cc:1.1.10.1 rna/elements/ip/siphmapper.cc:1.2
--- rna/elements/ip/siphmapper.cc:1.1.10.1	Mon Sep  8 11:35:44 2008
+++ rna/elements/ip/siphmapper.cc	Mon Sep  8 10:50:52 2008
@@ -1,7 +1,7 @@
 /*
  * sourceipmapper.{cc,hh} -- source IP mapper (using consistent hashing)
  *
- * $Id: siphmapper.cc,v 1.1.10.1 2008/09/08 18:35:44 pingali Exp $
+ * $Id: siphmapper.cc,v 1.2 2008/09/08 17:50:52 pingali Exp $
  *
  */
 
Index: rna/elements/rna/metaprotocol.cc
diff -u /dev/null rna/elements/rna/metaprotocol.cc:1.6
--- /dev/null	Sun Jan 25 11:47:09 2009
+++ rna/elements/rna/metaprotocol.cc	Fri Jan  2 14:06:58 2009
@@ -0,0 +1,1334 @@
+
+/* 
+
+################################################################
+#                                                              #
+# (c) University of Southern California                        #
+#                                                              #
+#  See LICENSE.RNA for the complete license                    #
+#                                                              #
+################################################################
+
+*/
+
+#include "rnaelement.hh" 
+#include "metaprotocol.hh" 
+
+class Handler; 
+
+CLICK_DECLS
+
+// This is the main file that implements the metaprotocol. It is yet
+// another RNA element, i.e., it is derived from the RNA element. Each
+// RNA Metaprotcol turns into a single protocol which corresponds to a
+// layer. The idea is to make the metaprotocol generic enough to
+// customize to any protocol at runtime. 
+//
+// It alters the composition of self using Click interfaces.
+// RNAElement provides a set of built in capabilities to alter the com
+//
+//
+// Patterns in memory: 
+//                                module namespace 
+//                                       |
+//                                       |
+//                                       V
+//  metaprotocol_patterns_db.txt --> patterns_parser.pl-->metaprotocol_patterns_db.cc
+//
+//
+// Use the patterns to dynamically adapt to a given situation
+// 
+//                             configuration/available modules   
+//                                          |
+//                                          V
+//                   Patterns file ----> metaprotocol 
+//
+//
+//             Feasible  --> Negotiate with --> Select --> Execute 
+//             Patterns  -->     Peer       --> Pattern-->   |
+//                ^                                          |
+//                |                                          |
+//                +------------------------------------------+
+//
+//
+
+//=========================================================
+//
+// Initialize/destroy the object
+//
+//=========================================================
+
+Metaprotocol::Metaprotocol()
+{
+
+  set_type(CONTROL); 
+  connection_oriented = true; 
+  _options = NULL;
+  instance = ""; 
+  _start_pattern = ""; 
+  _pattern_namespace = "DEFAULT"; 
+  enable_pattern_learning = false; 
+
+  autonegotiate = false; 
+  negotiation_ongoing = false; 
+  negotiation_pattern = 0; 
+  finished_negotiation = false; 
+  test_ongoing = false; 
+  finished_test = false; 
+  initialized_protocol = false; 
+
+
+};
+
+Metaprotocol::~Metaprotocol()
+{
+  //delete state; 
+};
+
+
+//=========================================================
+//
+// Element list processing...
+//
+// The configuration provides a list of elements for processing. This
+// is a function that will extract one element of a given type. There
+// are two versions - a version that is read only and another that
+// deletes the element before returning. 
+//
+//=========================================================
+
+//
+// Find the options element...
+//
+
+RNAElement *
+Metaprotocol::find_one_element(RNAElementType t){ 
+  
+  for (int i = 0; i < _elemlist.size(); i++){
+    RNAElement *e = _elemlist[i]; 
+    if (e && e->get_type() == t ){
+      return e; 
+    }
+  }
+  
+  return NULL; 
+};
+
+// 
+// Find an element of a given type and return that element. Remove the
+// element from the list.
+//
+
+RNAElement *
+Metaprotocol::find_one_element_erase(RNAElementType t){ 
+  
+  int elemnum = -1,i; 
+
+  for (i = 0; i < _elemlist.size(); i++){
+    RNAElement *e = _elemlist[i]; 
+    if (e && e->get_type() == t ){
+      elemnum = i; 
+      click_chatter("[%s] Metaprotocol::find_one_element_erase: "
+		    "found element %s \n", 
+		    instance_name(), e->instance_name());
+
+      break; 
+    }
+  };
+  
+  if (elemnum >= 0) {
+    RNAElement *e = _elemlist[i]; 
+    _elemlist.erase(_elemlist.begin() + i);
+    return e; 
+  } else { 
+    return NULL; 
+  };
+};
+
+//=========================================================
+//
+//
+// Select the next pattern - Given a list of possible pattern for the
+// next step, how should we select one? This is a place where
+// preferences and policy apply but there is is not support for them
+// at the present. We simply return the first valid pattern. 
+//
+//=========================================================
+
+Pattern *
+Metaprotocol::select_pattern(Vector<Pattern *> _patlist){
+  
+  // Return the very first...
+  if (_patlist.size() > 0)
+    return _patlist[0]; 
+  else 
+    return NULL; 
+};
+
+
+int
+Metaprotocol::update_capabilities(Pattern *p, ConfigType conf_in){
+  
+  if (!p) 
+    return -1; 
+  
+  // First obtain the list of capabilities altered by this pattern 
+  Vector<Capability *> c_list = p->Capabilities(); 
+  for (int i = 0; i < c_list.size(); i++){
+    
+    Capability *c = c_list[i];
+    
+    // For each capability check if we are in the right mode
+    // (CONFIG|UNCONFIG);
+    if (c->conf != conf_in)
+      continue; 
+    
+    // Execute the capability as long as it is set/unset. 
+    switch(c->c){
+      case CAP_VAR_CONNECTION_ORIENTED: 
+	if (c->cc == CAP_CHK_PRESENT) 
+	  connection_oriented = true; 
+	else if (c->cc == CAP_CHK_ABSENT) 
+	  connection_oriented = true; 	  
+	break;
+	
+      // Other variables come here....
+	
+      default: 
+	break;
+    }; // switch...
+
+  }; // Go through all the listed capabilities...
+  
+  return 0; 
+  
+}
+
+// #############################################################
+//
+// Handler for incoming test messages...
+//
+// #############################################################
+
+//
+// This is a function that tests the composition after execution by
+// sending a message back and forth. Only when the message is
+// received, the composition is assumed to complete and correct.
+//
+// Note: Metaprotocol does not allow concurrent testing of multiple
+// compositions. 
+
+//=========================================================
+//
+// Upon receiving a test request (after completion of negotiation and
+// execution), the peer sends a test reply. Upon receiving a test
+// reply, the negotiation process is assumed to be complete. If
+// autonegotiation is enabled, the process continues until it can
+// proceed no further. 
+//
+//=========================================================
+
+void
+Metaprotocol::test_reply(int port, Packet *p){
+  
+  (void)port; 
+  if (!p) 
+    return; 
+
+
+  unsigned char *data = (unsigned char *)p->data(); 
+
+  //=========================================================
+  // Sanity check....
+  //=========================================================  
+  if ((test_ongoing == false) || 
+      (*(data + 1) != MESSAGE_DATA_TEST) || 
+      (*(data + 2) != MESSAGE_DATA_TEST_ECHO_REPLY)) { 
+    rna_click_chatter(FUNC_DEFAULT,"[%s] Metaprotocol::test_reply "
+		      "reply %s \n", 
+		      instance_name(), 
+		      ((test_ongoing == false) ? "unexpected" : "wrong type")
+		      );
+    p->kill();
+    return; 
+  };
+  
+  //=========================================================
+  // Process the reply
+  //=========================================================
+  if (*(data + 2) == MESSAGE_DATA_TEST_ECHO_REPLY){
+
+    rna_click_chatter(FUNC_DEFAULT,"[%s] Metaprotocol::test_reply "
+		      "Handled reply\n\n", 
+		      instance_name());
+
+    // update the flags 
+    test_ongoing = false; 
+    finished_test = true; 
+    initialized_protocol = true; 
+    
+    // Eliminate the packet...
+    p->kill();
+
+    // If autonegotiate is enabled, then extract the next feasible
+    // pattern and initiate the negotiation with that pattern. 
+    if (autonegotiate){ 
+
+      if (negotiation_pattern->Name() == "NULL" && 
+	  _start_pattern != ""){ 
+
+	click_chatter("[%s] Metaprotocol::push_management - "
+		      " calling for startpat _start_pattern = %s \n", 
+		      instance_name(), _start_pattern.c_str()); 
+
+
+	Pattern * startpat = state->find_pattern(_start_pattern);
+	if (!startpat){
+	  
+	  click_chatter("[%s] Metaprotocol::test_reply - Start pattern %s " 
+			"not found", 
+			instance_name(), _start_pattern.c_str());
+	} else {
+	  initiate_negotiation(startpat); 
+	};
+
+      } else { 
+	Vector<Pattern *> next_pats = state->find_next_verified_patterns(); 
+
+	click_chatter("[%s] Metaprotocol::test_reply Found %d next patterns\n",
+		      instance_name(), next_pats.size());
+
+	for ( int i = 0; i < next_pats.size(); i++){ 
+	  Pattern *np = next_pats[i];
+	  click_chatter("[%s] Metaprotocol::test_reply "
+			" Potential next pattern is %s \n", 
+			instance_name(), np->Name().c_str()); 
+	}
+
+	if (next_pats.size() > 0){ 
+	  Pattern *next_pat = select_pattern(next_pats); 
+	  initiate_negotiation(next_pat); 
+	};
+      };
+    };
+    
+  };
+
+  return; 
+  
+};
+
+//
+// This test request is typically sent by the peer initiating the
+// negotiation. The test message is intended for exactly that -
+// testing whether the composition has been successful or not.  This
+// involves generating a new message labeled as test in the header and
+// sending it over the intra-layer outgoing links.
+
+void 
+Metaprotocol::test_request(int port, Packet *p){
+  
+  const char *func = __FUNCTION__;
+
+  click_chatter("[%s] Metaprotocol::test_request Entered", instance_name());
+  
+  //---------------------------------------------------------
+  // Sanity checks...
+  //---------------------------------------------------------
+  if (!p){ 
+    click_chatter("[%s] Metaprotocol::test_request Error - undefined message", 
+		  instance_name());
+    return; 
+  };
+
+
+  LinkState *incoming_link = lookup_link(port);
+  if (! incoming_link ){
+    rna_click_chatter(FUNC_DEFAULT,
+		      "[%s] Metaprotocol::test_request Dropping packet...\n", 
+		      instance_name()); 
+    p->kill();
+    return;
+  };   
+  
+  //---------------------------------------------------------
+  // Make sure that the message has a known type
+  //---------------------------------------------------------
+  unsigned char *data = (unsigned char *)p->data();
+
+  int data_message_type = *(data + 1);
+  if (data_message_type != MESSAGE_DATA_TEST) {
+    click_chatter("[%s] Metaprotocol::test_request Error - Wrong kind of message", 
+		  instance_name());
+    p->kill(); 
+    return; 
+  };
+  
+  
+  data_message_type = *(data + 2);
+  if (data_message_type != MESSAGE_DATA_TEST_ECHO_REQUEST){ 
+    click_chatter("[%s] Metaprotocol::test_request Error - "
+		  "Unknown test message type..", 
+		  instance_name());
+    p->kill(); 
+    return; 
+  };    
+  
+  //---------------------------------------------------------
+  // Send the reply...
+  //---------------------------------------------------------
+
+  // rewrite the first three bits of the header...
+  data = (unsigned char *)p->data(); 
+  *data = MESSAGE_DATA; 
+  *(data + 1) = MESSAGE_DATA_TEST; 
+  *(data + 2) = MESSAGE_DATA_TEST_ECHO_REPLY; 
+
+  // Eventually we might have to send some more information e.g., a
+  // nonce.
+
+  // Figure out where to send the message out. If the incoming message
+  // has come on a intra-layer link, then 
+
+  bool crosslayer = incoming_link->is_crosslayer(); 
+  LinkState *l = NULL; 
+  
+  l = select_outgoing_link(p, NULL, 
+			 true,       /* headed downstream */ 
+			 false,      /* not layer agnostic */
+			 crosslayer, /* cross layer */ 
+			 true,       /* agnostic remote endpoint */
+			             /* of the cross-layer link */
+			 false       /* doesnt matter */
+			 );
+  
+  if (! push_data_to_link(p, l, func)){
+    p->kill();
+  };
+   
+  click_chatter("[%s] Metaprotocol::test_request Exited", instance_name());
+
+  return;
+  
+};
+
+//=========================================================
+//
+// Initiate a test message to the peer...This is typically executed at
+// the end that initiated the negotiation process.
+//
+//=========================================================
+
+int
+Metaprotocol::initiate_test(bool crosslayer, String teststring, LinkState *l){ 
+
+  const char *func = __FUNCTION__; 
+
+  if (teststring.length() > 255) { 
+    click_chatter("[%s] Metaprotocol::initiate_test Error! "
+		  "teststring greater than 255 bytes", 
+		  instance_name());
+    return -1; 
+  };
+  
+
+  //=========================================================
+  // Generate the test message...
+  //=========================================================
+  
+  // Create a new packet
+  WritablePacket *p = Packet::make(teststring.length() + 4);  
+  unsigned char *data = (unsigned char *)p->data();   
+  
+  // Copy three bytes of header...
+  *data = MESSAGE_DATA; 
+  *(data + 1) = MESSAGE_DATA_TEST; 
+  *(data + 2) = MESSAGE_DATA_TEST_ECHO_REQUEST;
+  *(data + 3) = teststring.length(); 
+  memcpy(data + 4, teststring.c_str(), teststring.length()); 
+  
+
+  //=========================================================
+  // Find the outgoing link and send it out...
+  //=========================================================
+  
+  if (!l) 
+    l = select_outgoing_link(p, NULL, 
+			     true,       /* headed downstream */ 
+			     false,      /* not layer agnostic */
+			     crosslayer, /* cross layer */ 
+			     true,       /* agnostic remote endpoint */
+ 			                 /* of the cross-layer link */
+			     false       /* doesnt matter */
+			     );
+
+  if (l) { 
+    discover_connectionstate(l); 
+    if (l->connection_oriented) { 
+      ConnectionState *c = l->connstate_get(); 
+      SET_CONN_ANNO(p, c); 
+    };	  
+  };
+  
+  if (! push_data_to_link(p, l, func)){
+    p->kill();
+  };
+
+  test_ongoing = true;   
+  return 0;
+
+};
+
+
+//=========================================================
+// 
+// Initiate an exchange with the other endpoint regarding a potential
+// composition. The process might result in a success of failure. The
+// negotiation process must be modified to handle all possible
+// errors. For now, this is a fragile process. 
+//
+//=========================================================
+
+int
+Metaprotocol::initiate_negotiation(Pattern *next_pattern){ 
+
+  const char *func = __FUNCTION__; 
+
+  if (!next_pattern) { 
+    click_chatter("[%s] Metaprotocol::initiate_negotiation(*) - Failed. "
+		  "Pattern argument is undefined.",
+		  instance_name());
+    return -1;
+  }; 
+  
+  // Mostly useful only for printing purpose...
+  String s = next_pattern->Name(); 
+  click_chatter("[%s] Metaprotocol::initiate_negotiation(%s) Entering",
+		instance_name(), s.printable().c_str());
+  
+  // Check if we are in the middle of an exchange
+  if (negotiation_ongoing == true) {
+    click_chatter("[%s] Metaprotocol::initiate_negotiation(%s) - Terminated "
+		  "Negotiation ongoing.",
+		  instance_name(), s.printable().c_str());
+    return -1; 
+  }
+
+
+  //=========================================================
+  // Extract the pattern 
+  //=========================================================
+  
+  int ret = next_pattern->Verify(); 
+  if (ret < 0){  
+    click_chatter("[%s] Metaprotocol::initiate_negotiation(%s) - Failed. "
+		  "Pattern not verified.", 
+		  instance_name(), s.printable().c_str());    
+    return -1; 
+  };
+
+  click_chatter("[%s] Metaprotocol::initiate_negotiation(%s) - "
+		"verify successful", 
+		instance_name(), s.printable().c_str());
+
+  //=========================================================
+  // Generate the negotiation packet....
+  //=========================================================
+
+  Packet *p = next_pattern->GenerateMessage(); 
+  p->push(3); 
+  unsigned char *data = (unsigned char *)p->data(); 
+  *data = MESSAGE_CONTROL; 
+  *(data + 1) = MESSAGE_CONTROL_NEGOTIATE; 
+  *(data + 2) = MESSAGE_CONTROL_NEGOTIATE_REQUEST; 
+  
+  LinkState *l = select_outgoing_link(p, NULL, 
+				    true, /* headed downstream */ 
+				    false, /* not layer agnostic */
+				    true, /* cross layer */ 
+				    true, /* agnostic remote endpoint */
+					  /* of the cross-layer link */
+				    false /* doesnt matter */
+				    );
+
+  // If an outgoing link exists, then send the packet along the link
+  if (0) { 
+    discover_connectionstate(l); 
+    if (l->connection_oriented) { 
+      ConnectionState *c = l->connstate_get(); 
+      SET_CONN_ANNO(p, c); 
+    };	  
+  };
+  
+  if (! push_data_to_link(p, l, func)){
+    p->kill();
+  };
+
+  
+  negotiation_ongoing = true; 
+  negotiation_pattern = next_pattern; 
+
+  // rna_click_chatter(FUNC_DEFAULT,"[%s] Metaprotocol::initiate_negotiation()"
+  //	    "returning\n", instance_name()); 
+  return 0;
+
+};
+
+
+
+//=========================================================
+//
+
+// Upon receiving a negotiation request, a reply is generated. This
+// function is called at the initiator end of the neogitiation. 
+
+//
+//=========================================================
+
+void
+Metaprotocol::negotiate_reply(Packet *p){
+
+  const char *func = __FUNCTION__; 
+  
+  if (!p) 
+    return; 
+  
+  if (debug) 
+    rna_click_chatter(FUNC_DEFAULT,"[%s] Metaprotocol::negotiate_reply "
+		      "Enter\n", instance_name());
+  
+  unsigned char *data = (unsigned char *)p->data(); 
+
+  //=========================================================
+  // Sanity check....
+  //=========================================================  
+  if ((negotiation_ongoing == false) || 
+      (*(data + 1) != MESSAGE_CONTROL_NEGOTIATE)) { 
+    rna_click_chatter(FUNC_DEFAULT,"[%s] Metaprotocol::negotiate_reply "
+		      "Dropping packet...negotiation not in progress "
+		      "or wrong message type\n", 
+		      instance_name());
+    p->kill();
+    return; 
+  };
+  
+  //=========================================================
+  // Process the reply
+  //=========================================================
+  if (*(data + 2)  == MESSAGE_CONTROL_NEGOTIATE_REPLY_SUCCESS){
+
+    rna_click_chatter(FUNC_DEFAULT,"[%s] Metaprotocol::negotiate_reply "
+		      "process successful reply\n", instance_name());
+
+    // Execute the pattern 
+    state->execute_pattern(negotiation_pattern); 
+
+    // Get new capabilities...
+    update_capabilities(negotiation_pattern, CONF_CONFIG); 
+
+    // Cleanup 
+    negotiation_ongoing = false; 
+    finished_negotiation = true; 
+    p->kill();
+
+    rna_click_chatter(FUNC_DEFAULT,"[%s] Metaprotocol::negotiate_reply "
+		      "Initiate testing\n", instance_name());
+    
+    // Now initiate testing...
+    String pattern_name = negotiation_pattern->Name(); 
+    Vector<RNAElement *> used_elemlist = state->get_used_elements(); 
+    bool crosslayer = false; 
+    if (pattern_name == "NULL" || used_elemlist.size() == 0)
+      crosslayer = true; 
+
+    String testpattern = negotiation_pattern->Name();
+    initiate_test(crosslayer, testpattern, 0);
+
+  };
+
+  if (*(data + 2) == MESSAGE_CONTROL_NEGOTIATE_REPLY_FAILURE){
+
+    rna_click_chatter(FUNC_DEFAULT,"[%s] Metaprotocol::negotiate_reply "
+		      "Dropping packet - failure in reply\n", instance_name());
+
+    // Cleanup 
+    negotiation_ongoing = false; 
+    finished_negotiation = true; 
+    negotiation_pattern = 0; 
+    p->kill();
+        
+  };
+
+  if (*(data + 2)  == MESSAGE_CONTROL_NEGOTIATE_REPLY_LEARN_REQUEST){
+    
+    // This message has from the peer to whom a specific pattern has
+    // been proposed. The negotiation pattern must be encoded and 
+    // sent back. 
+    
+    int encoded_size = negotiation_pattern->encoded_size(); 
+    p->pull(p->length());
+    p->push(3 + encoded_size); 
+    
+    data = (unsigned char *)p->data(); 
+    *(data + 0) = MESSAGE_CONTROL;
+    *(data + 1) = MESSAGE_CONTROL_NEGOTIATE;
+    *(data + 2) = MESSAGE_CONTROL_NEGOTIATE_REPLY_LEARN_REPLY;     
+    
+    // Encode the entire pattern...
+    negotiation_pattern->encode(data + 3); 
+
+    rna_click_chatter(FUNC_DEFAULT,"[%s] Metaprotocol::negotiate_reply "
+		      "Sending encoded pattern (encoded size = %d; pkt size = %d)\n", 
+		      instance_name(), encoded_size, p->length());
+
+    // Send the packet...
+    LinkState *l = select_outgoing_link(p, NULL, 
+					true, /* headed downstream */ 
+					false, /* not layer agnostic */
+					true, /* cross layer */ 
+					true, /* agnostic remote endpoint */
+					/* of the cross-layer link */
+					false /* doesnt matter */
+					);
+    
+    // If an outgoing link exists, then send the packet along the link
+    if (l) { 
+      if (0) { 
+	discover_connectionstate(l); 
+	if (l->connection_oriented) { 
+	  ConnectionState *c = l->connstate_get(); 
+	  SET_CONN_ANNO(p, c); 
+	};	  
+      };
+    };
+    
+    if (! push_data_to_link(p, l, func)){
+      p->kill();
+    };
+
+  };
+
+  return; 
+  
+};
+  
+
+//=========================================================
+//
+// Handle the request from the peer
+//
+//=========================================================
+void
+Metaprotocol::negotiate_request(Packet *p, bool is_learn_reply){
+
+  const char *func = __FUNCTION__; 
+
+  bool send_learning_request = false; 
+
+  if (!p) 
+    return; 
+  
+  if (negotiation_ongoing == true && !is_learn_reply){
+    rna_click_chatter(FUNC_DEFAULT,
+		      "[%s] Metaprotocol::negotiate_request - Failure; "
+		      "Dropping packet due to ongoing negotiation\n", 
+		      instance_name()); 
+    return; 
+  };
+  
+
+  // Drop the negotiate flag and the type of negotiate message
+  p->pull(3); 
+  unsigned char *data = (unsigned char *) p->data(); 
+
+  //=========================================================
+  // Sanity check....
+  //=========================================================
+  if (!initialized_protocol) {
+    if (((int)*(data) != 4) || (memcmp("NULL", data + 1, 4) != 0)){
+      rna_click_chatter(FUNC_DEFAULT,
+			"[%s] Not initialized and the pattern is "
+			"not NULL. So dropping packet...\n", 
+			instance_name()); 
+      p->kill(); 
+      return; 
+    };
+  };
+  
+  // Ultimately what we want is this - the pattern object...
+  Pattern *matched_pattern = 0; 
+  
+  // Extract the pattern name...
+  if ( ! is_learn_reply ){ 
+
+    int length = *(data + 0); 
+    String proposed_pattern_name((const char *)data + 1, length); 
+
+    rna_click_chatter(FUNC_DEFAULT,
+		      "[%s] Metaprotocol::negotiate_request - proposed "
+		      "pattern name  = %s\n", 
+		      instance_name(), 
+		      proposed_pattern_name.c_str()); 
+  
+    
+    Vector<Pattern *> patlist = state->get_all_patterns();   
+    for (int i = 0; i < patlist.size(); i++){
+      Pattern *pat = patlist[i];
+      if (pat->ValidateMessage(proposed_pattern_name) >= 0){
+	matched_pattern = pat; 
+	break; 
+      };
+    };
+  
+    if (!matched_pattern){ 
+
+      if (enable_pattern_learning) { 
+	send_learning_request = true; 
+	rna_click_chatter(FUNC_DEFAULT,
+			  "[%s] Metaprotocol::negotiate_request "
+			  "Sending learn request for %s \n",
+			  instance_name(), proposed_pattern_name.c_str());
+
+      } else { 
+	rna_click_chatter(FUNC_DEFAULT,
+			  "[%s] Metaprotocol::negotiate_request - pattern %s "
+			  "Didnt match any pattern; Dropping packet...\n", 
+			  instance_name(), proposed_pattern_name.c_str()); 
+      };
+    };
+
+  } else {
+
+    // The reply contains the pattern embedded into the message...
+    
+    matched_pattern = new Pattern(state);
+    int len = matched_pattern->decode((const unsigned char *)data); 
+
+    rna_click_chatter(FUNC_DEFAULT,
+		      "[%s] Metaprotocol::negotiate_request "
+		      "Decoded message of length %d (total pkt len = %d) \n",
+		      instance_name(), len, p->length());
+    if (len == 0){
+
+      // Decoding has failed...
+      delete matched_pattern; 
+      matched_pattern = 0; 
+
+    } else {
+
+      if (!state->learn_pattern(matched_pattern)){
+	delete matched_pattern; 
+	matched_pattern = 0; 
+      };
+      
+      rna_click_chatter(FUNC_DEFAULT,
+			"[%s] Metaprotocol::negotiate_request Learnt pattern %s \n",
+			instance_name(), matched_pattern->Name().c_str());
+    };
+
+  };
+          
+
+  if (send_learning_request && !is_learn_reply) { 
+    
+    // Push a new header in...
+    int length = p->length();
+    p->pull(length); // Account for the string length...
+    p->push(3); 
+    data = (unsigned char *)p->data();
+    *(data + 0) = MESSAGE_CONTROL;
+    *(data + 1) = MESSAGE_CONTROL_NEGOTIATE;
+    *(data + 2) = MESSAGE_CONTROL_NEGOTIATE_REPLY_LEARN_REQUEST;     
+
+  } else { 
+
+    //=========================================================
+    // Generate a reply; use the incoming message. 
+    //=========================================================
+    
+    int length = p->length();
+    p->pull(length); 
+    p->push(3); 
+    data = (unsigned char *)p->data();
+    *(data + 0) = MESSAGE_CONTROL;
+    *(data + 1) = MESSAGE_CONTROL_NEGOTIATE;
+    
+    if (matched_pattern){ 
+      // Ok; Now obtained the matched pattern 
+      String name = matched_pattern->Name(); 
+      rna_click_chatter(FUNC_DEFAULT,
+			"[%s] Metaprotocol::negotiate_request Matched pattern %s \n", 
+			instance_name(), name.c_str()); 
+      
+      //=========================================================
+      // Can this pattern be instantiated? 
+      //=========================================================
+      int ret = matched_pattern->Verify(); 
+      //click_chatter("[%s] Metaprotocol::push_control() - verify ret = " 
+      //	"%d", instance_name(), ret); 
+      
+      if (ret < 0){  
+	click_chatter("[%s] Metaprotocol::negotiate_request (%s) - Failed. "
+		      "Pattern not verified.", 
+		      instance_name(), name.printable().c_str());
+      *(data + 2) = MESSAGE_CONTROL_NEGOTIATE_REPLY_FAILURE;
+      } else {
+	*(data + 2) = MESSAGE_CONTROL_NEGOTIATE_REPLY_SUCCESS;
+	click_chatter("[%s] Metaprotocol::negotiate_request (%s) - Successful. "
+		      "Pattern verified.",
+		      instance_name(), name.printable().c_str());
+      };
+    
+      // Finish executing the pattern...
+      if (ret >= 0) {
+	state->execute_pattern(matched_pattern);
+	update_capabilities(matched_pattern, CONF_CONFIG); 
+      };
+      
+    } else {
+      
+
+      *(data + 2) = MESSAGE_CONTROL_NEGOTIATE_REPLY_FAILURE;
+      if (is_learn_reply){ 
+	click_chatter("[%s] Metaprotocol::negotiate_request (%s) - Corrupted pattern received.", 
+		      instance_name());
+      } else {
+	click_chatter("[%s] Metaprotocol::negotiate_request (%s) - Unknown pattern.", 
+		      instance_name());
+      };
+
+    }; // check for a specific matched pattern...
+  };
+
+  //=========================================================
+  // Send a reply back...
+  //=========================================================
+  // Extract the outgoing path/lnk
+  LinkState *l = select_outgoing_link(p, NULL, 
+				    true, /* headed downstream */ 
+				    false, /* not layer agnostic */
+				    true, /* cross layer */ 
+				    true, /* agnostic remote endpoint */
+				    /* of the cross-layer link */
+				    false /* doesnt matter */
+				    );
+  if (l){ 
+    if (0) { 
+      discover_connectionstate(l); 
+      if (l->connection_oriented) { 
+	ConnectionState *c = l->connstate_get(); 
+	SET_CONN_ANNO(p, c); 
+      };	  
+    };
+  };
+
+  if (! push_data_to_link(p, l, func)){
+    p->kill();
+  };
+
+  finished_negotiation = true; 
+  initialized_protocol = true; 
+
+  return; 
+  
+};
+
+void
+Metaprotocol::push_management(int port, Packet *p){
+
+  click_chatter("[%s] Metaprotocol::push_management  - received a "
+		"management message", 
+		instance_name());
+  
+  LinkState *l = lookup_link (port); 
+  if (!l) 
+    return; 
+  
+  // If I am downstream and I havent completed negotiation...
+  if (!l->is_downstream() || !l->is_crosslayer()){ 
+    click_chatter("[%s] Metaprotocol::push_management  - not downstream and "
+		  "cross layer message \n", 
+		  instance_name());    
+    return; 
+  };
+  
+  unsigned char *data = (unsigned char *)p->data(); 
+  if ((*( data + 0) != MESSAGE_MANAGEMENT) || 
+      ((*(data + 1) != MESSAGE_MANAGEMENT_ADD_MODULE) && 
+       (*(data + 1) != MESSAGE_MANAGEMENT_DEL_MODULE))){
+    click_chatter("[%s] Metaprotocol::push_management  - wrong message type \n",
+		  instance_name());    
+    return; 
+  };
+
+  if (negotiation_ongoing || test_ongoing ){
+    
+    p->kill();		
+    click_chatter("[%s] Metaprotocol::push_management - "
+		  "Killing packet. Negotiation/testing ongoing\n",
+		  instance_name()); 
+    return; 
+  };
+  
+  if (*(data + 1) == MESSAGE_MANAGEMENT_ADD_MODULE){ 
+    
+    if (initialized_protocol == false){
+
+      Pattern * nullpat = state->find_pattern("NULL");
+      initiate_negotiation(nullpat); 
+
+    } else { 
+
+      Vector<Pattern *> next_pats = state->find_next_verified_patterns(); 
+      if (next_pats.size() > 0){ 
+	
+	click_chatter("[%s] Metaprotocol::push_management Found %d next patterns\n",
+		      next_pats.size());
+
+	for ( int i = 0; i < next_pats.size(); i++){ 
+	  Pattern *np = next_pats[i];
+	  click_chatter("[%s] Metaprotocol::push_management "
+			" Potential next pattern is %s \n", 
+			instance_name(), np->Name().c_str()); 
+	}
+	
+	Pattern *next_pat = select_pattern(next_pats); 	
+	if (!next_pat){ 
+	  click_chatter("[%s] Metaprotocol::Push management- "
+			" Next pattern is unknown ", 
+			instance_name()); 
+	} else { 
+	  initiate_negotiation(next_pat); 
+	};
+      }; // next_pats.size() > 0
+
+    };
+  };
+  
+  if (*(data + 1) == MESSAGE_MANAGEMENT_DEL_MODULE){ 
+    // ...
+  };
+  
+  return;
+};
+
+//=========================================================
+//
+// Handle the data from the other layers 
+//
+//=========================================================
+
+void
+Metaprotocol::push_data(int port, Packet *p){
+
+  (void)port; 
+  (void)p; 
+  
+  LinkState *l = lookup_link (port); 
+  if (!l) 
+    return; 
+  
+  if (l->is_crosslayer()) { 
+    click_chatter("\n\n----------------------------------------------------------\n\n");
+    click_chatter("[%s] Metaprotocol::push_data - received a data message", 
+		  instance_name());
+  };
+
+  
+  // If I am downstream and I havent completed negotiation...
+  if (l->is_downstream()){ 
+
+
+    if (initialized_protocol == false){
+      
+      // I am not initialized, yet. So throw away the message from the
+      // layer above.
+      
+      p->kill();
+      
+      click_chatter("[%s] Metaprotocol::push_data - "
+		    "Killing packet. Protocol not initialized. \n",
+		    instance_name()); 
+      
+      if (autonegotiate) { 
+	Pattern * nullpat = state->find_pattern("NULL");
+	initiate_negotiation(nullpat); 
+      };
+      
+    } else { 
+      
+      // =========================================================
+      // See if there are any more patterns. If there are, then
+      // negotiate them. Otherwise simply send data...
+      // =========================================================
+      
+      if (l->is_crosslayer() && 
+	  (negotiation_ongoing || test_ongoing )){
+
+	p->kill();		
+	click_chatter("[%s] Metaprotocol::push_data - "
+		      "Killing packet. Negotiation/testing ongoing\n",
+		      instance_name()); 
+	
+      } else {
+	//
+	// Add a header saying this layer is not doing anything
+	// interesting...
+	//
+	
+	p->push(3); 
+	unsigned char *data = (unsigned char *)p->data(); 
+	*data = MESSAGE_DATA; 
+	*(data + 1) = MESSAGE_DATA_NORMAL; 
+	*(data + 2) = 0; 
+	
+	if (debug) 
+	  RNAElement::print_packet("push_data", p, false);
+	
+	RNAElement::push_data(port, p); 
+      }
+            
+    };
+
+  } else { 
+    
+    //
+    // Coming from the lower layer...
+    //
+    
+    unsigned char *data = (unsigned char *)p->data(); 
+
+    if (*(data + 1) == MESSAGE_DATA_NORMAL){
+      click_chatter("[%s] Metaprotocol::push_data - "
+		    "Normal data. Pushing to intra-layer module.\n", 
+		    instance_name()); 
+      p->pull(3); 
+      RNAElement::push_data(port, p); 
+    };
+    
+    // Test message....
+    if (*(data + 1) == MESSAGE_DATA_TEST){ 
+      click_chatter("[%s] Metaprotocol::push_data - "
+		    "received TEST_%s (%d)\n", 
+		    instance_name(), 
+		    ((*(data + 2) == MESSAGE_DATA_TEST_ECHO_REQUEST) ? 
+		     "REQUEST" : "REPLY"),
+		    (int)(*(data + 2))); 
+
+      if (*(data + 2) == MESSAGE_DATA_TEST_ECHO_REQUEST)
+	test_request(port, p);
+      else 
+	test_reply(port, p);	
+    };
+
+  };
+
+  click_chatter("\n\n----------------------------------------------------------\n\n");
+
+  return; 
+};
+
+//=========================================================
+//
+// Handle control messages from the peer
+//
+//=========================================================
+
+void
+Metaprotocol::push_control(int port, Packet *p){
+
+  click_chatter("[%s] Metaprotocol::push_control - received a "
+		"control message", 
+		instance_name());
+  
+  if (!p) 
+    return; 
+  
+  //=========================================================
+  // Extract Data/incoming link
+  //=========================================================
+
+  LinkState *incoming_link = lookup_link(port);
+  if (! incoming_link ){
+    rna_click_chatter(FUNC_DEFAULT,
+		      "[%s] Dropping packet...\n", 
+		      instance_name()); 
+    p->kill();
+    return;
+  };   
+  
+  //=========================================================
+  // Receive a control message from the peer....
+  //=========================================================
+
+  // *data MESSAGE_CONTROL is already been pulled. 
+  unsigned char *data = (unsigned char *)p->data(); 
+  if (*(data + 1) != MESSAGE_CONTROL_NEGOTIATE){
+
+    if (debug) 
+      RNAElement::print_packet("push_control", p, false);
+
+    if (debug) 
+      rna_click_chatter(FUNC_DEFAULT,
+		      "[%s] Dropping packet...Unknown control message (%d)\n", 
+		      *(data + 1), 
+		      instance_name()); 
+    p->kill();
+    return;
+  };       
+  
+  
+  if ( *(data + 2) == MESSAGE_CONTROL_NEGOTIATE_REQUEST) { 
+    rna_click_chatter(FUNC_DEFAULT,
+		      "[%s] Metaprotocol::push_control negotiation request\n",
+		      instance_name()); 
+    negotiate_request(p); 
+  };
+
+
+  //=========================================================
+  // Handle the reply....
+  //=========================================================
+  if ((*(data + 2) == MESSAGE_CONTROL_NEGOTIATE_REPLY_FAILURE) || 
+      (*(data + 2) == MESSAGE_CONTROL_NEGOTIATE_REPLY_SUCCESS) || 
+      (*(data + 2) == MESSAGE_CONTROL_NEGOTIATE_REPLY_LEARN_REQUEST)){
+    
+    rna_click_chatter(FUNC_DEFAULT,
+		      "[%s] Metaprotocol::push_control received negotiation "
+		      "reply \n",
+		      instance_name());
+    negotiate_reply(p);
+  };
+
+  if (*(data + 2)  == MESSAGE_CONTROL_NEGOTIATE_REPLY_LEARN_REPLY){
+    rna_click_chatter(FUNC_DEFAULT,
+		      "[%s] Metaprotocol::push_control negotiation request\n",
+		      instance_name()); 
+    bool is_learn_reply = true; 
+    negotiate_request(p, is_learn_reply); 
+  };
+
+
+  return; 
+
+};
+
+//========================================================= 
+//
+// Dont add any intra-protocol links. Simply ensure that the up and
+// down inter-protocol links are added.
+//
+//=========================================================
+
+int 
+Metaprotocol::finish_configuration(){ 
+  
+  //struct linkspec *link;
+  Vector<struct linkspec *> linkspecs; 
+
+  click_chatter("[%s] Metaprotocol::finish_configuration() - " 
+		"noutputs = %d ninputs = %d\n", 
+		instance_name(), noutputs(), ninputs()); 
+
+#ifdef COMMENT
+  if (noutputs() < 2 || _elemlist.size() < 2) {
+    rna_click_chatter(FUNC_DEFAULT, 
+		      "[%s] ERROR! Metaprotocol::finish_configuration() - "
+		      "noutputs < 2 || element list < 2", 
+		      instance_name());
+    return -1; 
+  }
+
+  
+  // Is this an independent initiator of the link creation? 
+
+  if (exec_finish_configuration) { 
+    add_default_bidirectional_links(&linkspecs, true); 
+  };
+#endif
+  
+  if (exec_finish_configuration) {
+    if (_preconfigured_element_list) 
+      add_default_autodetect_links(&linkspecs, true); 
+    else 
+      add_default_bidirectional_links(&linkspecs, true); 
+  };
+  
+  //==================================================
+  
+  process_linkspecs(linkspecs);
+  
+  // print_links(); 
+
+  // Print out the table for the elements specified....
+  if (0) 
+    click_chatter("[%s] Element [myindex = %d, index = %d, inputs = %d, "
+		  "outputs = %d] \n", 
+		  instance_name(), eindex(), this->eindex(), 
+		  this->ninputs(), this->noutputs());
+
+  for (int i = 0; i < _elemlist.size(); i++){
+    Element *e = _elemlist[i]; 
+    if (0) 
+      click_chatter("[%s] Element [myindex = %d, index = %d, inputs = %d, "
+		    "outputs = %d] \n", 
+		    instance_name(), eindex(), e->eindex(), 
+		    e->ninputs(), e->noutputs());
+  };
+
+  // Test all the ports...
+  for (int i = 0; i < noutputs(); i++) { 
+    Port p = output(i); 
+    if (p.active()) {
+      Element *sender = p.element(); 
+      if (0) 
+	click_chatter("[%s] Metaprotocol::output port %d => %s\n", 
+		      instance_name(), i, sender->class_name()); 
+    } else {
+      if (0) 
+	click_chatter("[%s] Metaprotocol::output port %d => "
+		      "inactive \n", instance_name(), i);
+    }
+  };
+
+  
+  return 0; 
+};
+
+//===============================================================
+//
+// Initial configuration of this module. Read the parameters from the
+// configuration file....
+//
+//===============================================================
+
+int
+Metaprotocol::configure(Vector<String> &conf, ErrorHandler *errh)
+{
+  
+  RNAElement::configure(conf, errh); 
+  
+  if (cp_va_parse(conf, this, errh,
+		  cpKeywords, 
+		  "NAMESPACE", cpString, "Pattern Namespace", &_pattern_namespace,
+		  "AUTONEGOTIATE", cpBool, "Negotiate automatically", &autonegotiate,
+		  "LEARNING", cpBool, "Enable learning of patterns from peers", &enable_pattern_learning,
+		  cpEnd) < 0)
+    return -1; 
+
+  // Allocate state; Add the CONTROL element to element list provided
+  // to the state.
+  state = new State(this, _pattern_namespace, _elemlist); 
+  _start_pattern = state->get_start_pattern(); 
+  
+  if (exec_finish_configuration) 
+    finish_configuration();    
+  
+  return 0;
+};
+
+ELEMENT_REQUIRES(State)
+ELEMENT_REQUIRES(RNAElement)
+EXPORT_ELEMENT(Metaprotocol)
+
+CLICK_ENDDECLS
Index: rna/elements/rna/metaprotocol.hh
diff -u /dev/null rna/elements/rna/metaprotocol.hh:1.3
--- /dev/null	Sun Jan 25 11:47:09 2009
+++ rna/elements/rna/metaprotocol.hh	Fri Dec 26 16:56:59 2008
@@ -0,0 +1,96 @@
+/* 
+
+################################################################
+#                                                              #
+# (c) University of Southern California                        #
+#                                                              #
+#  See LICENSE.RNA for the complete license                    #
+#                                                              #
+################################################################
+
+*/
+#ifndef CLICK_TEST_DYNCONTROLELEMENT_HH
+#define CLICK_TEST_DYNCONTROLELEMENT_HH
+
+#include "rnaelement.hh" 
+
+//================================================================
+//
+// Core protocol - this will compose all other protocol modules 
+//
+// A lot of work is done in the RNAElement class, state and pattern
+// classes. So this appears a little more simpler than it is. 
+//
+//================================================================
+class Metaprotocol : public RNAElement { 
+public:
+
+  Metaprotocol();
+  ~Metaprotocol();
+
+  static void static_initialize() { static_initialize_default(); };
+  static void static_cleanup() { static_initialize_default(); };
+  
+  // Click stuff...
+  const char *class_name() const	{ return default_class_name();}
+  const char *port_count() const	{ return "-/-"; }
+  const char *processing() const	{ return PUSH; } 
+  int configuration_phase()             { return CONFIGURE_PHASE_LAST; };   
+  int configure(Vector<String> &, ErrorHandler *);
+  int finish_configuration(); 
+  bool can_live_reconfigure() const     { return true; }
+  
+  // Negotiation with the peer...
+  int initiate_negotiation(Pattern *); 
+  void negotiate_request(Packet *p, bool learn_reply = false);
+  void negotiate_reply(Packet *p);
+  
+  // Message flow...
+  void push_control(int port, Packet *p); 
+  void push_data(int port, Packet *p); 
+  void push_management(int port, Packet *p); 
+  
+  // Find element(s) that match a given type...
+  RNAElement *find_one_element(RNAElementType t); 
+  RNAElement *find_one_element_erase(RNAElementType t); 
+  
+  // Select one possible pattern for execution given n are possible
+  Pattern *select_pattern(Vector<Pattern *>);
+  
+  // Update the capabilities attained after the execution of the
+  // pattern.
+  int update_capabilities(Pattern *p, ConfigType conf_in);
+
+  // Test the constructed composition....
+  int initiate_test(bool crosslayer, String teststring, LinkState *l = 0);
+  void  test_reply(int port, Packet *p);
+  void  test_request(int port, Packet *p);
+
+
+ private:
+
+  Vector<RNAElement *> _processed_elemlist; 
+  RNAElement *_options; 
+  String _start_pattern; 
+  String _pattern_namespace; 
+  bool client; 
+  
+  // Negotiation related
+  bool autonegotiate; 
+  bool finished_negotiation;  
+  Pattern *negotiation_pattern;
+  bool negotiation_ongoing;
+  bool enable_pattern_learning; 
+
+  // testing related. 
+  bool finished_test; 
+  bool test_ongoing; 
+  
+  // Started exchange? 
+  bool initialized_protocol; 
+  
+
+};
+
+CLICK_ENDDECLS
+#endif
Index: rna/elements/rna/metaprotocol_patterns.cc
diff -u /dev/null rna/elements/rna/metaprotocol_patterns.cc:1.5
--- /dev/null	Sun Jan 25 11:47:09 2009
+++ rna/elements/rna/metaprotocol_patterns.cc	Fri Dec 26 16:57:00 2008
@@ -0,0 +1,1053 @@
+/* 
+
+################################################################
+#                                                              #
+# (c) University of Southern California                        #
+#                                                              #
+#  See LICENSE.RNA for the complete license                    #
+#                                                              #
+################################################################
+
+*/
+
+#include "metaprotocol_patterns.hh"
+
+//===================================================================
+// Class to store one pattern in each instance. A typical pattern 
+// looks like this (stored in metaprotocol_patterns.txt)
+//
+// PATTERN ENCRYPTED_ORDERED_DELIVERY
+//  FOLLOWS ORDERED_DELIVERY
+//  REQ MUST ENCRYPTION 1 
+//  REQ MUST REORDERBUFFER 1
+//  REQ MUST DEMULTIPLEXOR 1
+//  CONFIG ARG ENCRYPTION 1 algo des 
+//  CONFIG ARG ENCRYPTION 1  keysize 512
+//  CONFIG LINK ADD DEMULTIPLEXOR 1 REORDERBUFFER 1 
+//  CONFIG LINK ADD REORDERBUFFER 1 ENCRYPTION 1 
+//  UNCONFIG LINK DEL DEMULTIPLEXOR 1 REORDERBUFFER 1 
+//  UNCONFIG LINK DEL REORDERBUFFER 1 ENCRYPTION 1 
+//
+// Code for pattern ENCRYPTED_ORDERED_DELIVERY (generated by the patterns_parser.pl
+// {
+//	parents.clear();
+//	reqs.clear(); 
+//	args.clear(); 
+//	links.clear(); 
+//	parents.push_back("ORDERED_DELIVERY");
+//	r = new Req(CONSTRAINT_REQUIRE_MUST,ENCRYPTION,1);
+//	reqs.push_back(r);
+//	r = new Req(CONSTRAINT_REQUIRE_MUST,REORDERBUFFER,1);
+//	reqs.push_back(r);
+//	r = new Req(CONSTRAINT_REQUIRE_MUST,DEMULTIPLEXOR,1);
+//	reqs.push_back(r);
+//	a = new Arg(ENCRYPTION, 1, "algo", "");
+//	args.push_back(a); 
+//	a = new Arg(ENCRYPTION, 1, "keysize", "");
+//	args.push_back(a); 
+//	keywords.clear(); 
+//	l = new Link(DEMULTIPLEXOR, 1, 1, REORDERBUFFER, 1, 1, LINK_OP_ADD, CONF_CONFIG, keywords);
+//	links.push_back(l); 
+//	keywords.clear(); 
+//	l = new Link(REORDERBUFFER, 1, 1, ENCRYPTION, 1, 1, LINK_OP_ADD, CONF_CONFIG, keywords);
+//	links.push_back(l); 
+//	keywords.clear(); 
+//	l = new Link(DEMULTIPLEXOR, 1, 1, REORDERBUFFER, 1, 1, LINK_OP_DEL, CONF_UNCONFIG, keywords);
+//	links.push_back(l); 
+//	keywords.clear(); 
+//	l = new Link(REORDERBUFFER, 1, 1, ENCRYPTION, 1, 1, LINK_OP_DEL, CONF_UNCONFIG, keywords);
+//	links.push_back(l); 
+//	pat = new Pattern(this, "ENCRYPTED_ORDERED_DELIVERY", parents, reqs, args, links); 
+// }; 
+// ....
+//
+//===================================================================
+
+
+//
+// Populate the class
+//
+Pattern::Pattern(State *s,
+		 String name, 
+		 Vector<String> parentlist, 
+		 Vector<Req *> reqs,
+		 Vector<Capability *> capabilities,
+		 Vector<Arg *> args,
+		 Vector<Link *> links){
+  _s = s; 
+  _name  = name; 
+  _parentlist = parentlist; 
+  _reqs = reqs; 
+  _capabilities = capabilities; 
+  _args = args; 
+  _links = links; 
+  
+  // Result of the link create operations that are looked up 
+  // during cleanup...
+  _lspecs.clear();
+
+}; 
+
+Pattern::Pattern(State *s){
+  
+  _s = s; 
+  
+};
+
+//===================================================================
+// Encode and decode functions...
+//===================================================================
+
+// What is the total memory occupied by this pattern...
+int 
+Pattern::encoded_size() {
+  int length = 0; 
+
+  // name of the pattern...
+  length++; // length of the name 
+  length += _name.length();  // for the name...
+  
+  // Store all the parents...
+  length++; // Number of parents...
+  for (int i = 0; i < _parentlist.size(); i++){
+    length ++; // Length of this parent name...
+    length += _parentlist[i].length(); 
+  };
+  
+  // Store all the _reqs. 
+  length++; // Number of parents...
+  for (int i = 0; i < _reqs.size(); i++){
+    length += _reqs[i]->encoded_size(); 
+  };
+
+  // Store all the _capabilities. 
+  length++; // Number of capabilities
+  for (int i = 0; i < _capabilities.size(); i++){
+    length += _capabilities[i]->encoded_size(); 
+  };
+
+  // Store all the _args
+  length++; // Number of args
+  for (int i = 0; i < _args.size(); i++){
+    length += _args[i]->encoded_size(); 
+  };
+
+  // Store all the _links
+  length++; // Number of links
+  for (int i = 0; i < _links.size(); i++){
+    length += _links[i]->encoded_size(); 
+  };
+  
+  return length; 
+};
+
+int 
+Pattern::encode(unsigned char *data) {
+  
+  int off = 0; 
+  int name_off, parent_off, reqs_off, capabilities_off, args_off, links_off; 
+  
+  name_off = 0; 
+
+  // Store the name of this pattern...
+  *(data + off) = _name.length(); 
+  off++; 
+  const char *n_str = _name.c_str();
+  memcpy (data + off, n_str, _name.length()); 
+  off += _name.length(); 
+  
+  // Store all the parents...
+  parent_off = off; 
+  *(data + off) = _parentlist.size(); 
+  off++; // Number of parents...
+  for (int i = 0; i < _parentlist.size(); i++){
+    int len = _parentlist[i].length();
+    *(data + off) = len; 
+    off++;     
+    const char *n_str = _parentlist[i].c_str();
+    memcpy (data + off, n_str, len);
+    off += len; 
+  };
+  
+  // Store all the _reqs. 
+  reqs_off = off; 
+  *(data + off) = _reqs.size(); 
+  off++;   
+  for (int i = 0; i < _reqs.size(); i++){
+    off += _reqs[i]->encode(data + off); 
+  };
+
+  // Store all the _capabilities. 
+  capabilities_off = off; 
+  *(data + off) = _capabilities.size(); 
+  off++;   
+  for (int i = 0; i < _capabilities.size(); i++){
+    off += _capabilities[i]->encode(data + off); 
+  };
+
+  // Store all the _args
+  args_off = off; 
+  *(data + off) = _args.size(); 
+  off++;   
+  for (int i = 0; i < _args.size(); i++){
+    off += _args[i]->encode(data + off); 
+  };
+
+  // Store all the _links
+  links_off = off; 
+  *(data + off) = _links.size(); 
+  off++;   
+  for (int i = 0; i < _links.size(); i++){
+    off += _links[i]->encode(data + off); 
+  };
+  
+  if (0) 
+    click_chatter("Pattern::Encode Offsets: name(%d), parents(%d), reqs(%d), "
+		  "capabilities(%d), args(%d), links(%d) all(%d)\n",
+		  name_off, parent_off, reqs_off, 
+		  capabilities_off, args_off, links_off, off);
+  
+  return off; 
+};
+
+// Decode an incoming message from the peer. 
+int 
+Pattern::decode(const unsigned char *data) {
+  
+  int off = 0; 
+  int name_off, parent_off, reqs_off, capabilities_off, args_off, links_off; 
+  
+  name_off = 0;   
+  // Read the name of this pattern...
+  int len = *(data + off); 
+  off++; 
+  String v_str((const char *)(data + off), len); 
+  _name = v_str; 
+  off += len; 
+  
+  // Store all the parents...
+  parent_off = off; 
+  int num_parents = *(data + off); 
+  off++; 
+  for (int i = 0; i < num_parents; i++){
+    int len = *(data + off); 
+    off++;     
+    String p_str((const char *)(data + off), len); 
+    _parentlist.push_back(p_str);
+    off += len; 
+  };
+  
+  // Store all the _reqs. 
+  reqs_off = off; 
+  int num_reqs = *(data + off); 
+  off++; 
+  for (int i = 0; i < num_reqs; i++){
+    Req *r = new Req(); 
+    off += r->decode(data + off); 
+    _reqs.push_back(r);
+  };
+  
+  // Store all the _capabilities 
+  capabilities_off = off; 
+  int num_capabilities= *(data + off); 
+  off++; 
+  for (int i = 0; i < num_capabilities; i++){
+    Capability *c = new Capability(); 
+    off += c->decode(data + off); 
+    _capabilities.push_back(c);
+  };
+  
+  // Store all the _args
+  args_off = off; 
+  int num_args = *(data + off);
+  off++; 
+  for (int i = 0; i < num_args; i++){
+    Arg *a = new Arg(); 
+    off += a->decode(data + off); 
+    _args.push_back(a);
+  };
+  
+  // Store all the _links
+  links_off = off; 
+  int num_links = *(data + off); 
+  off++; 
+  for (int i = 0; i < num_links; i++){
+    Link *l = new Link(); 
+    off += l->decode(data + off); 
+    _links.push_back(l);
+  };  
+
+  if (0) 
+    click_chatter("Pattern::Decode Offsets: name(%d), parents(%d), reqs(%d), "
+		  "capabilities(%d), args(%d), links(%d) - all (%d)\n",
+		  name_off, parent_off, reqs_off, 
+		  capabilities_off, args_off, links_off, off);
+
+  
+  return off; 
+};
+
+
+//===================================================================
+//
+// Cleanup the elements assigned to this pattern instance. Ideally
+// this function should also check for 'active' patterns that is those
+// that have been instantiated so that the pattern can be undone
+// first.
+//
+//===================================================================
+Pattern::~Pattern(){
+  
+  // Put the elements back in the shared state. Ideally this should be
+  // empty.
+  if (_s) { 
+    while(_elemlist.size() > 0) {
+      _s->put_element(_elemlist.back());
+      _elemlist.pop_back(); 
+    };
+  };
+
+};
+
+//===================================================================
+//
+// Lookup a pattern by its name 
+//
+//===================================================================
+bool 
+Pattern::Match(String name){  
+  return (_name == name); 
+};
+
+//===================================================================
+//
+// Return the name of this pattern
+//
+//===================================================================
+String 
+Pattern::Name(){  
+  return _name; 
+};
+
+//===================================================================
+//
+// Return the list of all the parent patterns which must be executed
+// before this pattern can be.
+//
+//===================================================================
+Vector<String>
+Pattern::ParentNames(){
+  return _parentlist;
+};
+
+//===================================================================
+//
+// Return the prerequisites of this pattern. 
+//
+//===================================================================
+Vector<Req *>
+Pattern::Requirements(){  
+  return _reqs; 
+};
+
+//===================================================================
+//
+// Return the prerequisites of this pattern. 
+//
+//===================================================================
+Vector<Capability *>
+Pattern::Capabilities(){  
+  return _capabilities; 
+};
+
+
+//===================================================================
+// 
+// Test whether all the prerequisite previous patterns have been
+// executed 
+//
+//===================================================================
+bool 
+Pattern::MatchParentList(Vector<String> completed_parent_list){  
+  
+
+  // Go through each parent of the parent
+  for (int i = 0; i < _parentlist.size(); i++){
+    bool found = false; 
+    
+    // Look at the completed list of parents to see if they 
+    // satisfy the parent requirements of the given pattern 
+    // i.e., the follows requirement
+    for (int j = 0; j < completed_parent_list.size(); j++){    
+      if (completed_parent_list[j] == _parentlist[i]){
+	found = true; 
+	break;
+      }
+    };
+    
+    // Well, is this parent requirement satisfied? 
+    if (!found) 
+      return false; 
+  };
+
+  return true; 
+};
+
+//===================================================================
+//
+// Look at a list of patterns instead of one to determine the subset
+// of patterns that are ready to be executed. One or more of them are
+// selected for negotiation and execution later. 
+//
+//===================================================================
+bool 
+Pattern::MatchParentList(Vector<Pattern *> completed_parent_list){  
+
+  bool found = false; 
+  
+  // Debug 
+  //click_chatter("Pattern::MatchParentList Looking for parents of %s \n", 
+  //_name.c_str());
+  //
+  //for (int j = 0; j < completed_parent_list.size(); j++){
+  // String completed_parent_name = completed_parent_list[j]->Name(); 
+  //click_chatter("Pattern::MatchParentList(%s): completed[%d] = %s\n", 
+  //	_name.c_str(), j, completed_parent_name.c_str());    
+  //};
+
+
+  // Check if I am on the list of completed patterns. 
+  for (int j = 0; j < completed_parent_list.size(); j++){
+    String completed_parent_name = completed_parent_list[j]->Name(); 
+    if (completed_parent_name == _name){ 
+      found = true; 
+      break;
+    };
+  };
+  
+  // If I am on the list, then skip self. 
+  if (found) {
+    //click_chatter("Pattern::MatchParentList - Found %s on completed list\n",
+    // _name.c_str());
+    return false; 
+  };
+
+    
+  // Go through each parents to see if all of them are 
+  // in the completed list...
+  for (int i = 0; i < _parentlist.size(); i++){
+    found = false;
+
+    //click_chatter("Pattern::MatchParentList Looking at %s - parent %s \n", 
+    //	  _name.c_str(), _parentlist[i].c_str());
+
+    // Look at the completed list of parents to see if they 
+    // satisfy the parent requirements of the given pattern 
+    // i.e., the follows requirement
+    for (int j = 0; j < completed_parent_list.size(); j++){
+      String completed_parent_name = completed_parent_list[j]->Name(); 
+      int ret = String::compare(completed_parent_name, _parentlist[i]);
+      //click_chatter("Pattern::MatchParentList Looking at %s - "
+      //	    "parent \"%s\" current \"%s\" result = %d \n", 
+      //	    _name.c_str(), _parentlist[i].c_str(), 
+      //	    completed_parent_name.c_str(), ret);
+      if (ret == 0){
+	found = true; 
+	break;
+      }
+    };
+    
+    // Well, is this parent requirement satisfied? 
+    if (!found) {
+      //click_chatter("Pattern::MatchParentList %s - missed parent %s \n", 
+      //	    _name.c_str(), _parentlist[i].c_str());
+
+      return false; 
+    };
+  };
+  
+
+  // click_chatter("Pattern::MatchParentList %s - parents are all satisfied\n",
+  //	_name.c_str());
+  
+  return true; 
+};
+
+
+//===================================================================
+//
+// Among the elements 'owned' by this pattern (i.e., used for
+// instantiation), find elements of a given type
+//
+//===================================================================
+RNAElement *
+Pattern::FindElement(RNAElementType t, int n){
+
+  int c = -1;
+  
+  // Control is the metaprotocol. This is obtained from the state
+  // which obtains the same from the metaprotocol that instantiates
+  // the state.
+  if (t == CONTROL) {
+    RNAElement *control = _s->get_control(); 
+    return control; 
+  };
+  
+  for (int j = 0; j < _elemlist.size(); j++){
+    RNAElement *e = _elemlist[j];
+    if (e->get_type() == t){
+      c++;
+      if (c == n) {
+	return e; 
+      };      
+    };
+  };
+  
+  return NULL; 
+
+};
+
+//========================================================
+//
+// Generate the message corresponding to this pattern. This message
+// will be sent to the peer.
+// 
+//========================================================
+
+Packet *Pattern::GenerateMessage(){
+  
+  // Exchange the initial configuration - this pattern; once this
+  // accepted, then select one from the next few possible patterns. We
+  // could look ahead and exchange information on the other patterns
+  // as well. 
+  
+  // Create a new packet
+  WritablePacket *p = Packet::make(0);
+
+  int size   = 1 + _name.length(); 
+  p = p->push(size); 
+  char *data = (char *)p->data(); 
+  
+  // Add the header...
+  *(data + 0) = _name.length(); 
+  strncpy(data + 1, _name.c_str(), _name.length()); 
+
+  return p; 
+  
+};
+
+//========================================================
+//
+// Check the incoming message to see if the incoming message matches
+// this pattern.
+// 
+//========================================================
+
+int Pattern::ValidateMessage(Packet *p){
+  
+  if (!p) 
+    return -1; 
+  
+  const char *data = (const char *)p->data(); 
+
+  int length = *(data + 0); 
+  String iname (data + 1, length); 
+
+  if (_name.compare(iname)) 
+    return -1; 
+  
+  return 0; 
+  
+};
+
+int 
+Pattern::ValidateMessage(String s){
+    
+  if (_name.compare(s)) 
+    return -1; 
+  
+  return 0; 
+  
+};
+
+//========================================================
+//
+// Verify if the requirements corresponding to this pattern can be
+// met.
+// 
+//========================================================
+int 
+Pattern::Verify(){
+  
+  if (!_s) 
+    return -1; 
+  
+  //click_chatter("Pattern::Verify Requirements requirements size = %d\n",
+  //	_reqs.size());
+
+  // Check if the prerequisits have been met. 
+  for (int i = 0; i < _reqs.size(); i++){
+
+    Req *r = _reqs[i];     
+    if (!r){
+      click_chatter("Pattern::Verify r is NULL\n");
+      continue; 
+    };
+    
+    // Can I find the required number of elements of a given type? 
+    if (r->c == CONSTRAINT_REQUIRE_MUST){
+      int res = _s->check_elements(r->t, r->count);
+      if (res < 0){ 
+	// r->print("FAILED");
+	if (0) 
+	  click_chatter("[Pattern::Verify] Failed to verify %s\n", 
+			_name.c_str()); 
+	return -1;
+      };
+    };
+  };
+
+  //click_chatter("Pattern::Verify Extracting the elements...\n");
+  
+  return 0; 
+};
+
+
+//===================================================================
+//
+// Helper function during execute. This function only looks at the
+// LINK commands i.e., the subset of commands that alter the
+// connections between modules. The caller can specify whether the
+// execution must configure or deconfigure the pattern. The code for
+// both is identical. This function calls the add/delete link
+// functions of each RNA element so that the internal linkstate of the
+// modules is also updated in the process. 
+//
+//===================================================================
+int 
+Pattern::ExecuteHelper(ConfigType t){
+  
+  // Sanity check...
+  if (t != CONF_CONFIG && t != CONF_UNCONFIG) 
+    return -1; 
+
+  //click_chatter("[Pattern::ExecuteHelper] Entering...t = %s\n", 
+  //	((t == CONF_CONFIG) ? "CONFIG" : "UNCONFIG"));
+  
+  // Add the links...
+  RNAElement *control = _s->get_control();
+  Router *r = control->router(); 
+  
+  Vector <struct linkspec *> lspecs ; 
+  struct linkspec *lspec;
+  
+  // Go through each of the LINK commands
+  for (int i = 0; i < _links.size(); i++){
+    
+    Link *l = _links[i];
+
+    // Skip link commands that do not match...
+    if (l->conf != t)
+      continue; 
+    
+    // Only one of the two elements can have the wildcard specification. 
+    if ((l->count1 <= 0) || (l->count2 <= 0) ||  
+	(l->count1 > 1 && l->count2 > 1)){
+      click_chatter("[%s] Pattern::Execute(): Invalid Link command \n"); 
+      if (1) 
+	click_chatter("[Pattern::Complete] Found a link %s "
+		      "(type %d, instance %d num %d) -> (type %d, instance %d num %d) \n", 
+		      ((l->op == LINK_OP_ADD)? "ADD" : "DEL"), 
+		      l->t1, l->instance1, l->count1, l->t2, l->instance2, l->count2); 
+      
+      continue;
+    };
+
+    //
+    // This is intended to handle the situation where 
+    //
+
+    int max_combinations = (l->count1 > l->count2) ? l->count1 : l->count2; 
+    for (int c = 0; c < max_combinations; c++) { 
+
+      RNAElement *e0 = 0, *e1 = 0; 
+      
+      if (l->count1 > 1) { 
+	// First element is the wild card
+	e0 = _s->get_nth_element(l->t1, l->instance1 + c);
+	e1 = _s->get_nth_element(l->t2, l->instance2);
+      } else if (l->count1 > 1) { 
+	// Second element is the wild card
+	e0 = _s->get_nth_element(l->t1, l->instance1);
+	e1 = _s->get_nth_element(l->t2, l->instance2 + c);	
+      } else {
+	e0 = _s->get_nth_element(l->t1, l->instance1);
+	e1 = _s->get_nth_element(l->t2, l->instance2);		
+      };
+      
+      if (!e0 || !e1) {
+	click_chatter("[Pattern::Complete] Link cannot be executed.%s %s\n",
+		      (e0 ? "": "e0 missing"), (e1 ? "": "e1 missing")); 
+	continue; 
+      };
+      
+      if (l->op == LINK_OP_ADD){ 
+	
+	if (1) 
+	  click_chatter("[Patterns::Execute] <%s> ADD before updating "
+		      "connections %s (Ports: %d,%d) <-> %s(Ports: %d,%d)\n",
+		      _name.c_str(),
+		      e0->instance_name(), e0->ninputs(), e0->noutputs(), 
+		      e1->instance_name(), e1->ninputs(), e1->noutputs());
+      
+	//=============================
+	//
+	// Add bidirectional links between the modules identified.  The
+	// pattern specified is assumed to go from the top to the bottom.
+	// The links are between intra-protocol modules, 
+	//=============================
+	
+	lspecs.clear(); 
+	
+	lspec = new linkspec;
+	lspec->local_elem  =  e0->eindex(); 
+	lspec->local_out   =  e0->noutputs(); 
+	lspec->remote_elem =  e1->eindex();
+	lspec->remote_in   =  e1->ninputs();
+	lspec->local_is_upstream = true; 
+	lspec->crosslayer = false; 
+	lspecs.push_back(lspec); 
+	
+	// Store the updated the lspec information including the linkcmds
+	// returned from the control element (metaprotocol)
+	_lspecs.push_back(lspec);
+	
+	lspec = new linkspec;
+	lspec->local_elem  =  e1->eindex(); 
+	lspec->local_out   =  e1->noutputs(); 
+	lspec->remote_elem =  e0->eindex();
+	lspec->remote_in   =  e0->ninputs();
+	lspec->local_is_upstream = false; 
+	lspec->crosslayer = false; 
+	lspecs.push_back(lspec); 
+	
+	// Store the updated the lspec information including the linkcmds
+	// returned from the control element (metaprotocol)
+	_lspecs.push_back(lspec);
+	
+	// Now process the links. 
+	control->process_linkspecs(lspecs); 
+	
+	// Add this bidirectional link and update the internal router
+	// datastructure...
+	r->update_connections(); 
+	
+	if (1) 
+	  click_chatter("[Patterns::Execute] after updated connections "
+			"%s (%d,%d) <-> %s (%d,%d)\n", 
+			e0->instance_name(), e0->ninputs(), e0->noutputs(), 
+			e1->instance_name(), e1->ninputs(), e1->noutputs());
+	
+      }; 
+
+      if (l->op == LINK_OP_DEL) {
+	
+	
+	click_chatter("[Patterns::Execute] DEL before updated "
+		      "connections %s (%d,%d) <-> %s(%d,%d)\n", 
+		      e0->instance_name(), e0->ninputs(), e0->noutputs(), 
+		      e1->instance_name(), e1->ninputs(), e1->noutputs());
+	
+	int e0idx = e0->eindex();
+	int e1idx = e1->eindex();
+	
+	// Find the right lspec that corresponds to the downstream and
+	// upstream links. 
+	int down_link = -1, up_link = -1; 
+	
+	Vector<Pattern *> allpatterns = _s->get_all_patterns(); 
+	for (int p = 0; p < allpatterns.size(); p++){ 
+	  
+	  Pattern *pat = allpatterns[p]; 
+	  Vector<struct linkspec *>& pat_lspecs = pat->GetLinkspecs(); 
+
+	  for (int i = 0; i < pat_lspecs.size() ; i++){
+	    
+	    struct linkspec *lspec = pat_lspecs[i]; 
+	    
+	    if ((down_link < 0) && 
+		(lspec->local_elem == e0idx) && 
+		(lspec->remote_elem == e1idx) && 
+		(lspec->local_is_upstream == true)){
+	      // link going downstream...delete this
+	      
+	      click_chatter("[Patterns::Execute] Found the down link in "
+			    "pattern %s\n", pat->Name().c_str()); 
+	      
+	      r->disconnect_rna(e0, lspec->local_out,
+				e1, lspec->remote_in); 
+	      down_link = i; 
+	      
+	      // Update the state of the rna element...
+	      e0->delete_link(lspec->l0); 
+	      e1->delete_link(lspec->l1);
+	      
+	      continue; 
+	    };
+	    
+	    if ((up_link < 0) && 
+		(lspec->local_elem == e1idx) && 
+		(lspec->remote_elem == e0idx) && 
+		(lspec->local_is_upstream == false)){
+	      
+	      click_chatter("[Patterns::Execute] Found the uplink in "
+			    "pattern %s\n", pat->Name().c_str()); 
+	      
+	      // link going upstream....delete this
+	      r->disconnect_rna(e1, lspec->local_out,
+				e0, lspec->remote_in); 
+	      up_link = i; 
+	      
+	      // Update the state of the rna element...
+	      e1->delete_link(lspec->l0); 
+	      e0->delete_link(lspec->l1);
+	      
+	      continue;
+	    }; 
+	    
+	  }; // all linkspecs for a given pattern...
+	  
+	  if (up_link >= 0 && down_link >= 0) { 
+	    
+	    // Found a pattern at which this link delete can be performed. 
+	    
+	    // Commit the changes
+	    r->update_connections(); 
+	    
+	    // Delete the two link information for the two links...
+	    pat_lspecs[down_link] = pat_lspecs.back(); 
+	    pat_lspecs.pop_back(); 
+	    pat_lspecs[up_link] = pat_lspecs.back(); 
+	    pat_lspecs.pop_back(); 
+	    
+	    break; 
+	  };
+	  
+	}; // for each pattern...
+
+	
+	if (up_link < 0 || down_link < 0) { 
+	  if (1)
+	    click_chatter("[Patterns::Execute] ERROR! Cannot find a link "
+			  "that can be deleted...\n"); 
+	};
+	
+	if (1){ 
+	  click_chatter("[Patterns::Execute] after updated connections "
+			"%s (%d,%d) <-> %s (%d,%d)\n", 
+			e0->instance_name(), e0->ninputs(), e0->noutputs(), 
+			e1->instance_name(), e1->ninputs(), e1->noutputs());
+	  
+	  click_chatter("\n\n\n"); 	
+	  click_chatter("\n\n\n");
+	};
+	
+      };
+
+    }; // For all possible combinations...
+    
+    // What is the status after processing each link? 
+    if (1) { 
+      click_chatter("\n\n"); 
+      control->print_allelements_links();
+      click_chatter("\n\n");
+    };
+
+  }; // For all links...
+  
+  // click_chatter("[Pattern::ExecuteHelper] Exiting...t = %s\n", 
+  //		((t == CONF_CONFIG) ? "CONFIG" : "UNCONFIG"));
+
+  return 0; 
+  
+};
+
+//========================================================
+//
+// Execute the pattern. First check the prerequisites, gather the
+// elements required to execute the commands, pass new configuration
+// to each of the elements, and execute the helper function that
+// completes the establishment of links etc. 
+// 
+//========================================================
+int 
+Pattern::Execute(){
+  
+  
+  if (Verify() < 0){
+    click_chatter("[Pattern::Execute] Pattern %s "
+		  "cannot be verified \n", _name.c_str()); 
+    return -1; 
+  };
+
+  // Extract those elements from the state and store them in the
+  // pattern instance. This is potentially a problem because a pattern
+  // might be used repeatedly in a given composition. 
+
+  for (int i = 0; i < _reqs.size(); i++){
+    Req *r = _reqs[i]; 
+    if (r->c == CONSTRAINT_REQUIRE_MUST){
+      // Obtain a count number of elements specified in the requirements...
+      Vector<RNAElement *> list = _s->get_elements(r->t, r->count);
+      
+      if (list.size() < r->count){
+	click_chatter("[Pattern::Execute] Returned element list size (%d) "
+		      "is less than expected (%d)\n", 
+		      list.size(), r->count); 
+	return -1; 
+      };
+      for (int j = 0; j < r->count; j++) { 
+	RNAElement *e = list[j];
+	click_chatter("[Pattern::Execute] Obtained element name %s \n",
+		      e->instance_name()); 
+	_elemlist.push_back(e); 
+      };
+      list.clear();
+    };
+  };
+  
+  click_chatter("[Pattern::Execute] Acquired the elements \n");
+  
+
+  // Identify the arguments for each module and configure them
+  // appropriately...
+  for (int i = 0; i < _args.size(); i++){
+    click_chatter("[Pattern::Execute] Passing args...\n"); 
+    Arg *a = _args[i];
+    RNAElement *e = FindElement(a->t, a->c); 
+    if (e){
+      // Call the configure command with the appropriate var/arg
+      Vector<String> conf;
+      conf.push_back(a->var + " " + a->arg); 
+      e->configure(conf, (ErrorHandler *)NULL);
+    };
+  };
+  
+  ExecuteHelper(CONF_CONFIG); 
+    
+  return 0; 
+
+};
+
+//========================================================
+//
+// Undo the executed pattern. Essentially this involves calling the
+// execute helper that executes all the UNCONFIG LINK commands. The
+// elements are put back. 
+//
+//========================================================
+int 
+Pattern::Unexecute(){
+  
+  // UNCONFIG ARG commands must be eventually processed. 
+
+  // XXX: This should add a check for whether this pattern has been
+  // executed to begin with.
+  
+  ExecuteHelper(CONF_UNCONFIG);
+  
+  // Free up the elements to be added to the list....
+  RNAElement *e; 
+  while ((e = _elemlist.back())){
+    _s->put_element(e);
+    _elemlist.pop_back();
+  };
+  
+  return 0; 
+
+};
+
+int 
+Namespace::encoded_size(){
+
+  int off = 0; 
+  
+  // For the name...
+  off++; 
+  off +=  _name.length(); 
+  
+  // Store the patterns...
+  off ++; 
+  for (int i = 0; i < _patterns.size() ; i++){
+    
+    Pattern *p = _patterns[i]; 
+    off += p->encoded_size(); 
+  };
+  
+  return off; 
+};
+
+int 
+Namespace::encode(unsigned char *data) {
+  
+  int off = 0; 
+  
+  // Store the name....
+  *(data + off) = _name.length(); 
+  off++; 
+  const char *n_str = _name.c_str();
+  memcpy (data + off, n_str, _name.length()); 
+  off += _name.length(); 
+  
+
+  // Store the patterns...
+  *(data + off) = _patterns.size(); 
+  for (int i = 0; i < _patterns.size() ; i++){    
+    Pattern *p = _patterns[i]; 
+    off += p->encode(data + off);
+  };
+  
+  return off; 
+
+};
+
+// Decode an incoming message from the peer. 
+int 
+Namespace::decode(const unsigned char *data) {
+  
+  int off = 0; 
+  
+  // Read the name of this pattern...
+  int len = *(data + off); 
+  off++; 
+  String v_str((const char *)(data + off), len); 
+  _name = v_str; 
+  off += len; 
+  
+  int num_patterns = *(data + off); 
+  off++; 
+  
+  for (int i = 0; i < num_patterns; i++){    
+    Pattern *p = new Pattern(_s); 
+    off += p->decode(data + off); 
+    _patterns.push_back(p); 
+  }
+
+  return off; 
+};
+
+bool
+Namespace::learn_pattern(Pattern *pat){
+  
+  if (pat) {
+    _patterns.push_back(pat); 
+    return true; 
+  } else {
+    return false; 
+  }
+}; 
+
+ELEMENT_PROVIDES(Pattern)
+ELEMENT_REQUIRES(RNAElement)
+
+CLICK_ENDDECLS
Index: rna/elements/rna/metaprotocol_patterns.hh
diff -u /dev/null rna/elements/rna/metaprotocol_patterns.hh:1.5
--- /dev/null	Sun Jan 25 11:47:09 2009
+++ rna/elements/rna/metaprotocol_patterns.hh	Fri Dec 26 16:57:00 2008
@@ -0,0 +1,627 @@
+/* 
+
+################################################################
+#                                                              #
+# (c) University of Southern California                        #
+#                                                              #
+#  See LICENSE.RNA for the complete license                    #
+#                                                              #
+################################################################
+
+*/
+#ifndef PATTERNS_HH
+#define PATTERNS_HH
+
+#include "rnaelement.hh"
+
+//===================================================================
+// Class to store one pattern in each instance. A typical pattern 
+// looks like this (stored in metaprotocol_patterns.txt)
+//
+// PATTERN ENCRYPTED_ORDERED_DELIVERY
+//  FOLLOWS ORDERED_DELIVERY
+//  REQ MUST ENCRYPTION 1 
+//  REQ MUST REORDERBUFFER 1
+//  REQ MUST DEMULTIPLEXOR 1
+//  CONFIG ARG ENCRYPTION 1 algo des 
+//  CONFIG ARG ENCRYPTION 1  keysize 512
+//  CONFIG LINK ADD DEMULTIPLEXOR 1 REORDERBUFFER 1 
+//  CONFIG LINK ADD REORDERBUFFER 1 ENCRYPTION 1 
+//  UNCONFIG LINK DEL DEMULTIPLEXOR 1 REORDERBUFFER 1 
+//  UNCONFIG LINK DEL REORDERBUFFER 1 ENCRYPTION 1 
+//
+// Code for pattern ENCRYPTED_ORDERED_DELIVERY (generated by the patterns_parser.pl
+// {
+//	parents.clear();
+//	reqs.clear(); 
+//	args.clear(); 
+//	links.clear(); 
+//	parents.push_back("ORDERED_DELIVERY");
+//	r = new Req(CONSTRAINT_REQUIRE_MUST,ENCRYPTION,1);
+//	reqs.push_back(r);
+//	r = new Req(CONSTRAINT_REQUIRE_MUST,REORDERBUFFER,1);
+//	reqs.push_back(r);
+//	r = new Req(CONSTRAINT_REQUIRE_MUST,DEMULTIPLEXOR,1);
+//	reqs.push_back(r);
+//	a = new Arg(ENCRYPTION, 1, "algo", "");
+//	args.push_back(a); 
+//	a = new Arg(ENCRYPTION, 1, "keysize", "");
+//	args.push_back(a); 
+//	keywords.clear(); 
+//	l = new Link(DEMULTIPLEXOR, 1, 1, REORDERBUFFER, 1, 1, LINK_OP_ADD, CONF_CONFIG, keywords);
+//	links.push_back(l); 
+//	keywords.clear(); 
+//	l = new Link(REORDERBUFFER, 1, 1, ENCRYPTION, 1, 1, LINK_OP_ADD, CONF_CONFIG, keywords);
+//	links.push_back(l); 
+//	keywords.clear(); 
+//	l = new Link(DEMULTIPLEXOR, 1, 1, REORDERBUFFER, 1, 1, LINK_OP_DEL, CONF_UNCONFIG, keywords);
+//	links.push_back(l); 
+//	keywords.clear(); 
+//	l = new Link(REORDERBUFFER, 1, 1, ENCRYPTION, 1, 1, LINK_OP_DEL, CONF_UNCONFIG, keywords);
+//	links.push_back(l); 
+//	pat = new Pattern(this, "ENCRYPTED_ORDERED_DELIVERY", parents, reqs, args, links); 
+// }; 
+// ....
+//
+// Notes: 
+//
+// Note that the namespace and semantics of the patterns is shared by
+// both the endpoints. This is important because otherwise there may
+// be functionality mismatch
+//
+// Patterns have to be checked for feasibility because we may not have
+// modules that correspond to the pattern of operation. 
+//
+// The LINK commands are hints for the composition program to
+// indiciate where this module should go. The composition program may
+// ignore the link command and use internal knowledge - which ofcourse
+// makes it hard to reuse across layers etc.
+//
+// Patterns are specified in a particular order; A reference to
+// another pattern in the form of FOLLOWs command.
+//
+// It can be seen as a tree of possible decisions and the negotiation
+// process essentially walks the tree down during composition and
+// walks up when the composition is terminated. The trees supported by
+// each endpoint may be different and the endpoints walk only down the
+// shared paths.
+//
+//
+//===================================================================
+
+
+class State; 
+class Pattern; 
+class Namespace; 
+
+#include "rnaelement.hh" 
+#include "metaprotocol_state.hh" 
+
+
+//===================================================================
+//
+// Requirement: <constraint> <module> <number of instances> 
+// For now only MUST is supported 
+//
+// Eventually we should be able to send a pattern across to the peers
+// at the other end too. There is some initial code to encode an
+// instance of the class. 
+// 
+//===================================================================
+class Req {
+  
+public: 
+
+  ConstraintType c; 
+  int count; 
+  RNAElementType t; 
+  
+  void print(char *s = NULL){
+    if (s) 
+      click_chatter("[%s] Req [type=(%d,%s),c = %d,count=%d]\n", 
+		    s, t, str_elementtype[t], count, (int)c);
+    else 
+      click_chatter("Req [type=(%d,%s),c = %d,count=%d]\n", 
+		    t, str_elementtype[t], count, (int)c);
+  };
+
+  int encoded_size(){
+    return 4; 
+  };
+
+  
+  // Encode is pattern.
+  int encode(unsigned char *data){
+    
+    if (!data) 
+      return -1; 
+    
+    *(data + 0) = (char) PATTERN_REQ;
+    *(data + 1) = (char) c; 
+    *(data + 2) = (char) t; 
+    *(data + 3) = (char) count; 
+    
+    return 4; 
+
+  };
+     
+  // Decode a pattern (provided probably by a peer) 
+  int decode(const unsigned char *data){
+    
+    if (!data || *data != PATTERN_REQ) 
+      return -1; 
+    
+    c     = (ConstraintType) *(data + 1); 
+    t     = (RNAElementType) *(data + 2); 
+    count = (int)*(data + 3); 
+    
+    return 4; 
+
+  };
+  
+  // Initialize the Requirement object 
+  Req(ConstraintType c_in, RNAElementType t_in, int count_in) {
+    c = c_in; 
+    t = t_in;
+    count = count_in; 
+  };
+  
+  Req(){    
+    c = CONSTRAINT_END;
+    count = 0; 
+    t = UNKNOWN; 
+    
+  }
+  
+};
+
+//=============================================================
+// Capability of operations 
+//=============================================================
+
+class Capability {
+
+public: 
+  CapabilityCheck cc; 
+  CapabilityVar c; 
+  String value; 
+  ConfigType conf; 
+  
+  Capability(){
+    cc = CAP_CHK_BEGIN; 
+    c = CAP_VAR_BEGIN; 
+    value = ""; 
+    conf = CONF_BEGIN;
+  };
+
+  Capability(CapabilityCheck cc_in, 
+	  CapabilityVar c_in,
+	  String value_in, 
+	  ConfigType conf_in){
+    cc = cc_in; 
+    c = c_in; 
+    value = value_in;
+    conf = conf_in;
+  }; 
+
+  Capability(Capability &ct){
+    this->cc = ct.cc; 
+    this->c  = ct.c; 
+    this->value = ct.value; 
+    conf = ct.conf; 
+  };
+
+
+
+  int encoded_size(){
+    return 5 + value.length(); 
+  };
+
+  // Encode is pattern.
+  int encode(unsigned char *data){
+    
+    if (!data) 
+      return -1; 
+    
+    *(data + 0) = (char) PATTERN_CAPABILITY;
+    *(data + 1) = (char) cc; 
+    *(data + 2) = (char) c; 
+    *(data + 3) = (char) conf; 
+    *(data + 4) = value.length(); 
+
+    const char *v_str = value.c_str(); 
+    memcpy (data + 5, v_str, value.length()); 
+        
+    return 5 + value.length(); 
+  };
+     
+  // Decode a pattern (provided probably by a peer) 
+  int decode(const unsigned char *data){
+    
+    if (!data || *data != PATTERN_CAPABILITY) 
+      return -1; 
+    
+    cc     = (CapabilityCheck) *(data + 1); 
+    c      = (CapabilityVar) *(data + 2); 
+    conf   = (ConfigType) *(data + 3); 
+    
+    String v_str((const char *)(data + 5), (int)*(data + 4));
+    value  = v_str; 
+    
+    return 5 + v_str.length(); 
+
+  };
+
+  
+};
+
+
+//===================================================================
+//
+// Object that is used to store the LINK command 
+// Link: <config/unconfig> <first module> <first instance> [number of instances]
+//                         <second module> <first instance> [number of instances] 
+//
+// Only one of two modules can have number of instances > 1. This is a
+// limited form of wildcard. Ideally this should support regular
+// expressions and relative names, i.e., instead of using an absolute
+// instance number, a relative instance number must be used. 
+//
+// This does not yet support encoding/decoding like Req module
+// 
+//===================================================================
+
+class Link {
+  
+public: 
+
+  RNAElementType t1, t2; 
+  int instance1, instance2; 
+  int count1, count2; 
+  LinkOP op; 
+  ConfigType conf; 
+  Vector<String> keywords; 
+
+  Link(RNAElementType t1_in, int i1_in, int c1_in, 
+       RNAElementType t2_in, int i2_in, int c2_in,
+       LinkOP op_in, ConfigType conf_in, 
+       Vector<String> keywords_in
+       ){
+    t1 = t1_in; 
+    t2 = t2_in;
+    instance1 = i1_in;
+    instance2 = i2_in;
+    count1 = c1_in;
+    count2 = c2_in;
+    op = op_in; 
+    conf = conf_in;
+    keywords = keywords_in; 
+  };
+  
+  Link(){
+    
+    t1 = t2  = UNKNOWN; 
+    instance1 = instance2 = -1; 
+    count1 = count2 = 0; 
+    op = LINK_OP_BEGIN; 
+    conf = CONF_BEGIN; 
+    keywords.clear(); 
+  };
+
+
+  int encoded_size(){
+    
+    // The minimum
+    int length = 9; 
+
+    // How many keywords? 1 byte 
+    length++; 
+    
+    // Go through each keyword and add its length too...
+    for (int i = 0; i < keywords.size(); i++){     
+      length += (1 + keywords[i].length()); 
+    };    
+    
+    return length; 
+  };
+  
+  // Encode is pattern.The required length is assumed to be allocated
+  // already...
+
+  int encode(unsigned char *data){
+    
+    if (!data) 
+      return -1; 
+    
+    *(data + 0) = (char) PATTERN_LINK;
+    *(data + 1) = (char) t1; 
+    *(data + 2) = (char) t2; 
+    *(data + 3) = (char) instance1; 
+    *(data + 4) = (char) instance2; 
+    *(data + 5) = (char) count1; 
+    *(data + 6) = (char) count2; 
+    *(data + 7) = (char) op; 
+    *(data + 8) = (char) conf;     
+
+    // How many keywords? 
+    int length = 9; 
+    *(data + length) = keywords.size(); 
+    length++; 
+    
+    // Go through each keyword and encode it...
+    for (int i = 0; i < keywords.size(); i++){ 
+      const char *v_str = keywords[i].c_str(); 
+      
+      // Store the length
+      *(data + length) = keywords[i].length(); 
+      length++; 
+      
+      // Store the string.
+      memcpy (data + length, v_str, keywords[i].length()); 
+      length += keywords[i].length(); 
+      
+    };    
+
+    return length; 
+  };
+  
+  // Decode a pattern (provided probably by a peer) 
+  int decode(const unsigned char *data){
+    
+    if (!data || *data != PATTERN_LINK) 
+      return -1; 
+
+    t1        = (RNAElementType) *(data + 1); 
+    t2        = (RNAElementType) *(data + 2); 
+    instance1 = (int) *(data + 3);
+    instance2 = (int) *(data + 4);
+    count1    = (int) *(data + 5);
+    count2    = (int) *(data + 6);
+    op        = (LinkOP) *(data + 7); 
+    conf      = (ConfigType) *(data + 8); 
+    
+    int num_keywords = (int) *(data + 9);     // how many keywords 
+    int off   = 10;                           // where should I start?
+
+    // For each keyword...
+    for (int i = 0; i < num_keywords; i++){
+      
+      // Obtain the length of this keyword 
+      int len = (int)*(data + off); 
+      off++; 
+
+      // Load the keyword and store it in the keywords list...
+      String v_str((const char *)(data + off), len); 
+      keywords.push_back(v_str); 
+      
+      off += len; 
+    };
+    
+    return off; // Number of bytes consumed. 
+    
+  };
+  
+};
+
+//===================================================================
+//
+// Object that is used to store the ARG command
+// Arg: <module> <instance> <variable> <value> 
+//
+// Both the variable and value are strings. They are interpreted by
+// the modules to which this is presented upon inclusion into some
+// composition by the metaprotocol. Ideally this should also have
+// config/unconfig option. 
+//
+// This does not yet support encoding/decoding. 
+
+//===================================================================
+
+class Arg {
+  
+public: 
+  String var;
+  String arg; 
+  RNAElementType t;
+  int c; // Instance of this type 
+  
+  void print(char *s = NULL){
+    
+    if (s) 
+      click_chatter("[%s] Arg [type=(%d,%s),instance=%d,var=%s,arg=%s]\n", 
+		    s, t, str_elementtype[t], (int)c,var.c_str(), arg.c_str());
+    else 
+      click_chatter("Arg [type=(%d,%s),instance=%d,var=%s,arg=%s]\n", 
+		    t, str_elementtype[t], c,var.c_str(), arg.c_str());
+
+  };
+
+  Arg() {
+    t = UNKNOWN; 
+    c = -1; 
+    var = ""; 
+    arg = ""; 
+  };
+
+  Arg(RNAElementType t_in, int c_in, String v_in, String a_in){
+    c = c_in; 
+    t = t_in; 
+    arg = a_in;
+    var = v_in; 
+  };
+
+  int encoded_size(){    
+    return 5 + var.length() + arg.length(); 
+  };
+
+  
+  // Encode is pattern.
+  int encode(unsigned char *data){
+    
+    if (!data) 
+      return -1; 
+    
+    *(data + 0) = (char) PATTERN_ARG;
+    *(data + 1) = (char) c; 
+    *(data + 2) = (char) t; 
+    
+    int off = 3; 
+    
+    // Store var..
+    int len = var.length(); 
+    *(data + off) = len; 
+    off++;
+    const char *v_str = var.c_str(); 
+    memcpy (data + off, v_str, len); 
+    off += len;
+
+    // Store val...
+    len = arg.length(); 
+    *(data + off) = len; 
+    off++;
+    const char *a_str = arg.c_str(); 
+    memcpy (data + off, a_str, len); 
+    off += len;
+    
+    return off; 
+
+  };
+     
+  // Decode a pattern (provided probably by a peer) 
+  int decode(const unsigned char *data){
+    
+    if (!data || *data != PATTERN_ARG) 
+      return -1; 
+    
+    c     = (int) *(data + 1); 
+    t     = (RNAElementType) *(data + 2); 
+
+    int off = 3; 
+    int len = (int)*(data + off); 
+    off++; 
+    String v_str((const char *)(data + off), len); 
+    var = v_str; 
+    off += len; 
+
+    len = (int)*(data + off); 
+    off++; 
+    String a_str((const char *)(data + off), len); 
+    arg = a_str; 
+    off += len;     
+
+    return off; 
+
+  };
+
+};
+
+
+//===================================================================
+//
+// This class stores a single pattern that consists of a set of
+// follows, req, arg and link command objects. In addition the
+// elements used during the instantiation process is also
+// included. The class also stores information on the links that have
+// been created. this stored information is used during cleanup. The
+// follows is a list of the parent patterns upon which this pattern
+// depends. The parent list is simply stored as a vector of strings.
+// 
+//===================================================================
+
+class Pattern {
+
+ private: 
+  State *_s; 
+  String _name; 
+  Vector<String> _parentlist;
+  Vector<RNAElement *> _elemlist; 
+  Vector<Req *> _reqs; 
+  Vector<Capability *> _capabilities; 
+  Vector<Arg *> _args; 
+  Vector<Link *> _links; 
+  Vector<struct linkspec *> _lspecs; 
+
+ public: 
+  Pattern(State *s, 
+	  String name, 
+	  Vector<String> parentlist,
+	  Vector<Req *> reqs,
+	  Vector<Capability *> capabilities,
+	  Vector<Arg *> args,
+	  Vector<Link *> links);
+
+  Pattern(State *s); 
+
+  virtual ~Pattern();
+  
+  // Return the name of a given pattern or its parents 
+  virtual String Name(); 
+  virtual Vector<String> ParentNames(); 
+
+  // 
+  virtual bool Match(String s);
+  
+  // Check to see all parents are satisfied for a given pattern or a
+  // set of patterns. 
+  virtual bool MatchParentList(Vector<String> completed_parent_list);
+  virtual bool MatchParentList(Vector<Pattern *> completed_parent_list);
+  
+  // Check to see if pattern's prerequisites are satisfied.
+  virtual int Verify(); 
+
+  // Add the links and complete the composition
+  virtual int ExecuteHelper(ConfigType); 
+  virtual int Execute(); 
+  virtual int Unexecute(); 
+  
+  // Encode/decode...
+  int encoded_size(); 
+  int encode(unsigned char *data); 
+  int decode (const unsigned char *data); 
+  
+  // Generate and receive a message containing a specification of a
+  // pattern.
+  virtual Packet *GenerateMessage(); 
+  virtual int ValidateMessage(Packet *p);
+  virtual int ValidateMessage(String s);
+  
+  //Look at the list of the elements 
+  RNAElement *FindElement(RNAElementType t, int c); 
+  
+  // Extract the requirements 
+  Vector<Req *> Requirements();
+
+  Vector<Capability *> Capabilities();
+  
+  // Extract the links created by this pattern 
+  Vector<struct linkspec *>& GetLinkspecs() { return _lspecs; }
+  
+};
+
+class Namespace {
+private: 
+  State *_s; 
+  Vector<Pattern *> _patterns; 
+  String _name; 
+  String _start_pattern; 
+
+public: 
+  Namespace(State *s, String name, String start_pattern, Vector<Pattern *> patterns){
+    _s = s; 
+    _patterns = patterns; 
+    _name = name; 
+    _start_pattern = start_pattern; 
+  };
+  
+  String            name() { return _name; }; 
+  String            get_start_pattern() { return _start_pattern; } 
+  Vector<Pattern *> patterns() { return _patterns; };   
+  bool              learn_pattern(Pattern *pat);
+
+  // This is for transmission...
+  int encoded_size(); 
+  int encode(unsigned char *data); 
+  int decode (const unsigned char *data);   
+};
+
+#endif
Index: rna/elements/rna/metaprotocol_patterns_db.cc
diff -u /dev/null rna/elements/rna/metaprotocol_patterns_db.cc:1.6
--- /dev/null	Sun Jan 25 11:47:09 2009
+++ rna/elements/rna/metaprotocol_patterns_db.cc	Fri Jan  2 14:06:58 2009
@@ -0,0 +1,397 @@
+  //////////////////////////////////////////////////////////////////////////////////////////
+  //
+  // This code was automatically generated by the elements/rna/patterns_parser.pl.
+  // Please do not edit this file. Modify either metaprotocol_patterns_db.txt 
+  // or patterns_parser.pl 
+  //
+  // This code generated at: Fri Jan  2 13:52:45 2009
+  //
+  //////////////////////////////////////////////////////////////////////////////////////////
+  Vector<Namespace *> namespaces; 
+  Vector<Pattern *> patternlist; 
+  Pattern *pat;
+  Vector<String> parents;
+  Vector<Req *> reqs; 
+  Vector<Capability *> capabilities; 
+  Vector<Arg *> args; 
+  Vector<Link *> links; 
+  Req *r;
+  Capability *c;
+  Arg *a;
+  Link *l;
+  Vector<String> keywords;
+
+  // Namespace WIRELESS
+  {
+  	patternlist.clear();
+
+  	// Code for pattern WIRELESS::MIN
+  	{
+  		parents.clear();
+  		reqs.clear(); 
+  		capabilities.clear(); 
+  		args.clear(); 
+  		links.clear(); 
+
+  		c = new Capability(CAP_CHK_PRESENT, CAP_VAR_CONNECTION_ORIENTED,"", CONF_CONFIG);
+  		capabilities.push_back(c);
+  		c = new Capability(CAP_CHK_PRESENT, CAP_VAR_LOSSY,"", CONF_CONFIG);
+  		capabilities.push_back(c);
+  		pat = new Pattern(this, "MIN", parents, reqs, capabilities, args, links); 
+  		patternlist.push_back(pat); 
+  	};
+  	//Completed pattern WIRELESS::MIN
+
+  	// Code for pattern WIRELESS::ORDERED_DELIVERY
+  	{
+  		parents.clear();
+  		reqs.clear(); 
+  		capabilities.clear(); 
+  		args.clear(); 
+  		links.clear(); 
+
+  		parents.push_back("MIN");
+  		r = new Req(CONSTRAINT_REQUIRE_MUST,REORDERBUFFER,1);
+  		reqs.push_back(r);
+  		keywords.clear(); 
+			l = new Link(CONTROL, 0, 1, REORDERBUFFER, 0, 1, LINK_OP_ADD, CONF_CONFIG, keywords);
+  		links.push_back(l); 
+  		keywords.clear(); 
+			l = new Link(REORDERBUFFER, 0, 1, BUFFER, 0, 1, LINK_OP_ADD, CONF_CONFIG, keywords);
+  		links.push_back(l); 
+  		keywords.clear(); 
+			l = new Link(CONTROL, 0, 1, REORDERBUFFER, 0, 1, LINK_OP_DEL, CONF_UNCONFIG, keywords);
+  		links.push_back(l); 
+  		keywords.clear(); 
+			l = new Link(REORDERBUFFER, 0, 1, BUFFER, 0, 1, LINK_OP_DEL, CONF_UNCONFIG, keywords);
+  		links.push_back(l); 
+  		pat = new Pattern(this, "ORDERED_DELIVERY", parents, reqs, capabilities, args, links); 
+  		patternlist.push_back(pat); 
+  	};
+  	//Completed pattern WIRELESS::ORDERED_DELIVERY
+
+  	// Code for NULL
+  	{
+  		parents.clear();
+  		reqs.clear(); 
+  		capabilities.clear(); 
+  		args.clear(); 
+  		links.clear(); 
+  		pat = new Pattern(this, "NULL", parents, reqs, capabilities, args, links); 
+  		patternlist.push_back(pat); 
+  	};
+  	//Completed pattern NULL
+
+  	Namespace *n = new Namespace(this, "WIRELESS", "MIN", patternlist); 
+  	namespaces.push_back(n);
+
+  };
+  // Namespace WIRELESS
+
+  // Namespace DEFAULT
+  {
+  	patternlist.clear();
+
+  	// Code for pattern DEFAULT::FLEXLINKMIN
+  	{
+  		parents.clear();
+  		reqs.clear(); 
+  		capabilities.clear(); 
+  		args.clear(); 
+  		links.clear(); 
+
+  		parents.push_back("MIN");
+  		r = new Req(CONSTRAINT_REQUIRE_MUST,FLEXLINK,1);
+  		reqs.push_back(r);
+  		keywords.clear(); 
+			l = new Link(CONTROL, 0, 1, BUFFER, 0, 1, LINK_OP_DEL, CONF_CONFIG, keywords);
+  		links.push_back(l); 
+  		keywords.clear(); 
+			l = new Link(CONTROL, 0, 1, FLEXLINK, 0, 1, LINK_OP_ADD, CONF_CONFIG, keywords);
+  		links.push_back(l); 
+  		keywords.clear(); 
+			l = new Link(FLEXLINK, 0, 1, BUFFER, 0, 1, LINK_OP_ADD, CONF_CONFIG, keywords);
+  		links.push_back(l); 
+  		keywords.clear(); 
+			l = new Link(CONTROL, 0, 1, FLEXLINK, 0, 1, LINK_OP_DEL, CONF_UNCONFIG, keywords);
+  		links.push_back(l); 
+  		keywords.clear(); 
+			l = new Link(FLEXLINK, 0, 1, BUFFER, 0, 1, LINK_OP_DEL, CONF_UNCONFIG, keywords);
+  		links.push_back(l); 
+  		keywords.clear(); 
+			l = new Link(FLEXLINK, 0, 1, BUFFER, 0, 1, LINK_OP_ADD, CONF_UNCONFIG, keywords);
+  		links.push_back(l); 
+  		pat = new Pattern(this, "FLEXLINKMIN", parents, reqs, capabilities, args, links); 
+  		patternlist.push_back(pat); 
+  	};
+  	//Completed pattern DEFAULT::FLEXLINKMIN
+
+  	// Code for pattern DEFAULT::MIN
+  	{
+  		parents.clear();
+  		reqs.clear(); 
+  		capabilities.clear(); 
+  		args.clear(); 
+  		links.clear(); 
+
+  		r = new Req(CONSTRAINT_REQUIRE_MUST,BUFFER,1);
+  		reqs.push_back(r);
+  		c = new Capability(CAP_CHK_ABSENT, CAP_VAR_CONNECTION_ORIENTED,"", CONF_NONE);
+  		capabilities.push_back(c);
+  		keywords.clear(); 
+			l = new Link(CONTROL, 0, 1, BUFFER, 0, 1, LINK_OP_ADD, CONF_CONFIG, keywords);
+  		links.push_back(l); 
+  		keywords.clear(); 
+			l = new Link(BUFFER, 0, 1, CONTROL, 0, 1, LINK_OP_ADD, CONF_CONFIG, keywords);
+  		links.push_back(l); 
+  		keywords.clear(); 
+			l = new Link(CONTROL, 0, 1, BUFFER, 0, 1, LINK_OP_DEL, CONF_UNCONFIG, keywords);
+  		links.push_back(l); 
+  		keywords.clear(); 
+			l = new Link(BUFFER, 0, 1, CONTROL, 0, 1, LINK_OP_DEL, CONF_UNCONFIG, keywords);
+  		links.push_back(l); 
+  		pat = new Pattern(this, "MIN", parents, reqs, capabilities, args, links); 
+  		patternlist.push_back(pat); 
+  	};
+  	//Completed pattern DEFAULT::MIN
+
+  	// Code for pattern DEFAULT::ORDERED_DELIVERY
+  	{
+  		parents.clear();
+  		reqs.clear(); 
+  		capabilities.clear(); 
+  		args.clear(); 
+  		links.clear(); 
+
+  		parents.push_back("MIN");
+  		r = new Req(CONSTRAINT_REQUIRE_MUST,REORDERBUFFER,1);
+  		reqs.push_back(r);
+  		c = new Capability(CAP_CHK_PRESENT, CAP_VAR_CONNECTION_ORIENTED,"FALSE", CONF_NONE);
+  		capabilities.push_back(c);
+  		keywords.clear(); 
+			l = new Link(CONTROL, 0, 1, BUFFER, 0, 1, LINK_OP_DEL, CONF_CONFIG, keywords);
+  		links.push_back(l); 
+  		keywords.clear(); 
+			l = new Link(CONTROL, 0, 1, REORDERBUFFER, 0, 1, LINK_OP_ADD, CONF_CONFIG, keywords);
+  		links.push_back(l); 
+  		keywords.clear(); 
+			l = new Link(REORDERBUFFER, 0, 1, BUFFER, 0, 1, LINK_OP_ADD, CONF_CONFIG, keywords);
+  		links.push_back(l); 
+  		keywords.clear(); 
+			l = new Link(CONTROL, 0, 1, REORDERBUFFER, 0, 1, LINK_OP_DEL, CONF_UNCONFIG, keywords);
+  		links.push_back(l); 
+  		keywords.clear(); 
+			l = new Link(REORDERBUFFER, 0, 1, BUFFER, 0, 1, LINK_OP_DEL, CONF_UNCONFIG, keywords);
+  		links.push_back(l); 
+  		keywords.clear(); 
+			l = new Link(CONTROL, 0, 1, BUFFER, 0, 1, LINK_OP_ADD, CONF_UNCONFIG, keywords);
+  		links.push_back(l); 
+  		pat = new Pattern(this, "ORDERED_DELIVERY", parents, reqs, capabilities, args, links); 
+  		patternlist.push_back(pat); 
+  	};
+  	//Completed pattern DEFAULT::ORDERED_DELIVERY
+
+  	// Code for pattern DEFAULT::NULL
+  	{
+  		parents.clear();
+  		reqs.clear(); 
+  		capabilities.clear(); 
+  		args.clear(); 
+  		links.clear(); 
+
+  		pat = new Pattern(this, "NULL", parents, reqs, capabilities, args, links); 
+  		patternlist.push_back(pat); 
+  	};
+  	//Completed pattern DEFAULT::NULL
+
+  	// Code for pattern DEFAULT::TUNNEL
+  	{
+  		parents.clear();
+  		reqs.clear(); 
+  		capabilities.clear(); 
+  		args.clear(); 
+  		links.clear(); 
+
+  		parents.push_back("NULL");
+  		r = new Req(CONSTRAINT_REQUIRE_MUST,MULTITUNNEL,1);
+  		reqs.push_back(r);
+  		keywords.clear(); 
+  		keywords.push_back("BIDIRECTIONAL");
+  		keywords.push_back("ALL");
+			l = new Link(CONTROL, 1, 1, MULTITUNNEL, 1, 1, LINK_OP_ADD, CONF_CONFIG, keywords);
+  		links.push_back(l); 
+  		keywords.clear(); 
+  		keywords.push_back("BIDIRECTIONAL");
+  		keywords.push_back("ALL");
+			l = new Link(CONTROL, 1, 1, MULTITUNNEL, 1, 1, LINK_OP_DEL, CONF_UNCONFIG, keywords);
+  		links.push_back(l); 
+  		pat = new Pattern(this, "TUNNEL", parents, reqs, capabilities, args, links); 
+  		patternlist.push_back(pat); 
+  	};
+  	//Completed pattern DEFAULT::TUNNEL
+
+  	// Code for pattern DEFAULT::ENCRYPTED_ORDERED_DELIVERY
+  	{
+  		parents.clear();
+  		reqs.clear(); 
+  		capabilities.clear(); 
+  		args.clear(); 
+  		links.clear(); 
+
+  		parents.push_back("ORDERED_DELIVERY");
+  		r = new Req(CONSTRAINT_REQUIRE_MUST,ENCRYPTION,1);
+  		reqs.push_back(r);
+  		r = new Req(CONSTRAINT_REQUIRE_MUST,REORDERBUFFER,1);
+  		reqs.push_back(r);
+  		r = new Req(CONSTRAINT_REQUIRE_MUST,DEMULTIPLEXOR,1);
+  		reqs.push_back(r);
+  		a = new Arg(ENCRYPTION, 1, "algo", "");
+  		args.push_back(a); 
+  		a = new Arg(ENCRYPTION, 1, "keysize", "");
+  		args.push_back(a); 
+  		keywords.clear(); 
+			l = new Link(DEMULTIPLEXOR, 1, 1, REORDERBUFFER, 1, 1, LINK_OP_ADD, CONF_CONFIG, keywords);
+  		links.push_back(l); 
+  		keywords.clear(); 
+			l = new Link(REORDERBUFFER, 1, 1, ENCRYPTION, 1, 1, LINK_OP_ADD, CONF_CONFIG, keywords);
+  		links.push_back(l); 
+  		keywords.clear(); 
+			l = new Link(DEMULTIPLEXOR, 1, 1, REORDERBUFFER, 1, 1, LINK_OP_DEL, CONF_UNCONFIG, keywords);
+  		links.push_back(l); 
+  		keywords.clear(); 
+			l = new Link(REORDERBUFFER, 1, 1, ENCRYPTION, 1, 1, LINK_OP_DEL, CONF_UNCONFIG, keywords);
+  		links.push_back(l); 
+  		pat = new Pattern(this, "ENCRYPTED_ORDERED_DELIVERY", parents, reqs, capabilities, args, links); 
+  		patternlist.push_back(pat); 
+  	};
+  	//Completed pattern DEFAULT::ENCRYPTED_ORDERED_DELIVERY
+
+  	// Code for pattern DEFAULT::MUXDEMUX
+  	{
+  		parents.clear();
+  		reqs.clear(); 
+  		capabilities.clear(); 
+  		args.clear(); 
+  		links.clear(); 
+
+  		parents.push_back("NULL");
+  		r = new Req(CONSTRAINT_REQUIRE_MUST,MULTIPLEXOR,1);
+  		reqs.push_back(r);
+  		r = new Req(CONSTRAINT_REQUIRE_MUST,DEMULTIPLEXOR,1);
+  		reqs.push_back(r);
+  		r = new Req(CONSTRAINT_REQUIRE_MUST,BUFFER,2);
+  		reqs.push_back(r);
+  		keywords.clear(); 
+			l = new Link(CONTROL, 0, 1, MULTIPLEXOR, 0, 1, LINK_OP_ADD, CONF_CONFIG, keywords);
+  		links.push_back(l); 
+  		keywords.clear(); 
+			l = new Link(DEMULTIPLEXOR, 0, 1, CONTROL, 0, 1, LINK_OP_ADD, CONF_CONFIG, keywords);
+  		links.push_back(l); 
+  		keywords.clear(); 
+			l = new Link(MULTIPLEXOR, 0, 1, BUFFER, 0, 2, LINK_OP_ADD, CONF_CONFIG, keywords);
+  		links.push_back(l); 
+  		keywords.clear(); 
+			l = new Link(BUFFER, 0, 2, DEMULTIPLEXOR, 0, 1, LINK_OP_ADD, CONF_CONFIG, keywords);
+  		links.push_back(l); 
+  		keywords.clear(); 
+			l = new Link(CONTROL, 0, 1, MULTIPLEXOR, 0, 1, LINK_OP_DEL, CONF_UNCONFIG, keywords);
+  		links.push_back(l); 
+  		keywords.clear(); 
+			l = new Link(DEMULTIPLEXOR, 0, 1, CONTROL, 0, 1, LINK_OP_DEL, CONF_UNCONFIG, keywords);
+  		links.push_back(l); 
+  		keywords.clear(); 
+			l = new Link(MULTIPLEXOR, 0, 1, BUFFER, 0, 2, LINK_OP_DEL, CONF_UNCONFIG, keywords);
+  		links.push_back(l); 
+  		keywords.clear(); 
+			l = new Link(BUFFER, 0, 2, DEMULTIPLEXOR, 0, 1, LINK_OP_DEL, CONF_UNCONFIG, keywords);
+  		links.push_back(l); 
+  		pat = new Pattern(this, "MUXDEMUX", parents, reqs, capabilities, args, links); 
+  		patternlist.push_back(pat); 
+  	};
+  	//Completed pattern DEFAULT::MUXDEMUX
+
+  	// Code for pattern DEFAULT::REXMITFLEXLINKMIN
+  	{
+  		parents.clear();
+  		reqs.clear(); 
+  		capabilities.clear(); 
+  		args.clear(); 
+  		links.clear(); 
+
+  		parents.push_back("FLEXLINKMIN");
+  		r = new Req(CONSTRAINT_REQUIRE_MUST,REXMIT,1);
+  		reqs.push_back(r);
+  		keywords.clear(); 
+			l = new Link(CONTROL, 0, 1, FLEXLINK, 0, 1, LINK_OP_DEL, CONF_CONFIG, keywords);
+  		links.push_back(l); 
+  		keywords.clear(); 
+			l = new Link(CONTROL, 0, 1, REXMIT, 0, 1, LINK_OP_ADD, CONF_CONFIG, keywords);
+  		links.push_back(l); 
+  		keywords.clear(); 
+			l = new Link(REXMIT, 0, 1, FLEXLINK, 0, 1, LINK_OP_ADD, CONF_CONFIG, keywords);
+  		links.push_back(l); 
+  		keywords.clear(); 
+			l = new Link(CONTROL, 0, 1, REXMIT, 0, 1, LINK_OP_DEL, CONF_UNCONFIG, keywords);
+  		links.push_back(l); 
+  		keywords.clear(); 
+			l = new Link(REXMIT, 0, 1, FLEXLINK, 0, 1, LINK_OP_DEL, CONF_UNCONFIG, keywords);
+  		links.push_back(l); 
+  		keywords.clear(); 
+			l = new Link(CONTROL, 0, 1, FLEXLINK, 0, 1, LINK_OP_ADD, CONF_UNCONFIG, keywords);
+  		links.push_back(l); 
+  		pat = new Pattern(this, "REXMITFLEXLINKMIN", parents, reqs, capabilities, args, links); 
+  		patternlist.push_back(pat); 
+  	};
+  	//Completed pattern DEFAULT::REXMITFLEXLINKMIN
+
+  	Namespace *n = new Namespace(this, "DEFAULT", "MIN", patternlist); 
+  	namespaces.push_back(n);
+
+  };
+  // Namespace DEFAULT
+
+  // Namespace DEFAULT_SIMPLIFIED
+  {
+  	patternlist.clear();
+
+  	// Code for pattern DEFAULT_SIMPLIFIED::MIN
+  	{
+  		parents.clear();
+  		reqs.clear(); 
+  		capabilities.clear(); 
+  		args.clear(); 
+  		links.clear(); 
+
+  		r = new Req(CONSTRAINT_REQUIRE_MUST,BUFFER,1);
+  		reqs.push_back(r);
+  		c = new Capability(CAP_CHK_PRESENT, CAP_VAR_CONNECTION_ORIENTED,"", CONF_CONFIG);
+  		capabilities.push_back(c);
+  		keywords.clear(); 
+			l = new Link(CONTROL, 0, 1, BUFFER, 0, 1, LINK_OP_ADD, CONF_CONFIG, keywords);
+  		links.push_back(l); 
+  		keywords.clear(); 
+			l = new Link(BUFFER, 0, 1, CONTROL, 0, 1, LINK_OP_ADD, CONF_CONFIG, keywords);
+  		links.push_back(l); 
+  		pat = new Pattern(this, "MIN", parents, reqs, capabilities, args, links); 
+  		patternlist.push_back(pat); 
+  	};
+  	//Completed pattern DEFAULT_SIMPLIFIED::MIN
+
+  	// Code for pattern DEFAULT_SIMPLIFIED::NULL
+  	{
+  		parents.clear();
+  		reqs.clear(); 
+  		capabilities.clear(); 
+  		args.clear(); 
+  		links.clear(); 
+
+  		pat = new Pattern(this, "NULL", parents, reqs, capabilities, args, links); 
+  		patternlist.push_back(pat); 
+  	};
+  	//Completed pattern DEFAULT_SIMPLIFIED::NULL
+
+  	Namespace *n = new Namespace(this, "DEFAULT_SIMPLIFIED", "MIN", patternlist); 
+  	namespaces.push_back(n);
+
+  };
+  // Namespace DEFAULT_SIMPLIFIED
Index: rna/elements/rna/metaprotocol_patterns_db.txt
diff -u /dev/null rna/elements/rna/metaprotocol_patterns_db.txt:1.5
--- /dev/null	Sun Jan 25 11:47:09 2009
+++ rna/elements/rna/metaprotocol_patterns_db.txt	Fri Dec 26 16:57:00 2008
@@ -0,0 +1,137 @@
+#-------------------------------------
+# Patterns 
+#-------------------------------------
+
+# The default namespace...
+NAMESPACE DEFAULT
+
+START MIN
+
+PATTERN NULL
+
+# This simply specifies a buffer. no reodering etc. 
+PATTERN MIN
+    REQ MUST BUFFER 1 
+    CAPABILITY ABSENT CONNECTION_ORIENTED ""
+    CONFIG LINK ADD CONTROL 0 BUFFER 0 
+    CONFIG LINK ADD BUFFER 0 CONTROL 0
+    UNCONFIG LINK DEL CONTROL 0 BUFFER 0 
+    UNCONFIG LINK DEL BUFFER 0 CONTROL 0
+
+# Next use this pattern in MIN is successful 
+PATTERN ORDERED_DELIVERY
+    FOLLOWS MIN
+    REQ MUST REORDERBUFFER 1 
+    CAPABILITY PRESENT CONNECTION_ORIENTED FALSE 
+    CONFIG LINK DEL CONTROL 0 BUFFER 0
+    CONFIG LINK ADD CONTROL 0 REORDERBUFFER 0
+    CONFIG LINK ADD REORDERBUFFER 0 BUFFER 0
+    UNCONFIG LINK DEL CONTROL 0 REORDERBUFFER 0
+    UNCONFIG LINK DEL REORDERBUFFER 0 BUFFER 0
+    UNCONFIG LINK ADD CONTROL 0 BUFFER 0
+    
+PATTERN ENCRYPTED_ORDERED_DELIVERY
+    FOLLOWS ORDERED_DELIVERY
+    REQ MUST ENCRYPTION 1 
+    REQ MUST REORDERBUFFER 1
+    REQ MUST DEMULTIPLEXOR 1
+    CONFIG ARG ENCRYPTION 1 algo des 
+    CONFIG ARG ENCRYPTION 1  keysize 512
+    CONFIG LINK ADD DEMULTIPLEXOR 1 REORDERBUFFER 1 
+    CONFIG LINK ADD REORDERBUFFER 1 ENCRYPTION 1 
+    UNCONFIG LINK DEL DEMULTIPLEXOR 1 REORDERBUFFER 1 
+    UNCONFIG LINK DEL REORDERBUFFER 1 ENCRYPTION 1 
+
+PATTERN TUNNEL 
+    FOLLOWS NULL 
+    REQ MUST MULTITUNNEL 1 
+    CONFIG LINK ADD CONTROL 1 MULTITUNNEL 1 BIDIRECTIONAL ALL 
+    UNCONFIG LINK DEL CONTROL 1 MULTITUNNEL 1 BIDIRECTIONAL ALL 
+
+# Illustrates the problem of matching arbitrary patterns of
+#  composition.
+
+PATTERN MUXDEMUX  
+    FOLLOWS NULL 
+    REQ MUST MULTIPLEXOR 1
+    REQ MUST DEMULTIPLEXOR 1    
+    REQ MUST BUFFER 2 
+    CONFIG LINK ADD CONTROL 0 MULTIPLEXOR 0
+    CONFIG LINK ADD DEMULTIPLEXOR 0 CONTROL 0
+    # The -1 indicates a varible. the language must be ideally
+    # extended to specify a variable. For now we use -1 as a stand in
+    # for the variable.
+    CONFIG LINK ADD MULTIPLEXOR 0 BUFFER 0 2
+    CONFIG LINK ADD BUFFER 0 2 DEMULTIPLEXOR 0 
+    UNCONFIG LINK DEL CONTROL 0 MULTIPLEXOR 0
+    UNCONFIG LINK DEL DEMULTIPLEXOR 0 CONTROL 0 
+    #This again uses a variable  BUFFER (0, 2)
+    UNCONFIG LINK DEL MULTIPLEXOR 0 BUFFER 0 2 
+    UNCONFIG LINK DEL BUFFER 0 2 DEMULTIPLEXOR 0
+
+# Start from NULL 
+#PATTERN FLEXLINK 
+#    FOLLOWS NULL 
+#    REQ MUST FLEXLINK 1 
+#    CONFIG LINK ADD CONTROL 0 FLEXLINK 0 
+#    CONFIG LINK ADD FLEXLINK 0 CONTROL 0
+#    UNCONFIG LINK DEL CONTROL 0 FLEXLINK 0 
+#    UNCONFIG LINK DEL FLEXLINK 0 CONTROL 0 
+
+# Start from MIN instead of NULL
+PATTERN FLEXLINKMIN
+    FOLLOWS MIN 
+    REQ MUST FLEXLINK 1 
+    CONFIG LINK DEL CONTROL 0 BUFFER 0 
+    CONFIG LINK ADD CONTROL 0 FLEXLINK 0 
+    CONFIG LINK ADD FLEXLINK 0 BUFFER 0
+    UNCONFIG LINK DEL CONTROL 0 FLEXLINK 0 
+    UNCONFIG LINK DEL FLEXLINK 0 BUFFER 0 
+    UNCONFIG LINK ADD FLEXLINK 0 BUFFER 0 
+
+
+PATTERN REXMITFLEXLINKMIN 
+    FOLLOWS FLEXLINKMIN 
+    REQ MUST REXMIT 1 
+    CONFIG LINK DEL CONTROL 0 FLEXLINK 0 
+    CONFIG LINK ADD CONTROL 0 REXMIT 0 
+    CONFIG LINK ADD REXMIT 0 FLEXLINK 0 
+    UNCONFIG LINK DEL CONTROL 0 REXMIT 0 
+    UNCONFIG LINK DEL REXMIT 0 FLEXLINK 0 
+    UNCONFIG LINK ADD CONTROL 0 FLEXLINK 0 	   
+
+# The default namespace...
+NAMESPACE WIRELESS
+
+START MIN
+
+PATTERN MIN
+	CONFIG CAPABILITY PRESENT CONNECTION_ORIENTED ""
+	CONFIG CAPABILITY PRESENT LOSSY ""
+
+# Next use this pattern in MIN is successful 
+PATTERN ORDERED_DELIVERY
+    FOLLOWS MIN
+    REQ MUST REORDERBUFFER 1 
+    CONFIG LINK ADD CONTROL 0 REORDERBUFFER 0
+    CONFIG LINK ADD REORDERBUFFER 0 BUFFER 0
+    UNCONFIG LINK DEL CONTROL 0 REORDERBUFFER 0
+    UNCONFIG LINK DEL REORDERBUFFER 0 BUFFER 0
+
+
+# The default namespace stripped of important elements. The endpoint
+# that has this will learn the rest.
+
+NAMESPACE DEFAULT_SIMPLIFIED
+
+START MIN
+
+PATTERN NULL
+
+# This simply specifies a buffer. no reodering etc. 
+PATTERN MIN
+    REQ MUST BUFFER 1 
+    CONFIG CAPABILITY PRESENT CONNECTION_ORIENTED ""
+    CONFIG LINK ADD CONTROL 0 BUFFER 0 
+    CONFIG LINK ADD BUFFER 0 CONTROL 0
+
Index: rna/elements/rna/metaprotocol_state.cc
diff -u /dev/null rna/elements/rna/metaprotocol_state.cc:1.4
--- /dev/null	Sun Jan 25 11:47:09 2009
+++ rna/elements/rna/metaprotocol_state.cc	Fri Jan  2 14:06:58 2009
@@ -0,0 +1,485 @@
+/* 
+
+################################################################
+#                                                              #
+# (c) University of Southern California                        #
+#                                                              #
+#  See LICENSE.RNA for the complete license                    #
+#                                                              #
+################################################################
+
+*/
+
+#include "metaprotocol_state.hh"
+
+//################################################################
+//#                                                      
+//# Manages the composition-related state of the metaprotocol.
+//# It keeps track of available elements, patterns to the executed,
+//# and the result of the execution. The bulk of the execution is 
+//# in metaprotocol_patterns.cc.
+//# 
+//##################################################################
+
+
+//========================================================
+//
+// Constructor and destructor...
+//
+//========================================================
+
+State::State(RNAElement *control_in, String initial_namespace_scope, 
+	     Vector<RNAElement *> &list) {
+  
+  
+  control = control_in;
+  _elemlist = list; 
+  _available_elemlist = list; 
+  _used_elemlist.clear();
+  _namespace = NULL; 
+  _start_pattern = ""; 
+
+  // Debug message 
+  if (0) { 
+    click_chatter("[State::State] element list size = %d \n", list.size());
+    for (int i = 0; i < list.size(); i++){
+      RNAElement *e = list[i]; 
+      click_chatter("[State::State] Element[%d] = %d \n", 
+		    i, e->get_type());
+    }
+  };
+
+#include   PROCESSED_PATTERNS
+  
+  // Check to make sure that atleast one namespace is specified. 
+  if (namespaces.size() == 0 ){
+    click_chatter("[State::State] Need atleast one namespace. "
+		  "Check elements/rna/metaprotocol_patterns_db.cc"); 
+    exit(1); 
+  };
+
+  _namespaces = namespaces; 
+  
+  // Set the initial scope to be something 
+  Namespace *default_namespace = NULL;
+  for (int i = 0; i < _namespaces.size(); i++){
+    String n = _namespaces[i]->name(); 
+    if ( n == "DEFAULT" ){
+      default_namespace = _namespaces[i];
+    };
+
+    if ( n == initial_namespace_scope ){
+      _namespace = _namespaces[i];
+      break; 
+    };
+  };
+  
+  if (_namespace == NULL) {
+    if (default_namespace){ 
+      click_chatter("[State::State] Unknown namespace; Choosing DEFAULT\n");
+      _namespace = default_namespace; 
+    } else { 
+      click_chatter("[State::State] Unknown namespace; DEFAULT not specified." 
+		    "Choosing first available. \n");      
+      _namespace = _namespaces[0]; 
+
+    };
+  };
+  
+  _patternlist = _namespace->patterns(); 
+  _start_pattern = _namespace->get_start_pattern(); 
+  
+  click_chatter("[State::State] Selected namespace %s with start pattern %s\n",
+		_namespace->name().c_str(), _start_pattern.c_str());
+
+};
+
+State::~State(){  
+  // Do nothing...
+};
+
+//========================================================
+//
+// Misc functions...
+//
+//========================================================
+RNAElement *
+State::get_control() {
+  return control; 
+}
+
+Namespace *
+State::get_namespace() {
+  return _namespace; 
+};
+
+String 
+State::get_namespace_name() {
+  return _namespace->name(); 
+};
+
+//========================================================
+//
+// Learn and unlearn patterns...
+//
+//========================================================
+
+bool 
+State::learn_pattern(Pattern *pat) {
+  
+  // XXX Add more checks here...
+  return _namespace->learn_pattern(pat); 
+
+};
+
+
+//========================================================
+//
+// Return a given number of elements of a given type; 
+//
+//========================================================
+Vector<RNAElement *>
+State::get_elements(RNAElementType t, int count = 1){
+
+  Vector<RNAElement *> list; 
+  
+  // Debug messages 
+  if (0) { 
+    click_chatter("[State::get_elements] Require elements of type %d "
+		  "(count = %d)\n", 
+		  t, count);
+    click_chatter("[State::get_elements] element list size = %d \n", 
+		  _available_elemlist.size());
+    for (int i = 0; i < _available_elemlist.size(); i++){
+      RNAElement *e = _available_elemlist[i]; 
+      click_chatter("[State::get_elements] Element[%d] = %d \n", 
+		    i, e->get_type());
+    }
+  };
+
+  if (count <= 0) 
+    return list; 
+  
+  // Check to ensure that we do have count number of elements of the
+  // given type. 
+  if (check_elements(t, count) < 0) 
+    return list; 
+
+  if (t == CONTROL){ 
+    list.push_back(control); 
+    return list; 
+  };
+  
+  Vector<RNAElement *>::iterator iter;     
+  for (iter = _available_elemlist.begin(); 
+       iter != _available_elemlist.end(); ){
+
+    RNAElement *e = *iter; 
+    if (e && e->get_type() == t){       
+      iter = _available_elemlist.erase(iter);
+      _used_elemlist.push_back(e);      
+      list.push_back(e); 
+      count--;       
+    } else {
+      iter++;
+    }
+    
+    if (count == 0) 
+      break; 
+  };
+  
+  return list; 
+};
+
+//========================================================
+//
+// Get the Nth element of a given type. Dont add or delete anything.
+// the count starts from 0;
+//
+//========================================================
+
+RNAElement *
+State::get_nth_element(RNAElementType t, int count){
+
+  if (count < 0) 
+    return NULL; 
+  
+  if (t == CONTROL) {
+    return control; 
+  };
+
+  Vector<RNAElement *>::iterator iter;     
+  for (iter = _elemlist.begin(); iter != _elemlist.end(); iter++){
+
+    RNAElement *e = *iter; 
+    if (e && 
+	(((t != ANY) && (e->get_type() == t)) || 
+	 (t == ANY))){ 
+      count--; 
+      if (count < 0)
+	return e; 
+    };
+    
+  };
+  
+  return NULL; 
+};
+
+
+//========================================================
+//
+// Get the status of the elements provided to the state object. This
+// is useful to determine if the patterns executed until now used any
+// elements at all. 
+//
+//========================================================
+
+Vector<RNAElement *>
+State::get_available_elements(){
+  return _available_elemlist; 
+};
+
+Vector<RNAElement *>
+State::get_used_elements(){
+  return _used_elemlist; 
+};
+
+//========================================================
+//
+// Add an element back to the list of the composable elements
+//
+//========================================================
+
+void 
+State::put_element(RNAElement *e){
+  
+  if (!e) 
+    return; 
+
+  // Ignore CONTROL (metaprotocol) element...
+  RNAElementType t = e->get_type(); 
+  if (t == CONTROL)
+    return; 
+
+  Vector<RNAElement *>::iterator iter;     
+  for (iter = _used_elemlist.begin(); iter != _used_elemlist.end(); iter++){
+    RNAElement *e0 = *iter;
+    if (e == e0) {
+      
+      //Move it back to the available list...
+      _used_elemlist.erase(iter);
+      _available_elemlist.push_back(e);
+      
+      break; 
+    };
+  };
+  
+};
+
+//========================================================
+//
+// Can a composition be supported? This function checks whether a
+// required number of elements of a given type are available.
+//
+//========================================================
+
+int 
+State::check_elements(RNAElementType t, int count){
+  
+  int c = 0; 
+  
+  // Check is for control element...
+  if (t == CONTROL){
+    if (count > 1 || count == 0) 
+      return -1; 
+    
+    return 0;
+  };
+  
+  // Go through the available list to see if the 
+  for (Vector<RNAElement *>::iterator iter = _available_elemlist.begin(); 
+       iter != _available_elemlist.end(); iter++){
+
+    RNAElement *e = *iter;
+
+    if (!e) {
+      continue; 
+    };
+    
+    const char *classname = e->class_name(); 
+    
+    if (strcmp(classname, "RNAElement") != 0)
+      continue; 
+    
+    //click_chatter("State::check_elements classname = %s type  = (%d, %s)\n",
+    //	  classname, e->get_type(), str_elementtype[e->get_type()]);
+
+    if (e->get_type() == t) 
+      c++; 
+  };
+
+  // click_chatter("State::check_elements found %d/%d of type %s \n", 
+  //	c,count, str_elementtype[t]); 
+
+  if (c >= count)
+    return 0; 
+  else 
+    return -1; 
+  
+};
+
+//#########################################################
+//#                                                       #
+//# Pattern management                                    #
+//#                                                       #
+//#########################################################
+
+
+//========================================================
+//
+// Return the list of patterns 
+//
+//========================================================
+
+String 
+State::get_start_pattern() {
+  return _start_pattern; 
+};
+
+Vector<Pattern *> 
+State::get_all_patterns() {
+  return _patternlist; 
+}
+
+
+//========================================================
+//
+// Find a pattern of a given name. This name may be specified by the
+// peer or my metaprotocol (which parsed configuration file
+//
+//========================================================
+Pattern *
+State::find_pattern(String name) {
+  
+  for (int i = 0; i < _patternlist.size(); i++){
+    Pattern *p = _patternlist[i];
+    if (p->Match(name)){ 
+      return p; 
+    };
+  };
+  
+  return NULL; 
+
+};
+
+//========================================================
+//
+// Execute a given pattern - allocate the resourcees and assign them
+// to the given pattern. 
+//
+//========================================================
+
+int 
+State::execute_pattern(Pattern *p){
+  
+  if (!p) 
+    return -1; 
+  
+  String name = p->Name(); 
+
+  click_chatter("[State::execute_pattern] Executing pattern %s \n", 
+		name.c_str());
+  
+  p->Execute();
+
+  // We have to complete this...
+  _completed_patterns.push_back(p);
+  
+  return 0; 
+};
+
+//========================================================
+//
+// Unexecute a given pattern - deallocate the resources and reset the
+// protocol structure to the old way.
+//
+//========================================================
+
+int 
+State::unexecute_pattern(Pattern *p){
+  
+  if (!p) 
+    return -1; 
+  
+  String name = p->Name(); 
+
+  click_chatter("State::unexecute_pattern Adding %s to completed list\n", 
+		name.c_str());
+  
+  p->Unexecute();
+
+  // We have to complete this...
+  //_completed_patterns.push_back(p);
+  
+  return 0; 
+};
+
+//========================================================
+//
+// Execute a given pattern - allocate the resourcees and assign them
+// to the given pattern. 
+//
+//========================================================
+
+Vector<Pattern *> 
+State::find_next_patterns(){
+
+  Vector<Pattern *> patlist;
+  for (int i = 0; i < _patternlist.size(); i++){
+    Pattern *p = _patternlist[i];
+    String patname = p->Name(); 
+    
+    if (p->MatchParentList(_completed_patterns) == true){
+      if (0) 
+	click_chatter("[State::find_next_patterns] Adding %s to the next "
+		      "possible patterns  \n", patname.c_str());
+      patlist.push_back(p); 
+    };
+  };
+
+  
+  return patlist; 
+};
+
+//========================================================
+//
+// Find the executable patterns. 
+//
+//========================================================
+
+Vector<Pattern *> 
+State::find_next_verified_patterns(){
+
+  Vector<Pattern *> patlist;
+  for (int i = 0; i < _patternlist.size(); i++){
+    Pattern *p = _patternlist[i];
+    String patname = p->Name(); 
+    
+    if ((p->MatchParentList(_completed_patterns) == true) && 
+	(p->Verify() >= 0)){
+      click_chatter("State::find_next_patterns Adding %s to the next "
+		    "possible patterns  \n", patname.c_str());
+      patlist.push_back(p); 
+    };
+  };
+  
+  click_chatter("State::find_next_patterns Found %d entries \n", 
+		patlist.size());
+
+  return patlist; 
+};
+
+
+
+ELEMENT_PROVIDES(State)
+CLICK_ENDDECLS
Index: rna/elements/rna/metaprotocol_state.hh
diff -u /dev/null rna/elements/rna/metaprotocol_state.hh:1.2
--- /dev/null	Sun Jan 25 11:47:09 2009
+++ rna/elements/rna/metaprotocol_state.hh	Thu Sep 11 14:41:41 2008
@@ -0,0 +1,81 @@
+/* 
+
+################################################################
+#                                                              #
+# (c) University of Southern California                        #
+#                                                              #
+#  See LICENSE.RNA for the complete license                    #
+#                                                              #
+################################################################
+
+*/
+#ifndef STATE_HH
+#define STATE_HH
+
+#include "rnaelement.hh" 
+#include "metaprotocol_patterns.hh" 
+
+//================================================================
+// State management; 
+//
+// State stores the list of patterns, instantiates them, handles the
+// message handling part of the negotiation etc. 
+//
+// The patterns effectively store the "knowledge" that is specific to
+// the individual protocol. 
+//
+//================================================================
+
+#define PROCESSED_PATTERNS "metaprotocol_patterns_db.cc" 
+
+class State {
+  
+ private:
+  RNAElement *control; 
+  Vector<Namespace *> _namespaces; 
+  Namespace *_namespace; 
+  String _start_pattern; 
+
+  Vector<RNAElement *> _elemlist;
+  Vector<RNAElement *> _available_elemlist;
+  Vector<RNAElement *> _used_elemlist;
+  Vector<Pattern *>    _patternlist;
+  Vector<Pattern *>    _completed_patterns; 
+
+ public:
+  State(RNAElement *, String initial_namespace_scope, 
+	Vector<RNAElement *> &list); 
+
+  virtual ~State(); 
+  
+  // Element management
+  virtual int                   check_elements(RNAElementType t, int count);
+  virtual RNAElement *          get_nth_element(RNAElementType t,int count);
+  virtual Vector <RNAElement *> get_elements (RNAElementType t, int count);
+  virtual Vector <RNAElement *> get_available_elements ();
+  virtual Vector <RNAElement *> get_used_elements ();
+  virtual void                  put_element(RNAElement *e);
+  
+  // Learn and unlearn patterns...
+  virtual bool                  learn_pattern(Pattern *p);
+
+  //Return the patterns stored...
+  virtual Vector<Pattern *>     get_all_patterns(); 
+  
+  // Find the matching pattern...
+  String                        get_start_pattern();
+  Pattern *                     find_pattern(String name); 
+  Vector<Pattern *>             find_next_patterns();
+  Vector<Pattern *>             find_next_verified_patterns();
+  
+  // Do/undo a pattern. This reorganizes the protocol composition.
+  int                           execute_pattern(Pattern *p);
+  int                           unexecute_pattern(Pattern *p);
+  
+  // Get a pointer to the metaprotocol module 
+  RNAElement *                  get_control(); 
+  Namespace *                   get_namespace(); 
+  String                        get_namespace_name(); 
+};
+
+#endif
Index: rna/elements/rna/modules_buffer.cc
diff -u /dev/null rna/elements/rna/modules_buffer.cc:1.2
--- /dev/null	Sun Jan 25 11:47:09 2009
+++ rna/elements/rna/modules_buffer.cc	Mon Jun 30 12:43:20 2008
@@ -0,0 +1,365 @@
+/* 
+
+################################################################
+#                                                              #
+# (c) University of Southern California                        #
+#                                                              #
+#  See LICENSE.RNA for the complete license                    #
+#                                                              #
+################################################################
+
+*/
+
+#include "modules_buffer.hh"
+
+//
+//===================================================================
+//
+
+Buffer::BufferedPacket::BufferedPacket(int port, Packet *p) {
+  assert(p);
+  _p = p;
+  _port = port; 
+  click_gettimeofday(&_time_added);
+  delay = static_cast<unsigned long>
+    (RNABUFFER_MAX_DELAY * 
+     (static_cast<double>(rand())/static_cast<double>(RAND_MAX))); 
+  //click_chatter("[BufferedPacket] delay = %ums, time_added = %ld %ld \n", 
+  // delay, _time_added.tv_sec, _time_added.tv_usec); 
+};
+
+bool 
+Buffer::BufferedPacket::expired(timeval *now) { 
+  if (!now || delay == 0)
+    return false; 
+  
+  unsigned long time_elapsed = 
+    Buffer::diff_in_ms(*now,_time_added);
+  return (time_elapsed > delay); 
+};
+
+bool 
+Buffer::BufferedPacket::expired() { 
+  timeval curr_time;
+  click_gettimeofday(&curr_time);
+  return expired(&curr_time); 
+};
+
+void
+Buffer::BufferedPacket::print() { 
+  //click_chatter("[BUFFER] delay = %u\n", delay); 
+  return; 
+};
+
+
+//
+//===================================================================
+//
+
+Buffer::Buffer() : 
+  _rnabuffer_timer(static_rnabuffer_timer_hook, this)
+{
+  // Set the seed...
+  srand(0x2322311);
+  set_type(BUFFER);
+  copies = false; 
+  delay = false; 
+  snd_count = 0; 
+
+  // Send a management packet very fifth time or so...
+  management = false; 
+  skip = 5; 
+}
+
+Buffer::~Buffer()
+{
+  // Do nothing... 
+}
+
+//
+// Buffer code cannibalized from grid/dsrroutetable.[hh|cc]
+//
+unsigned long
+Buffer::diff_in_ms(timeval t1, timeval t2)
+{
+  unsigned long s, us, ms;
+
+  //click_chatter ("diff_in_ms: t1 %ld %ld; t2 %ld %ld\n", t1.tv_sec,
+  //t1.tv_usec, t2.tv_sec, t2.tv_usec);
+
+  while (t1.tv_usec < t2.tv_usec) {
+    t1.tv_usec += 1000000;
+    t1.tv_sec -= 1;
+  }
+
+  assert(t1.tv_sec >= t2.tv_sec);
+
+  s = t1.tv_sec - t2.tv_sec;
+  assert(s < ((unsigned long)(1<<31))/1000);
+
+  us = t1.tv_usec - t2.tv_usec;
+  ms = s * 1000L + us / 1000L;
+
+//   click_chatter ("diff_in_ms: difference is %ld %ld -> %ld\n", s,
+//   us, ms);
+
+  return ms;
+}
+
+
+int 
+Buffer::finish_configuration(){ 
+  
+  //struct linkspec *link;
+  Vector<struct linkspec *> linkspecs; 
+
+  click_chatter("[%s] Buffer::finish_configuration() - " 
+		"noutputs = %d ninputs = %d\n", 
+		instance_name(), noutputs(), ninputs()); 
+
+  if (exec_finish_configuration) { 
+    add_default_bidirectional_links(&linkspecs, true); 
+    process_linkspecs(linkspecs);
+  };
+
+  return 0; 
+
+};
+int 
+Buffer::rna_finish_configuration() {
+
+
+  return 0;
+};
+
+
+int 
+Buffer::initialize(ErrorHandler *) {
+  
+  // click_chatter("[%s] Buffer::initialize \n", instance_name());
+  _rnabuffer_timer.initialize(this);
+  _rnabuffer_timer.schedule_after_msec(RNABUFFER_TIMER_INTERVAL);
+
+  return 0; 
+};
+
+
+void
+Buffer::static_rnabuffer_timer_hook(Timer *, void *v)
+{
+  // click_chatter("[Buffer::static_rnabuffer_timer_hook] \n");
+  Buffer *buf = (Buffer *)v;
+  buf->rnabuffer_timer_hook(); 
+}
+
+void
+Buffer::rnabuffer_timer_hook()
+{
+
+  Vector<BufferedPacket *> retained, dropped; 
+
+  //click_chatter("[Buffer::rnabuffer_timer_hook] \n");
+  
+  
+  timeval curr_time;
+  click_gettimeofday(&curr_time);
+
+  if (rnabuffer.size() > 0){
+    for (int i = 0; i < rnabuffer.size(); i++){ 
+      BufferedPacket *p = rnabuffer[i];
+      if (p->expired(&curr_time)){
+	//click_chatter("[%s] Resending data? \n", instance_name());
+
+	if (copies == false) { 
+	  
+	  // Here there is a 1:1 mapping between the packets that are
+	  // coming in from above and those that go out. However every
+	  // <skip>'th packet is replaced by a management packet...
+
+	  click_chatter("\n[%s] Buffer::rnabuffer_timer_hook 1 "
+			"snd_count = %d skip = %d management = %s \n", 
+			instance_name(), snd_count, skip, 
+			((management == false) ? "NONE" : "YES"));
+
+	  if ((management == true) && ((snd_count % skip) == 0)){
+	    send_management(p->_port); 
+	  } else { 
+	    RNAElement::push_data(p->_port, p->_p);
+	    dropped.push_back(p);
+	    snd_count++; 
+	  };
+	  
+	} else {
+
+	  click_chatter("[%s] Buffer::rnabuffer_timer_hook 2 "
+			"snd_count = %d skip = %d management = %d \n", 
+			instance_name(), snd_count, skip, 
+			(management == false));	  
+	  
+	  // If this buffering module is supposed to send management
+	  // packets from to time to trigger action at the next lower
+	  // layer, then skip the current packet. 
+	  if ((management == true) && ((snd_count % skip) == 0)){
+	    send_management(p->_port); 
+	  } else { 
+	    RNAElement::push_data(p->_port, p->_p->clone());	  
+	  };
+	  snd_count++; 
+	}; // send copies...
+
+      } else {
+	// has not expired....
+	retained.push_back(p);
+      };
+    };
+    
+    if (copies == false) { 
+      rnabuffer.swap(retained);
+    };
+    //delete dropped; 
+  };
+  _rnabuffer_timer.schedule_after_msec(RNABUFFER_TIMER_INTERVAL);
+
+};
+
+//################################################################
+// Send a management message to the layer below...This will trigger
+// composition and testing...
+//################################################################
+
+void 
+Buffer::send_management(int i){
+
+  LinkState *incoming_link = lookup_link(i);
+  if (! incoming_link  || !incoming_link->is_downstream()){
+    rna_click_chatter(FUNC_DEFAULT,
+		      "[%s] Buffer::send_management Dropping packet...Wrong incoming link\n", 
+		      instance_name()); 
+    return;
+  };     
+    
+  WritablePacket *p = Packet::make(3);
+  char *data = (char *)p->data();   
+  
+  // For now only an add message. Later this should be expanded to del
+  // as well.
+  *data = MESSAGE_MANAGEMENT;
+  *(data + 1) = MESSAGE_MANAGEMENT_ADD_MODULE; 
+  *(data + 2) = 0; 
+
+  rna_click_chatter(FUNC_DEFAULT,
+		    "[%s] Buffer::send_management (port %d)\n",
+		      instance_name(), i); 
+  if (debug) 
+    RNAElement::print_packet("send_management", p, false);    
+
+  RNAElement::push_data(i, p); 
+  
+};
+
+//################################################################
+//
+// Main data message handler from above and below...
+//
+//################################################################
+
+void 
+Buffer::push_data(int i, Packet *p){
+  
+  (void) i;
+
+  //click_chatter("[%s] Got a new packet on port %d \n", 
+  //	instance_name(), i); 
+  //  click_chatter("[%s] Storing the packet in the rnabuffer \n", 
+  //	instance_name());
+
+  LinkState *incoming_link = lookup_link(i);
+  if (! incoming_link ){
+    rna_click_chatter(FUNC_DEFAULT,
+		      "[%s] Buffer::push_data Dropping packet...\n", 
+		      instance_name()); 
+    p->kill();
+    return;
+  };   
+  
+  if (incoming_link->is_downstream()) { 
+
+    // Coming from upstream...
+    p->push(3); 
+    char *data = (char *)p->data(); 
+    *(data + 0) = MESSAGE_DATA; 
+    *(data + 1) = MESSAGE_DATA_NORMAL; 
+    *(data + 2) = 0; 
+
+  } else {
+
+    // Coming from downstream...Remove the header...
+    p->pull(3); 
+
+  };
+  
+  // Buffer only if the message is coming from upstream. 
+  if ((delay == true) && (incoming_link->is_downstream())){ 
+
+    click_chatter("[%s] Storing the packet in the rnabuffer \n", 
+		  instance_name());
+    BufferedPacket *b = new BufferedPacket(i, p);
+    rnabuffer.push_back(b);
+  } else {
+
+    if (debug) 
+      RNAElement::print_packet("push_data", p, false);
+    
+    // Copy the integer at the end...
+    if (0){ 
+      String snd_str(snd_count); 
+      int currlen = p->length(); 
+      WritablePacket *p1 = p->put(snd_str.length()); 
+      char *data = (char *)p1->data(); 
+      memcpy(data + currlen, snd_str.c_str(), snd_str.length()); 
+    };
+
+    RNAElement::push_data(i, p); 
+    snd_count++; 
+  };
+};
+
+//################################################################
+//
+// Handle arguments passed to this module during configuration phase
+// of Click. It does not yet require RNA-specific configuration
+// function (rna_finish_configuration); 
+//
+//################################################################
+int
+Buffer::configure(Vector<String> &conf, ErrorHandler *errh)
+{
+  
+  // click_chatter("Configuring Buffer... %s \n", class_name());
+  
+  RNAElement::configure(conf, errh); 
+
+  if (cp_va_parse(conf, this, errh,
+		  cpKeywords, 
+		  "COPIES", cpBool, "Send packet copies repeated?", &copies,
+		  "DELAY", cpBool, "Enable delayed send", &delay, 
+		  "MANAGEMENT", cpBool, "Enable sending management packets",&management,
+		  "SKIP", cpInteger, "#packets between successive management packets",&skip,
+		  
+		  cpEnd) < 0)
+    return -1; 
+  
+  if (exec_finish_configuration) 
+    finish_configuration(); 
+
+  return 0;
+}
+
+ELEMENT_REQUIRES(RNAElement)
+EXPORT_ELEMENT(Buffer)
+ELEMENT_MT_SAFE(Buffer)
+
+CLICK_ENDDECLS
+
+
+
Index: rna/elements/rna/modules_buffer.hh
diff -u /dev/null rna/elements/rna/modules_buffer.hh:1.2
--- /dev/null	Sun Jan 25 11:47:09 2009
+++ rna/elements/rna/modules_buffer.hh	Fri Dec 26 16:57:00 2008
@@ -0,0 +1,106 @@
+/* 
+
+################################################################
+#                                                              #
+# (c) University of Southern California                        #
+#                                                              #
+#  See LICENSE.RNA for the complete license                    #
+#                                                              #
+################################################################
+
+*/
+#ifndef CLICK_BUFFERELEMENT_HH
+#define CLICK_BUFFERELEMENT_HH
+
+//##########################################################
+//
+//
+// This is a multi-purpose buffering module stores the elements delayed
+// by some time (possibly zero), generate management trigger messages,
+// make copies of packets etc.
+//
+//
+// Buffer code cannibalized from grid/dsrroutetable.[hh|cc]
+//##########################################################
+
+#include "rnaelement.hh" 
+
+#define RNABUFFER_TIMER_INTERVAL 5000           // Every 5 secs
+#define RNABUFFER_MAX_DELAY 10000               // Delay max 10 secs
+
+class Buffer : public RNAElement { 
+public:
+
+ // Packets buffered while waiting for route replies
+  class BufferedPacket
+  {
+  public:
+    Packet *_p;
+    int _port; 
+    struct timeval _time_added;
+    unsigned long delay; 
+
+    BufferedPacket(int port, Packet *p);
+
+    bool expired(timeval *now);
+    bool expired();
+
+    void print();
+  };
+  
+  // Constructor/destructor 
+  Buffer();
+  ~Buffer();
+  
+  // Click related maintenance code...
+  int initialize(ErrorHandler *); 
+  static void static_initialize() { RNAElement::static_initialize_default(); };
+  static void static_cleanup() { RNAElement::static_initialize_default(); };
+  const char *class_name() const { return default_class_name(); } 
+  const char *port_count() const	{ return "-/-"; } 
+  const char *processing() const	{ return PUSH; } 
+  
+  // Configuration 
+  // 
+  // COPIES     Send packet copies repeated?
+  // DELAY      Enable delayed send
+  //            (default = false; true => each packet delayed for a random time < some max )
+  // MANAGEMENT Enable sending management packets
+  // SKIP       The number of packets between successive management packets
+  //            (default = 5) 
+
+  int configure(Vector<String> &, ErrorHandler *);
+  int rna_finish_configuration(); // Complete the configuration step...
+  int finish_configuration(); 
+  bool can_live_reconfigure() const     { return true; }
+  
+  // The buffer can also generate management messages from time to
+  // time.
+  void push_data(int i, Packet *p); 
+  void send_management(int port); 
+
+  // Timer management 
+  static unsigned long diff_in_ms(timeval t1, timeval t2); 
+  static void static_rnabuffer_timer_hook(Timer *, void *);
+  void rnabuffer_timer_hook();
+  
+ private:
+
+  // Buffered packets 
+  Vector<BufferedPacket *> rnabuffer;
+  
+  // Internal timer object...
+  Timer _rnabuffer_timer;
+
+  bool copies; // should I make copies of the incoming packet from above and send them? 
+  bool delay;  // should I delay the packets coming from above? 
+  int snd_count;   // how many packets have I sent? 
+
+  // Should I send management packets from time to time; how frequently? 
+  bool management; 
+  int skip; 
+
+};
+
+CLICK_ENDDECLS
+#endif
Index: rna/elements/rna/modules_crypt.cc
diff -u /dev/null rna/elements/rna/modules_crypt.cc:1.1
--- /dev/null	Sun Jan 25 11:47:09 2009
+++ rna/elements/rna/modules_crypt.cc	Fri Jun 27 10:40:57 2008
@@ -0,0 +1,342 @@
+/* 
+
+################################################################
+#                                                              #
+# (c) University of Southern California                        #
+#                                                              #
+#  See LICENSE.RNA for the complete license                    #
+#                                                              #
+################################################################
+
+*/
+
+#include "modules_crypt.hh" 
+
+//#################################################################
+// 
+// This is a simple symmetric key encryption. It assumes that the key
+// is already shared and it generates the initialization vector
+// randomly and embeds it in the message. 
+//
+//#################################################################
+
+Crypt::Crypt() 
+{
+  set_type(CRYPT); 
+
+  // This is packet source. Dont check for connection state.
+  set_skip_conn_check(true); 
+
+
+}
+
+Crypt::~Crypt() 
+{
+}
+
+//#################################################################
+// 
+// Assume a two way path and assume a default configuration. 
+//
+//             ^         |
+//             |         V
+//                Crypt  
+//             |         ^
+//             V         |
+//
+//#################################################################
+
+int 
+Crypt::finish_configuration() {
+
+  rna_click_chatter(FUNC_ENTRY, 
+		    "[%s] Crypt finish_configuration \n", 
+		    instance_name());  
+  
+  // Add the links to begin with...
+  Vector<struct linkspec *> links; 
+  add_default_bidirectional_links(&links, true);  // cross layer...
+  rna_click_chatter(FUNC_DEFAULT, 
+		    "[%s] linkspecs size = %d \n", 
+		    instance_name(), links.size()); 
+  process_linkspecs(links); 
+  print_links();
+
+  return 0; 
+};
+
+
+//#####################################################
+// Acknowledgement: This code has been copied from
+// http://linuxgazette.net/issue87/vinayak.html
+//
+// Copyright (c) 2003 by Vinayak Hegde. This material may be
+// distributed only subject to the terms and conditions set forth in
+// the Open Publication License, v1.0 or later (the latest version is
+// presently available at http://www.opencontent.org/openpub/).
+//
+// The code has been edited to suit the need of RNA by Venkata Pingali
+// (USC/ISI) - April 2008 USC/ISI copyright applies to the modified
+// code.
+//
+//####################################################
+
+Packet *
+Crypt::encrypt (Packet *p)
+{
+
+  int olen = 0, tlen = 0;
+
+  // Reinitialize the initialization vector...
+  unsigned char iv[8]; 
+  for (int i = 0; i < 8; i++) 
+    iv[i] = random () & 0x0ff;
+ 
+  // Make a clone and write the data....
+  Packet *p0 = p->clone(); 
+
+  // Key question. What will be the resulting size of the message?     
+  EVP_CIPHER_CTX ctx;
+  EVP_CIPHER_CTX_init (& ctx);
+  EVP_EncryptInit (& ctx, EVP_bf_cbc (), 
+		   (const unsigned char *)key, 
+		   (const unsigned char *)iv);
+  
+  int cipher_blk_size = EVP_CIPHER_CTX_block_size(&ctx);
+  int iv_length = EVP_CIPHER_CTX_iv_length(&ctx);
+  p = p->push(cipher_blk_size); 
+  
+  click_chatter("[%s] encrypt: cipher_blk_size = %d pkt len = %d \n", 
+		instance_name(), cipher_blk_size, p->length());
+
+  // Get the beginning of the data
+  unsigned char *data_out = (unsigned char *)p->data();
+    
+  // 
+  if (EVP_EncryptUpdate (&ctx, data_out, &olen,p0->data(),p0->length()) != 1){
+    printf ("error in encrypt update\n");
+    return 0;
+  }
+    
+  if (EVP_EncryptFinal (& ctx, data_out + olen, &tlen) != 1){
+    printf ("error in encrypt final\n");
+    return 0;
+  }
+  
+  int diff = (p->length() - (olen + tlen)); 
+  click_chatter("[%s] pkt len = %d olen = %d tlen = %d diff = %d \n", 
+		instance_name(), p->length(), olen, tlen, diff); 
+  if (diff > 0) 
+    p->take(diff); 
+  
+  olen += tlen;
+
+  print_packet("encrypt", p);
+
+  // Push the initialization vector...
+  p = p->push(iv_length);
+  data_out = (unsigned char *)p->data();
+  memcpy (data_out, iv, 8);
+
+  EVP_CIPHER_CTX_cleanup (& ctx);
+  
+  p0->kill(); 
+  
+  return p;
+}
+
+Packet *
+Crypt::decrypt (Packet *p)
+{
+
+  int olen = 0, tlen = 0;
+  
+  // Remove the nonce from the header...
+  Packet *p0 = p->clone();   
+  
+  // Extract the initialization vector....
+  unsigned char iv[8]; 
+  unsigned char *data_in = (unsigned char *)p0->data(); 
+  memcpy (iv, data_in, sizeof(iv)); 
+  
+  // Use the new IV to initialize the packet...
+  EVP_CIPHER_CTX ctx;
+  EVP_CIPHER_CTX_init (& ctx);
+  EVP_DecryptInit (& ctx, EVP_bf_cbc (), key, iv);
+  
+  // over-write the clone...
+  if (EVP_DecryptUpdate (& ctx, 
+			 (unsigned char *)p->data(), & olen, 
+			 ((unsigned char *)p0->data() + sizeof(iv)), 
+			 (p->length() - sizeof(iv))) != 1){
+    printf ("error in decrypt update\n");
+    return 0;
+  }
+      
+  if (EVP_DecryptFinal (& ctx, ((unsigned char *)p->data()+olen),&tlen) != 1){
+    printf ("error in decrypt final\n");
+    return 0;
+  }
+    
+  olen += tlen;
+
+  int diff = (p->length() - olen);
+  if (diff > 0)
+    p->take(diff); 
+  
+  print_packet("decrypt", p);
+
+  EVP_CIPHER_CTX_cleanup (& ctx);
+  
+  p0->kill();
+  
+  return p;
+
+}; 
+
+//#################################################################
+// 
+// End included the code...
+//
+//#################################################################
+
+void
+Crypt::push_data(int port, Packet *p){  
+  
+  LinkState *incoming_link = lookup_link(port);
+  if (! incoming_link ){
+    rna_click_chatter(FUNC_DEFAULT,
+		      "[%s] Crypt::push_data Dropping packet...\n", 
+		      instance_name()); 
+    p->kill();
+    return;
+  };
+  
+  
+  // Encrypt the packet if coming from above and decrypt in case the
+  // packet is coming from below. 
+  if (incoming_link->is_downstream()) { 
+    
+    p = encrypt(p); 
+    
+    if (!p) 
+      return; 
+
+    // Coming from upstream...
+    p = p->push(3); 
+    
+    // insert the normal header...
+    char *data = (char *)p->data(); 
+    *(data + 0) = MESSAGE_DATA; 
+    *(data + 1) = MESSAGE_DATA_NORMAL; 
+    *(data + 2) = 0; 
+    
+  } else {
+
+    // Coming from downstream...Remove the header...
+    p->pull(3); 
+
+    p = decrypt(p); 
+    if (!p) 
+      return; 
+    
+  };
+  
+  if (debug) 
+    RNAElement::print_packet("Crypt::push_data", p, false);
+
+  RNAElement::push_data(port, p);   
+  
+  return; 
+};
+
+// Read the key in from the configuration file. In case the key is not
+// specified, a pre-defined key is used.
+
+int
+Crypt::configure(Vector<String> &conf, ErrorHandler *errh)
+{
+  
+  String key_in;
+  
+  RNAElement::configure(conf, errh); 
+  
+  if (cp_va_parse(conf, this, errh,
+		  cpKeywords, 
+		  "KEY", cpString, "Symmetric Key", &key_in, 
+		  cpEnd) < 0)
+    return -1; 
+  
+  if (debug) 
+    rna_click_chatter(FUNC_DEFAULT, 
+		      "[%s] Configuring Crypt. \n",  
+		      instance_name());
+  
+  // 
+  if (key_in.length() == 0) { 
+    unsigned char key_static[16] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
+    memcpy(key, key_static, sizeof(key)); 
+  } else {
+    unsigned char *key_in_c = (unsigned char *)key_in.c_str(); 
+
+    if (
+	((key_in.length() != 32) && (key_in.length() != 34)) || 
+	((key_in.length() == 34) && 
+	 ((key_in_c[0] != '0') && (key_in_c[1] != 'x'))) || 
+	((key_in.length() == 32) && 
+	 ((key_in_c[0] == '0') && (key_in_c[1] == 'x')))
+	){
+      rna_click_chatter(FUNC_DEFAULT, 
+			"[%s] Configuring Crypt. Invalid key. \n",  
+			instance_name());
+      return -1; 
+    };
+
+    if (key_in.length() == 34) 
+      key_in_c += 2; 
+    
+    // Convert the 32 character string into a 16 byte binary 
+    // string. 
+    // 0xabcd12341 processed as ab => ('a' - '0')
+    // 
+    if (debug) {
+      rna_click_chatter(FUNC_DEFAULT, 
+		      "[%s] Configure(): Parsing Key = \"%s\" (length = %d)\n", 
+		      instance_name(), key_in_c, key_in.length());
+
+      rna_click_chatter(FUNC_DEFAULT, 
+		      "[%s] Configure(): Processed Key = ", 
+		      instance_name());
+    };
+
+    for (int i = 0; i < 4; i++){ 
+      unsigned char c[9]; 
+      unsigned long x; 
+      
+      // Copy 8 characters at a time
+      memcpy((void *)c, (void *)&key_in_c[i << 3], 8);
+      c[9] = '\0';
+
+      x = strtoul((const char *)c, 0, 16); 
+      *((unsigned long *)&key[i << 2]) = x; 
+
+      if (debug) rna_click_chatter(FUNC_DEFAULT, "[%8.8x]:", x);
+
+    };
+    if (debug) rna_click_chatter(FUNC_DEFAULT, "\n"); 
+
+  }
+  
+  // Finally add all the links and discover peers 
+  if (exec_finish_configuration) 
+    finish_configuration(); 
+  
+  return 0;
+
+};
+
+
+ELEMENT_REQUIRES(RNAElement)
+EXPORT_ELEMENT(Crypt)
+
+CLICK_ENDDECLS
Index: rna/elements/rna/modules_crypt.hh
diff -u /dev/null rna/elements/rna/modules_crypt.hh:1.1
--- /dev/null	Sun Jan 25 11:47:09 2009
+++ rna/elements/rna/modules_crypt.hh	Fri Jun 27 10:40:57 2008
@@ -0,0 +1,74 @@
+/* 
+
+################################################################
+#                                                              #
+# (c) University of Southern California                        #
+#                                                              #
+#  See LICENSE.RNA for the complete license                    #
+#                                                              #
+################################################################
+
+*/
+#ifndef CLICK_CRYPT_HH
+#define CLICK_CRYPT_HH
+
+#include "rnaelement.hh" 
+
+#include "openssl/evp.h" 
+#include <openssl/stack.h>
+#include <openssl/asn1.h>
+#include <openssl/safestack.h>
+
+#ifndef NO_RSA
+#include <openssl/rsa.h>
+#endif
+
+#ifndef NO_DSA
+#include <openssl/dsa.h>
+#endif
+
+#define IP_SIZE  128 
+#define OP_SIZE  136
+
+//############################################
+//
+// Simple symmetric key encryption module...
+//
+//############################################
+
+
+class Crypt : public RNAElement { 
+public:
+  
+  // Constructor/destructor
+  Crypt();
+  ~Crypt();
+  
+  // Click-related stuff 
+  static void static_initialize() { RNAElement::static_initialize_default(); };
+  static void static_cleanup() { RNAElement::static_initialize_default(); };
+  const char *class_name() const  { return  default_class_name(); };
+  const char *port_count() const	{ return "-/-"; } 
+  const char *processing() const	{ return PUSH; } 
+  
+  // Configuration...
+  int configure(Vector<String> &, ErrorHandler *);
+  int configure_phase() { return CONFIGURE_PHASE_LAST; }; 
+  int finish_configuration(); // Complete the configuration step...
+  bool can_live_reconfigure() const     { return true; }
+  
+  // Message handling...Encrypts messages going downstream 
+  // and decrypts messages going upstream...
+  void push_data(int port, Packet *p); 
+  
+  // Helper functions...
+  Packet *encrypt (Packet *p);
+  Packet *decrypt (Packet *p);
+  
+ private:
+  unsigned char key[16]; 
+
+};
+
+CLICK_ENDDECLS
+#endif
Index: rna/elements/rna/modules_demultiplexor.cc
diff -u /dev/null rna/elements/rna/modules_demultiplexor.cc:1.1
--- /dev/null	Sun Jan 25 11:47:09 2009
+++ rna/elements/rna/modules_demultiplexor.cc	Fri Jun 27 10:40:57 2008
@@ -0,0 +1,277 @@
+/* 
+
+################################################################
+#                                                              #
+# (c) University of Southern California                        #
+#                                                              #
+#  See LICENSE.RNA for the complete license                    #
+#                                                              #
+################################################################
+
+*/
+
+#include "modules_demultiplexor.hh"
+
+// Initialization and cleanup...
+
+Demultiplexor::Demultiplexor()
+{
+  set_type(DEMULTIPLEXOR); 
+  first = true; 
+}
+
+Demultiplexor::~Demultiplexor()
+{
+  // Do nothing... 
+}
+
+//################################################################
+//
+// parse input arguments...
+//
+//################################################################
+int
+Demultiplexor::configure(Vector<String> &conf, ErrorHandler *errh)
+{
+
+  RNAElement::configure(conf, errh); 
+
+  if (debug) 
+    rna_click_chatter(FUNC_ENTRY, "[%s] Configuring Demultiplexor \n",  
+		      instance.c_str());
+  
+  if (exec_finish_configuration) 
+    finish_configuration(); 
+
+  return 0;
+}
+
+// ################################################################
+// Call from the module that is composing this demuxer, i.e.,
+// metaprotocol.
+// ################################################################
+
+int 
+Demultiplexor::rna_finish_configuration(){
+  
+  if (debug) 
+    rna_click_chatter(FUNC_ENTRY,"[%s] rna_finish_configuration Entry \n",
+		      instance_name());
+  
+  // Obtain a list of all the links to downstream elements and
+  // initialize the linkstate corresponding to each (e.g., obtain a
+  // connection state associated with each link). 
+
+  Vector<LinkState *> downstream; 
+  downstream =   list_downstream_elements(true, // downstream
+					  true, // layeragnostic
+					  false, // crosslayer
+					  true,// agnostic remote
+					  false // remote is unknown
+					  );
+
+  for(int i = 0; i < downstream.size(); i++) {
+    LinkState *l = downstream[i];
+    initialize_link(l); 
+  };
+
+  rna_click_chatter(FUNC_EXIT,"[%s] rna_finish_configuration Exit \n",
+		    instance_name());
+
+  return 0; 
+};
+
+
+// ################################################################
+//
+// Look for an outgoing link that is headed towards downstream (or
+// upstream) and crosslayer (or not). 
+//
+// ################################################################
+LinkState *Demultiplexor::select_outgoing_link(Packet *p,
+					     LinkState *incoming, 
+					     bool downstream, 
+					     bool layeragnostic, 
+					     bool crosslayer,
+					     bool agnostic_remote,             
+					     bool remote_unknown){
+  (void) incoming; 
+
+  rna_click_chatter(FUNC_ENTRY, 
+		    "[%s] Demultiplexor::select_outgoing_link Entered \n",
+		    instance_name());
+  
+  LinkState *return_l = NULL;
+  
+  if (!downstream) { 
+
+    // Look at packets that are headed upstream...  Otherwise ignore
+    // the messages...
+
+    // Extract the data...
+    const char *header = (const char *)p->data();
+    
+    // Match the registered pattern; 
+    Vector<MuxDemuxCmd *> v;
+    for (int i = 0; i < DemuxTable.size(); i++){
+      MuxDemuxCmd *m = DemuxTable[i];
+      if (!m)
+	continue; 
+      const char *pattern = m->pattern;
+      int length = m->len; 
+      if (memcmp(header, pattern, length) == 0){
+	// Found the match.
+	return_l = m->l;
+	rna_click_chatter(FUNC_DEFAULT, "[%s] Demultiplexor::"
+			  "select_outgoing_link - Found a match\n",
+			  instance_name());
+	return_l->print(instance_name());
+	break;
+      };
+    };
+    
+  } else { 
+
+    Vector<LinkState *> templist; 
+  
+    // Identify all possible links...
+    for (int i = 0; i < all_links.size(); i++){
+      LinkState *l = all_links[i];
+      
+      // Find a link in which I am an downstream node and 
+      // the link is outgoing...
+      if (l->is_outgoing()                         // ignore incoming links
+	  && ((!layeragnostic && (l->is_crosslayer() == crosslayer)) ||
+	      (layeragnostic ))
+	  && ((downstream && l->is_upstream()) || 
+	      (!downstream && l->is_downstream()))
+	  && ((agnostic_remote) || 
+	      (! agnostic_remote && 
+	               (l->is_remote_unknown() == remote_unknown)))
+	  ) { 
+	templist.push_back(l);
+      };
+    };
+    
+    if (templist.size() >= 2) { 
+      if (first) {
+	click_chatter("[%s] Selecting alternative path 1 \n", instance_name());
+	first = false; 
+	return_l = templist[0];
+      } else {
+	click_chatter("[%s] Selecting alternative path 2 \n", instance_name());
+	first = true; 
+	return_l = templist[1];      
+      }
+    } else if (templist.size() == 1 ) { 
+      click_chatter("[%s] Selecting alternative path 1 (only available)\n", 
+		    instance_name()); 
+      first = true; 
+      return_l = templist[0]; 
+    };
+
+  };
+
+  
+  rna_click_chatter(FUNC_EXIT, 
+		    "[%s] Demultiplexor::select_outgoing_link Exit\n",
+		    instance_name());
+  return return_l; 
+}
+
+
+// ################################################################
+//
+// Handle pattern registration requests from the upstream modules. 
+//
+// ################################################################
+
+RNAControlMsg *
+Demultiplexor::module_specific_control(RNAControlMsg *c){
+  
+  rna_click_chatter(FUNC_ENTRY, 
+		    "[%s] RNAElement::module_specific_control Entered \n", 
+		    instance_name());
+
+  // Create a reply object and the default response...and fill it up.
+  RNAControlMsg *reply = new RNAControlMsg(RNAControlMsg::REPLY); 
+  reply->set_unsupported(); 
+  reply->set_error("NONE!"); 
+
+  // Sanity check...
+  if (!c){ 
+    reply->set_invalid(); 
+    reply->set_error("c is empty!"); 
+    rna_click_chatter(FUNC_EXIT, "[%s] RNAElement::control Exit \n", 
+		      instance_name());
+    return reply; 
+  };
+  
+  c->print(instance_name()); 
+
+  reply->set_operationtype(c->o);
+  switch(c->m) { 
+  case RNAControlMsg::COMMAND: 
+    switch(c->o){
+    case RNAControlMsg::CONFIGURE: 
+      switch(c->op){
+      case RNAControlMsg::DEMUX_PATTERN_ADD: 
+	do { 
+	  MuxDemuxCmd *m = (MuxDemuxCmd *)c->get_data();
+	  if (m) { 
+	    m->print("Add demux pattern");
+	    LinkState *l = lookup_link(m->e, LinkState::INCOMING); 
+	    if (l) { 
+	      m->l = l;
+	      DemuxTable.push_back(m);
+	      reply->set_data(0); 
+	      reply->set_success(); 
+	    } else {
+	      reply->set_error("MuxDemuxCmd Invalid parameter e");
+	      reply->set_invalid();
+	    }
+	  } else {
+	    reply->set_error("MuxDemuxCmd (data) is NULL!");
+	    reply->set_invalid();
+	  }
+	} while (0); 
+	break; 
+      case RNAControlMsg::DEMUX_PATTERN_DEL: 
+	do { 
+	  MuxDemuxCmd *oldm = (MuxDemuxCmd *)c->get_data();
+	  Vector<MuxDemuxCmd *> v;
+	  for (int i = 0; i < DemuxTable.size(); i++){
+	    MuxDemuxCmd *m = DemuxTable[i];
+	    if (oldm != m){ // skip this one? 
+	      v.push_back(m);
+	    };
+	  }; // For loop..
+	  DemuxTable.swap(v);
+	} while(0);
+	break; 
+      default: 
+	break;
+      };
+      break;
+    default: 
+      break; 
+    };
+    break; 
+  default: 
+    break; 
+    
+  };
+
+  rna_click_chatter(FUNC_EXIT, "[%s] RNAElement::module_specific_control EXIT\n", 
+		    instance_name());
+  return reply; 
+  
+};
+
+
+
+
+ELEMENT_REQUIRES(RNAElement)
+EXPORT_ELEMENT(Demultiplexor)
+
+CLICK_ENDDECLS
Index: rna/elements/rna/modules_demultiplexor.hh
diff -u /dev/null rna/elements/rna/modules_demultiplexor.hh:1.1
--- /dev/null	Sun Jan 25 11:47:09 2009
+++ rna/elements/rna/modules_demultiplexor.hh	Fri Jun 27 10:40:57 2008
@@ -0,0 +1,76 @@
+/* 
+
+################################################################
+#                                                              #
+# (c) University of Southern California                        #
+#                                                              #
+#  See LICENSE.RNA for the complete license                    #
+#                                                              #
+################################################################
+
+*/
+#ifndef CLICK_DEMULTIPLEXOR_HH
+#define CLICK_DEMULTIPLEXOR_HH
+
+#include "rnaelement.hh" 
+
+//###############################################################
+//
+// Demultiplexing module. 
+//
+//             |  |      |   |       |   |
+//             +--+      +---+       +---+
+//              ||         ||          ||
+//          +---------------------------------+
+//           \                               / 
+//            \           DEMUX             /
+//             +---------------------------+
+//                          ||
+//
+
+// The demuxing module supports registration of the limited demuxing
+// patterns from the modules attached to it upstream.
+//
+//###############################################################
+class Demultiplexor : public RNAElement { 
+
+public:
+
+  // Constructor/destructors...
+  Demultiplexor();
+  ~Demultiplexor();
+ 
+  // Click functions...
+  static void static_initialize() { RNAElement::static_initialize_default(); };
+  static void static_cleanup() { RNAElement::static_initialize_default(); };  
+  const char *class_name() const	{ return default_class_name(); }
+  const char *port_count() const	{ return "-/-"; } 
+  const char *processing() const	{ return PUSH; } 
+  
+  // Initialization code...
+  int configure(Vector<String> &, ErrorHandler *);
+  int finish_configuration() { return RNAElement::finish_configuration(); }; 
+  int rna_finish_configuration(); 
+  
+
+  // Only the selection of the outgoing link is overridden. Other
+  // functions are reused from the base class.
+  virtual LinkState *select_outgoing_link(Packet *p, 
+					LinkState *incoming, 
+					bool downstream = true, 
+					bool layeragnostic = false,
+					bool crosslayer = false,
+					bool agnostic_remote = true,
+					bool remote_unknown = false); 
+  
+  // Handle registration requests from the modules above.
+  RNAControlMsg *module_specific_control(RNAControlMsg *c); 
+
+ private:
+  bool first; 
+  Vector<MuxDemuxCmd *> DemuxTable; 
+
+};
+
+CLICK_ENDDECLS
+#endif
Index: rna/elements/rna/modules_flexlink.cc
diff -u /dev/null rna/elements/rna/modules_flexlink.cc:1.3
--- /dev/null	Sun Jan 25 11:47:09 2009
+++ rna/elements/rna/modules_flexlink.cc	Fri Jan  2 14:06:58 2009
@@ -0,0 +1,205 @@
+/* 
+
+################################################################
+#                                                              #
+# (c) University of Southern California                        #
+#                                                              #
+#  See LICENSE.RNA for the complete license                    #
+#                                                              #
+################################################################
+
+*/
+
+////////////////////////////////////////////////////////////////////////
+//
+// This module will randomly drop packets
+//
+////////////////////////////////////////////////////////////////////////
+
+#include "modules_flexlink.hh"
+
+FlexLink::FlexLink() 
+{
+  // Set the seed...
+  srand(0x2322311);
+  set_type(FLEXLINK);
+  snd_count = 0; 
+  dropped_count = 0; 
+
+}
+
+FlexLink::~FlexLink()
+{
+  // Do nothing... 
+}
+
+int 
+FlexLink::finish_configuration(){ 
+  
+  //struct linkspec *link;
+  Vector<struct linkspec *> linkspecs; 
+
+  click_chatter("[%s] FlexLink::finish_configuration() - " 
+		"noutputs = %d ninputs = %d\n", 
+		instance_name(), noutputs(), ninputs()); 
+
+  if (exec_finish_configuration) { 
+    add_default_bidirectional_links(&linkspecs, true); 
+    process_linkspecs(linkspecs);
+  };
+
+  return 0; 
+
+};
+int 
+FlexLink::rna_finish_configuration() {
+
+
+  return 0;
+};
+
+
+//################################################################
+//
+// Apply loss rate if necessary before forwarding. A packet handed off
+// to this function is not returned. It is either forwarded or killed.
+//
+//################################################################
+void FlexLink::push_data_aux(int i, Packet *p) {
+  
+  // Where did this packet come from? 
+  LinkState *incoming_link = lookup_link(i);
+  if (! incoming_link ){
+    rna_click_chatter(FUNC_DEFAULT,
+		      "[%s] FlexLink::push_data_aux Dropping packet...\n", 
+		      instance_name()); 
+    p->kill();
+    return;
+  };   
+  
+  // Make note of it 
+  if (debug) 
+    RNAElement::print_packet("push_data_aux", p, false);
+
+  // Am I upstream node? That is, is the message coming from
+  // downstream? In that case, dont do anything
+  if (incoming_link->is_upstream()) { 
+    RNAElement::push_data(i, p); 
+  }; 
+  
+  // Am i a downstream node? Is the message coming from upstream node?
+  // Then drop with some probability.
+  if (incoming_link->is_downstream()){ 
+    // Is this a lossy link? 
+    if (lossrate > 0) { 
+      double r = (static_cast<double>(rand())/static_cast<double>(RAND_MAX));	
+      if (r < lossrate ) { 
+	click_chatter("[%s] push_data_aux: DROP in flexbuf "
+		      "(r=%0.3f,lossrate=%0.3f; dropped = %d, sent = %d)\n", 
+		      instance_name(), r, lossrate, dropped_count+1, snd_count);
+	p->kill();
+	dropped_count++; 
+      } else { 
+	// Should not be dropped. forward it...
+	click_chatter("[%s] push_data_aux: SEND in "
+		      "flexbuf (r=%0.3f,lossrate=%0.3f; dropped = %d, "
+		      "sent = %d)\n", 
+		      instance_name(), r, lossrate, dropped_count, snd_count);
+	RNAElement::push_data(i, p); 
+	snd_count++; 
+      };
+    } else { 
+      // Link not lossy. So forward it...
+      click_chatter("[%s] push_data_aux: SEND in "
+		    "flexbuf (lossrate=%0.3f; dropped = %d, "
+		    "sent = %d)\n", 
+		    instance_name(), lossrate, dropped_count, snd_count);
+      RNAElement::push_data(i, p); 
+      snd_count++; 
+    };
+  };
+  
+  return;
+};
+
+//################################################################
+//
+// Main data message handler from above and below...
+//
+//################################################################
+
+void 
+FlexLink::push_data(int i, Packet *p){
+  
+  (void) i;
+
+  //click_chatter("[%s] Got a new packet on port %d \n", 
+  //	instance_name(), i); 
+  //  click_chatter("[%s] Storing the packet in the flexbuf \n", 
+  //	instance_name());
+
+  LinkState *incoming_link = lookup_link(i);
+  if (! incoming_link ){
+    rna_click_chatter(FUNC_DEFAULT,
+		      "[%s] FlexLink::push_data Dropping packet...\n", 
+		      instance_name()); 
+    p->kill();
+    return;
+  };   
+  
+  // Adding a new header is not really necessary - This is just to
+  // detect the fact that the packet has gone through a module.
+
+  if (incoming_link->is_downstream()) { 
+    // Coming from upstream...
+    p->push(3); 
+    char *data = (char *)p->data(); 
+    *(data + 0) = MESSAGE_DATA; 
+    *(data + 1) = MESSAGE_DATA_NORMAL; 
+    *(data + 2) = 0; 
+  } else {
+    // Coming from downstream...Remove the header...
+    p->pull(3); 
+  };
+  
+  // Apply the probability 
+  push_data_aux(i, p);
+
+};
+
+//################################################################
+//
+// Handle arguments passed to this module during configuration phase
+// of Click. It does not yet require RNA-specific configuration
+// function (rna_finish_configuration); 
+//
+//################################################################
+int
+FlexLink::configure(Vector<String> &conf, ErrorHandler *errh)
+{
+  
+  // click_chatter("Configuring FlexLink.... %s \n", class_name());
+  
+  RNAElement::configure(conf, errh); 
+
+  if (cp_va_parse(conf, this, errh,
+		  cpKeywords, 
+		  "LOSSRATE", cpDouble, 
+		        "Fraction of packets lost", &lossrate, 
+		  cpEnd) < 0)
+    return -1; 
+  
+  if (lossrate > 1 || lossrate < 0)
+    return -1; 
+
+  if (exec_finish_configuration) 
+    finish_configuration(); 
+
+  return 0;
+}
+
+ELEMENT_REQUIRES(RNAElement)
+EXPORT_ELEMENT(FlexLink)
+ELEMENT_MT_SAFE(FlexLink)
+
+CLICK_ENDDECLS
Index: rna/elements/rna/modules_flexlink.hh
diff -u /dev/null rna/elements/rna/modules_flexlink.hh:1.3
--- /dev/null	Sun Jan 25 11:47:09 2009
+++ rna/elements/rna/modules_flexlink.hh	Fri Jan  2 14:06:58 2009
@@ -0,0 +1,66 @@
+/* 
+
+################################################################
+#                                                              #
+# (c) University of Southern California                        #
+#                                                              #
+#  See LICENSE.RNA for the complete license                    #
+#                                                              #
+################################################################
+
+*/
+#ifndef CLICK_FLEXLINK_HH
+#define CLICK_FLEXLINK_HH
+
+//##########################################################
+//
+//
+// This module with drop packets with a given probability...
+//
+// Buffer code cannibalized from grid/dsrroutetable.[hh|cc]
+// Configuration 
+// 
+// LOSSRATE       Fraction of packets lost 
+// 
+//
+//##########################################################
+
+#include "rnaelement.hh" 
+
+class FlexLink : public RNAElement { 
+
+public:
+
+  // Constructor/destructor 
+  FlexLink();
+  ~FlexLink();
+  
+  // Click related maintenance code...
+  static void static_initialize() { RNAElement::static_initialize_default(); };
+  static void static_cleanup() { RNAElement::static_initialize_default(); };
+  const char *class_name() const { return default_class_name(); } 
+  const char *port_count() const	{ return "-/-"; } 
+  const char *processing() const	{ return PUSH; } 
+  
+  int configure(Vector<String> &, ErrorHandler *);
+  int rna_finish_configuration(); // Complete the configuration step...
+  int finish_configuration(); 
+  bool can_live_reconfigure() const     { return true; }
+  
+  // The buffer can also generate management messages from time to
+  // time.
+  void push_data(int i, Packet *p); 
+  void push_data_aux(int i, Packet *p); 
+
+ private:
+
+  double lossrate;    // what fraction of the packets are lost? 
+  
+  // Internal...
+  int snd_count;       // how many packets have I sent downstream? 
+  int dropped_count;   // how many packets have I dropped? 
+
+};
+
+CLICK_ENDDECLS
+#endif
Index: rna/elements/rna/modules_multiplexor.cc
diff -u /dev/null rna/elements/rna/modules_multiplexor.cc:1.1
--- /dev/null	Sun Jan 25 11:47:09 2009
+++ rna/elements/rna/modules_multiplexor.cc	Fri Jun 27 10:40:58 2008
@@ -0,0 +1,184 @@
+/* 
+
+################################################################
+#                                                              #
+# (c) University of Southern California                        #
+#                                                              #
+#  See LICENSE.RNA for the complete license                    #
+#                                                              #
+################################################################
+
+*/
+
+#include "modules_multiplexor.hh"
+
+//################################################################
+// Constructor/destructor...
+//################################################################
+
+Multiplexor::Multiplexor()
+{
+  set_type(MULTIPLEXOR); 
+  first = true;
+  strategy = "ALTERNATE_TWO"; 
+}
+
+Multiplexor::~Multiplexor()
+{
+  // Do nothing... 
+}
+
+//################################################################
+// Parse the arguments provided in the configuration file.  Called
+// during the initialization of Click router.
+//################################################################
+int
+Multiplexor::configure(Vector<String> &conf, ErrorHandler *errh)
+{
+  
+  RNAElement::configure(conf, errh); 
+
+  if (cp_va_parse(conf, this, errh,
+		  cpKeywords, 
+		  "STRATEGY", cpString, "multiplexing strategy", &strategy,
+		  cpEnd) < 0)
+    return -1; 
+  
+  if (strategy != "ALTERNATE_TWO") 
+    return -1; 
+
+  if (exec_finish_configuration) 
+    finish_configuration(); 
+  
+  return 0;
+}
+
+//################################################################
+// 
+// This will effectively initialize all the links information. Called
+// by the metaprotocol that has composed this module. 
+// 
+//################################################################
+
+int 
+Multiplexor::rna_finish_configuration(){
+    
+    if (debug) 
+      rna_click_chatter(FUNC_ENTRY,"[%s] rna_finish_configuration Entry \n",
+			instance_name());
+  
+    // Obtain the downstream element list and 
+    Vector<LinkState *> downstream; 
+    downstream =   list_downstream_elements(true, // downstream
+					    true, // layeragnostic
+					    false, // crosslayer
+					    true,// agnostic remote
+					    false // remote is unknown
+					    );
+    
+    for(int i = 0; i < downstream.size(); i++) {
+      LinkState *l = downstream[i];
+      initialize_link(l); 
+    };
+    
+    if (debug) 
+      rna_click_chatter(FUNC_EXIT,"[%s] rna_finish_configuration Exit \n",
+			instance_name());
+
+    return 0; 
+};
+
+//################################################################
+// 
+// There could be multiple strategies for selecting one path down the
+// multiplexor. The module currently supports only one strategy -
+// ALTERNATE_TWO that alternates between two outgoing paths. There
+// should be more ideally speaking.
+//
+//################################################################
+
+LinkState *
+Multiplexor::select_outgoing_link(Packet *p, 
+				  LinkState *incoming, 
+				  bool downstream, 
+				  bool layeragnostic,
+				  bool crosslayer,
+				  bool agnostic_remote,
+				  bool remote_unknown){
+
+  (void) p;
+  (void) incoming; 
+
+  LinkState *return_l = NULL;
+  
+  if (strategy != "ALTERNATE_TWO") {
+    if (debug) 
+      rna_click_chatter(FUNC_EXIT,
+			"[%s] Multiplexor::select_outgoing_link - Error! "
+			"Unknown strategy %s\n",
+			instance_name(), strategy.c_str());
+    return NULL;
+  };
+  
+  if (debug) 
+    rna_click_chatter(FUNC_ENTRY,
+		      "[%s] Multiplexor::select_outgoing_link - Entry \n",
+		      instance_name());
+  
+  // First obtain all possible outgoing links 
+  Vector<LinkState *> templist;   
+  // Identify all possible links...
+  for (int i = 0; i < all_links.size(); i++){
+    LinkState *l = all_links[i];
+
+    // Find a link in which I am an downstream node and 
+    // the link is outgoing...
+    if (l->is_outgoing()                         // ignore incoming links
+	&& ((!layeragnostic && (l->is_crosslayer() == crosslayer)) ||
+	      (layeragnostic ))
+	&& ((downstream && l->is_upstream()) || 
+	    (!downstream && l->is_downstream()))
+	&& ((agnostic_remote) || 
+	    (! agnostic_remote && (l->is_remote_unknown() == remote_unknown)))
+	) { 
+      templist.push_back(l);
+    };
+  };
+  
+  if (strategy == "ALTERNATE_TWO") { 
+
+    if (templist.size() >= 2) { 
+      if (first) {
+	click_chatter("[%s] Selecting alternative path 1 \n", 
+		      instance_name());
+	first = false; 
+	return_l = templist[0];
+      } else {
+	click_chatter("[%s] Selecting alternative path 2 \n", 
+		      instance_name()); 
+	first = true; 
+	return_l = templist[1];      
+      }
+    } else if (templist.size() == 1 ) { 
+      click_chatter("[%s] Selecting alternative path 1 (only available)\n", 
+		    instance_name()); 
+      first = true; 
+      return_l = templist[0]; 
+    } else { 
+      return_l = NULL; 
+    };
+    
+  };
+  
+  rna_click_chatter(FUNC_EXIT,
+		    "[%s] Multiplexor::select_outgoing_link - Exit \n",
+		    instance_name());
+  return return_l;
+};
+
+
+
+ELEMENT_REQUIRES(RNAElement)
+EXPORT_ELEMENT(Multiplexor)
+
+CLICK_ENDDECLS
Index: rna/elements/rna/modules_multiplexor.hh
diff -u /dev/null rna/elements/rna/modules_multiplexor.hh:1.1
--- /dev/null	Sun Jan 25 11:47:09 2009
+++ rna/elements/rna/modules_multiplexor.hh	Fri Jun 27 10:40:58 2008
@@ -0,0 +1,76 @@
+/* 
+
+################################################################
+#                                                              #
+# (c) University of Southern California                        #
+#                                                              #
+#  See LICENSE.RNA for the complete license                    #
+#                                                              #
+################################################################
+
+*/
+#ifndef CLICK_MULTIPLEXOR_HH
+#define CLICK_MULTIPLEXOR_HH
+
+#include "rnaelement.hh" 
+
+//
+//###############################################################
+//
+// Multiplexing module
+//
+//
+//             +---------------------------+
+//	      /           MUX               \                   #
+//           /                               \                  #
+//          +---------------------------------+
+//              ||         ||          ||
+//             +--+      +---+       +---+
+//             |  |      |   |       |   |
+//
+//
+// The muxing uses various strategies (currently supports only one
+// simple strategy) to select the outgoing link to the messages headed
+// downstream.
+//
+//###############################################################
+
+class Multiplexor : public RNAElement { 
+public:
+
+  // Constructor/destructor...
+  Multiplexor();
+  ~Multiplexor();
+
+  // Click management functions 
+  static void static_initialize() { RNAElement::static_initialize_default(); };
+  static void static_cleanup() { RNAElement::static_initialize_default(); };  
+  const char *class_name() const	{ return default_class_name(); }
+  const char *port_count() const	{ return "-/-"; } 
+  const char *processing() const	{ return PUSH; } 
+  
+  // Configuration 
+  int configure(Vector<String> &, ErrorHandler *);
+  int finish_configuration() { return RNAElement::finish_configuration(); }; 
+  virtual int rna_finish_configuration(); 
+  bool can_live_reconfigure() const     { return true; }
+
+  // Override only the function selecting the outgoing link. 
+  virtual LinkState *select_outgoing_link(Packet *p, 
+					LinkState *incoming, 
+					bool downstream = true, 
+					bool layeragnostic = false,
+					bool crosslayer = false,
+					bool agnostic_remote = true,
+					bool remote_unknown = false); 
+
+  
+ private:
+  bool first;      // used for the ALTERNATE_TWO strategy
+  String strategy; // The name of the strategy that must be used to mux the 
+                   // messages
+
+};
+
+CLICK_ENDDECLS
+#endif
Index: rna/elements/rna/modules_multitunnel.cc
diff -u /dev/null rna/elements/rna/modules_multitunnel.cc:1.1
--- /dev/null	Sun Jan 25 11:47:09 2009
+++ rna/elements/rna/modules_multitunnel.cc	Fri Jun 27 10:40:58 2008
@@ -0,0 +1,144 @@
+/* 
+
+################################################################
+#                                                              #
+# (c) University of Southern California                        #
+#                                                              #
+#  See LICENSE.RNA for the complete license                    #
+#                                                              #
+################################################################
+
+*/
+
+#include "modules_multitunnel.hh"
+
+Multitunnel::Multitunnel()
+{
+  set_type(MULTITUNNEL); 
+  first = true;
+}
+
+Multitunnel::~Multitunnel()
+{
+  // Do nothing... 
+}
+
+int
+Multitunnel::configure(Vector<String> &conf, ErrorHandler *errh)
+{
+
+  if (cp_va_parse(conf, this, errh,
+		  cpKeywords, 
+		  "NAME", cpString, "Name", &instance,
+		  "PROCESS", cpBool, "Enable processing configuration", 
+		  &exec_finish_configuration,
+		  cpEnd) < 0)
+    return -1; 
+  
+  click_chatter("Configuring Multitunnel... %s \n",  instance.c_str());
+
+  if (exec_finish_configuration) 
+    finish_configuration(); 
+  
+  return 0;
+}
+
+// This will effectively initialize all the links. 
+
+int 
+Multitunnel::rna_finish_configuration(){
+
+  rna_click_chatter(FUNC_ENTRY,"[%s] rna_finish_configuration Entry \n",
+		    instance_name());
+
+  Vector<LinkState *> downstream; 
+  downstream =   list_downstream_elements(true, // downstream
+					  true, // layeragnostic
+					  false, // crosslayer
+					  true,// agnostic remote
+					  false // remote is unknown
+					  );
+
+  for(int i = 0; i < downstream.size(); i++) {
+    LinkState *l = downstream[i];
+    initialize_link(l); 
+  };
+
+  rna_click_chatter(FUNC_EXIT,"[%s] rna_finish_configuration Exit \n",
+		    instance_name());
+
+  return 0; 
+};
+
+// The basic strategy is to select alternative link each time...
+LinkState *
+Multitunnel::select_outgoing_link(Packet *p, 
+				  LinkState *incoming, 
+				  bool downstream, 
+				  bool layeragnostic,
+				  bool crosslayer,
+				  bool agnostic_remote,
+				  bool remote_unknown){
+
+  (void) p;
+  (void) incoming; 
+
+  LinkState *return_l = NULL;
+
+  rna_click_chatter(FUNC_ENTRY,
+		    "[%s] Multitunnel::select_outgoing_link - Entry \n",
+		    instance_name());
+  
+  Vector<LinkState *> templist; 
+  
+  // Identify all possible links...
+  for (int i = 0; i < all_links.size(); i++){
+    LinkState *l = all_links[i];
+
+    // Find a link in which I am an downstream node and 
+    // the link is outgoing...
+    if (l->is_outgoing()                         // ignore incoming links
+	&& ((!layeragnostic && (l->is_crosslayer() == crosslayer)) ||
+	      (layeragnostic ))
+	&& ((downstream && l->is_upstream()) || 
+	    (!downstream && l->is_downstream()))
+	&& ((agnostic_remote) || 
+	    (! agnostic_remote && (l->is_remote_unknown() == remote_unknown)))
+	) { 
+      templist.push_back(l);
+    };
+  };
+  
+  if (templist.size() >= 2) { 
+    if (first) {
+      click_chatter("[%s] Selecting alternative path 1 \n", 
+		    instance_name());
+      first = false; 
+      return_l = templist[0];
+    } else {
+      click_chatter("[%s] Selecting alternative path 2 \n", 
+		    instance_name()); 
+      first = true; 
+      return_l = templist[1];      
+    }
+  } else if (templist.size() == 1 ) { 
+    click_chatter("[%s] Selecting alternative path 1 (only available)\n", 
+		  instance_name()); 
+    first = true; 
+    return_l = templist[0]; 
+  } else { 
+    return_l = NULL; 
+  };
+
+  rna_click_chatter(FUNC_EXIT,
+		    "[%s] Multitunnel::select_outgoing_link - Exit \n",
+		    instance_name());
+  return return_l;
+};
+
+
+
+ELEMENT_REQUIRES(RNAElement)
+EXPORT_ELEMENT(Multitunnel)
+
+CLICK_ENDDECLS
Index: rna/elements/rna/modules_multitunnel.hh
diff -u /dev/null rna/elements/rna/modules_multitunnel.hh:1.2
--- /dev/null	Sun Jan 25 11:47:09 2009
+++ rna/elements/rna/modules_multitunnel.hh	Mon Jun 30 12:43:20 2008
@@ -0,0 +1,58 @@
+/* 
+
+################################################################
+#                                                              #
+# (c) University of Southern California                        #
+#                                                              #
+#  See LICENSE.RNA for the complete license                    #
+#                                                              #
+################################################################
+
+*/
+#ifndef CLICK_MULTITUNNEL_HH
+#define CLICK_MULTITUNNEL_HH
+
+#include "rnaelement.hh" 
+
+//###################################################
+//
+// Minimal tunneling capability. Only a placeholder for now. Do not
+// use.
+//
+// ##################################################
+
+class Multitunnel : public RNAElement { 
+public:
+
+  Multitunnel();
+  ~Multitunnel();
+
+  static void static_initialize() { RNAElement::static_initialize_default(); };
+  static void static_cleanup() { RNAElement::static_initialize_default(); };
+  
+  const char *class_name() const	{ return default_class_name(); }
+  const char *port_count() const	{ return "-/-"; } 
+  const char *processing() const	{ return PUSH; } 
+  
+  int configure(Vector<String> &, ErrorHandler *);
+  int finish_configuration() { return RNAElement::finish_configuration(); }; 
+  virtual int rna_finish_configuration(); 
+  bool can_live_reconfigure() const     { return true; }
+
+
+  virtual LinkState *select_outgoing_link(Packet *p, 
+					LinkState *incoming, 
+					bool downstream = true, 
+					bool layeragnostic = false,
+					bool crosslayer = false,
+					bool agnostic_remote = true,
+					bool remote_unknown = false); 
+
+  
+ private:
+  bool first;
+
+};
+
+CLICK_ENDDECLS
+#endif
Index: rna/elements/rna/modules_pktsrc.cc
diff -u /dev/null rna/elements/rna/modules_pktsrc.cc:1.3
--- /dev/null	Sun Jan 25 11:47:09 2009
+++ rna/elements/rna/modules_pktsrc.cc	Fri Dec 26 16:57:00 2008
@@ -0,0 +1,114 @@
+/* 
+
+################################################################
+#                                                              #
+# (c) University of Southern California                        #
+#                                                              #
+#  See LICENSE.RNA for the complete license                    #
+#                                                              #
+################################################################
+
+*/
+
+#include "modules_pktsrc.hh"
+
+//#############################################################
+//
+// Simple wrapper around the packet source. 
+//
+//#############################################################
+
+RNAPktSrc::RNAPktSrc() 
+{
+  set_type(PKTSRC); 
+
+  // This is packet source. Dont check for connection state.
+  set_skip_conn_check(true); 
+}
+
+RNAPktSrc::~RNAPktSrc() 
+{
+  // Do nothing...
+}
+
+//
+// This function assumes a unidirectional link 
+//
+//                 Packet Generator
+//                      |
+//                      V
+//                  RNAPktSrc
+//                      |
+//                      V
+//              Some other modules
+//
+
+int 
+RNAPktSrc::finish_configuration() {
+
+  if (debug) 
+    rna_click_chatter(FUNC_ENTRY, 
+		      "[%s] RNAPktSrc finish_configuration \n", 
+		      instance_name());  
+  
+  // Add the links to begin with...
+  Vector<struct linkspec *> links; 
+  add_default_unidirectional_links(&links, true);  // cross layer...
+  process_linkspecs(links); 
+  print_links();
+
+  return 0; 
+};
+
+
+//
+// Add the data header and send the message out...
+//
+void
+RNAPktSrc::push_data(int port, Packet *p){
+
+  p->push(3); 
+  unsigned char *data = (unsigned char *)p->data(); 
+  *data = MESSAGE_DATA; 
+  *(data + 1) = MESSAGE_DATA_NORMAL; 
+  *(data + 2) = 0; 
+  
+  if (1) 
+    RNAElement::print_packet("push_data", p, false);
+  
+  RNAElement::push_data(port, p);   
+
+};
+
+// 
+// No module-specific configuration parameters. Use buffer with
+// appropriate parameters to generate copies and management messages.
+// 
+int
+RNAPktSrc::configure(Vector<String> &conf, ErrorHandler *errh)
+{
+  
+  RNAElement::configure(conf, errh); 
+
+  if (cp_va_parse(conf, this, errh,
+		  cpKeywords, 
+		  cpEnd) < 0)
+    return -1; 
+  
+  if (debug) 
+    rna_click_chatter(FUNC_DEFAULT, 
+		      "[%s] Configuring RNAPktSrc. \n",  
+		      instance_name());
+  
+  if (exec_finish_configuration) 
+    finish_configuration(); 
+
+  return 0;
+}
+
+
+ELEMENT_REQUIRES(RNAElement)
+EXPORT_ELEMENT(RNAPktSrc)
+ELEMENT_MT_SAFE(RNAPktSrc)
+
+CLICK_ENDDECLS
Index: rna/elements/rna/modules_pktsrc.hh
diff -u /dev/null rna/elements/rna/modules_pktsrc.hh:1.2
--- /dev/null	Sun Jan 25 11:47:09 2009
+++ rna/elements/rna/modules_pktsrc.hh	Mon Jun 30 12:43:20 2008
@@ -0,0 +1,52 @@
+/* 
+
+################################################################
+#                                                              #
+# (c) University of Southern California                        #
+#                                                              #
+#  See LICENSE.RNA for the complete license                    #
+#                                                              #
+################################################################
+
+*/
+#ifndef CLICK_RNAPKTSRC_HH
+#define CLICK_RNAPKTSRC_HH
+
+#include "rnaelement.hh" 
+
+//#############################################################
+//
+// Simple wrapper around the Infinite Source packet generator in
+// Click. This module introduces a data message header into the packet
+// and sends it out. Derives basic control interface from the base
+// class RNAElement. 
+//
+//#############################################################
+class RNAPktSrc : public RNAElement { 
+public:
+
+  RNAPktSrc();
+  ~RNAPktSrc();
+
+  // Click house keep functions...
+  static void static_initialize() { RNAElement::static_initialize_default(); };
+  static void static_cleanup() { RNAElement::static_initialize_default(); };  
+  const char *class_name() const  { return  default_class_name(); };
+  const char *port_count() const	{ return "-/-"; } 
+  const char *processing() const	{ return PUSH; } 
+  
+  // Configuration...
+  int configure(Vector<String> &, ErrorHandler *);
+  int finish_configuration(); // Complete the configuration step...
+  bool can_live_reconfigure() const     { return true; }
+  int configure_phase() { return CONFIGURE_PHASE_LAST; }; 
+
+  // Introduce a data header and send it out. 
+  void push_data(int port, Packet *p); 
+  
+ private:
+
+};
+
+CLICK_ENDDECLS
+#endif
Index: rna/elements/rna/modules_reorderbuffer.cc
diff -u /dev/null rna/elements/rna/modules_reorderbuffer.cc:1.3
--- /dev/null	Sun Jan 25 11:47:09 2009
+++ rna/elements/rna/modules_reorderbuffer.cc	Mon Jun 30 12:43:20 2008
@@ -0,0 +1,301 @@
+/* 
+
+################################################################
+#                                                              #
+# (c) University of Southern California                        #
+#                                                              #
+#  See LICENSE.RNA for the complete license                    #
+#                                                              #
+################################################################
+
+*/
+
+#include "modules_reorderbuffer.hh"
+
+
+//############################################################
+// 
+// This code inserts a sequence number in the packet header and orders
+// messages according to the sequence number. This module does not do
+// retransmission.
+//
+//############################################################
+
+//
+//===================================================================
+// Buffering component of the reorder buffer. 
+//
+ReorderBuffer::BufferedPacket::BufferedPacket(LinkState *incoming, 
+					      int seq, 
+					      Packet *p) {
+  assert(p);
+  _p = p;
+  _incoming_link = incoming; 
+  _seq = seq; 
+};
+
+void
+ReorderBuffer::BufferedPacket::print() { 
+  click_chatter("[BUFFER] seq = %u\n", _seq); 
+  return; 
+};
+
+bool 
+ReorderBuffer::BufferedPacket::match(int seq) { 
+  return (_seq == seq); 
+}; 
+
+//
+//===================================================================
+//
+
+ReorderBuffer::ReorderBuffer() : 
+  _rnabuffer_timer(static_rnabuffer_timer_hook, this)
+{
+  // Set the seed...
+  srand(0x2322311);
+  set_type(REORDERBUFFER);
+  _next_seq = 0; 
+  _out_seq = 0; 
+}
+
+ReorderBuffer::~ReorderBuffer()
+{
+  // Do nothing... 
+}
+
+unsigned long
+ReorderBuffer::diff_in_ms(timeval t1, timeval t2)
+{
+  unsigned long s, us, ms;
+
+//   DEBUG_CHATTER ("diff_in_ms: t1 %ld %ld; t2 %ld %ld\n",
+//               t1.tv_sec, t1.tv_usec,
+//               t2.tv_sec, t2.tv_usec);
+
+  while (t1.tv_usec < t2.tv_usec) {
+    t1.tv_usec += 1000000;
+    t1.tv_sec -= 1;
+  }
+
+  assert(t1.tv_sec >= t2.tv_sec);
+
+  s = t1.tv_sec - t2.tv_sec;
+  assert(s < ((unsigned long)(1<<31))/1000);
+
+  us = t1.tv_usec - t2.tv_usec;
+  ms = s * 1000L + us / 1000L;
+
+//   DEBUG_CHATTER ("diff_in_ms: difference is %ld %ld -> %ld\n",
+//               s,
+//               us,
+//               ms);
+
+  return ms;
+}
+
+int 
+ReorderBuffer::rna_finish_configuration() {
+
+
+  return 0;
+};
+
+
+int 
+ReorderBuffer::initialize(ErrorHandler *) {
+  
+  click_chatter("[ReorderBuffer::initialize] \n");
+  _rnabuffer_timer.initialize(this);
+  _rnabuffer_timer.schedule_after_msec(RNAREORDERBUFFER_TIMER_INTERVAL);
+
+  return 0; 
+};
+
+
+void
+ReorderBuffer::static_rnabuffer_timer_hook(Timer *, void *v)
+{
+  //click_chatter("[ReorderBuffer::static_rnabuffer_timer_hook] \n");
+  ReorderBuffer *buf = (ReorderBuffer *)v;
+  buf->rnabuffer_timer_hook(); 
+}
+
+void
+ReorderBuffer::rnabuffer_timer_hook()
+{
+  
+  deliver_ready_messages(); 
+  _rnabuffer_timer.schedule_after_msec(RNAREORDERBUFFER_TIMER_INTERVAL);
+
+};
+
+void
+ReorderBuffer::deliver_ready_messages(){
+  
+  bool found = false; 
+  int size = rnabuffer.size(); 
+  
+  if (size > 0) 
+    click_chatter("[%s] ReorderBuffer::deliver_ready_messages() \n", 
+		  instance_name());
+  
+  // Look through the list and clean it up. 
+  do { 
+    
+    found = false; 
+    Vector<BufferedPacket *> remaining; 
+    
+    // Go through all the stored messages and see if there is one
+    // with the next seq number...
+    for (int i = 0; i < rnabuffer.size(); i++){ 
+      
+      BufferedPacket *buf = rnabuffer[i];
+      
+      // Well if the packet with the next sequence number has been
+      // found, then skip everything...
+      if ( found || ! buf->match(_next_seq)){
+	remaining.push_back(buf); 
+	continue; 
+      };
+      
+      // Found the match...
+      found = true; 
+      
+      // Extract
+      LinkState *incoming_link = buf->_incoming_link;
+      Packet *pkt = buf->_p;
+      int port = incoming_link->local_port; 
+      
+      // Forward the packet...
+      RNAElement::push_data(port, pkt); 
+      
+    }; // for(....)
+    
+    if (found) 
+      _next_seq++; 
+    
+    rnabuffer.swap(remaining); 
+
+    //
+    // if (found) 
+    // rna_click_chatter(FUNC_DEFAULT,"[%s] Found = %d next_seq = %d (remaining in buffer = %d)\n", 
+    //		instance_name(), found, _next_seq, rnabuffer.size()); 
+    
+  } while(found); 
+
+}; // deliver_ready_messages..
+
+
+//
+// Buffer only messages coming from downstream. Check their sequence
+// numbers and send packets in order. Introduce a sequence number in
+// messages headed downstream. 
+//
+void 
+ReorderBuffer::push_data(int port, Packet *p){
+  
+  click_chatter("[%s] ReorderBuffer::push_data \n", instance_name());
+  
+  LinkState *incoming_link = lookup_link(port); 
+  if (!incoming_link) {
+   rna_click_chatter(FUNC_DEFAULT,
+		      "[%s] ReorderBuffer::push_data Dropping packet...incoming link\n", 
+		      instance_name()); 
+    p->kill();
+    return;
+  };   
+
+
+  if (incoming_link->is_downstream()) { 
+
+    // Message is coming from upstream 
+    process_incoming_from_upstream(&p, incoming_link); 
+    
+    // Introduce the header....
+    p->push(3 + 4); 
+    char *data = (char *)p->data(); 
+    *(data + 0) = MESSAGE_DATA; 
+    *(data + 1) = MESSAGE_DATA_NORMAL; 
+    *(data + 2) = 0; 
+    
+    click_chatter("[%s] ReorderBuffer::push_data Copying out_seq = %d \n", 
+		  instance_name(), _out_seq);
+
+    // Copy the sequence number...This should be revised...
+    memcpy((data + 3), (char *)&_out_seq, 4); 
+    _out_seq++;
+    
+    if (debug) 
+      RNAElement::print_packet(instance, p, false);
+    
+    RNAElement::push_data(port, p);     
+
+  } else { 
+    
+    // Remove the header...
+    char *data = (char *)p->data(); 
+    
+    // I cant handle anything other than minimal capabilities...
+    if ( *(data + 1) != MESSAGE_DATA_NORMAL){
+      rna_click_chatter(FUNC_DEFAULT,
+			"[%s] ReorderElement::push_data "
+			"Dropping packet...message type\n", 
+			instance_name()); 
+      p->kill();
+      return;
+    };         
+    
+    // Remove the rest of the header...
+    p->pull(3);
+    
+    // Message coming from downstream
+    process_incoming_from_downstream(&p, incoming_link); 
+    
+    // Extract the sequence number...
+    data = (char *)p->data(); 
+    int seqnum = 0; 
+    memcpy(&seqnum, data, 4); 
+    
+    // remove the seq number as well. 
+    p->pull(4); 
+
+    rna_click_chatter(FUNC_DEFAULT,"[%s] Storing packet - seqnum = %d \n", 
+		      instance_name(), seqnum ); 
+    
+    // Store this packet
+    BufferedPacket *b = new BufferedPacket(incoming_link, seqnum, p);
+    rnabuffer.push_back(b);
+    
+  }; // else...
+
+
+  return; 
+    
+};
+
+
+//
+// Configure. No module-specific parameters to process, yet.
+//
+int
+ReorderBuffer::configure(Vector<String> &conf, ErrorHandler *errh)
+{
+  
+  RNAElement::configure(conf, errh); 
+  
+  if (debug) 
+    click_chatter("Configuring ReorderBuffer... %s \n", class_name());
+  
+  if (exec_finish_configuration) 
+    finish_configuration(); 
+
+  return 0;
+}
+
+
+ELEMENT_REQUIRES(RNAElement)
+EXPORT_ELEMENT(ReorderBuffer)
+ELEMENT_MT_SAFE(ReorderBuffer)
+
+CLICK_ENDDECLS
Index: rna/elements/rna/modules_reorderbuffer.hh
diff -u /dev/null rna/elements/rna/modules_reorderbuffer.hh:1.3
--- /dev/null	Sun Jan 25 11:47:09 2009
+++ rna/elements/rna/modules_reorderbuffer.hh	Mon Jun 30 12:43:20 2008
@@ -0,0 +1,92 @@
+/* 
+
+################################################################
+#                                                              #
+# (c) University of Southern California                        #
+#                                                              #
+#  See LICENSE.RNA for the complete license                    #
+#                                                              #
+################################################################
+
+*/
+#ifndef CLICK_REORDERBUFFER_HH
+#define CLICK_REORDERBUFFER_HH
+
+//##############################################################
+//
+// Reorder buffer is a modification of the default buffer that uses
+// sequence numbers to order messages. A sequence number is
+// incorporated into outgoing messages before being sent out. The
+// incoming messages are buffered until the message with the right
+// sequence number shows up. Then the packets are delivered upstream
+// in order. This is a simple buffer with no capability to retransmit.
+//
+//##############################################################
+
+#include "rnaelement.hh" 
+
+#define RNAREORDERBUFFER_TIMER_INTERVAL 1000           // Every second 
+#define RNAREORDERBUFFER_MAX_DELAY 1000               // Delay
+
+class ReorderBuffer : public RNAElement { 
+public:
+
+  // One object for each packet coming in from downstream. 
+  class BufferedPacket
+  {
+  public:
+    Packet *_p;
+    LinkState *_incoming_link; 
+    int _seq; 
+    
+    // Initialize the object 
+    BufferedPacket(LinkState *incoming, int seq, Packet *p);
+    
+    // Check if the packet has a specific sequence number
+    bool match(int seq);
+    
+    // Debug message
+    void print();
+  };
+
+  // Constructor and cleanup 
+  ReorderBuffer();
+  ~ReorderBuffer();
+  
+  // Click housekeeping functions..
+  int initialize(ErrorHandler *); 
+  static void static_initialize() { RNAElement::static_initialize_default(); };
+  static void static_cleanup() { RNAElement::static_initialize_default(); };
+  const char *class_name() const { return default_class_name(); }
+  const char *port_count() const	{ return "-/-"; } 
+  const char *processing() const	{ return PUSH; } 
+  
+  // Configuration..
+  int configure(Vector<String> &, ErrorHandler *);
+  int rna_finish_configuration(); // Complete the configuration step...
+  bool can_live_reconfigure() const     { return true; }
+  
+  // Data path. 
+  void push_data(int i, Packet *p); 
+  
+
+  // Timer management 
+  static unsigned long diff_in_ms(timeval t1, timeval t2); 
+  static void static_rnabuffer_timer_hook(Timer *, void *);
+  void rnabuffer_timer_hook();
+  
+  // Go through the buffer to see if there are messages that are ready
+  // to be delivered to the upstream...
+  void deliver_ready_messages(); 
+
+ private:
+
+  int _next_seq; 
+  int _out_seq; 
+  Vector<BufferedPacket *> rnabuffer;
+  Timer _rnabuffer_timer;
+
+};
+
+CLICK_ENDDECLS
+#endif
Index: rna/elements/rna/modules_rexmit.cc
diff -u /dev/null rna/elements/rna/modules_rexmit.cc:1.2
--- /dev/null	Sun Jan 25 11:47:09 2009
+++ rna/elements/rna/modules_rexmit.cc	Fri Jan  2 14:06:58 2009
@@ -0,0 +1,562 @@
+/* 
+
+################################################################
+#                                                              #
+# (c) University of Southern California                        #
+#                                                              #
+#  See LICENSE.RNA for the complete license                    #
+#                                                              #
+################################################################
+
+*/
+
+#include "modules_rexmit.hh"
+
+
+//############################################################
+// 
+// This code inserts a sequence number in the packet header and orders
+// messages according to the sequence number. When the messages are
+// received out of order, they are cached and delivered in order to
+// the application (the next layer). 
+//
+// 
+//############################################################
+
+//===================================================================
+// Buffering component of the rexmit buffer. 
+//===================================================================
+               
+//              send_queue             recv_queue
+// ack_recv -->                                 <----- ack_sent 
+//              +-----+                  +-----+
+//              |     |                  |     |
+//              +-----+                  +-----+
+//                 |                        ^
+//                 V                        |
+//              +-----+                  +-----+
+//              |     |                  |     |
+//              +-----+                  +-----+
+//                 |                        ^
+//                 V                        |
+//              +-----+                  +-----+
+//              |     |                  |     |
+//              +-----+                  +-----+
+// last_seq ---> 
+
+// Packets with seq number < ack_recv are dropped (they have been
+// successfully delivered).
+//
+// ack_sent is incremented when the packet with seq number (ack_sent +
+// 1) is received and delived to the application. An acknowledgement
+// is sent with the new ack_sent value (which is inturn used to update
+// ack_recv)
+//
+
+//===================================================================
+// One buffer containing one packet
+//===================================================================
+Rexmit::BufferedPacket::BufferedPacket(LinkState *incoming, int seq, Packet *p) {
+  assert(p);
+  _p = p;
+  _incoming_link = incoming; 
+  _seq = seq; 
+  _num_xmits = 0; 
+};
+
+Rexmit::BufferedPacket::~BufferedPacket(){    
+  click_chatter("[Rexmit::BufferedPacket::~BufferedPacket] Deleting seq = %u\n", _seq); 
+  if (_p) 
+    _p->kill();   
+};
+
+void
+Rexmit::BufferedPacket::print() { 
+  click_chatter("[BUFFER] seq = %u\n", _seq); 
+  return; 
+};
+
+bool 
+Rexmit::BufferedPacket::match(int seq) { 
+  return (_seq == seq); 
+}; 
+
+int
+Rexmit::BufferedPacket::seq() { 
+  return _seq; 
+}; 
+
+Packet *
+Rexmit::BufferedPacket::pkt() { 
+  return _p; 
+}; 
+
+int 
+Rexmit::BufferedPacket::increment_xmits() { 
+  return ++_num_xmits;
+};
+
+int 
+Rexmit::BufferedPacket::xmits() { 
+  return _num_xmits;
+};
+
+
+//===================================================================
+//
+//
+//
+//===================================================================
+
+Rexmit::Rexmit() :
+  _rexmit_timer(static_rexmit_timer_hook, this)
+{
+  // Set the seed...
+  srand(0x2322311);
+  set_type(REXMIT);
+  _last_seq = 0; 
+  _ack_recv = 0;
+  _ack_sent = 0; 
+}
+
+Rexmit::~Rexmit()
+{
+  // kill packets here but this is never reached in our usage
+  // scenario.
+  
+    for (int i = 0; i < _recv_queue.size(); i++){ 
+    BufferedPacket *buf = _recv_queue[i];
+    delete buf;
+  };
+  for (int i = 0; i < _send_queue.size(); i++){ 
+    BufferedPacket *buf = _send_queue[i];
+    delete buf; 
+  };
+}
+
+int 
+Rexmit::rna_finish_configuration() {
+  return 0;
+};
+
+
+int 
+Rexmit::initialize(ErrorHandler *) {  
+  _rexmit_timer.initialize(this);
+  _rexmit_timer.schedule_after_msec(RNAREXMIT_TIMER_INTERVAL);
+  return 0; 
+};
+
+
+// Called every second or so. but can be reduced 
+void
+Rexmit::static_rexmit_timer_hook(Timer *, void *v)
+{
+  Rexmit *r = (Rexmit *)v;
+  r->rexmit_timer_hook(); 
+}
+
+void
+Rexmit::rexmit_timer_hook()
+{
+  
+  deliver_ready_messages(); 
+  _rexmit_timer.schedule_after_msec(RNAREXMIT_TIMER_INTERVAL);
+
+};
+
+//
+// Debug function 
+//
+
+void 
+Rexmit::print_queues() {
+
+  click_chatter("[%s] Rexmit::print_queues - recv[%d] send[%d] \n", 
+		instance_name(), _recv_queue.size(), _send_queue.size());
+  click_chatter("[%s] Rexmit::print_queues _last_seq = %d, "
+		"_ack_recv = %d, _ack_sent = %d \n", 
+		instance_name(), _last_seq, _ack_recv, _ack_sent);
+
+  for (int i = 0; i < _recv_queue.size(); i++){ 
+    BufferedPacket *buf = _recv_queue[i];
+    click_chatter("[%s] Rexmit::print_queues: Recv[%d] = seq %d\n", 
+		  instance_name(), i, buf->seq());
+  };
+  for (int i = 0; i < _send_queue.size(); i++){ 
+    BufferedPacket *buf = _send_queue[i];
+    click_chatter("[%s] Rexmit::print_queues: Send[%d] = seq %d\n", 
+		  instance_name(), i, buf->seq());
+  };
+
+};
+
+//
+// Look through the messages received and see if this message is a
+// duplicate.
+//
+bool
+Rexmit::should_be_saved( int seq_num){
+  
+  // Invalid sequence message 
+  if (seq_num <= 0) 
+    return false; 
+  
+  // A message that has already been delivered to the app
+  if (seq_num < _ack_sent) 
+    return false; 
+
+  // A message that has already been queued...
+  for (int i = 0; i < _recv_queue.size(); i++){ 
+    BufferedPacket *buf = _recv_queue[i];
+    if (buf->seq() == seq_num)
+      return false; 
+  };
+  
+  return true; 
+};
+
+
+//
+// Process all the messages in the send queue and receive queue. 
+//
+
+void
+Rexmit::deliver_ready_messages(){
+  
+  
+  // First drop all the messages in the send queue that have been
+  // acknowledged.....
+  { 
+    
+    Vector<BufferedPacket *> remaining;     
+    for (int i = 0; i < _send_queue.size(); i++){ 
+      
+      BufferedPacket *buf = _send_queue[i];      
+      // Skip if this is null for some reason...
+      if (!buf) 
+	continue; 
+
+      // Well if the packet with the next sequence is greater than 
+      // the last acknowledged sequence number, then transmit it. 
+      int seq = buf->seq(); 
+      if (seq > _ack_recv) { 
+	remaining.push_back(buf);       
+      }; // for(....)
+    };
+    
+    // Keep only unacknowledged messages and send these 
+    _send_queue.swap(remaining); 
+
+  };
+  
+  print_queues();  
+  
+  // Deliver messages and acknowledge them...
+  { 
+    
+    if (_recv_queue.size() > 0) 
+      click_chatter("[%s] Rexmit::deliver_ready_messages processing "
+		    "_recv_queue\n",
+		    instance_name());
+
+    Vector<BufferedPacket *> remaining, to_deliver;         
+    bool app_recv_seq_incremented = false; 
+    
+    do { 
+      
+      app_recv_seq_incremented = false; 
+      remaining.clear(); 
+      to_deliver.clear(); 
+      
+      for (int i = 0; i < _recv_queue.size(); i++){ 
+	
+	BufferedPacket *buf = _recv_queue[i]; 
+	
+	// Well if the packet with the next sequence is greater than 
+	// the last acknowledged sequence number, then transmit it. 
+	int seq = buf->seq(); 
+	if (seq == _ack_sent + 1) { 
+	  _ack_sent++;
+	  app_recv_seq_incremented = true;
+	  break; 
+	};
+	
+	if (seq <= _ack_sent)
+	  to_deliver.push_back(buf); 
+	else 
+	  remaining.push_back(buf); 
+	
+      }; // for all the _recv_queue entries...
+      
+    } while(app_recv_seq_incremented);
+    
+    // Keep only unacknowledged messages and send these 
+    _recv_queue.swap(remaining); 
+    
+    // If any new message have to be delivered, then deliver them and
+    // send an ack...
+    if (to_deliver.size() > 0){ 
+      
+      // Not enough information to generate an ack...
+      BufferedPacket *buf = to_deliver[0]; 
+      LinkState *ack_incoming_link = buf->_incoming_link; 
+      Packet *ack_packet = buf->pkt()->clone();
+      
+      // Deliver the messages to the app...
+      for (int i = 0; i < to_deliver.size(); i++){ 
+	
+	buf = to_deliver[i]; 
+	
+	LinkState *incoming_link = buf->_incoming_link;
+	Packet *pkt = buf->pkt()->clone();
+	int port = incoming_link->local_port; 
+	
+	// Remove the rexmit header...
+	pkt->pull(7); 
+	
+	if (debug){
+	  RNAElement::print_packet("Rexmit::deliver_ready_messages", pkt, false);
+	};
+
+	// deliver 
+	RNAElement::push_data(port, pkt); 
+      };
+      
+      click_chatter("[%s] Rexmit::deliver_ready_messages processing "
+		  "sending an ack\n",
+		    instance_name());
+     
+      // Send one ack for all the messages delivered to the app...
+      send_ack(ack_incoming_link, ack_packet); 
+ 
+    };
+
+  };
+    
+  // Send the outstanding packets to the remote end...
+  {
+    if (_send_queue.size() > 0) 
+      click_chatter("[%s] Rexmit::deliver_ready_messages processing "
+		    "_send_queue\n",
+		    instance_name());
+    
+    for (int i = 0; i < _send_queue.size(); i++){ 
+      
+      BufferedPacket *buf = _send_queue[i];
+      LinkState *incoming_link = buf->_incoming_link;
+      Packet *pkt = buf->pkt()->clone();
+      int seqnum = buf->seq(); 
+      int port = incoming_link->local_port; 
+      int num_rexmits = buf->increment_xmits() - 1; 
+      
+      if (num_rexmits > 0) 
+	click_chatter("[%s] Rexmit::deliver_ready_messages: "
+		      "SEND msg (seq # %d, rexmits %d)\n",
+		      instance_name(), seqnum, num_rexmits);  
+      
+      // Forward the packet...
+      RNAElement::push_data(port, pkt); 
+      
+    }
+  };
+
+  
+}; // deliver_ready_messages..
+
+//
+// Send acknowledgment to the remote end with the latest sequence
+// number. Use the specified packet and link to send the same. Problem
+// is if the packet or the link is not specified, then it may be hard
+// to figure out the outgoing link for a given message (when there are
+// multiple of them).
+//
+void 
+Rexmit::send_ack(LinkState *incoming_link, Packet *p){
+  
+  const char *func = __FUNCTION__;
+
+  if (!incoming_link || !p || p->length() < 7) 
+    return; 
+
+  click_chatter("[%s] Rexmit::send_ack - sending an ack", 
+		instance_name());
+
+  // Update the header of the packet with the ack information.
+  char *data = (char *)p->data(); 
+  *(data + 0) = MESSAGE_DATA; 
+  *(data + 1) = MESSAGE_DATA_REXMIT; 
+  *(data + 2) = MESSAGE_DATA_REXMIT_ACK; 
+  
+  // Copy the sequence number...This should be revised...
+  memcpy((data + 3), (char *)&_ack_sent, 4); 
+  
+  // Figure out where to send the message out. If the incoming message
+  // has come on a intra-layer link, then 
+  bool crosslayer = incoming_link->is_crosslayer(); 
+  LinkState *l = NULL; 
+      
+  l = select_outgoing_link(p, NULL, 
+			   true,       /* headed downstream */ 
+			   false,      /* not layer agnostic */
+			   crosslayer, /* cross layer */ 
+			   true,       /* agnostic remote endpoint */
+			               /* of the cross-layer link */
+	 		   false       /* doesnt matter */
+			   );
+  if (! push_data_to_link(p, l, func)){
+    p->kill(); 
+  }; 
+  
+  return; 
+};
+
+
+//
+// Buffer only messages coming from downstream. Check their sequence
+// numbers and send packets in order. Introduce a sequence number in
+// messages headed downstream. 
+//
+void 
+Rexmit::push_data(int port, Packet *p){
+  
+  click_chatter("[%s] Rexmit::push_data \n", instance_name());
+  
+  LinkState *incoming_link = lookup_link(port); 
+  if (!incoming_link) {
+   rna_click_chatter(FUNC_DEFAULT,
+		      "[%s] Rexmit::push_data Dropping packet...incoming link\n", 
+		      instance_name()); 
+    p->kill();
+    return;
+  };   
+
+
+  if (incoming_link->is_downstream()) { 
+
+    // Message is coming from upstream 
+    
+    // Do any preprocessing. This is usually a nop 
+    process_incoming_from_upstream(&p, incoming_link); 
+    
+    // Introduce the header....
+    p = p->push(7); 
+    char *data = (char *)p->data(); 
+    *(data + 0) = MESSAGE_DATA; 
+    *(data + 1) = MESSAGE_DATA_REXMIT; 
+    *(data + 2) = MESSAGE_DATA_REXMIT_SEND; 
+    
+    _last_seq++;
+
+    // Copy the sequence number...This should be revised...
+    memcpy((data + 3), (char *)&_last_seq, 4); 
+
+    // Store this packet; Send it in the timer callback...
+    BufferedPacket *b = new BufferedPacket(incoming_link, _last_seq, p);
+    _send_queue.push_back(b);
+
+    RNAElement::print_packet("Rexmit::push_data", p, false);
+    click_chatter("[%s] Rexmit::push_data Added to _send_queue last_seq = %d \n", 
+		  instance_name(), _last_seq);
+
+    
+  } else { 
+    
+    // Message is coming from downstream, i.e., the remote end 
+    // Remove the header...
+    char *data = (char *)p->data(); 
+    
+    // I cant handle anything other than minimal capabilities...
+    if (( *(data + 1) != MESSAGE_DATA_REXMIT) || 
+	(( *(data + 2) != MESSAGE_DATA_REXMIT_SEND) && 
+	 ( *(data + 2) != MESSAGE_DATA_REXMIT_ACK))){ 
+      rna_click_chatter(FUNC_DEFAULT,
+			"[%s] Rexmit::push_data "
+			"Dropping packet...wrong message type (%d)\n", 
+			instance_name(), (int) *(data + 1));
+      p->kill();
+      return;
+    };         
+    
+    // Message coming from downstream
+    process_incoming_from_downstream(&p, incoming_link); 
+    
+    // Have received a message from the peer...
+    if ( *(data + 2) == MESSAGE_DATA_REXMIT_SEND){ 
+      
+      // Extract the sequence number and store it if it is new...
+      int seqnum = 0; 
+      memcpy(&seqnum, data + 3, 4);       
+      bool tosave = should_be_saved(seqnum);
+
+      rna_click_chatter(FUNC_DEFAULT,"[%s] Received packet "
+			"(seqnum = %d) %s to _recv_queue \n", 
+			instance_name(), seqnum, 
+			(tosave? "Adding" : "Not adding")
+			);
+
+      if (tosave) { 
+	// Store this packet; Send it in the timer callback...
+	BufferedPacket *b = new BufferedPacket(incoming_link, seqnum, p);
+	_recv_queue.push_back(b); 
+      }; 
+      
+      // Process messages in the receive queue...
+      deliver_ready_messages() ;
+      
+    }; // Rexmit send an ack back....
+    
+
+    if ( *(data + 2) == MESSAGE_DATA_REXMIT_ACK){ 
+      
+      // Received the acknowlegdement for a packet. So drop the messages 
+      int seqnum = 0; 
+      memcpy(&seqnum, data + 3, 4); 
+      
+      rna_click_chatter(FUNC_DEFAULT,"[%s] Received ack packet - "
+			"seqnum = %d (_ack_recv = %d) \n", 
+			instance_name(), seqnum, _ack_recv );      
+      
+      // Store it if it is higher than what we have currently...
+      if (seqnum > _ack_recv) 
+	_ack_recv = seqnum; 
+      
+      p->kill(); 
+      
+      // Drop all the messages...
+      deliver_ready_messages();
+
+    };
+
+  }; // packet coming from downstream...
+
+
+  return; 
+    
+};
+
+
+//
+// Configure. No module-specific parameters to process, yet.
+//
+int
+Rexmit::configure(Vector<String> &conf, ErrorHandler *errh)
+{
+  
+  RNAElement::configure(conf, errh); 
+  
+  if (debug) 
+    click_chatter("Configuring Rexmit... %s \n", class_name());
+  
+  if (exec_finish_configuration) 
+    finish_configuration(); 
+
+  return 0;
+}
+
+
+ELEMENT_REQUIRES(RNAElement)
+EXPORT_ELEMENT(Rexmit)
+ELEMENT_MT_SAFE(Rexmit)
+
+CLICK_ENDDECLS
Index: rna/elements/rna/modules_rexmit.hh
diff -u /dev/null rna/elements/rna/modules_rexmit.hh:1.2
--- /dev/null	Sun Jan 25 11:47:09 2009
+++ rna/elements/rna/modules_rexmit.hh	Fri Jan  2 14:06:58 2009
@@ -0,0 +1,108 @@
+/* 
+
+################################################################
+#                                                              #
+# (c) University of Southern California                        #
+#                                                              #
+#  See LICENSE.RNA for the complete license                    #
+#                                                              #
+################################################################
+
+*/
+#ifndef CLICK_REXMIT_HH
+#define CLICK_REXMIT_HH
+
+//##############################################################
+//
+// Reorder buffer is a modification of the default buffer that uses
+// sequence numbers to order messages. A sequence number is
+// incorporated into outgoing messages before being sent out. The
+// incoming messages are buffered until the message with the right
+// sequence number shows up. Then the packets are delivered upstream
+// in order. This is a simple buffer with no capability to retransmit.
+//
+//##############################################################
+
+#include "rnaelement.hh" 
+
+#define RNAREXMIT_TIMER_INTERVAL 4000           // Every four seconds
+
+class Rexmit : public RNAElement { 
+public:
+
+  // One object for each packet coming in from upstream
+  class BufferedPacket
+  {
+  public:
+    Packet *_p;
+    LinkState *_incoming_link; 
+    int _seq; 
+    int _num_xmits; 
+
+    // Initialize the object 
+    BufferedPacket(LinkState *incoming, int seq, Packet *p);
+    ~BufferedPacket(); 
+    
+    // Check if the packet has a specific sequence number
+    bool match(int seq);
+    int seq(); 
+    Packet *pkt();
+    // Debug message
+    void print();
+    
+    int xmits(); 
+    int increment_xmits(); 
+    
+  };
+
+  // Constructor and cleanup 
+  Rexmit();
+  ~Rexmit();
+  
+  // Click housekeeping functions..
+  int initialize(ErrorHandler *); 
+  static void static_initialize() { RNAElement::static_initialize_default(); };
+  static void static_cleanup() { RNAElement::static_initialize_default(); };
+  const char *class_name() const { return default_class_name(); }
+  const char *port_count() const	{ return "-/-"; } 
+  const char *processing() const	{ return PUSH; } 
+  
+  // Configuration..
+  int configure(Vector<String> &, ErrorHandler *);
+  int rna_finish_configuration(); // Complete the configuration step...
+  bool can_live_reconfigure() const     { return true; }
+  
+  // Data path. 
+  void push_data(int i, Packet *p); 
+
+  // Timer management 
+  static void static_rexmit_timer_hook(Timer *, void *);
+  void rexmit_timer_hook();  
+  
+  // Check for the existence of this sequence number...
+  bool should_be_saved(int); 
+  void print_queues();
+
+  // Go through the buffer to see if there are messages that are ready
+  // to be delivered to the upstream...
+  void deliver_ready_messages(); 
+  void send_ack(LinkState *, Packet *);
+
+ private:
+  
+  // Timer for all data processing...
+  Timer _rexmit_timer;
+
+  // on the sending side....
+  int _ack_recv;   /* Last acknowledgement received */
+  int _last_seq;   /* Last message in the window */
+  Vector<BufferedPacket *> _send_queue;
+
+  // at the receiving end...
+  int _ack_sent;   /* Last acknowledgement sent ; also the seq number of pkt delivered to app*/
+  Vector<BufferedPacket *> _recv_queue;
+
+};
+
+CLICK_ENDDECLS
+#endif
Index: rna/elements/rna/patterns_parser.pl
diff -u /dev/null rna/elements/rna/patterns_parser.pl:1.7
--- /dev/null	Sun Jan 25 11:47:09 2009
+++ rna/elements/rna/patterns_parser.pl	Fri Jan  2 14:06:58 2009
@@ -0,0 +1,905 @@
+#! /usr/bin/perl 
+
+################################################################
+#                                                              #
+# (c) University of Southern California                        #
+#                                                              #
+#  See LICENSE.RNA for the complete license                    #
+#                                                              #
+################################################################
+
+use Parse::RecDescent;
+use Data::Dumper; 
+
+our ($allowed_names, $patterns) = (undef) x 2;
+
+#-------------------------------------
+# Grammar to setup the patterns...
+#-------------------------------------
+
+## The default namespace...
+#NAMESPACE DEFAULT_NAMES 
+#
+#START MIN
+#
+## This simply specifies a buffer. no reodering etc. 
+#PATTERN MIN
+#    REQ MUST BUFFER 1 
+#    CONFIG LINK ADD CONTROL 0 BUFFER 1  
+#    CONFIG LINK ADD BUFFER 1 CONTROL 0 
+#
+## Next use this pattern in MIN is successful 
+#PATTERN ORDERED_DELIVERY
+#    FOLLOWS MIN
+#    REQ MUST REORDERBUFFER 1 
+#    CONFIG CAPABILITY PRESENT CONNECTION_ORIENTED 
+#    CONFIG LINK DEL CONTROL 0 BUFFER 1 
+#    CONFIG LINK ADD CONTROL 0 REORDERBUFFER 1 
+#    CONFIG LINK ADD REORDERBUFFER 1 BUFFER 1 
+#    UNCONFIG LINK DEL CONTROL 0 REORDERBUFFER 1 
+#    UNCONFIG LINK DEL REORDERBUFFER 1 BUFFER 1 
+#    UNCONFIG LINK ADD CONTROL 0 BUFFER 1 
+#
+#PATTERN ENCRYPTED_ORDERED_DELIVERY
+#    FOLLOWS ORDERED_DELIVERY
+#    REQ MUST ENCRYPTION 1 
+#    REQ MUST REORDERBUFFER 1
+#    REQ MUST DEMULTIPLEXOR 1
+#    CONFIG ARG ENCRYPTION 1 algo des 
+#    CONFIG ARG ENCRYPTION 1  keysize 512
+#    CONFG LINK ADD DEMULTIPLEXOR 1 REORDERBUFFER 1 
+#    CONFIG LINK ADD REORDERBUFFER 1 ENCRYPTION 1 
+#    UNCONFG LINK DEL DEMULTIPLEXOR 1 REORDERBUFFER 1 
+#    UNCONFIG LINK DEL REORDERBUFFER 1 ENCRYPTION 1 
+#
+
+#----------------------------------------
+# code implementing the grammar
+#----------------------------------------
+
+$::RD_ERRORS = 1; 
+$::RD_HINT = 1;
+#$::RD_TRACE = 0; 
+
+my $grammar = q { 
+
+{ 
+    use Data::Dumper;
+
+    my $namespace = undef; 
+    my %results = (); 
+    my %name_shortcuts = (); 
+    my @lines = (); 
+    
+    sub preprocess_text($){
+	@lines = split (/\n/, shift @_); 
+	#print Dumper(\@lines); 
+    }
+}
+
+PROGRAM: COMMAND(s) eofile
+{
+    $return = \%results;
+}
+
+eofile: /^\Z/
+
+COMMAND: NAMESPACE_CMD
+       | START_CMD  
+       | PATTERN_CMD 
+       | COMMENT 
+       | <error: Cannot parse line $thisline>
+       | /!^\Z/ {  
+	   die ("Cannot parse line " . ($thisline + 1). " "); 
+       } 
+
+
+NAMESPACE_CMD: 'NAMESPACE' IDENTIFIER 
+{
+    my $old_namespace = $namespace; 
+    $old_namespace = "" if (not defined $old_namespace); 
+    $namespace = $item{IDENTIFIER}; 
+    
+    #print "Redefining namespace; old = $old_namespace; new = $namespace\n"; 
+    
+}
+
+
+START_CMD: 'START' IDENTIFIER 
+{
+    die("Namespace undefined")  unless (defined $namespace); 
+
+    #print "Namespace in START command = $namespace \n"; 
+
+    $results{$namespace}{start} = $item{IDENTIFIER}; 
+}
+
+PATTERN_CMD: 'PATTERN' IDENTIFIER RULES
+{
+    
+    die("Namespace undefined")  unless (defined $namespace); 
+
+    #print "Namespace in PATTERN command = $namespace \n"; 
+    #print Dumper(\%item); 
+
+    my $name = $item{IDENTIFIER}; 
+    my $rules = $item{RULES}; 
+
+    #print "PATTERN_CMD RULES = " . Dumper($rules); 
+    
+    $results{$namespace}{patterns}{$name} = $item{RULES}; 
+}
+
+COMMENT: <skip: '^\s*'> ( /#/ | /^$/ ) <resync>
+
+#{
+#    print "Comment $thisline ******\n"; 
+#}
+
+
+RULES: RULE(s?)
+{
+    
+    #print "Entering rule" . Dumper(\@item); 
+
+    my %rules = (); 
+    foreach my $rule (@{$item[1]}){ 
+	next if (not defined $rule);
+	my $type = $rule->{type}; 
+	next if ($type =~ /RENAME/);
+	delete ($rule->{type});
+	push @{$rules{$type}}, $rule;
+    };
+
+    $return = \%rules; 
+}
+
+RULE: ( REQ_CMD | FOLLOWS_CMD | RENAME_CMD | CONF_CMD | CAPABILITY_CMD )
+{    
+    $return = $item[1]; 
+}
+
+
+#0        1        2          3       4       5    
+REQ_CMD: 'REQ'  ('MUST') IDENTIFIER VALUE(?) OP(?) 
+{
+    
+    #print "req_cmd = " . Dumper(\@item);
+
+    my %reqcmd       = (); 
+    $reqcmd{type}    = "REQ"; 
+    $reqcmd{cond}    = $item[2]; 
+    $reqcmd{name}     = $item[3]; 
+
+    #if (not defined main::lookup_module_name($reqcmd{name})){
+    #	die("Module type $reqcmd{var} must be defined before use\n". 
+    #	    "[" . $thisline . "] " . $lines[$thisline-1]. "\n");
+    #	return undef; 
+    #}
+    
+    my $instance = shift @{$item[4]};
+    if (defined $instance) { 
+	$reqcmd{instance}  = $instance; 
+    } else {
+	my $shortcut = $item[3];
+	$reqcmd{instance}  = $name_shortcuts{$shortcut}{instance};
+	$reqcmd{name}       = $name_shortcuts{$shortcut}{name};
+    };
+
+    my $op           = shift @{$item[5]};
+    if (defined $op) { 
+	$reqcmd{op}  = $op; 
+    } else {
+	$reqcmd{op}  = '='; 
+    };
+
+    $return = \%reqcmd; 
+
+    #print "Req = " . Dumper($return); 
+}
+
+##0             1         2          3         4    
+#COND_CMD: 'CONDITION' IDENTIFIER LOGICAL_OP IDENTIFIER 
+#{
+#    
+#    for (my $i = 0; $i <= $#item; $i++){
+#	print "COND_CMD var $i = " . Dumper($item[$i]); 
+#    }#
+#
+#    my %condcmd = (); 
+#    $condcmd{type}    = "COND"; 
+#    $condcmd{var}     = $item[2];
+#    $condcmd{op}      = $item[3]; 
+#    $condcmd{val}     = $item[4];
+#    
+#    $return = \%condcmd; 
+#
+#}
+
+#0             1         2        
+FOLLOWS_CMD: 'FOLLOWS' IDENTIFIER 
+{
+    die("Namespace undefined")  unless (defined $namespace); 
+
+    my $pattern = $item{IDENTIFIER}; 
+    
+    if (defined $results{$namespace}{patterns}{$pattern}){
+	my %patterncmd = (); 
+	$patterncmd{type}    = "FOLLOWS"; 
+	$patterncmd{dependency}     = $pattern; 
+	$return = \%patterncmd; 
+    } else { 
+	die("Pattern variable $pattern must be defined before use\n". 
+	    "[" . $thisline . "] " . $lines[$thisline-1]. "\n");
+    }
+}
+
+#0               #1               #2              #3           #4   
+CAPABILITY_CMD: 'CAPABILITY' CAPABILITY_CHECK  CAPABILITY_VAR TEXT
+{
+    
+    print "CAPABILITY : READING " . Dumper(\@item); 
+
+    my %patterncmd          = (); 
+    $patterncmd{type}       = "CAPABILITY"; 
+    $patterncmd{check}      = $item[2]; 
+    
+    my $cap = $item[3]; 
+    $patterncmd{capability} = $cap; 
+    my $d = $::allowed_names->{CapabilityVar}{"CAP_VAR_" . $cap};
+    die("Capability $cap is unknown!") if (not defined $d);
+    
+    my $val = $item[4]; # Could be potentially undef
+    $val = "" if ((not defined $val) or ($val =~ /""/) or ($val =~ /^$/)); 
+    $patterncmd{value} = $val; 
+
+    $return = \%patterncmd; 
+    
+    print Dumper($return); 
+
+}
+
+
+#0                  #1                    #2
+CONF_CMD: ('CONFIG' | 'UNCONFIG') (ARG_CMD | LINK_CMD | CAPABILITY_CMD )
+{
+    my $conf_type = $item[1]; 
+    my $cmd = $item[2]; 
+    $cmd->{conf} = $conf_type; 
+    $return = $cmd; 
+    #print "Conf command = " . Dumper($return); 
+}
+
+#0         1         2     3          4       5   
+ARG_CMD: 'ARG' IDENTIFIER  VALUE(?)  TEXT   TEXT 
+{
+
+    my $mod_name     = $item[2];
+    my $mod_instance = $item[3][0];
+    my $arg_name     = $item[4];
+    my $arg_val      = $item[5];
+
+    if (not defined $mod_instance) { 
+	my $shortcut = $mod_name;
+	$mod_instance  = $name_shortcuts{$shortcut}{instance};
+	$mod_name      = $name_shortcuts{$shortcut}{name};
+    };
+
+    #if (not defined main::lookup_module_name($mod_name)){
+    #	die("Module type $mod_name must be defined before use\n". 
+    #	    "[" . $thisline . "] " . $lines[$thisline-1]. "\n");
+    #	return undef; 
+    #}; 
+    
+    #if (($arg_type =~ /MODULE/) and 
+    #	(not defined main::lookup_module_name($arg_name))){
+    #	die("Module type $arg_name must be defined before use\n". 
+    #	    "[" . $thisline . "] " . $lines[$thisline-1]. "\n");
+    #	return undef; 
+    #}; 
+    
+    my %arg = (); 
+    $arg{type}         = 'ARG';
+    $arg{mod_name}     = $mod_name; 
+    $arg{mod_instance} = $mod_instance; 
+    $arg{arg_name}     = $arg_name; 
+    $arg{arg_val}      = $arg_val; 
+    
+    $return = \%arg; 
+
+    #print "Arg = " . Dumper($return); 
+}
+
+#0          1          2         3         4          5         6        7       8           9
+LINK_CMD: 'LINK' ('ADD'|'DEL') IDENTIFIER VALUE(?) VALUE(?) IDENTIFIER VALUE(?)  VALUE(?) KEYWORD(s?)
+{
+
+    my $link_op       = $item[2]; 
+    my $mod1_name     = $item[3];
+    my $mod1_instance = $item[4][0];
+    my $mod1_count    = $item[5][0];
+    my $mod2_name     = $item[6];
+    my $mod2_instance = $item[7][0];
+    my $mod2_count    = $item[8][0];
+    my $keywords      = $item[9]; 
+
+    if (not defined $mod1_instance) { 
+	my $shortcut = $mod1_name;
+	$mod1_instance  = $name_shortcuts{$shortcut}{instance};
+	$mod1_name      = $name_shortcuts{$shortcut}{name};
+    };
+
+    if (not defined $mod2_instance) {
+	my $shortcut = $mod2_name;
+	$mod2_instance  = $name_shortcuts{$shortcut}{instance};
+	$mod2_name      = $name_shortcuts{$shortcut}{name};
+    };
+
+    $mod1_count = 1 if (not defined $mod1_count); 
+    $mod2_count = 1 if (not defined $mod2_count);     
+    
+    die ("Only one side of the link cmd may be a wild card on line $thisline") 
+	if (($mod1_count > 1) and ($mod2_count > 1)); 
+
+    my %link = (); 
+    $link{type}          = 'LINK'; 
+    $link{op}            = $link_op; 
+    $link{mod1_name}     = $mod1_name; 
+    $link{mod1_instance} = $mod1_instance; 
+    $link{mod1_count}    = $mod1_count; 
+    $link{mod2_name}     = $mod2_name; 
+    $link{mod2_instance} = $mod2_instance; 
+    $link{mod2_count}    = $mod2_count; 
+    $link{keywords}      = $keywords; 
+    
+    $return = \%link; 
+    
+}
+
+#0               1         2     3         4     
+RENAME_CMD: 'RENAME' IDENTIFIER  VALUE TEXT 
+{
+    my $mod_name     = $item[2];
+    my $mod_instance = $item[3];
+    my $new_mod_name = $item[4];
+    
+    #if (not defined main::lookup_module_name($mod_name)){
+    #	die("Module $mod_name must be defined before use\n". 
+    #	    "[" . $thisline . "] " . $lines[$thisline-1]. "\n");
+    #	return undef; 
+    #};
+    
+    # XXX The count must be verified....
+
+    $name_shortcuts{$new_mod_name}{name}= $mod_name;
+    $name_shortcuts{$new_mod_name}{instance}= $mod_instance;
+
+    #print "RENAME " . Dumper(\%name_shortcuts); 
+    my %dummy = (
+		 type => 'RENAME'
+		 ); 
+    $return = \%dummy; 
+
+}
+
+#0                      #1 
+CAPABILITY_CHECK: ( 'PRESENT' | 'ABSENT' | 'MATCH' | 'PROVIDE' | 'NOTPROVIDE' )
+
+OP: ('>='|'<='|'='|'<'|'>')
+
+LOGICAL_OP: ('XOR'|'AND'|'OR') 
+
+CAPABILITY_VAR: IDENTIFIER 
+{
+    $return = $item[1]; 
+}
+
+IDENTIFIER: /[A-Za-z_][A-Za-z0-9_]*/
+
+KEYWORD: (SIMPLE_KEYWORD|RANGE_KEYWORD)
+{
+    
+    #print "Keyword = " . Dumper(\@item); 
+
+    my $name = $item[1][0]; 
+    if ($name =~ /(BIDIRECTIONAL|ALL)/){
+	$return = $name; 
+    } elsif ($name =~ /RANGE/) {
+	$return = $name;
+    };    
+}
+
+SIMPLE_KEYWORD: ('BIDIRECTIONAL'|'ALL')
+{
+    #print "Simple keyword = " . Dumper(\@item); 
+    $return = [$item[1]]; 
+}
+
+
+# This is not handled at this point...
+
+RANGE_KEYWORD: 'RANGE' VALUE '-' VALUE 
+{
+    #print "Range Cmd = " . Dumper(\@item); 
+    $return = [ 'RANGE', $item[2], $item[4] ]; 
+    
+    die("Range command not supported right now..."); 
+}
+
+TEXT: /\S+/
+
+VALUE: /\d+/ 
+
+};
+
+
+sub read_namespaces($){
+    my $file = shift; 
+    
+    my %allowed_names_local = (); 
+
+    return if (not defined $file); 
+    open(FILE, "<$file") || die("Cannot open file $file "); 
+    
+    my $classname = undef; 
+    while(<FILE>){
+	
+	
+	# Cleanup the line first...
+	chomp; 
+	s/\/\/.*$//g; 
+	s/^\s+//;
+	s/=.*$//g;
+	s/,//g;
+
+	next if (/^\#/);	
+	next if (/^\s*$/); 
+	
+	# Track the enum
+	if (not defined $classname) {
+	    my $line = $_; 
+	    #print "line = $line \n"; 
+	    $line =~ s/\s*enum//g; 
+	    $line =~ s/\{//g; 	
+	    $line =~ s/\s+//g;
+	    $classname = $line; 
+	    next; 
+	};
+	
+	if (defined $classname and /\}/){
+	    $classname = undef; 
+	    next; 
+	}
+	
+	next if (/(_END|_BEGIN)/);
+	
+	# Clean up the keyword...
+	s/\s*//g; 
+	$allowed_names_local{$classname}{$_} = 1; 
+    };
+
+    close(FILE); 
+
+    #print Dumper(\%allowed_names_local); 
+
+    return \%allowed_names_local;
+};
+
+
+sub read_patterns($){
+    my $file = shift; 
+    my $text = ""; 
+
+    return undef if (not defined $file); 
+
+    open(FILE, "<$file") || die("Cannot open file $file "); 
+    while(<FILE>){
+	chop;
+	unless ( /(^\s*\#)|(^\s*$ )/ ){
+	    $text .= $_;
+	}
+	$text .= "\n"; 
+    };
+    
+    $text .= "\n"; 
+    print $text; 
+    close(FILE); 
+    
+	
+    return $text; 
+};
+
+sub lookup_module_name($) {
+
+    my $varname = shift; 
+    
+    my $val = (defined $allowed_names 
+	       and defined $varname 
+	       and defined $$allowed_names{RNAElementType}{$varname}); 
+
+    #print "in Lookup_module_name $varname val = $val " . 
+    #Dumper($allowed_names) . $allowed_names{$varname}; 
+        
+    return 1 if ($val == 1);
+    return undef;
+};
+
+##########################################
+#
+# Generate the output file...
+# 
+##########################################
+#
+#         'WIRELESS' => {
+#                          'patterns' => {
+#                                          'MIN' => {
+#                                                     'CAPABILITY' => [
+#                                                                       {
+#                                                                         'check' => 'PRESENT',
+#                                                                         'value' => undef,
+#                                                                         'capability' => 'CONNECTION_LESS'
+#                                                                       },
+#                                                                       {
+#                                                                         'check' => 'PRESENT',
+#                                                                         'value' => undef,
+#                                                                         'capability' => 'LOSSY'
+#                                                                       }
+#                                                                     ]
+#                                                   },
+#                                          'ORDERED_DELIVERY' => {
+#                                                                  'REQ' => [
+#                                                                             {
+#                                                                               'cond' => 'MUST',
+#                                                                               'name' => 'REORDERBUFFER',
+#                                                                               'instance' => '1',
+#                                                                               'op' => '='
+#                                                                             }
+#                                                                           ],
+#                                                                  'LINK' => [
+#                                                                              {
+#                                                                                'mod1_count' => 1,
+#                                                                                'mod2_count' => 1,
+#                                                                                'mod1_instance' => '0',
+#                                                                                'mod1_name' => 'CONTROL',
+#                                                                                'mod2_name' => 'BUFFER',
+#                                                                                'conf' => 'CONFIG',
+#                                                                                'keywords' => [],
+#                                                                                'mod2_instance' => '0',
+#                                                                                'op' => 'DEL'
+#                                                                              },
+#                                                                              {
+#                                                                                'mod1_count' => 1,
+#                                                                                'mod2_count' => 1,
+#                                                                                'mod1_instance' => '0',
+#                                                                                'mod1_name' => 'CONTROL',
+#                                                                                'mod2_name' => 'REORDERBUFFER',
+#                                                                                'conf' => 'CONFIG',
+#                                                                                'keywords' => [],
+#                                                                                'mod2_instance' => '0',
+#                                                                                'op' => 'ADD'
+#                                                                              },
+#                                                                              {
+#                                                                                'mod1_count' => 1,
+#                                                                                'mod2_count' => 1,
+#                                                                                'mod1_instance' => '0',
+#                                                                                'mod1_name' => 'REORDERBUFFER',
+#                                                                                'mod2_name' => 'BUFFER',
+#                                                                                'conf' => 'CONFIG',
+#                                                                                'keywords' => [],
+#                                                                                'mod2_instance' => '0',
+#                                                                                'op' => 'ADD'
+#                                                                              },
+#                                                                              {
+#                                                                                'mod1_count' => 1,
+#                                                                                'mod2_count' => 1,
+#                                                                                'mod1_instance' => '0',
+#                                                                                'mod1_name' => 'CONTROL',
+#                                                                                'mod2_name' => 'REORDERBUFFER',
+#                                                                                'conf' => 'UNCONFIG',
+#                                                                                'keywords' => [],
+#                                                                                'mod2_instance' => '0',
+#                                                                                'op' => 'DEL'
+#                                                                              },
+#                                                                              {
+#                                                                                'mod1_count' => 1,
+#                                                                                'mod2_count' => 1,
+#                                                                                'mod1_instance' => '0',
+#                                                                                'mod1_name' => 'REORDERBUFFER',
+#                                                                                'mod2_name' => 'BUFFER',
+#                                                                                'conf' => 'UNCONFIG',
+#                                                                                'keywords' => [],
+#                                                                                'mod2_instance' => '0',
+#                                                                                'op' => 'DEL'
+#                                                                              },
+#                .
+#                .
+#                .
+#                .
+#                                                            },
+#                                                    'NULL' => {}
+#                                                  },
+#                                    'start' => 'MIN'
+#                                  }
+#
+#                .
+#                .
+#
+#           'DEFAULT' => {
+#                         'patterns' => {
+#                                         'MIN' => {
+#                                                    'REQ' => [
+#                                                               {
+#                                                                 'cond' => 'MUST',
+#                                                                 'name' => 'BUFFER',
+#                                                                 'instance' => '1',
+#                                                                 'op' => '='
+#                                                               }
+#                                                             ],
+#                                                    'CAPABILITY' => [
+#                                                                      {
+#                                                                        'check' => 'PRESENT',
+#                                                                        'value' => undef,
+#                                                                        'capability' => 'CONNECTION_LESS'
+#                                                                      }
+#                                                                    ]
+#                                                  },
+#                                         'ORDERED_DELIVERY' => {
+#                                                                 'REQ' => [
+#                                                                            {
+#                                                                              'cond' => 'MUST',
+#                                                                              'name' => 'REORDERBUFFER',
+#                                                                              'instance' => '1',
+#                                                                              'op' => '='
+#                                                                            }
+#                                                                          ],
+#                                                                 'LINK' => [
+#                                                                             {
+#                                                                               'mod1_count' => 1,
+#                                                                               'mod2_count' => 1,
+#                                                                               'mod1_instance' => '0',
+#                                                                               'mod1_name' => 'CONTROL',
+#                                                                               'mod2_name' => 'BUFFER',
+#                                                                               'conf' => 'CONFIG',
+#                                                                               'keywords' => [],
+#                                                                               'mod2_instance' => '0',
+#                                                                               'op' => 'DEL'
+#                                                                             },
+#                                                                             {
+#                                                                               'mod1_count' => 1,
+#                                                                               'mod2_count' => 1,
+#                                                                               'mod1_instance' => '0',
+#                                                                               'mod1_name' => 'CONTROL',
+#                                                                               'mod2_name' => 'REORDERBUFFER',
+#                                                                               'conf' => 'CONFIG',
+#                                                                               'keywords' => [],
+#                                                                               'mod2_instance' => '0',
+#                                                                               'op' => 'ADD'
+#                                                                             },
+#                                                                             {
+#                                                                               'mod1_count' => 1,
+#                                                                               'mod2_count' => 1,
+#
+#                .
+#                .
+#                .
+#                .
+#                .
+#
+
+sub gen_code_for_patterns($){
+    my $allpatterns = shift; 
+    
+    #print "gen_code_for_patterns" . Dumper($allpatterns); 
+
+    my $msg = ""; 
+    
+    $msg .= "  " . "\/\/" x 45 . "\n";
+    $msg .= "  \/\/\n";
+    $msg .= "  \/\/ This code was automatically generated by the elements/rna/patterns_parser.pl.\n"; 
+    $msg .= "  \/\/ Please do not edit this file. Modify either metaprotocol_patterns_db.txt \n"; 
+    $msg .= "  \/\/ or patterns_parser.pl \n"; 
+    $msg .= "  \/\/\n";
+    $msg .= "  \/\/ This code generated at: " . localtime() . "\n";
+    $msg .= "  \/\/\n";
+    $msg .= "  " . "\/\/" x 45 . "\n";
+
+    $msg .= "  Vector<Namespace *> namespaces; \n"; 
+    $msg .= "  Vector<Pattern *> patternlist; \n"; 
+    $msg .= "  Pattern *pat;\n";
+    $msg .= "  Vector<String> parents;\n";
+    $msg .= "  Vector<Req *> reqs; \n"; 
+    $msg .= "  Vector<Capability *> capabilities; \n"; 
+    $msg .= "  Vector<Arg *> args; \n"; 
+    $msg .= "  Vector<Link *> links; \n"; 
+    $msg .= "  Req *r;\n"; 
+    $msg .= "  Capability *c;\n"; 
+    $msg .= "  Arg *a;\n"; 
+    $msg .= "  Link *l;\n"; 
+    $msg .= "  Vector<String> keywords;\n"; 
+    
+    foreach my $namespace (keys %{$allpatterns}){ 
+	
+	#print "Process namespace $namespace \n"; 
+
+	$msg .= "\n  // Namespace $namespace"; 
+	$msg .= "\n  {\n"; 
+	$msg .= "  \tpatternlist.clear();\n"; 
+	foreach my $pattern (keys %{$allpatterns->{$namespace}{patterns}}){
+	
+	    my $thispattern = $allpatterns->{$namespace}{patterns}{$pattern};
+
+	    #print "Looking at pattern $namespace::$pattern " . Dumper($thispattern); 
+	
+	    $msg .= "\n  \t// Code for pattern ${namespace}::$pattern\n";
+	    $msg .= "  \t{\n"; 
+	    $msg .= "  \t\tparents.clear();\n";
+	    $msg .= "  \t\treqs.clear(); \n"; 
+	    $msg .= "  \t\tcapabilities.clear(); \n"; 
+	    $msg .= "  \t\targs.clear(); \n"; 
+	    $msg .= "  \t\tlinks.clear(); \n\n"; 
+	    
+	    my $parent_arr = $thispattern->{FOLLOWS};
+	    foreach my $parent (@{$parent_arr}){
+		$msg .= "  \t\tparents.push_back(\"$parent->{dependency}\");\n"; 
+	    };
+	    
+	    my $r_arr = $thispattern->{REQ};
+	    foreach my $r (@{$r_arr}){
+		
+		my $cond = $r->{cond}; 
+		my $name = $r->{name}; 
+		my $instances = $r->{instance}; 
+		
+		if ($cond =~ /MUST/){
+		    $cond = "CONSTRAINT_REQUIRE_MUST";
+		};
+		
+		$msg .= "  \t\tr = new Req($cond,$name,$instances);\n"; 
+		$msg .= "  \t\treqs.push_back(r);\n"; 
+	    };
+	    
+	    my $c_arr = $thispattern->{CAPABILITY};
+	    foreach my $c (@{$c_arr}){
+		
+		my $check = $c->{check}; 
+		my $capability = $c->{capability}; 
+		my $value = $c->{value}; 
+		$value = "" if (not defined $value); 
+		my $conf;
+		if (defined $c->{conf}){ 
+		    $conf      = "CONF_" . $c->{conf};
+		} else {
+		    $conf      = "CONF_NONE"; 
+		};
+		    
+		$msg .= "  \t\tc = new Capability(CAP_CHK_$check, CAP_VAR_$capability,".
+		    "\"$value\", $conf);\n"; 
+		$msg .= "  \t\tcapabilities.push_back(c);\n"; 
+	    };
+	    
+	    my $a_arr = $thispattern->{ARG};
+	    foreach my $a (@{$a_arr}){
+		
+		my $name     = $a->{mod_name}; 
+		my $instance = $a->{mod_instance}; 
+		my $var      = $a->{arg_name}; 
+		my $val      = $l->{arg_val}; 
+		
+		$msg .= "  \t\ta = new Arg($name, $instance, \"$var\", \"$val\");\n"; 
+		$msg .= "  \t\targs.push_back(a); \n"; 
+	    };
+	    
+	    my $l_arr = $thispattern->{LINK};
+	    foreach my $l (@{$l_arr}){
+		
+		my $name1     = $l->{mod1_name}; 
+		my $name2     = $l->{mod2_name}; 
+		my $instance1 = $l->{mod1_instance}; 
+		my $instance2 = $l->{mod2_instance};
+		my $count1    = $l->{mod1_count}; 
+		my $count2    = $l->{mod2_count};
+		
+		my $op        = "LINK_OP_" . $l->{op}; 
+		my $conf      = "CONF_" . $l->{conf};
+		my $keywords  = $l->{keywords}; 
+
+		if (not defined $name1 or not defined $name2){
+		    print Dumper($l);
+		};
+
+		
+		$msg .= "  \t\tkeywords.clear(); \n"; 
+		foreach my $str (@{$keywords}){
+		    $msg .= "  \t\tkeywords.push_back(\"$str\");\n"; 
+		};
+		
+		my $txt = "\t\t\tl = new Link($name1, $instance1, $count1, " . 
+		    "$name2, $instance2, $count2, $op, $conf, keywords);\n";
+		#print "$txt"; 
+		$msg .= $txt; 
+		$msg .= "  \t\tlinks.push_back(l); \n"; 
+		
+	    };
+	
+	    $msg .= "  \t\tpat = new Pattern(this, \"$pattern\", ". 
+		"parents, reqs, capabilities, args, links); \n"; 
+	    $msg .= "  \t\tpatternlist.push_back(pat); \n"; 
+	    $msg .= "  \t};\n"; 
+	    $msg .= "  \t//Completed pattern ${namespace}::$pattern\n"; 
+	}
+	
+	# Add a NULL pattern....
+	if (not defined $allpatterns->{$namespace}{patterns}{NULL}){ 
+	    $msg .= "\n  \t// Code for NULL\n";
+	    $msg .= "  \t{\n";
+	    $msg .= "  \t\tparents.clear();\n";
+	    $msg .= "  \t\treqs.clear(); \n"; 
+	    $msg .= "  \t\tcapabilities.clear(); \n"; 
+	    $msg .= "  \t\targs.clear(); \n"; 
+	    $msg .= "  \t\tlinks.clear(); \n"; 
+	    $msg .= "  \t\tpat = new Pattern(this, \"NULL\", parents, reqs, capabilities, args, links); \n"; 
+	    $msg .= "  \t\tpatternlist.push_back(pat); \n"; 
+	    $msg .= "  \t};\n"; 
+	    $msg .= "  \t//Completed pattern NULL\n"; 
+	};
+	
+	
+	#=> Now create the namespace structure...
+	my $start = $allpatterns->{$namespace}{start}; 
+	$start = "NULL" if (not defined $start); 
+
+	$msg .= "\n  \tNamespace *n = new Namespace(this, \"$namespace\", " . 
+	        "\"$start\", patternlist); \n"; 
+	$msg .= "  \tnamespaces.push_back(n);\n"; 
+	$msg .= "\n  };\n"; 
+	$msg .= "  // Namespace $namespace\n"; 
+    }; # ..all namespaces...
+    
+
+    return $msg; 
+};
+
+##########################################
+sub Usage() {
+    
+    print "Usage: perl patterns_parser.pl <patterns-file> <namespace> ".
+	  "<generated-code-file>\n"; 
+    die; 
+};
+
+my ($patterns_file, $module_namespace_file, $code_file) = @ARGV; 
+Usage() unless (defined $patterns_file and 
+		defined $module_namespace_file and 
+		defined $code_file);
+		
+
+# -----------------
+# Read variable names from another file...
+# -----------------
+$allowed_names = read_namespaces($module_namespace_file);
+
+# -----------------
+# Read patterns from the file...
+# -----------------
+$patterns = read_patterns($patterns_file); 
+die ("Read failed") if (not defined $patterns); 
+
+# -----------------
+# Generate a parser from the specification in $grammar
+# -----------------
+my $parser = new Parse::RecDescent ($grammar);
+die ("Parser not compiled") if (not defined $parser); 
+
+my $parser_result = $parser->PROGRAM($patterns);
+#print "Result = " . Dumper($parser_result);
+die ("Parsing failed") if (not defined $parser_result); 
+
+# -----------------
+# Generate code and dump it in the patterns file...
+# -----------------
+my $code =  gen_code_for_patterns($parser_result); 
+die ("Code generation failed") if (not defined $code); 
+
+open(FILE, ">$code_file") || die("Cannot open file $code_file to write"); 
+print FILE $code; 
+close(FILE); 
Index: rna/elements/rna/rnaelement.cc
diff -u /dev/null rna/elements/rna/rnaelement.cc:1.3
--- /dev/null	Sun Jan 25 11:47:09 2009
+++ rna/elements/rna/rnaelement.cc	Fri Dec 26 16:57:00 2008
@@ -0,0 +1,80 @@
+/* 
+
+################################################################
+#                                                              #
+# (c) University of Southern California                        #
+#                                                              #
+#  See LICENSE.RNA for the complete license                    #
+#                                                              #
+################################################################
+
+*/
+
+#include "rnaelement.hh"
+
+//
+// Core RNA element...All the interesting code is elsewhere such as in
+// the neighbors, control etc. 
+//
+ 
+// Gather all the upstream and downstream nodes 
+#include "rnaelement_neighbors.cc" 
+
+// Parse the arguments to the module; configuration commands. 
+#include "rnaelement_parse.cc" 
+
+// Process the links. 
+#include "rnaelement_links.cc" 
+
+// Control interface to the module. If the message is not handled by
+// the default code, then run the module-specific control code; also
+// included is the connection state at the next layer...
+#include "rnaelement_control.cc" 
+
+// Miscellaneous 
+#include "rnaelement_handlers.cc" 
+
+// Message handling
+#include "rnaelement_messages.cc" 
+
+
+
+//############################################################
+//
+// Constructor and destructor...
+// 
+//############################################################
+RNAElement::RNAElement() { 
+
+  if (0)
+    rna_click_chatter(FUNC_ENTRY, "RNAElement::RNAElement()\n"); 
+  
+  type = UNKNOWN; 
+  instance = String::stable_string(""); 
+  exec_finish_configuration = false; 
+  connection_oriented = false; 
+  skip_connection_check = true; 
+  state = 0;
+  debug = true; 
+  conns.clear(); 
+
+  _preconfigured_element_list = false; 
+  _upstream_element_list.clear(); 
+  _downstream_element_list.clear(); 
+  
+} 
+
+RNAElement::~RNAElement() {
+  // Do nothing....
+};
+
+
+
+ELEMENT_REQUIRES(LinkState)
+ELEMENT_REQUIRES(RNAError)
+ELEMENT_REQUIRES(RNAControlMsg)
+ELEMENT_REQUIRES(ConnectionState)
+
+ELEMENT_PROVIDES(RNAElement)
+
+CLICK_ENDDECLS
Index: rna/elements/rna/rnaelement.hh
diff -u /dev/null rna/elements/rna/rnaelement.hh:1.3
--- /dev/null	Sun Jan 25 11:47:09 2009
+++ rna/elements/rna/rnaelement.hh	Fri Dec 26 16:57:00 2008
@@ -0,0 +1,324 @@
+/* 
+
+################################################################
+#                                                              #
+# (c) University of Southern California                        #
+#                                                              #
+#  See LICENSE.RNA for the complete license                    #
+#                                                              #
+################################################################
+
+*/
+#ifndef CLICK_RNAELEMENT_HH
+#define CLICK_RNAELEMENT_HH
+
+#include "rnaelement_common.hh" 
+
+class LinkState; 
+class State; 
+class RNAElement; 
+class RNAControlMsg; 
+
+extern const char *str_elementtype[];
+#include "shared_namespaces.txt" 
+
+#include "rnaelement_error.hh" 
+#include "rnaelement_connstate.hh" 
+#include "rnaelement_ctlmsg.hh" 
+#include "rnaelement_messages.hh" 
+#include "rnaelement_linkstate.hh" 
+#include "metaprotocol_patterns.hh" 
+
+
+CLICK_DECLS
+
+
+//##########################################################
+// Misc definitions 
+//##########################################################
+#define MAX_PRINT_PKT 50
+
+//##########################################################
+// This is high-level specification from the configure function.
+// 
+// This is just an internal structure to pass parameters; not the most
+// important.
+//
+//##########################################################
+class linkspec {
+public: 
+  bool local_is_upstream; 
+  bool crosslayer; 
+  bool intrastack; 
+  int local_elem;
+  int local_out; 
+  int remote_elem;
+  int remote_in;
+  LinkState *l0;                // linkcmd at the local node 
+  LinkState *l1;                // linkcmd at the remote node
+};
+
+//#########################################################
+//#
+//#  RNA Element structure...
+//#
+//#########################################################
+
+
+//#########################################################
+// 
+// RNAElement
+// 
+// This is a wrapper around the basic element structure provided by
+// Click. This adds: 
+// 
+// * Control interface - to communicate between RNAElements for discovery
+//   and state modification
+// 
+// * Link management - addition/deletion of the links on the fly 
+// 
+// * Message flow - default algorithms to move data across modules; do
+//   pre and post processing of the messages. 
+// 
+// * Element management - maintain the list of elements 
+// 
+// * Template - the state and pattern management. 
+// 
+// 
+// LIMITATIONS: 
+// 
+// * Only push interface is supported right now. Pull interface is not
+// fundamentally different in terms of the functionality except the
+// RNAElement structure must be generalized a little more.
+// 
+// * Template is static. Patterns are statically generated and stored.
+// 
+//#########################################################
+
+//class RNAElement : public RNAControlElement, public Element { 
+class RNAElement : public Element { 
+
+protected: 
+  
+  bool debug;                             // Is debug enabled for this module? 
+  String instance;                        // name of this element
+  RNAElementType type;                    // the type of this RNA element
+  bool skip_connection_check;             // should I check for connection state? 
+  Vector<ConnectionState *> conns;        // my connection state 
+  bool connection_oriented;               // Is this protocol connection-oriented? 
+  String controlnode;                     // ?? 
+  State *state;                           // Store of the patterns   
+  Vector<LinkState *> all_links;          // All the links associated with this element
+  bool exec_finish_configuration;         // should I initiate the connection process? 
+  
+  Vector<RNAElement *> _elemlist;         // Elements specified and how they are eventually 
+                                          // connected. 
+
+
+  // Input provided by user until it can be automatically computed...
+  bool _preconfigured_element_list; 
+  Vector<Element *> _upstream_element_list; 
+  Vector<Element *> _downstream_element_list; 
+
+public:
+
+  //============================================================
+  // Constructor and destructor...
+  //============================================================
+  RNAElement(); 
+  ~RNAElement();
+
+  //============================================================
+  // Handle Click router-related calls...
+  //============================================================
+  static void static_initialize_default(); 
+  static void static_cleanup_default(); 
+  
+  // This is called  by the Click router and used to parse the 
+  // argued parsed. 
+  virtual int configure(Vector<String> &conf, ErrorHandler *errh); 
+  
+  // Misc functions...
+  void *cast(const char *n); 
+  virtual const char *default_class_name() const { return "RNAElement"; }
+  
+  // Callback handlers. Not doing much at this point. 
+  static String rna_read_handler(Element *e, void *thunk);
+  static int rna_write_handler(const String &conf, Element *e, 
+			       void *p, ErrorHandler *errh); 
+  
+
+  //============================================================
+  // Handle messages from other layers and modules 
+  //============================================================
+  virtual void push_data(int i, Packet *); 
+  virtual bool push_data_to_link(Packet *p, LinkState *l, const char *func);
+  virtual void push_control(int i, Packet *); 
+  virtual void push_management(int i, Packet *); 
+  virtual void push(int i, Packet *p);
+
+  
+  //============================================================
+  // parse the element list specified in the configure 
+  // command. 
+  //============================================================
+  static void elementlist_parse(cp_value *v, const String &arg, 
+				ErrorHandler *errh, const char *argname, 
+				Element *context);
+  static void  elementlist_store(cp_value *v, Element *); 
+  
+  // Not used. 
+  static Vector<Element *> elementlist_find_prefix(String name,
+						   Element *); 
+  // Not used.   
+  RNAElement *elementlist_lookup_one(Vector<RNAElement *>& array, 
+				     RNAElementType t, 
+				     bool modify = false);
+  // Not used. 
+  Vector<RNAElement *> elementlist_lookup(Vector<RNAElement *>& array, 
+					  RNAElementType t, 
+					  bool modify = false);
+
+  //============================================================
+  // Identifies what type this module is. This is useful in 
+  // matching the module to the specification of the protocol 
+  //============================================================
+  void set_type(RNAElementType s) { type = s; } 
+  RNAElementType get_type() { return type; }   
+
+  //============================================================
+  // Functions to enable human readability 
+  //============================================================
+  const char *instance_name() { return instance.printable().c_str(); } 
+  void print_packet(String label, Packet *p, bool print_annotations = false);
+
+  //============================================================
+  // Control interface to the module 
+  //============================================================
+  bool is_control() { return ((type == CONTROL) || (type == NETSTACK)); }
+  virtual RNAControlMsg *control(RNAControlMsg *c);  // added by RNA
+
+  virtual RNAControlMsg *module_specific_control(RNAControlMsg *c);  // added by RNA
+  
+  
+  // Complete the configuration. During the initialization by Click
+  // and later by RNA metaprotocol while finishing up the composition. 
+  virtual int finish_configuration(); // Called from the default configure 
+                                      // if PROCESS is enabled. 
+  virtual int rna_finish_configuration(); // Complete the configuration step...
+  
+  // Misc click callback handler. Not really used. 
+  void add_handlers();                  
+  
+  //============================================================
+  // Connection State Management 
+  //============================================================
+  
+  // Should I do connection check when sending a message on a certain
+  // outgoing link? (typically necessary for downstream protocol that 
+  // is connection-oriented 
+  void set_skip_conn_check(bool val) { skip_connection_check = val; return; }
+  bool get_skip_conn_check() { return skip_connection_check; }
+
+  // Check the state in the incoming message 
+  bool check_connectionstate(LinkState *incoming_link, Packet *p_in);  
+  
+  // Update the connection state for each outgoing link...
+  bool open_connection(LinkState *incoming_link = NULL);
+  void discover_connectionstate(LinkState *l); 
+  void initialize_link(LinkState *l);   
+
+  //============================================================
+  // Link management functions. 
+  // Information about the incoming and outgoing links. 
+  //============================================================
+  int  add_default_bidirectional_links(Vector <struct linkspec *> *links,
+				       bool crosslayer); 
+  int  add_default_unidirectional_links(Vector <struct linkspec *> *links,
+					bool crosslayer); 
+  int add_default_autodetect_links(Vector <struct linkspec *> *links, 
+				   bool crosslayer);
+  int process_linkspecs(Vector<struct linkspec *> &linkspecs); 
+  int delete_link(LinkState *); 
+  void print_links(); 
+  void print_allelements_links(); 
+
+
+  //============================================================
+  // Manipulation of the predessor and successor lists 
+  //============================================================
+  void skip_type(Vector<Element *> &v, char *typename_in); 
+  void filter(char *what, Vector<Element*>& v); 
+  Element *upstream_element(Element *e, int inputport);
+  Vector<Element*> upstream_elements(Element *e, int inputport = -1);
+  Vector<Element*> downstream_elements(Element *e);
+
+  
+  //============================================================
+  // Handle the incoming and outgoing messages
+  //============================================================
+  virtual void process_incoming_from_downstream(Packet **p_in, 
+						LinkState *incoming = NULL, 
+						MessageStatus *status = NULL); 
+  virtual void process_incoming_from_upstream  (Packet **p_in, 
+						LinkState *incoming = NULL, 
+						MessageStatus *status = NULL); 
+  virtual void process_outgoing_to_downstream  (Packet **p_in, 
+						LinkState *outgoing = NULL, 
+						MessageStatus *status = NULL); 
+  virtual void process_outgoing_to_upstream    (Packet **p_in, 
+						LinkState *outgoing = NULL, 
+						MessageStatus *status = NULL); 
+
+  //============================================================
+  // Link state management functions...
+  //============================================================
+  // Select the outgoing links to forward the message to..
+  virtual LinkState *check_for_duplicate_link(LinkState *l);
+  void merge_link_information(LinkState *existing_link, LinkState *newlink); 
+  
+  LinkState *lookup_link(int port, bool incoming = true); 
+  LinkState *lookup_link(RNAElement *e, bool incoming = true); 
+  
+  // Which way should a packet go? 
+  virtual LinkState *select_outgoing_link(Packet *p, 
+					LinkState *incoming, 
+					bool downstream = true, 
+					bool layeragnostic = false,
+					bool crosslayer = false,
+					bool agnostic_remote = true,
+					bool remote_unknown = false, 
+					ConnectionState *preferred = 0); 
+  virtual Vector<LinkState *>
+                     list_outgoing_link(Packet *p, 
+					LinkState *incoming, 
+					bool downstream = true, 
+					bool layeragnostic = false,
+					bool crosslayer = false,
+					bool agnostic_remote = true,
+					bool remote_unknown = false, 
+					ConnectionState *preferred = 0); 
+
+  virtual int count_outgoing_links(Packet *p, LinkState *incoming, 
+				   bool downstream, 
+				   bool layeragnostic, 
+				   bool crosslayer,
+				   bool agnostic_remote,           
+				   bool remote_unknown, 
+				   ConnectionState *preferred = 0);
+  
+  virtual Vector<LinkState *> 
+           list_downstream_elements(bool downstream, 
+				    bool layeragnostic, 
+				    bool crosslayer,
+				    bool agnostic_remote,             
+				    bool remote_unknown, 
+				    ConnectionState *preferred = 0);
+  
+};
+
+
+
+
+CLICK_ENDDECLS
+#endif
Index: rna/elements/rna/rnaelement_common.hh
diff -u /dev/null rna/elements/rna/rnaelement_common.hh:1.2
--- /dev/null	Sun Jan 25 11:47:09 2009
+++ rna/elements/rna/rnaelement_common.hh	Fri Dec 26 16:57:00 2008
@@ -0,0 +1,27 @@
+#include <click/config.h>
+#include <clicknet/ip.h>
+#include <click/router.hh> 
+#include <click/error.hh>
+#include <click/glue.hh>
+#include <click/standard/alignmentinfo.hh>
+#ifdef CLICK_LINUXMODULE
+# include <net/checksum.h>
+#endif
+#include <click/elemfilter.hh> 
+#include <click/element.hh>
+#include <click/glue.hh>
+#include <click/atomic.hh>
+#include <clicknet/udp.h>
+#include <click/confparse.hh>
+#include <click/straccum.hh> 
+#include <click/vector.hh> 
+#include <iostream> 
+
+using namespace std;
+
+#include <stdarg.h> 
+
+#define QUOTE(EXP) #EXP 
+
+CLICK_DECLS
+
Index: rna/elements/rna/rnaelement_connstate.cc
diff -u /dev/null rna/elements/rna/rnaelement_connstate.cc:1.1
--- /dev/null	Sun Jan 25 11:47:09 2009
+++ rna/elements/rna/rnaelement_connstate.cc	Fri Jun 27 10:40:58 2008
@@ -0,0 +1,107 @@
+/* 
+
+################################################################
+#                                                              #
+# (c) University of Southern California                        #
+#                                                              #
+#  See LICENSE.RNA for the complete license                    #
+#                                                              #
+################################################################
+
+*/
+
+#include "rnaelement_connstate.hh"
+
+//############################################
+// Initialization and cleanup
+//############################################
+ConnectionState::ConnectionState()
+{
+  // Do nothing...
+}
+
+ConnectionState::~ConnectionState()
+{
+
+  while (varlist.size() > 0){ 
+    Variable *v = varlist.back();
+    if (v) 
+      delete v; 
+    varlist.pop_back();
+  };
+};
+
+int 
+ConnectionState::add_variable(VariableType t, void *data){  
+  Variable *v = new Variable(t, data); 
+  add_variable(v); 
+  return 0; 
+  
+};
+
+//############################################
+// Add and delete variables from the state..
+//############################################
+
+int 
+ConnectionState::add_variable(Variable *v){  
+  varlist.push_back(v); 
+  return 0; 
+  
+};
+
+int 
+ConnectionState::del_variable(int index){  
+
+  Vector<Variable *> modified; 
+  for (int i = 0; i < varlist.size(); i++)
+    if (i != index) 
+      modified.push_back(varlist[i]);
+  varlist.swap(modified); 
+  
+  return 0; 
+  
+};
+
+int 
+ConnectionState::del_variable(Variable *v){  
+
+  Vector<Variable *> modified; 
+  for (int i = 0; i < varlist.size(); i++)
+    if (v != varlist[i]) 
+      modified.push_back(varlist[i]);
+  varlist.swap(modified); 
+  
+  return 0; 
+  
+};
+
+//################################################################
+//
+// Extract either the complete list of variable or one of a specific
+// kind.
+//
+//################################################################
+
+Vector<Variable *>
+ConnectionState::get_variables(){  
+  return varlist; 
+};
+
+void *
+ConnectionState::get_data(VariableType t){  
+  
+  for (int i = 0; i < varlist.size(); i++){
+    Variable *v = varlist[i]; 
+    if (v->get_type() == t)
+      return v->get_data(); 
+  };
+  
+  return NULL;
+
+};
+
+
+CLICK_ENDDECLS
+ELEMENT_PROVIDES(ConnectionState)
+
Index: rna/elements/rna/rnaelement_connstate.hh
diff -u /dev/null rna/elements/rna/rnaelement_connstate.hh:1.1
--- /dev/null	Sun Jan 25 11:47:09 2009
+++ rna/elements/rna/rnaelement_connstate.hh	Fri Jun 27 10:40:59 2008
@@ -0,0 +1,99 @@
+/* 
+
+################################################################
+#                                                              #
+# (c) University of Southern California                        #
+#                                                              #
+#  See LICENSE.RNA for the complete license                    #
+#                                                              #
+################################################################
+
+*/
+#ifndef CLICK_CONNECTIONSTATE_HH
+#define CLICK_CONNECTIONSTATE_HH
+
+#include "rnaelement_common.hh" 
+
+//#########################################################
+//
+// Connection state information that is exchanged between protocols. A
+// pointer to the connection state is included in each message that is
+// retrieved and used by the next layer to determine the next steps. 
+//
+//#########################################################
+
+// The connection state consists of a set of variables. Each variable
+// has a type and value. A set of functions are supported to add and
+// delete variables. 
+
+//############################################
+// Variable definition
+//############################################
+
+enum VariableType{
+  VAR_UNKNOWN,
+  VAR_LINKINFO,
+  
+};
+
+class Variable {
+
+protected: 
+  VariableType var_type;// Type of this variable...
+  void *var_data;       // pointer to the memory
+  
+public: 
+  
+  Variable(VariableType t, void *data){
+    var_type = t; 
+    var_data = data; 
+  };
+
+  ~Variable() {
+  }
+  
+  void *get_data(){ 
+    return var_data; 
+  };
+  
+  void set_data (void *d) {
+    var_data = d; 
+  };
+
+  VariableType get_type(){ 
+    return var_type; 
+  };
+  
+  void set_type (VariableType t) {
+    var_type = t; 
+  };
+  
+};
+
+
+//############################################
+// Store and retrieve a set of variables.
+//############################################
+class ConnectionState { 
+
+public:
+  
+  ConnectionState();
+  ~ConnectionState();
+  
+  // Simple operations on the variables...
+  int add_variable(VariableType t, void *); 
+  int add_variable(Variable *v); 
+  int del_variable(int index);
+  int del_variable(Variable *v);
+  Vector<Variable *> get_variables(); 
+  void *get_data(VariableType t); 
+  
+ private:
+
+  Vector<Variable *> varlist; 
+
+};
+
+CLICK_ENDDECLS
+#endif
Index: rna/elements/rna/rnaelement_control.cc
diff -u /dev/null rna/elements/rna/rnaelement_control.cc:1.3
--- /dev/null	Sun Jan 25 11:47:09 2009
+++ rna/elements/rna/rnaelement_control.cc	Fri Dec 26 16:57:00 2008
@@ -0,0 +1,483 @@
+/* 
+
+################################################################
+#                                                              #
+# (c) University of Southern California                        #
+#                                                              #
+#  See LICENSE.RNA for the complete license                    #
+#                                                              #
+################################################################
+
+*/
+
+// The RNA control interface between layers and between modules within
+// a single module.
+
+//############################################################
+//
+// Process the control messages from the top and bottom 
+//
+//############################################################
+
+// This function is called if the default RNAElement::control()
+// function cannot handle the specific call. This is virtual and
+// overridden by modules.
+
+RNAControlMsg *
+RNAElement::module_specific_control(RNAControlMsg *c){
+  // Module-specific control 
+  (void)c; 
+  return NULL; 
+};
+
+// Give additional information that is used to update internal state.
+RNAControlMsg *
+RNAElement::control(RNAControlMsg *c){
+  
+  if (debug) 
+    rna_click_chatter(FUNC_ENTRY, "[%s] RNAElement::control Entered \n", 
+		      instance_name());
+  
+  bool handled_here = false; 
+
+  // Create a reply object and the default response...and fill it up.
+  RNAControlMsg *reply = new RNAControlMsg(RNAControlMsg::REPLY); 
+  reply->set_unsupported(); 
+  reply->set_error("NONE!"); 
+
+  // Sanity check...
+  if (!c){ 
+    reply->set_invalid(); 
+    reply->set_error("ControlMsg c is empty!"); 
+    rna_click_chatter(FUNC_EXIT, "[%s] RNAElement::control Exit \n", 
+		      instance_name());
+    return reply; 
+  };
+  
+  c->print(instance_name()); 
+
+  reply->set_operationtype(c->o);
+  switch(c->m) { 
+  case RNAControlMsg::COMMAND: 
+    switch(c->o){
+      
+    case RNAControlMsg::CONFIGURE: 
+      switch(c->op){
+      case RNAControlMsg::CONF_LINK_ADD:
+	do { 
+	  LinkState *l = (LinkState *)c->get_data();
+	  if (l) {
+	    l->print(instance_name());
+	    LinkState *l0 = check_for_duplicate_link(l);
+	    if (!l0) { 
+	      all_links.push_back(l);
+	    } else {
+	      rna_click_chatter(FUNC_EXIT, 
+				"[%s] RNAElement::control Found duplicate link\n", 
+				instance_name());
+	      merge_link_information(l0, l);
+	    };
+	    reply->set_success();
+	  } else {
+	    reply->set_error("LinkState (data) is NULL!");
+	    reply->set_invalid();
+	  };
+	  handled_here = true; 
+	} while (0); // To ensure that l is not visible outside..
+	break;
+
+      case RNAControlMsg::CONF_LINK_PROCESS:
+	do { 
+	  if (finish_configuration() >= 0) 
+	    reply->set_success(); 
+	  else 
+	    reply->set_failure();
+	} while(0); 
+	handled_here = true; 
+	break;
+      default: 
+	break; // Do nothing...
+      }; // CONFIGURE 
+      break; 
+
+    case RNAControlMsg::DISCOVER: 
+      switch(c->op){
+      case RNAControlMsg::DISC_ELEMENT:
+	do { 
+	  DiscoverCmd *d = static_cast<DiscoverCmd *>(c->get_data()); 
+	  if (d) { 
+	    switch(d->get_discover_type()){
+	    case DiscoverCmd::ELEMENT: 
+	      d->set_elem_type(type); 
+	      d->set_connection_oriented(connection_oriented); 
+	      d->print(); 
+	      // more stuff here about the element eventually..
+	      reply->set_data(d);
+	      reply->set_success(); 
+	      break; 
+	    default: 
+	      reply->set_error("Unsupported command");
+	      reply->set_invalid(); 
+	      break; 
+	    };
+	  } else {
+	    reply->set_error("Data is NULL");
+	    reply->set_invalid(); 
+	  }
+	} while(0); 
+	handled_here = true; 
+	break;
+      default: 
+	break; 
+      }
+      break; 
+
+    case RNAControlMsg::CONNECTION: 
+      switch(c->op){
+      case RNAControlMsg::CONN_OPEN:
+	do { 
+	  rna_click_chatter(FUNC_DEFAULT, 
+			    "[%s] connection_oriented = %s\n", 
+			    instance_name(), 
+			    (connection_oriented? "true":"false")); 
+	  if (connection_oriented) { 
+	    DiscoverCmd *d = new DiscoverCmd();
+	    if (conns.size() > 0) {
+	      reply->set_success(); 
+	      d->set_conn(conns[0]); 
+	    } else {
+	      if (open_connection()) {
+		reply->set_success(); 
+		d->set_conn(conns[0]); 
+	      } else {
+		reply->set_error("Could not open connection state"); 
+	      };
+	    };
+	    reply->set_data(d); 
+	  } else {
+	    reply->set_success(); 	    
+	    reply->set_data(NULL); 
+	  }; 
+	  
+	} while(0); 
+	handled_here = true; 
+	break;
+
+      default: 
+	break; 
+      };
+      break; 
+
+    default: 
+      break;// Do nothing..
+    }; // COMMAND
+    break;
+
+  default: 
+    break; 
+  };// MESSAGETYPE
+
+  // If this cannot be handled by the default handler, then call the
+  // module-specific handler. Notes for future: Module-specific
+  // handler may be called first instead. 
+  if (!handled_here) {
+    delete reply; 
+    reply = module_specific_control(c);
+  }
+
+  if (0 && debug) print_links(); 
+  if (0 && debug) reply->print(instance_name()); 
+  if (0 && debug) rna_click_chatter(FUNC_DEFAULT, 
+			   "[%s] RNAElement::control Exit \n", 
+			   this->instance_name());
+  return reply; 
+};
+
+
+//############################################################
+//
+// Lookup the outgoing links...
+//
+//############################################################
+
+//
+// Find the link that is to/from a specific port. 
+//
+
+LinkState *
+RNAElement::lookup_link(int port, bool incoming){
+  LinkState *link = NULL; 
+  
+  for (int i = 0; i < all_links.size(); i++){
+    LinkState *l = all_links[i];
+    
+    if (((incoming && l->dir == LinkState::INCOMING) 
+	 || (!incoming && l->dir == LinkState::OUTGOING)) 
+	&& l->local_port == port) {
+      link = l; 
+      break;
+    };
+  };
+  
+  if (!link) {
+    rna_click_chatter(FUNC_DEFAULT,
+		      "[%s] %s::lookup_link(port = %d) failed\n", 
+		      class_name(), instance_name(), port); 
+    if (debug) 
+      print_links();
+  };
+
+  return link; 
+  
+}
+
+//
+// Find the link that is to/from a specific element, if any.
+//
+
+LinkState *
+RNAElement::lookup_link(RNAElement *e, bool incoming){
+  LinkState *link = NULL; 
+  
+  for (int i = 0; i < all_links.size(); i++){
+    LinkState *l = all_links[i];
+    
+    if (((incoming && l->dir == LinkState::INCOMING) 
+	 || (!incoming && l->dir == LinkState::OUTGOING)) 
+	&& l->e == e) {
+      link = l; 
+      break;
+    };
+  };
+  
+  if (debug) { 
+    if (!link) {
+      rna_click_chatter(FUNC_DEFAULT,
+			"[%s] %s::lookup_link(element = %d) failed\n", 
+			class_name(), instance_name(), (int)e); 
+      print_links();
+    } else {
+      rna_click_chatter(FUNC_DEFAULT,
+			"[%s] %s::lookup_link(element = %d) successful\n", 
+			class_name(), instance_name(), (int)e);     
+      link->print(instance_name()); 
+    }
+  };
+
+  return link;   
+}
+
+
+// For each outgoing link, extract the connection state from the next
+// layer and store it. 
+void
+RNAElement::discover_connectionstate(LinkState *l){
+  
+  if (!l) 
+    return; 
+  
+  if (!l->is_initialized()) 
+    open_connection(l); 
+    
+  if (!l->connection_oriented) 
+    return; 
+    
+};
+
+
+
+//############################################################
+//
+// Initialize the link with connection state from the downstream
+// element. Discover the type of the downstream link. 
+//
+//############################################################
+
+void
+RNAElement::initialize_link(LinkState *l) {
+
+  if (debug) 
+    rna_click_chatter(FUNC_ENTRY,"[%s] initialize_link Entry\n", 
+		      instance_name()); 
+  
+  do { 
+
+    if (!l) 
+      break; 
+    
+    if (0) 
+      click_chatter("[%s] RNAElement::initialize_link Looking at link \n", 
+		    instance_name()); 
+    
+    if (l->is_initialized())
+      break; 
+
+    l->print(instance_name()); 
+    
+    Element *e = l->e;         
+    if (!e) 
+      break; 
+    
+    const char * remote_class_name = e->class_name();     
+    
+    if (debug) 
+      rna_click_chatter(FUNC_DEFAULT, 
+		      "[%s] RNAElement::initialize_link remote node = %s !\n",
+		      instance_name(), remote_class_name); 
+
+    if (strcmp(remote_class_name, "RNAElement") != 0){
+      l->set_initialized();
+    };
+
+    if (strcmp(remote_class_name, "RNAElement") == 0){
+      
+      RNAElement *erna = (RNAElement *)e->cast("RNAElement"); 
+      
+      if (debug) 
+	rna_click_chatter(FUNC_DEFAULT, 
+			  "[%s] Calling RNA module Control interface %s \n",
+			  instance_name(), erna->instance_name()); 
+      
+      if (l->elemtype == UNKNOWN) { 
+	// Discover 
+	DiscoverCmd *d = new DiscoverCmd(DiscoverCmd::ELEMENT);
+	RNAControlMsg *ctl = new RNAControlMsg(RNAControlMsg::COMMAND, 
+					       RNAControlMsg::DISCOVER, 
+					       RNAControlMsg::DISC_ELEMENT, 
+					     d);
+	RNAControlMsg *reply = erna->control(ctl);
+	
+	// Obtain the discover reply..
+	if ( ! reply || 
+	     reply->m != RNAControlMsg::REPLY || 
+	     reply->op != RNAControlMsg::REPL_SUCCESS){
+	  //l->set_initialized(); 
+	  l->print("Initialized Failed - Unknown element!"); 
+	  break; 
+	};
+	
+	DiscoverCmd *d1 = (DiscoverCmd *)reply->get_data();
+	if (!d1){ 
+	  l->print("Initialized Failed!"); 
+	  break; 
+	};
+	  
+	//Store somewhere...
+	d1->print(instance_name()); 
+	l->elemtype = d1->get_elem_type(); 
+	l->connection_oriented = d1->get_connection_oriented(); 
+	
+	if (!l->connection_oriented){
+	  l->set_initialized(); 
+	  l->print("Initialized"); 	  
+	};
+
+	// Cleanup 
+	delete d; 
+	delete reply; 
+      }; 
+      
+      if (l->elemtype != UNKNOWN && l->connection_oriented) { 
+	// If connection oriented, then we have open the connection at
+	// the next layer? 
+	
+	// connection data...
+	DiscoverCmd *d = new DiscoverCmd(DiscoverCmd::CONNECTION); 
+	RNAControlMsg *ctl = new RNAControlMsg(RNAControlMsg::COMMAND, 
+					       RNAControlMsg::CONNECTION, 
+					       RNAControlMsg::CONN_OPEN, 
+					       d);
+	RNAControlMsg *reply = erna->control(ctl); 
+	
+	// Obtain the discover reply..
+	if ( ! reply || 
+	     reply->m != RNAControlMsg::REPLY || 
+	     reply->op != RNAControlMsg::REPL_SUCCESS){
+	  //l->set_initialized(); 
+	  l->print("Initialized Failed! Discovery failed"); 
+	  break; 
+	};
+	
+	//obtain the connection state from the next layer...
+	d = (DiscoverCmd *)reply->get_data(); 
+	if (!d) { 
+	  //l->set_initialized(); 
+	  l->print("Initialized Failed! Reply data invalid"); 
+	  break; 
+	};
+	
+	l->connstate_set(d->get_conn()); 
+	l->set_initialized(); 
+	l->print("Initialized"); 
+	break; 
+      };
+      
+
+    }; // strcmd... 
+
+  } while(0); 
+  
+  if (debug) 
+    rna_click_chatter(FUNC_ENTRY,"[%s] initialize_link Exit\n", 
+		      instance_name()); 
+  
+  return; 
+
+};
+
+//############################################################
+//
+// Create the connection state 
+//
+//############################################################
+
+// If the incoming link is specified, then open connection 
+// to the endpoint of that link alone. If not open 
+// connections to all the next link layers. 
+bool
+RNAElement::open_connection(LinkState *incoming_link) {
+  
+  
+  if (0 && debug ) 
+    rna_click_chatter(FUNC_ENTRY,"[%s] open_connection Entry \n", 
+		      instance_name()); 
+  
+  if (0 && debug && incoming_link) 
+    incoming_link->print(instance_name()); 
+  
+  Vector<LinkState *> downstream; 
+  
+  if (! incoming_link) { 
+    downstream =   list_downstream_elements(true, // downstream
+					    false, // layeragnostic
+					    true, // crosslayer
+					    true,// agnostic remote
+					    false // remote is unknown
+					    );
+  } else {
+    if (incoming_link->is_outgoing() && 
+	incoming_link->is_crosslayer() && 
+	incoming_link->is_upstream() && 
+	!incoming_link->is_remote_unknown()) { 
+      downstream.push_back(incoming_link);
+    };
+  };
+  
+  if (0) 
+    rna_click_chatter(FUNC_ENTRY,"[%s] open_connection: "
+		      "Found %d downstream elements\n", 
+		      instance_name(), downstream.size()); 
+
+  for(int i = 0; i < downstream.size(); i++) {
+    LinkState *l = downstream[i];
+    initialize_link(l); 
+  };
+  
+  if (0) 
+    rna_click_chatter(FUNC_EXIT,"[%s] open_connection Exit\n", 
+		      instance_name()); 
+  
+  
+  return true; 
+
+};
Index: rna/elements/rna/rnaelement_ctlmsg.cc
diff -u /dev/null rna/elements/rna/rnaelement_ctlmsg.cc:1.2
--- /dev/null	Sun Jan 25 11:47:09 2009
+++ rna/elements/rna/rnaelement_ctlmsg.cc	Fri Dec 26 16:57:00 2008
@@ -0,0 +1,234 @@
+/* 
+
+################################################################
+#                                                              #
+# (c) University of Southern California                        #
+#                                                              #
+#  See LICENSE.RNA for the complete license                    #
+#                                                              #
+################################################################
+
+*/
+
+#include "rnaelement_ctlmsg.hh"
+
+const char *str_elementtype[] = {
+  QUOTE(ELEMTYPE_BEGIN), 
+  QUOTE(ANY), 
+  QUOTE(BUFFER),
+  QUOTE(CONTROL),
+  QUOTE(CRYPT),
+  QUOTE(DEMULTIPLEXOR),
+  QUOTE(DISCOVERY),
+  QUOTE(ENCRYPTION),
+  QUOTE(FLEXLINK), 
+  QUOTE(MULTIPLEXOR),
+  QUOTE(MULTITUNNEL),
+  QUOTE(MUXDEMUX),
+  QUOTE(NEGOTIATE),
+  QUOTE(NETSTACK),
+  QUOTE(OPTIONS),
+  QUOTE(PKTSRC),
+  QUOTE(REORDERBUFFER),
+  QUOTE(REXMIT),
+  QUOTE(RINGBUFFER), 
+  QUOTE(ROOT),
+  QUOTE(TUNNEL),
+  QUOTE(UNKNOWN), 
+  QUOTE(ELEMTYPE_END), 
+};
+
+RNAControlMsg::RNAControlMsg(MessageType m_in) : 
+  m(m_in), o(UNKNOWN), op(NOP), data(0) {
+  // Do nothing...
+}
+
+RNAControlMsg::RNAControlMsg(MessageType m_in, OperationType o_in, 
+			     Operation op_in, void *d_in): 
+    m(m_in), o(o_in), op(op_in), data(d_in) {
+}
+  
+RNAControlMsg::RNAControlMsg(RNAControlMsg& c) {
+  m = c.m;
+  o = c.o;
+  op = c.op; 
+  data = c.data; 
+}; 
+
+RNAControlMsg::~RNAControlMsg(){
+  // Do nothing...
+}; 
+
+void 
+RNAControlMsg::print(const char *s) {
+      
+  char *m_arr[] = { 
+    QUOTE(NONE),
+    QUOTE(COMMAND), 
+    QUOTE(REPLY),
+    QUOTE(LAST_MTYPE),
+  };
+  
+  char *o_arr[] = { 
+    QUOTE(UNKNOWN), 
+    QUOTE(CONFIGURE), 
+    QUOTE(CONNECTION), 
+    QUOTE(MUX), 
+    QUOTE(DISCOVER), 
+    QUOTE(LAST_OPTYPE),
+  }; 
+  
+  char *op_arr[] = { 
+    QUOTE(NOP),               
+    QUOTE(CONF_LINK_ADD), 
+    QUOTE(CONF_LINK_DELETE), 
+    QUOTE(CONF_LINK_PROCESS), 
+    QUOTE(CONN_OPEN), 
+    QUOTE(CONN_CLOSE),    
+    QUOTE(DEMUX_PATTERN_ADD), 
+    QUOTE(DEMUX_PATTERN_DEL), 
+    QUOTE(MUX_PATTERN_ADD), 
+    QUOTE(MUX_PATTERN_DEL), 
+    QUOTE(DISC_ELEMENT), 
+    QUOTE(REPL_INVALID), 
+    QUOTE(REPL_SUCCESS), 
+    QUOTE(REPL_FAILURE),
+    QUOTE(REPL_UNSUPPORTED),
+    QUOTE(LAST_OP),
+  }; 
+    
+  if ((m >= NONE && m < LAST_MTYPE) && 
+      (o >= UNKNOWN && o < LAST_OPTYPE) && 
+      (op >= NOP && op < LAST_OP)) 
+    click_chatter("[%s] Control Message %s %s %s %x error = %s\n", 
+		  (s ? s : ""),
+		  m_arr[m], o_arr[o], op_arr[op], 
+		  (caddr_t)data, error.c_str());
+  else 
+    click_chatter("[CONTROL] Misconfigured message \n");
+  
+  return;
+  
+};
+
+// Update the operation 
+int 
+RNAControlMsg::set_messagetype(MessageType m_in){
+  if (m_in >= NONE && m_in < LAST_MTYPE){ 
+    m = m_in; 
+    return 0; 
+  } else {
+    return -1; 
+  }
+};
+
+// Update the operation 
+int 
+RNAControlMsg::set_operationtype(OperationType o_in){
+  if (o_in >= UNKNOWN && o_in < LAST_OPTYPE){ 
+    o = o_in; 
+    return 0; 
+  } else {
+    return -1; 
+  }
+};
+
+
+// Update the operation 
+int 
+RNAControlMsg::set_operation(Operation op_in){
+
+  if (op_in >= NOP && op_in < LAST_OP){ 
+    op = op_in; 
+    return 0; 
+  } else {
+    return -1; 
+  }
+}
+
+void *
+RNAControlMsg::get_data() { 
+  return data; 
+};
+
+int 
+RNAControlMsg::set_data(void *d_in){
+  data = d_in; 
+  return 0; 
+};
+
+
+// Some short cuts....
+void 
+RNAControlMsg::set_unsupported(){
+  if (m == REPLY) 
+    op = REPL_UNSUPPORTED;
+}; 
+
+// Some short cuts....
+void 
+RNAControlMsg::set_failure(){
+  if (m = REPLY) 
+    op = REPL_FAILURE; 
+}; 
+
+// Some short cuts....
+void 
+RNAControlMsg::set_invalid(){
+  if (m = REPLY) 
+    op = REPL_INVALID; 
+}; 
+
+// Some short cuts....
+void 
+RNAControlMsg::set_success(){
+  if (m = REPLY) 
+    op = REPL_SUCCESS; 
+};
+
+// Store error message along with the error state...
+void 
+RNAControlMsg::set_error(const char *s){
+  error = s; 
+}; 
+
+void 
+DiscoverCmd::set_conn_array(Vector<ConnectionState *> conn_array_in){
+  conn_array.clear(); 
+  for(int i = 0; conn_array_in.size(); i++){
+    conn_array.push_back(conn_array_in[i]);
+  };
+};
+
+void 
+DiscoverCmd::set_elem_array(Vector<RNAElement *> elem_array_in){
+  elem_array.clear(); 
+  for(int i = 0; elem_array_in.size(); i++){
+    elem_array.push_back(elem_array_in[i]);
+  };
+};     
+
+void 
+DiscoverCmd::print(const char *s) {
+        
+  char *m_arr[] = {
+    QUOTE(ELEMENT), 
+    QUOTE(CONNECTION)
+  };
+  
+  char *bool_arr[] = {
+    "FALSE", 
+    "TRUE"
+  };
+  
+  click_chatter("[%s] DiscoverCmd type = %s, type = %s "
+		"connoriented = %s",
+		(s ? s : ""),
+		m_arr[dtype],
+		str_elementtype[elemtype],
+		bool_arr[connection_oriented]
+		); 
+};
+
+CLICK_ENDDECLS
+ELEMENT_PROVIDES(RNAControlMsg)
Index: rna/elements/rna/rnaelement_ctlmsg.hh
diff -u /dev/null rna/elements/rna/rnaelement_ctlmsg.hh:1.2
--- /dev/null	Sun Jan 25 11:47:09 2009
+++ rna/elements/rna/rnaelement_ctlmsg.hh	Fri Dec 26 16:57:00 2008
@@ -0,0 +1,142 @@
+/* 
+
+################################################################
+#                                                              #
+# (c) University of Southern California                        #
+#                                                              #
+#  See LICENSE.RNA for the complete license                    #
+#                                                              #
+################################################################
+
+*/
+#ifndef CLICK_RNACONTROLMSG_HH
+#define CLICK_RNACONTROLMSG_HH
+
+class LinkState; 
+
+#include "rnaelement.hh"
+
+class RNAControlMsg { 
+
+public: 
+  
+  enum MessageType { NONE, COMMAND, REPLY, LAST_MTYPE }; 
+  enum OperationType { UNKNOWN, CONFIGURE, CONNECTION, 
+		       MUX, DISCOVER, NEGOTIATE, LAST_OPTYPE }; 
+  enum Operation { 
+    NOP,                                  // NONE 
+    CONF_LINK_ADD, CONF_LINK_DELETE, CONF_LINK_PROCESS,   // Configure 
+    CONN_OPEN, CONN_CLOSE,                // Connection State 
+    DEMUX_PATTERN_ADD, DEMUX_PATTERN_DEL,     // Add/del matching patterns 
+    MUX_PATTERN_ADD, MUX_PATTERN_DEL,     // Add/del matching patterns 
+    DISC_ELEMENT,                         // Discover what? 
+    REPL_INVALID, REPL_SUCCESS, REPL_FAILURE,// Reply status 
+    REPL_UNSUPPORTED,
+    LAST_OP,
+  }; 
+  
+  MessageType m;
+  OperationType o; 
+  Operation op;
+  String error; 
+  void *data; 
+
+  // Constructor/Destructor..
+  RNAControlMsg(MessageType m_in); 
+  RNAControlMsg(MessageType m_in, OperationType o_in, 
+		Operation op_in, void *d_in = NULL);
+  RNAControlMsg(RNAControlMsg& c);
+  ~RNAControlMsg(); 
+
+  // 
+  void print(const char *s = NULL); 
+  int set_messagetype(MessageType m_in);
+  int set_operationtype(OperationType o_in);
+  int set_operation(Operation op_in);  
+  
+  // Set/get the data 
+  void *get_data();  
+  int set_data(void *d_in);
+  
+  // 
+  void set_error(const char *s);
+
+  // Some short cuts....
+  void set_unsupported();
+  void set_failure();
+  void set_invalid();
+  void set_success();
+  
+};
+
+
+
+class DiscoverCmd { 
+public: 
+  enum DiscoverType { ELEMENT, CONNECTION };
+  
+  // Discover what? 
+  DiscoverType dtype; 
+  
+  // About this element
+  RNAElementType elemtype; 
+  bool connection_oriented; 
+  
+  // About the connections...
+  ConnectionState *conn; 
+  Vector<ConnectionState *> conn_array; 
+  Vector<RNAElement *> elem_array; 
+
+  DiscoverCmd(DiscoverType t): dtype(t), elemtype(UNKNOWN), 
+			       connection_oriented(false), conn(0) {}; 
+
+  DiscoverCmd(): dtype(ELEMENT), elemtype(UNKNOWN), conn(0) {}; 
+  ~DiscoverCmd() {};
+
+  ConnectionState *get_conn() { return conn; };
+  void set_conn(ConnectionState *conn_in) { conn = conn_in; return; };
+
+  DiscoverType get_discover_type() { return dtype; };
+  void set_discover_type(DiscoverType t) { dtype = t; return; };
+
+  bool get_connection_oriented() { return connection_oriented; } 
+  void set_connection_oriented(bool v) { connection_oriented = v;  };
+
+  RNAElementType get_elem_type() { return elemtype; };
+  void set_elem_type(RNAElementType t) { elemtype = t; };
+
+  
+  void set_conn_array(Vector<ConnectionState *> conn_array_in);
+  void set_elem_array(Vector<RNAElement *> elem_array_in);
+  
+  void print(const char *s = NULL);
+
+};
+
+
+class MuxDemuxCmd {
+public: 
+  const char *pattern; 
+  int len; 
+  RNAElement *e; 
+  LinkState *l; 
+  MuxDemuxCmd () {} 
+  void print(char *s = NULL){
+    click_chatter("[MuxDemuxCmd] %s pattern = %s, e = %x  \n", 
+		  (s? s : ""), pattern, e);
+    return; 
+  }
+};
+
+class NegotiateCmd {
+public: 
+  Vector<RNAElement *> *_elemlist; 
+  String _initpattern; 
+  NegotiateCmd(Vector<RNAElement *> *elemlist, String initpattern) {
+    _elemlist = elemlist; 
+    _initpattern = initpattern;
+  };
+  
+};
+CLICK_ENDDECLS
+#endif
Index: rna/elements/rna/rnaelement_error.cc
diff -u /dev/null rna/elements/rna/rnaelement_error.cc:1.1
--- /dev/null	Sun Jan 25 11:47:09 2009
+++ rna/elements/rna/rnaelement_error.cc	Fri Jun 27 10:40:59 2008
@@ -0,0 +1,33 @@
+/* 
+
+################################################################
+#                                                              #
+# (c) University of Southern California                        #
+#                                                              #
+#  See LICENSE.RNA for the complete license                    #
+#                                                              #
+################################################################
+
+*/
+
+#include "rnaelement_common.hh" 
+#include "rnaelement_error.hh"
+
+void
+rna_click_chatter(ErrorClass x, const char *fmt, ...)
+{
+  (void)x; 
+
+  va_list ap; 
+  va_start(ap, fmt);
+#ifdef COMMENT
+  click_chatter(fmt, ap); 
+#endif   
+  vfprintf(stderr, fmt, ap); 
+  va_end(ap); 
+
+}
+
+
+CLICK_ENDDECLS
+ELEMENT_PROVIDES(RNAError)
Index: rna/elements/rna/rnaelement_error.hh
diff -u /dev/null rna/elements/rna/rnaelement_error.hh:1.1
--- /dev/null	Sun Jan 25 11:47:09 2009
+++ rna/elements/rna/rnaelement_error.hh	Fri Jun 27 10:40:59 2008
@@ -0,0 +1,30 @@
+/* 
+
+################################################################
+#                                                              #
+# (c) University of Southern California                        #
+#                                                              #
+#  See LICENSE.RNA for the complete license                    #
+#                                                              #
+################################################################
+
+*/
+#ifndef CLICK_RNAERROR_HH
+#define CLICK_RNAERROR_HH
+
+#include "rnaelement_common.hh" 
+
+enum ErrorClass { 
+  FUNC_ENTRY,
+  FUNC_EXIT, 
+  FUNC_DEFAULT,
+  MESSAGE,
+  MYDATA,
+  ERROR,
+};
+
+void
+rna_click_chatter(ErrorClass x, const char *fmt, ...); 
+
+CLICK_ENDDECLS
+#endif
Index: rna/elements/rna/rnaelement_handlers.cc
diff -u /dev/null rna/elements/rna/rnaelement_handlers.cc:1.1
--- /dev/null	Sun Jan 25 11:47:09 2009
+++ rna/elements/rna/rnaelement_handlers.cc	Fri Jun 27 10:40:59 2008
@@ -0,0 +1,92 @@
+/* 
+
+################################################################
+#                                                              #
+# (c) University of Southern California                        #
+#                                                              #
+#  See LICENSE.RNA for the complete license                    #
+#                                                              #
+################################################################
+
+*/
+
+//==============================================================
+//
+// Allow processing of element names as argument to the element
+//
+//==============================================================
+void
+RNAElement::static_initialize_default()
+{
+ 
+  //rna_click_chatter(FUNC_DEFAULT,"RNAElement::static_initialize()\n"); 
+
+  cp_register_argtype("ELEMENTS", 
+		      "list of elements", 
+		      cpArgNormal, 
+		      elementlist_parse, 
+		      elementlist_store, 
+		      0);
+
+};
+
+void
+RNAElement::static_cleanup_default()
+{
+
+  rna_click_chatter(FUNC_DEFAULT,"RNAElement::static_cleanup()\n"); 
+  cp_unregister_argtype("ELEMENTS");
+}
+
+int
+RNAElement::rna_write_handler(const String &conf, Element *e, 
+			      void *vparam, ErrorHandler *errh)
+{
+  (void)vparam; 
+  (void)errh; 
+
+  RNAElement *erna = (RNAElement *)(e->cast("RNAElement")); 
+
+  rna_click_chatter(FUNC_DEFAULT,
+		    "[%s] RNAElement::rna_write_handler String = %s \n", 
+		    erna->instance_name(), 
+		    conf.printable().c_str());
+  
+  return 1; 
+}
+
+String
+RNAElement::rna_read_handler(Element *e, void *thunk)
+{
+  (void)thunk;
+    
+  RNAElement *erna = (RNAElement *)(e->cast("RNAElement")); 
+
+  rna_click_chatter(FUNC_DEFAULT,
+		    "[%s] RNAElement::rna_read_handler String = %s \n", 
+		    erna->instance_name(),
+		    erna->instance_name());
+  
+  return String(erna->instance_name());
+  
+}
+
+void
+RNAElement::add_handlers()
+{
+  //rna_click_chatter(FUNC_DEFAULT,"RNAElement::add_handlers()\n"); 
+  add_read_handler("control", rna_read_handler, (void *)0);
+  add_write_handler("control", rna_write_handler, (void *)0);
+}
+
+
+void *
+RNAElement::cast(const char *n)
+{
+  if (strcmp(n, "RNAElement") == 0)
+    return (RNAElement *) this;
+  else
+    return 0;
+}
+
+
Index: rna/elements/rna/rnaelement_links.cc
diff -u /dev/null rna/elements/rna/rnaelement_links.cc:1.2
--- /dev/null	Sun Jan 25 11:47:09 2009
+++ rna/elements/rna/rnaelement_links.cc	Fri Dec 26 16:57:00 2008
@@ -0,0 +1,580 @@
+/* 
+
+################################################################
+#                                                              #
+# (c) University of Southern California                        #
+#                                                              #
+#  See LICENSE.RNA for the complete license                    #
+#                                                              #
+################################################################
+
+*/
+
+//###############################################################
+//
+// Link information processing - check, merge, print etc. 
+// Misc functions. 
+//
+//###############################################################
+
+
+// Delete only if the linkcmd pointer points to a legitimate link.
+int RNAElement::delete_link(LinkState *l){
+  
+  int match = -1; 
+
+  if (!l) 
+    return match; 
+  
+  for (int i = 0; i < all_links.size(); i++){
+    LinkState *l0 = all_links[i];
+    if (l0 == l) {
+      match = i; 
+      break; 
+    };
+  };
+  
+  if (match < 0) 
+    return -1; 
+  
+  all_links[match] = all_links.back(); 
+  all_links.pop_back(); 
+
+  return 0; 
+}
+
+LinkState *
+RNAElement::check_for_duplicate_link(LinkState *l){
+
+  LinkState *match = NULL; 
+  
+  if (!l) 
+    return match; 
+  
+  for (int i = 0; i < all_links.size(); i++){
+    LinkState *l0 = all_links[i];
+    if (l0->minimal_match(l)){
+      match = l0; 
+      break; 
+    };
+  };
+
+  return match; 
+}
+
+void 
+RNAElement::merge_link_information(LinkState *existing_link, LinkState *newlink){
+  
+  // Update only the element information 
+  if ( !existing_link || !newlink) 
+    return; 
+
+  // Only the remote element and port are updated and that 
+  // only when the local information is UNKNOWN 
+  if (existing_link->is_remote_unknown()) {
+    existing_link->remote_port = newlink->remote_port; 
+    existing_link->e = newlink->e; 
+  };
+  
+  return; 
+};
+
+
+//###############################################################
+//
+// Print the link information for this/all element(s). These functions
+// go through each type of link and prints them - incoming/outgoing
+// and intra/cross layer.
+//
+//###############################################################
+void
+RNAElement::print_links(){
+  
+  if (0) rna_click_chatter(FUNC_ENTRY,
+			   "[%s] RNAElement::print_links Enter\n", 
+			   instance_name());
+  
+  for (int j = 0; j < 4; j++) { 
+
+    for (int i = 0; i < all_links.size(); i++){
+      LinkState *l = all_links[i];
+      
+      switch(j){ 
+      case 0: 
+	if (l->is_downstream() && l->dir == LinkState::INCOMING )
+	  l->print(instance_name()); 
+	break; 
+      case 1: 
+	if (!l->is_downstream() && l->dir == LinkState::INCOMING )
+	  l->print(instance_name()); 
+	break; 
+      case 2: 
+	if (l->is_downstream() && l->dir == LinkState::OUTGOING )
+	  l->print(instance_name()); 
+	break; 
+      case 3: 
+	if (!l->is_downstream() && l->dir == LinkState::OUTGOING )
+	  l->print(instance_name()); 
+	break; 
+      default: 
+	break; 
+      };
+    };
+
+  };
+
+  if (0) rna_click_chatter(FUNC_EXIT, 
+		    "[%s] RNAElement::print_links Exit \n", 
+		    instance_name());
+
+};
+
+void
+RNAElement::print_allelements_links(){
+  
+  rna_click_chatter(FUNC_ENTRY,
+		    "[%s] All links to and from element\n", 
+		    instance_name());
+  
+ // List all the possible elements;
+  Vector<Element*> allelements = router()->elements();
+
+  // For each element look through all the outputs...
+  for (int i = 0; i < allelements.size(); i++){
+    Element *e = allelements[i];
+    if (strcmp(e->class_name(), "RNAElement") == 0){
+      RNAElement *e1 = static_cast<RNAElement *>(e->cast("RNAElement"));
+      e1->print_links();
+    };
+  };
+
+  rna_click_chatter(FUNC_EXIT, 
+		    "[%s] RNAElement::print_allelement_links Exit \n", 
+		    instance_name());
+
+};
+
+
+//###############################################################
+//
+// Process link information during configuration phase.
+//
+// Look at all the links going in and out of the element and add them
+//
+// This function is supposed to autodetect the links including
+// crosslayer functionality and upstream/downstream-ness. This is
+// right now incomplete. The upstream/downstream is not handled right
+// now. The cross layer is not detected either.
+//
+//###############################################################
+
+int 
+RNAElement::add_default_autodetect_links(Vector <struct linkspec *> *links, 
+					 bool crosslayer){
+  
+  struct linkspec *link;
+
+  if (_preconfigured_element_list) { 
+    
+    click_chatter("[%s] RNAElement::add_default_autodetect_links - "
+		  "Found preconf element list \n",
+		  instance_name());
+    
+    
+    // Take care of incoming links from upstream nodes...
+    for(int i = 0; i < _upstream_element_list.size(); i++){
+      Element *upstream_e = _upstream_element_list[i]; 
+      for (int p = 0; p < upstream_e->noutputs(); p++){
+	if (upstream_e->output(p).element() == this){
+
+	  link = new linkspec;
+	  link->local_elem  =  upstream_e->eindex();
+	  link->local_out   =  p; 
+	  link->remote_elem = this->eindex(); 
+	  link->remote_in   = upstream_e->output(p).port(); 
+	  link->local_is_upstream = true; 
+	  link->crosslayer = crosslayer; 
+	  links->push_back(link);   
+	};
+      }; 
+    };
+
+    // Take care of incoming links from downstream nodes..
+    for(int i = 0; i < _downstream_element_list.size(); i++){
+      Element *downstream_e = _downstream_element_list[i]; 
+      for (int p = 0; p < downstream_e->noutputs(); p++){
+	if (downstream_e->output(p).element() == this){
+
+	  link = new linkspec;
+	  link->local_elem  =  downstream_e->eindex();
+	  link->local_out   =  p; 
+	  link->remote_elem = this->eindex(); 
+	  link->remote_in   = downstream_e->output(p).port(); 
+	  link->local_is_upstream = false; 
+	  link->crosslayer = crosslayer; 
+	  links->push_back(link);   
+	};
+      }; 
+    };
+
+    
+    // Take care of outgoing links...
+    for (int j = 0; j < noutputs(); j++){ 
+      
+      link = new linkspec;
+      link->local_elem  =  this->eindex(); 
+      link->local_out   =  j; 
+      
+      Element *remote_e = output(j).element(); 
+      if (remote_e) { 
+	link->remote_elem =  remote_e->eindex();
+	link->remote_in   =  output(j).port();    
+      } else { 
+	link->remote_elem =  -1;
+	link->remote_in   =  -1;
+      };
+
+      if (!remote_e)
+	click_chatter("[%s] remote_e is NULL \n", instance_name()); 
+    
+      // XXX How do I know which is upstream? 
+      //      link->local_is_upstream = true; 
+
+      for (int j = 0; j < _upstream_element_list.size(); j++){
+	if (_upstream_element_list[j] == remote_e) { 
+	  link->local_is_upstream = false; 
+	  break;
+	};
+      }; 
+
+      for (int j = 0; j < _downstream_element_list.size(); j++){
+	if (_downstream_element_list[j] == remote_e) { 
+	  link->local_is_upstream = true; 
+	  break;
+	};
+      }; 
+      
+
+      link->crosslayer = crosslayer; 
+      links->push_back(link); 
+    };
+    
+  } else {
+
+    // Could be wrong! Needs to be checked.
+    bool crosslayer = true; 
+    
+    for (int i = 0; i < ninputs(); i++){ 
+      link = new linkspec;
+      
+      //link->local_elem  =  -1; 
+      //link->local_out   =  -1; 
+      Element *local_e = input(i).element(); 
+      if (local_e) { 
+	link->local_elem =  local_e->eindex();
+	link->local_out   =  input(i).port();    
+      } else { 
+	link->local_elem =  -1;
+	link->local_out   =  -1;
+      };
+      link->remote_elem =  this->eindex();
+      link->remote_in   =  i;
+      
+      // XXX How do I know which is upstream? 
+      link->local_is_upstream = true; 
+      link->crosslayer = crosslayer; 
+      links->push_back(link);   
+      
+    };
+    
+    for (int j = 0; j < noutputs(); j++){ 
+      
+      link = new linkspec;
+      link->local_elem  =  this->eindex(); 
+      link->local_out   =  j; 
+      
+      Element *remote_e = output(j).element(); 
+      if (remote_e) { 
+	link->remote_elem =  remote_e->eindex();
+	link->remote_in   =  output(j).port();    
+      } else { 
+	link->remote_elem =  -1;
+	link->remote_in   =  -1;
+      };
+    
+      // XXX How do I know which is upstream? 
+      link->local_is_upstream = true; 
+      link->crosslayer = crosslayer; 
+      links->push_back(link); 
+    };
+  };
+
+  
+  return 0; 
+  
+};
+//###############################################################
+//
+// Process link information during configuration phase.
+//
+//                             WAIT!!!! 
+// This function makes assumptions about the specific links being added
+// and their port numbers. So use this function with caution..
+//
+//###############################################################
+
+int 
+RNAElement::add_default_bidirectional_links(Vector <struct linkspec *> *links,
+					    bool crosslayer){
+  
+  
+  struct linkspec *link;
+  
+  //=================================================
+  // All other non-RNAElement connections 
+  // These are fixed and known ahead of time...
+  //src -> [0] r1 [1] -> [0] l
+  // l[0] -> Print -> [1] r1 [0] -> Discard
+
+  //=============================
+
+  // src -> r1 [0] 
+  link = new linkspec;
+
+  //link->local_elem  =  -1; 
+  //link->local_out   =  -1; 
+  Element *local_e = input(0).element(); 
+  if (local_e) { 
+    link->local_elem =  local_e->eindex();
+    link->local_out   =  input(0).port();    
+  } else { 
+    link->local_elem =  -1;
+    link->local_out   =  -1;
+  };
+  link->remote_elem =  this->eindex();
+  link->remote_in   =  0;
+  link->local_is_upstream = true; 
+  link->crosslayer = crosslayer; 
+  links->push_back(link); 
+
+  //=============================
+  
+  // r1 [1] -> [0]l
+  link = new linkspec;
+  link->local_elem  =  this->eindex(); 
+  link->local_out   =  1; 
+
+  Element *remote_e = output(1).element(); 
+  if (remote_e) { 
+    link->remote_elem =  remote_e->eindex();
+    link->remote_in   =  output(1).port();    
+  } else { 
+    link->remote_elem =  -1;
+    link->remote_in   =  -1;
+  };
+
+  link->local_is_upstream = true; 
+  link->crosslayer = crosslayer; 
+  links->push_back(link); 
+
+  //=============================
+    
+  // Print -> [1] r1
+  link = new linkspec;
+
+  //link->local_elem  =  -1;
+  //link->local_out   =  -1; 
+  local_e = input(1).element(); 
+  if (local_e) { 
+    link->local_elem =  local_e->eindex();
+    link->local_out   =  input(1).port();    
+  } else { 
+    link->local_elem =  -1;
+    link->local_out   =  -1;
+  };
+  link->remote_elem =  this->eindex();
+  link->remote_in   =  1;
+  link->local_is_upstream = false; 
+  link->crosslayer = crosslayer; 
+  links->push_back(link); 
+
+  //=============================  
+  
+  // r1 [0] -> Discard
+  link = new linkspec;
+  link->local_elem  =  this->eindex();
+  link->local_out   =  0; 
+
+  remote_e = output(0).element(); 
+  if (remote_e) { 
+    link->remote_elem =  remote_e->eindex();
+    link->remote_in   =  output(0).port();    
+  } else { 
+    link->remote_elem =  -1;
+    link->remote_in   =  -1;
+  };
+
+  link->local_is_upstream = false; 
+  link->crosslayer = crosslayer; 
+  links->push_back(link); 
+  
+  return 0;
+
+}
+
+//###############################################################
+//
+//                             WAIT!!!! 
+// This function makes assumptions about the specific links being added
+// and their port numbers. So use this function with caution..
+//
+//###############################################################
+
+int 
+RNAElement::add_default_unidirectional_links(Vector <struct linkspec *> *links,
+					     bool crosslayer){
+  
+  struct linkspec *link;
+  
+  //=================================================
+  // All other non-RNAElement connections 
+  // These are fixed and known ahead of time...
+  //src -> [0] r1 [0] -> dst 
+  
+  // src -> Ctl [0] 
+  link = new linkspec;
+  link->local_elem  =  -1; 
+  link->local_out   =  -1; 
+  link->remote_elem =  this->eindex();
+  link->remote_in   =  0;
+  link->local_is_upstream = true; 
+  link->crosslayer = crosslayer; 
+  links->push_back(link); 
+  
+  // Ctl [0] -> Discard
+  link = new linkspec;
+  link->local_elem  =  this->eindex();
+  link->local_out   =  0; 
+
+  Element *remote_e = output(0).element(); 
+  if (remote_e) { 
+    link->remote_elem =  remote_e->eindex();
+    link->remote_in   =  output(0).port();    
+  } else { 
+    link->remote_elem =  -1;
+    link->remote_in   =  -1;
+  };
+
+  link->local_is_upstream = true; 
+  link->crosslayer = crosslayer; 
+  links->push_back(link); 
+  
+  return 0;
+
+}
+
+
+//###############################################################
+//
+// Macro processors for adding links
+//
+//###############################################################
+
+int RNAElement::process_linkspecs(Vector<struct linkspec *> &linkspecs){
+  
+  if (debug) 
+    rna_click_chatter(FUNC_ENTRY, 
+		      "[%s] RNAElement::process_linkspecs \n", 
+		      instance_name());
+
+  Router *r = router(); 
+  for (int i = 0; i < linkspecs.size(); i++){
+
+    struct linkspec *l = linkspecs[i]; 
+    
+    // Initialize...the elements and the link command structures...
+    RNAElement *e0 = NULL, *e1 = NULL;
+    l->l0 = l->l1 = 0; 
+
+    if (l->local_elem >= 0) 
+      e0 = (RNAElement *) 
+	((r->element(l->local_elem))->cast("RNAElement")); 
+
+    if (l->remote_elem >= 0) 
+      e1 = (RNAElement *) 
+	((r->element(l->remote_elem))->cast("RNAElement")); 
+    
+    // Add this link only if both the end points are defined.
+    // Pre-existing links are just accounted for in the all_links
+    // structure and not added.
+    if (l->local_elem >= 0 && l->remote_elem >= 0) { 
+      int retval = r->add_connection(l->local_elem, 
+				     l->local_out,
+				     l->remote_elem, 
+				     l->remote_in); 
+      
+      rna_click_chatter(FUNC_DEFAULT,
+			"[%s] Add_connection [retval = %d]:\t"
+			"%s [%d,%d, %s]\t->"
+			"\t[%d,%d,%s] %s \n", 
+			instance_name(),
+			retval, (e0? e0->instance_name(): "UNKNOWN"), 
+			l->local_elem, l->local_out, 
+			(l->local_is_upstream? "UPSTREAM" : "DOWNSTREAM"),
+			l->remote_elem, l->remote_in, 
+			(l->local_is_upstream? "DOWNSTREAM" : "UPSTREAM"),
+			(e1 ? e1->instance_name() : "UNKNOWN"));
+    };
+
+    // e0 --> e1. if e0 is upstream node, then local_is_upstream will
+    // be set.
+
+    // Tell e0 that this is an outgoing link to e1.
+    if (e0) { 
+      LinkState *l0 = new LinkState(true, // outgoing
+				l->local_is_upstream,
+				l->local_out,
+				l->remote_in, 
+				l->crosslayer, 
+				e1);
+      RNAControlMsg c(RNAControlMsg::COMMAND, 
+		      RNAControlMsg::CONFIGURE, 
+		      RNAControlMsg::CONF_LINK_ADD, 
+		      l0);       
+      e0->control(&c); 
+
+      // Return the linkcmd created...
+      l->l0 = l0; 
+    };
+
+    // Tell e1 that this is an incoming link from e0
+    if (e1) { 
+      LinkState *l1 = new LinkState(false, // incoming 
+				!l->local_is_upstream, 
+				l->remote_in, 
+				l->local_out,
+				l->crosslayer, 
+				e0);
+      RNAControlMsg c(RNAControlMsg::COMMAND, 
+		      RNAControlMsg::CONFIGURE, 
+		      RNAControlMsg::CONF_LINK_ADD, 
+		      l1);
+      
+      e1->control(&c); 
+
+      // Return the linkcmd created...
+      l->l1 = l1;
+
+    }; 
+
+  };
+
+  // Commit the changes 
+  int retval  = r->update_connections(); 
+  rna_click_chatter(FUNC_DEFAULT, 
+		    "[%s] RNAElement::process_linkspecs updated connections: "
+		    "retval = %d \n", 
+		    instance_name(), retval);
+  
+  return 0; 
+};
Index: rna/elements/rna/rnaelement_linkstate.cc
diff -u /dev/null rna/elements/rna/rnaelement_linkstate.cc:1.1
--- /dev/null	Sun Jan 25 11:47:09 2009
+++ rna/elements/rna/rnaelement_linkstate.cc	Fri Jun 27 10:40:59 2008
@@ -0,0 +1,232 @@
+/* 
+
+################################################################
+#                                                              #
+# (c) University of Southern California                        #
+#                                                              #
+#  See LICENSE.RNA for the complete license                    #
+#                                                              #
+################################################################
+
+*/
+
+#include "rnaelement_linkstate.hh" 
+
+//############################################################
+//
+// Constructor and destructor...of LinkState...
+// 
+//############################################################
+
+//
+// Instantiate an empty link. This is not used in general. 
+//
+LinkState::LinkState() {
+
+  dir = NODIR;
+  type = NOTYPE;
+  local_port = -1;
+  remote_port = -1;
+  crosslayer = true; 
+  e = 0;
+  ltype = LINK_TYPE_DATA;
+  initialized = false;
+  connection_oriented = false; 
+  elemtype = UNKNOWN;
+  conns.clear();
+  initialized = true; 
+
+};
+
+//
+// Instantiate a link with all the information. We dont however
+// instantiate the connection state from the next layer. That is
+// obtained explicitly through the open_connection() function.
+//
+LinkState::LinkState (bool outgoing, 
+		      bool upstream, 
+		      int local_port_in, 
+		      int remote_port_in,
+		      bool crosslayer_in, 
+		      RNAElement *e_in, 
+		      bool control){ 
+
+  dir = outgoing? OUTGOING : INCOMING; 
+  type = upstream ? UPSTREAM : DOWNSTREAM; 
+  local_port = local_port_in;  
+  remote_port = remote_port_in;
+  crosslayer = crosslayer_in;
+  e = e_in;
+  ltype = (control? LINK_TYPE_CONTROL: LINK_TYPE_DATA);
+  initialized = false;
+  connection_oriented = false;
+  elemtype = UNKNOWN;
+  conns.clear(); 
+    
+  if (!e) 
+    initialized = true; 
+  else 
+    initialized = false; 
+  
+};
+
+//
+// Make a copy of the state of the link. 
+//
+
+LinkState::LinkState (LinkState &l) { 
+  dir = l.dir; 
+  type = l.type; 
+  remote_port = l.remote_port; 
+  local_port = l.local_port;
+  crosslayer = l.crosslayer; 
+  e = l.e; 
+  initialized = l.initialized; 
+  connection_oriented = l.connection_oriented; 
+  elemtype = l.elemtype; 
+  conns = l.conns;
+};
+
+//
+// Cleanup including the connection state. This simply updates the
+// local state. There is change in the state stored in the router
+// itself. 
+//
+LinkState::~LinkState() {
+  // Do nothing...
+};
+
+
+//
+// User-readable message 
+//
+void 
+LinkState::print(const char *s) {
+  
+  rna_click_chatter(MYDATA, "[LINK] <<%s, %s, %s link, %s >> "
+		    "[%s local, %d port] %s [%s remote, %d port]]\n",
+		    (initialized? "INIT=YES" : "INIT=NO "),
+		    (dir == LinkState::INCOMING? "INCOMING" : "OUTGOING"), 
+		    (crosslayer ? "cross-layer" : "intra-layer"),
+		    (type == LinkState::UPSTREAM? 
+		     ((dir == LinkState::INCOMING)? 
+		      "From DOWNSTREAM" : "To   DOWNSTREAM"):
+		     ((dir == LinkState::INCOMING)? 
+		      "From UPSTREAM  " : "To   UPSTREAM  ")),
+		    (s ? s : "-"), 
+		    local_port, 
+		    ((dir == LinkState::INCOMING)?  "<-" : "->"),
+		    (e ? e->instance_name(): "UNKNOWN"), 
+		    remote_port
+		    );    
+};
+
+//
+// This is useful while creating links to see if there is a duplicate
+// link. 
+//
+bool 
+LinkState::minimal_match(LinkState *incoming) {
+  
+  if (!incoming) 
+    return false; 
+  
+  if ((is_outgoing() == incoming->is_outgoing()) && 
+      (local_port == incoming->local_port)){
+    return true; 
+  };
+  
+  return false; 
+};
+
+
+//############################################################
+//
+// Connection state management. Each link is associated with a set of
+// connection state structures, one which is used during message
+// delivery. 
+// 
+//############################################################
+
+//
+// Add the connecton state if it does not already exist. 
+//
+int 
+LinkState::connstate_add(ConnectionState *c) { 
+  for (int i = 0; i < conns.size(); i++) 
+    if (conns[i] == c) 
+      return 0; 
+  
+  conns.push_back(c); 
+  return 0; 
+} 
+
+//
+// Delete a connection state if it exists..
+//
+int 
+LinkState::connstate_del(ConnectionState *c) { 
+
+  Vector<ConnectionState *> modified; 
+
+  for (int i = 0; i < conns.size(); i++) 
+    if (conns[i] != c) 
+      modified.push_back(conns[i]); 
+  
+  if (conns.size() == modified.size()) 
+    return -1; 
+  
+  conns.swap(modified); 
+  
+  return 0; 
+} 
+
+//
+// Store the connection state - an array 
+//
+int 
+LinkState::connstate_set(Vector<ConnectionState *> &conns_in) { 
+  
+  conns.clear(); 
+  for (int i = 0; i < conns_in.size(); i++)
+    conns.push_back(conns_in[i]);
+
+  return 0; 
+} 
+
+//
+// Store the connection state - an instance
+//
+int 
+LinkState::connstate_set(ConnectionState * c) { 
+  
+  conns.clear(); 
+  conns.push_back(c); 
+  return 0; 
+} 
+
+
+//
+// Return the first instance of the connection state 
+//
+ConnectionState *
+LinkState::connstate_get() { 
+  if (conns.size() > 0 ) {
+    return conns[0]; 
+  } else { 
+    return NULL; 
+  };
+} 
+
+//
+// Return the connection state array...
+//
+Vector<ConnectionState *> 
+LinkState::connstate_getall() { 
+  return conns; 
+} 
+
+
+ELEMENT_PROVIDES(LinkState)
+
+CLICK_ENDDECLS
Index: rna/elements/rna/rnaelement_linkstate.hh
diff -u /dev/null rna/elements/rna/rnaelement_linkstate.hh:1.1
--- /dev/null	Sun Jan 25 11:47:09 2009
+++ rna/elements/rna/rnaelement_linkstate.hh	Fri Jun 27 10:40:59 2008
@@ -0,0 +1,106 @@
+/* 
+
+################################################################
+#                                                              #
+# (c) University of Southern California                        #
+#                                                              #
+#  See LICENSE.RNA for the complete license                    #
+#                                                              #
+################################################################
+
+*/
+#ifndef CLICK_LINKINFO_HH
+#define CLICK_LINKINFO_HH
+
+#include "rnaelement.hh" 
+#include "rnaelement_error.hh" 
+#include "rnaelement_connstate.hh" 
+#include "rnaelement_ctlmsg.hh" 
+
+//####################################################################
+// Each RNAElement, including the metaprotocol, maintains a list of links
+// to other elements. This is necessary to determine how to route a given
+// packet. This LinkState is a datastructure that is created upon addition
+// of a link or during initialization process. The datastructure
+// maintains information about 
+//
+// * ports - the local and remote ports, 
+// * element - a pointer to the element structure 
+// * direction - the direction of traffic flow because Click links are 
+//   unidirectional (they flow from the output port of a given element to 
+//   the input port of another element),
+// * optional linktype - which tells whether the link from the module
+//   goes to the metaprotocol element or another data processing element. 
+// * Whether the next layer is connection-oriented or not and if yes,
+//   whether the connection state has been obtained or not
+// * Exported connection state from the next layer. Ideally this should
+//   be per-connection and not per-link. May be this should be an array.  
+//
+//#######################################################################
+
+class RNAElement; 
+
+// control operation is config
+class LinkState { 
+public: 
+  enum LinkType { LINK_TYPE_CONTROL, LINK_TYPE_DATA }; 
+  enum LinkDir { NODIR, INCOMING, OUTGOING };
+  enum MyNodeType { NOTYPE, UPSTREAM, DOWNSTREAM }; 
+  
+  // How does this module relate to other modules. 
+  LinkDir dir;
+  MyNodeType type;
+  int local_port;
+  int remote_port;
+  bool crosslayer; 
+  RNAElement *e; 
+  LinkType ltype; 
+
+  // Each outgoing link may be associated with multiple 
+  // connection states...
+  bool initialized;                // obtained the connection state? 
+  bool connection_oriented; 
+  RNAElementType elemtype; 
+  Vector<ConnectionState *> conns; 
+  
+  // Constructor/destructor...
+  LinkState(); 
+  LinkState (bool outgoing, bool upstream, int local_port_in, int remote_port_in = -1,
+	   bool crosslayer_in = true, RNAElement *e_in = 0, bool control = false);
+  LinkState (LinkState &l);
+  ~LinkState();   
+  
+  // Am I downstream to the node from which the message 
+  // is coming? 
+  bool is_downstream() { return (type == DOWNSTREAM); } 
+  bool is_upstream() { return (type == UPSTREAM); } 
+  
+  // What is the direction? 
+  bool is_outgoing() { return (dir == OUTGOING); } 
+  bool is_incoming() { return (dir == INCOMING); } 
+  
+  // Get/set the connection state associated with the next layer...
+  int connstate_add(ConnectionState *c);
+  int connstate_del(ConnectionState *c);
+  int connstate_set(Vector<ConnectionState *> &conns);
+  int connstate_set(ConnectionState *c);
+  ConnectionState *connstate_get(); 
+  Vector<ConnectionState *> connstate_getall(); 
+  
+  // Is this cross-layer? 
+  bool is_crosslayer() { return crosslayer; }; 
+  bool is_remote_unknown() { return (!e); }
+  
+  // initialization routines...
+  bool is_initialized() { return initialized; }; 
+  void set_initialized() { initialized = true; return; }
+  
+  // minimal match 
+  bool minimal_match(LinkState *incoming);
+  
+  // Debug ..
+  void print(const char *s = NULL);
+
+}; 
+
+#endif 
Index: rna/elements/rna/rnaelement_messages.cc
diff -u /dev/null rna/elements/rna/rnaelement_messages.cc:1.5
--- /dev/null	Sun Jan 25 11:47:09 2009
+++ rna/elements/rna/rnaelement_messages.cc	Fri Dec 26 16:57:00 2008
@@ -0,0 +1,898 @@
+/* 
+
+################################################################
+#                                                              #
+# (c) University of Southern California                        #
+#                                                              #
+#  See LICENSE.RNA for the complete license                    #
+#                                                              #
+################################################################
+
+*/
+
+//#########################################################
+//
+// Misc functions...
+//
+//#########################################################//
+
+// The logic here is a bit complicated because the same push_data
+// function is used for both the meta-protocol and modules within the
+// meta-protocol instance. So a packet that is coming in must be
+// checked for where it is coming and from in order to know how to
+// process it.
+
+//#########################################################//
+//       
+//                   IN      OUT            <---- Inter-layer
+//                   |        |
+//          +----------------------------+metaprotocol
+//          |         \       /          |
+//          |          \     /  Intra-layer
+//          |           IN  OUT          |
+//          |            |   |           |
+//          |         +--------+ some module
+//          |         |        |         |
+//          |         |        |         |
+//          |         +--------+         |
+//          |            |  |            |
+//          |           IN  OUT          |
+//          |            |   \           |
+//          |           /     |          |
+//          |          /      |          |
+//          |         /       |          |
+//          |        /        |          |
+//          +----------------------------+
+//                   |        |
+//                   IN      OUT
+//
+//#########################################################//
+
+
+
+// Copied from element/standard/Print.cc
+
+void 
+RNAElement::print_packet(String label, Packet *p, bool print_annotation){
+  
+  
+  int _bytes = ((p->length() > MAX_PRINT_PKT) ? MAX_PRINT_PKT : p->length()); 
+
+  if (0) 
+    click_chatter("[%s] RNAElement::print_packet pkt len = %d, "
+		  "MAX_PRINT = %d _bytes = %d \n", 
+		  instance_name(), p->length(), MAX_PRINT_PKT, 
+		  _bytes);
+
+  int sa_len = instance.length() + 3 
+               + label.length() + 2 // label:
+	       + 9		// length |
+	       + Packet::USER_ANNO_SIZE*2 + 3 // annotations |
+               + 2 * _bytes;
+
+  StringAccum sa(sa_len);
+
+  if (sa.out_of_memory()) {
+    click_chatter("no memory for Print");
+    return; 
+  }
+  
+  sa << "[" << instance << "] "; 
+
+  sa << label;
+  if (label)
+    sa << ": ";
+  
+  // sa.reserve() must return non-null; we checked capacity above
+  int len;
+  len = sprintf(sa.reserve(9), "%4d | ", p->length());
+  sa.adjust_length(len);
+  
+  if (print_annotation) {
+    char *buf = sa.reserve(Packet::USER_ANNO_SIZE*2);
+    int pos = 0;
+    for (unsigned j = 0; j < Packet::USER_ANNO_SIZE; j++, pos += 2) 
+      sprintf(buf + pos, "%02x", p->user_anno_c(j));
+    sa.adjust_length(pos);
+    
+    len = sprintf(sa.reserve(3), " | ");
+    sa.adjust_length(len);
+  }
+  
+  char *buf = sa.data() + sa.length();
+  int pos = 0;
+  
+  for (unsigned i = 0; i < _bytes; i++) {
+    sprintf(buf + pos, "%02x", p->data()[i] & 0xff);
+    pos += 2;
+    if ((i % 4) == 3) buf[pos++] = ' ';
+  }
+  sa.adjust_length(pos);
+
+  click_chatter("%s", sa.c_str());
+  
+  return; 
+  
+};
+
+
+//#########################################################
+//
+// Identify outgoing link for a given message
+// upstream/downstream messages. 
+//
+//#########################################################
+
+int 
+RNAElement::count_outgoing_links(Packet *p, LinkState *incoming, 
+				 bool downstream, 
+				 bool layeragnostic, 
+				 bool crosslayer,
+				 bool agnostic_remote,             
+				 bool remote_unknown, 
+				 ConnectionState *required){
+
+  //rna_click_chatter(FUNC_DEFAULT,
+  //	    "[%s] RNAElement::count_outgoing_links\n", 
+  //	    instance_name());
+  
+  int count = 0; 
+  (void)p;
+  (void)incoming; 
+
+  if (0) print_links(); 
+  
+  if (required){
+    
+    // Right now this function only knows about this type of
+    // connection state.  but can be expanded later on...
+    LinkState *l = (LinkState *)required->get_data(VAR_LINKINFO); 
+    if (l && 
+	l->is_outgoing()                         // ignore incoming links
+	&& ((layeragnostic) || 
+	    (!layeragnostic && (l->is_crosslayer() == crosslayer)))       // 
+	&& ((downstream && l->is_upstream()) || 
+	    (!downstream && l->is_downstream()))
+	&& ((agnostic_remote) || 
+	    (! agnostic_remote && (l->is_remote_unknown() == remote_unknown)))
+	) { 
+      count++;
+    };    
+
+  }  else { 
+
+    for (int i = 0; i < all_links.size(); i++){
+      LinkState *l = all_links[i];
+      
+      // Find a link in which I am an downstream node and 
+      // the link is outgoing...
+      if (l->is_outgoing()                         // ignore incoming links
+	  && ((layeragnostic) || 
+	      (!layeragnostic && (l->is_crosslayer() == crosslayer)))       // 
+	  && ((downstream && l->is_upstream()) || 
+	      (!downstream && l->is_downstream()))
+	  && ((agnostic_remote) || 
+	      (! agnostic_remote && (l->is_remote_unknown() == remote_unknown)))
+	  ) { 
+	count++;
+      };
+    };
+  };
+  
+  return count; 
+};
+
+// Look for an outgoing link that is headed towards downstream (or
+// upstream) and crosslayer (or not). 
+// This could be potentially replaced by a specific module whether control 
+// or data module. There could be a map between the cross-layer links 
+// and intra-layer links for multiplexing modules. 
+// 
+// agnostic_remote = do I care about whether the remote endpoint is 
+// known or not? 
+// remote_known = if I care, do I care that it IS unknown or NOT? 
+//
+LinkState *
+RNAElement::select_outgoing_link(Packet *p, 
+				 LinkState *incoming, 
+				 bool downstream, 
+				 bool layeragnostic, 
+				 bool crosslayer,
+				 bool agnostic_remote,             
+				 bool remote_unknown, 
+				 ConnectionState *required){
+
+  rna_click_chatter(FUNC_DEFAULT,
+		    "[%s] RNAElement::select_outgoing_link "
+		    "(%s, %s, %s, %s, %s, %s)\n",
+		    instance_name(), 
+		    (downstream? "downstream" : "upstream"),
+		    (layeragnostic? "layer agnostic": "layer sensitive"),
+		    (crosslayer? "crosslayer": "intra-layer"), 
+		    (agnostic_remote? "agnostic remote": "sensitive remote"), 
+		    (remote_unknown? "remote unknown" : "remote known"),
+		    (required? "conn state required" : "conn state not required")
+		    );
+  
+  (void)p;
+  (void)incoming; 
+
+  if (0) print_links(); 
+
+  if (required){
+    
+    // Right now this function only knows about this type of
+    // connection state.  but can be expanded later on...
+    LinkState *l = (LinkState *)required->get_data(VAR_LINKINFO); 
+    if (l && 
+	l->is_outgoing()                         // ignore incoming links
+	&& ((layeragnostic) || 
+	    (!layeragnostic && (l->is_crosslayer() == crosslayer)))       // 
+	&& ((downstream && l->is_upstream()) || 
+	    (!downstream && l->is_downstream()))
+	&& ((agnostic_remote) || 
+	    (! agnostic_remote && (l->is_remote_unknown() == remote_unknown)))
+	) { 
+      //l->print("Selected this link");
+      return l; 
+    };
+  } else { 
+    
+    for (int i = 0; i < all_links.size(); i++){
+      LinkState *l = all_links[i];
+      
+      // Find a link in which I am an downstream node and 
+      // the link is outgoing...
+      if (l->is_outgoing()                         // ignore incoming links
+	  && ((layeragnostic) || 
+	      (!layeragnostic && (l->is_crosslayer() == crosslayer)))       // 
+	  && ((downstream && l->is_upstream()) || 
+	      (!downstream && l->is_downstream()))
+	  && ((agnostic_remote) || 
+	      (! agnostic_remote && (l->is_remote_unknown() == remote_unknown)))
+	  ) { 
+	//l->print("Selected this link");
+	return l; 
+      };
+    };
+  };
+
+  return NULL; 
+};
+
+
+Vector<LinkState *>
+RNAElement::list_outgoing_link(Packet *p, 
+			       LinkState *incoming, 
+			       bool downstream, 
+			       bool layeragnostic, 
+			       bool crosslayer,
+			       bool agnostic_remote,             
+			       bool remote_unknown,
+			       ConnectionState *required){
+
+  rna_click_chatter(FUNC_DEFAULT,
+		    "[%s] RNAElement::list_outgoing_link\n",
+		    instance_name());
+  
+  (void)p;
+  (void)incoming; 
+  Vector<LinkState *> link_list; 
+
+  if (0) print_links(); 
+
+  if (required){
+    
+    // Right now this function only knows about this type of
+    // connection state.  but can be expanded later on...
+    LinkState *l = (LinkState *)required->get_data(VAR_LINKINFO); 
+    // the link is outgoing...
+    if (l && 
+	l->is_outgoing()                         // ignore incoming links
+	&& ((layeragnostic) || 
+	    (!layeragnostic && (l->is_crosslayer() == crosslayer)))       // 
+	&& ((downstream && l->is_upstream()) || 
+	    (!downstream && l->is_downstream()))
+	&& ((agnostic_remote) || 
+	    (! agnostic_remote && (l->is_remote_unknown() == remote_unknown)))
+	) { 
+      link_list.push_back(l);
+      //l->print("Selected this link");
+    };
+  } else { 
+
+    for (int i = 0; i < all_links.size(); i++){
+      LinkState *l = all_links[i];
+      
+      // Find a link in which I am an downstream node and 
+      // the link is outgoing...
+      if (l->is_outgoing()                         // ignore incoming links
+	  && ((layeragnostic) || 
+	      (!layeragnostic && (l->is_crosslayer() == crosslayer)))       // 
+	  && ((downstream && l->is_upstream()) || 
+	      (!downstream && l->is_downstream()))
+	  && ((agnostic_remote) || 
+	      (! agnostic_remote && (l->is_remote_unknown() == remote_unknown)))
+	  ) { 
+	link_list.push_back(l);
+	//l->print("Selected this link");
+      };
+    };
+  };
+  
+  return link_list; 
+};
+
+
+//#########################################################
+//
+// Pre-processing messages from incoming/outgoing to 
+// upstream/downstream messages. 
+//
+//#########################################################
+
+// Default data path processing....
+void
+RNAElement::process_incoming_from_downstream(Packet **p_in, 
+					     LinkState *incoming, 
+					     MessageStatus *status){
+  // Do nothing...
+  (void)p_in;
+  (void)incoming; 
+  (void)status; 
+}
+
+void
+RNAElement::process_outgoing_to_downstream(Packet **p_in, 
+					   LinkState *outgoing,
+					   MessageStatus *status){
+  // Do nothing
+  (void)outgoing; 
+  (void)status; 
+  (void) p_in;
+
+  if (0) 
+    rna_click_chatter(FUNC_DEFAULT,
+		      "[%s] RNAElement::process_outgoing_to_downstream "
+		      "Adding byte\n", instance_name());
+  
+  // Write out a control/data one byte header...
+  // WritablePacket *p = (*p_in)->push(1); 
+  // char *data = reinterpret_cast<char *>(p->data());
+  // *data = MESSAGE_DATA; 
+  // *p_in = p; 
+
+}
+
+void
+RNAElement::process_incoming_from_upstream(Packet **p_in, 
+					   LinkState *incoming,  
+					   MessageStatus *status){
+  // Do nothing
+  (void)p_in;
+  (void)incoming; 
+  (void)status; 
+}
+
+void
+RNAElement::process_outgoing_to_upstream(Packet **p_in, 
+					 LinkState *outgoing,
+					 MessageStatus *status){
+  // Do nothing
+  (void)p_in;
+  (void)outgoing; 
+  (void)status; 
+}
+
+
+// 
+// Check if the state is correct 
+// 
+bool 
+RNAElement::check_connectionstate(LinkState *incoming_link, Packet *p_in){
+
+  if (0) 
+    rna_click_chatter(FUNC_DEFAULT,
+		      "[%s] RNAElement::check_connectionstate \n", 
+		      instance_name());
+
+  if (!incoming_link || !p_in) 
+    return false; 
+  
+  // XXX To be filled later. Skip if I am upstream 
+  if (incoming_link->is_upstream()) 
+    return true; 
+
+  // Nothing to check if this is not connection oriented...
+  if (!connection_oriented)
+    return true; 
+  
+  ConnectionState *c = GET_CONN_ANNO(p_in); 
+  
+  if (!c) 
+    return false; 
+
+  for (int i = 0; i < conns.size(); i++)
+    if (c == conns[i])
+      return true; 
+  
+  return false;  
+
+};
+
+
+// Where should I send it next? 
+bool
+RNAElement::push_data_to_link(Packet *p, LinkState *l, const char *func = ""){
+  
+  // Cant send the packet out...
+  if (!l) {
+    // XXX Add a check to see if any modules have been composed and
+    // that composition has failed for some reason.
+    click_chatter("[%s] %s  - NOT sending test reply. "
+		  "No outgoing link found\n",
+		  instance_name(), (func ? func : ""));
+    return false;
+  };
+  
+  if (debug) { 
+    click_chatter("[%s] %s - Sending message\n", 
+		  instance_name(), (func ? func : ""));
+    click_chatter("[M1] Sending packet to:\n");
+    l->print(instance_name());
+  };
+  
+  Port port = output(l->local_port);
+  if (port.active()){
+    click_chatter("Sending out on port");
+    //process_outgoing_to_downstream(&p, l);
+    port.push(p);
+  } else {
+    rna_click_chatter(FUNC_DEFAULT,"output port is not active.\n");
+  };
+  
+  return true;
+};
+
+//#########################################################
+//
+// Handle a message on the data path....
+//
+//#########################################################
+
+// Where should I send it next? 
+void
+RNAElement::push_data(int port, Packet *p_in)
+{
+
+  rna_click_chatter(FUNC_DEFAULT,
+		    "[%s] RNAElement::push_data(port = %d)\n", 
+		    instance_name(), port); 
+  
+  LinkState *incoming_link = lookup_link(port);
+  if (! incoming_link ){
+    rna_click_chatter(FUNC_DEFAULT,
+		      "[%s] Dropping packet...\n", 
+		      instance_name()); 
+    p_in->kill();
+    return;
+  };   
+  
+  incoming_link->print(instance_name());
+
+  if (0) 
+    rna_click_chatter(FUNC_DEFAULT,
+		    "[%s] %s::push_data Incoming message on port = %d "
+		    "direction = %s remote = %s \n", 
+		    instance_name(), class_name(), port, 
+		    (incoming_link->is_upstream() ? "UPSTREAM":"DOWNSTREAM"), 
+		    (incoming_link->e ? incoming_link->e->instance_name() : 
+		                      "UNKNOWN"));
+  
+  bool sent = false;
+
+  //
+  //==========================================================
+  //  If this layer is connection-oriented check if the 
+  //  previous layer has correctly specified the state. 
+  if (!skip_connection_check && 
+      !check_connectionstate(incoming_link, p_in)){ 
+    // Packet has to be dropped...
+    rna_click_chatter(FUNC_DEFAULT,
+		      "[%s] Did not specify the connection. Dropping packet\n",
+		      instance_name()); 
+    p_in->kill();
+    return;    
+  }; 
+  
+  // Find the required connection state...
+  ConnectionState *required_connstate = 0; 
+  if (!skip_connection_check) 
+    required_connstate = GET_CONN_ANNO(p_in);
+  
+
+  //
+  //==========================================================
+  // 
+  if (0) print_links(); 
+    
+  // If this is not control, then dont look for cross-layer outgoing
+  // links. If the non-control module (e.g., a data processing module)
+  // has less than 4 links (2 each to downstream and upstream), then
+  // we have to force the data down the available paths...
+  
+  int count = count_outgoing_links(p_in, incoming_link, 
+				   incoming_link->is_downstream(), 
+				   true, true, // layer agnostic 
+				   true, true, 
+				   required_connstate);
+  
+  //rna_click_chatter(FUNC_DEFAULT,"[%s] %s::push_data "
+  //	    "# outgoing links = %d \n", 
+  //	    instance_name(), class_name(), count); 
+  
+  // What if there are no choices? 
+  if (count == 1){
+
+    // Need to send this up to the next layer above...
+    if (incoming_link->is_upstream()) 
+      process_incoming_from_downstream(&p_in, incoming_link);
+    else 
+      process_incoming_from_upstream(&p_in, incoming_link);
+
+    // upstream, layer agnostic, cross-layer
+    LinkState *l = select_outgoing_link(p_in, 
+					incoming_link, 
+					incoming_link->is_downstream(), 
+					true, // layer agnostic
+					true, // cross layer 
+					true, // remote agnostic 
+					true, // dont care
+					required_connstate);
+    if (l){ 
+
+      if (0) 
+	rna_click_chatter(FUNC_DEFAULT,"[%s] connection_oriented = %d, "
+			  "conn = %x \n", 
+			  instance_name(), l->connection_oriented, 
+			  l->connstate_get()); 
+      
+      // Dont discover connection state for links going
+      // upstream...atleast not yet...XXX 
+      // discover_connectionstate(l);
+      
+      if (l->connection_oriented) { 
+	ConnectionState *c = l->connstate_get(); 
+	SET_CONN_ANNO(p_in, c); 
+      };
+
+      click_chatter("[10] Sending packet to: ");
+      l->print(instance_name()); 
+
+      Port p = output(l->local_port);
+      if (p.active()){
+	if (l->is_upstream()) 
+	  process_outgoing_to_downstream(&p_in, l);
+	else
+	  process_outgoing_to_upstream(&p_in, l);
+	p.push(p_in); 
+	sent = true; 
+      } else {
+	rna_click_chatter(FUNC_DEFAULT, "Output port is not active.\n");
+      };
+    };
+    
+  } else { 
+    
+    // There are choices....
+    bool treat_as_interlayer = false; 
+    if (this->is_control()){
+      if (incoming_link->is_crosslayer()){
+	treat_as_interlayer = true; 
+      }
+    } else { 
+      // incoming/outgoing downstream/upstream
+      treat_as_interlayer = true; 
+    };
+
+    if (treat_as_interlayer){ 
+
+      rna_click_chatter(FUNC_DEFAULT,
+			"[%s] RNAElement::push_data inter-layer message \n", 
+			instance_name()); 
+      
+      if (incoming_link->is_downstream()) {
+	
+	// XXX Message coming from the layer above...  Forward on any
+	// of the ports to the modules within the protocol. Ideally
+	// there should be a selection function here....
+	
+	process_incoming_from_upstream(&p_in, incoming_link);
+	
+	// downstream, layer specific, intra-layer
+	LinkState *l = select_outgoing_link(p_in, 
+					    incoming_link, 
+					    true, 
+					    false, // layer sensitive
+					    false, // intra-layer
+					    true,  // agnostic_remote
+					    false, // dont care
+					    required_connstate); 
+	if (l){ 
+	  
+	  if (0) 
+	    rna_click_chatter(FUNC_DEFAULT,
+			      "[%s] connection_oriented = %d, conn = %x \n", 
+			      instance_name(), l->connection_oriented, 
+			      l->connstate_get()); 
+	  
+	  discover_connectionstate(l); 
+	  
+	  if (l->connection_oriented) { 
+	    ConnectionState *c = l->connstate_get(); 
+	    SET_CONN_ANNO(p_in, c); 
+	  };	  
+	  
+	  click_chatter("[11] Sending packet to: ");
+	  l->print(instance_name()); 
+
+	  Port p = output(l->local_port);
+	  if (p.active()){
+	    process_outgoing_to_downstream(&p_in, l);
+	    p.push(p_in); 
+	    sent = true; 
+	  } else {
+	    rna_click_chatter(FUNC_DEFAULT,"output port is not active.\n");
+	  };
+	};
+	
+	rna_click_chatter(FUNC_DEFAULT,"[%s] \n\n", instance_name()); 
+	
+      } else { // if downstream && cross layer..
+	
+	// message coming from the layer below...This message should
+	// eventually be delivered to one of module paths. A message
+	// must exit the layer only when the message is delivered back
+	// to the control module after processing in the module path.
+	// XXX 
+	process_incoming_from_downstream(&p_in, incoming_link);
+	
+	// upstream, layer specific, intra-layer
+	LinkState *l = select_outgoing_link(p_in, 
+					    incoming_link, 
+					    false, // upstream
+					    false, // layer sensitive
+					    false, // intra-layer
+					    true,  // remote agnostic 
+					    true,  // dont care
+					    required_connstate); 
+	if (l){ 
+	  
+	  if (0) 
+	    rna_click_chatter(FUNC_DEFAULT,
+			      "[%s] connection_oriented = %d, conn = %x \n", 
+			      instance_name(), l->connection_oriented, 
+			      l->connstate_get()); 
+	  
+	  discover_connectionstate(l); 
+	  
+	  if (l->connection_oriented) { 
+	    ConnectionState *c = l->connstate_get(); 
+	    SET_CONN_ANNO(p_in, c); 
+	  };	  
+	  
+
+	  click_chatter("[12] Sending packet to: ");
+	  l->print(instance_name()); 
+
+	  Port p = output(l->local_port);
+	  if (p.active()){
+	    process_outgoing_to_upstream(&p_in, l);
+	    p.push(p_in); 
+	    sent = true; 
+	  } else {
+	    rna_click_chatter(FUNC_DEFAULT,"output port is not active....\n"); 
+	  };
+	};
+	
+      }; // if downstream && cross layer..
+      
+    } else {
+      
+      
+      rna_click_chatter(FUNC_DEFAULT,
+			"[%s] RNAElement::push_data intra-protocol message\n",
+			instance_name()); 
+      
+      // Intra-layer...Depending on the path down or up, 
+      // accordingly forward the message. 
+      
+      // Am I upstream or downstream? 
+      if (incoming_link->is_downstream()) { 
+	
+	// Need to send this up to the next layer below...       
+	process_incoming_from_upstream(&p_in, incoming_link);
+	
+	// downstream, layer-specific, cross-layer, 
+	LinkState *l = select_outgoing_link(p_in, 
+					    incoming_link, 
+					    true, 
+					    false, 
+					    true, 
+					    true,  // remote agnostic 
+					    true,  // dont care
+					    required_connstate);
+	if (!l) {
+	  rna_click_chatter(FUNC_DEFAULT,
+			    "[%s] RNAElement::push_data Cannot "
+			    "find link\n", instance_name());
+	};
+	
+	if (l){ 
+	  
+	  if (debug) 
+	    rna_click_chatter(FUNC_DEFAULT,
+			      "[%s] connection_oriented = %d, conn = %x \n", 
+			      instance_name(), l->connection_oriented, 
+			      l->connstate_get()); 
+
+	  discover_connectionstate(l); 
+	  
+	  if (l->connection_oriented) { 
+	    ConnectionState *c = l->connstate_get(); 
+	    SET_CONN_ANNO(p_in, c); 
+	  };	  
+	  
+	  click_chatter("[13] Sending packet to: ");
+	  l->print(instance_name()); 
+
+	  Port p = output(l->local_port);
+	  if (p.active()){
+	    process_outgoing_to_downstream(&p_in, l);
+	    p.push(p_in); 
+	    sent = true; 
+	  } else {
+	    rna_click_chatter(FUNC_DEFAULT,"output port is not active....\n"); 
+	  };
+	};
+	
+      } else {
+	
+	// Need to send this up to the next layer above...
+	process_incoming_from_downstream(&p_in, incoming_link);
+	
+	// upstream, layer specific, cross-layer
+	LinkState *l = select_outgoing_link(p_in, 
+					    incoming_link, 
+					    false, 
+					    false, // layer sensitive
+					    true,  // intra-layer 
+					    true,  // remote agnostic 
+					    true,  // dont care
+					    required_connstate);
+	if (l){ 
+	  
+	  if (0) 
+	    rna_click_chatter(FUNC_DEFAULT,
+			      "[%s] connection_oriented = %d, conn = %x \n", 
+			      instance_name(), l->connection_oriented, 
+			      l->connstate_get()); 
+	  
+	  discover_connectionstate(l); 
+	  
+	  if (l->connection_oriented) { 
+	    ConnectionState *c = l->connstate_get(); 
+	    SET_CONN_ANNO(p_in, c);
+	  };	  
+	  
+	  click_chatter("[14] Sending packet to: ");
+	  l->print(instance_name()); 
+
+	  Port p = output(l->local_port);
+	  if (p.active()){
+	    process_outgoing_to_upstream(&p_in, l);
+	    p.push(p_in); 
+	    sent = true; 
+	  } else {
+	    rna_click_chatter(FUNC_DEFAULT,"output port is not active....\n"); 
+	  };
+	};
+	
+      }; // else inter-layer if..downstream..
+    }; // ..if..crosslayer.......
+  };  // if count...
+  
+  if (! sent) {
+    rna_click_chatter(FUNC_DEFAULT,"push_data: Could not send the packet.\n");
+    p_in->kill(); 
+  };
+  
+  return; 
+  
+}; // push ...
+
+
+void
+RNAElement::push_control(int port, Packet *p_in)
+{
+  (void)port; 
+  (void)p_in;
+  // Do nothing for now...
+  return; 
+};
+
+void
+RNAElement::push_management(int port, Packet *p_in)
+{
+  (void)port; 
+  (void)p_in;
+
+  // Do nothing for now...
+  return; 
+};
+
+void 
+RNAElement::push(int i, Packet *p)
+{
+
+  unsigned char type = MESSAGE_DATA; 
+
+  if (!p || !p->data()) 
+    return; 
+  
+  // If the message is coming from downstream and has 
+  // the first byte as control, then hand it off to a 
+  // control message processor. Otherwise give it to 
+  // data message processor (push_data); 
+  LinkState *incoming_link = lookup_link(i);
+  if (! incoming_link ){
+    rna_click_chatter(FUNC_DEFAULT,
+		      "[%s] RNAElement::push Dropping packet...\n", 
+		      instance_name()); 
+    p->kill();
+    return;
+  }; 
+  
+  if (incoming_link->is_upstream() || 
+      (incoming_link->is_downstream() && 
+       !incoming_link->is_remote_unknown())){ 
+    const unsigned char *data = p->data(); 
+    type = *data; 
+  };
+
+  if (debug){
+    rna_click_chatter(FUNC_DEFAULT,"\n");   
+    if (0) 
+      RNAElement::print_packet("RNAElement::push", p, false);
+  };
+
+  switch(type){
+
+  case MESSAGE_CONTROL: 
+    push_control(i,p); 
+    break;
+
+  case MESSAGE_DATA:
+    push_data(i,p); 
+    break;
+
+  case MESSAGE_MANAGEMENT: 
+    push_management(i, p); 
+    break; 
+    
+  default: 
+    {
+      if (debug) 
+	rna_click_chatter(FUNC_DEFAULT," [%s] RNAElement::push "
+			  "type(UNKNOWN %x)\n", instance_name(), type);
+      p->kill(); 
+      break;
+    };
+    
+  };
+  
+  return; 
+
+};
+
+
Index: rna/elements/rna/rnaelement_messages.hh
diff -u /dev/null rna/elements/rna/rnaelement_messages.hh:1.3
--- /dev/null	Sun Jan 25 11:47:09 2009
+++ rna/elements/rna/rnaelement_messages.hh	Fri Dec 26 16:57:00 2008
@@ -0,0 +1,84 @@
+/* 
+
+################################################################
+#                                                              #
+# (c) University of Southern California                        #
+#                                                              #
+#  See LICENSE.RNA for the complete license                    #
+#                                                              #
+################################################################
+
+*/
+//##########################################################
+// Message definitions. 
+//##########################################################
+
+enum MessageType {
+  MESSAGE_CONTROL = 0xa0,
+  MESSAGE_DATA = 0xb0,
+  MESSAGE_MANAGEMENT = 0xc0
+};
+
+// 
+// Right now only type of control message is supported - NEGOTIATE. 
+//
+
+enum ControlMessageType {
+  MESSAGE_CONTROL_NEGOTIATE = 0x10
+};
+
+// 
+// What is the nature of the negotiate control message?
+// 
+
+enum NegotiateMessageType {
+  MESSAGE_CONTROL_NEGOTIATE_REQUEST = 0x11,
+  MESSAGE_CONTROL_NEGOTIATE_REPLY_SUCCESS = 0x12,
+  MESSAGE_CONTROL_NEGOTIATE_REPLY_FAILURE = 0x13,
+  MESSAGE_CONTROL_NEGOTIATE_REPLY_LEARN_REQUEST = 0x14,
+  MESSAGE_CONTROL_NEGOTIATE_REPLY_LEARN_REPLY = 0x15,  
+};
+
+
+// 
+// When a message is delivered to a particular module, should it
+// process it or strip the headers and deliver it to the next layer?
+// 
+enum DataMessageType{
+  MESSAGE_DATA_NORMAL = 0x20,
+  MESSAGE_DATA_TEST = 0x30,
+  MESSAGE_DATA_REXMIT = 0x40
+};
+
+enum TestMessageType{ 
+  MESSAGE_DATA_TEST_ECHO_REQUEST = 0x31,
+  MESSAGE_DATA_TEST_ECHO_REPLY = 0x32
+};
+
+enum RexmitMessageType {
+  MESSAGE_DATA_REXMIT_SEND = 0x41,
+  MESSAGE_DATA_REXMIT_ACK = 0x42,
+};
+
+enum ManagementMessageType {
+  MESSAGE_MANAGEMENT_ADD_MODULE, 
+  MESSAGE_MANAGEMENT_DEL_MODULE, 
+  MESSAGE_MANAGEMENT_REPLY,
+  MESSAGE_MANAGEMENT_INFORMATION
+};
+
+
+
+#define GET_CONN_ANNO(p) ((ConnectionState *)(p)->user_anno_u(4))
+#define SET_CONN_ANNO(p, v) ((p)->set_user_anno_u(4, ((unsigned int)(v))))
+
+// Default processing on the outgoing and incoming messages. 
+// Replace this in instances of the RNAElement. 
+typedef  enum {
+  MESSAGE_STATUS_KILL, 
+  MESSAGE_STATUS_CONTINUE, 
+  MESSAGE_STATUS_IGNORE,
+  MESSAGE_STATUS_REPLY
+} MessageStatus;
+
+
Index: rna/elements/rna/rnaelement_neighbors.cc
diff -u /dev/null rna/elements/rna/rnaelement_neighbors.cc:1.1
--- /dev/null	Sun Jan 25 11:47:09 2009
+++ rna/elements/rna/rnaelement_neighbors.cc	Fri Jun 27 10:40:59 2008
@@ -0,0 +1,206 @@
+/* 
+
+################################################################
+#                                                              #
+# (c) University of Southern California                        #
+#                                                              #
+#  See LICENSE.RNA for the complete license                    #
+#                                                              #
+################################################################
+
+*/
+
+//==============================================================
+//
+// This is for processing the list of predecessors/successors 
+//
+//==============================================================
+
+void
+RNAElement::skip_type(Vector<Element*>& v, char *typename_in )
+{
+    Vector<Element*> nv;
+
+    if (!typename_in) 
+      return;
+
+    for (int i = 0; i < v.size(); i++){
+      const char *mytypename = v[i]->class_name(); 
+      if (strcmp(mytypename, typename_in) != 0)
+	nv.push_back(v[i]);
+    };
+
+    v.swap(nv);
+}
+
+
+void 
+RNAElement::filter(char *what, Vector<Element*>& v){
+  
+  Vector<Element*> nv;
+  for (int i = 0; i < v.size(); i++){
+    const char *elemname = v[i]->class_name(); 
+    if (!what || strcmp(what, elemname))
+      nv.push_back(v[i]);
+    v.swap(nv);
+  };
+
+  return; 
+};
+
+Vector<Element*> 
+RNAElement::upstream_elements(Element *e, int inputport){
+  
+  Vector<Element*> v; 
+  if (!e) 
+    return v; 
+  
+  // List all the possible elements;
+  Vector<Element*> allelements = router()->elements();
+  
+  // For each element look through all the outputs...
+  for (int i = 0; i < allelements.size(); i++){
+
+    // ith element
+    Element *e0 = allelements[i]; 
+    
+    // For each element go through the list of output ports. 
+    for (int j = 0; j < e0->noutputs(); j++){
+
+      // find out who is at the other end of the output. 
+      Port p = e0->output(j);
+      Element *temp = p.element();
+      
+      rna_click_chatter(FUNC_DEFAULT, 
+			"upstream_elements: %s [%d] -> %s [%d] \n",
+			e0->class_name(), j, 
+			(temp? temp->class_name() : "NULL"), 
+			p.port());
+
+       // Does the port numbers match? p.port() is the value of 
+       // input port at the other end. 
+      if (temp && temp == this) { 
+	  if (inputport >= 0) {
+	    if (inputport == p.port()){
+	      rna_click_chatter(FUNC_DEFAULT,"upstream_elements: Selected!\n");
+	      v.push_back(e0); 
+	    };
+	  } else { 
+	    rna_click_chatter(FUNC_DEFAULT,"upstream_elements: Selected!\n"); 
+	    v.push_back(e0); 	    
+	  };
+      };
+    }; // for all outputs
+  }; // for all elements...
+  
+  return v; 
+}; // upstream_elements...
+
+
+// Return one element that connects to a given element on 
+// a given input port...
+Element *
+RNAElement::upstream_element(Element *e, int inputport){
+  
+  // The input port must be specified. 
+  if (inputport < 0 || !e) 
+    return NULL; 
+  
+  Vector<Element *> v = upstream_elements(e, inputport); 
+  
+  if (v.size() == 0) 
+    return NULL; 
+  
+  // Return the first element...
+  return v[0]; 
+
+};
+
+Vector<Element*> 
+RNAElement::downstream_elements(Element *e){
+  
+  Vector<Element*> v; 
+  
+  // If no element is specified return an empty list...
+  if (!e) 
+    return v; 
+  
+  // For each element go through the list of output ports. 
+  for (int j = 0; j < e->noutputs(); j++){
+    
+    // find out who is at the other end of the output. 
+    Port p = e->output(j);
+    Element *temp = p.element();
+      
+    rna_click_chatter(FUNC_DEFAULT,
+		      "downstream_elements: %s [%d] -> %s [%d] \n", 
+		      e->class_name(), j, 
+		      (temp? temp->class_name() : "NULL"), p.port());
+
+    // If the port exists, then include it. 
+    if (temp) 
+      v.push_back(temp); 
+    
+  }; // for all outputs...
+  
+  return v; 
+}; // downstream_elements
+
+
+Vector<LinkState *>
+RNAElement::list_downstream_elements(bool downstream, 
+				      bool layeragnostic, 
+				      bool crosslayer,
+				      bool agnostic_remote,             
+				      bool remote_unknown, 
+				     ConnectionState *required){
+
+  rna_click_chatter(FUNC_DEFAULT,
+		    "[%s] RNAElement::list_downstream_elements " 
+		    "downstream = %d, layeragnostic = %d crosslayer = %d"
+		    " agnostic_remote = %d, remote_unknown = %d \n",
+		    instance_name(), 
+		    downstream, layeragnostic, crosslayer,
+		    agnostic_remote, remote_unknown);
+  
+  Vector<LinkState *> list; 
+
+  if (required){
+    
+    // Right now this function only knows about this type of
+    // connection state.  but can be expanded later on...
+    LinkState *l = (LinkState *)required->get_data(VAR_LINKINFO); 
+    if (l && 
+	l->is_outgoing()                         // ignore incoming links
+	&& ((layeragnostic) || 
+	    (!layeragnostic && (l->is_crosslayer() == crosslayer)))       // 
+	&& ((downstream && l->is_upstream()) || 
+	    (!downstream && l->is_downstream()))
+	&& ((agnostic_remote) || 
+	    (!agnostic_remote && (l->is_remote_unknown() == remote_unknown)))
+	) { 
+      list.push_back(l);
+    };
+
+  } else { 
+
+    for (int i = 0; i < all_links.size(); i++){
+      LinkState *l = all_links[i];
+      
+      // Find a link in which I am an downstream node and 
+      // the link is outgoing...
+      if (l->is_outgoing()                         // ignore incoming links
+	  && ((layeragnostic) || 
+	      (!layeragnostic && (l->is_crosslayer() == crosslayer)))       // 
+	  && ((downstream && l->is_upstream()) || 
+	      (!downstream && l->is_downstream()))
+	  && ((agnostic_remote) || 
+	      (!agnostic_remote && (l->is_remote_unknown() == remote_unknown)))
+	  ) { 
+	list.push_back(l);
+      };
+    };
+  };
+  
+  return list; 
+};
Index: rna/elements/rna/rnaelement_parse.cc
diff -u /dev/null rna/elements/rna/rnaelement_parse.cc:1.3
--- /dev/null	Sun Jan 25 11:47:10 2009
+++ rna/elements/rna/rnaelement_parse.cc	Fri Dec 26 16:57:00 2008
@@ -0,0 +1,326 @@
+/* 
+
+################################################################
+#                                                              #
+# (c) University of Southern California                        #
+#                                                              #
+#  See LICENSE.RNA for the complete license                    #
+#                                                              #
+################################################################
+
+*/
+
+//################################################################
+//
+// Extract the modules of the right kind from the element list that 
+// has been provided using the ELEMENTS argument. 
+//
+//################################################################
+
+Vector<RNAElement *> 
+RNAElement::elementlist_lookup(Vector<RNAElement *>& array, 
+			       RNAElementType t, 
+			       bool modify){ 
+  
+  Vector<RNAElement *> returned_list; 
+  if (
+      t < ELEMTYPE_BEGIN ||
+      t > ELEMTYPE_END || 
+      t == UNKNOWN ||
+      t == ROOT
+      )
+    return returned_list; 
+  
+  Vector<RNAElement *> array_modified; 
+  for (int i = 0; i < array.size(); i++){
+    
+    RNAElement *e = array[i]; 
+    if (!e) 
+      continue; 
+    
+    
+#ifdef COMMENT
+    if ((strcmp(e->class_name(), "RNAElement") != 0)){ 
+      array_modified.push_back(e);
+      continue; 
+    }
+    
+    RNAElement *e1 = static_cast<RNAElement *>(e->cast("RNAElement"));
+    if (e1->get_type() == t) { 
+      returned_list.push_back(e1); 
+      if (!modify) 
+	array_modified.push_back(e);	
+    } else {
+      array_modified.push_back(e);
+    }
+#endif 
+
+    if (e->get_type() == t) { 
+      returned_list.push_back(e); 
+      if (!modify) 
+	array_modified.push_back(e);	
+    } else {
+      array_modified.push_back(e);
+    };
+  };
+  
+  array.swap(array_modified);
+  
+  return returned_list; 
+
+};
+
+//################################################################
+//
+// Extract the modules of the right kind from the element list that 
+// has been provided using the ELEMENTS argument. 
+//
+//################################################################
+RNAElement *
+RNAElement::elementlist_lookup_one(Vector<RNAElement *>& array, 
+				   RNAElementType t, 
+				   bool modify){ 
+  
+  RNAElement * returned = NULL; 
+  if (
+      t < ELEMTYPE_BEGIN ||
+      t > ELEMTYPE_END || 
+      t == UNKNOWN ||
+      t == ROOT
+      )
+    return returned; 
+  
+  if (array.size() == 0)
+    return returned;
+  
+  Vector<RNAElement *> array_modified; 
+  for (int i = 0; i < array.size(); i++){
+    
+    RNAElement *e = array[i]; 
+    if (!e) 
+      continue; 
+
+#ifdef COMMENT    
+    if (returned || 
+	(strcmp(e->class_name(), "RNAElement") != 0)){ 
+      array_modified.push_back(e);
+      continue; 
+    }
+    
+    RNAElement *e1 = static_cast<RNAElement *>(e->cast("RNAElement"));
+    if (e1->get_type() == t) { 
+      returned = e1; 
+      if (!modify) 
+	array_modified.push_back(e);	
+    } else {
+      array_modified.push_back(e);
+    }
+#endif 
+    if (returned){ 
+      array_modified.push_back(e);
+      continue; 
+    }
+    
+    if (e->get_type() == t) { 
+      returned = e; 
+      if (!modify) 
+	array_modified.push_back(e);	
+    } else {
+      array_modified.push_back(e);
+    }    
+  };
+  
+  array.swap(array_modified);
+  
+  return returned; 
+
+};
+
+//################################################################
+//
+// Parse the element list
+//
+//################################################################
+
+//
+// Expects the name of an element and matches it exact or looks for a
+// prefix such as in case of compound elements...
+// 
+Vector<Element *>
+RNAElement::elementlist_find_prefix(String prefix, Element *context){
+
+  Vector<Element *> list; 
+  
+  // click_chatter("[RNA] prefix = %s \n", prefix.c_str()); 
+
+  Router *r = context->router(); 
+  Vector<Element *> allelements = r->elements(); 
+
+  for (int j=0; j < allelements.size(); j++){
+       
+    Element *e =  allelements[j];
+    String ename = e->name(); 
+
+    //click_chatter("[RNA] RNAElement::elementlist_find_prefix name[%d] = %s \n", 
+    //	  j, ename.c_str());
+    
+    if (ename == prefix){
+      list.push_back(e);
+      break; 
+    };
+    
+    // Name doesnt match...words[i] == l0 and name == l0/Socket@1
+    int slash = ename.find_left('/');
+    if (slash >= 0) {
+      String ename1 = ename.substring(0, slash); 
+      //click_chatter("[RNA] RNAElement::elementlist_find_prefix slash = %d %s \n", 
+      //		    slash, ename1.c_str());
+      if (ename1 == prefix){
+	list.push_back(e); 
+      };
+    };       
+  }; // for...
+  
+  //for (int j = 0; j < list.size(); j++)
+  //  click_chatter("[RNA] Found element[%d] = %s \n", j, list[j]->name().c_str());
+
+  return list; 
+};
+
+void
+RNAElement::elementlist_parse(cp_value *v, const String &arg, 
+			      ErrorHandler *errh, 
+			      const char *argname, Element *context){
+  (void) argname; 
+
+  // Do the processing the store function...
+  v->v_string = arg; 
+
+  // Check the validity of the error. 
+  Vector<Element *> *array = (Vector<Element *> *)v->store;  
+  if (! array){ 
+    errh->error("Failed to process element list. Empty argument (%s,%s)", 
+		v->description, 
+		v->v_string.printable().c_str());
+    return;
+  };
+ 
+  // Check whether the element list is fine...
+  Vector<String> words;
+  cp_spacevec(v->v_string, words);
+
+  
+  for (int i = 0; i < words.size(); i++){
+    
+    String test; 
+
+    if (!cp_string(words[i], &test)) {
+      if (errh)
+	errh->error("cp_string bad name format");
+      return;
+    } 
+
+    
+    Vector<Element *> list = elementlist_find_prefix(words[i], context);
+    if (list.size() == 0){
+      if (errh)
+	errh->error("Cannot find elements");
+      return;
+    } 
+    
+  }; // For all words....
+
+  return; 
+}
+
+void
+RNAElement::elementlist_store(cp_value *v, Element *context){
+  
+  // Check the validity of the error. 
+  Vector<Element *> *array = (Vector<Element *> *)v->store;  
+
+  Vector<String> words;
+  cp_spacevec(v->v_string, words);
+
+  Router *r = context->router(); 
+  Vector<Element *> allelements = r->elements(); 
+  
+  // Process the element list provided...
+  for (int i = 0; i < words.size(); i++){
+    
+    Vector<Element *> list = elementlist_find_prefix(words[i], context);
+    for (int j = 0; j < list.size(); j++) 
+      array->push_back(list[j]);
+
+  }; // for all words...
+
+  return;
+}
+
+//################################################################
+//
+// Handle a default set of keywords...
+//
+//################################################################
+int
+RNAElement::configure(Vector<String> &conf, ErrorHandler *errh)
+{
+  
+  if (cp_va_parse_remove_keywords(conf, 0, this, errh,
+		  cpKeywords, 
+		  "NAME", cpString, "Name", &instance,
+		  "ELEMENTS", "ELEMENTS", "Names of Elements", &_elemlist,
+		  "PROCESS", cpBool, "Enable processing configuration", 
+		  &exec_finish_configuration,
+		  "CONN", cpBool, 
+		  "Has a notion of connection state", &connection_oriented,
+		  "UPSTREAM", "ELEMENTS", "Names of Upstream Elements", 
+				  &_upstream_element_list,
+		  "DOWNSTREAM", "ELEMENTS", "Names of Downstream Elements", 
+				  &_downstream_element_list,
+		  "DEBUG", cpBool, "Debug option enabled for this module",
+				  &debug, 
+		  cpEnd) < 0)
+    return -1; 
+  
+  
+  if (_upstream_element_list.size() > 0 || 
+      _downstream_element_list.size() > 0 ) 
+    _preconfigured_element_list = true; 
+  
+  for(int i = 0; i < _upstream_element_list.size(); i++){
+    Element *e = _upstream_element_list[i]; 
+    click_chatter("[%s] upstream_element[%d]: index = %d %s \n", 
+		  instance_name(), i, 
+		  e->eindex(), e->class_name()); 
+  };
+  
+  for(int i = 0; i < _downstream_element_list.size(); i++){
+    Element *e = _downstream_element_list[i]; 
+    click_chatter("[%s] downstream_element[%d]: index = %d %s \n", 
+		  instance_name(), i, 
+		  e->eindex(), e->class_name()); 
+  };
+  
+
+
+  return 0;
+};
+
+
+// This will be overridden by individual elements. 
+//
+int 
+RNAElement::finish_configuration() {
+  // Do nothing...
+  return 0; 
+}
+
+int 
+RNAElement::rna_finish_configuration() {
+  // Do nothing...
+  rna_click_chatter(FUNC_ENTRY,"[%s] rna_finish_configuration Enter/Exit\n", 
+		    instance_name()); 
+
+  return 0; 
+}
Index: rna/elements/rna/shared_namespaces.txt
diff -u /dev/null rna/elements/rna/shared_namespaces.txt:1.4
--- /dev/null	Sun Jan 25 11:47:10 2009
+++ rna/elements/rna/shared_namespaces.txt	Fri Dec 26 16:57:00 2008
@@ -0,0 +1,87 @@
+#ifndef __SHARED_NAMESPACES_
+#define __SHARED_NAMESPACES_
+
+enum RNAElementType {
+  ELEMTYPE_BEGIN,
+  ANY,
+  BUFFER, 
+  CONTROL, 
+  CRYPT,
+  DEMULTIPLEXOR,
+  DISCOVERY,
+  ENCRYPTION,
+  FLEXLINK, 
+  MULTIPLEXOR,
+  MULTITUNNEL, 
+  MUXDEMUX, 
+  NEGOTIATE,
+  NETSTACK, 
+  OPTIONS, 
+  PKTSRC, 
+  REORDERBUFFER,
+  REXMIT, 
+  RINGBUFFER, 
+  ROOT, 
+  TUNNEL, 
+  UNKNOWN, 
+  ELEMTYPE_END
+};
+
+// Only a small number of commands are supported. 
+enum PatternRuleType {
+  PATTERN_BEGIN, 
+  PATTERN_FOLLOWS,        // Follows pattern X
+  PATTERN_REQ,            // Requires n instances of module 
+  PATTERN_CAPABILITY,     // What does the metaprotocol require/provide
+                          // incorporating this pattern?
+  PATTERN_ARG,            // Pass variable X with value Y to module X
+  PATTERN_LINK,
+  PATTERN_END
+};
+
+// What is the nature of constraint? 
+enum ConstraintType {
+  CONSTRAINT_BEGIN,
+  CONSTRAINT_REQUIRE_MUST,  // A requirement must be followed 
+  // There may be others e.g., MAY, PREFERABLY 
+  CONSTRAINT_END,
+};
+
+//What is the nature of the LINK configuration operation? 
+enum LinkOP {
+  LINK_OP_BEGIN, 
+  LINK_OP_ADD,                    // Add a link
+  LINK_OP_DEL,                    // Delete a link
+  LINK_OP_END
+}; 
+
+// When should the configuration command be executed? 
+enum ConfigType {
+  CONF_BEGIN, 
+  CONF_CONFIG,               // During instantiation of the composition
+  CONF_UNCONFIG,             // During cleanup of a composition 
+  CONF_NONE,                 // No specific time for this configuration command...
+  CONF_END
+}; 
+
+
+enum CapabilityVar {
+  CAP_VAR_BEGIN,
+  CAP_VAR_CONNECTION_ORIENTED,
+  CAP_VAR_MULTIHOP,
+  CAP_VAR_MULTIPOINT,
+  CAP_VAR_LOSSY, 
+  CAP_VAR_END
+};
+
+enum CapabilityCheck {
+  CAP_CHK_BEGIN,
+  CAP_CHK_PRESENT, 
+  CAP_CHK_ABSENT,
+  CAP_CHK_MATCH,
+  CAP_CHK_PROVIDE, 
+  CAP_CHK_NOTPROVIDE, 
+  CAP_CHK_END
+};
+
+#endif
Index: rna/elements/userlevel/fromdump.cc
diff -u rna/elements/userlevel/fromdump.cc:1.1.10.1 rna/elements/userlevel/fromdump.cc:1.3
--- rna/elements/userlevel/fromdump.cc:1.1.10.1	Mon Sep  8 11:36:18 2008
+++ rna/elements/userlevel/fromdump.cc	Mon Sep  8 10:51:31 2008
@@ -516,7 +516,11 @@
     case H_ENCAP:
 	return String(fake_pcap_unparse_dlt(fd->_linktype));
     case H_PACKET_FILEPOS:
+	#ifdef RNA 
+	return String((long int)fd->_packet_filepos);
+	#else 
 	return String(fd->_packet_filepos);
+	#endif 
     case H_COUNT:
 	return String(fd->_count);
     default:
Index: rna/elements/userlevel/fromfile.cc
diff -u rna/elements/userlevel/fromfile.cc:1.1.10.1 rna/elements/userlevel/fromfile.cc:1.3
--- rna/elements/userlevel/fromfile.cc:1.1.10.1	Mon Sep  8 11:36:19 2008
+++ rna/elements/userlevel/fromfile.cc	Mon Sep  8 10:51:31 2008
@@ -543,7 +543,7 @@
     FromFile *fd = reinterpret_cast<FromFile *>((uint8_t *)e + (intptr_t)thunk);
     struct stat s;
     if (fd->_fd >= 0 && fstat(fd->_fd, &s) >= 0 && S_ISREG(s.st_mode))
-	return String(s.st_size);
+	return String((unsigned int)s.st_size);
     else
 	return "-";
 }
@@ -552,7 +552,7 @@
 FromFile::filepos_handler(Element* e, void* thunk)
 {
     FromFile* fd = reinterpret_cast<FromFile*>((uint8_t*)e + (intptr_t)thunk);
-    return String(fd->_file_offset + fd->_pos);
+    return String((unsigned int)(fd->_file_offset + fd->_pos));
 }
 
 int
Index: rna/elements/userlevel/umlswitch.cc
diff -u rna/elements/userlevel/umlswitch.cc:1.1.10.1 rna/elements/userlevel/umlswitch.cc:1.1.3.1
--- rna/elements/userlevel/umlswitch.cc:1.1.10.1	Mon Sep  8 11:36:16 2008
+++ rna/elements/userlevel/umlswitch.cc	Mon Sep  8 09:46:50 2008
@@ -5,7 +5,7 @@
  * Mark Huang <mlhuang@cs.princeton.edu>
  * Copyright (C) 2005 The Trustees of Princeton University
  *
- * $Id: umlswitch.cc,v 1.1.10.1 2008/09/08 18:36:16 pingali Exp $
+ * $Id: umlswitch.cc,v 1.1.3.1 2008/09/08 16:46:50 pingali Exp $
  */
 
 #include <click/config.h>
Index: rna/elements/wifi/rc4.hh
diff -u rna/elements/wifi/rc4.hh:1.1.10.1 rna/elements/wifi/rc4.hh:1.2
--- rna/elements/wifi/rc4.hh:1.1.10.1	Mon Sep  8 11:36:10 2008
+++ rna/elements/wifi/rc4.hh	Mon Sep  8 10:51:36 2008
@@ -35,7 +35,7 @@
  * OF SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/crypto/rc4/rc4.h,v 1.3 2000/07/16 05:53:14 peter Exp $
- * $Id: rc4.hh,v 1.1.10.1 2008/09/08 18:36:10 pingali Exp $
+ * $Id: rc4.hh,v 1.2 2008/09/08 17:51:36 pingali Exp $
  */
 
 #ifndef CLICK_RC4
Index: rna/etc/linux-2.2.18-patch
diff -u rna/etc/linux-2.2.18-patch:1.1.10.1 rna/etc/linux-2.2.18-patch:1.2
--- rna/etc/linux-2.2.18-patch:1.1.10.1	Mon Sep  8 11:35:23 2008
+++ rna/etc/linux-2.2.18-patch	Mon Sep  8 10:51:43 2008
@@ -882,7 +882,7 @@
 *** 49,62 ****
   static const char *version =
   "eepro100.c:v1.09j-t 9/29/99 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/eepro100.html\n"
-  "eepro100.c: $Revision: 1.1.10.1 $ 2000/05/31 Modified by Andrey V. Savochkin <saw@saw.sw.com.sg> and others\n"
+  "eepro100.c: $Revision: 1.2 $ 2000/05/31 Modified by Andrey V. Savochkin <saw@saw.sw.com.sg> and others\n"
 ! "eepro100.c: VA Linux custom, Dragan Stancevic <visitor@valinux.com> 2000/11/15\n";
   
   /* A few user-configurable values that apply to all boards.
@@ -897,7 +897,7 @@
 --- 49,69 ----
   static const char *version =
   "eepro100.c:v1.09j-t 9/29/99 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/eepro100.html\n"
-  "eepro100.c: $Revision: 1.1.10.1 $ 2000/05/31 Modified by Andrey V. Savochkin <saw@saw.sw.com.sg> and others\n"
+  "eepro100.c: $Revision: 1.2 $ 2000/05/31 Modified by Andrey V. Savochkin <saw@saw.sw.com.sg> and others\n"
 ! "eepro100.c: VA Linux custom, Dragan Stancevic <visitor@valinux.com> 2000/11/15\n"
 ! "eepro100.c: MIT click polling extensions\n";
 ! 
Index: rna/etc/linux-2.2.19-patch
diff -u rna/etc/linux-2.2.19-patch:1.1.10.1 rna/etc/linux-2.2.19-patch:1.2
--- rna/etc/linux-2.2.19-patch:1.1.10.1	Mon Sep  8 11:35:22 2008
+++ rna/etc/linux-2.2.19-patch	Mon Sep  8 10:51:43 2008
@@ -783,7 +783,7 @@
 *** 49,62 ****
   static const char *version =
   "eepro100.c:v1.09j-t 9/29/99 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/eepro100.html\n"
-  "eepro100.c: $Revision: 1.1.10.1 $ 2000/05/31 Modified by Andrey V. Savochkin <saw@saw.sw.com.sg> and others\n"
+  "eepro100.c: $Revision: 1.2 $ 2000/05/31 Modified by Andrey V. Savochkin <saw@saw.sw.com.sg> and others\n"
 ! "eepro100.c: VA Linux custom, Dragan Stancevic <visitor@valinux.com> 2000/11/15\n";
   
   /* A few user-configurable values that apply to all boards.
@@ -798,7 +798,7 @@
 --- 49,69 ----
   static const char *version =
   "eepro100.c:v1.09j-t 9/29/99 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/eepro100.html\n"
-  "eepro100.c: $Revision: 1.1.10.1 $ 2000/05/31 Modified by Andrey V. Savochkin <saw@saw.sw.com.sg> and others\n"
+  "eepro100.c: $Revision: 1.2 $ 2000/05/31 Modified by Andrey V. Savochkin <saw@saw.sw.com.sg> and others\n"
 ! "eepro100.c: VA Linux custom, Dragan Stancevic <visitor@valinux.com> 2000/11/15\n"
 ! "eepro100.c: MIT click polling extensions\n";
 ! 
Index: rna/etc/linux-2.4.20-wifi-patch
diff -u rna/etc/linux-2.4.20-wifi-patch:1.1.10.1 rna/etc/linux-2.4.20-wifi-patch:1.2
--- rna/etc/linux-2.4.20-wifi-patch:1.1.10.1	Mon Sep  8 11:35:21 2008
+++ rna/etc/linux-2.4.20-wifi-patch	Mon Sep  8 10:51:43 2008
@@ -580,7 +580,7 @@
  #endif /* WIRELESS_EXT */
  
 -static const char version[] = "airo.c 0.6 (Ben Reed & Javier Achirica)";
-+static const char version[] = "$Revision: 1.1.10.1 $";
++static const char version[] = "$Revision: 1.2 $";
  
  struct airo_info;
  
Index: rna/etc/linux-2.6.16.13-patch
diff -u rna/etc/linux-2.6.16.13-patch:1.1.10.1 rna/etc/linux-2.6.16.13-patch:1.2
--- rna/etc/linux-2.6.16.13-patch:1.1.10.1	Mon Sep  8 11:35:22 2008
+++ rna/etc/linux-2.6.16.13-patch	Mon Sep  8 10:51:43 2008
@@ -1477,7 +1477,7 @@
 +++ ./include/asm-m32r/module.h	2006-05-02 22:59:18.000000000 -0700
 @@ -3,7 +3,7 @@
  
- /* $Id: linux-2.6.16.13-patch,v 1.1.10.1 2008/09/08 18:35:22 pingali Exp $ */
+ /* $Id: linux-2.6.16.13-patch,v 1.2 2008/09/08 17:51:43 pingali Exp $ */
  
 -struct mod_arch_specific { };
 +EMPTY_STRUCT_DECL(mod_arch_specific);
Index: rna/etc/linux-2.6.19.2-patch
diff -u rna/etc/linux-2.6.19.2-patch:1.1.10.1 rna/etc/linux-2.6.19.2-patch:1.1.3.1
--- rna/etc/linux-2.6.19.2-patch:1.1.10.1	Mon Sep  8 11:35:22 2008
+++ rna/etc/linux-2.6.19.2-patch	Mon Sep  8 09:45:53 2008
@@ -1212,7 +1212,7 @@
 +++ ./include/asm-m32r/module.h	2007-02-01 22:37:01.000000000 -0800
 @@ -3,7 +3,7 @@
  
- /* $Id: linux-2.6.19.2-patch,v 1.1.10.1 2008/09/08 18:35:22 pingali Exp $ */
+ /* $Id: linux-2.6.19.2-patch,v 1.1.3.1 2008/09/08 16:45:53 pingali Exp $ */
  
 -struct mod_arch_specific { };
 +EMPTY_STRUCT_DECL(mod_arch_specific);
Index: rna/etc/ns-2.30-patch
diff -u rna/etc/ns-2.30-patch:1.1.10.1 rna/etc/ns-2.30-patch:1.1.3.1
--- rna/etc/ns-2.30-patch:1.1.10.1	Mon Sep  8 11:35:22 2008
+++ rna/etc/ns-2.30-patch	Mon Sep  8 09:45:54 2008
@@ -8199,7 +8199,7 @@
 --- ns-2.30-pure/tools/random.cc	2006-09-24 22:11:00.000000000 -0700
 +++ ns-2.30/tools/random.cc	2007-09-11 21:04:07.000000000 -0700
 @@ -34,7 +34,7 @@
-  * "@(#) $Header: /home/xbone/CVSROOT/rna/etc/ns-2.30-patch,v 1.1.10.1 2008/09/08 18:35:22 pingali Exp $ (LBL)";
+  * "@(#) $Header: /home/xbone/CVSROOT/rna/etc/ns-2.30-patch,v 1.1.3.1 2008/09/08 16:45:54 pingali Exp $ (LBL)";
   */
  
 -#ifndef WIN32
Index: rna/include/click/element.hh
diff -u rna/include/click/element.hh:1.1.10.1 rna/include/click/element.hh:1.3
--- rna/include/click/element.hh:1.1.10.1	Mon Sep  8 11:36:38 2008
+++ rna/include/click/element.hh	Mon Sep  8 10:51:50 2008
@@ -38,7 +38,9 @@
     virtual Packet* pull(int port);
     virtual Packet* simple_action(Packet*);
 
-    virtual bool run_task(Task *);	// return true iff did useful work
+    virtual bool run_task(Task *);    // return true iff did useful work
+    virtual bool run_task() CLICK_DEPRECATED;
+
     virtual void run_timer(Timer *);
 #if CLICK_USERLEVEL
     virtual void selected(int fd);
@@ -206,7 +208,6 @@
     inline void add_input() CLICK_ELEMENT_PORT_COUNT_DEPRECATED;
     inline void add_output() CLICK_ELEMENT_PORT_COUNT_DEPRECATED;
     
-    virtual bool run_task() CLICK_DEPRECATED;
     virtual void run_timer() CLICK_DEPRECATED;
     
   private:
@@ -236,6 +237,10 @@
     void initialize_ports(const int* input_codes, const int* output_codes);
     int connect_port(bool isoutput, int port, Element*, int);
     
+    // RNA commands...
+    int connect_port_rna(bool isoutput, int port, Element*, int);
+    int disconnect_port_rna(bool isoutput, int port, Element* e, int e_port);
+
     void add_default_handlers(bool writable_config);
 
     friend class Router;
Index: rna/include/click/router.hh
diff -u rna/include/click/router.hh:1.1.10.1 rna/include/click/router.hh:1.3
--- rna/include/click/router.hh:1.1.10.1	Mon Sep  8 11:36:37 2008
+++ rna/include/click/router.hh	Mon Sep  8 10:51:51 2008
@@ -125,6 +125,11 @@
     void activate(bool foreground, ErrorHandler* errh);
     inline void activate(ErrorHandler* errh);
 
+    // RNA
+    int update_connections();
+    void set_connections_rna();
+    int disconnect_rna(Element *, int, Element *, int);
+
     int new_notifier_signal(NotifierSignal& signal);
     //@}
 
Index: rna/lib/confparse.cc
diff -u rna/lib/confparse.cc:1.1.10.1 rna/lib/confparse.cc:1.3
--- rna/lib/confparse.cc:1.1.10.1	Mon Sep  8 11:35:29 2008
+++ rna/lib/confparse.cc	Mon Sep  8 10:52:00 2008
@@ -1340,7 +1340,7 @@
 bool
 cp_file_offset(const String &str, off_t *result)
 {
-# if SIZEOF_OFF_T == 4
+# if ((SIZEOF_OFF_T == 4) || !defined(HAVE_INT64_TYPES))
   return cp_integer(str, reinterpret_cast<uint32_t *>(result));
 # elif SIZEOF_OFF_T == 8 && HAVE_INT64_TYPES
   return cp_integer(str, reinterpret_cast<uint64_t *>(result));
Index: rna/lib/element.cc
diff -u rna/lib/element.cc:1.1.10.1 rna/lib/element.cc:1.4
--- rna/lib/element.cc:1.1.10.1	Mon Sep  8 11:35:27 2008
+++ rna/lib/element.cc	Mon Sep  8 10:52:00 2008
@@ -557,15 +557,24 @@
 int
 Element::set_nports(int new_ninputs, int new_noutputs)
 {
+    
+    //    click_chatter("Element::set_nports [%s,%d] Entering \n", class_name(), eindex()); 
+
     // exit on bad counts, or if already initialized
     if (new_ninputs < 0 || new_noutputs < 0)
 	return -EINVAL;
+
     if (_router && _router->_have_connections) {
+#ifndef RNA
+	// This section of the code had to be disabled because the
+	// reorganization is happening on the fly. there might be more
+	// cleaner ways of doing this!
 	if (_router->_state >= Router::ROUTER_PREINITIALIZE)
 	    return -EBUSY;
+#endif 
 	_router->_have_connections = false;
     }
-    
+
     // decide if inputs & outputs were inlined
     bool old_in_inline =
 	(_ports[0] == _inline_ports);
@@ -585,6 +594,10 @@
 	 || (new_noutputs <= INLINE_PORTS && !new_in_inline));
 
     // create new port arrays
+
+    //click_chatter("Element::set_nports [%s,%d] Allocating new ports
+    //(%d,%d) \n", class_name(), eindex(), new_ninputs, new_noutputs);
+
     Port *new_inputs =
 	(new_in_inline ? _inline_ports : new Port[new_ninputs]);
     if (!new_inputs)		// out of memory -- return
@@ -741,12 +754,16 @@
     for (int i = 0; i < ninputs(); i++) {
 	// allowed iff in_v[i] == VPULL
 	int port = (in_v[i] == VPULL ? 0 : -1);
+	//click_chatter("Element::initialize_ports inputs [%s, %d] Calling Port(%d)\n", 
+	//      class_name(), eindex(), i);
 	_ports[0][i] = Port(this, 0, port);
     }
     
     for (int o = 0; o < noutputs(); o++) {
 	// allowed iff out_v[o] != VPULL
 	int port = (out_v[o] == VPULL ? -1 : 0);
+	//click_chatter("Element::initialize_ports outputs [%s, %d] Calling Port(%d)\n", 
+	//      class_name(), eindex(), o);
 	_ports[1][o] = Port(this, 0, port);
     }
 }
@@ -754,13 +771,67 @@
 int
 Element::connect_port(bool isoutput, int port, Element* e, int e_port)
 {
-    if (port_active(isoutput, port)) {
+    if (isoutput && 0) {
+	click_chatter("Element::connect_port [%s] [%s, %d, %d]\t\t-->" 
+		      "\t[%s, %d, %d] active = %d \n",
+		      (isoutput ? "OUTPUT" : "INPUT"), 
+		      this->class_name(), eindex(), port, 
+		      e->class_name(), e->eindex(), e_port, 
+		      port_active(isoutput, port));
+	if (port_active(isoutput, port) == 0 || 1){
+	    int first = ((unsigned) port < (unsigned) nports(isoutput));
+	    int second = _ports[isoutput][port].port();
+	    click_chatter("Element::connect_port [%s] first = %d, second = %d \n", 
+			  this->class_name(), first, second);
+	};
+    };
+    
+    if (port_active(isoutput, port)) {	
+	//click_chatter("Element::connect_port Calling Port()\n");
 	_ports[isoutput][port] = Port(this, e, e_port);
 	return 0;
     } else
 	return -1;
 }
 
+#ifdef RNA 
+
+// Free up the port information within the element.
+int
+Element::disconnect_port_rna(bool isoutput, int port, Element* e, int e_port)
+{
+    if (1) 
+	click_chatter("Element::disconnect_port_rna [%s, %d, %d]\t\t-->" 
+		      "\t[%s, %d, %d] active = %d \n",
+		      this->class_name(), eindex(), port, 
+		      e->class_name(), e->eindex(), e_port, 
+		      port_active(isoutput, port));
+    
+    // if (port_active(isoutput, port)) {
+    _ports[isoutput][port] = Port(this, 0, -1);
+    return 0;
+    //} else
+    //return -1;
+};
+
+int
+Element::connect_port_rna(bool isoutput, int port, Element* e, int e_port)
+{
+    if (isoutput) 
+	click_chatter("Element::connect_port [%s, %d, %d]\t\t-->\t"
+		      "[%s, %d, %d] active = %d \n",
+		      this->class_name(), eindex(), port, 
+		      e->class_name(), e->eindex(), e_port, 
+		      port_active(isoutput, port));
+    
+    //    if (port_active(isoutput, port)) {
+    if (isoutput) 
+	_ports[isoutput][port] = Port(this, e, e_port);
+    return 0;
+    //    } else
+    // return -1;
+}
+#endif 
 
 // FLOW
 
Index: rna/lib/router.cc
diff -u rna/lib/router.cc:1.1.10.1 rna/lib/router.cc:1.3
--- rna/lib/router.cc:1.1.10.1	Mon Sep  8 11:35:27 2008
+++ rna/lib/router.cc	Mon Sep  8 10:52:01 2008
@@ -213,7 +213,7 @@
 Router::find(const String &name, Element *context, ErrorHandler *errh) const
 {
   String prefix = ename(context->eindex());
-  int slash = prefix.find_right('/');
+  int slash = prefix.find_right('/');  
   return find(name, (slash >= 0 ? prefix.substring(0, slash + 1) : String()), errh);
 }
 
@@ -338,8 +338,13 @@
 Router::add_connection(int from_idx, int from_port, int to_idx, int to_port)
 {
     assert(from_idx >= 0 && from_port >= 0 && to_idx >= 0 && to_port >= 0);
+
+#ifndef RNA
+    // This prevents runtime reconfiguration of the router. So has
+    // been disabled. - Venkata Sep 2007 
     if (_state != ROUTER_NEW)
 	return -1;
+#endif
     Hookup hfrom(from_idx, from_port);
     Hookup hto(to_idx, to_port);
     // only add new connections
@@ -651,9 +656,16 @@
   
     if (errh->nerrors() != before)
 	return -1;
+    
+    for (int e = 0; e < nelements(); e++){
+
+	//click_chatter("[Router::check_push_and_pull] [%s,%d] Calling
+	//initialize ports here \n", _elements[e]->class_name(),
+	//_elements[e]->eindex());
 
-    for (int e = 0; e < nelements(); e++)
 	_elements[e]->initialize_ports(input_pers.begin() + _gports[0].e2g[e], output_pers.begin() + _gports[1].e2g[e]);
+
+    };
     return 0;
 }
 
@@ -751,13 +763,21 @@
     make_hookup_gports();
     int nresult = ngports(!forward);
     int nsource = ngports(forward);
-    
+
     Bitvector old_results(nresult, false);
     results.assign(nresult, false);
     Bitvector diff, scratch;
     
+    if (0) printf("%s->nports(%s) = %d ; nresult = %d, nsource = %d\n", 
+		  first_element->class_name(), 
+		  (forward ? "forward" : "backward"), 
+		  first_element->nports(forward), nresult, nsource);
+    
     Bitvector source(nsource, false);
     int first_gport = _gports[forward].e2g[first_element->eindex()];
+    if (0) printf("first_gport = %d, first_port = %d \n", 
+		  first_gport, first_port); 
+
     if (first_port < 0)
 	for (int i = 0; i < first_element->nports(forward); i++)
 	    source[first_gport + i] = true;
@@ -765,14 +785,22 @@
 	source[first_gport + first_port] = true;
 
     while (true) {
+	if (0) printf("Another iteration \n"); 
+
 	old_results = results;
 
-	for (const int* gfrom = _hookup_gports[forward].begin(); gfrom < _hookup_gports[forward].end(); gfrom++)
+	for (const int* gfrom = _hookup_gports[forward].begin(); gfrom < _hookup_gports[forward].end(); gfrom++){
+
+	    if (0) printf("Looking at gfrom = %d ", *gfrom);
+
 	    if (source[*gfrom]) {
 		int i = gfrom - _hookup_gports[forward].begin();
+		if (0) printf(" Selected...i = %d \n", i); 
 		results[_hookup_gports[!forward][i]] = true;
+	    } else {
+		if (0) printf("\n"); 
 	    }
-    
+	}
 	diff = results - old_results;
 	if (diff.zero())
 	    break;
@@ -862,6 +890,83 @@
 	    _elements[i]->add_handlers();
 }
 
+#ifdef RNA 
+
+// This enables runtime disconnection between modules. 
+int 
+Router::disconnect_rna(Element *from_e, int from_port, Element *to_e, int to_port){
+    
+    if (!from_e || !to_e) 
+	return -1; 
+
+    int from_idx = from_e->eindex();
+    int to_idx   =   to_e->eindex();
+    
+    // Deallocate the ports corresponding to this link in the individual 
+    // elements. 
+    int found_c = -1; 
+    for (int c = 0; c < _hookup_from.size(); c++) {
+	Hookup& hfrom = _hookup_from[c];
+	Hookup& hto = _hookup_to[c];
+	
+	if (hfrom.idx  == from_idx && 
+	    hfrom.port == from_port && 
+	    hto.idx    == to_idx && 
+	    hto.port   == to_port) {
+	
+	    found_c = c; 
+    
+	    from_e->disconnect_port_rna(true, hfrom.port, to_e, hto.port);
+	    to_e->disconnect_port_rna(false, hto.port, from_e, hfrom.port);
+	    break; 
+
+	};
+    };
+    
+    // Delete the hookup entry as well. 
+    if (found_c >= 0) {
+	_hookup_from[found_c] = _hookup_from.back(); 
+	_hookup_from.pop_back(); 
+	_hookup_to[found_c] = _hookup_to.back(); 
+	_hookup_to.pop_back(); 
+    };
+    
+    
+    return 0; 
+};
+
+void
+Router::set_connections_rna()
+{
+    // actually assign ports
+    for (int c = 0; c < _hookup_from.size(); c++) {
+	Hookup& hfrom = _hookup_from[c];
+	Element* frome = _elements[hfrom.idx];
+	Hookup& hto = _hookup_to[c];
+	Element* toe = _elements[hto.idx];
+	frome->connect_port_rna(true, hfrom.port, toe, hto.port);
+	toe->connect_port_rna(false, hto.port, frome, hfrom.port);
+    }
+    _have_connections = true;
+}
+
+int Router::update_connections() { 
+    
+    ErrorHandler *errh = ErrorHandler::default_handler(); 
+
+    //click_chatter("Router::update_connections() \n"); 
+    
+    //check_hookup_range(errh, false);
+    //check_hookup_completeness(errh, false);
+    check_hookup_range(errh); 
+    check_push_and_pull(errh);
+    make_gports();
+    set_connections();
+
+    return 0; 
+};
+#endif 
+
 int
 Router::initialize(ErrorHandler *errh)
 {
