[commits] r1634 - in trunk/batman-experimental: . lib/bmx_gsf_map lib/bmx_howto_plugin lib/bmx_http_info lib/bmx_uci_config linux posix

postmaster at open-mesh.net postmaster at open-mesh.net
Thu Apr 15 10:16:39 CEST 2010


Author: axel
Date: 2010-04-15 10:16:16 +0200 (Thu, 15 Apr 2010)
New Revision: 1634

Added:
   trunk/batman-experimental/avl.c
   trunk/batman-experimental/avl.h
Modified:
   trunk/batman-experimental/CHANGELOG
   trunk/batman-experimental/Makefile
   trunk/batman-experimental/allocate.c
   trunk/batman-experimental/batman.c
   trunk/batman-experimental/batman.h
   trunk/batman-experimental/control.c
   trunk/batman-experimental/control.h
   trunk/batman-experimental/hna.c
   trunk/batman-experimental/hna.h
   trunk/batman-experimental/lib/bmx_gsf_map/Makefile
   trunk/batman-experimental/lib/bmx_gsf_map/gsf_map.c
   trunk/batman-experimental/lib/bmx_howto_plugin/howto_plugin.c
   trunk/batman-experimental/lib/bmx_http_info/http_info.c
   trunk/batman-experimental/lib/bmx_uci_config/HOWTO
   trunk/batman-experimental/lib/bmx_uci_config/uci_config.c
   trunk/batman-experimental/lib/bmx_uci_config/uci_config.h
   trunk/batman-experimental/linux/route.c
   trunk/batman-experimental/list-batman.c
   trunk/batman-experimental/list-batman.h
   trunk/batman-experimental/metrics.c
   trunk/batman-experimental/metrics.h
   trunk/batman-experimental/originator.c
   trunk/batman-experimental/originator.h
   trunk/batman-experimental/os.h
   trunk/batman-experimental/plugin.c
   trunk/batman-experimental/plugin.h
   trunk/batman-experimental/posix/posix.c
   trunk/batman-experimental/posix/tunnel.c
   trunk/batman-experimental/schedule.c
   trunk/batman-experimental/schedule.h
Log:
binary avl-tree, --ogi_power_save (mode), better OGM aggregation, many 64bit OS fixes, many cleanups

 - debug sorted originator lists (using a binary avl-tree instead of hash)
 - ogi_power_save (mode) for energy-restriced devices
 - many 64-bit fixes
 - harded ogm-aggregation and more tolerant acceptance of late OGMs (old SQNs) with --path_lounge_size

 - dead-path detection by concurrent path-quality observation using a  long-term and short-term observation window


Modified: trunk/batman-experimental/CHANGELOG
===================================================================
--- trunk/batman-experimental/CHANGELOG	2010-04-12 19:06:37 UTC (rev 1633)
+++ trunk/batman-experimental/CHANGELOG	2010-04-15 08:16:16 UTC (rev 1634)
@@ -3,7 +3,20 @@
 
 Important changes should be listed in the following, most recent changes on top:
 
+---------------------------------------------------------------------------------------------------
+2010-04-15 -
 
+ - debug sorted originator lists (using a binary avl-tree instead of hash)
+
+ - ogi_power_save (mode) for energy-restriced devices
+
+ - many 64-bit fixes
+
+ - harded ogm-aggregation and more tolerant acceptance of late OGMs (old SQNs) with --path_lounge_size
+
+ - dead-path detection by concurrent path-quality observation using a  long-term and short-term observation window
+
+
 ---------------------------------------------------------------------------------------------------
 2009-08-18 - bmx_http_info and bmx_gsf_map plugin, ...
 

Modified: trunk/batman-experimental/Makefile
===================================================================
--- trunk/batman-experimental/Makefile	2010-04-12 19:06:37 UTC (rev 1633)
+++ trunk/batman-experimental/Makefile	2010-04-15 08:16:16 UTC (rev 1634)
@@ -20,17 +20,17 @@
 REVISION_VERSION =	\"\ rv$(REVISION)\"
 
 
-CFLAGS +=	 -pedantic -Wall -W -Wno-unused-parameter -O1 -g3 -std=gnu99 -I./ -DREVISION_VERSION=$(REVISION_VERSION) -DDEBUG_MALLOC -DMEMORY_USAGE 
+CFLAGS +=	 -pedantic -Wall -W -Wno-unused-parameter -Os -g3 -std=gnu99 -I./ -DREVISION_VERSION=$(REVISION_VERSION) -DDEBUG_MALLOC -DMEMORY_USAGE
 
+#EXTRA_CFLAGS += -DTESTDEBUG
+#EXTRA_CFLAGS += -DNODEBUGALL
+
 # Recommended defines and approximate binary sizes with gcc-x86
 # -static
 # -pedantic -Wall -W -Wno-unused-parameter -O1 -g3 -std=gnu99
 # -pg  # "-pg" with openWrt toolchain results in "gcrt1.o: No such file" ?!
 #
 
-# compared to -O1 stripped:
-# -Os								- ~29k
-#	
 # -DDEBUG_MALLOC  						+ ~0k
 # -DMEMORY_USAGE 						+ ~1k
 # -DPROFILE_DATA	(some realtime profiling)		+ ~3k
@@ -38,6 +38,7 @@
 # optional defines (you may disable these features if you dont need it):
 # -DNOTRAILER							- ~3K
 # -DNODEBUGALL							- ~13k
+# -DLESS_OPTIONS                                                - ~7K
 #
 # -DNOTUNNEL  		(only affects this node)		- ~23k
 # -DNOSRV  		(only affects this node)		- ~3k
@@ -72,8 +73,8 @@
 
 SRC_FILES= "\(\.c\)\|\(\.h\)\|\(Makefile\)\|\(INSTALL\)\|\(LIESMICH\)\|\(README\)\|\(THANKS\)\|\(./posix\)\|\(./linux\)\|\(./man\)\|\(./doc\)"
 
-SRC_C= batman.c originator.c hna.c schedule.c plugin.c list-batman.c allocate.c hash.c profile.c control.c metrics.c $(OS_C)
-SRC_H= batman.h originator.h hna.h schedule.h plugin.h list-batman.h allocate.h hash.h profile.h control.h metrics.h vis-types.h os.h
+SRC_C= batman.c originator.c hna.c schedule.c plugin.c list-batman.c allocate.c avl.c profile.c control.c metrics.c $(OS_C)
+SRC_H= batman.h originator.h hna.h schedule.h plugin.h list-batman.h allocate.h avl.h profile.h control.h metrics.h vis-types.h os.h
 OBJS=  $(SRC_C:.c=.o)
 
 #PACKAGE_NAME=	batmand-exp
@@ -99,7 +100,7 @@
 
 all:	
 	$(MAKE) $(BINARY_NAME)
-	$(MAKE) help
+	# further make targets: help, libs, build_all, strip[_libs|_all], install[_libs|_all], clean[_libs|_all]
 
 libs:	all
 	$(MAKE) -C lib all
@@ -148,7 +149,7 @@
 
 
 help:
-	# make targets:
+	# further make targets:
 	# help					show this help
 	# all					compile  bmxd core only
 	# libs			 		compile  bmx plugins

Modified: trunk/batman-experimental/allocate.c
===================================================================
--- trunk/batman-experimental/allocate.c	2010-04-12 19:06:37 UTC (rev 1633)
+++ trunk/batman-experimental/allocate.c	2010-04-15 08:16:16 UTC (rev 1634)
@@ -193,8 +193,7 @@
 		for (walker = chunkList; walker != NULL; walker = walker->next) {
 			syslog( LOG_ERR, "Memory leak detected, malloc tag = %d\n", walker->tag );
 		
-			if (debug_level >= 0)
-				fprintf( stderr, "Memory leak detected, malloc tag = %d \n", walker->tag );
+			fprintf( stderr, "Memory leak detected, malloc tag = %d \n", walker->tag );
 			
 		}
 		

Added: trunk/batman-experimental/avl.c
===================================================================
--- trunk/batman-experimental/avl.c	                        (rev 0)
+++ trunk/batman-experimental/avl.c	2010-04-15 08:16:16 UTC (rev 1634)
@@ -0,0 +1,316 @@
+/* Copyright (C) 2006 B.A.T.M.A.N. contributors:
+ * Axel Neumann
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ *
+ */
+
+/*
+ * avl code inspired by:
+ * http://eternallyconfuzzled.com/tuts/datastructures/jsw_tut_avl.aspx
+ * where Julienne Walker said ( 28. 2. 2010 12:55):
+ * ...Once again, all of the code in this tutorial is in the public domain.
+ * You can do whatever you want with it, but I assume no responsibility
+ * for any damages from improper use. ;-)
+ */
+
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+
+#include "batman.h"
+#include "os.h"
+
+#include "avl.h"
+
+
+void *avl_find( struct avl_tree *tree, void *key )
+{
+
+        struct avl_node *it = tree->root;
+        int cmp;
+
+        // Search for a dead path or a matching entry
+        while ( it  &&  ( cmp = memcmp(it->key, key, tree->key_size) ) )
+                it = it->link[ cmp < 0 ];
+
+
+        return it ? it->key : NULL;
+}
+
+
+
+void *avl_next(struct avl_tree *tree, void *key)
+{
+        struct avl_node *it = tree->root;
+        void *best = NULL;
+
+        if ( !it )
+                return NULL;
+
+        while (it) {
+
+                if ( memcmp(it->key, key, tree->key_size) <= 0 ) { 
+
+                        if (it->link[1]) {
+                                it = it->link[1];
+                                continue;
+                        } else {
+                                return best;
+                        }
+
+                } else {
+
+                        if (it->link[0]) {
+                                best = it->key;
+                                it = it->link[0];
+                                continue;
+                        } else {
+                                return it->key;
+                        }
+
+                }
+
+        }
+
+        paranoia( -500177, 1 );
+        return NULL;
+}
+
+
+
+static struct avl_node *avl_create_node(void *key)
+{
+        struct avl_node *an = debugMalloc(sizeof (struct avl_node), 327);
+
+        paranoia( -500189, !an );
+        memset( an, 0, sizeof( struct avl_node) );
+                an->key = key;
+
+        return an;
+}
+
+static struct avl_node *avl_rotate_single(struct avl_node *root, int dir)
+{
+	struct avl_node *save = root->link[!dir];
+	int rlh, rrh, slh;
+
+	/* Rotate */
+	root->link[!dir] = save->link[dir];
+	save->link[dir] = root;
+
+	/* Update balance factors */
+	rlh = avl_height(root->link[0]);
+	rrh = avl_height(root->link[1]);
+	slh = avl_height(save->link[!dir]);
+
+	root->balance = avl_max(rlh, rrh) + 1;
+	save->balance = avl_max(slh, root->balance) + 1;
+
+	return save;
+}
+
+static struct avl_node *avl_rotate_double(struct avl_node *root, int dir)
+{
+	root->link[!dir] = avl_rotate_single(root->link[!dir], !dir);
+	return avl_rotate_single(root, dir);
+}
+
+
+void avl_insert(struct avl_tree *tree, void *key) {
+        
+        if (tree->root) {
+
+                struct avl_node *it = tree->root;
+                struct avl_node *up[AVL_MAX_HEIGHT];
+                int upd[AVL_MAX_HEIGHT], top = 0;
+                int done = 0;
+
+                /* Search for an empty link, save the path */
+                for (;;) {
+                        /* Push direction and node onto stack */
+                        upd[top] = memcmp(it->key, key, tree->key_size) < 0;
+                        up[top++] = it;
+
+                        if (it->link[upd[top - 1]] == NULL)
+                                break;
+
+                        it = it->link[upd[top - 1]];
+                }
+
+                /* Insert a new node at the bottom of the tree */
+                it->link[upd[top - 1]] = avl_create_node(key);
+
+                paranoia(-500178, (it->link[upd[top - 1]] == NULL));
+
+                /* Walk back up the search path */
+                while (--top >= 0 && !done) {
+
+                        int lh, rh, max;
+
+                        lh = avl_height(up[top]->link[upd[top]]);
+                        rh = avl_height(up[top]->link[!upd[top]]);
+
+                        /* Terminate or rebalance as necessary */
+                        if (lh - rh == 0)
+                                done = 1;
+                        if (lh - rh >= 2) {
+                                struct avl_node *a = up[top]->link[upd[top]]->link[upd[top]];
+                                struct avl_node *b = up[top]->link[upd[top]]->link[!upd[top]];
+
+                                if (avl_height(a) >= avl_height(b))
+                                        up[top] = avl_rotate_single(up[top], !upd[top]);
+                                else
+                                        up[top] = avl_rotate_double(up[top], !upd[top]);
+
+                                /* Fix parent */
+                                if (top != 0)
+                                        up[top - 1]->link[upd[top - 1]] = up[top];
+                                else
+                                        tree->root = up[0];
+
+                                done = 1;
+                        }
+
+                        /* Update balance factors */
+                        lh = avl_height(up[top]->link[upd[top]]);
+                        rh = avl_height(up[top]->link[!upd[top]]);
+                        max = avl_max(lh, rh);
+
+                        up[top]->balance = max + 1;
+                }
+        
+        } else {
+
+                tree->root = avl_create_node(key);
+                paranoia( -500179, (tree->root==NULL));
+
+        }
+
+        return;
+}
+
+
+
+void avl_remove(struct avl_tree *tree, void *key)
+{
+        struct avl_node *it = tree->root;
+        struct avl_node *up[AVL_MAX_HEIGHT];
+        int upd[AVL_MAX_HEIGHT], top = 0, cmp;
+
+        paranoia(-500182, !it); // paranoia if not found
+
+        while ((cmp = memcmp(it->key, key, tree->key_size))) {
+
+                // Push direction and node onto stack
+                upd[top] = (cmp < 0);
+                up[top] = it;
+
+                it = it->link[(cmp < 0)];
+                top++;
+                paranoia(-500180, !it); // paranoia if not found
+        }
+
+        // Remove the node:
+        if (!(it->link[0] && it->link[1])) { // at least one child is NULL:
+                
+                // Which child is not null?
+                int dir = !(it->link[0]);
+
+                /* Fix parent */
+                if (top)
+                        up[top - 1]->link[upd[top - 1]] = it->link[dir];
+                else
+                        tree->root = it->link[dir];
+
+                debugFree(it, 1327);
+
+        } else { // both childs NOT NULL:
+
+                // Find the inorder successor
+                struct avl_node *heir = it->link[1];
+
+                // Save the path
+                upd[top] = 1;
+                up[top] = it;
+                top++;
+
+                while (heir->link[0]) {
+                        upd[top] = 0;
+                        up[top] = heir;
+                        top++;
+                        heir = heir->link[0];
+                }
+
+                // Swap data
+                it->key = heir->key;
+
+                // Unlink successor and fix parent
+                up[top - 1]->link[ (up[top - 1] == it) ] = heir->link[1];
+
+                debugFree(heir, 2327);
+        }
+
+        // Walk back up the search path
+        while (--top >= 0) {
+                int lh = avl_height(up[top]->link[upd[top]]);
+                int rh = avl_height(up[top]->link[!upd[top]]);
+                int max = avl_max(lh, rh);
+
+                /* Update balance factors */
+                up[top]->balance = max + 1;
+
+
+                // Terminate or re-balance as necessary:
+                if (lh - rh >= 0)  // re-balance upper path...
+                        continue;
+
+                if (lh - rh == -1) // balance for upper path unchanged!
+                        break;
+
+                if (!(up[top]) || !(up[top]->link[!upd[top]])) {
+                        dbgf(DBGL_SYS, DBGT_ERR, "up(top) %p  link %p   lh %d   rh %d",
+                                (void*)(up[top]), (void*)((up[top]) ? (up[top]->link[!upd[top]]) : NULL), lh, rh);
+
+                        paranoia(-500187, (!(up[top])));
+                        paranoia(-500188, (!(up[top]->link[!upd[top]])));
+                }
+/*
+                paranoia(-500183, (lh - rh <= -3) );
+                paranoia(-500185, (lh - rh == 2) );
+                paranoia(-500186, (lh - rh >= 3) );
+*/
+
+                // if (lh - rh <= -2):  rebalance here and upper path
+
+                struct avl_node *a = up[top]->link[!upd[top]]->link[upd[top]];
+                struct avl_node *b = up[top]->link[!upd[top]]->link[!upd[top]];
+
+                if (avl_height(a) <= avl_height(b))
+                        up[top] = avl_rotate_single(up[top], upd[top]);
+                else
+                        up[top] = avl_rotate_double(up[top], upd[top]);
+
+                // Fix parent:
+                if (top)
+                        up[top - 1]->link[upd[top - 1]] = up[top];
+                else
+                        tree->root = up[0];
+        }
+
+}
+

Added: trunk/batman-experimental/avl.h
===================================================================
--- trunk/batman-experimental/avl.h	                        (rev 0)
+++ trunk/batman-experimental/avl.h	2010-04-15 08:16:16 UTC (rev 1634)
@@ -0,0 +1,63 @@
+/* Copyright (C) 2006 B.A.T.M.A.N. contributors:
+ * Axel Neumann
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ *
+ */
+
+/*
+ * avl code based on:
+ * http://eternallyconfuzzled.com/tuts/datastructures/jsw_tut_avl.aspx
+ * where Julienne Walker said ( 28. 2. 2010 12:55):
+ * ...Once again, all of the code in this tutorial is in the public domain.
+ * You can do whatever you want with it, but I assume no responsibility
+ * for any damages from improper use. ;-)
+ */
+
+#ifndef _AVL_H
+#define _AVL_H
+
+#include <stdint.h>
+
+
+struct avl_node {
+        void *key;
+        int balance;
+        struct avl_node * link[2];
+};
+
+struct avl_tree {
+	uint16_t key_size;
+        struct avl_node *root;
+};
+
+
+#define AVL_INIT_TREE(tree, size) do { 	tree.root = NULL; tree.key_size = (size); } while (0)
+#define AVL_TREE(tree, size) struct avl_tree (tree) = { (size), NULL }
+
+
+#define AVL_MAX_HEIGHT 128
+
+#define avl_height(p) ((p) == NULL ? -1 : (p)->balance)
+#define avl_max(a,b) ((a) > (b) ? (a) : (b))
+
+void *avl_find( struct avl_tree *tree, void *key );
+void *avl_next( struct avl_tree *tree, void *key );
+void avl_insert(struct avl_tree *tree, void *key);
+void avl_remove(struct avl_tree *tree, void *key);
+
+
+
+#endif
\ No newline at end of file

Modified: trunk/batman-experimental/batman.c
===================================================================
--- trunk/batman-experimental/batman.c	2010-04-12 19:06:37 UTC (rev 1633)
+++ trunk/batman-experimental/batman.c	2010-04-15 08:16:16 UTC (rev 1634)
@@ -33,6 +33,7 @@
 #include "metrics.h"
 #include "plugin.h"
 #include "schedule.h"
+//#include "avl.h"
 
 
 
@@ -65,7 +66,7 @@
 
 int32_t Gateway_class = 0;
 
-uint8_t Link_flags = 0;
+//uint8_t Link_flags = 0;
 
 uint32_t batman_time = 0;
 uint32_t batman_time_sec = 0;
@@ -74,8 +75,6 @@
 
 uint32_t s_curr_avg_cpu_load = 0;
 
-int Trash;
-
 void batman( void ) {
 
 	struct list_head *list_pos;
@@ -206,7 +205,7 @@
 	((struct vis_packet *)vis_packet)->sender_ip = primary_addr;
 	((struct vis_packet *)vis_packet)->version = VIS_COMPAT_VERSION;
 	((struct vis_packet *)vis_packet)->gw_class = Gateway_class;
-	((struct vis_packet *)vis_packet)->seq_range = my_lws;  
+	((struct vis_packet *)vis_packet)->seq_range = local_lws;
 
 	
 	/* iterate link list */
@@ -552,22 +551,22 @@
 
 static int32_t opt_srvs ( uint8_t cmd, uint8_t _save, struct opt_type *opt, struct opt_parent *patch, struct ctrl_node *cn ) {
 	
-	struct hash_it_t *hashit = NULL;
-
 	int dbg_ogm_out = 0;
 	static char dbg_ogm_str[MAX_DBG_STR_SIZE + 1]; // TBD: must be checked for overflow when 
-
+        struct orig_node *on;
 	uint16_t srv_count = 0;
 
 	if ( cmd != OPT_APPLY )
 		return SUCCESS;
 	
 	dbg_printf( cn, "Originator      Announced services ip:port:seqno ...\n");
-	
-	while ( (hashit = hash_iterate( orig_hash, hashit )) ) {
 
-		struct orig_node *on = hashit->bucket->data;
+        uint32_t orig_ip = 0;
 
+        while ((on = (struct orig_node*) avl_next(&orig_avl, &orig_ip))) {
+
+                orig_ip = on->orig;
+
 		if ( on->router == NULL  ||  srv_orig_registry < 0  ||  on->plugin_data[srv_orig_registry] == NULL )
 			continue;
 
@@ -618,10 +617,8 @@
 
 static int32_t send_my_srv_ext( unsigned char* ext_buff ) {
 	
-	if ( my_srv_list_enabled )
-		memcpy( ext_buff, 
-		        (unsigned char *)my_srv_ext_array, 
-		        my_srv_list_enabled * sizeof(struct ext_packet) );
+	if ( my_srv_list_enabled)
+                memcpy(ext_buff, (unsigned char *) my_srv_ext_array, my_srv_list_enabled * sizeof (struct ext_packet));
 	
 	return my_srv_list_enabled * sizeof(struct ext_packet);
 

Modified: trunk/batman-experimental/batman.h
===================================================================
--- trunk/batman-experimental/batman.h	2010-04-12 19:06:37 UTC (rev 1633)
+++ trunk/batman-experimental/batman.h	2010-04-15 08:16:16 UTC (rev 1634)
@@ -28,10 +28,10 @@
 #include <linux/if.h>
 
 #include "list-batman.h"
-#include "hash.h"
 #include "control.h"
 #include "allocate.h"
 #include "profile.h"
+#include "avl.h"
 
 
 /***
@@ -61,9 +61,8 @@
  * Global Variables and definitions 
  */
 
+#define SOURCE_VERSION "0.3-rc1" //put exactly one distinct word inside the string like "0.3-pre-alpha" or "0.3-rc1" or "0.3"
 
-#define SOURCE_VERSION "0.3-alpha" //put exactly one distinct word inside the string like "0.3-pre-alpha" or "0.3-rc1" or "0.3"
-
 #define COMPAT_VERSION 10 
 
 
@@ -108,8 +107,9 @@
 
 #define MAX_GW_UNAVAIL_FACTOR 10 /* 10 */
 #define GW_UNAVAIL_TIMEOUT 10000
-#define CHOOSE_GW_DELAY_DIVISOR 1
 
+#define COMMON_OBSERVATION_WINDOW (DEF_OGI*DEF_PWS)
+
 #define MAX_SELECT_TIMEOUT_MS 400 /* MUST be smaller than (1000/2) to fit into max tv_usec */
 
 //#define TYPE_OF_WORD unsigned long /* you should choose something big, if you don't want to waste cpu */
@@ -137,13 +137,9 @@
 
 #define MAX( a, b ) ( (a>b) ? (a) : (b) )
 #define MIN( a, b ) ( (a<b) ? (a) : (b) )
+#define MAX_SQ( a, b ) ( (GREAT_SQ( (a), (b) )) ? (a) : (b) )
 
 
-#ifdef NOPARANOIA
-#define paranoia( ... )
-#else
-#define paranoia( code , problem ); do { if ( problem ) { cleanup_all( code ); } }while(0)
-#endif
 
 
 #define WARNING_PERIOD 20000
@@ -157,8 +153,7 @@
    could not be send by nodes with the old MAX_PACKET_SIZE = 256 */
 #define MIN_UDPD_SIZE 24
 #define DEF_UDPD_SIZE 256
-/* which is the maximum packet size which could be defined with the bat_header->size field */
-#define MAX_UDPD_SIZE 1024 
+#define MAX_UDPD_SIZE (255<<2) //the maximum packet size which could be defined with the bat_header->size field
 #define ARG_UDPD_SIZE "udp_data_size"
 
 #define MAX_MTU 1500
@@ -257,8 +252,6 @@
 
 extern uint32_t s_curr_avg_cpu_load;
 
-extern int Trash;
-
 #define SQ_TYPE uint16_t
 
 
@@ -272,24 +265,27 @@
 #define CLONED_FLAG		0x04 /* set when (re-)broadcasting a OGM not-for-the-first time or re-broadcasting a OGM with this flag */
 
 
-extern uint8_t Link_flags;
+//extern uint8_t Link_flags;
 
-#define UNICAST_PROBES_CAP 0x01 /* set on bat_header->link_flags to announce capability for unidirectional UDP link measurements */
+#define BAT_CAPAB_UNICAST_PROBES 0x01 /* set on bat_header->link_flags to announce capability for unidirectional UDP link measurements */
+#define BAT_CAPAB_ ...
 
 
 struct bat_header
 {
 	uint8_t  version;
-	uint8_t  link_flags; 	// UNICAST_PROBES_CAP, ...
+	uint8_t  link_flags; 	// BAT_CAPAB_UNICAST_PROBES, ...
 	uint8_t  reserved;
 	uint8_t  size; 		// the relevant data size in 4 oktets blocks of the packet (including the bat_header)
 } __attribute__((packed));
 
 
-#define BAT_TYPE_OGM 0x00	// originator message
-#define BAT_TYPE_UPM 0x01	// unicast link-probe message
+#define BAT_TYPE_OGM  0x00	// originator message
+#define BAT_TYPE_UPM  0x01	// unicast link-probe message
+#define BAT_TYPE_ ...
 
 
+
 struct bat_packet_common
 {
 #if __BYTE_ORDER == __LITTLE_ENDIAN
@@ -426,7 +422,6 @@
 	uint32_t		neigh;
 	char neigh_str[ADDR_STR_LEN];
 	int16_t			total_length;
-	uint8_t			link_flags;
 	uint8_t 		unicast;
 	
 	//filled by strip_packet()
@@ -460,10 +455,11 @@
 	uint8_t  own_if;
 	int32_t  ogm_buff_len;
 	struct batman_if *if_outgoing;
+	struct bat_packet_ogm *ogm;
 
 	// the following ogm_buff array MUST be aligned with bit-range of the OS (64bit for 64-bit OS)
 	// having a pointer right before ensures this alignment.
-	unsigned char ogm_buff[]; // this is to access following ogm data
+	unsigned char _attached_ogm_buff[]; // this is to access attached ogm data (only if allocated) !!!
 };
 
 
@@ -483,21 +479,22 @@
 	char dev_phy[IFNAMSIZ+1];
 	char if_ip_str[ADDR_STR_LEN];
 	
-	int32_t if_index;
 	uint8_t if_active;
 	uint8_t if_scheduling;
-	
-	uint8_t if_reserved;
-	
-	uint8_t  if_prefix_length;
+
+	uint16_t  if_prefix_length;
+
+	int32_t if_index;
+	uint32_t if_netaddr;
+	uint32_t if_addr;
+	uint32_t if_broad;
+
+
 	uint32_t if_netmask;
-	uint32_t if_netaddr;
 	
 	int32_t if_rp_filter_orig;
 	int32_t if_send_redirects_orig;
 	
-	uint32_t if_addr;
-	uint32_t if_broad;
 	
 	struct sockaddr_in if_unicast_addr;
 	struct sockaddr_in if_netwbrc_addr;
@@ -508,13 +505,18 @@
 	
 	SQ_TYPE if_seqno;
 	uint32_t if_seqno_schedule;
-	
-	struct send_node *own_send_node;
+	uint32_t if_last_link_activity;
+	uint32_t if_next_pwrsave_hardbeat;
+
+	/*
+	struct send_node own_send_struct;
 	struct bat_packet_ogm *own_ogm_out;
-	unsigned char own_send_buff[MAX_UDPD_SIZE + 1 + sizeof(struct send_node)];
+	 */
+
+	// having a pointer right before the following array ensures 32/64 bit alignment.
+	unsigned char *aggregation_out;
+	unsigned char aggregation_out_buff[MAX_UDPD_SIZE + 1];
 	
-	unsigned char aggregation_out[MAX_UDPD_SIZE + 1];
-	
 	int16_t aggregation_len;
 	
 	int8_t send_own;
@@ -527,6 +529,7 @@
 	int8_t if_linklayer;
 	
 	int16_t if_ttl_conf;
+	int16_t if_ttl;
 	
 	int16_t if_send_clones_conf;
 	int16_t if_send_clones;
@@ -542,13 +545,15 @@
 
 struct orig_node                 /* structure for orig_list maintaining nodes of mesh */
 {
-	uint32_t orig;          /* this must be the first four bytes! otherwise the hash functionality does not work */
+	uint32_t orig;          /* this must be the first four bytes! otherwise avl or hash functionality do not work */
 		
 	struct neigh_node *router;   /* the neighbor which is the currently best_next_hop */
 	
 	char orig_str[ADDR_STR_LEN];
 	
 	struct list_head_first neigh_list;
+	struct avl_tree neigh_avl;
+
 	
 	uint32_t last_aware;              /* when last valid ogm via  this node was received */
 	uint32_t last_valid_time;         /* when last valid ogm from this node was received */
@@ -558,22 +563,32 @@
 	SQ_TYPE last_decided_sqn;
 	SQ_TYPE last_accepted_sqn;              /* last squence number acceppted for metric */
 	SQ_TYPE last_valid_sqn;			/* last and best known squence number */
-	
+	SQ_TYPE last_wavg_sqn;                  /* last sequence number used for estimating ogi */
+
 	// From nodes with several interfaces we may know several originators, 
 	// this points to the originator structure of the primary interface of a node 
 	struct orig_node *primary_orig_node;
-	//struct list_head_first pog_referrer_list;
 	int16_t pog_refcnt;
 	
 	
 	//	uint8_t  last_accept_largest_ttl;  /* largest (best) TTL received with last sequence number */
 	uint8_t  last_path_ttl;
-	
+
 	uint8_t  ogx_flag;
 	uint8_t  pws;
-	uint8_t  path_lounge;
+//	uint8_t  path_lounge;
 	uint8_t  ogm_misc;
-	
+
+//	uint8_t path_hystere;
+//	uint8_t late_penalty;
+//	uint8_t hop_penalty;
+//	uint8_t asym_weight;
+
+//	uint8_t rcnt_pws;
+//	uint8_t rcnt_lounge;
+//	uint8_t rcnt_hystere;
+//	uint8_t rcnt_fk;
+
 	uint32_t ogi_wavg;
 	uint32_t rt_changes;
 	
@@ -595,25 +610,18 @@
 	
 };
 
-/*
-struct pog_referrer_node
-{
-	struct list_head list;
-	uint32_t addr;
-};
-*/
 
 #define SQN_LOUNGE_SIZE (8*sizeof(uint32_t)) /* must correspond to bits of neigh_node->considered_seqnos */
 
 struct sq_record {
 	
 	SQ_TYPE wa_clr_sqn; 	// SQN upto which waightedAverageVal has been purged
-	SQ_TYPE wa_set_sqn; 	// SQN which has been applied (if equals wa_pos) then wa_unscaled MUST NO be set again!
+	SQ_TYPE wa_set_sqn; 	// SQN which has been applied (if equals wa_pos) then wa_unscaled MUST NOT be set again!
 	uint32_t wa_unscaled;	// unscaled summary value of processed SQNs
 	uint32_t wa_val;	// scaled and representative value of processed SQNs
 	
-	uint8_t sqn_entry_queue[SQN_LOUNGE_SIZE];	// cache for greatest rcvd SQNs waiting to be processed
-	SQ_TYPE sqn_entry_queue_tip;			// the greatest SQN rcvd so fare
+//	uint8_t sqn_entry_queue[SQN_LOUNGE_SIZE];	// cache for greatest rcvd SQNs waiting to be processed
+//	SQ_TYPE sqn_entry_queue_tip;			// the greatest SQN rcvd so fare
 };
 
 
@@ -638,32 +646,39 @@
  */
 struct link_node
 {
+	uint32_t orig_addr;
+
 	struct list_head list;
-	
+
 	struct orig_node *orig_node;
-	uint8_t link_flags;
 	
 	struct list_head_first lndev_list; // list with one link_node_dev element per link
 
 };
 
+struct neigh_node_key {
+	uint32_t addr;
+	struct batman_if *iif;
+};
 
-
-
 /* Path statistics per neighbor via which OGMs of the parent orig_node have been received */
 /* Every OG has one ore several neigh_nodes. */
 struct neigh_node
 {
+
+	struct neigh_node_key key;
+#define nnkey_addr key.addr
+#define nnkey_iif key.iif
+//	uint32_t nnkey_addr;
+//	struct batman_if *nnkey_iif;
+
 	struct list_head list;
-	uint32_t addr;
 	uint32_t last_aware;            /* when last packet via this neighbour was received */
 	
-	uint32_t considered_seqnos;	//MUST have SQN_LOUNGE_SIZE bits
 	SQ_TYPE last_considered_seqno;
 	
-	struct batman_if *iif;
-	
-	struct sq_record accepted_sqr;
+	struct sq_record longtm_sqr;
+	struct sq_record recent_sqr;
 };
 
 

Modified: trunk/batman-experimental/control.c
===================================================================
--- trunk/batman-experimental/control.c	2010-04-12 19:06:37 UTC (rev 1633)
+++ trunk/batman-experimental/control.c	2010-04-15 08:16:16 UTC (rev 1634)
@@ -41,12 +41,20 @@
 
 static char run_dir[MAX_PATH_SIZE] = DEF_RUN_DIR;
 
-int32_t debug_level = -1;
+static int32_t debug_level = -1;
 static int32_t dbg_mute_to;
-static int32_t loop_period;
+
+#define MIN_LOOP_PERIOD 100
+#define MAX_LOOP_PERIOD 10000
+#define DEF_LOOP_PERIOD 1000
+static int32_t loop_period = DEF_LOOP_PERIOD;
+
 static int32_t loop_mode;
 
-static int32_t pedantic_cmd_check;
+#define MIN_PEDANT_CHK NO
+#define MAX_PEDANT_CHK YES
+#define DEF_PEDANT_CHK NO
+static int32_t pedantic_check = DEF_PEDANT_CHK;
 
 
 int unix_sock = 0;
@@ -246,7 +254,8 @@
 void close_ctrl_node( uint8_t cmd, struct ctrl_node *ctrl_node ) {
 
 	struct list_head* list_pos, *list_prev, *list_tmp;
-	
+	int trash;
+
 	list_prev = (struct list_head *)&ctrl_list;
 	
 	list_for_each_safe( list_pos, list_tmp, &ctrl_list ) {
@@ -265,7 +274,7 @@
 				
 				
 				if ( cmd == CTRL_CLOSE_SUCCESS )
-					Trash = write( cn->fd, CONNECTION_END_STR, strlen(CONNECTION_END_STR) );
+					trash=write( cn->fd, CONNECTION_END_STR, strlen(CONNECTION_END_STR) );
 				
 				if ( cmd != CTRL_CLOSE_DELAY ) {
 					close( cn->fd );
@@ -935,7 +944,7 @@
  * call given function for each applied option
  * thus: if several hna are active func() is called once for each
  */
-int8_t func_for_each_opt( struct ctrl_node *cn, void *data, struct opt_type *opt_tmpl, char* func_name, 
+int8_t func_for_each_opt( struct ctrl_node *cn, void *data, char* func_name, 
                           int8_t (*func) ( struct ctrl_node *cn, void *data, struct opt_type *opt, struct opt_parent *p, struct opt_child *c ) ) 
 {
 	
@@ -947,46 +956,33 @@
 		
 		if ( /* !opt->help  || we are also interested in uncommented configurations*/ !opt->long_name )
 			continue;
-		
-		if ( !( /*proceed if:*/ !opt_tmpl  ||  opt_tmpl == opt  ||  !list_empty(&opt->d.childs_type_list) )  )
-			continue;
-		
-		
+
 		struct list_head *p_pos;
 		
 		list_for_each( p_pos, &(opt->d.parents_instance_list) ) {
 			
 			struct opt_parent *p = (struct opt_parent*)list_entry( p_pos, struct opt_parent, list );
 			
-			if ( !opt_tmpl  ||  opt_tmpl  == opt ) {
-				
-				if ( (*func)( cn, data, opt, p, NULL ) == FAILURE ) {
-					
-					dbgf_cn( cn, DBGL_SYS, DBGT_ERR, 
-					         "%s func()=%s with %s %s failed", 
-					         opt_tmpl->long_name, func_name, opt->long_name, p->p_val );
-					
-					return FAILURE;
-				}
-			}
+                        if ( (*func)( cn, data, opt, p, NULL ) == FAILURE ) {
+
+                                dbgf_cn( cn, DBGL_SYS, DBGT_ERR,
+                                         "func()=%s with %s %s failed",
+                                         func_name, opt->long_name, p->p_val );
+
+                                return FAILURE;
+                        }
 			
 			struct list_head *c_pos;
 			
 			list_for_each( c_pos, &p->childs_instance_list ) {
 				
-				struct opt_child *c = 
-					(struct opt_child*)list_entry( c_pos, struct opt_child, list );
+				struct opt_child *c = (struct opt_child*)list_entry( c_pos, struct opt_child, list );
 				
-				if ( !( /*proceed if:*/ !opt_tmpl  ||  opt_tmpl == c->c_opt ) )
-					continue;
-				
-				
 				if ( (*func)( cn, data, opt, p, c ) == FAILURE ) {
 					
 					dbgf_cn( cn, DBGL_SYS, DBGT_ERR, 
-					         "%s func()=%s with %s %s %s %s failed", 
-					         opt_tmpl->long_name, func_name,
-					         opt->long_name, p->p_val, c->c_opt->long_name, c->c_val );
+					         "func()=%s with %s %s %s %s failed",
+					         func_name, opt->long_name, p->p_val, c->c_opt->long_name, c->c_val );
 					
 					return FAILURE;
 				}
@@ -1004,12 +1000,14 @@
 		return;
 	
 	dbg_printf(cn, "\n");
-	dbg_printf(cn, "Usage: %s [LONGOPT [%c]VAL] | [-SHORTOPT[SHORTOPT...] [%c]VAL] ...\n", 
+	dbg_printf(cn, "Usage: %s [LONGOPT[=[%c]VAL]] | [-SHORTOPT[SHORTOPT...] [[%c]VAL]] ...\n",
 	           prog_name, ARG_RESET_CHAR , ARG_RESET_CHAR);
-	dbg_printf(cn, "  e.g. %s -cid8\n", prog_name);
-	dbg_printf(cn, "  e.g. %s -c a 192.200.200.1/24\n", prog_name);
-	dbg_printf(cn, "  e.g. %s -c %s  my-vpn /n=192.168.115.0 /m=24\n", prog_name, ARG_THROW);
-	dbg_printf(cn, "  e.g. %s -c %s -my-vpn \n", prog_name, ARG_THROW);
+	dbg_printf(cn, "  e.g. %s dev=eth0 dev=wlan0         # to start daemon on interface eth0 and wlan0\n", prog_name);
+	dbg_printf(cn, "  e.g. %s plugin=bmx_http_info.so -X # to show verbose help of bmxd and its' plugin\n", prog_name);
+
+	dbg_printf(cn, "  e.g. %s -c -a 192.200.200.1/24     # to connect to running bmxd and announce given network\n", prog_name);
+	dbg_printf(cn, "  e.g. %s -c -a -192.200.200.1/24    # to connect and stop announcing given network\n", prog_name);
+	dbg_printf(cn, "  e.g. %s -cid8                      # to connect and show configured options and connevtivity\n", prog_name);
 	dbg_printf(cn, "\n");
 	//dbg_printf(cn, "\nValid options are:\n" );
 	
@@ -1019,6 +1017,7 @@
 		
 		struct list_head *pos;
 		struct opt_type *opt = (struct opt_type *)list_entry( list_pos, struct opt_data, list );
+                char sn[5], st[3 * MAX_ARG_SIZE], defaults[100];
 		
 		if ( !( all_opts  ||  opt->short_name ) )
 			continue;
@@ -1030,25 +1029,25 @@
 		
 		if ( opt->long_name  &&  opt->help  &&  !opt->parent_name ) {
 			
-			char sn[5];
+
 			if ( opt->short_name )
 				snprintf( sn,5, ", -%c", opt->short_name );
-			
 			else 
 				*sn = '\0';
 			
+			sprintf( st, "--%s%s %s ", opt->long_name, sn, opt->syntax ? opt->syntax: "" );
+
+			if ( opt->opt_t != A_PS0  &&  opt->imin != opt->imax )
+				sprintf( defaults, "def: %-6d  range: [ %d %s %d ]",
+				         opt->idef, opt->imin, opt->imin+1 == opt->imax ? ",": "...", opt->imax );
+                        else
+                                defaults[0]='\0';
+
+			dbg_printf( cn, "\n%-40s %s\n", st, defaults );
 			
-			char ln[MAX_ARG_SIZE];
-			snprintf( ln,MAX_ARG_SIZE, "--%s", opt->long_name );
-			
-			dbg_printf( cn, "\n%s%s %s \n", ln, sn, opt->syntax ? opt->syntax: "" );
-			
 			if ( verbose )
 				dbg_printf( cn, "	%s\n", opt->help );
 			
-			if ( verbose  &&  opt->opt_t != A_PS0  &&  opt->imin != opt->imax )
-				dbg_printf( cn, "	default: %5d, valid range: [ %d %s %d ] \n", 
-				            opt->idef, opt->imin, opt->imin+1 == opt->imax ? ",": "...", opt->imax );
 			
 			
 		} else if ( !opt->long_name && opt->help ) {
@@ -1062,36 +1061,32 @@
 			
 			struct opt_type *c_opt = (struct opt_type *)list_entry( pos, struct opt_data, list );
 			
-			if ( !c_opt->parent_name )
+			if ( !c_opt->parent_name  ||  !c_opt->help )
 				continue;
 			
-			if ( !c_opt->help )
-				continue;
-			
 #ifndef NODEPRECATED
 			if ( c_opt->call_custom_option == opt_deprecated )
 				continue;
 #endif
-			
-			char sn[5];
-			if ( c_opt->short_name )
-				snprintf( sn,5, " ,/%c", c_opt->short_name );
-			
-			else 
+
+                        if ( c_opt->short_name )
+				snprintf( sn,5, ", /%c", c_opt->short_name );
+			else
 				*sn = '\0';
-			
-			char ln[MAX_ARG_SIZE];
-			snprintf( ln,MAX_ARG_SIZE, "/%s", c_opt->long_name );
-			
-			dbg_printf( cn, "\n	%s%s %s \n", ln, sn, c_opt->syntax ? c_opt->syntax: "" );
-			
+
+			sprintf( st, "  /%s%s %s ", c_opt->long_name, sn, c_opt->syntax ? c_opt->syntax: "" );
+
+			if ( c_opt->opt_t != A_PS0  &&  c_opt->imin != c_opt->imax )
+				sprintf( defaults, "def: %-6d  range: [ %d %s %d ]",
+				         c_opt->idef, c_opt->imin, c_opt->imin+1 == c_opt->imax ? ",": "...", c_opt->imax );
+                        else
+                                defaults[0]='\0';
+
+			dbg_printf( cn, "%-40s %s\n", st, defaults );
+
 			if ( verbose )
-				dbg_printf( cn, "		%s\n", c_opt->help );
-			
-			if ( verbose  &&  c_opt->opt_t != A_PS0  &&  c_opt->imin != c_opt->imax )
-				dbg_printf( cn, "		default: %5d, valid range: [ %d %s %d ] \n", 
-				            c_opt->idef, c_opt->imin, c_opt->imin+1 == c_opt->imax ? ",": "...", c_opt->imax );
-			
+				dbg_printf( cn, "	        %s\n", c_opt->help );
+
 		}
 	}
 	
@@ -1773,6 +1768,7 @@
 	
 	char tmp_path[MAX_PATH_SIZE+20] = "";
 	char unix_buff[MAX_UNIX_MSG_SIZE+1] = "";
+	int trash;
 	
 	dbgf_all( DBGT_INFO, "cmd %s, opt_name %s, stream %s", 
 	          opt_cmd2str[cmd], opt->long_name, curr_strm_pos );
@@ -1856,7 +1852,7 @@
 			//printf("::::::::::::::::: from %s begin :::::::::::::::::::\n", tmp_path );
 			
 			if ( loop_mode )
-				Trash = system( "clear" );
+				trash=system( "clear" );
 			
 			int32_t recv_buff_len = 0;
 			
@@ -2243,7 +2239,7 @@
 		}
 		
 		// be pedantic only after startup (!on_the_fly) and not reload-config (!save)
-		if ( !changed  &&  on_the_fly  &&  save  &&  pedantic_cmd_check ) {
+		if ( !changed  &&  on_the_fly  &&  save  &&  pedantic_check ) {
 			
 			dbg_cn( cn, DBGL_SYS, DBGT_ERR, "--%s %s already configured", 
 			        p_opt->long_name, p_patch->p_val );
@@ -2278,7 +2274,8 @@
 		return FAILURE;
 	}
 	
-	if ( ad == DEL  &&  ( !on_the_fly  /*||  opt->dyn_t == A_INI this is what conf-reload tries */  ||  opt->cfg_t == A_ARG ) ) {
+	if ( ad == DEL  &&  ( /*!on_the_fly this is what concurrent -r and -g configurations do || */
+                /* opt->dyn_t == A_INI this is what conf-reload tries   ||*/  opt->cfg_t == A_ARG ) ) {
 		dbg( DBGL_SYS, DBGT_ERR, "option %s can not be resetted during startup!", opt->long_name );
 		return FAILURE;
 	}
@@ -2457,7 +2454,7 @@
 			LONG_OPT_ARG_VAL,	// 7
 	};
 	
-	char *state2str[] = {"NEXT_OPT","NEW_OPT","SHORT_OPT","LONG_OPT","LONG_OPT_VAL","LONG_OPT_WHAT","LONG_OPT_ARG","LONG_OPT_ARG_VAL"};
+	//char *state2str[] = {"NEXT_OPT","NEW_OPT","SHORT_OPT","LONG_OPT","LONG_OPT_VAL","LONG_OPT_WHAT","LONG_OPT_ARG","LONG_OPT_ARG_VAL"};
 	
 	
 	int8_t state = NEW_OPT;
@@ -2481,8 +2478,8 @@
 	
 	while ( s && strlen(s) >= 1 ) {
 		
-		dbgf_all( DBGT_INFO, "cmd: %-10s, state: %s opt: %s, wordlen: %d rest: %s",
-		          opt_cmd2str[cmd], state2str[state], opt?opt->long_name:"null", wordlen(s), s );
+		dbgf_all( DBGT_INFO, "cmd: %-10s, state: 0x%X opt: %s, wordlen: %d rest: %s",
+		          opt_cmd2str[cmd], state, opt?opt->long_name:"null", wordlen(s), s );
 		
 		if ( Testing ) {
 			Testing = 0;
@@ -3049,7 +3046,7 @@
 		dbg_printf(cn, "\n");
 		*/
 		
-		func_for_each_opt( cn, NULL, NULL, "opt_show_info()", show_info );
+		func_for_each_opt( cn, NULL, "opt_show_info()", show_info );
 		
 		if ( !on_the_fly )
 			cleanup_all(CLEANUP_SUCCESS);
@@ -3285,34 +3282,31 @@
 	{ODI,3,0,"loop_mode",		'l',A_PS0,A_ADM,A_INI,A_ARG,A_ANY,	&loop_mode,	0, 		1,		0, 		0,
 			0,		"put client daemon in loop mode to periodically refresh debug information"},
 		
-	{ODI,3,0,"loop_period",		0,  A_PS1,A_ADM,A_INI,A_ARG,A_ANY,	&loop_period,	100, 		10000,		1000,		0,
+#ifndef LESS_OPTIONS
+	{ODI,3,0,"loop_period",		0,  A_PS1,A_ADM,A_INI,A_ARG,A_ANY,	&loop_period,	MIN_LOOP_PERIOD,MAX_LOOP_PERIOD,DEF_LOOP_PERIOD,0,
 			ARG_VALUE_FORM,	"periodicity in ms with which client daemon in loop-mode refreshes debug information"},
+#endif
 		
-//config.c
 #ifndef NODEPRECATED
 	{ODI,3,0,"batch_mode",		'b',A_PS0,A_ADM,A_INI,A_ARG,A_ANY,	0,		0, 		0,		0, 		opt_deprecated,0,0},
 #endif
 		
-//control.c
 	{ODI,3,0,ARG_CONNECT,		'c',A_PS0,A_ADM,A_INI,A_ARG,A_EAT,	0,		0, 		0,		0, 		opt_connect,
 			0,		"set client mode. Connect and forward remaining args to main routing daemon"},
 
-//config.c	
 	//order=5: so when used during startup it also shows the config-file options	
 	{ODI,5,0,ARG_SHOW_CHANGED,	'i',A_PS0,A_ADM,A_DYI,A_ARG,A_ANY,	0,		0,		0,		0, 		opt_show_info,
 			0,		"inform about configured options" },
-		
-//config.c				
-	{ODI,5,0,ARG_PEDANTIC_CMDCHECK,	0,  A_PS1,A_ADM,A_DYI,A_CFA,A_ANY,	&pedantic_cmd_check,0,		1,		0,		0,
+#ifndef LESS_OPTIONS
+	{ODI,5,0,ARG_PEDANTIC_CMDCHECK,	0,  A_PS1,A_ADM,A_DYI,A_CFA,A_ANY,	&pedantic_check,MIN_PEDANT_CHK, MAX_PEDANT_CHK, DEF_PEDANT_CHK,	0,
 			ARG_VALUE_FORM,	"disable/enable pedantic checking of command-line parameters and context -\n"
 			"	( e.g. fail setting a parameter without changing it)" },
-		
-		//control.c
+#endif
 	{ODI,5,0,"dbg_mute_timeout",	0,  A_PS1,A_ADM,A_DYI,A_CFA,A_ANY,	&dbg_mute_to,	0,		10000000,	100000,		0,
 			ARG_VALUE_FORM,	"set timeout in ms for muting frequent messages"},
-		
+
 #ifndef NODEPRECATED
-//batman.c
+
 	{ODI,5,0,"fake_uptime",		0,  A_PS1,A_ADM,A_DYN,A_ARG,A_ANY,	0,		MIN_UPTIME,	MAX_UPTIME,	0,		opt_uptime,0,0},
 		
 	{ODI,5,0,"bmx_defaults",	0,  A_PS0,A_ADM,A_INI,A_ARG,A_ANY,	0,		0, 		0,		0, 		opt_deprecated,0,0},
@@ -3321,7 +3315,6 @@
 	{ODI,5,0,"24c3",		0,  A_PS0,A_ADM,A_INI,A_ARG,A_ANY,	0,		0, 		0,		0, 		opt_deprecated,0,0},
 #endif
 		
-//config.c
 	{ODI,5,0,ARG_QUIT,EOS_DELIMITER,    A_PS0,A_USR,A_DYN,A_ARG,A_END,	0,		0, 		0,		0, 		opt_quit,0,0}
 };
 
@@ -3331,6 +3324,10 @@
 	
 	int i;
 	
+	char *d = getenv(BMX_ENV_DEBUG);
+	if ( d  &&  strtol(d, NULL , 10) >= DBGL_MIN  &&  strtol(d, NULL , 10) <= DBGL_MAX )
+		debug_level = strtol(d, NULL , 10);
+
 	for ( i = DBGL_MIN; i <= DBGL_MAX; i++ )
 		INIT_LIST_HEAD_FIRST( dbgl_clients[i] );
 	

Modified: trunk/batman-experimental/control.h
===================================================================
--- trunk/batman-experimental/control.h	2010-04-12 19:06:37 UTC (rev 1633)
+++ trunk/batman-experimental/control.h	2010-04-15 08:16:16 UTC (rev 1634)
@@ -28,7 +28,7 @@
 #define	DBGT_ERR  3
 
 
-extern int debug_level;
+//extern int debug_level;
 #define DBGL_MIN	0
 #define DBGL_SYS	0
 #define DBGL_ROUTES	1
@@ -325,7 +325,7 @@
 	
 		
 	OPT_CHECK,
-	// to test a give patch (type-value pair) !
+	// to test a given patch (type-value pair) !
 	// Returns FAILURE or n>=0 of processed bytes-1
 		
 		
@@ -378,7 +378,7 @@
 
 
 
-int8_t func_for_each_opt( struct ctrl_node *cn, void *data, struct opt_type *opt_tmpl, char* func_name, 
+int8_t func_for_each_opt( struct ctrl_node *cn, void *data, char* func_name, 
                           int8_t (*func) ( struct ctrl_node *cn, void *data, struct opt_type *opt, struct opt_parent *p, struct opt_child *c ) );
 
 int respect_opt_order( uint8_t test, int8_t last, int8_t next, struct opt_type *on, uint8_t load_config, uint8_t cmd, struct ctrl_node *cn );

Modified: trunk/batman-experimental/hna.c
===================================================================
--- trunk/batman-experimental/hna.c	2010-04-12 19:06:37 UTC (rev 1633)
+++ trunk/batman-experimental/hna.c	2010-04-15 08:16:16 UTC (rev 1634)
@@ -22,12 +22,17 @@
 
 #include <string.h>
 #include <stdio.h>
+#include <asm/types.h>
+#include <sys/socket.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
 
 #include "batman.h"
 #include "os.h"
 #include "originator.h"
 #include "plugin.h"
 #include "hna.h"
+//#include "avl.h"
 
 
 static int32_t hna_orig_registry = FAILURE;
@@ -35,52 +40,42 @@
 static struct ext_type_hna *my_hna_ext_array = NULL;
 static uint16_t my_hna_list_enabled = 0;
 
-static struct hashtable_t *hna_hash = NULL;
+//static struct avl_tree hna_avl = { sizeof(struct hna_key), NULL};
+static AVL_TREE( hna_avl, sizeof(struct hna_key) );
 
-
 // this function finds (or if it does not exits and create is true it creates) 
 // an hna entry for the given hna address, anetmask, and atype 
-static struct hna_hash_node *get_hna_node( struct hna_key *hk, uint8_t create ) {
+static struct hna_node *get_hna_node( struct hna_key *hk, uint8_t create ) {
 	
-	struct hna_hash_node *hash_node;
-	struct hashtable_t *swaphash;
+	struct hna_node *hn;
+	hn = ((struct hna_node *)avl_find( &hna_avl, hk ));
 	
-	hash_node = ((struct hna_hash_node *)hash_find( hna_hash, hk ));
-	
-	if ( hash_node ) {
+	if ( hn ) {
 		
-		paranoia( -500022, ( memcmp( hk, &hash_node->key, sizeof( struct hna_key ) ) ) );// found incorrect key
+		paranoia( -500022, ( memcmp( hk, &hn->key, sizeof( struct hna_key ) ) ) );// found incorrect key
 		
-		return hash_node;
+		return hn;
 	}
 	
 	if ( !create )
 		return NULL;
 	
-	dbgf_all( DBGT_INFO, "  creating new and empty hna_hash_node: %s/%d, type %d", 
+	dbgf_all( DBGT_INFO, "  creating new and empty hna_node: %s/%d, type %d", 
 	         ipStr(hk->addr), hk->KEY_FIELD_ANETMASK, hk->KEY_FIELD_ATYPE );
 	
-	hash_node = debugMalloc( sizeof(struct hna_hash_node), 401 );
-	memset(hash_node, 0, sizeof(struct hna_hash_node));
+	hn = debugMalloc( sizeof(struct hna_node), 401 );
+	memset(hn, 0, sizeof(struct hna_node));
 	
-	hash_node->key.addr = hk->addr;
-	hash_node->key.KEY_FIELD_ATYPE = hk->KEY_FIELD_ATYPE;
-	hash_node->key.KEY_FIELD_ANETMASK = hk->KEY_FIELD_ANETMASK;
-	hash_node->status = HNA_HASH_NODE_EMPTY;
+	hn->key.addr = hk->addr;
+	hn->key.KEY_FIELD_ATYPE = hk->KEY_FIELD_ATYPE;
+	hn->key.KEY_FIELD_ANETMASK = hk->KEY_FIELD_ANETMASK;
+	hn->status = HNA_HASH_NODE_EMPTY;
 	
-	hash_add( hna_hash, hash_node );
+        avl_insert( &hna_avl, hn );
 	
-	if ( hna_hash->elements * 4 > hna_hash->size ) {
-		
-		if ( !(swaphash = hash_resize( hna_hash, hna_hash->size * 2 )) )
-			cleanup_all( -500095 );
-		
-		hna_hash = swaphash;
-	}
+	paranoia( -500022, ( memcmp( hk, &hn->key, sizeof( struct hna_key ) ) ) );// found incorrect key
 	
-	paranoia( -500022, ( memcmp( hk, &hash_node->key, sizeof( struct hna_key ) ) ) );// found incorrect key
-	
-	return hash_node;
+	return hn;
 }
 
 
@@ -91,14 +86,14 @@
 	if ( atype > A_TYPE_MAX ) // NOT YET supported!
 		return SUCCESS;
 	
-	uint8_t err = !del  &&  other_orig  &&  ( !router || !router->addr ||  !router->iif );
+	uint8_t err = !del  &&  other_orig  &&  ( !router || !router->nnkey_addr ||  !router->nnkey_iif );
 	
-	dbgf( ( err ? DBGL_SYS : DBGL_CHANGES ), ( err ? DBGT_ERR : DBGT_INFO ), 
+	dbgf( ( err ? DBGL_SYS : DBGL_ALL ), ( err ? DBGT_ERR : DBGT_INFO ),
 	     "%s %s %s %s %s/%d %d",
 	     del?"DEL":"ADD",
 	     other_orig?ipStr(other_orig->orig):"myself",
-	     ipStr( router&&router->addr ? router->addr : 0 ),
-	     ( router&&router->iif ? router->iif->dev : "???" ),
+	     ipStr( router&&router->nnkey_addr ? router->nnkey_addr : 0 ),
+	     ( router&&router->nnkey_iif ? router->nnkey_iif->dev : "???" ),
 	     ipStr(ip), mask, atype );
 	
 	paranoia( -500023, err );
@@ -107,77 +102,73 @@
 	key.addr = ip;
 	key.KEY_FIELD_ANETMASK = mask;
 	key.KEY_FIELD_ATYPE = atype;
+
+        int16_t rt_table = (atype == A_TYPE_INTERFACE || atype == A_TYPE_NETWORK) ? RT_TABLE_NETWORKS : 0;
 	
-	uint8_t rt_table = ( atype == A_TYPE_INTERFACE ? RT_TABLE_INTERFACES : 
-	                     (atype == A_TYPE_NETWORK ? RT_TABLE_NETWORKS : 0 ) );
-	
-	struct hna_hash_node *hhn = get_hna_node( &key, NO/*create*/);
-	
+	struct hna_node *hn = get_hna_node( &key, NO/*create*/);
+
+        
 	if ( del ) {
 		
-		if ( !other_orig  &&  hhn  &&  hhn->status == HNA_HASH_NODE_MYONE ) {
+		if ( !other_orig  &&  hn  &&  hn->status == HNA_HASH_NODE_MYONE ) {
 			
 			/* del throw routing entries for own hna */
-			add_del_route( ip, mask, 0,0,0, "unknown", RT_TABLE_HOSTS,      RT_THROW, DEL, TRACK_MY_HNA );
-			add_del_route( ip, mask, 0,0,0, "unknown", RT_TABLE_INTERFACES, RT_THROW, DEL, TRACK_MY_HNA );
-			add_del_route( ip, mask, 0,0,0, "unknown", RT_TABLE_NETWORKS,   RT_THROW, DEL, TRACK_MY_HNA );
-			add_del_route( ip, mask, 0,0,0, "unknown", RT_TABLE_TUNNEL,     RT_THROW, DEL, TRACK_MY_HNA );
+			add_del_route( ip, mask, 0,0,0, "unknown", RT_TABLE_HOSTS,      RTN_THROW, DEL, TRACK_MY_HNA );
+			add_del_route( ip, mask, 0,0,0, "unknown", RT_TABLE_NETWORKS,   RTN_THROW, DEL, TRACK_MY_HNA );
+			add_del_route( ip, mask, 0,0,0, "unknown", RT_TABLE_TUNNEL,     RTN_THROW, DEL, TRACK_MY_HNA );
 			
 			my_hna_list_enabled--;
 			
-		} else if ( other_orig  &&  hhn  &&  hhn->status == HNA_HASH_NODE_OTHER   &&  hhn->orig == other_orig ) {
+		} else if ( other_orig  &&  hn  &&  hn->status == HNA_HASH_NODE_OTHER   &&  hn->orig == other_orig ) {
 			
-			add_del_route( ip, mask, 0, primary_addr, 0, 0, rt_table, RT_UNICAST, DEL, TRACK_OTHER_HNA );
+			add_del_route( ip, mask, 0, primary_addr, 0, 0, rt_table, RTN_UNICAST, DEL, TRACK_OTHER_HNA );
 			
-		} else if ( !hhn ) {
-			
-			dbgf( DBGL_SYS, DBGT_WARN, "get_hna_hash() requested to remove non-existing hna registry");
-			return FAILURE;
-			
 		} else {
-			
-			return FAILURE;
-		}
+                        // paranoia( -500181, 1 );
+                        if (!hn) {
+                                dbgf(DBGL_SYS, DBGT_WARN, "get_hna_node() requested to remove non-existing hna registry");
+                        }
+                        return FAILURE;
+                }
+
+                avl_remove(&hna_avl, hn);
 		
-		hash_remove( hna_hash, hhn );
+		debugFree( hn, 1401 );
 		
-		debugFree( hhn, 1401 );
-		
 	} else {
 		
-		if ( other_orig  &&  !hhn ) {
+		if ( other_orig  &&  !hn ) {
 			
-			hhn = get_hna_node( &key, YES/*create*/);
-			hhn->status = HNA_HASH_NODE_OTHER;
-			hhn->orig = other_orig;
+			hn = get_hna_node( &key, YES/*create*/);
+			hn->status = HNA_HASH_NODE_OTHER;
+			hn->orig = other_orig;
 			
 			// we checked for err = !del  &&  ( !router || !router->addr ||  !router->iif ) at beginning: 
-			add_del_route( ip, mask, router->addr, primary_addr,
-			               router->iif->if_index, 
-			               router->iif->dev, 
-			               rt_table, RT_UNICAST, ADD, TRACK_OTHER_HNA  );
+			add_del_route( ip, mask, router->nnkey_addr, primary_addr,
+			               router->nnkey_iif->if_index,
+			               router->nnkey_iif->dev,
+			               rt_table, RTN_UNICAST, ADD, TRACK_OTHER_HNA  );
 			
 		
-		} else if (  other_orig  &&  hhn  &&  hhn->status == HNA_HASH_NODE_OTHER  &&  hhn->orig == other_orig ) {
+		} else if (  other_orig  &&  hn  &&  hn->status == HNA_HASH_NODE_OTHER  &&  hn->orig == other_orig ) {
 			
 			dbgf( DBGL_SYS, DBGT_WARN, "requested to add already-existing hna registry");
 			cleanup_all ( -500092 );
 		
-		} else if ( !other_orig  &&  !hhn ) {
+		} else if ( !other_orig  &&  !hn ) {
 			
-			hhn = get_hna_node( &key, YES/*create*/);
-			hhn->status = HNA_HASH_NODE_MYONE;
-			hhn->orig = NULL;
+			hn = get_hna_node( &key, YES/*create*/);
+			hn->status = HNA_HASH_NODE_MYONE;
+			hn->orig = NULL;
 			
 			/* add throw routing entries for own hna */  
-			add_del_route( ip, mask, 0,0,0, "unknown", RT_TABLE_HOSTS,      RT_THROW, ADD, TRACK_MY_HNA );
-			add_del_route( ip, mask, 0,0,0, "unknown", RT_TABLE_INTERFACES, RT_THROW, ADD, TRACK_MY_HNA );
-			add_del_route( ip, mask, 0,0,0, "unknown", RT_TABLE_NETWORKS,   RT_THROW, ADD, TRACK_MY_HNA );
-			add_del_route( ip, mask, 0,0,0, "unknown", RT_TABLE_TUNNEL,     RT_THROW, ADD, TRACK_MY_HNA );
+			add_del_route( ip, mask, 0,0,0, "unknown", RT_TABLE_HOSTS,      RTN_THROW, ADD, TRACK_MY_HNA );
+			add_del_route( ip, mask, 0,0,0, "unknown", RT_TABLE_NETWORKS,   RTN_THROW, ADD, TRACK_MY_HNA );
+			add_del_route( ip, mask, 0,0,0, "unknown", RT_TABLE_TUNNEL,     RTN_THROW, ADD, TRACK_MY_HNA );
 			
 			my_hna_list_enabled++;
 			
-		} else if ( !other_orig  &&  hhn  &&  hhn->status == HNA_HASH_NODE_MYONE ) {
+		} else if ( !other_orig  &&  hn  &&  hn->status == HNA_HASH_NODE_MYONE ) {
 			
 			dbgf( DBGL_SYS, DBGT_WARN, "requested to add already registered own hna %s/%d", 
 			      ipStr(ip), mask );
@@ -205,22 +196,19 @@
 		}
 		
 		uint16_t array_len = 0;
-		
-		struct hash_it_t *hashit = NULL;
-		
-		/* for all hna_hash_nodes... */
-		while ( (hashit = hash_iterate( hna_hash, hashit )) ) {
+
+                struct hna_key hk = {0,{0,0}};
+                while ( (hn = avl_next( &hna_avl, &hk))) {
+                        hk = hn->key;
 			
-			hhn = hashit->bucket->data;
-			
-			if ( hhn->status == HNA_HASH_NODE_MYONE ) {
+			if ( hn->status == HNA_HASH_NODE_MYONE ) {
 				
 				my_hna_ext_array[array_len].EXT_FIELD_MSG  = YES;
 				my_hna_ext_array[array_len].EXT_FIELD_TYPE = EXT_TYPE_64B_HNA;
 				
-				my_hna_ext_array[array_len].EXT_HNA_FIELD_ADDR    = hhn->key.addr;
-				my_hna_ext_array[array_len].EXT_HNA_FIELD_NETMASK = hhn->key.KEY_FIELD_ANETMASK;
-				my_hna_ext_array[array_len].EXT_HNA_FIELD_TYPE    = hhn->key.KEY_FIELD_ATYPE;
+				my_hna_ext_array[array_len].EXT_HNA_FIELD_ADDR    = hn->key.addr;
+				my_hna_ext_array[array_len].EXT_HNA_FIELD_NETMASK = hn->key.KEY_FIELD_ANETMASK;
+				my_hna_ext_array[array_len].EXT_HNA_FIELD_TYPE    = hn->key.KEY_FIELD_ATYPE;
 				
 				array_len++;
 			}
@@ -245,9 +233,9 @@
 	     ( !len  &&  (  array  || !orig_hna ) ) ) 
 	{
 		dbgf( DBGL_SYS, DBGT_ERR,
-		     "invalid hna information on %d, hal %d, ha %d, ohna_data %d ohal %d, oha %d!",
-		      on, len, array, orig_hna, 
-		      orig_hna?orig_hna->hna_array_len:0, (orig_hna?orig_hna->hna_array:0) );
+		     "invalid hna information on %p, hal %d, ha %p, ohna_data %p ohal %d, oha %p!",
+                        (void*)on, len, (void*)array, (void*)orig_hna,
+		      orig_hna?orig_hna->hna_array_len:0, (void*)(orig_hna?orig_hna->hna_array:0) );
 		
 		cleanup_all( -500024 );
 	}
@@ -298,7 +286,7 @@
 	
 	uint32_t ip;
 	int32_t mask;
-	struct hna_hash_node *hhn;
+	struct hna_node *hhn;
 	struct hna_key key;
 	char new[30];
 	
@@ -345,7 +333,8 @@
 					return FAILURE;
 				
 				// 3. remove the old HNA and hope to not mess it up...
-				if ( cmd == OPT_APPLY  &&  add_del_hna( DEL, NULL, NULL, ip, mask, A_TYPE_NETWORK ) == FAILURE )
+				if ( cmd == OPT_APPLY  &&
+                                        add_del_hna( DEL, NULL, NULL, ip, mask, A_TYPE_NETWORK ) == FAILURE )
 					cleanup_all( -500110 );
 				
 			}
@@ -390,25 +379,26 @@
 
 static int32_t opt_show_hnas ( uint8_t cmd, uint8_t _save, struct opt_type *opt, struct opt_parent *patch, struct ctrl_node *cn ) {
 	
-	struct hash_it_t *hashit = NULL;
-	
 	int dbg_ogm_out = 0;
 	char dbg_ogm_str[MAX_DBG_STR_SIZE + 1];
 	uint8_t blocked;
 	uint16_t hna_count = 0;
 	struct hna_key key;
-	struct hna_hash_node *hash_node;
+	struct hna_node *hn;
+	struct orig_node *orig_node;
 	
-	
 	if ( cmd == OPT_APPLY ) {
 		
 		dbg_printf( cn, "Originator      Announced networks HNAs:  network/netmask or interface/IF (B:blocked)...\n");
-		
-		while ( (hashit = hash_iterate( orig_hash, hashit )) ) {
+
+                uint32_t orig_ip = 0;
+
+                while ((orig_node = (struct orig_node*) avl_next(&orig_avl, &orig_ip))) {
+
+                        orig_ip = orig_node->orig;
+
+                        struct hna_orig_data *orig_hna = orig_node->plugin_data[hna_orig_registry];
 			
-			struct orig_node *orig_node = hashit->bucket->data;
-			struct hna_orig_data *orig_hna = orig_node->plugin_data[hna_orig_registry];
-			
 			if ( !orig_node->router  ||  !orig_hna )
 				continue;
 			
@@ -424,9 +414,9 @@
 				key.KEY_FIELD_ATYPE    = orig_hna->hna_array[hna_count].EXT_HNA_FIELD_TYPE;
 				
 				// check if HNA was blocked
-				hash_node = get_hna_node( &key, NO/*create*/ );
+				hn = get_hna_node( &key, NO/*create*/ );
 				
-				if ( hash_node  &&  hash_node->status == HNA_HASH_NODE_OTHER  &&  hash_node->orig == orig_node )
+				if ( hn  &&  hn->status == HNA_HASH_NODE_OTHER  &&  hn->orig == orig_node )
 					blocked = NO;
 				else
 					blocked = YES;
@@ -544,7 +534,7 @@
 		while ( hna_count < hna_array_len ) {
 			
 			struct hna_key key;
-			struct hna_hash_node *hash_node;
+                        struct hna_node *hn;
 			
 			key.addr               = ((hna_array)[hna_count]).EXT_HNA_FIELD_ADDR;
 			key.KEY_FIELD_ANETMASK = ((hna_array)[hna_count]).EXT_HNA_FIELD_NETMASK;
@@ -555,25 +545,38 @@
 			      key.addr != ( key.addr & htonl( 0xFFFFFFFF<<(32 - key.KEY_FIELD_ANETMASK ) ) ) ) 
 			{
 				
-				dbg_mute( 45, DBGL_SYS, DBGT_WARN, 
-				          "drop OGM: purging originator %15s "
-				          "hna: %s/%i, type %d -> ignoring (invalid netmask or type)", 
-				          orig_node->orig_str, ipStr( key.addr ), key.KEY_FIELD_ANETMASK, key.KEY_FIELD_ATYPE );
+				dbg_mute( 45, DBGL_SYS, DBGT_WARN,
+                                        "drop OGM: purging originator %15s "
+                                        "hna: %s/%i, type %d -> ignoring (invalid netmask or type)",
+                                        orig_node->orig_str, ipStr(key.addr),
+                                        key.KEY_FIELD_ANETMASK, key.KEY_FIELD_ATYPE);
 				
 				return CB_OGM_REJECT;
 				
-			} else if ( (hash_node = get_hna_node( &key, NO /*create*/ )) &&
-			            !(hash_node->status == HNA_HASH_NODE_OTHER  &&  hash_node->orig == orig_node)  &&
-			            (key.KEY_FIELD_ATYPE == A_TYPE_INTERFACE  ||  key.KEY_FIELD_ATYPE == A_TYPE_NETWORK) )
-			{
+			} else if ( (hn = get_hna_node( &key, NO /*create*/ )) &&
+                                !(hn->status == HNA_HASH_NODE_OTHER && hn->orig == orig_node) &&
+                                (key.KEY_FIELD_ATYPE <= A_TYPE_MAX) ) {
+
+                                dbg_mute(45, DBGL_SYS, DBGT_WARN,
+                                        "DAD-alert! ignoring %15s "
+                                        "hna: %s/%d type %d is blocked by %s "
+                                        "which may be purged in %d secs ( check --%s=%d )!",
+                                        orig_node->orig_str,
+                                        ipStr(key.addr), key.KEY_FIELD_ANETMASK, key.KEY_FIELD_ATYPE,
+                                        (hn->status == HNA_HASH_NODE_OTHER ? hn->orig->orig_str : "myself"),
+                                        (hn->status == HNA_HASH_NODE_OTHER ?
+                                        (int) (dad_to - (((uint32_t) (batman_time - hn->orig->last_valid_time)) / 1000)) :
+                                        -1),
+                                        ARG_PURGE_TO, dad_to);
+
+                                if (hn->status == HNA_HASH_NODE_OTHER) {
+                                        // if HNA is blocked by other node which has ńot bean heard of for 
+                                        // dad-timeout secs, 
+                                        // then its' HNAs should be removed before purge-timeout expires
+                                        if (LSEQ_U32(dad_to, (((uint32_t) (batman_time - hn->orig->last_valid_time)) / 1000)))
+                                                update_other_hna(hn->orig, 0, NULL, 0);
+                                }
 				
-				dbg_mute( 45, DBGL_SYS, DBGT_WARN, 
-				          "drop OGM: purging originator %15s "
-				          "hna: %s/%d type %d is blocked by %s",
-				          orig_node->orig_str,
-				          ipStr( key.addr ), key.KEY_FIELD_ANETMASK, key.KEY_FIELD_ATYPE,
-				          ( hash_node->status == HNA_HASH_NODE_OTHER  ? hash_node->orig->orig_str : "myself" )  );
-				
 				return CB_OGM_REJECT;
 				
 			} else {
@@ -637,7 +640,6 @@
 	
 	set_snd_ext_hook( EXT_TYPE_64B_HNA, send_my_hna_ext, DEL );
 	
-	hash_destroy( hna_hash );
 	
 }
 
@@ -646,10 +648,6 @@
 	
 	paranoia( -500061, ( sizeof(struct ext_type_hna) != sizeof(struct ext_packet) ) );
 	
-	if ( NULL == ( hna_hash = hash_new( 128, compare_key, choose_key, 5 ) ) )
-		cleanup_all( -500066 );
-	
-	
 	register_options_array( hna_options, sizeof( hna_options ) );
 	
 	if ( (hna_orig_registry = reg_plugin_data( PLUGIN_DATA_ORIG )) < 0 )

Modified: trunk/batman-experimental/hna.h
===================================================================
--- trunk/batman-experimental/hna.h	2010-04-12 19:06:37 UTC (rev 1633)
+++ trunk/batman-experimental/hna.h	2010-04-15 08:16:16 UTC (rev 1634)
@@ -27,7 +27,7 @@
 
 // my HNA extension messages (attached to all primary OGMs)
 
-#define A_TYPE_INTERFACE 0x00
+#define A_TYPE_INTERFACE 0x00 //unused
 #define A_TYPE_NETWORK   0x01
 #define A_TYPE_MAX       0x01
 
@@ -90,7 +90,7 @@
 #define  HNA_HASH_NODE_MYONE 0x01
 #define  HNA_HASH_NODE_OTHER 0x02
 
-struct hna_hash_node
+struct hna_node
 {
 	struct hna_key key;
 	

Modified: trunk/batman-experimental/lib/bmx_gsf_map/Makefile
===================================================================
--- trunk/batman-experimental/lib/bmx_gsf_map/Makefile	2010-04-12 19:06:37 UTC (rev 1633)
+++ trunk/batman-experimental/lib/bmx_gsf_map/Makefile	2010-04-15 08:16:16 UTC (rev 1634)
@@ -1,38 +1,5 @@
 
-CFLAGS +=	-fpic -pedantic -Wall -W -Wno-unused-parameter -O1 -g3 -std=gnu99 -I../../
-LDFLAGS +=	-shared
-#-Wl,-soname,bmxd_config 
+PLUGINS = $(shell find  -maxdepth 1 -type d | grep -e '^./bmx_' | sort)
 
-PLUGIN_NAME =   bmx_gsf_map
-PLUGIN_VER =    1
-
-SRC_C = gsf_map.c
-SRC_H = gsf_map.h
-OBJS= $(SRC_C:.c=.o)
-
-PLUGIN_FULLNAME = $(PLUGIN_NAME).so.$(PLUGIN_VER)
-PLUGIN_SHORTNAME = $(PLUGIN_NAME).so
-
-LIBDIR = /usr/lib
-
-all:	$(PLUGIN_FULLNAME) Makefile
-
-
-$(PLUGIN_FULLNAME):	$(OBJS) Makefile
-	$(CC) $(LDFLAGS) $(EXTRA_LDFLAGS) $(OBJS) -o $(PLUGIN_FULLNAME) 
-
-%.o:	%.c %.h Makefile
-	$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -c $< -o $@
-
-
-clean:
-	rm -f *.o *.so.$(PLUGIN_VER)
-	
-
-install:	all
-		mkdir -p $(LIBDIR)
-		install -D -m 755 $(PLUGIN_FULLNAME) $(LIBDIR)/$(PLUGIN_FULLNAME); /sbin/ldconfig -n $(LIBDIR); ln -f -s $(LIBDIR)/$(PLUGIN_FULLNAME) $(LIBDIR)/$(PLUGIN_SHORTNAME)
-
-
-strip:		all
-		strip $(PLUGIN_FULLNAME)
+%:
+	for d in $(PLUGINS); do $(MAKE) -C $$d $@ || echo compiling $$d failed; echo;echo; done

Modified: trunk/batman-experimental/lib/bmx_gsf_map/gsf_map.c
===================================================================
--- trunk/batman-experimental/lib/bmx_gsf_map/gsf_map.c	2010-04-12 19:06:37 UTC (rev 1633)
+++ trunk/batman-experimental/lib/bmx_gsf_map/gsf_map.c	2010-04-15 08:16:16 UTC (rev 1634)
@@ -34,6 +34,7 @@
 #include "plugin.h"
 #include "metrics.h"
 //#include "schedule.h"
+//#include "avl.h"
 
 
 #define GSF_MAP_MYNAME 		"gsf_map_name"
@@ -94,7 +95,7 @@
 			if ( !orig_node->router  ||  !orig_node->primary_orig_node )
 				continue;
 			
-			struct orig_node *onn = get_orig_node( orig_node->router->addr, NO/*create*/ );
+			struct orig_node *onn = get_orig_node( orig_node->router->nnkey_addr, NO/*create*/ );
 			
 			if ( !onn  ||  !onn->last_valid_time  ||  !onn->router )
 				continue;
@@ -116,7 +117,7 @@
 				            "'rtq' : %3i, 'rq' : %3i, 'tq' : %3i} ",
 				            count_neigh++,
 				            orig_node->primary_orig_node->orig_str,
-				            orig_node->router->accepted_sqr.wa_val/PROBE_TO100, 
+				            orig_node->router->longtm_sqr.wa_val/PROBE_TO100,
 				            orig_node->last_valid_sqn,
 				            ( batman_time - orig_node->last_valid_time)/1000,
 				            lndev->bif->if_ip_str,
@@ -143,23 +144,25 @@
 	
 	if ( cmd == OPT_APPLY  &&  cn ) {
 	
-	struct hash_it_t *hashit = NULL;
 	struct orig_node *orig_node;
 	uint32_t count=0;
 
 	dbg_printf( cn, "\nall_nodes = {\n" "  '%s' : {\n", ipStr(primary_addr) );
 
-	while ( (hashit = hash_iterate( orig_hash, hashit )) ) {
+        uint32_t orig_ip = 0;
 
-		orig_node = hashit->bucket->data;
+        while ((orig_node = (struct orig_node*) avl_next(&orig_avl, &orig_ip))) {
 
+                orig_ip = orig_node->orig;
+
+
 		if ( orig_node->router == NULL )
 			continue;
 
 		if ( orig_node->primary_orig_node != orig_node )
 			continue;
 
-		struct orig_node *onn = get_orig_node( orig_node->router->addr, NO );
+		struct orig_node *onn = get_orig_node( orig_node->router->nnkey_addr, NO );
 
 		if ( !onn  ||  !onn->last_valid_time  ||  !onn->router  ||  !onn->primary_orig_node )
 			continue;
@@ -174,15 +177,15 @@
 				"      "
 				"'dev' : '%s', 'via' : '%s', 'viaPub' : '%s', 'pq' : %i, 'ut' : '%s', "
 				"'lseq' : %i, 'lvld' : %i, 'pwd' : %i, 'ogi' : %i, 'hop' : %i, 'chng' : %i }",
-				orig_node->router->iif->dev,
-				ipStr( orig_node->router->addr ),
+				orig_node->router->nnkey_iif->dev,
+				ipStr( orig_node->router->nnkey_addr ),
 				ipStr( onn->primary_orig_node->orig ),
-		        	orig_node->router->accepted_sqr.wa_val/PROBE_TO100,
+		        	orig_node->router->longtm_sqr.wa_val/PROBE_TO100,
 				get_human_uptime( orig_node->first_valid_sec ),
 				orig_node->last_valid_sqn,
 				( batman_time - orig_node->last_valid_time)/1000,
 				orig_node->pws,
-				get_wavg( orig_node->ogi_wavg, OGI_WAVG_EXP ),
+				WAVG( orig_node->ogi_wavg, OGI_WAVG_EXP ),
 				(Ttl+1 - orig_node->last_path_ttl),
 				orig_node->rt_changes
 				); 
@@ -272,13 +275,13 @@
 };
 
 
-void gsf_map_cleanup( void ) {
+static void gsf_map_cleanup( void ) {
 	
 	//	remove_options_array( gsf_map_options );
 	
 }
 
-int32_t gsf_map_init( void ) {
+static int32_t gsf_map_init( void ) {
 	
 	register_options_array( gsf_map_options, sizeof( gsf_map_options ) );
 	

Modified: trunk/batman-experimental/lib/bmx_howto_plugin/howto_plugin.c
===================================================================
--- trunk/batman-experimental/lib/bmx_howto_plugin/howto_plugin.c	2010-04-12 19:06:37 UTC (rev 1633)
+++ trunk/batman-experimental/lib/bmx_howto_plugin/howto_plugin.c	2010-04-15 08:16:16 UTC (rev 1634)
@@ -115,13 +115,13 @@
 };
 
 
-void howto_plugin_cleanup( void ) {
+static void howto_plugin_cleanup( void ) {
 	
 	dbgf( DBGL_CHANGES, DBGT_INFO, "cleanung up plugin %s", HOWTO_PLUGIN );
 	
 }
 
-int32_t howto_plugin_init( void ) {
+static int32_t howto_plugin_init( void ) {
 	
 	dbgf( DBGL_CHANGES, DBGT_INFO, "init plugin %s", HOWTO_PLUGIN );
 	

Modified: trunk/batman-experimental/lib/bmx_http_info/http_info.c
===================================================================
--- trunk/batman-experimental/lib/bmx_http_info/http_info.c	2010-04-12 19:06:37 UTC (rev 1633)
+++ trunk/batman-experimental/lib/bmx_http_info/http_info.c	2010-04-15 08:16:16 UTC (rev 1634)
@@ -70,7 +70,10 @@
 		struct opt_type *opt;
 		char *request = &(tcp_req_data[HTTP_PREAMBLE_LEN]);
 	
-		
+//		dbg_printf( cn, "Content-type: text/plain\n\n" );
+		dbg_printf( cn, "\n" );
+
+
 		if ( wordlen( request ) <= MAX_ARG_SIZE  &&
 		     (opt = get_option(0,0,request))  &&
 		     opt->auth_t == A_USR  &&
@@ -83,7 +86,7 @@
 			      tcp_req_len, cn->fd, opt->long_name );
 			
 			check_apply_parent_option( ADD, OPT_APPLY, 0, opt, 0, cn );
-		
+                        
 		} else {
 			
 			dbg( DBGL_CHANGES, DBGT_INFO, "rcvd illegal %d bytes long HTTP request via fd %d", 
@@ -259,13 +262,13 @@
 };
 
 
-void http_info_cleanup( void ) {
+static void http_info_cleanup( void ) {
 	
 	//	remove_options_array( http_info_options );
 	
 }
 
-int32_t http_info_init( void ) {
+static int32_t http_info_init( void ) {
 	
 	register_options_array( http_info_options, sizeof( http_info_options ) );
 	

Modified: trunk/batman-experimental/lib/bmx_uci_config/HOWTO
===================================================================
--- trunk/batman-experimental/lib/bmx_uci_config/HOWTO	2010-04-12 19:06:37 UTC (rev 1633)
+++ trunk/batman-experimental/lib/bmx_uci_config/HOWTO	2010-04-15 08:16:16 UTC (rev 1634)
@@ -1,4 +1,15 @@
-_very_ short HOWTO for the bmx_uci_config.so plugin
+2009-08-10 - bmx_uci_config plugin for openWrt universial configuraton interface (UCI)
 
+- plugin for dynamic interaction with uci 
+  ( http://downloads.openwrt.org/sources/uci-0.7.3.tar.gz )
 
-please check etc_config/bmx and etc_config/bmx-advanced
\ No newline at end of file
+- to compile first install uci: 
+	wget http://downloads.openwrt.org/sources/uci-0.7.3.tar.gz
+	tar xzvf uci-0.7.3.tar.gz; cd uci-0.7.3; make; sudo make install
+
+- default configuration backend is: /etc/config/bmx
+
+- see lib/bmx_uci_config/etc_config for a simple (bmx) 
+  and an advanced (bmx-advanced) example
+
+

Modified: trunk/batman-experimental/lib/bmx_uci_config/uci_config.c
===================================================================
--- trunk/batman-experimental/lib/bmx_uci_config/uci_config.c	2010-04-12 19:06:37 UTC (rev 1633)
+++ trunk/batman-experimental/lib/bmx_uci_config/uci_config.c	2010-04-15 08:16:16 UTC (rev 1634)
@@ -563,9 +563,6 @@
 				return FAILURE;
 			}
 			
-			// remove all (re)loaded opts from the cached list. They dont have to be resetted later on
-			if ( (p_tmp=get_opt_parent_ref(&tmp_conf_opt, config_sect_val)) || (p_tmp=get_opt_parent_val(&tmp_conf_opt, config_sect_val)) )
-				del_opt_parent( &tmp_conf_opt, p_tmp );
 			
 			list_for_each( pos, &opt->d.childs_type_list ) {
 				
@@ -621,6 +618,12 @@
 				     del_opt_parent( &Patch_opt, patch );
 				     return FAILURE;
 			     }
+
+			// remove all (re)loaded opts from the cached list. They dont have to be resetted later on
+                        if ((p_tmp = get_opt_parent_ref(&tmp_conf_opt, config_sect_val)) ||
+                                (p_tmp = get_opt_parent_val(&tmp_conf_opt, patch->p_val)))
+                                del_opt_parent(&tmp_conf_opt, p_tmp);
+
 			
 			del_opt_parent( &Patch_opt, patch );
 		}
@@ -699,7 +702,7 @@
 		if ( wordlen(f)+1 +strlen(UCI_CONFDIR)+1 >= MAX_PATH_SIZE )
 			return FAILURE;
 		
-		if ( f[0] == '0' ) {
+		if ( wordsEqual( f, ARG_NO_CONFIG_FILE ) ) {
 			
 			if ( cmd == OPT_APPLY )
 				bmx_conf_name = NULL;
@@ -829,9 +832,9 @@
 		dbg_printf( cn, "config '%s' '%s'\n", DEF_SECT_TYPE, DEF_SECT_NAME );
 		
 		show_conf_general = YES;
-		func_for_each_opt( cn, NULL, NULL, "show_conf()", show_conf );
+		func_for_each_opt( cn, NULL, "show_conf()", show_conf );
 		show_conf_general = NO;
-		func_for_each_opt( cn, NULL, NULL, "show_conf()", show_conf );
+		func_for_each_opt( cn, NULL, "show_conf()", show_conf );
 		
 		dbg_printf( cn, "\n" );
 		
@@ -848,7 +851,8 @@
 		
 		
 	{ODI,1,0,ARG_CONFIG_FILE,	'f',A_PS1,A_ADM,A_INI,A_ARG,A_ANY,	0,		0, 		0,		0, 		opt_conf_file,
-			ARG_FILE_FORM,	"use non-default config file. If defined, this must be the first given option!" },
+			ARG_FILE_FORM,	"use non-default config file. If defined, this must be the first given option.\n"
+                        "	use --" ARG_CONFIG_FILE "=" ARG_NO_CONFIG_FILE " or -f" ARG_NO_CONFIG_FILE " to disable"},
 	
 	{ODI,1,0,ARG_RELOAD_CONFIG,	0,  A_PS0,A_ADM,A_DYN,A_ARG,A_ANY,	0,		0, 		0,		0, 		opt_conf_reload,
 			0,		"dynamically reload config file"},

Modified: trunk/batman-experimental/lib/bmx_uci_config/uci_config.h
===================================================================
--- trunk/batman-experimental/lib/bmx_uci_config/uci_config.h	2010-04-12 19:06:37 UTC (rev 1633)
+++ trunk/batman-experimental/lib/bmx_uci_config/uci_config.h	2010-04-15 08:16:16 UTC (rev 1634)
@@ -26,3 +26,4 @@
 #define ARG_SHOW_CONFIG		"show_config"
 #define ARG_RELOAD_CONFIG	"reload_config"
 
+#define ARG_NO_CONFIG_FILE      "0"
\ No newline at end of file

Modified: trunk/batman-experimental/linux/route.c
===================================================================
--- trunk/batman-experimental/linux/route.c	2010-04-12 19:06:37 UTC (rev 1633)
+++ trunk/batman-experimental/linux/route.c	2010-04-15 08:16:16 UTC (rev 1634)
@@ -41,28 +41,56 @@
 #include "schedule.h"
 
 
-int32_t base_port;
+int32_t base_port = DEF_BASE_PORT;
 
-int32_t Rt_table;
 
-int32_t Rt_prio;
+#define ARG_RT_TABLE "rt_table_offset"
+#define DEF_RT_TABLE 64
+#define MIN_RT_TABLE 0
+#define MAX_RT_TABLE 254
+#define RT_TABLE_HOSTS_OFFS	0
+#define RT_TABLE_NETS_OFFS	1
+#define RT_TABLE_TUNS_OFFS	2
+#define RT_TABLE_MAX_OFFS       2
+static int32_t Rt_table = DEF_RT_TABLE;
 
-static int32_t Lo_rule;
 
-int32_t prio_rules;
+#define ARG_RT_PRIO "prio_rules_offset"
+#define MIN_RT_PRIO 3
+#define MAX_RT_PRIO 32765
+#define DEF_RT_PRIO 6400
+#define RT_PRIO_HOSTS      (Rt_prio + 0)
+#define RT_PRIO_NETWORKS   (Rt_prio + 1)
+#define RT_PRIO_TUNNEL     (Rt_prio + 2)
+static int32_t Rt_prio = DEF_RT_PRIO;
 
-static int32_t throw_rules;
 
-static int32_t Pedantic_cleanup;
 
+#define ARG_PRIO_RULES "prio_rules"
+#define ARG_THROW_RULES "throw_rules"
+#define ARG_NO_POLICY_RT "no_policy_routing"
+#define ARG_PEDANTIC_CLEANUP "pedantic_cleanup"
 
+#define DEF_PRIO_RULES 1
+static int32_t prio_rules = DEF_PRIO_RULES;
 
-static uint8_t touched_systen_config = NO;
+#define DEF_THROW_RULES 1
+static int32_t throw_rules = DEF_THROW_RULES;
 
+#define DEF_PEDANT_CLNUP  NO
+static int32_t Pedantic_cleanup = DEF_PEDANT_CLNUP;
 
-static int netlink_sock = -1;
+#define DEF_LO_RULE 1
+static int32_t Lo_rule = DEF_LO_RULE;
 
+#define DEF_METRIC 0
+static int32_t metric = DEF_METRIC;
 
+static uint8_t touched_systen_config = NO;
+
+static int nl_sk = -1;
+static int flush_sk = -1;
+
 static int rt_sock = 0;
 
 
@@ -79,15 +107,34 @@
 int Mtu_min = MAX_MTU;
 
 
+
+static struct {
+        struct nlmsghdr nlh;
+        struct rtmsg rtm;
+        char buff[ 256 ];
+} req;
+
+static void add_rtattr( int rta_type, char *data, int data_len ) {
+
+        struct rtattr *rta = (struct rtattr *)(((char *) &req) + NLMSG_ALIGN(req.nlh.nlmsg_len));
+
+        req.nlh.nlmsg_len = NLMSG_ALIGN( req.nlh.nlmsg_len ) + RTA_LENGTH(data_len);
+
+        paranoia( -50173, (NLMSG_ALIGN( req.nlh.nlmsg_len ) > sizeof( req )) );
+        // if this fails then double req buff size !!
+
+        rta->rta_type = rta_type;
+        rta->rta_len = RTA_LENGTH(data_len);
+        memcpy( RTA_DATA(rta), data, data_len );
+}
+
 static char *rt2str( uint8_t t ) {
-	if ( t == RT_UNICAST )
-		return "RT_UNICAST";
-	else if ( t == RT_THROW )
-		return "RT_THROW  ";
-	else if ( t == RT_UNREACH )
-		return "RT_UNREACH";
+	if ( t == RTN_UNICAST )
+		return "RTN_UNICAST";
+	else if ( t == RTN_THROW )
+		return "RTN_THROW  ";
 	
-	return "RT_ILLEGAL";
+	return "RTN_ILLEGAL";
 }
 
 
@@ -116,53 +163,314 @@
 
 
 static int open_netlink_socket( void ) {
-	
-	if ( ( netlink_sock = socket( PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE ) ) < 0 ) {
 
+        int sock = 0;
+	if ( ( sock = socket( AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE ) ) < 0 ) {
+
 		dbg( DBGL_SYS, DBGT_ERR, "can't create netlink socket for routing table manipulation: %s",
 		     strerror(errno) );
-		netlink_sock = 0;
+
 		return -1;
 
 	}
 	
 	
-	if ( fcntl( netlink_sock, F_SETFL, O_NONBLOCK) < 0 ) {
+	if ( fcntl( sock, F_SETFL, O_NONBLOCK) < 0 ) {
 		
 		dbg( DBGL_SYS, DBGT_ERR, "can't set netlink socket nonblocking : (%s)",  strerror(errno));
-		close(netlink_sock);
-		netlink_sock = 0;
+		close(sock);
 		return -1;
 	}
 	
-	return netlink_sock;
+	return sock;
 
 }
 
-static void close_netlink_socket( void ) {
+
+static int rt_macro_to_table( int rt_macro ) {
+  
+	dbgf_all(  DBGT_INFO, "rt_macro %d", rt_macro  );
+
+        if ( rt_macro == RT_TABLE_HOSTS )
+		return Rt_table + RT_TABLE_HOSTS_OFFS;
+	     
+	else if ( rt_macro == RT_TABLE_NETWORKS )
+		return Rt_table + RT_TABLE_NETS_OFFS;
+	     
+	else if ( rt_macro == RT_TABLE_TUNNEL )
+		return Rt_table + RT_TABLE_TUNS_OFFS;
+	     
+	else if ( rt_macro > MAX_RT_TABLE )
+		cleanup_all( -500170 );
+  
+	else if ( rt_macro >= 0 )
+		return rt_macro;
+  
+	cleanup_all( -500171 );
+
+	return 0;
+
+}
+
+static int8_t track_rule_and_proceed( uint32_t network, int16_t mask, int16_t rt_table, uint32_t prio, char* iif,
+                                      int16_t rule_type, int8_t del, int8_t track_t)
+{
 	
-	if ( netlink_sock > 0 )
-		close( netlink_sock );
+	struct list_head *list_pos, *tmp_pos, *first_found_pos=NULL, *first_found_prev=NULL;
+	struct list_head *prev_pos = (struct list_head*)&rules_list;
+	struct rules_node *first_found_rn=NULL;
+	uint32_t found_rns=0;
+
+        paranoia( -500176, ( !del && track_t == TRACK_NO ) );
+
+	
+	list_for_each_safe( list_pos, tmp_pos, &rules_list ) {
 		
-	netlink_sock = 0;
+		struct rules_node *tmp_rn = list_entry( list_pos, struct rules_node, list );
+		
+		if ( tmp_rn->network == network &&  
+		     tmp_rn->netmask == mask &&
+		     tmp_rn->rt_table == rt_table &&
+		     tmp_rn->prio == prio &&
+		     tmp_rn->iif == iif &&
+		     tmp_rn->rta_type == rule_type )
+		{
+			
+			// the kernel-ip-stack does not care about my track_t when adding the same rule twice 
+			// but found_rns is evaluated for this
+			if ( !first_found_rn &&  (tmp_rn->track_t == track_t || track_t == TRACK_NO) ) {
+				first_found_rn = tmp_rn;
+				first_found_pos = list_pos;
+				first_found_prev = prev_pos;
+			}
+			
+			found_rns++;
+			
+		}
+		
+		prev_pos = &tmp_rn->list;
+		
+	}
+	
+	if ( (track_t == TRACK_NO) ||
+	     ( del && !first_found_rn ) ||
+	     ( del && found_rns != 1 ) ||
+	     ( !del && found_rns > 0 ) )
+	{
+		
+		dbg( (track_t == TRACK_NO || (del && !first_found_rn)) ? DBGL_SYS : DBGL_CHANGES, 
+		     (track_t == TRACK_NO || (del && !first_found_rn)) ? DBGT_ERR : DBGT_INFO, 
+		     "   %s rule from %s/%d  table %d  prio %d  iif %s  type %d  "
+		     "%s exists %d tims with at least %d exact match", 
+		     del?"del":"add", ipStr(network), mask, rt_table, prio, iif, rule_type,
+		     trackt2str(track_t), found_rns, (first_found_rn?1:0) );
+	}
+
+        if ( track_t == TRACK_NO )
+                return YES;
+	
+	if ( del ) {
+               
+                if ( first_found_rn ) {
+
+                        list_del(first_found_prev, first_found_pos, &rules_list);
+                        debugFree(first_found_rn, 1741);
+
+                        if (found_rns > 1)
+                                return NO;
+
+                } else {
+                        return NO;
+                }
+		
+	} else {
+		
+		struct rules_node *tmp_rn = debugMalloc( sizeof( struct rules_node ), 741 );
+		memset( tmp_rn, 0, sizeof( struct rules_node ) );
+		INIT_LIST_HEAD( &tmp_rn->list );
+		
+		tmp_rn->network = network;
+		tmp_rn->netmask = mask;
+		tmp_rn->rt_table = rt_table;
+		tmp_rn->prio = prio;
+		tmp_rn->iif = iif;
+		tmp_rn->rta_type = rule_type;
+		tmp_rn->track_t = track_t;
+		
+		list_add_tail( &tmp_rn->list, &rules_list );
+		
+		if ( found_rns > 0 )
+			return NO;
+		
+	}
+        
+        return YES;
 }
 
 
+static void add_del_rule( uint32_t network, int16_t mask, int16_t rt_table_macro, uint32_t prio, char* iif,
+                          int16_t rta_type, int8_t del, int8_t track_t)
+{
+	
+	char buf[4096], str1[16];
+	struct sockaddr_nl nladdr;
+	struct iovec iov = { buf, sizeof(buf) };
+	struct msghdr msg;
+	struct nlmsghdr *nh;
+
+	uint16_t rt_table = rt_macro_to_table(rt_table_macro);
+
+	inet_ntop( AF_INET, &network, str1, sizeof (str1) );
+
+        if ( track_rule_and_proceed( network, mask, rt_table, prio, iif, rta_type, del, track_t ) == NO )
+                return;
+
+
+	dbg( DBGL_CHANGES, DBGT_INFO, "%s rule from %s/%d  table %d  prio %d  iif %s  type %d",
+	     del?"del":"add", str1, mask, rt_table, prio, iif, rta_type );
+		
+	
+	memset( &nladdr, 0, sizeof(struct sockaddr_nl) );
+	memset( &req, 0, sizeof(req) );
+	memset( &msg, 0, sizeof(struct msghdr) );
+	
+	nladdr.nl_family = AF_NETLINK;
+
+        req.nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
+	req.nlh.nlmsg_pid = My_pid;
+
+        req.rtm.rtm_family = AF_INET;
+	req.rtm.rtm_table = rt_table;
+	
+	dbgf_all( DBGT_INFO, "%s ip rule pref %d iif %s %d %s/%d  lookup table %d",
+	          (del?"del":"add"), prio, iif, rta_type, str1, mask, rt_table );
+	
+	
+	if ( del ) {
+		
+		req.nlh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
+		req.nlh.nlmsg_type = RTM_DELRULE;
+
+                req.rtm.rtm_scope = RT_SCOPE_NOWHERE;
+		
+	} else {
+		
+		req.nlh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE | NLM_F_EXCL;
+		req.nlh.nlmsg_type = RTM_NEWRULE;
+
+                req.rtm.rtm_scope = RT_SCOPE_UNIVERSE;
+		req.rtm.rtm_protocol = RTPROT_STATIC;
+		req.rtm.rtm_type = RTN_UNICAST;
+		
+	}
+	
+
+        if (rta_type == RTA_DST) {
+			
+                req.rtm.rtm_dst_len = mask;
+                add_rtattr( rta_type,  (char*)&network, sizeof(network) );
+			
+        } else if ( rta_type == RTA_SRC ) {
+
+                req.rtm.rtm_src_len = mask;
+                add_rtattr( rta_type,  (char*)&network, sizeof(network) );
+        }
+		
+
+        if ( iif )
+                add_rtattr( RTA_IIF, iif, strlen(iif)+1 );
+
+	
+	if ( prio )
+                add_rtattr( RTA_PRIORITY, (char*)&prio, sizeof(prio) );
+	
+	
+	if ( sendto( nl_sk, &req, req.nlh.nlmsg_len, 0, (struct sockaddr *)&nladdr, sizeof(struct sockaddr_nl) ) < 0 ) {
+		
+		dbg( DBGL_SYS, DBGT_ERR, 
+		     "can't send message to kernel via netlink socket for routing rule manipulation: %s",
+		     strerror(errno) );
+		return;
+		
+	}
+	
+	
+	while ( 1 ) {
+		
+		msg.msg_name = (void *)&nladdr;
+		msg.msg_namelen = sizeof(nladdr);
+		msg.msg_iov = &iov;
+		msg.msg_iovlen = 1;
+		msg.msg_control = NULL;
+		msg.msg_controllen = 0;
+		msg.msg_flags = 0;
+		
+		int32_t len = recvmsg( nl_sk, &msg, 0 );
+		
+		
+		if ( len < 0 ) {
+			
+			if ( errno == EINTR ) {
+				dbgf( DBGL_SYS, DBGT_WARN, "(EINTR) %s", strerror(errno) );
+				continue;
+			}
+			
+			if ( errno == EWOULDBLOCK || errno == EAGAIN ) {
+				//dbgf( DBGL_SYS, DBGT_WARN, "(EWOULDBLOCK || EAGAIN) %s", strerror(errno) );
+				break;
+			}
+			
+			dbgf( DBGL_SYS, DBGT_ERR, "%s", strerror(errno) );
+			
+			continue;
+			
+		}
+		
+		if ( len == 0 ) {
+			dbgf( DBGL_SYS, DBGT_ERR, "netlink EOF" );
+		}
+		
+		nh = (struct nlmsghdr *)buf;
+		
+		while ( NLMSG_OK(nh, (uint32_t)len) ) {
+			
+			if ( nh->nlmsg_type == NLMSG_DONE )
+				return;
+			
+			if ( ( nh->nlmsg_type == NLMSG_ERROR ) && ( ((struct nlmsgerr*)NLMSG_DATA(nh))->error != 0 ) ) {
+				
+				dbg( DBGL_SYS, DBGT_WARN, "can't %s rule %s %s/%i iif %s table %d, prio %d: %s "
+				     "(if busy: Help me! Howto avoid this ERROR message?)", 
+				     del ? "delete" : "add", 
+				     ( rta_type == RTA_DST ? "to" :
+                                             ( rta_type == RTA_SRC ? "from" :
+                                                     ( rta_type == RTA_IIF ? "iif" : "???") ) ),
+				     str1, mask, iif, rt_table, prio,
+				     strerror(-((struct nlmsgerr*)NLMSG_DATA(nh))->error) );
+			}
+			
+			nh = NLMSG_NEXT( nh, len );
+			
+		}
+	}
+}
+
+
 static void flush_tracked_rules( int8_t track_type ) {
 	
 	dbgf_all( DBGT_INFO, "%s", trackt2str(track_type) );
 	
 	struct list_head *list_pos;
 	struct rules_node *rn, *p_rn=NULL;
+
 	
-	
 	list_for_each( list_pos, &rules_list ) {
 		
 		rn = list_entry( list_pos, struct rules_node, list );
 		
 		if ( p_rn )
 			add_del_rule( p_rn->network, p_rn->netmask, 
-			              p_rn->rt_table, p_rn->prio, p_rn->iif, p_rn->rule_t, DEL, p_rn->track_t );
+			              p_rn->rt_table, p_rn->prio, p_rn->iif, p_rn->rta_type, DEL, p_rn->track_t );
 		
 		if ( track_type == rn->track_t  || track_type == TRACK_NO )
 			p_rn = rn;
@@ -173,7 +481,7 @@
 	
 	if ( p_rn )
 		add_del_rule( p_rn->network, p_rn->netmask, 
-		              p_rn->rt_table, p_rn->prio, p_rn->iif, p_rn->rule_t, DEL, p_rn->track_t );
+		              p_rn->rt_table, p_rn->prio, p_rn->iif, p_rn->rta_type, DEL, p_rn->track_t );
 	
 }
 
@@ -191,7 +499,7 @@
 		
 		if ( p_rn )
 			add_del_route( p_rn->dest, p_rn->netmask, 0, 0, 0, 0, 
-			               p_rn->rt_table, p_rn->route_t, DEL, p_rn->track_t );
+			               p_rn->rt_table, p_rn->rta_type, DEL, p_rn->track_t );
 		
 		if ( track_type == rn->track_t  ||  track_type == TRACK_NO )
 			p_rn = rn;
@@ -202,20 +510,17 @@
 	
 	if ( p_rn )
 		add_del_route( p_rn->dest, p_rn->netmask, 0, 0, 0, 0, 
-		               p_rn->rt_table, p_rn->route_t, DEL, p_rn->track_t );
+		               p_rn->rt_table, p_rn->rta_type, DEL, p_rn->track_t );
 	
 }
 
-static int flush_routes_rules( int8_t is_rule ) {
+static void flush_routes_rules( int8_t is_rule ) {
 	
 	dbgf_all( DBGT_INFO, "is_rule %d", is_rule);
 	
 	size_t len;
 	int rtl;
-	int32_t dest = 0, router = 0, ifi = 0;
-	uint32_t prio = 0;
-	int8_t rule_type = RTA_SRC;
-	char buf[8192], *dev = NULL;
+	char buf[8192];
 	struct sockaddr_nl nladdr;
 	struct iovec iov = { buf, sizeof(buf) };
 	struct msghdr msg;
@@ -226,144 +531,163 @@
 		struct rtmsg rtm;
 	} req;
 	struct rtattr *rtap;
-	
+
 	memset( &nladdr, 0, sizeof(struct sockaddr_nl) );
 	memset( &req, 0, sizeof(req) );
-	memset( &msg, 0, sizeof(struct msghdr) );
 	
 	nladdr.nl_family = AF_NETLINK;
-	
-	req.nlh.nlmsg_len = NLMSG_LENGTH(sizeof(req));
+
+        req.nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
 	req.nlh.nlmsg_pid = My_pid;
-	req.rtm.rtm_family = AF_INET;
-	
 	req.nlh.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
 	req.nlh.nlmsg_type = ( is_rule ? RTM_GETRULE : RTM_GETROUTE );
+
+        req.rtm.rtm_family = AF_INET;
 	req.rtm.rtm_scope = RTN_UNICAST;
 	
-	if ( sendto( netlink_sock, &req, req.nlh.nlmsg_len, 0, 
+	if ( sendto( flush_sk, &req, req.nlh.nlmsg_len, 0,
 	             (struct sockaddr *)&nladdr, sizeof(struct sockaddr_nl) ) < 0 ) 
 	{
 		
 		dbg( DBGL_SYS, DBGT_ERR, 
 		     "can't send message to kernel via netlink socket for flushing the routing table: %s",
 		     strerror(errno) );
-		
-		return -1;
-		
-	}
-	
-	msg.msg_name = (void *)&nladdr;
-	msg.msg_namelen = sizeof(nladdr);
-	msg.msg_iov = &iov;
-	msg.msg_iovlen = 1;
-	msg.msg_control = NULL;
-	
-	len = recvmsg( netlink_sock, &msg, 0 );
-	nh = (struct nlmsghdr *)buf;
-	
-	while ( NLMSG_OK(nh, len) ) {
-		
-		if ( nh->nlmsg_type == NLMSG_DONE )
-			break;
-		
-		if ( ( nh->nlmsg_type == NLMSG_ERROR ) && ( ((struct nlmsgerr*)NLMSG_DATA(nh))->error != 0 ) ) {
-			
-			dbg( DBGL_SYS, DBGT_ERR, "can't flush %s: %s", 
-			     ( is_rule ? "routing rules" : "routing table" ),
-			     strerror(-((struct nlmsgerr*)NLMSG_DATA(nh))->error) );
-			
-			return -1;
-			
-		}
-		
-		rtm = (struct rtmsg *)NLMSG_DATA(nh);
-		rtap = (struct rtattr *)RTM_RTA(rtm);
-		rtl = RTM_PAYLOAD(nh);
-		
-		nh = NLMSG_NEXT( nh, len );
-		
-		if ( ( rtm->rtm_table != RT_TABLE_INTERFACES )  &&  
-		     ( rtm->rtm_table != RT_TABLE_NETWORKS )  && 
-		     ( rtm->rtm_table != RT_TABLE_HOSTS )  && 
-		     ( rtm->rtm_table != RT_TABLE_TUNNEL ) )
-			continue;
-		
-		while ( RTA_OK(rtap, rtl) ) {
-			
-			switch( rtap->rta_type ) {
-				
-			case RTA_DST:
-				dest = *((int32_t *)RTA_DATA(rtap));
-				rule_type = RTA_DST;
-				break;
-				
-			case RTA_SRC:
-				dest = *((int32_t *)RTA_DATA(rtap));
-				rule_type = RTA_SRC;
-				break;
-				
-			case RTA_GATEWAY:
-				router = *((int32_t *)RTA_DATA(rtap));
-				break;
-				
-			case RTA_OIF:
-				ifi = *((int32_t *)RTA_DATA(rtap));
-				break;
-				
-			case RTA_PRIORITY:
-				prio = *((uint32_t *)RTA_DATA(rtap));
-				break;
-				
-			case RTA_IIF:
-				dev = ((char *)RTA_DATA(rtap));
-				rule_type = RTA_IIF;
-				break;
-				
-			case 15:  /* FIXME: RTA_TABLE is not always available - not needed but avoid warning */
-				break;
-				
-			case RTA_PREFSRC:  /* rta_type 7 - not needed but avoid warning */
-				break;
-				
-			default:
-				dbg( DBGL_SYS, DBGT_ERR, "unknown rta type: %i", rtap->rta_type );
-				break;
-				
-			}
-			
-			rtap = RTA_NEXT(rtap,rtl);
-			
-		}
-		
-		char str1[16], str2[16];
-		
-		if ( is_rule ) {
-			
-			add_del_rule( ( rule_type == RTA_IIF ? 0 : dest ),
-			              ( rule_type == RTA_IIF ? 0 : ( rule_type == RTA_DST ? rtm->rtm_dst_len : rtm->rtm_src_len ) ),
-			              rtm->rtm_table, prio, 
-			              ( rule_type == RTA_IIF ? dev : 0 ),
-			              rule_type, DEL, TRACK_NO );
-			
-			inet_ntop( AF_INET, &dest, str1, sizeof (str1) );
-			
-			dbg( DBGL_SYS, DBGT_WARN, "flushing orphan rule type dest? %s  %d  table %d  prio %d", 
-			     rule_type == RTA_IIF ? "none" : str1, rule_type, rtm->rtm_table, prio );
-			
-		} else {
-			
-			inet_ntop( AF_INET, &dest, str1, sizeof (str1) );
-			inet_ntop( AF_INET, &router, str2, sizeof (str2) );
-			
-			add_del_route( dest, rtm->rtm_dst_len, router, 0, ifi, "unknown", rtm->rtm_table, rtm->rtm_type, DEL, TRACK_NO );
-			
-			dbg( DBGL_SYS, DBGT_WARN, "flushing orphan route to %s  via %s  type %d  table %d", 
-			     str1, str2, rtm->rtm_type, rtm->rtm_table );
-		}
-	}
-	
-	return 1;
+
+                cleanup_all( CLEANUP_FAILURE );
+        }
+
+        uint8_t nlm_f_multi = NO;
+
+        do {
+                memset(&msg, 0, sizeof(struct msghdr));
+                memset(&nladdr, 0, sizeof(struct sockaddr_nl));
+
+                nladdr.nl_family = AF_NETLINK;
+
+                msg.msg_name = (void *) & nladdr;
+                msg.msg_namelen = sizeof(nladdr);
+                msg.msg_iov = &iov;
+                msg.msg_iovlen = 1;
+                msg.msg_control = NULL;
+
+                len = recvmsg(flush_sk, &msg, 0);
+                nh = (struct nlmsghdr *) buf;
+
+                dbgf_all( DBGT_INFO, "searching: %s  NLMSG_OK: %d  len: %d",
+                        is_rule ? "rules" : "routes", NLMSG_OK(nh, len), (int)len);
+
+
+                while (NLMSG_OK(nh, len)) {
+
+                        if ( nh->nlmsg_flags & NLM_F_MULTI )
+                                nlm_f_multi = YES;
+
+                        if (nh->nlmsg_type == NLMSG_DONE) {
+                                dbgf_all( DBGT_INFO, "found NLMSG_DONE");
+                                break;
+                        }
+
+                        if ((nh->nlmsg_type == NLMSG_ERROR) && (((struct nlmsgerr*) NLMSG_DATA(nh))->error != 0)) {
+
+                                dbg(DBGL_SYS, DBGT_ERR, "can't flush %s: %s",
+                                        (is_rule ? "routing rules" : "routing table"),
+                                        strerror(-((struct nlmsgerr*) NLMSG_DATA(nh))->error));
+
+                                cleanup_all( CLEANUP_FAILURE );
+                        }
+
+                        rtm = (struct rtmsg *) NLMSG_DATA(nh);
+                        rtap = (struct rtattr *) RTM_RTA(rtm);
+                        rtl = RTM_PAYLOAD(nh);
+
+                        nh = NLMSG_NEXT(nh, len);
+
+                        if ( /* rtm->rtm_table == 0 || */
+                                rtm->rtm_table == Rt_table + RT_TABLE_NETS_OFFS ||
+                                rtm->rtm_table == Rt_table + RT_TABLE_HOSTS_OFFS ||
+                                rtm->rtm_table == Rt_table + RT_TABLE_TUNS_OFFS ) {
+
+                                int8_t rule_type = RTA_UNSPEC;
+                                uint32_t dest = 0;
+                                uint32_t router = 0;
+                                uint16_t mask = 0;
+                                int32_t oif = 0;
+                                int32_t prio = 0;
+                                char *iif = NULL;
+
+                                while (RTA_OK(rtap, rtl)) {
+                                        
+                                        dbgf_all( DBGT_INFO, "found rtm_table %d, rta_type %d rta_len %d",
+                                                rtm->rtm_table, rtap->rta_type, rtap->rta_len);
+
+
+                                        switch (rtap->rta_type) {
+
+                                        case RTA_DST:
+                                                dest = *((int32_t *) RTA_DATA(rtap));
+                                                mask = rtm->rtm_dst_len;
+                                                rule_type = RTA_DST;
+                                                break;
+
+                                        case RTA_SRC:
+                                                dest = *((int32_t *) RTA_DATA(rtap));
+                                                mask = rtm->rtm_src_len;
+                                                rule_type = RTA_SRC;
+                                                break;
+
+                                        case RTA_GATEWAY:
+                                                router = *((int32_t *) RTA_DATA(rtap));
+                                                break;
+
+                                        case RTA_OIF:
+                                                oif = *((int32_t *) RTA_DATA(rtap));
+                                                break;
+
+                                        case RTA_PRIORITY:
+                                                prio = *((uint32_t *) RTA_DATA(rtap));
+                                                break;
+
+                                        case RTA_IIF:
+                                                iif = ((char *) RTA_DATA(rtap));
+                                                break;
+  
+                                        case 15: // FIXME: RTA_TABLE is not always available - not needed but avoid warning
+                                                break;
+
+                                        case RTA_PREFSRC: // rta_type 7 - not needed but avoid warning
+                                                break;
+
+                                        default:
+                                                dbg(DBGL_SYS, DBGT_ERR, "unknown rta type: %i", rtap->rta_type);
+                                                break;
+
+                                        }
+
+                                        rtap = RTA_NEXT(rtap, rtl);
+
+                                }
+
+
+                                if (is_rule) {
+
+                                        add_del_rule( dest, mask, rtm->rtm_table, prio, iif, rule_type, DEL, TRACK_NO);
+
+
+                                        dbg(DBGL_SYS, DBGT_WARN, "flushing orphan rule type %d dest? %s/%d  table %d  prio %d",
+                                                rule_type, ipStr(dest), mask , rtm->rtm_table,  prio);
+
+                                } else {
+
+                                        add_del_route(dest, mask, router, 0, oif, "unknown", rtm->rtm_table, rtm->rtm_type, DEL, TRACK_NO);
+
+                                        dbg(DBGL_SYS, DBGT_WARN, "flushing orphan route to %s  via %s  type %d  table %d",
+                                                ipStr(dest), ipStr(router), rtm->rtm_type, rtm->rtm_table);
+                                }
+                        }
+                }
+                
+        } while ( !( nlm_f_multi == NO  ||  ( ( NLMSG_OK(nh, len)  &&  (nh->nlmsg_type == NLMSG_DONE) ) ) ) );
+
 }
 
 static void check_proc_sys( char *file, int32_t desired, int32_t *backup ) {
@@ -371,9 +695,9 @@
 	FILE *f;
 	int32_t state = 0;
 	char filename[MAX_PATH_SIZE];
+	int trash;
 	
 	
-	
 	sprintf( filename, "/proc/sys/%s", file );
 	
 	if((f = fopen(filename, "r" )) == NULL) {
@@ -386,7 +710,7 @@
 		return;
 	}
 	
-	Trash=fscanf(f, "%d", &state);
+	trash=fscanf(f, "%d", &state);
 	fclose(f);
 	
 	if ( backup )
@@ -482,20 +806,28 @@
 }
 
 
+static int8_t get_if_req( char* dev_name, struct ifreq *int_req, int siocgi_req ) {
 
+	memset( int_req, 0, sizeof (struct ifreq) );
+	strncpy( int_req->ifr_name, dev_name, IFNAMSIZ - 1 );
+	
+        if ( ioctl( rt_sock, siocgi_req, int_req ) < 0 ) {
+		
+		dbg( DBGL_SYS, DBGT_ERR, "can't get SIOCGI %d of interface %s: %s", siocgi_req, dev_name, strerror(errno) );
+                return FAILURE;
+	}
+	
+	return SUCCESS;
+			        
+}
+
 static int8_t if_validate( uint8_t set, struct batman_if *bif, char* dev_name, uint8_t reduced ) {
 	
 	struct ifreq int_req;
 	
-	memset( &int_req, 0, sizeof (struct ifreq) );
-	strncpy( int_req.ifr_name, dev_name, IFNAMSIZ - 1 );
 	
-	
-	if ( ioctl( rt_sock, SIOCGIFADDR, &int_req ) < 0 ) {
-		
-		dbg( DBGL_SYS, DBGT_WARN, "can't get IP address of %s: %s", dev_name, strerror(errno) );
+	if ( get_if_req( dev_name, &int_req, SIOCGIFADDR ) == FAILURE )
 		goto if_validate_failure;
-	} 
 	
 	if ( set ) {
 		
@@ -517,12 +849,9 @@
 	}
 	
 	
-	if ( ioctl( rt_sock, SIOCGIFNETMASK, &int_req ) < 0 ) {
-		
-		dbg( DBGL_SYS, DBGT_WARN, "can't get netmask address of %s: %s", dev_name, strerror(errno) );
+	if ( get_if_req( dev_name, &int_req, SIOCGIFNETMASK ) == FAILURE )
 		goto if_validate_failure;
-	}
-	
+
 	if ( set ) {
 		
 		bif->if_netaddr = ( ((struct sockaddr_in *)&int_req.ifr_addr)->sin_addr.s_addr & bif->if_addr );
@@ -557,11 +886,8 @@
 		return SUCCESS;
 	
 	
-	if ( ioctl( rt_sock, SIOCGIFINDEX, &int_req ) < 0 ) {
-		
-		dbg( DBGL_SYS, DBGT_ERR, "can't get index of interface %s: %s", dev_name, strerror(errno) );
+	if ( get_if_req( dev_name, &int_req, SIOCGIFINDEX ) == FAILURE )
 		goto if_validate_failure;
-	}
 	
 	if ( set ) {
 		
@@ -577,12 +903,8 @@
 	
 	
 	
-	if ( ioctl( rt_sock, SIOCGIFBRDADDR, &int_req ) < 0 ) {
-		
-		dbg( DBGL_SYS, DBGT_WARN, "Can't get broadcast address of %s: %s",
-		     dev_name, strerror(errno) );
+	if ( get_if_req( dev_name, &int_req, SIOCGIFBRDADDR ) == FAILURE )
 		goto if_validate_failure;
-	} 
 	
 	if ( set ) {
 		
@@ -603,11 +925,8 @@
 	
 	
 	
-	if ( ioctl( rt_sock, SIOCGIFMTU, &int_req ) < 0 ) {
-		
-		dbg( DBGL_SYS, DBGT_WARN, "can't get SIOCGIFMTU from device %s: %s", dev_name, strerror(errno) );
+	if ( get_if_req( dev_name, &int_req, SIOCGIFMTU ) == FAILURE )
 		goto if_validate_failure;
-	} 
 	
 	if ( set ) {
 		
@@ -625,13 +944,19 @@
 	
 if_validate_failure:
 	
-	bif->if_addr = ((struct sockaddr_in *)&int_req.ifr_addr)->sin_addr.s_addr = 0;
+	bif->if_addr = 0;
 	addr_to_str( 0, bif->if_ip_str );
 	return FAILURE;
 }
 
-static char *get_ifconf_buffer ( struct ifconf *ifc ) {
-	
+
+
+static char *get_ip4conf_buffer ( struct ifconf *ifc ) {
+
+        /* use netlink, netdevice and rtnetlink (7)
+         * to resolve ipv6 addresses. SIOCGIFCONF will only resolv ipv4 addresses !!!
+         */
+
 	char *buf;
 	
 	int32_t len = 10 * sizeof(struct ifreq); /* initial buffer size guess (10 interfaces) */
@@ -639,6 +964,9 @@
 	while ( 1 ) {
 		
 		buf = debugMalloc( len, 601 );
+                memset( buf, 0, len);
+                memset( ifc, 0, sizeof( struct ifconf ));
+                
 		ifc->ifc_len = len;
 		ifc->ifc_buf = buf;
 		
@@ -707,7 +1035,7 @@
 
 
 static void if_reconfigure_soft( struct batman_if *bif) {
-	
+
 	if ( !bif->if_active ) {
 		
 		dbg( DBGL_SYS, DBGT_INFO, 
@@ -740,17 +1068,15 @@
 	
 	if ( bif == primary_if ) {
 		
-		bif->own_ogm_out->ogm_ttl = Ttl;
+		bif->if_ttl = Ttl;
 		bif->if_singlehomed = NO;
 		
 	} else {
 		
-		bif->own_ogm_out->ogm_ttl = 1;
+		bif->if_ttl = 1;
 		bif->if_singlehomed = YES;
 	}
 	
-	bif->own_ogm_out->ogm_pws = my_pws;
-	//bif->own_ogm_out->ogm_path_lounge = Signal_lounge;
 	
 	bif->if_ant_diversity = 1;
 	
@@ -761,10 +1087,13 @@
 		bif->if_ant_diversity = bif->if_ant_diversity_conf;
 	
 	if ( bif->if_ttl_conf != -1 )
-		bif->own_ogm_out->ogm_ttl = bif->if_ttl_conf;
+		bif->if_ttl = bif->if_ttl_conf;
 	
 	if ( bif->if_singlehomed_conf  != -1 )
 		bif->if_singlehomed = bif->if_singlehomed_conf;
+
+        bif->if_last_link_activity = batman_time;
+        bif->if_next_pwrsave_hardbeat = batman_time;
 	
 	bif->if_conf_soft_changed = NO;
 	
@@ -784,8 +1113,7 @@
 
 
 static void if_activate( struct batman_if *bif ) {
-	
-	
+
 	if ( if_validate( YES/*set*/, bif, bif->dev, NO/*reduced check*/ ) == FAILURE )
 		goto error;
 	
@@ -937,7 +1265,6 @@
 	
 	check_kernel_config( bif );
 	
-	bif->own_ogm_out->orig = bif->if_addr;
 	
 	if ( bif == primary_if ) {
 		
@@ -977,170 +1304,153 @@
 	
 }
 
+static int8_t track_route_and_proceed( uint32_t dest, int16_t mask, uint32_t gw, uint32_t src, int32_t ifi, char *dev,
+                              int16_t rt_table, int16_t rta_type, int8_t del, int8_t track_t )
+{
 
-
-void add_del_route( uint32_t dest, uint8_t netmask, uint32_t router, uint32_t source, int32_t ifi, char *dev, 
-                    uint8_t rt_table, int8_t route_type, int8_t del, int8_t track_t ) 
-{
-	
-	uint32_t my_router;
-	char buf[4096], dsts[16], vias[16], srcs[16];
-	struct rtattr *rta;
-	struct sockaddr_nl nladdr;
-	struct iovec iov = { buf, sizeof(buf) };
-	struct msghdr msg;
-	struct nlmsghdr *nh;
-	struct {
-		struct nlmsghdr nlh;
-		struct rtmsg rtm;
-		char buff[4 * ( sizeof(struct rtattr) + 4 )];
-	} req;
-	
-	if ( !rt_table ) {
-		dbgf( DBGL_SYS, DBGT_ERR, "NO rt_table %s", ILLEGAL_STATE );
-		return;
-	}
-	
-	
-	if ( !del && track_t == TRACK_NO ) {
-		dbgf( DBGL_SYS, DBGT_ERR, "ADD and TRACK_NO %s", ILLEGAL_STATE );
-		return;
-	}
-	
-	dest = dest & htonl( 0xFFFFFFFF<<(32 - netmask ) ); // ToBeDone in add_del_route()...
-	
-	if ( ( !throw_rules ) && ( route_type == RT_THROW ) )
-		return;
-	
-	inet_ntop( AF_INET, &dest, dsts, sizeof (dsts) );
-	inet_ntop( AF_INET, &router, vias, sizeof (vias) );
-	inet_ntop( AF_INET, &source, srcs, sizeof (srcs) );
-	
-	
-	struct list_head *list_pos, *tmp_pos, *prev_pos = (struct list_head*)&routes_list;
+        struct list_head *list_pos, *tmp_pos, *prev_pos = (struct list_head*)&routes_list;
 	struct list_head *first_found_pos=NULL, *first_found_prev=NULL;
 	struct routes_node *first_found_rn=NULL;
 	uint32_t found_rns=0;
-	
+
+        paranoia(-500177, (!del && track_t == TRACK_NO));
+
 	list_for_each_safe( list_pos, tmp_pos, &routes_list ) {
-		
+
 		struct routes_node *tmp_rn = list_entry( list_pos, struct routes_node, list );
-		
-		if ( tmp_rn->dest    == dest &&  
-		     tmp_rn->netmask == netmask &&
+
+		if ( tmp_rn->dest    == dest &&
+		     tmp_rn->netmask == mask &&
 		     tmp_rn->rt_table == rt_table &&
-		     tmp_rn->route_t == route_type ) 
+		     tmp_rn->rta_type == rta_type )
 		{
-			
-			// the kernel-ip-stack does not care about my track_t when adding the same route twice 
+
+			// the kernel-ip-stack does not care about my track_t when adding the same route twice
 			// but found_rns is evaluated for this
 			if ( !first_found_rn  &&  (tmp_rn->track_t  == track_t  ||  track_t == TRACK_NO ) ) {
-				
+
 				first_found_rn = tmp_rn;
 				first_found_pos = list_pos;
 				first_found_prev = prev_pos;
 			}
-			
+
 			found_rns++;
-			
+
 		}
-		
+
 		prev_pos = &tmp_rn->list;
-		
+
 	}
-	
+
 	if ( track_t == TRACK_NO  ||
 	     ( del && !first_found_rn ) ||
 	     ( del && found_rns != 1 )  ||
-	     ( !del && found_rns > 0 ) ) 
+	     ( !del && found_rns > 0 ) )
 	{
-		dbg( (track_t == TRACK_NO || (del && !first_found_rn)) ? DBGL_SYS : DBGL_ALL, 
-		     (track_t == TRACK_NO || (del && !first_found_rn)) ? DBGT_ERR : DBGT_INFO, 
+		dbg( (track_t == TRACK_NO || (del && !first_found_rn)) ? DBGL_SYS : DBGL_ALL,
+		     (track_t == TRACK_NO || (del && !first_found_rn)) ? DBGT_ERR : DBGT_INFO,
 		     "  %s route to %-15s via %-15s  src %s  dev %s table %d  %s  "
-		     "%s has %d (%d exact) matches", 
-		     del?"del":"add", dsts, vias, srcs, dev, rt_table, 
-		     rt2str(route_type), trackt2str(track_t), found_rns,  (first_found_rn?1:0) );
-	}
-	
-	
+		     "%s has %d (%d exact) matches",
+		     del?"del":"add", ipStr(dest), ipStr(gw), ipStr(src), dev, rt_table,
+		     rt2str(rta_type), trackt2str(track_t), found_rns,  (first_found_rn?1:0) );
+        }
+
+        if ( track_t == TRACK_NO )
+                return YES;
+
+
 	if ( del && !first_found_rn)  {
-		
+
 		dbgf_all( DBGT_WARN, "removing orphan route");
-		// continue to remove, maybe an orphan route
-		
+		return NO;
+
 	} else if ( del && first_found_rn ) {
-		
+
 		list_del( first_found_prev, first_found_pos, &routes_list );
 		debugFree( first_found_rn, 1742 );
-		
+
 		if ( found_rns > 1 )
-			return;
-		
-		
+			 return NO;
+
+
 	} else if ( !del ) {
-		
+
 		struct routes_node *tmp_rn = debugMalloc( sizeof( struct routes_node ), 742 );
 		memset( tmp_rn, 0, sizeof( struct routes_node ) );
 		INIT_LIST_HEAD( &tmp_rn->list );
-		
+
 		tmp_rn->dest = dest;
-		tmp_rn->netmask = netmask;
+		tmp_rn->netmask = mask;
 		tmp_rn->rt_table = rt_table;
-		tmp_rn->route_t = route_type;
+		tmp_rn->rta_type = rta_type;
 		tmp_rn->track_t = track_t;
-		
+
 		list_add_tail( &tmp_rn->list, &routes_list );
-		
+
 		if ( found_rns > 0 )
-			return;
-		
+			return NO;
+
 	}
+
+        return YES;
+}
+
+
+
+void add_del_route( uint32_t dest, int16_t mask, uint32_t gw, uint32_t src, int32_t ifi, char *dev,
+                    int16_t rt_table_macro, int16_t rta_type, int8_t del, int8_t track_t )
+{
 	
+	uint32_t my_router;
+	char buf[4096];
+	struct sockaddr_nl nladdr;
+	struct iovec iov = { buf, sizeof(buf) };
+	struct msghdr msg;
+	struct nlmsghdr *nh;
 	
+	uint16_t rt_table = rt_macro_to_table(rt_table_macro);
+	
+	dest = dest & htonl( 0xFFFFFFFF<<(32 - mask ) );
+	
+	if ( ( !throw_rules ) && ( rta_type == RTN_THROW ) )
+		return;
+
+
+
+        if ( track_route_and_proceed(dest, mask, gw, src, ifi, dev, rt_table, rta_type, del, track_t) == NO )
+                return;
+
 	if ( track_t != TRACK_OTHER_HOST )
 		dbg( DBGL_CHANGES, DBGT_INFO, 
 		     " %s route to %15s/%-2d  table %d  via %-15s  dev %-10s ifi %2d  %s %s",
-		     del?"del":"add", dsts, netmask, rt_table, vias, dev, ifi, rt2str(route_type), trackt2str(track_t) );
-	
-	
-	
-	if ( router == dest ) {
-		
+		     del?"del":"add", 
+                     ipStr(dest), mask, rt_table, ipStr(gw), dev, ifi, rt2str(rta_type), trackt2str(track_t));
+
+
+	if ( gw == dest )
 		my_router = 0;
-		
-		if ( dest == 0 ) {
-			
-			dbgf_all( DBGT_INFO, "%s default route via %s src %s (table %i)", 
-			          del ? "del" : "add", dev, srcs, rt_table );
-			
-		} else {
-			
-			dbgf_all( DBGT_INFO, "%s route to %s via %s  (table %i - %s src %s )", 
-			          del ? "del" : "add", dsts, vias, rt_table, dev, srcs );
-			
-		}
-		
-	} else {
-		
-		my_router = router;
-		
-		dbgf_all( DBGT_INFO, "%s %s to %s/%i via %s (table %i - %s src %s )", 
-		          del ? "del" : "add", rt2str(route_type), dsts, netmask, vias, rt_table, dev, srcs );
-		
-		
-	}
+
+        else
+		my_router = gw;
+
+
+        dbgf_all( DBGT_INFO, "%s %s to %s/%i via %s (table %i - %s src %s )",
+                  del ? "del" : "add",
+                  rt2str(rta_type), ipStr(dest), mask, ipStr(gw), rt_table, dev, ipStr(src));
+
 	
-	
 	memset( &nladdr, 0, sizeof(struct sockaddr_nl) );
 	memset( &req, 0, sizeof(req) );
 	memset( &msg, 0, sizeof(struct msghdr) );
 	
 	nladdr.nl_family = AF_NETLINK;
-	
+
+        req.nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
 	req.nlh.nlmsg_pid = My_pid;
-	req.rtm.rtm_family = AF_INET;
+
+        req.rtm.rtm_family = AF_INET;
 	req.rtm.rtm_table = rt_table;
-	req.rtm.rtm_dst_len = netmask;
+	req.rtm.rtm_dst_len = mask;
 	
 	if ( del ) {
 		
@@ -1150,63 +1460,41 @@
 		
 	} else {
 		
-		req.nlh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE | NLM_F_EXCL;
+		req.nlh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE | NLM_F_EXCL/* | NLM_F_REPLACE*/;
 		req.nlh.nlmsg_type = RTM_NEWROUTE;
 		
-		if ( /* source != 0 && */ route_type == RT_UNICAST && my_router == 0  ) {
+		if ( /* source != 0 && */ rta_type == RTN_UNICAST && my_router == 0  ) {
 			req.rtm.rtm_scope = RT_SCOPE_LINK;
 		} else {
 			req.rtm.rtm_scope = RT_SCOPE_UNIVERSE;
 		}
 		
 		req.rtm.rtm_protocol = RTPROT_STATIC; // may be changed to some batman specific value - see <linux/rtnetlink.h>
-		req.rtm.rtm_type = ( route_type == RT_THROW ? RTN_THROW : RTN_UNICAST );
+		req.rtm.rtm_type = ( rta_type == RTN_THROW ? RTN_THROW : RTN_UNICAST );
 		
 	}
-	
-	int i=0;
-	
-	rta = (struct rtattr *)(req.buff + (i * sizeof(struct rtattr)) + (i*4));
-	rta->rta_type = RTA_DST;
-	rta->rta_len = sizeof(struct rtattr) + 4;
-	memcpy( ((char *)&req.buff) + ((i+1) * sizeof(struct rtattr)) + (i*4), (char *)&dest, 4 );
-	i++;
-	
-	if ( route_type == RT_UNICAST ) {
+
+        add_rtattr( RTA_DST, (char*)&dest, sizeof(dest) );
+
+	if ( rta_type == RTN_UNICAST ) {
 		
-		if ( my_router != 0 ) {
-			rta = (struct rtattr *)(req.buff + (i * sizeof(struct rtattr)) + (i*4));
-			rta->rta_type = RTA_GATEWAY;
-			rta->rta_len = sizeof(struct rtattr) + 4;
-			memcpy( ((char *)&req.buff) + ((i+1) * sizeof(struct rtattr)) + (i*4), (char *)&my_router, 4 );
-			i++;
-		}
+		if ( my_router )
+                        add_rtattr( RTA_GATEWAY, (char*)&my_router, sizeof(my_router) );
 		
-		if ( ifi != 0 ) {
-			rta = (struct rtattr *)(req.buff + (i * sizeof(struct rtattr)) + (i*4));
-			rta->rta_type = RTA_OIF;
-			rta->rta_len = sizeof(struct rtattr) + 4;
-			memcpy( ((char *)&req.buff) + ((i+1) * sizeof(struct rtattr)) + (i*4), (char *)&ifi, 4 );
-			i++;
-		}		
-		
-		if( source != 0 /* && my_router == 0 */ ) {
-			rta = (struct rtattr *)(req.buff + (i * sizeof(struct rtattr)) + (i*4));
-			rta->rta_type = RTA_PREFSRC;
-			rta->rta_len = sizeof(struct rtattr) + 4;
-			memcpy( ((char *)&req.buff) + ((i+1) * sizeof(struct rtattr)) + (i*4), (char *)&source, 4 );
-			i++;
-			
-			
-		}
-	}
+		if ( ifi )
+                        add_rtattr ( RTA_OIF, (char*)&ifi, sizeof(ifi) );
+
+                if ( src /* && my_router == 0 */)
+                        add_rtattr( RTA_PREFSRC, (char*)&src, sizeof(src) );
+
+                if ( metric )
+                        add_rtattr( RTA_PRIORITY, (char*)&metric, sizeof(metric) );
+
+        }
 	
-	
-	req.nlh.nlmsg_len = NLMSG_LENGTH( sizeof(struct rtmsg) + (i * (sizeof(struct rtattr) + 4)) );
-	
 	errno=0;
 	
-	if ( sendto( netlink_sock, &req, req.nlh.nlmsg_len, 0, (struct sockaddr *)&nladdr, sizeof(struct sockaddr_nl) ) < 0 ) {
+	if ( sendto( nl_sk, &req, req.nlh.nlmsg_len, 0, (struct sockaddr *)&nladdr, sizeof(struct sockaddr_nl) ) < 0 ) {
 		
 		dbg( DBGL_SYS, DBGT_ERR, 
 		     "can't send message to kernel via netlink socket for routing table manipulation: %s",
@@ -1228,7 +1516,7 @@
 		msg.msg_flags = 0;
 		
 		errno=0;
-		int32_t len = recvmsg( netlink_sock, &msg, 0 );
+		int32_t len = recvmsg( nl_sk, &msg, 0 );
 		
 		
 		if ( len < 0 ) {
@@ -1265,7 +1553,7 @@
 			if ( ( nh->nlmsg_type == NLMSG_ERROR ) && ( ((struct nlmsgerr*)NLMSG_DATA(nh))->error != 0 ) )
 			{
 				dbg( DBGL_CHANGES, DBGT_WARN, "can't %s %s to %s/%i via %s (table %i): %s", 
-				     del ? "delete" : "add", rt2str(route_type), dsts, netmask, vias, rt_table,
+				     del ? "delete" : "add", rt2str(rta_type), ipStr(dest), mask, ipStr(gw), rt_table,
 				     strerror(-((struct nlmsgerr*)NLMSG_DATA(nh))->error) );
 			}
 			
@@ -1278,281 +1566,6 @@
 
 
 
-void add_del_rule( uint32_t network, uint8_t netmask, uint8_t rt_table, uint32_t prio, char *iif, int8_t rule_type, int8_t del, int8_t track_t ) {
-	
-	int32_t len;
-	char buf[4096], str1[16];
-	struct rtattr *rta;
-	struct sockaddr_nl nladdr;
-	struct iovec iov = { buf, sizeof(buf) };
-	struct msghdr msg;
-	struct nlmsghdr *nh;
-	struct {
-		struct nlmsghdr nlh;
-		struct rtmsg rtm;
-		char buff[2 * ( sizeof(struct rtattr) + 4 )];
-	} req;
-	
-	if ( !rt_table ) {
-		dbgf( DBGL_SYS, DBGT_ERR, "NO rt_table %s", ILLEGAL_STATE );
-		return;
-	}
-	
-	
-	if ( !del && track_t == TRACK_NO ) {
-		dbgf( DBGL_SYS, DBGT_ERR, "ADD and TRACK_NO %s", ILLEGAL_STATE );
-		return;
-	}
-	
-	inet_ntop( AF_INET, &network, str1, sizeof (str1) );
-	
-	
-	struct list_head *list_pos, *tmp_pos, *first_found_pos=NULL, *first_found_prev=NULL;
-	struct list_head *prev_pos = (struct list_head*)&rules_list;
-	struct rules_node *first_found_rn=NULL;
-	uint32_t found_rns=0;
-	
-	
-	list_for_each_safe( list_pos, tmp_pos, &rules_list ) {
-		
-		struct rules_node *tmp_rn = list_entry( list_pos, struct rules_node, list );
-		
-		if ( tmp_rn->network == network &&  
-		     tmp_rn->netmask == netmask &&
-		     tmp_rn->rt_table == rt_table &&
-		     tmp_rn->prio == prio &&
-		     tmp_rn->iif == iif &&
-		     tmp_rn->rule_t == rule_type ) 
-		{
-			
-			// the kernel-ip-stack does not care about my track_t when adding the same rule twice 
-			// but found_rns is evaluated for this
-			if ( !first_found_rn &&  (tmp_rn->track_t == track_t || track_t == TRACK_NO) ) {
-				first_found_rn = tmp_rn;
-				first_found_pos = list_pos;
-				first_found_prev = prev_pos;
-			}
-			
-			found_rns++;
-			
-		}
-		
-		prev_pos = &tmp_rn->list;
-		
-	}
-	
-	if ( (track_t == TRACK_NO) ||
-	     ( del && !first_found_rn ) ||
-	     ( del && found_rns != 1 ) ||
-	     ( !del && found_rns > 0 ) )
-	{
-		
-		dbg( (track_t == TRACK_NO || (del && !first_found_rn)) ? DBGL_SYS : DBGL_CHANGES, 
-		     (track_t == TRACK_NO || (del && !first_found_rn)) ? DBGT_ERR : DBGT_INFO, 
-		     "   %s rule from %s/%d  table %d  prio %d  if %s  type %d  "
-		     "%s exists %d tims with at least %d exact match", 
-		     del?"del":"add", str1, netmask, rt_table, prio, iif, rule_type, 
-		     trackt2str(track_t), found_rns, (first_found_rn?1:0) );
-	}
-	
-	if ( del && !first_found_rn)  {
-		return;
-		
-	} else if ( del && first_found_rn ) {
-		
-		list_del( first_found_prev, first_found_pos, &rules_list );
-		debugFree( first_found_rn, 1741 );
-		
-		if ( found_rns > 1 )
-			return;
-		
-	} else if ( !del ) {
-		
-		struct rules_node *tmp_rn = debugMalloc( sizeof( struct rules_node ), 741 );
-		memset( tmp_rn, 0, sizeof( struct rules_node ) );
-		INIT_LIST_HEAD( &tmp_rn->list );
-		
-		tmp_rn->network = network;
-		tmp_rn->netmask = netmask;
-		tmp_rn->rt_table = rt_table;
-		tmp_rn->prio = prio;
-		tmp_rn->iif = iif;
-		tmp_rn->rule_t = rule_type;
-		tmp_rn->track_t = track_t;
-		
-		list_add_tail( &tmp_rn->list, &rules_list );
-		
-		if ( found_rns > 0 )
-			return;
-		
-	}
-	
-	dbg( DBGL_CHANGES, DBGT_INFO, "%s rule from %s/%d  table %d  prio %d  if %s  type %d",
-	     del?"del":"add", str1, netmask, rt_table, prio, iif, rule_type );
-	
-	
-	
-	memset( &nladdr, 0, sizeof(struct sockaddr_nl) );
-	memset( &req, 0, sizeof(req) );
-	memset( &msg, 0, sizeof(struct msghdr) );
-	
-	nladdr.nl_family = AF_NETLINK;
-	
-	len = sizeof(struct rtmsg) + sizeof(struct rtattr) + 4;
-	
-	if ( prio != 0 )
-		len += sizeof(struct rtattr) + 4;
-	
-	req.nlh.nlmsg_len = NLMSG_LENGTH(len);
-	req.nlh.nlmsg_pid = My_pid;
-	req.rtm.rtm_family = AF_INET;
-	req.rtm.rtm_table = rt_table;
-	
-	dbgf_all( DBGT_INFO, "%s ip rule pref %d %s %s/%d  lookup table %d", 
-	          (del ? "Deleting" : "Adding"), 
-	          prio, 
-	          (rule_type == RTA_SRC ? "from" : (rule_type == RTA_DST ? "to" : "dev" ) ), 
-	          ((rule_type == RTA_SRC || rule_type == RTA_DST) ? str1: ( rule_type == RTA_IIF ? iif : "??" )), 
-	          netmask, 
-	          rt_table );
-	
-	
-	if ( del ) {
-		
-		req.nlh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
-		req.nlh.nlmsg_type = RTM_DELRULE;
-		req.rtm.rtm_scope = RT_SCOPE_NOWHERE;
-		
-	} else {
-		
-		req.nlh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE | NLM_F_EXCL;
-		req.nlh.nlmsg_type = RTM_NEWRULE;
-		req.rtm.rtm_scope = RT_SCOPE_UNIVERSE;
-		req.rtm.rtm_protocol = RTPROT_STATIC;
-		req.rtm.rtm_type = RTN_UNICAST;
-		
-	}
-	
-	
-	if ( rule_type == RTA_IIF ) {
-		
-		if ( del ) {
-			
-			rta = (struct rtattr *)req.buff;
-			rta->rta_type = RTA_SRC;
-			rta->rta_len = sizeof(struct rtattr) + 4;
-			memcpy( ((char *)&req.buff) + sizeof(struct rtattr), (char *)&network, 4 );
-			
-		} else {
-			
-			rta = (struct rtattr *)req.buff;
-			rta->rta_type = RTA_IIF;
-			rta->rta_len = sizeof(struct rtattr) + 4;
-			memcpy( ((char *)&req.buff) + sizeof(struct rtattr), iif, 4 );
-			
-		}
-		
-	} else {
-		
-		rta = (struct rtattr *)req.buff;
-		
-		if ( rule_type == RTA_DST ) {
-			
-			req.rtm.rtm_dst_len = netmask;
-			
-			rta->rta_type = RTA_DST;
-			
-		} else {
-			
-			req.rtm.rtm_src_len = netmask;
-			
-			rta->rta_type = RTA_SRC;
-			
-		}
-		
-		rta->rta_len = sizeof(struct rtattr) + 4;
-		memcpy( ((char *)&req.buff) + sizeof(struct rtattr), (char *)&network, 4 );
-		
-	}
-	
-	
-	if ( prio != 0 ) {
-		
-		rta = (struct rtattr *)(req.buff + sizeof(struct rtattr) + 4);
-		rta->rta_type = RTA_PRIORITY;
-		rta->rta_len = sizeof(struct rtattr) + 4;
-		memcpy( ((char *)&req.buff) + 2 * sizeof(struct rtattr) + 4, (char *)&prio, 4 );
-		
-	}
-	
-	
-	if ( sendto( netlink_sock, &req, req.nlh.nlmsg_len, 0, (struct sockaddr *)&nladdr, sizeof(struct sockaddr_nl) ) < 0 ) {
-		
-		dbg( DBGL_SYS, DBGT_ERR, 
-		     "can't send message to kernel via netlink socket for routing rule manipulation: %s",
-		     strerror(errno) );
-		return;
-		
-	}
-	
-	
-	while ( 1 ) {
-		
-		msg.msg_name = (void *)&nladdr;
-		msg.msg_namelen = sizeof(nladdr);
-		msg.msg_iov = &iov;
-		msg.msg_iovlen = 1;
-		msg.msg_control = NULL;
-		msg.msg_controllen = 0;
-		msg.msg_flags = 0;
-		
-		len = recvmsg( netlink_sock, &msg, 0 );
-		
-		
-		if ( len < 0 ) {
-			
-			if ( errno == EINTR ) {
-				dbgf( DBGL_SYS, DBGT_WARN, "(EINTR) %s", strerror(errno) );
-				continue;
-			}
-			
-			if ( errno == EWOULDBLOCK || errno == EAGAIN ) {
-				//dbgf( DBGL_SYS, DBGT_WARN, "(EWOULDBLOCK || EAGAIN) %s", strerror(errno) );
-				break;
-			}
-			
-			dbgf( DBGL_SYS, DBGT_ERR, "%s", strerror(errno) );
-			
-			continue;
-			
-		}
-		
-		if ( len == 0 ) {
-			dbgf( DBGL_SYS, DBGT_ERR, "netlink EOF" );
-		}
-		
-		nh = (struct nlmsghdr *)buf;
-		
-		while ( NLMSG_OK(nh, (uint32_t)len) ) {
-			
-			if ( nh->nlmsg_type == NLMSG_DONE )
-				return;
-			
-			if ( ( nh->nlmsg_type == NLMSG_ERROR ) && ( ((struct nlmsgerr*)NLMSG_DATA(nh))->error != 0 ) ) {
-				
-				dbg( DBGL_SYS, DBGT_WARN, "can't %s rule %s %s/%i table %d, prio %d: %s "
-				     "(if busy: Help me! Howto avoid this ERROR message?)", 
-				     del ? "delete" : "add", 
-				     ( rule_type == RTA_DST ? "to" : "from" ), 
-				     str1, netmask, rt_table, prio,
-				     strerror(-((struct nlmsgerr*)NLMSG_DATA(nh))->error) );
-			}
-			
-			nh = NLMSG_NEXT( nh, len );
-			
-		}
-	}
-}
 
 
 int update_interface_rules( uint8_t cmd ) {
@@ -1560,9 +1573,10 @@
 
 	static uint8_t setup_tunnel = NO;
 	static uint8_t setup_networks = NO;
-	static uint32_t checksum = 0;
+
+        static uint64_t checksum = 0;
 	
-	uint32_t old_checksum = checksum;
+	uint64_t old_checksum = checksum;
 	checksum = 0;
 
 	uint8_t if_count = 1;
@@ -1605,19 +1619,18 @@
 	
 	}
 
-	if ( !(buf = get_ifconf_buffer( &ifc )) )
+	if ( !(buf = get_ip4conf_buffer( &ifc )) )
 		return FAILURE;
 	
 	for ( buf_ptr = buf; buf_ptr < buf + ifc.ifc_len; ) {
 
 		struct batman_if bif;
+//                memset( &bif, 0, sizeof(struct batman_if));
 		
 		ifr = (struct ifreq *)buf_ptr;
-		buf_ptr += sizeof(ifr->ifr_name) + 
-			( ifr->ifr_addr.sa_family == AF_INET6 ? 
-			  sizeof(struct sockaddr_in6) : 
-			  sizeof(struct sockaddr) );
 
+                buf_ptr += sizeof(struct ifreq);
+
 		/* ignore if not IPv4 interface */
 		if ( ifr->ifr_addr.sa_family != AF_INET )
 			continue;
@@ -1627,15 +1640,27 @@
 		
 		if ( if_validate( YES/*set*/, &bif, ifr->ifr_name, YES/*reduced check only*/ ) == FAILURE )
 			continue;
+
+                size_t i;
+                struct key {
+                        uint32_t if_prefix_length;
+                        uint32_t if_netaddr;
+                        uint32_t if_addr;
+                } key = { bif.if_prefix_length, /*bif.if_index,*/ bif.if_netaddr, bif.if_addr };
+
+                for (i = 0; i < sizeof( struct key); i++) {
+                        checksum += ((unsigned char*)(&key))[i];
+                        checksum += (checksum << 10);
+                        checksum ^= (checksum >> 6);
+                }
+                
+                dbgf_ext(  DBGT_INFO, "%15ju  %15ju  %10s %15s %15s %2d ",
+                        old_checksum, checksum,
+//                        ((uint32_t*)&(old_checksum))[0], ((uint32_t*)&(old_checksum))[1],
+//                        ((uint32_t*)&(checksum))[0], ((uint32_t*)&(checksum))[1],
+                        ifr->ifr_name,  ipStr(bif.if_addr), ipStr(bif.if_netaddr), bif.if_prefix_length);
 		
 		
-		checksum += bif.if_addr + bif.if_netaddr + bif.if_prefix_length;
-		
-		dbgf_all( DBGT_INFO, "%15d %10s %15s %15s %2d",
-		          checksum, ifr->ifr_name, 
-		          ipStr(bif.if_addr), ipStr(bif.if_netaddr), bif.if_prefix_length  );
-		
-		
 		if ( cmd == IF_RULE_CHK_IPS )
 			continue;
 		
@@ -1667,15 +1692,16 @@
 				if_count++;
 			}
 			
-			if ( Lo_rule && strncmp( ifr->ifr_name, "lo", IFNAMSIZ - 1 ) == 0 )
-				add_del_rule( 0, 0, 
-				              RT_TABLE_TUNNEL, RT_PRIO_TUNNEL, "lo", RTA_IIF, ADD, TRACK_MY_NET );
+			if ( Lo_rule && strncmp( ifr->ifr_name, "lo", IFNAMSIZ - 1 ) == 0 ) {
 
+				add_del_rule( 0, 0, RT_TABLE_TUNNEL, RT_PRIO_TUNNEL, "lo", RTA_IIF, ADD, TRACK_MY_NET );
+                        }
+
 		}
 		
 		if( throw_rules && setup_tunnel == YES )
 			add_del_route( bif.if_netaddr, bif.if_prefix_length, 
-			               0, 0, 0, ifr->ifr_name, RT_TABLE_TUNNEL, RT_THROW, ADD, TRACK_MY_NET );
+			               0, 0, 0, ifr->ifr_name, RT_TABLE_TUNNEL, RTN_THROW, ADD, TRACK_MY_NET );
 
 		
 		if ( is_batman_if( ifr->ifr_name, &batman_if ) )
@@ -1684,7 +1710,7 @@
 		
 		if( throw_rules  &&  setup_networks == YES )
 			add_del_route( bif.if_netaddr, bif.if_prefix_length, 
-			               0, 0, 0, ifr->ifr_name, RT_TABLE_NETWORKS, RT_THROW, ADD, TRACK_MY_NET );
+			               0, 0, 0, ifr->ifr_name, RT_TABLE_NETWORKS, RTN_THROW, ADD, TRACK_MY_NET );
 		
 	
 	}
@@ -1700,20 +1726,18 @@
 			throw_node = list_entry(throw_pos, struct throw_node, list);
 		
 			add_del_route( throw_node->addr, throw_node->netmask, 
-			               0, 0, 0, "unknown", RT_TABLE_HOSTS,	RT_THROW, ADD, TRACK_MY_NET );
+			               0, 0, 0, "unknown", RT_TABLE_HOSTS,	RTN_THROW, ADD, TRACK_MY_NET );
 			add_del_route( throw_node->addr, throw_node->netmask, 
-			               0, 0, 0, "unknown", RT_TABLE_INTERFACES,	RT_THROW, ADD, TRACK_MY_NET );
+			               0, 0, 0, "unknown", RT_TABLE_NETWORKS,	RTN_THROW, ADD, TRACK_MY_NET );
 			add_del_route( throw_node->addr, throw_node->netmask, 
-			               0, 0, 0, "unknown", RT_TABLE_NETWORKS,	RT_THROW, ADD, TRACK_MY_NET );
-			add_del_route( throw_node->addr, throw_node->netmask, 
-			               0, 0, 0, "unknown", RT_TABLE_TUNNEL,	RT_THROW, ADD, TRACK_MY_NET );
+			               0, 0, 0, "unknown", RT_TABLE_TUNNEL,	RTN_THROW, ADD, TRACK_MY_NET );
 			
 		}
 		
 	}
 	
 
-	if ( cmd == IF_RULE_CHK_IPS  &&  (checksum-old_checksum) ) {
+	if ( cmd == IF_RULE_CHK_IPS  &&  (checksum != old_checksum) ) {
 		dbg( DBGL_CHANGES, DBGT_INFO, 
 		     "systems' IP configuration changed! Going to re-init interface rules...");
 		update_interface_rules( IF_RULE_UPD_ALL );
@@ -1858,6 +1882,9 @@
 			}
 			
 		}
+
+                if (if_conf_soft_changed )
+                        bif->if_conf_soft_changed = YES; // to be considered in if_activate()->if_reconfigure_soft()
 		
 		if ( (!bif->if_active)  &&  (is_interface_up(bif->dev)) ) {
 			
@@ -1886,7 +1913,7 @@
 			}
 		}
 		
-		if ( /*bif->if_active  &&*/  (if_conf_soft_changed  ||  bif->if_conf_soft_changed) ) {
+		if ( /*bif->if_active  &&*/ ( /*if_conf_soft_changed  ||*/  bif->if_conf_soft_changed) ) {
 			
 			if ( on_the_fly )
 				dbg( DBGL_CHANGES, DBGT_INFO, "%s soft interface configuration changed", bif->dev );
@@ -1965,38 +1992,28 @@
 		check_apply_parent_option( ADD, OPT_APPLY, _save, get_option( 0, 0, ARG_THROW_RULES ), "0", cn );
 		
 	} else if ( cmd == OPT_SET_POST  &&  !on_the_fly ) {
-		
-		// flush orphan routes must be before flushing rules, otherwise orphan routes are not found !
-		if ( flush_routes_rules(0 /* flush routes */) < 0 )
-			cleanup_all( CLEANUP_FAILURE );
-		
-		
+
+                // flush orphan routes must be before flushing rules, otherwise orphan routes are not found !
+		flush_routes_rules( 0 /* flush routes */);
+
 		/* add rule for hosts and announced interfaces and networks */
-		if ( prio_rules ) { 
+		if ( prio_rules )
+                        flush_routes_rules( 1 /* flush rules */);
+
+
+	} else if ( cmd == OPT_POST  &&  !on_the_fly ) {
 			
-			if ( flush_routes_rules(1 /* flush rules */) < 0 )
-				cleanup_all( CLEANUP_FAILURE );
-			
-		}
-		
-	}
-	/*
-	else if ( cmd == OPT_POST  &&  !on_the_fly ) {
-	
 		// add rule for hosts and announced interfaces and networks
 		if ( prio_rules ) { 
-			add_del_rule( 0, 0, RT_TABLE_INTERFACES, RT_PRIO_INTERFACES, 0, RTA_DST, ADD, TRACK_STANDARD );
 			add_del_rule( 0, 0, RT_TABLE_HOSTS,      RT_PRIO_HOSTS,      0, RTA_DST, ADD, TRACK_STANDARD );
 			add_del_rule( 0, 0, RT_TABLE_NETWORKS,   RT_PRIO_NETWORKS,   0, RTA_DST, ADD, TRACK_STANDARD );
 		}
-	
+		
 		// add rules and routes for interfaces
 		if ( update_interface_rules( IF_RULE_SET_NETWORKS ) < 0 )
 			cleanup_all( CLEANUP_FAILURE );
-	
-	
+			
 	}
-	*/
 	
 	return SUCCESS;
 }
@@ -2127,21 +2144,26 @@
 	{ODI,4,0,ARG_RT_PRIO,		0,  A_PS1,A_ADM,A_INI,A_CFA,A_ANY,	&Rt_prio,	MIN_RT_PRIO,	MAX_RT_PRIO,	DEF_RT_PRIO,	0,
 			ARG_VALUE_FORM,	"set preferences for iproute2-style rules to rt_table (see: man ip)"},
 		
-	{ODI,4,0,ARG_RT_TABLE,		0,  A_PS1,A_ADM,A_INI,A_CFA,A_ANY,	&Rt_table,	MIN_RT_TABLE,	MAX_RT_TABLE,	DEF_RT_TABLE,	0,
-			ARG_VALUE_FORM,	"set tables for iproute2-style routing tables (see: man ip)"},
-		
-	{ODI,4,0,ARG_THROW_RULES,	0,  A_PS1,A_ADM,A_INI,A_CFA,A_ANY,	&throw_rules,	0, 		1,		1, 		0,
+	{ODI,4,0,ARG_RT_TABLE,		0,  A_PS1,A_ADM,A_INI,A_CFA,A_ANY,	&Rt_table,	MIN_RT_TABLE,	MAX_RT_TABLE-RT_TABLE_MAX_OFFS,	DEF_RT_TABLE,	0,
+			ARG_VALUE_FORM,	"set bmx routing-table offset (iproute2 style, see: man ip)"},
+
+#ifndef LESS_OPTIONS
+	{ODI,4,0,ARG_THROW_RULES,	0,  A_PS1,A_ADM,A_INI,A_CFA,A_ANY,	&throw_rules,	0, 		1,		DEF_THROW_RULES,0,
 			ARG_VALUE_FORM,	"disable/enable default throw rules"},
 		
-	{ODI,4,0,ARG_PRIO_RULES,	0,  A_PS1,A_ADM,A_INI,A_CFA,A_ANY,	&prio_rules,	0, 		1,		1, 		0,
+	{ODI,4,0,ARG_PRIO_RULES,	0,  A_PS1,A_ADM,A_INI,A_CFA,A_ANY,	&prio_rules,	0, 		1,		DEF_PRIO_RULES, 0,
 			ARG_VALUE_FORM,	"disable/enable default priority rules"},
-		
+#endif
 	{ODI,4,0,ARG_NO_POLICY_RT,	'n',A_PS0,A_ADM,A_INI,A_ARG,A_ANY,	0,		0, 		0,		0,		opt_policy_rt,
 			0,		"disable policy routing (throw and priority rules)"},
 		
-	{ODI,4,0,"lo_rule",		0,  A_PS1,A_ADM,A_INI,A_CFA,A_ANY,	&Lo_rule,	0, 		1,		1, 		0,
+#ifndef LESS_OPTIONS
+	{ODI,4,0,"metric",	        0,  A_PS1,A_ADM,A_INI,A_CFA,A_ANY,	&metric,	0, 		OV32,           DEF_METRIC,	0,
+			ARG_VALUE_FORM,	"set non-zero metric for all bmx routes"},
+
+        {ODI,4,0,"lo_rule",		0,  A_PS1,A_ADM,A_INI,A_CFA,A_ANY,	&Lo_rule,	0, 		1,		DEF_LO_RULE,	0,
 			ARG_VALUE_FORM,	"disable/enable autoconfiguration of lo rule"},
-		
+#endif
 	{ODI,5,0,ARG_THROW,		0,  A_PMN,A_ADM,A_DYI,A_CFA,A_ANY,	0,		0,		0,		0,		opt_throw,
 			ARG_PREFIX_FORM, 	"do NOT route packets matching src or dst IP range(s) into gateway tunnel or announced networks"},
 		
@@ -2149,13 +2171,15 @@
 			ARG_NETW_FORM, 	"specify network of throw rule"},
 		
 	{ODI,5,ARG_THROW,ARG_MASK,	'm',A_CS1,A_ADM,A_DYI,A_CFA,A_ANY,	0,		0,		0,		0,		opt_throw,
-			ARG_MASK_FORM, 	"specify network of throw rule"},
+			ARG_MASK_FORM, 	"specify network of throw rule"}
 		
-		
-	{ODI,5,0,ARG_PEDANTIC_CLEANUP,	0,  A_PS1,A_ADM,A_DYI,A_CFA,A_ANY,	&Pedantic_cleanup,0,		1,		0,		0,
+#ifndef LESS_OPTIONS
+	,
+	{ODI,5,0,ARG_PEDANTIC_CLEANUP,	0,  A_PS1,A_ADM,A_DYI,A_CFA,A_ANY,	&Pedantic_cleanup,0,		1,		DEF_PEDANT_CLNUP,0,
 			ARG_VALUE_FORM,	"disable/enable pedantic cleanup of system configuration (like ip_forward,..) \n"
 			"	at program termination. Its generally safer to keep this disabled to not mess up \n"
-			"	with other routing protocols" }
+			"	with other routing protocols"}
+#endif
 		
 };
 
@@ -2169,11 +2193,14 @@
 
 void init_route( void ) {
 	
-	if( open_netlink_socket() < 0 )
+	if( ( nl_sk = open_netlink_socket()) <= 0 )
 		cleanup_all( -500067 );
 	
-	errno=0;
-	if ( !rt_sock  &&  (rt_sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
+	if( ( flush_sk = open_netlink_socket()) <= 0 )
+		cleanup_all( -500067 );
+
+        errno=0;
+	if ( !rt_sock  &&  (rt_sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
 		dbgf( DBGL_SYS, DBGT_ERR, "can't create routing socket %s:",  strerror(errno) );
 		cleanup_all( -500021 );
 	} 
@@ -2200,8 +2227,12 @@
 	
 	restore_kernel_config( NULL );
 	
-	close_netlink_socket();
+        if( nl_sk > 0 )
+                close( nl_sk );
 	
+        if( flush_sk > 0 )
+                close( flush_sk );
+
 	if ( rt_sock )
 		close( rt_sock );
 	

Modified: trunk/batman-experimental/list-batman.c
===================================================================
--- trunk/batman-experimental/list-batman.c	2010-04-12 19:06:37 UTC (rev 1633)
+++ trunk/batman-experimental/list-batman.c	2010-04-15 08:16:16 UTC (rev 1634)
@@ -29,12 +29,14 @@
  * This is only for internal list manipulation where we know
  * the next entries already!
  */
+/*
 void __list_add( struct list_head *new, struct list_head *prev, struct list_head *next ) {
 
 	new->next = next;
 	prev->next = new;
 
 }
+*/
 
 /**
  * list_add - add a new entry
@@ -46,8 +48,11 @@
  */
 void list_add( struct list_head *new, struct list_head_first *head ) {
 
-	__list_add( new, (struct list_head *)head, head->next );
+//	__list_add( new, (struct list_head *)head, head->next );
+	new->next = head->next;
+	((struct list_head *)head)->next = new;
 
+
 	if ( head->prev == (struct list_head *)head )
 		head->prev = new;
 
@@ -63,7 +68,9 @@
  */
 void list_add_tail( struct list_head *new, struct list_head_first *head ) {
 
-	__list_add( new, head->prev, (struct list_head *)head );
+//	__list_add( new, head->prev, (struct list_head *)head );
+        new->next = (struct list_head *)head;
+        head->prev->next = new;
 
 	head->prev = new;
 
@@ -85,11 +92,13 @@
  * This is only for internal list manipulation where we know
  * the next entries already!
  */
+/*
 void __list_del( struct list_head *prev, struct list_head *next ) {
 
 	prev->next = next;
 
 }
+*/
 
 /**
  * list_del - deletes entry from list.
@@ -101,8 +110,10 @@
 	if ( head->prev == entry )
 		head->prev = prev_entry;
 
-	__list_del( prev_entry, entry->next );
+//	__list_del( prev_entry, entry->next );
+	prev_entry->next = entry->next;
 
+
 	entry->next = (void *) 0;
 
 }
@@ -113,9 +124,10 @@
  * list_empty - tests whether a list is empty
  * @head: the list to test.
  */
+/*
 int list_empty( struct list_head_first *head ) {
 
 	return head->next == (struct list_head *)head;
 
 }
-
+*/

Modified: trunk/batman-experimental/list-batman.h
===================================================================
--- trunk/batman-experimental/list-batman.h	2010-04-12 19:06:37 UTC (rev 1633)
+++ trunk/batman-experimental/list-batman.h	2010-04-15 08:16:16 UTC (rev 1634)
@@ -52,10 +52,10 @@
 void list_add_tail( struct list_head *new, struct list_head_first *head );
 void list_add_before( struct list_head *prev_node, struct list_head *next_node, struct list_head *new_node );
 void list_del( struct list_head *prev_entry, struct list_head *entry, struct list_head_first *head );
-int list_empty( struct list_head_first *head );
+//int list_empty( struct list_head_first *head );
 
+#define list_empty(lst)  ((lst)->next == (struct list_head *)(lst))
 
-
 #define INIT_LIST_HEAD(ptr) do { \
 	(ptr)->next = (ptr); \
 } while (0)

Modified: trunk/batman-experimental/metrics.c
===================================================================
--- trunk/batman-experimental/metrics.c	2010-04-12 19:06:37 UTC (rev 1633)
+++ trunk/batman-experimental/metrics.c	2010-04-15 08:16:16 UTC (rev 1634)
@@ -29,136 +29,16 @@
 
 void flush_sq_record( struct sq_record *sqr ) {
 	
-	sqr->wa_val = sqr->wa_unscaled = sqr->wa_clr_sqn = sqr->wa_clr_sqn = 0;
-	
-	memset( sqr->sqn_entry_queue, 0, SQN_LOUNGE_SIZE );
-}
+	sqr->wa_val = sqr->wa_unscaled = 0;
+        sqr->wa_clr_sqn = sqr->wa_set_sqn = ((SQ_TYPE) (sqr->wa_clr_sqn - (MAX_PATH_LOUNGE + MAX_PWS + 1)));
 
-
-//returns seqno tip of exit queue
-static void push_sqn_lounge_queue( uint8_t probe, uint8_t lounge_size, SQ_TYPE seqno, 
-                            struct sq_record *sqr, uint8_t ws,
-                            uint8_t *exit_queue, uint8_t *exit_queue_len, SQ_TYPE *exit_queue_tip, 
-                            uint32_t orig, uint32_t neigh, struct batman_if *bif, char *who )
-{
-
-	uint8_t pos = seqno % (SQN_LOUNGE_SIZE);
-	
-	dbgf_ext( DBGT_INFO, "probe %d, SQN %d, exitQueueTip %d, lounge_size %d, wa_val_old %d ws %d",
-	          probe, seqno, sqr->sqn_entry_queue_tip, lounge_size, sqr->wa_val, ws );
-	
-	if ( seqno == sqr->sqn_entry_queue_tip ) { 
-		
-#ifndef NOPARANOIA
-		if ( probe  &&  sqr->sqn_entry_queue[pos] ) {
-			dbgf( DBGL_SYS, DBGT_ERR,
-			      "%s  OG %16s  NB %16s  IF %s probe[%d]=%d but entryQueue[pos:%d]=%d already marked!",
-			      who, ipStr(orig), ipStr(neigh), bif->dev, 
-			      seqno, probe, pos, sqr->sqn_entry_queue[pos] );
-		}
-#endif		
-		if ( !sqr->sqn_entry_queue[pos] )
-			sqr->sqn_entry_queue[pos] = probe;
-		
-		*exit_queue_len = 0;
-		*exit_queue_tip = sqr->sqn_entry_queue_tip - lounge_size;
-		
-		dbgf_ext( DBGT_INFO, "MAINSTREAM (SQN equal to entry_queue_tip) wa_val_new %d, exitQueueLen %d, exitQueue[tip:%d] %d",
-		         sqr->wa_val, *exit_queue_len, *exit_queue_tip, exit_queue[(*exit_queue_tip)%SQN_LOUNGE_SIZE]);
-		
-		
-		
-	} else if ( ((SQ_TYPE)( seqno - sqr->sqn_entry_queue_tip )) > MAX_SEQNO - lounge_size ) {  //impossible for lounge_size==0
-		
-#ifndef NOPARANOIA
-		if ( probe  &&  sqr->sqn_entry_queue[pos] ) {
-			dbgf( DBGL_SYS, DBGT_ERR,
-			      "%s  OG %16s  NB %16s  IF %s probe[%d]=%d but entryQueue[pos:%d]=%d already marked! tip %d",
-			      who, ipStr(orig), ipStr(neigh), bif->dev, 
-			      seqno, probe, pos, sqr->sqn_entry_queue[pos], sqr->sqn_entry_queue_tip);
-		}
-#endif
-		if ( !sqr->sqn_entry_queue[pos] )
-			sqr->sqn_entry_queue[pos] = probe;
-		
-		*exit_queue_len = 0;
-		
-		*exit_queue_tip = sqr->sqn_entry_queue_tip - lounge_size;
-		
-		dbgf_ext( DBGT_INFO, "ACCEPTABLE (SQN within entry-queue-boundaries) wa_val_new %d, exitQueueLen %d, exitQueue[tip:%d] %d",
-		         sqr->wa_val, *exit_queue_len, *exit_queue_tip, exit_queue[(*exit_queue_tip)%SQN_LOUNGE_SIZE]);
-		
-		
-	} else if ( ((SQ_TYPE)( seqno - sqr->sqn_entry_queue_tip )) <= lounge_size ) {  //impossible for lounge_size==0
-		// seqno == sqr->sqn_entry_queue_tip has already been catched above
-		
-		SQ_TYPE i;
-		uint8_t len = 0;
-		
-		
-		for( i = sqr->sqn_entry_queue_tip+1-lounge_size; i != ((SQ_TYPE)(seqno+1-lounge_size)); i++ ) {
-			len++;
-			exit_queue[i%SQN_LOUNGE_SIZE] = sqr->sqn_entry_queue[i%SQN_LOUNGE_SIZE];
-		}
-		
-		for( i = sqr->sqn_entry_queue_tip+1 ; i != ((SQ_TYPE)(seqno+1)); i++ )
-			sqr->sqn_entry_queue[i%SQN_LOUNGE_SIZE] = 0;
-		
-		sqr->sqn_entry_queue[pos] = probe;
-		sqr->sqn_entry_queue_tip = seqno;
-		
-		*exit_queue_len = len;
-		*exit_queue_tip = sqr->sqn_entry_queue_tip - lounge_size;
-		
-		dbgf_ext( DBGT_INFO, "AVANTGARDE (SQN redefining entry-queue-boundaries) wa_val_new %d, exitQueueLen %d, exitQueue[tip:%d] %d",
-		         sqr->wa_val, *exit_queue_len, *exit_queue_tip, exit_queue[(*exit_queue_tip)%SQN_LOUNGE_SIZE]);
-		
-		
-		
-	} else if ( ((SQ_TYPE)( seqno - sqr->sqn_entry_queue_tip )) <= ws + lounge_size ) {
-		// seqno - sqr->sqn_entry_queue_tip <= lounge_size has already been catched above
-		
-		SQ_TYPE i, old_entry_queue_tip = sqr->sqn_entry_queue_tip;
-		
-		for( i = sqr->sqn_entry_queue_tip+1-lounge_size ; i != ((SQ_TYPE)(sqr->sqn_entry_queue_tip+1)); i++ )
-			exit_queue[i%SQN_LOUNGE_SIZE] = sqr->sqn_entry_queue[i%SQN_LOUNGE_SIZE];
-		
-		
-		for( i = seqno+1 - lounge_size ; i != ((SQ_TYPE)(seqno+1)); i++ )
-			sqr->sqn_entry_queue[i%SQN_LOUNGE_SIZE] = 0;
-		
-		sqr->sqn_entry_queue[pos] = probe;
-		sqr->sqn_entry_queue_tip = seqno;
-		
-		*exit_queue_len = lounge_size;
-		*exit_queue_tip = old_entry_queue_tip;
-		
-		dbgf_ext( DBGT_INFO, "CRITICAL NEW (partly purging entry-queue) wa_val_new %d, exitQueueLen %d, exitQueue[tip:%d] %d",
-		         sqr->wa_val, *exit_queue_len, *exit_queue_tip, exit_queue[(*exit_queue_tip)%SQN_LOUNGE_SIZE]);
-		
-	} else {
-		
-		SQ_TYPE i;
-		
-		for( i = seqno+1 - lounge_size ; i != ((SQ_TYPE)(seqno+1)); i++ )
-			sqr->sqn_entry_queue[i%SQN_LOUNGE_SIZE] = 0;
-		
-		sqr->sqn_entry_queue[pos] = probe;
-		sqr->sqn_entry_queue_tip = seqno;
-		
-		*exit_queue_len = 0;
-		*exit_queue_tip = sqr->sqn_entry_queue_tip - lounge_size;
-		
-		dbgf_ext( DBGT_INFO, "LOST NEW (completely purging entry-queue) wa_val_new %d, exitQueueLen %d, exitQueue[tip:%d] %d",
-		         sqr->wa_val, *exit_queue_len, *exit_queue_tip, exit_queue[(*exit_queue_tip)%SQN_LOUNGE_SIZE]);
-
-	}
 }
 
 
+/*
+//static
+void update_metric( uint8_t probe, SQ_TYPE sq_upd, struct sq_record *sqr, uint8_t ws ) {
 
-static void update_metric( uint8_t probe, SQ_TYPE sq_upd, struct sq_record *sqr, uint8_t ws ) {
-
 	uint32_t m_weight = ws/2;
 	SQ_TYPE offset = sq_upd - sqr->wa_clr_sqn;
 	uint32_t old_wa_val = sqr->wa_val;
@@ -195,75 +75,57 @@
 	dbgf_ext( DBGT_INFO, "probe %d, SQN %d, old_wa_val %d, new_wa_val %d", probe, sq_upd, old_wa_val, sqr->wa_val );
 	
 }
+*/
 
 
 
-/*update_queued_metric() MUST deal with unordered SQNs !!!
+void update_lounged_metric(uint8_t probe, uint8_t lounge_size, SQ_TYPE sqn_incm, SQ_TYPE sqn_max, struct sq_record *sqr, uint8_t ws)
+{
+        SQ_TYPE sq_upd;
 
-SQNs of incoming OGM are collected (queued) in a waiting-room/lounge (entry-queue) 
-before being further processed (considered for path/link quality calculation).
-This way we can reorder lately rcvd OGM-SQNs and process them in the right order.
-The maximum acceptable delay (in terms of SQNs) is defined by the lounge_size of each node.
+        if ( probe )
+                sq_upd = sqn_incm;
 
-push_sqn_lounge_queue() is responsible to manage the waiting room and return ready-to-process SQN in the exit-queue
+        else if ( ((SQ_TYPE)(sqn_max - sqr->wa_clr_sqn )) > lounge_size )
+                sq_upd = sqn_max - lounge_size;
 
+        else
+                return;
 
-*/
-void update_queued_metric( uint8_t probe, uint8_t lounge_size, SQ_TYPE seqno, struct sq_record *sqr, uint8_t ws,
-                           uint32_t orig, uint32_t neigh, struct batman_if *bif, char* who )
-{
-	dbgf_ext( DBGT_INFO, " " );
-	
-	uint8_t old_wa_val;
-	old_wa_val = sqr->wa_val;
-	
-	if ( lounge_size == 0 ) {
-		
-		//IMPORTANT: update_metric needs ordered SQNs
-		update_metric( probe, seqno, sqr, ws );
-	
+
+        uint32_t m_weight = ws/2;
+	SQ_TYPE i, offset = sq_upd - sqr->wa_clr_sqn;
+
+	if ( offset >= ws ) {
+
+		sqr->wa_unscaled = 0;
+
 	} else {
-	
-		uint8_t exit_queue[SQN_LOUNGE_SIZE];
-		uint8_t exit_queue_len;
-		SQ_TYPE exit_queue_tip;
-		
-		push_sqn_lounge_queue( probe, lounge_size, seqno, sqr, ws, 
-		                       exit_queue, &exit_queue_len, &exit_queue_tip,
-		                       orig, neigh, bif, who );
-		
-		SQ_TYPE i;
-		for( i = exit_queue_tip+1-exit_queue_len; i != ((SQ_TYPE)(exit_queue_tip+1)); i++ )
-			update_metric( exit_queue[i%SQN_LOUNGE_SIZE], i, sqr, ws );
-		
-		if ( sqr->sqn_entry_queue_tip == seqno ) { 						// MAINSTREAM, AVANTGARDE, CRITICAL_NEW, or LOST_NEW
-			
-			if ( exit_queue_len == 0  ||							// MAINSTREAM, ACCEPTABLE, or LOST_NEW
-			     ((SQ_TYPE)(sqr->sqn_entry_queue_tip - lounge_size)) != exit_queue_tip )	// CRITICAL_NEW
-			{
-				update_metric( 0, sqr->sqn_entry_queue_tip - lounge_size, sqr, ws );
-			}
-		
-		}	
+
+		for ( i=0; i < offset; i++ )
+			sqr->wa_unscaled -= ( sqr->wa_unscaled / m_weight );
+
 	}
-	
-	//dbgf( ((old_wa_val && !sqr->wa_val) ?  DBGL_CHANGES : DBGL_ALL), ((old_wa_val && !sqr->wa_val) ?  DBGT_WARN : DBGT_INFO),
-	dbgf_ext( DBGT_INFO,
-	/*if ( !strcmp( who, "process_ogm(own via NB)" ) || !strcmp( who, "schedule_own_ogm()") ) 
-	 	dbg( DBGL_CHANGES, DBGT_INFO, */
-	          "done! %26s  OG %-15s  via IF %-10s  NB %-10s  probe %3d  lounge_size %2d  SQN %-5d  wa_val old %3d  new %3d",
-	          who, ipStr( orig ), bif->dev, ipStr( neigh ), probe, lounge_size, seqno, old_wa_val, sqr->wa_val );
-	
-	
-}
 
+	sqr->wa_clr_sqn = sq_upd;
 
-uint32_t get_wavg( uint32_t wavg, uint8_t weight_exp ) {
+	if ( probe /* &&  sqr->wa_set_sqn != sq_upd */  ) {
 
-	return wavg>>weight_exp;
+                paranoia( -500197, (sqr->wa_set_sqn == sq_upd) /*check validate_considered_order()*/ );
+
+		sqr->wa_unscaled += ( (probe * WA_SCALE_FACTOR) / m_weight );
+
+		sqr->wa_set_sqn = sq_upd;
+	}
+
+	sqr->wa_val = sqr->wa_unscaled/WA_SCALE_FACTOR;
+
+
 }
 
 
+
+
 uint32_t upd_wavg( uint32_t *wavg, uint32_t probe, uint8_t weight_exp ) {
 	
 #ifndef NOPARANOIA
@@ -280,5 +142,5 @@
 		*wavg = probe<<weight_exp;
 	
 	
-	return *wavg>>weight_exp;
+	return WAVG(*wavg,weight_exp);
 }

Modified: trunk/batman-experimental/metrics.h
===================================================================
--- trunk/batman-experimental/metrics.h	2010-04-12 19:06:37 UTC (rev 1633)
+++ trunk/batman-experimental/metrics.h	2010-04-15 08:16:16 UTC (rev 1634)
@@ -28,10 +28,10 @@
 
 void flush_sq_record( struct sq_record *sqr );
 
-void update_queued_metric( uint8_t probe, uint8_t lounge_size, SQ_TYPE seqno, struct sq_record *sqr, uint8_t ws,
-                           uint32_t orig, uint32_t neigh, struct batman_if *bif, char* who );
+void update_lounged_metric( uint8_t probe, uint8_t lounge_size, SQ_TYPE sqn_incm, SQ_TYPE sqn_max, struct sq_record *sqr, uint8_t ws );
 
-uint32_t get_wavg( uint32_t wavg, uint8_t weight_exp );
+#define WAVG( wavg , weight_exp ) ( (uint32_t) ( (wavg) >> (weight_exp) ) )
+
 uint32_t upd_wavg( uint32_t *wavg, uint32_t probe, uint8_t weight_exp );
 
 #endif

Modified: trunk/batman-experimental/originator.c
===================================================================
--- trunk/batman-experimental/originator.c	2010-04-12 19:06:37 UTC (rev 1633)
+++ trunk/batman-experimental/originator.c	2010-04-15 08:16:16 UTC (rev 1634)
@@ -30,41 +30,62 @@
 #include "originator.h"
 #include "plugin.h"
 #include "schedule.h"
+//#include "avl.h"
 
 static int32_t my_seqno;
-static int32_t path_hystere;
 
-int32_t my_lws;
-int32_t my_pws;
-int32_t my_ogi = DEF_OGI;   /* orginator message interval in miliseconds */
 
-int32_t my_link_lounge;
-int32_t Default_lounge;
+int32_t my_pws = DEF_PWS;
 
-static int32_t purge_to;
-static int32_t dad_to;
+int32_t local_lws = DEF_LWS;
 
-static int32_t lateness_penalty;
+int32_t local_rtq_lounge = DEF_RTQ_LOUNGE;
 
-static int32_t Asocial_device;
+int32_t my_path_lounge = DEF_PATH_LOUNGE;
 
-int32_t Ttl;
+static int32_t my_path_hystere = DEF_PATH_HYST;
 
-int32_t wl_clones;
+static int32_t my_rcnt_hystere = DEF_RCNT_HYST;
 
-static int32_t asym_weight;
+static int32_t my_rcnt_pws = DEF_RCNT_PWS;
 
-static int32_t asym_exp;
+/*
+static int32_t my_rcnt_lounge = DEF_RCNT_LOUNGE;
+*/
 
+static int32_t my_rcnt_fk = DEF_RCNT_FK;
 
+static int32_t my_late_penalty = DEF_LATE_PENAL;
+
+static int32_t drop_2hop_loop = DEF_DROP_2HLOOP;
+
+static int32_t purge_to = DEF_PURGE_TO;
+
+int32_t dad_to = DEF_DAD_TO;
+
+static int32_t Asocial_device = DEF_ASOCIAL;
+
+int32_t Ttl = DEF_TTL;
+
+int32_t wl_clones = DEF_WL_CLONES;
+
+static int32_t my_asym_weight = DEF_ASYM_WEIGHT;
+
+static int32_t my_hop_penalty = DEF_HOP_PENALTY;
+
+static int32_t my_asym_exp = DEF_ASYM_EXP;
+
+
 static SIMPEL_LIST( pifnb_list );
 SIMPEL_LIST( link_list );
+//struct avl_tree link_avl = {sizeof( uint32_t), NULL};
+AVL_TREE( link_avl, sizeof( uint32_t) );
 
 struct batman_if *primary_if = NULL;
 uint32_t primary_addr = 0;
-//char primary_ip_str[ADDR_STR_LEN] = "";
 
-struct hashtable_t *orig_hash = NULL;
+//struct avl_tree orig_avl = {sizeof( uint32_t), NULL};
+AVL_TREE( orig_avl, sizeof( uint32_t) );
 
 SIMPEL_LIST( if_list );
 
@@ -79,20 +100,20 @@
 	
 	dbgf_all( DBGT_INFO, " " );
 	
-	addr_to_str( (new_router        ? new_router->addr :        0 ), new_nh_str );
-	addr_to_str( (orig_node->router ? orig_node->router->addr : 0 ), old_nh_str );
+	addr_to_str( (new_router        ? new_router->nnkey_addr :        0 ), new_nh_str );
+	addr_to_str( (orig_node->router ? orig_node->router->nnkey_addr : 0 ), old_nh_str );
 	
 	/* update routing table and check for changed hna announcements */
 	if ( orig_node->router != new_router )
 		dbg( DBGL_CHANGES, DBGT_INFO, "change route to %-15s via %-15s %s %3d / %3d (prev. via %-15s %s %3d)",
 		     orig_node->orig_str, 
 		     new_nh_str, 
-		     (new_router ? new_router->iif->dev : "--"),
-		     (new_router ? new_router->accepted_sqr.wa_val : 0), 
+		     (new_router ? new_router->nnkey_iif->dev : "--"),
+		     (new_router ? new_router->longtm_sqr.wa_val : 0),
 		     orig_node->pws, 
 		     old_nh_str, 
-		     (orig_node->router ? orig_node->router->iif->dev : "--"),
-		     (orig_node->router ? orig_node->router->accepted_sqr.wa_val : 0) );
+		     (orig_node->router ? orig_node->router->nnkey_iif->dev : "--"),
+		     (orig_node->router ? orig_node->router->longtm_sqr.wa_val : 0) );
 	
 	
 	if (  orig_node->router != new_router  ) {
@@ -104,10 +125,10 @@
 		/* route altered or deleted */
 		if ( orig_node->router ) {
 			
-			add_del_route( 	orig_node->orig, 32, orig_node->router->addr, 0, 
-			               	orig_node->router->iif->if_index, 
-			               	orig_node->router->iif->dev, 
-			               	RT_TABLE_HOSTS, RT_UNICAST, DEL, TRACK_OTHER_HOST );
+			add_del_route( 	orig_node->orig, 32, orig_node->router->nnkey_addr, 0,
+			               	orig_node->router->nnkey_iif->if_index,
+			               	orig_node->router->nnkey_iif->dev,
+			               	RT_TABLE_HOSTS, RTN_UNICAST, DEL, TRACK_OTHER_HOST );
 			
 		}
 		
@@ -116,10 +137,10 @@
 			
 			orig_node->rt_changes++;
 			
-			add_del_route( orig_node->orig, 32, new_router->addr, primary_addr, 
-			               new_router->iif->if_index, 
-			               new_router->iif->dev, 
-			               RT_TABLE_HOSTS, RT_UNICAST, ADD, TRACK_OTHER_HOST );
+			add_del_route( orig_node->orig, 32, new_router->nnkey_addr, primary_addr,
+			               new_router->nnkey_iif->if_index,
+			               new_router->nnkey_iif->dev,
+			               RT_TABLE_HOSTS, RTN_UNICAST, ADD, TRACK_OTHER_HOST );
 			
 		}
 		
@@ -132,7 +153,7 @@
 }
 
 static void flush_orig( struct orig_node *orig_node, struct batman_if *bif ) {
-	struct list_head *neigh_pos /*, *neigh_temp, *neigh_prev*/;
+	struct list_head *neigh_pos /*, *neigh_temp, *neigh_prev */;
 	struct neigh_node *neigh_node = NULL;
 	
 	dbgf_all( DBGT_INFO, "%s", ipStr( orig_node->orig ) );
@@ -141,20 +162,49 @@
 
 		neigh_node = list_entry( neigh_pos, struct neigh_node, list );
 		
-		if ( !bif  ||  bif == neigh_node->iif )
-			flush_sq_record( &neigh_node->accepted_sqr );
+		if ( !bif  ||  bif == neigh_node->nnkey_iif ) {
+			flush_sq_record( &neigh_node->longtm_sqr );
+			flush_sq_record( &neigh_node->recent_sqr );
+                }
 	}
+
 	
-	if ( !bif  ||  ( orig_node->router  &&  orig_node->router->iif == bif ) ) {
+	if ( !bif  ||  ( orig_node->router  &&  orig_node->router->nnkey_iif == bif ) ) {
 		
 		update_routes( orig_node, NULL );
 	
 		cb_plugin_hooks( orig_node, PLUGIN_CB_ORIG_FLUSH );
 	}
+
+/*
+ * plugins must be called with PLUGIN_CB_ORIG_FLUSH and PLUGIN_CB_ORIG_DESRTROY
+ * before orig_node->router can be destroyed:
+ *
+        neigh_prev = (struct list_head *) & orig_node->neigh_list;
+        // for all neighbours towards this originator ...
+
+        list_for_each_safe(neigh_pos, neigh_temp, &orig_node->neigh_list) {
+
+                neigh_node = list_entry(neigh_pos, struct neigh_node, list);
+
+                if (!bif || (neigh_node->iif == bif)) {
+
+                        list_del(neigh_prev, neigh_pos, &orig_node->neigh_list);
+
+                        debugFree(neigh_node, 1403);
+
+                } else {
+                        neigh_prev = &neigh_node->list;
+                }
+        }
+*/
+
+
 }
 
 
-static struct neigh_node *init_neigh_node( struct orig_node *orig_node, uint32_t neigh, struct batman_if *iif, uint16_t seqno, uint32_t last_aware )
+static
+struct neigh_node *init_neigh_node( struct orig_node *orig_node, uint32_t neigh, struct batman_if *iif, uint16_t seqno, uint32_t last_aware )
 {
 	dbgf_all( DBGT_INFO, " " );
 
@@ -162,142 +212,207 @@
 	memset( neigh_node, 0, sizeof(struct neigh_node) );
 	INIT_LIST_HEAD( &neigh_node->list );
 
-	neigh_node->addr = neigh;
-	neigh_node->iif = iif;
+	neigh_node->nnkey_addr = neigh;
+	neigh_node->nnkey_iif = iif;
 	neigh_node->last_aware = last_aware;
 	
 	list_add_tail( &neigh_node->list, &orig_node->neigh_list );
+        avl_insert(&orig_node->neigh_avl, neigh_node );
 	return neigh_node;
 
 }
 
-
-
-static struct neigh_node *update_orig( struct orig_node *orig_node, struct orig_node *orig_node_neigh, 
-                                       uint16_t *oCtx, struct msg_buff *mb )
+static
+struct neigh_node *update_orig(struct orig_node *on, uint16_t *oCtx, struct msg_buff *mb)
 {
-
 	prof_start( PROF_update_originator );
 	
 	struct list_head *neigh_pos;
-	struct neigh_node *incoming_neigh = NULL, *tmp_neigh = NULL;
-	struct neigh_node *curr_router = orig_node->router;
-	
+	struct neigh_node *incm_rt = NULL, *tmp_neigh = NULL;
+	struct neigh_node *curr_rt = on->router;
+        struct neigh_node *old_rt;
 	struct bat_packet_ogm *ogm = mb->bp.ogm;
-	
-	uint32_t best_neigh_val = 0;
-	
-	dbgf_all( DBGT_INFO, "%s", orig_node->orig_str );
 
-	
+        old_rt = curr_rt;
+        uint32_t max_othr_longtm_val = 0;
+	uint32_t max_othr_recent_val = 0;
+
+	dbgf_all( DBGT_INFO, "%s", on->orig_str );
+
 	/* only used for debugging purposes */
-	if (  orig_node->first_valid_sec == 0  )
-		orig_node->first_valid_sec = batman_time_sec;
+        if (!on->first_valid_sec)
+                on->first_valid_sec = batman_time_sec;
 	
 	
 	// find incoming_neighbor and purge outdated SQNs of alternative next hops
-	list_for_each( neigh_pos, &orig_node->neigh_list ) {
+	list_for_each( neigh_pos, &on->neigh_list ) {
 
+		uint8_t probe = 0;
+
 		tmp_neigh = list_entry( neigh_pos, struct neigh_node, list );
 
-		if ( ( tmp_neigh->addr == mb->neigh ) && ( tmp_neigh->iif == mb->iif ) )
-			incoming_neigh = tmp_neigh;
+		if ( ( tmp_neigh->nnkey_addr == mb->neigh ) && ( tmp_neigh->nnkey_iif == mb->iif ) ) {
 
-		uint8_t probe = 0;
-		
-		if ( incoming_neigh == tmp_neigh  && (*oCtx & IS_ACCEPTED)) {
-			
-			if ( *oCtx & IS_NEW )
-				probe = PROBE_RANGE;
-			else
-				probe = PROBE_RANGE - (lateness_penalty*PROBE_TO100);
-			
-		}
-		
-		update_queued_metric( probe,
-		                      orig_node->path_lounge, ogm->ogm_seqno, &tmp_neigh->accepted_sqr, orig_node->pws,
-		                      orig_node->orig, tmp_neigh->addr, mb->iif, 
-		                      (incoming_neigh == tmp_neigh) ? "update_orig( incoming NB )" : "update_orig( other NB )" );
-			
-	
-		best_neigh_val = MAX( best_neigh_val, tmp_neigh->accepted_sqr.wa_val );
-		
-	}
+			incm_rt = tmp_neigh;
 
-	if ( !incoming_neigh )
-		cleanup_all( -500001 );
-	
-	
-	/* 
-	only change curr_router if:
-	- incoming packet has been received via incoming_neighbor which is better than the old curr_router
-	- not-yet-rebroadcasted (not-yet-decided based on) this or newer seeqno
-	*/
-	
-	if ( ( ( curr_router == NULL ) ||  
-	       ( curr_router->accepted_sqr.wa_val == 0  &&  incoming_neigh->accepted_sqr.wa_val )  ||
-	       ( curr_router->accepted_sqr.wa_val + (path_hystere*PROBE_TO100) < incoming_neigh->accepted_sqr.wa_val) )  &&
-	     //( (uint16_t)( ogm->ogm_seqno - (orig_node->last_decided_sqn + 1) )  <=  MAX_SEQNO - orig_node->pws ) )
-	     ((SQ_TYPE)( orig_node->last_decided_sqn - ogm->ogm_seqno ) >= orig_node->pws ) )
-	{
-		curr_router = incoming_neigh;
-	}
-	
-	/* 
-	only keep and rebroadcast OGM rcvd via old curr_router if:
-	- curr_router == incoming_neighbor is really the best neighbor towards our destination
-	- not-yet-rebroadcasted (not-yet-decided based on) this or newer seeqno
-	*/
-	if ( curr_router == incoming_neigh ) {
-		
-		if ( ( curr_router->accepted_sqr.wa_val + (path_hystere*PROBE_TO100) >= best_neigh_val ) &&
-		     ((SQ_TYPE)( orig_node->last_decided_sqn - ogm->ogm_seqno ) >= orig_node->pws ) ) {
-			
-			orig_node->last_decided_sqn = ogm->ogm_seqno;
-		
-			*oCtx |= IS_BEST_NEIGH_AND_NOT_BROADCASTED;
-			
-		}
-		
-	} else {
-		
+                        if (*oCtx & IS_ACCEPTED) {
+
+                                if (*oCtx & IS_NEW)
+                                        probe = PROBE_RANGE;
+                                else
+                                        probe = PROBE_RANGE - (my_late_penalty * PROBE_TO100);
+                        }
+                }
+
+                update_lounged_metric(probe, my_path_lounge, ogm->ogm_seqno, on->last_valid_sqn, &tmp_neigh->longtm_sqr,
+                        on->pws);
+
+                if ( incm_rt != tmp_neigh)
+                        max_othr_longtm_val = MAX(max_othr_longtm_val, tmp_neigh->longtm_sqr.wa_val);
+
+
+
+                if ( my_rcnt_fk == MAX_RCNT_FK )
+                        continue;
+
+                //if (*oCtx & IS_NEW || (((SQ_TYPE) (on->last_valid_sqn - ogm->ogm_seqno)) <= my_rcnt_lounge))
+
+                update_lounged_metric(probe, my_path_lounge, ogm->ogm_seqno, on->last_valid_sqn, &tmp_neigh->recent_sqr,
+                        my_rcnt_pws);
+                
+
+                if ( incm_rt != tmp_neigh )
+                        max_othr_recent_val = MAX(max_othr_recent_val, tmp_neigh->recent_sqr.wa_val);
+
+        }
+
+
+
+        paranoia( -500001, !incm_rt );
+
+        /*
+         * The following if-else-else branch implements my currently best known heuristic
+         * Its tuned for fast path convergence as well as long-term path-quality awareness.
+         * In the future this should be configurable by each node participating in the mesh.
+         * Its Fuzzy! The following path-quality characteristics are judged:
+         * - Recent vers. Longterm  path quality
+         * - eXtreme vers. Conservative  distinction to alternative paths
+         * - Best  vers. Worst  path quality
+         * allowing combinations like:
+         *   Recent_Conservative_Best (RCB)  --  Recent_eXtreme_Best (RXB)  --  Longterm_Conservative_Best (LCB)
+         * The  general idea is to keep/change the path (best neighbor) if:
+         *   -  change: (RXB (implying RCB)) || (RCB && LCB)
+         *   -  keep:  RXB || RCB || LCB
+         *   -  not-yet-rebroadcasted (not-yet-finally-decided based on) this or newer seqno
+         *    - incoming packet has been received via incoming_neighbor which is better than all other router
+         *    - curr_router == incoming_neighbor is really the best neighbor towards our destination
+         * */
+        int8_t RXB = 0, RCB = 0, LCB = 0, changed = 0;
+
+
+        if ( ( curr_rt != incm_rt ) &&
+             ( ((SQ_TYPE)( on->last_decided_sqn - ogm->ogm_seqno ) >= on->pws ) )  &&
+
+             ( ( ( my_rcnt_fk == MAX_RCNT_FK ) &&
+                 ( (   LCB = ((int)incm_rt->longtm_sqr.wa_val >  (int)(max_othr_longtm_val)                    + (my_path_hystere * PROBE_TO100)) ) )
+
+               ) || (
+
+                 ( my_rcnt_fk != MAX_RCNT_FK ) &&
+
+                 ( ( ( LCB = ((int)incm_rt->longtm_sqr.wa_val >  (int)(max_othr_longtm_val)                    + (my_path_hystere * PROBE_TO100)) ) &&
+                     ( RCB = ((int)incm_rt->recent_sqr.wa_val >  (int)(max_othr_recent_val)                                                     ) ) )
+                   ||
+                   (   RXB = ((int)incm_rt->recent_sqr.wa_val >  (int)((max_othr_recent_val * my_rcnt_fk)/100) + (my_rcnt_hystere * PROBE_TO100)) )
+
+                 )
+               )
+             )
+           ) {
+
+                curr_rt = incm_rt;
+                on->last_decided_sqn = ogm->ogm_seqno;
+                *oCtx |= IS_BEST_NEIGH_AND_NOT_BROADCASTED;
+                changed = YES;
+
+        } else if
+           ( ( curr_rt == incm_rt ) &&
+             ( ((SQ_TYPE)( on->last_decided_sqn - ogm->ogm_seqno ) >= on->pws ) )  &&
+
+             ( ( ( my_rcnt_fk == MAX_RCNT_FK ) &&
+                 ( (   LCB = ((int)incm_rt->longtm_sqr.wa_val >= (int)(max_othr_longtm_val)                    - (my_path_hystere * PROBE_TO100)) ) )
+
+               ) || (
+
+                 ( my_rcnt_fk != MAX_RCNT_FK ) &&
+
+                 ( ( ( LCB = ((int)incm_rt->longtm_sqr.wa_val >= (int)(max_othr_longtm_val)                    - (my_path_hystere * PROBE_TO100)) ) ||
+                     ( RCB = ((int)incm_rt->recent_sqr.wa_val >= (int)(max_othr_recent_val)                                                     ) ) )
+                 )
+               )
+             )
+           ) {
+
+                on->last_decided_sqn = ogm->ogm_seqno;
+                *oCtx |= IS_BEST_NEIGH_AND_NOT_BROADCASTED;
+
+        }
+
+        if ( changed && !LCB ) {
+                dbgf(DBGL_CHANGES, DBGT_INFO,
+                        "%s path to %-15s via %-15s (old %-15s incm %-15s) due to %s %s %s PH: "
+                        "recent incm %3d  othr %3d  fk %-4d  "
+                        "longtm incm %3d  othr %3d",
+                        changed ? "NEW" : "OLD",
+                        on->orig_str,
+                        curr_rt ? ipStr(curr_rt->nnkey_addr) : "----",
+                        old_rt ? ipStr(old_rt->nnkey_addr) : "----",
+                        ipStr(incm_rt->nnkey_addr),
+                        LCB ? " LCB" : "!LCB",
+                        RCB ? " RCB" : "!RCB",
+                        RXB ? " RXB" : "!RXB",
+                        incm_rt->recent_sqr.wa_val / PROBE_TO100,
+                        max_othr_recent_val, my_rcnt_fk,
+                        incm_rt->longtm_sqr.wa_val / PROBE_TO100,
+                        max_othr_longtm_val
+                        );
+        }
+
+        if ( curr_rt != incm_rt ) {
+
 		// only evaluate and change recorded attributes and route if arrived via best neighbor
 		prof_stop( PROF_update_originator );
-		return curr_router;
+		return curr_rt;
 	}
-		
-	orig_node->last_path_ttl = ogm->ogm_ttl;
+
+
+	on->last_path_ttl = ogm->ogm_ttl;
 	
-	orig_node->ogx_flag = ogm->ogx_flag;
+	on->ogx_flag = ogm->ogx_flag;
 	
-	orig_node->ogm_misc = ogm->ogm_misc;	
+	on->ogm_misc = ogm->ogm_misc;
 	
-	uint8_t orig_changed = 0;
 	
-	if ( orig_node->pws != ogm->ogm_pws ) {
+	if ( on->pws != ogm->ogm_pws ) {
 	
 		dbg( DBGL_SYS, DBGT_INFO, 
 		     "window size of OG %s changed from %d to %d, flushing packets and route!",
-		     orig_node->orig_str, orig_node->pws, ogm->ogm_pws );
+		     on->orig_str, on->pws, ogm->ogm_pws );
 	
-		orig_node->pws = ogm->ogm_pws;
-		orig_changed++;
-	}
-		
-	if ( orig_changed ) {
-		flush_orig( orig_node, NULL );
+		on->pws = ogm->ogm_pws;
+		flush_orig( on, NULL );
 		prof_stop( PROF_update_originator );
 		return NULL;
 	}
-
 	
 	prof_stop( PROF_update_originator );
-	return curr_router;
+	return curr_rt;
 }
 
 
 
-static void free_pifnb_node( struct orig_node *orig_node ) {
+static
+void free_pifnb_node( struct orig_node *orig_node ) {
 	struct pifnb_node *pn;
 	struct list_head *pifnb_pos, *pifnb_pos_tmp, *prev_list_head;
 	
@@ -332,7 +447,8 @@
 }
 
 
-static int8_t init_pifnb_node( struct orig_node *orig_node ) {
+static
+int8_t init_pifnb_node( struct orig_node *orig_node ) {
 	struct pifnb_node *pn_tmp = NULL;
 	struct list_head *list_pos, *prev_list_head;
 	uint16_t id4him = 1;
@@ -378,7 +494,8 @@
 
 
 
-static void free_link_node( struct orig_node *orig_node, struct batman_if *bif ) {
+static
+void free_link_node( struct orig_node *orig_node, struct batman_if *bif ) {
 	
 	struct link_node *ln;
 	struct list_head *list_pos, *list_tmp, *list_prev;
@@ -399,7 +516,7 @@
 		
 		if ( !bif  ||  lndev->bif == bif ) {
 		
-			dbgf( DBGL_CHANGES, DBGT_INFO, "purging lndev %16s %10s %s",
+			dbgf_all( DBGT_INFO, "purging lndev %16s %10s %s",
 			     orig_node->orig_str, lndev->bif->dev, lndev->bif->if_ip_str );
 		
 			list_del( list_prev, list_pos, &ln->lndev_list );
@@ -421,7 +538,10 @@
 
 		if ( ln->orig_node == orig_node  &&  list_empty( &ln->lndev_list ) ) {
 
+                        dbgf_all( DBGT_INFO, "purging link_node %16s ", orig_node->orig_str);
+
 			list_del( list_prev, list_pos, &link_list );
+                        avl_remove(&link_avl, /*(uint32_t*)*/orig_node->link_node);
 			
 			debugFree( orig_node->link_node, 1428 );
 			
@@ -436,7 +556,8 @@
 }
 
 
-static void flush_link_node_seqnos( void ) {
+static
+void flush_link_node_seqnos( void ) {
 	struct list_head *ln_pos, *lndev_pos, *lndev_tmp;
 	struct link_node *ln = NULL;
 	
@@ -457,7 +578,8 @@
 	}
 }
 
-static void init_link_node( struct orig_node *orig_node ) {
+static
+void init_link_node( struct orig_node *orig_node ) {
 	
 	struct link_node *ln;
 	
@@ -468,47 +590,52 @@
 	INIT_LIST_HEAD( &ln->list );
 	
 	ln->orig_node = orig_node;
+        ln->orig_addr = orig_node->orig;
 	
 	INIT_LIST_HEAD_FIRST( ln->lndev_list );
 	
 	list_add_tail ( &ln->list, &link_list );
+        avl_insert(&link_avl, ln);
 }
 
 
-static int8_t validate_orig_seqno( struct orig_node *orig_node, uint32_t neigh, SQ_TYPE ogm_seqno ) {
+static
+int8_t validate_orig_seqno( struct orig_node *orig_node, uint32_t neigh, SQ_TYPE ogm_seqno ) {
 	
 	// this originator IP is somehow known..(has ever been valid)
 	if ( orig_node->last_valid_time  ||  orig_node->last_valid_sqn ) {
 		
-		if ( (uint16_t)( ogm_seqno + orig_node->path_lounge - orig_node->last_valid_sqn )  >  
+		if ( (uint16_t)( ogm_seqno + my_path_lounge - orig_node->last_valid_sqn )  >
 		     MAX_SEQNO - orig_node->pws ) {
 			
 			dbg_mute( 25, DBGL_CHANGES, DBGT_WARN,
 			          "drop OGM %-15s  via %4s NB %-15s  with old SQN %5i  "
 			          "(prev %5i  lounge-margin %2i  pws %3d  lvld %d) !", 
 			          orig_node->orig_str, 
-			          (orig_node->router && orig_node->router->addr == neigh) ? "best" : "altn",
+			          (orig_node->router && orig_node->router->nnkey_addr == neigh) ? "best" : "altn",
 			          ipStr(neigh), 
 			          ogm_seqno, 
 			          orig_node->last_valid_sqn, 
-			          orig_node->path_lounge, orig_node->pws, orig_node->last_valid_time );
+			          my_path_lounge, orig_node->pws, orig_node->last_valid_time );
 			
 			return FAILURE;
-		} 
-		
-		
-		if ( // if seqno is more than 10 times out of dad timeout
-		     ((uint16_t)( ogm_seqno + orig_node->path_lounge - orig_node->last_valid_sqn )) > 
-		     ((10 * dad_to) + orig_node->path_lounge)  && 
-		     // but we have received an ogm in less than timeout sec
-		     LESS_U32( batman_time, (orig_node->last_valid_time + (1000 * dad_to)) ) )  
+		}
+
+
+                if (// if seqno is more than 10 times out of dad timeout
+                        ((uint16_t) (ogm_seqno + my_path_lounge - orig_node->last_valid_sqn)) >
+                        (my_path_lounge +
+                        ((1000 * dad_to) / MIN(WAVG(orig_node->ogi_wavg, OGI_WAVG_EXP), MIN_OGI))) &&
+                        // but we have received an ogm in less than timeout sec
+                        LESS_U32(batman_time, (orig_node->last_valid_time + (1000 * dad_to))))
 		{
 			
 			dbg_mute( 26, DBGL_SYS, DBGT_WARN, 
 			          "DAD-alert! %s  via NB %s  with out-of-range SQN %i  lounge-margin %i "
-			          "lvld %i  at %d  Reinit in %d s", 
-			          orig_node->orig_str, ipStr(neigh), ogm_seqno, orig_node->path_lounge,
-			          orig_node->last_valid_sqn, orig_node->last_valid_time, 
+			          "lvld %i  at %d  dad_to %d  wavg %d  Reinit in %d s",
+			          orig_node->orig_str, ipStr(neigh), ogm_seqno, my_path_lounge,
+			          orig_node->last_valid_sqn, orig_node->last_valid_time,
+                                dad_to, WAVG(orig_node->ogi_wavg, OGI_WAVG_EXP),
 			          ((orig_node->last_valid_time + (1000 * dad_to)) - batman_time)/1000 );
 			
 			return FAILURE;
@@ -533,27 +660,8 @@
 		// remove old:
 		if ( orig_node->primary_orig_node != orig_node ) {
 			
-			/*
-			struct list_head *pos, *tmp;
-			struct list_head *prev = (struct list_head *)&orig_node->primary_orig->pog_referrer_list;
-			list_for_each_safe( pos, tmp, &orig_node->primary_orig->pog_referrer_list ) {
-				
-				struct pog_referrer_node *pog_referrer_node = list_entry( pos, struct pog_referrer_node, list );
-				
-				if ( pog_referrer_node->addr = orig_node->orig ) ) {
-					
-					list_del( prev, pos, &orig_node->primary_orig->pog_referrer_list );
-					
-					debugFree( pos, 1555 );
-					
-				} else {
-					prev = &pog_referrer_node->list;
-				}
-				
-			}
-			*/
 			orig_node->primary_orig_node->pog_refcnt--;
-			paranoia( -5000152, orig_node->pog_refcnt < 0 );
+			paranoia( -500152, orig_node->pog_refcnt < 0 );
 		}
 		
 		orig_node->primary_orig_node = NULL;
@@ -564,15 +672,8 @@
 		// add new:
 		
 		if ( orig_node->orig != new_primary_addr ) {
-			/*
-			struct pog_referrer_node *pog_referrer_node = debugMalloc( sizeof (struct pog_referrer_node), 555 );
-			memset( pog_referrer_node, 0, sizeof(struct pog_referrer_node) );
-			INIT_LIST_HEAD( &pog_referrer_node->list );
-			pog_referrer_node->addr = new_primary_addr;
-			list_add_tail( &pog_referrer_node->list, &orig_node->pog_referrer_list );
-			*/
-			orig_node->primary_orig_node = get_orig_node( new_primary_addr, YES/*create*/ );
-			
+
+                        orig_node->primary_orig_node = get_orig_node( new_primary_addr, YES/*create*/ );
 			orig_node->primary_orig_node->pog_refcnt++;
 			
 		} else {
@@ -585,8 +686,8 @@
 }
 
 
-static int8_t validate_primary_orig( struct orig_node *orig_node, struct msg_buff *mb, uint16_t oCtx ) {
-	//static int8_t validate_primary_orig( struct orig_node *orig_node, uint32_t primary_addr, SQ_TYPE primary_sqn, uint8_t is_direct ) {
+static
+int8_t validate_primary_orig( struct orig_node *orig_node, struct msg_buff *mb, uint16_t oCtx ) {
 	
 	if ( mb->rcv_ext_len[EXT_TYPE_64B_PIP] ) {
 		
@@ -667,11 +768,60 @@
 	return SUCCESS;
 }
 
+static
+void update_rtq_link(struct orig_node *orig_node_neigh, uint16_t oCtx, struct msg_buff *mb,
+        struct batman_if *iif, struct bat_packet_ogm *ogm, struct link_node_dev *lndev)
+{
 
+        dbgf_all(DBGT_INFO,
+                "received own OGM via NB, lastTxIfSeqno: %d, currRxSeqno: %d  oCtx: 0x%X "
+                "link_node %s primary_orig %s",
+                (iif->if_seqno - OUT_SEQNO_OFFSET), ogm->ogm_seqno, oCtx,
+                (orig_node_neigh->link_node ? "exist" : "NOT exists"),
+                (orig_node_neigh->primary_orig_node ? "exist" : "NOT exists"));
 
+        if (!(oCtx & HAS_DIRECTLINK_FLAG) || (oCtx & HAS_CLONED_FLAG) || iif->if_addr != ogm->orig)
+                return;
 
-static void update_link( struct orig_node *orig_node, SQ_TYPE sqn, struct batman_if *iif, uint16_t oCtx, uint8_t link_flags ) {
-	
+
+        if (((SQ_TYPE) ((iif->if_seqno - OUT_SEQNO_OFFSET) - ogm->ogm_seqno)) >  local_rtq_lounge ) {
+
+                dbg_mute(51, DBGL_CHANGES, DBGT_WARN,
+                        "late reception of own OGM via NB %s  lastTxIfSqn %d  rcvdSqn %d  margin %d ! "
+                        "Try configureing a greater --%s value .",
+                        mb->neigh_str, (iif->if_seqno - OUT_SEQNO_OFFSET),
+                        ogm->ogm_seqno, local_rtq_lounge, ARG_RTQ_LOUNGE);
+
+                return;
+        }
+
+        /* neighbour has to indicate direct link and it has to come via the corresponding interface */
+        /* if received seqno equals last send seqno save new seqno for bidirectional check */
+        if (orig_node_neigh->link_node && orig_node_neigh->primary_orig_node && lndev) {
+
+                update_lounged_metric(PROBE_RANGE, local_rtq_lounge, ogm->ogm_seqno, (iif->if_seqno - OUT_SEQNO_OFFSET),
+                        &lndev->rtq_sqr, local_lws);
+
+
+                if (orig_node_neigh->primary_orig_node->id4me != ogm->prev_hop_id) {
+
+                        if (orig_node_neigh->primary_orig_node->id4me != 0)
+                                dbg_mute(53, DBGL_CHANGES, DBGT_WARN,
+                                "received changed prev_hop_id from neighbor %s !!!",
+                                mb->neigh_str);
+
+                        orig_node_neigh->primary_orig_node->id4me = ogm->prev_hop_id;
+                }
+
+                dbgf_all(DBGT_INFO, "indicating bidirectional link");
+
+        }
+}
+
+
+static
+void update_rq_link( struct orig_node *orig_node, SQ_TYPE sqn, struct batman_if *iif, uint16_t oCtx ) {
+
 	if ( !( (oCtx & IS_DIRECT_NEIGH)  ||  orig_node->link_node ) )
 		return;
 	
@@ -682,32 +832,20 @@
 
 		if ( !orig_node->link_node )
 			init_link_node( orig_node );
-		
-		//check for changed link flags
-		if ( orig_node->link_node->link_flags != link_flags ) {
-			
-			dbg( DBGL_SYS, DBGT_INFO, "neighbor %s changed link flags from %X to %X", 
-			     orig_node->orig_str, orig_node->link_node->link_flags, link_flags );
-			
-			orig_node->link_node->link_flags = link_flags;
-		}
 	}
 	
 	
-	dbgf_all( DBGT_INFO, "OG %s  SQN %d  IF %s  ctx %x  link_flags %x  ln %s  cloned %s  direct %s", 
-	          orig_node->orig_str, sqn, iif->dev, oCtx, link_flags, 
+	dbgf_all( DBGT_INFO, "OG %s  SQN %d  IF %s  ctx %x  ln %s  cloned %s  direct %s", 
+	          orig_node->orig_str, sqn, iif->dev, oCtx, 
 	          orig_node->link_node ? "YES":"NO", 
 	          (oCtx & HAS_CLONED_FLAG) ? "YES":"NO",
 	          (oCtx & IS_DIRECT_NEIGH) ? "YES":"NO" );
 	
-	
-	
-	// skip updateing link_node if this SQN is known but not new
+
+        // skip updateing link_node if this SQN is known but not new
 	if ( ( orig_node->last_valid_time  ||  orig_node->last_valid_sqn )  &&
-	     ( (uint16_t)( sqn + my_link_lounge - orig_node->last_valid_sqn )  >  MAX_SEQNO - my_lws ) )
-	{
+	     ( (uint16_t)( sqn + RQ_LINK_LOUNGE - orig_node->last_valid_sqn )  >  MAX_SEQNO - local_lws - MAX_PATH_LOUNGE) )
 		return;
-	}
 	
 	paranoia( -500156, !orig_node->link_node );
 		
@@ -730,9 +868,7 @@
 			this_lndev = lndev;
 		
 		} else {
-			update_queued_metric( 0, my_link_lounge, sqn, &lndev->rq_sqr, my_lws,
-						orig_node->orig, orig_node->orig, lndev->bif, 
-						"update_link( other link )" );
+			update_lounged_metric( 0, RQ_LINK_LOUNGE, sqn, orig_node->last_valid_sqn, &lndev->rq_sqr, local_lws );
 			
 		}
 		
@@ -744,12 +880,12 @@
 	if ( this_lndev ) {
 		
 		uint8_t probe = ( (oCtx & IS_DIRECT_NEIGH) &&  !(oCtx & HAS_CLONED_FLAG) ) ? PROBE_RANGE : 0;
-		
-		update_queued_metric( probe, my_link_lounge, sqn, &this_lndev->rq_sqr, my_lws,
-		                      orig_node->orig, orig_node->orig, iif, 
-		                      "update_link( this link )" );
-		
-		this_lndev->last_lndev = batman_time;
+
+                update_lounged_metric(probe, RQ_LINK_LOUNGE, sqn, orig_node->last_valid_sqn, &this_lndev->rq_sqr, local_lws);
+
+                if ( probe)
+                        this_lndev->last_lndev = batman_time;
+                
 	}		
 	
 	//orig_node->link_node->last_rq_sqn = in_seqno;
@@ -769,12 +905,13 @@
 }
 
 
-static int tq_power( int tq_rate_value, int range ) {
+static
+int tq_power( int tq_rate_value, int range ) {
 	
 	int tq_power_value = range;
 	int exp_counter;
 	
-	for ( exp_counter = 0; exp_counter < asym_exp; exp_counter++ )
+	for ( exp_counter = 0; exp_counter < my_asym_exp; exp_counter++ )
 		tq_power_value = ((tq_power_value * tq_rate_value) / range);
 	
 	return tq_power_value;
@@ -782,83 +919,49 @@
 
 
 
-static uint8_t alreadyConsideredValid( struct orig_node *orig_node, SQ_TYPE seqno, uint32_t neigh, struct batman_if *iif ) {
+static
+int8_t validate_considered_order( struct orig_node *orig_node, SQ_TYPE seqno, uint32_t neigh, struct batman_if *iif ) {
+
+
+	struct neigh_node *nn;
+        struct neigh_node_key key = {neigh, iif};
+
+        if ( (nn = (struct neigh_node*)avl_find( &orig_node->neigh_avl, &key )) ) {
+
+                paranoia( -500198, (nn->nnkey_addr != neigh || nn->nnkey_iif != iif ) );
+
+                nn->last_aware = batman_time;
+
+                if (seqno == nn->last_considered_seqno) {
+
+                        return FAILURE;
+
+                } else if (((SQ_TYPE) (seqno - nn->last_considered_seqno)) > MAX_SEQNO - my_pws) {
+
+                        dbgf_ext(DBGT_WARN,
+                                "rcvd illegal SQN %d order from %s via %s %s (last considered sqn %d",
+                                seqno, orig_node->orig_str, ipStr(neigh), iif->dev,
+                                nn->last_considered_seqno);
+
+                        return FAILURE;
+                }
+
+                nn->last_considered_seqno = seqno;
+                return SUCCESS;
+        }
 	
-	struct list_head *neigh_pos;
-	struct neigh_node *neigh_node;
+	nn = init_neigh_node( orig_node, neigh, iif, seqno, batman_time );
 	
-	uint8_t spos = seqno % (SQN_LOUNGE_SIZE);
-	
-	list_for_each( neigh_pos, &orig_node->neigh_list ) {
-		
-		neigh_node = list_entry( neigh_pos, struct neigh_node, list );
-		
-		if ( neigh == neigh_node->addr && iif == neigh_node->iif ) {
-			
-			dbgf_ext( DBGT_INFO, 
-			          "OG %s  via IF %s  NB %s  SQN %d  spos %d  lastConsideredSQN %d  lounge_size %d",
-			          orig_node->orig_str, iif->dev, ipStr(neigh), 
-			          seqno, spos, neigh_node->last_considered_seqno, orig_node->path_lounge );
-			
-			neigh_node->last_aware = batman_time;
-			
-			if ( seqno == neigh_node->last_considered_seqno ) {
-				
-				if ( neigh_node->considered_seqnos & (0x01<<spos) )
-					return YES;
-				
-				neigh_node->considered_seqnos |= (0x01<<spos);
-				return NO;
-				
-			} else if ( ((SQ_TYPE)( seqno - neigh_node->last_considered_seqno )) >  MAX_SEQNO - orig_node->path_lounge ) {
-				
-				if ( neigh_node->considered_seqnos & (0x01<<spos) )
-					return YES;
-				
-				neigh_node->considered_seqnos |= (0x01<<spos);
-				return NO;
-				
-				
-			} else if ( ((SQ_TYPE)( seqno - neigh_node->last_considered_seqno )) <= orig_node->path_lounge ) {
-				// seqno == neigh_node->last_considered_seqno has already been catched above
-				
-				SQ_TYPE i;
-				
-				for( i = neigh_node->last_considered_seqno+1 ; i != ((SQ_TYPE)(seqno+1)); i++ )
-					neigh_node->considered_seqnos &= ~( 0x01 << (i%(SQN_LOUNGE_SIZE)) );
-				
-				neigh_node->considered_seqnos |= (0x01<<spos);
-				neigh_node->last_considered_seqno = seqno;
-				return NO;
-				
-			} else {
-				
-				neigh_node->considered_seqnos = (0x01<<spos);
-				neigh_node->last_considered_seqno = seqno;
-				return NO;
-				
-			}
-			
-		}
-		
-	}
-	
-	neigh_node = init_neigh_node( orig_node, neigh, iif, seqno, batman_time );
-	
-	neigh_node->considered_seqnos = (0x01<<spos);
-	neigh_node->last_considered_seqno = seqno;
-	return NO;
+	nn->last_considered_seqno = seqno;
+	return SUCCESS;
 }
 
 /* this function finds and may create an originator entry for the given address */
 struct orig_node *get_orig_node( uint32_t addr, uint8_t create ) {
 	
 	prof_start( PROF_get_orig_node );
-	struct orig_node *orig_node;
-	struct hashtable_t *swaphash;
-	
-	orig_node = ((struct orig_node *)hash_find( orig_hash, &addr ));
-	
+	struct orig_node *orig_node = ((struct orig_node *)avl_find( &orig_avl, &addr));
+
 	if ( !create ) {
 		prof_stop( PROF_get_orig_node );
 		return orig_node;
@@ -874,7 +977,8 @@
 	memset( orig_node, 0, (sizeof(struct orig_node) + (plugin_data_registries[PLUGIN_DATA_ORIG] * sizeof(void*) ) ) );
 	
 	INIT_LIST_HEAD_FIRST( orig_node->neigh_list );
-	//INIT_LIST_HEAD_FIRST( pog_referrer_list	);
+        AVL_INIT_TREE( orig_node->neigh_avl, sizeof( struct neigh_node_key ) );
+
 	
 	addr_to_str( addr, orig_node->orig_str );
 	dbgf_all( DBGT_INFO, "creating new originator: %s with %d plugin_data_registries", 
@@ -884,26 +988,23 @@
 	orig_node->last_aware = batman_time;
 	orig_node->router = NULL;
 	orig_node->link_node = NULL;
-	orig_node->path_lounge = Default_lounge;
-	
-	orig_node->ogi_wavg = 0;
-	orig_node->pws = my_pws;
-	
-	hash_add( orig_hash, orig_node );
-	
-	if ( orig_hash->elements * 4 > orig_hash->size ) {
-		
-		swaphash = hash_resize( orig_hash, orig_hash->size * 2 );
-		
-		if ( swaphash == NULL ) {
-			dbg( DBGL_SYS, DBGT_ERR, "couldn't resize hash table" );
-			cleanup_all( -500097 );
-		}
-		
-		orig_hash = swaphash;
-		
-	}
-	
+//	orig_node->path_lounge = my_path_lounge;
+        orig_node->pws = my_pws;
+//        orig_node->path_hystere = my_path_hystere;
+//        orig_node->late_penalty = my_late_penalty;
+//        orig_node->hop_penalty = my_hop_penalty;
+//        orig_node->asym_weight = my_asym_weight;
+//        orig_node->asym_exp = my_asym_exp;
+//        orig_node->rcnt_pws = my_rcnt_pws;
+//        orig_node->rcnt_lounge = my_rcnt_lounge;
+//        orig_node->rcnt_hystere = my_rcnt_hystere;
+//        orig_node->rcnt_fk = my_rcnt_fk;
+
+
+        upd_wavg(&orig_node->ogi_wavg, DEF_OGI, OGI_WAVG_EXP);
+
+        avl_insert( &orig_avl, /*(uint32_t*)*/orig_node);
+
 	cb_plugin_hooks( orig_node, PLUGIN_CB_ORIG_CREATE );
 	
 	prof_stop( PROF_get_orig_node );
@@ -914,26 +1015,28 @@
 void purge_orig( uint32_t curr_time, struct batman_if *bif ) {
 	
 	prof_start( PROF_purge_originator );
-	struct hash_it_t *hashit = NULL;
 	struct list_head *neigh_pos, *neigh_temp, *neigh_prev;
-	struct orig_node *orig_node;
+	struct orig_node *orig_node = NULL;
 	struct neigh_node *neigh_node;
 	static char neigh_str[ADDR_STR_LEN];
 	
 	dbgf_all( DBGT_INFO, "%d %s", curr_time, bif ? bif->dev : "???" );
 	
-	checkIntegrity();
+	//checkIntegrity();
 	
 	/* for all origins... */
-	while ( (hashit = hash_iterate( orig_hash, hashit )) ) {
+        uint32_t orig_ip = 0;
+
+        while ( (orig_node = (struct orig_node*)avl_next( &orig_avl, &orig_ip ) ) ) {
+
+                orig_ip = orig_node->orig;
+
+                dbgf_all( DBGT_INFO, "%d %s %s", curr_time, bif ? bif->dev : "???", orig_node->orig_str );
+
+
 		
-		orig_node = hashit->bucket->data;
-		
-		dbgf_all( DBGT_INFO, "%d %s %s", curr_time, bif ? bif->dev : "???", orig_node->orig_str );
-		
-		/* purge outdated originators completely */
-		
 		if ( !curr_time  ||  bif  ||  LESS_U32( orig_node->last_aware + (1000*((uint32_t)purge_to)), curr_time ) ) {
+                        /* purge outdated originators completely */
 			
 			dbgf_all( DBGT_INFO, "originator timeout: %s, last_valid %u, last_aware %u", 
 			          orig_node->orig_str, orig_node->last_valid_time, orig_node->last_aware );
@@ -952,9 +1055,10 @@
 				
 				neigh_node = list_entry( neigh_pos, struct neigh_node, list );
 				
-				if ( !bif  ||  ( neigh_node->iif == bif ) ) {
+				if ( !bif  ||  ( neigh_node->nnkey_iif == bif ) ) {
 					
 					list_del( neigh_prev, neigh_pos, &orig_node->neigh_list );
+                                        avl_remove( &orig_node->neigh_avl, neigh_node );
 					
 					debugFree( neigh_node, 1403 );
 					
@@ -979,7 +1083,7 @@
 				
 				set_primary_orig( orig_node, 0 );
 				
-				hash_remove_bucket( orig_hash, hashit );
+                                avl_remove( &orig_avl, /*(uint32_t*)*/orig_node);
 				
 				debugFree( orig_node, 1402 );
 			}
@@ -1044,12 +1148,14 @@
 				      orig_node->router != neigh_node  ) 
 				{
 					
-					addr_to_str( neigh_node->addr, neigh_str );
+					addr_to_str( neigh_node->nnkey_addr, neigh_str );
 					dbgf_all( DBGT_INFO, 
 					          "Neighbour timeout: originator %s, neighbour: %s, last_aware %u",
 					          orig_node->orig_str, neigh_str, neigh_node->last_aware );
 					
 					list_del( neigh_prev, neigh_pos, &orig_node->neigh_list );
+
+                                        avl_remove( &orig_node->neigh_avl, neigh_node );
 					
 					debugFree( neigh_node, 1403 );
 					
@@ -1062,9 +1168,8 @@
 		}
 	}
 	
-	checkIntegrity();
+	//checkIntegrity();
 	
-	
 	prof_stop( PROF_purge_originator );
 }
 
@@ -1198,193 +1303,136 @@
 	} 
 	
 	
-	//mb->orig_node_neigh = 
 	orig_node_neigh = get_orig_node( neigh, YES/*create*/ );
 	
 	
-	if ( orig_node_neigh->link_node )
-		lndev = get_lndev( orig_node_neigh->link_node, iif, NO/*create*/ );
-	
-	
-	if ( !( (oCtx & IS_DIRECT_NEIGH) || orig_node_neigh->last_valid_time ) ) {
-		
+	if ( !(oCtx & IS_DIRECT_NEIGH) && !(orig_node_neigh->last_valid_time) ) {
 		dbgf_all( DBGT_INFO, "drop OGM: rcvd via unknown neighbor!" );
 		goto process_ogm_end;
-	} 
+	}
+
+        if ((oCtx & HAS_CLONED_FLAG) && !orig_node_neigh->primary_orig_node) {
+                dbgf_all(DBGT_INFO, "drop OGM: first contact with neighbor MUST be without cloned flag!");
+		goto process_ogm_end;
+	}
+
+        if (orig_node_neigh->link_node)
+                lndev = get_lndev(orig_node_neigh->link_node, iif, NO/*create*/);
+
 	
-	
 	if ( oCtx & IS_MY_ORIG ) {
-		
-		dbgf_all( DBGT_INFO,
-		          "received own OGM via NB, lastTxIfSeqno: %d, currRxSeqno: %d, prevRxSeqno: %d, "
-		          "currRxSeqno-prevRxSeqno %d, link_node %s primary_orig %s",
-		          ( iif->if_seqno - OUT_SEQNO_OFFSET ), ogm->ogm_seqno, 0, 0, 
-		          (orig_node_neigh->link_node ? "exist":"NOT exists"),
-		          (orig_node_neigh->primary_orig_node ? "exist":"NOT exists") );
-		
-		if ( !(oCtx & HAS_DIRECTLINK_FLAG)  ||  iif->if_addr != ogm->orig )
-			goto process_ogm_end;
-		
-		
-		if ( ((SQ_TYPE)(( iif->if_seqno - OUT_SEQNO_OFFSET ) - ogm->ogm_seqno )) > my_link_lounge ) {
-			
-			dbg_mute( 51, DBGL_CHANGES, DBGT_WARN,
-			          "late reception of own OGM via NB %s  lastTxIfSqn %d  rcvdSqn %d  margin %d",
-			          mb->neigh_str, ( iif->if_seqno - OUT_SEQNO_OFFSET ), 
-			          ogm->ogm_seqno, my_link_lounge  );
-			
-			goto process_ogm_end;
-		}
-		
-		/* neighbour has to indicate direct link and it has to come via the corresponding interface */
-		/* if received seqno equals last send seqno save new seqno for bidirectional check */
-		if ( !(oCtx & HAS_CLONED_FLAG)  &&
-		     orig_node_neigh->link_node  &&
-		     orig_node_neigh->primary_orig_node && 
-		     lndev  )
-		{
-			
-			update_queued_metric( PROBE_RANGE, my_link_lounge, ogm->ogm_seqno,
-			                      &lndev->rtq_sqr, my_lws,
-			                      ogm->orig, orig_node_neigh->orig, iif, "process_ogm(own via NB)" );
-			
-			
-			if ( orig_node_neigh->primary_orig_node->id4me != ogm->prev_hop_id ) {
-				
-				if( orig_node_neigh->primary_orig_node->id4me != 0 ) 
-					dbg_mute( 53, DBGL_CHANGES, DBGT_WARN, 
-					          "received changed prev_hop_id from neighbor %s !!!",
-					          mb->neigh_str );
-				
-				orig_node_neigh->primary_orig_node->id4me = ogm->prev_hop_id;
-			}
-			
-			dbgf_all( DBGT_INFO, "indicating bidirectional link");
-			
-		} else {
-			
-			dbgf_all( DBGT_WARN, "NOT indicating bidirectional link" );
-			
-		}
-		
+                update_rtq_link(orig_node_neigh, oCtx, mb, iif, ogm, lndev);
 		goto process_ogm_end;
 	} 
-	
-	
-	/* drop packet if sender is not a direct NB and if we have no route towards the rebroadcasting NB */
-	if ( !(oCtx & IS_DIRECT_NEIGH)  &&  orig_node_neigh->router == NULL  ) {
-		
-		dbgf_all( DBGT_INFO, "drop OGM: via unknown (non-direct) neighbor!" );
+
+        if ( ogm->ogm_ttl == 0 ) {
+		dbgf_all( DBGT_INFO, "drop OGM: TTL of zero!" );
 		goto process_ogm_end;
-	} 
+	}
+
 	
+        if ( lndev  &&  lndev->rtq_sqr.wa_val > 0 )
+		oCtx |= IS_BIDIRECTIONAL;
+
 	
-	if ( !(oCtx & IS_DIRECT_NEIGH)  &&  ( orig_node_neigh->primary_orig_node == NULL ||
-	                                      orig_node_neigh->primary_orig_node->id4me == 0 ||
-	                                      orig_node_neigh->primary_orig_node->id4me == ogm->prev_hop_id ) ) 
-	{
-		
-		dbgf_all( DBGT_INFO, "drop OGM: %s via NB %s %s !!!!",
-		          ipStr( ogm->orig ), mb->neigh_str, 
-		          ( ( orig_node_neigh->primary_orig_node == NULL ||
-		              orig_node_neigh->primary_orig_node->id4me == 0 ) ? 
-		            "with unknown primaryOG" :" via two-hop loop " ) );
-		
-		goto process_ogm_end;
-	} 
+	// drop packet if sender is not a direct NB and if we have no route towards the rebroadcasting NB
+        if (!(oCtx & IS_DIRECT_NEIGH) && !(orig_node_neigh->router)) {
+                dbgf_all(DBGT_INFO, "drop OGM: via unknown (non-direct) neighbor!");
+                goto process_ogm_end;
+        }
 	
+
+        if (!(oCtx & IS_DIRECT_NEIGH)) {
+
+                if (!orig_node_neigh->primary_orig_node || !orig_node_neigh->primary_orig_node->id4me) {
+
+                        dbgf_all(DBGT_INFO, "drop OGM: %s via NB %s %s !!!!",
+                                ipStr(ogm->orig), mb->neigh_str, "with unknown primaryOG");
+                        goto process_ogm_end;
+                }
+
+                if (drop_2hop_loop &&
+                        orig_node_neigh->primary_orig_node &&
+                        orig_node_neigh->primary_orig_node->id4me == ogm->prev_hop_id) {
+
+                        dbgf_all(DBGT_INFO, "drop OGM: %s via NB %s %s !!!!",
+                                ipStr(ogm->orig), mb->neigh_str, " via two-hop loop ");
+                        goto process_ogm_end;
+                }
+        }
 	
-	if ( ogm->ogm_ttl == 0 ) {
-		
-		dbgf_all( DBGT_INFO, "drop OGM: TTL of zero!" );
-		goto process_ogm_end;
-	}
 	
 	mb->orig_node = orig_node = 
 		(oCtx & IS_DIRECT_NEIGH) ? orig_node_neigh : get_orig_node( ogm->orig, YES/*create*/ );
-	
-	if ( validate_orig_seqno( orig_node, neigh, ogm->ogm_seqno ) == FAILURE ) {
-		//dbg_mute( 25, DBGL_CHANGES, DBGT_WARN, "drop OGM: %15s, via NB %15s, with seqno %i\n",
-		//     ipStr( ogm->orig ), mb->neigh_str, ogm->ogm_seqno );
-		goto process_ogm_end;
+
+
+        if (validate_orig_seqno(orig_node, neigh, ogm->ogm_seqno) == FAILURE) {
+                dbgf_all( DBGT_WARN, "drop OGM: %15s, via NB %15s, SQN %i\n",
+                        ipStr(ogm->orig), mb->neigh_str, ogm->ogm_seqno);
+                goto process_ogm_end;
 	}
-	
-	
-	if ( (oCtx & HAS_CLONED_FLAG) && orig_node_neigh->primary_orig_node == NULL ) {
 		
-		dbgf_all( DBGT_INFO, "drop OGM: first contact with neighbor MUST be without cloned flag!" );
-		goto process_ogm_end;
-	} 
 	
-	
 	if ( validate_primary_orig( orig_node, mb, oCtx ) == FAILURE ) {
-		
 		dbg( DBGL_SYS, DBGT_WARN, "drop OGM: primary originator/if conflict!" );
 		goto process_ogm_end;
 	}
 	
 	
-	if ( alreadyConsideredValid( orig_node, ogm->ogm_seqno, neigh, iif ) ) {
-		
+	if ( validate_considered_order( orig_node, ogm->ogm_seqno, neigh, iif ) == FAILURE ) {
 		dbgf_all( DBGT_INFO, "drop OGM: already considered this OGM and SEQNO via this link neighbor!" );
 		goto process_ogm_end;
 	}
 	
 	
-	// OK! OGM seems valid..
-	oCtx |= IS_VALID;
-	
 	uint16_t rand_100 = rand_num( 100 );
 	
 	addr_to_str( ogm->orig, mb->orig_str );
+		
 	
-	//MUST be after validate_primary_orig()
-	update_link( orig_node, ogm->ogm_seqno, iif, oCtx, mb->link_flags );
 	
-	
-	if ( orig_node_neigh->link_node  &&  lndev  &&  lndev->rtq_sqr.wa_val > 0 )
-		oCtx |= IS_BIDIRECTIONAL;
-	
-	
 	if ( ((SQ_TYPE)( orig_node->last_valid_sqn - ogm->ogm_seqno )) >= orig_node->pws ) {
 		
 		// we've never seen a valid sqn of this size before, therefore:
 		// everything which is out of our current path-window is new!
-		oCtx |= IS_NEW; 
+		oCtx |= IS_NEW;
+
+                // estimating average originaotr interval of this node
+                if (orig_node->last_valid_time && LESS_U32(orig_node->last_valid_time, batman_time)) {
+
+                        if (((SQ_TYPE) (ogm->ogm_seqno - (orig_node->last_wavg_sqn + 1))) < orig_node->pws) {
+                                upd_wavg(&orig_node->ogi_wavg,
+                                        ((batman_time - orig_node->last_valid_time) /
+                                        (ogm->ogm_seqno - orig_node->last_wavg_sqn)),
+                                        OGI_WAVG_EXP);
+                        }
+
+                        orig_node->last_wavg_sqn = ogm->ogm_seqno;
+                }
+
+		orig_node->last_valid_sqn = ogm->ogm_seqno;
+		orig_node->last_valid_time = batman_time;
+
+	} else if ( ((SQ_TYPE)( orig_node->last_valid_sqn - ogm->ogm_seqno )) <= my_path_lounge ) {
 		
-	} else if ( ((SQ_TYPE)( orig_node->last_valid_sqn - ogm->ogm_seqno )) <= orig_node->path_lounge ) {
-		
 		// everything else which is still within SQN_ENTRY_QUEUE is acceptable
 		oCtx |= IS_ACCEPTABLE;
-		
 	}
 	
 	
-	if ( oCtx & IS_NEW ) {
-		
-		// estimating average originaotr interval of this node
-		if ( ((SQ_TYPE)( ogm->ogm_seqno - orig_node->last_valid_sqn+1 )) < orig_node->pws  &&
-		     orig_node->last_valid_time  &&  LESS_U32( orig_node->last_valid_time, batman_time ) )
-		{
-			upd_wavg( &orig_node->ogi_wavg,
-			          ( (batman_time - orig_node->last_valid_time) / 
-			            (ogm->ogm_seqno - orig_node->last_valid_sqn)),
-			          OGI_WAVG_EXP );
-		}
-		
-		orig_node->last_valid_sqn = ogm->ogm_seqno;
-		orig_node->last_valid_time = batman_time;
-		
-	}
+        //MUST be after validate_primary_orig()
+	update_rq_link( orig_node, ogm->ogm_seqno, iif, oCtx );
+
+
 	
-	
 	int tq_rate_value = tq_rate( orig_node_neigh, iif, PROBE_RANGE );
 	
 	
 	if ( (oCtx & IS_BIDIRECTIONAL)  &&  
 	     ((oCtx & IS_NEW) || (oCtx & IS_ACCEPTABLE))  &&
+             rand_100  >=  my_hop_penalty  &&
 //	     rand_100  <=  (MAX_ASYM_WEIGHT - asym_weight)  +  ( (tq_power(tq_rate_value,PROBE_RANGE)/PROBE_TO100) * 99) / 100    ) 
-	     rand_100  <=  (MAX_ASYM_WEIGHT - asym_weight)  +  ( (tq_power(tq_rate_value,PROBE_RANGE)/PROBE_TO100) ) )
+	     rand_100  <=  (MAX_ASYM_WEIGHT - my_asym_weight)  +  ( (tq_power(tq_rate_value,PROBE_RANGE)/PROBE_TO100) ) )
 	{
 		
 		// finally we only accept OGMs with probability TQ of its incoming link
@@ -1395,20 +1443,25 @@
 	
 	struct neigh_node *old_router = orig_node->router;
 	
-	struct neigh_node *new_router = update_orig( orig_node, orig_node_neigh, &oCtx, mb );
+	struct neigh_node *new_router = update_orig( orig_node, &oCtx, mb );
 	
 	
 	if ( old_router != new_router )
 		update_routes( orig_node, new_router );
 	
-	if ( new_router != orig_node->router ) {
+	if ( !new_router || new_router != orig_node->router ) {
 		
-		dbgf( DBGL_SYS, DBGT_ERR, 
-		      "new_router %s for %s differs from installed router %s",
-		      ipStr( new_router ? new_router->addr : 0 ),
+		dbgf_all( DBGT_INFO, //as long as incoming link is not bidirectional,...
+		      "new_rt %s for %s is zero or differs from installed rt %s  "
+                        "(old_rt %s  rcvd vi %s %s",
+		      ipStr( new_router ? new_router->nnkey_addr : 0 ),
 		      orig_node->orig_str,
-		      ipStr( orig_node->router ? orig_node->router->addr : 0 ) );
+		      ipStr( orig_node->router ? orig_node->router->nnkey_addr : 0 ),
+		      ipStr( old_router ? old_router->nnkey_addr : 0 ), mb->neigh_str, mb->iif->dev );
 	}
+
+        // new_router can be zero !!!
+        //paranoia( -500195, ( !new_router || new_router != orig_node->router ) );
 	
 	// check if ogm_hooks would reject new_router
 	if ( cb_ogm_hooks( mb, oCtx, old_router ) != CB_OGM_ACCEPT ) {
@@ -1420,14 +1473,14 @@
 	
 	dbgf_all( DBGT_INFO,
 	          "done OGM accepted %s  acceptable %s  bidirectLink %s  new %s  BNTOG %s  asocial %s  tq %d  "
-	          "asym_w %d  acceptSQN %d  rcvdSQN %d  rand100 %d", 
+	          "hop_penalty %d  asym_w %d  acceptSQN %d  rcvdSQN %d  rand100 %d",
 	          ( oCtx & IS_ACCEPTED   ? "Y" : "N" ), 
 	          ( oCtx & IS_ACCEPTABLE ? "Y" : "N" ), 
 	          ( oCtx & IS_BIDIRECTIONAL ? "Y" : "N" ), 
 	          ( oCtx & IS_NEW ? "Y" : "N" ), 
 	          ( oCtx & IS_BEST_NEIGH_AND_NOT_BROADCASTED ? "Y" : "N" ), 
 	          ( oCtx & IS_ASOCIAL ? "Y" : "N" ), 
-	          tq_rate_value, asym_weight, orig_node->last_accepted_sqn, ogm->ogm_seqno, rand_100 );
+	          tq_rate_value, my_hop_penalty, my_asym_weight, orig_node->last_accepted_sqn, ogm->ogm_seqno, rand_100 );
 	
 	
 	// either it IS_DIRECT_NEIGH, then validate_primary_orig() with orig_node=orig_neigh_node has been called
@@ -1436,7 +1489,10 @@
 	
 	//paranoia( -5000151, (!orig_node_neigh->primary_orig_node->id4him) );	
 	if ( !orig_node_neigh->primary_orig_node->id4him ) {
-		dbgf( DBGL_SYS, DBGT_WARN, "invalid id4him");
+
+                dbgf( DBGL_SYS, DBGT_WARN, "invalid id4him for orig %s via %s",
+                        orig_node->orig_str, mb->neigh_str );
+
 		goto process_ogm_end;
 	}
 	
@@ -1452,9 +1508,9 @@
 
 
 
-static int32_t opt_show_origs ( uint8_t cmd, uint8_t _save, struct opt_type *opt, struct opt_parent *patch, struct ctrl_node *cn ) {
+static
+int32_t opt_show_origs ( uint8_t cmd, uint8_t _save, struct opt_type *opt, struct opt_parent *patch, struct ctrl_node *cn ) {
 	
-	struct hash_it_t *hashit = NULL;
 	struct orig_node *orig_node;
 	uint16_t batman_count = 0;
 	
@@ -1465,113 +1521,123 @@
 		
 		if ( !strcmp( opt->long_name, ARG_ORIGINATORS ) ) {
 			
-			int nodes_count = 0, sum_packet_count = 0, sum_rcvd_all_bits = 0;
-			int sum_lvld = 0, sum_last_pws = 0, sum_last_pls = 0, sum_ogi_avg = 0;
+			int nodes_count = 0, sum_packet_count = 0, sum_recent_count = 0;
+			int sum_lvld = 0, sum_last_pws = 0, sum_ogi_avg = 0;
 			int sum_reserved_something = 0, sum_route_changes = 0, sum_hops = 0;
 			
 			
-			dbg_printf( cn, "Originator      outgoingIF     bestNextHop brc "
-			            "(~rcvd  knownSince  lseq lvld pws pls ~ogi misc hop change )\n");
-			
-			while ( (hashit = hash_iterate( orig_hash, hashit )) ) {
-				
-				orig_node = hashit->bucket->data;
-				
+			dbg_printf( cn, "Originator      outgoingIF bestNextHop      TQ(rcnt) "
+			            "knownSince lsqn(diff) lvld pws ~ogi cpu hop\n");
+                        uint32_t orig_ip = 0;
+
+                        while ((orig_node = (struct orig_node*) avl_next(&orig_avl, &orig_ip))) {
+
+                                orig_ip = orig_node->orig;
+
 				if ( !orig_node->router  ||  orig_node->primary_orig_node != orig_node )
 					continue;
+
+                                /*
+                                struct orig_node *onn = get_orig_node( orig_node->router->addr, NO );
+
+                                if ( !onn  ||  !onn->last_valid_time  ||  !onn->router )
+                                        continue;
+                                 */
+/*
+				int estimated_rcvd = (( (100 * orig_node->router->accepted_sqr.wa_val)/PROBE_TO100 )+99) /
+					(((tq_power( tq_rate( onn, onn->router->iif, PROBE_RANGE ), PROBE_RANGE ) )/PROBE_TO100)+1);
+*/
 				
-				struct orig_node *onn = get_orig_node( orig_node->router->addr, NO/*create*/ );
-				
-				if ( !onn  ||  !onn->last_valid_time  ||  !onn->router )
-					continue;
-				
 				nodes_count++;
 				batman_count++;
 				
-				int estimated_rcvd = (( (100 * orig_node->router->accepted_sqr.wa_val)/PROBE_TO100 )+99) / 
-					(((tq_power( tq_rate( onn, onn->router->iif, PROBE_RANGE ), PROBE_RANGE ) )/PROBE_TO100)+1);
 				
-				dbg_printf( cn, "%-15s %-10s %15s %3i (  %3i %s %5i %4i %3i %3i %4i %4i %3i %6i )\n", 
-				            orig_node->orig_str, orig_node->router->iif->dev, 
-				            ipStr( orig_node->router->addr ),
-				            orig_node->router->accepted_sqr.wa_val/PROBE_TO100,
-				            estimated_rcvd > 100 ? 100 : estimated_rcvd,
+				dbg_printf( cn, "%-15s %-10s %-15s %3i %3i  %s %5i %3i %5i %3i %4i %3i %3i\n",
+				            orig_node->orig_str, orig_node->router->nnkey_iif->dev,
+				            ipStr( orig_node->router->nnkey_addr ),
+				            orig_node->router->longtm_sqr.wa_val/PROBE_TO100,
+				            orig_node->router->recent_sqr.wa_val/PROBE_TO100,
+//				            estimated_rcvd > 100 ? 100 : estimated_rcvd,
 				            get_human_uptime( orig_node->first_valid_sec ),
 				            orig_node->last_valid_sqn,
+                                            orig_node->router->longtm_sqr.wa_clr_sqn - orig_node->last_valid_sqn,
 				            ( batman_time - orig_node->last_valid_time)/1000,
 				            orig_node->pws,
-				            orig_node->path_lounge,
-				            get_wavg( orig_node->ogi_wavg, OGI_WAVG_EXP ),
+				            WAVG( orig_node->ogi_wavg, OGI_WAVG_EXP ),
 				            orig_node->ogm_misc,
-				            (Ttl+1 - orig_node->last_path_ttl),
-				            orig_node->rt_changes
+				            (Ttl+1 - orig_node->last_path_ttl)
 				          ); 
 				
-				sum_packet_count+= orig_node->router->accepted_sqr.wa_val/PROBE_TO100; /* accepted */
-				sum_rcvd_all_bits+= MIN( estimated_rcvd, 100 ); 
+				sum_packet_count+= orig_node->router->longtm_sqr.wa_val/PROBE_TO100; /* accepted */
+				sum_recent_count+= orig_node->router->recent_sqr.wa_val/PROBE_TO100; /* accepted */
+//				sum_rcvd_all_bits+= MIN( estimated_rcvd, 100 );
 				sum_lvld+= (batman_time - orig_node->last_valid_time)/1000;
 				sum_last_pws+= orig_node->pws;
-				sum_last_pls+=orig_node->path_lounge;
-				sum_ogi_avg+= get_wavg( orig_node->ogi_wavg, OGI_WAVG_EXP );
+				sum_ogi_avg+= WAVG( orig_node->ogi_wavg, OGI_WAVG_EXP );
 				sum_reserved_something+= orig_node->ogm_misc;
 				sum_route_changes+= orig_node->rt_changes;
 				sum_hops+= (Ttl+1 - orig_node->last_path_ttl);
 			}
 			
-			dbg_printf( cn, "%4d %-37s %3i (  %3i                   %4i %3i %3i %4i %4i %3i %6d )\n", 
+			dbg_printf( cn, "%8d %-33s %3i %3i                        %5i %3i %4i %3i %3i\n",
 			            nodes_count, "known Originator(s), averages: ", 
 			            (nodes_count > 0 ? ( sum_packet_count / nodes_count ) : -1 ), 
-			            (nodes_count > 0 ? ( sum_rcvd_all_bits / nodes_count ) : -1 ), 
+			            (nodes_count > 0 ? ( sum_recent_count / nodes_count ) : -1 ),
+//			            (nodes_count > 0 ? ( sum_rcvd_all_bits / nodes_count ) : -1 ),
 			            (nodes_count > 0 ? ( sum_lvld / nodes_count ) : -1),
 			            (nodes_count > 0 ? ( sum_last_pws / nodes_count ) : -1 ), 
-			            (nodes_count > 0 ? ( sum_last_pls / nodes_count ) : -1 ), 
 			            (nodes_count > 0 ? ( sum_ogi_avg / nodes_count ) : -1), 
 			            (nodes_count > 0 ? ( sum_reserved_something / nodes_count ) : -1),
-			            (nodes_count > 0 ? ( sum_hops / nodes_count ) : -1),
-			            (nodes_count > 0 ? ( sum_route_changes / nodes_count ) : -1)      ); 
+			            (nodes_count > 0 ? ( sum_hops / nodes_count ) : -1) );
 			
 		
 		} else if ( !strcmp( opt->long_name, ARG_STATUS ) ) {
 			
-			dbg_printf( cn, "BatMan-eXp %s%s, "
-			            "%s %s, LWS %i, PWS %i, OGI %4ims, SQN %5d, "
-			            "UT %s, CPU %2d.%1d\n",
+			dbg_printf( cn, "BMX %s%s, "
+			            "%s, LWS %i, PWS %i, OGI %4ims, "
+			            "UT %s, CPU %d.%1d\n",
 			            SOURCE_VERSION, 
 			            ( strncmp( REVISION_VERSION, "0", 1 ) != 0 ? REVISION_VERSION : "" ),
-			            primary_if ? primary_if->dev : "--",
 			            ipStr( primary_addr ),
-			            my_lws, my_pws, my_ogi, 
-			            primary_if ? primary_if->if_seqno : 0,
+			            local_lws, my_pws, my_ogi,
 			            get_human_uptime( 0 ),
 			            s_curr_avg_cpu_load/10, s_curr_avg_cpu_load%10
 			          );
 			
 		} else if ( !strcmp( opt->long_name, ARG_LINKS ) ) {
 			
+			
+			dbg_printf( cn, "Neighbor        viaIF      Originator      RTQ  RQ  TQ     "
+			            "  lseq lvld rid nid\n");
+
+                        uint32_t orig_ip = 0;
+                        struct link_node * ln;
+                        
+                        while ((ln = (struct link_node*) avl_next(&link_avl, &orig_ip))) {
+
+                                orig_ip = ln->orig_addr;
+
+/*
 			struct list_head *link_pos;
-			
-			dbg_printf( cn, "Neighbor        outgoingIF     bestNextHop brc "
-			            "(~rcvd  knownSince  lseq lvld rid nid ) [     viaIF RTQ  RQ  TQ]\n");
-			
 			list_for_each( link_pos, &link_list ) {
 				
 				struct link_node *ln = list_entry(link_pos, struct link_node, list);
-				
+*/
+
+
 				orig_node = ln->orig_node;
 				
 				if ( !orig_node->router )
 					continue;
 				
-				struct orig_node *onn = get_orig_node( orig_node->router->addr, NO/*create*/ );
+/*
+				struct orig_node *onn = get_orig_node( orig_node->router->addr, NO );
 				
 				if ( !onn  ||  !onn->last_valid_time  ||  !onn->router )
 					continue;
+*/
 				
-				int estimated_rcvd = (( (100 * orig_node->router->accepted_sqr.wa_val)/PROBE_TO100 )+99) / 
-					(((tq_power( tq_rate( onn, onn->router->iif, PROBE_RANGE ), PROBE_RANGE ) )/PROBE_TO100)+1);
 				
-				
-				
 				struct list_head *lndev_pos;
 				
 				list_for_each( lndev_pos, &ln->lndev_list ) {
@@ -1582,22 +1648,22 @@
 					tq = tq_rate( orig_node, lndev->bif, PROBE_RANGE );
 					rtq = lndev->rtq_sqr.wa_val;
 					
-					dbg_printf( cn, "%-15s %-10s %15s %3i (  %3i %s %5i %4i %3d %3d ) "
-					            "[%10s %3i %3i %3i] \n",
-					            orig_node->orig_str, orig_node->router->iif->dev, 
-					            ipStr( orig_node->router->addr ),
-						 // accepted and rebroadcasted:
-					            orig_node->router->accepted_sqr.wa_val/PROBE_TO100,
-					            estimated_rcvd > 100 ? 100 : estimated_rcvd,
-					            get_human_uptime( orig_node->first_valid_sec ),
+					dbg_printf( cn, "%-15s %-10s %-15s %3i %3i %3i      %5i %4i %3d %3d\n",
+					            orig_node->orig_str, lndev->bif->dev,
+					            orig_node->primary_orig_node ? orig_node->primary_orig_node->orig_str : "???",
+					            rtq/PROBE_TO100, rq/PROBE_TO100, tq/PROBE_TO100,
+                                                //  accepted and rebroadcasted:
+                                                //  orig_node->router->accepted_sqr.wa_val/PROBE_TO100,
+                                                //  estimated_rcvd > 100 ? 100 : estimated_rcvd,
+                                                //  get_human_uptime( orig_node->first_valid_sec ),
 					            orig_node->last_valid_sqn,
-					            ( batman_time - orig_node->last_valid_time)/1000,
+//					            ( batman_time - orig_node->last_valid_time)/1000,
+					            ( batman_time - lndev->last_lndev)/1000,
 					            ( orig_node->primary_orig_node ?
 					              orig_node->primary_orig_node->id4me : -1 ),
 					            ( orig_node->primary_orig_node ?
-					              orig_node->primary_orig_node->id4him : -1 ),
-					            lndev->bif->dev, 
-					            rtq/PROBE_TO100, rq/PROBE_TO100, tq/PROBE_TO100  ); 
+					              orig_node->primary_orig_node->id4him : -1 )
+                                                );
 					
 				}
 				
@@ -1615,35 +1681,38 @@
 			            ipStr( primary_addr ),
 			            get_human_uptime( 0 ) );
 			
-			
-			while ( (hashit = hash_iterate( orig_hash, hashit )) ) {
-				
-				orig_node = hashit->bucket->data;
-				
+                        uint32_t orig_ip = 0;
+
+                        while ((orig_node = (struct orig_node*) avl_next(&orig_avl, &orig_ip))) {
+
+                                orig_ip = orig_node->orig;
+
 				if ( !orig_node->router  ||  orig_node->primary_orig_node != orig_node )
 					continue;
 				
-				struct orig_node *onn = get_orig_node( orig_node->router->addr, NO/*create*/ );
+/*
+				struct orig_node *onn = get_orig_node( orig_node->router->addr, NO );
 				
 				if ( !onn  ||  !onn->last_valid_time  ||  !onn->router )
 					continue;
+*/
 				
 				dbg_ogm_out = snprintf( dbg_ogm_str, MAX_DBG_STR_SIZE, "%-15s (%3i) %15s [%10s] ", 
 				                        orig_node->orig_str, 
-				                        orig_node->router->accepted_sqr.wa_val/PROBE_TO100, 
-				                        ipStr( orig_node->router->addr ), 
-				                        orig_node->router->iif->dev );
+				                        orig_node->router->longtm_sqr.wa_val/PROBE_TO100,
+				                        ipStr( orig_node->router->nnkey_addr ),
+				                        orig_node->router->nnkey_iif->dev );
 				
 				list_for_each( neigh_pos, &orig_node->neigh_list ) {
 					neigh_node = list_entry( neigh_pos, struct neigh_node, list );
 					
-					if( neigh_node->addr != orig_node->router->addr ) {
+					if( neigh_node->nnkey_addr != orig_node->router->nnkey_addr ) {
 						
 						dbg_ogm_out = dbg_ogm_out + 
 							snprintf( (dbg_ogm_str + dbg_ogm_out), (MAX_DBG_STR_SIZE - dbg_ogm_out), 
 							          " %15s (%3i)", 
-							          ipStr( neigh_node->addr ), 
-							          neigh_node->accepted_sqr.wa_val/PROBE_TO100 );
+							          ipStr( neigh_node->nnkey_addr ),
+							          neigh_node->longtm_sqr.wa_val/PROBE_TO100 );
 						
 					}
 				}
@@ -1663,7 +1732,8 @@
 
 
 
-static int32_t opt_dev_show ( uint8_t cmd, uint8_t _save, struct opt_type *opt, struct opt_parent *patch, struct ctrl_node *cn ) {
+static
+int32_t opt_dev_show ( uint8_t cmd, uint8_t _save, struct opt_type *opt, struct opt_parent *patch, struct ctrl_node *cn ) {
 	
 	struct list_head *pos;
 	
@@ -1672,9 +1742,10 @@
 		list_for_each( pos, &if_list ) {
 			
 			struct batman_if *bif = list_entry( pos, struct batman_if, list );
-			
-			dbg_cn( cn, DBGL_ALL, DBGT_NONE, "%-10s %8s %15s/%-2d  brc %-15s  SQN %5d  TTL %2d  %11s  %8s  %11s", 
+
+			dbg_cn( cn, DBGL_ALL, DBGT_NONE, "%-10s %5d %8s %15s/%-2d  brc %-15s  SQN %5d  TTL %2d  %11s  %8s  %11s",
 			        bif->dev,
+                                bif->if_index,
 			        !bif->if_active ? "-" : 
 			        ( bif->if_linklayer == VAL_DEV_LL_LO ? "loopback": 
 			          ( bif->if_linklayer == VAL_DEV_LL_LAN ? "ethernet": 
@@ -1683,7 +1754,7 @@
 			        bif->if_prefix_length,
 			        ipStr(bif->if_broad),
 			        bif->if_seqno,
-			        bif->own_ogm_out ? bif->own_ogm_out->ogm_ttl : -1,
+			        bif->if_ttl,
 			        bif->if_singlehomed ? "singlehomed" : "multihomed",
 			        bif->if_active ? "active" : "inactive",
 			        bif == primary_if ? "primary" : "non-primary"
@@ -1694,7 +1765,8 @@
 	return SUCCESS;
 }
 
-static int32_t opt_dev ( uint8_t cmd, uint8_t _save, struct opt_type *opt, struct opt_parent *patch, struct ctrl_node *cn ) {
+static
+int32_t opt_dev ( uint8_t cmd, uint8_t _save, struct opt_type *opt, struct opt_parent *patch, struct ctrl_node *cn ) {
 	
 	struct list_head *list_pos, *list_tmp, *list_prev;
 	struct batman_if *bif = NULL;
@@ -1741,9 +1813,9 @@
 				remove_outstanding_ogms( bif );
 				
 				list_del( list_prev, list_pos, &if_list );
+
+                                debugFree(bif, 1214);
 				
-				debugFree( list_pos, 1214 );
-				
 				return SUCCESS;
 				
 				
@@ -1756,18 +1828,27 @@
 		
 		if ( !bif ) {
 			
-			if ( cmd == OPT_APPLY )
-				bif = debugMalloc( sizeof(struct batman_if), 206 );
-			else 
+			if ( cmd == OPT_APPLY ) {
+
+                                bif = debugMalloc( sizeof(struct batman_if), 206 );
+                                memset(bif, 0, sizeof (struct batman_if));
+
+                                INIT_LIST_HEAD(&bif->list);
+
+                                if ( list_empty( &if_list ) )
+					primary_if = bif;
+
+				list_add_tail( &bif->list, &if_list );
+
+                        } else {
+
 				bif = &test_bif;
-			
-			
-			memset( bif, 0, sizeof(struct batman_if) );
-			INIT_LIST_HEAD( &bif->list );
-			
-			bif->own_send_node = (struct send_node*)&(bif->own_send_buff[0]);
-			bif->own_ogm_out = (struct bat_packet_ogm*)&(bif->own_send_node->ogm_buff[0]);
-			
+                                memset(bif, 0, sizeof (struct batman_if));
+
+                        }
+                        
+                        bif->aggregation_out = bif->aggregation_out_buff;
+
 			snprintf( bif->dev, wordlen(patch->p_val)+1, "%s", patch->p_val );
 			snprintf( bif->dev_phy, wordlen(patch->p_val)+1, "%s", patch->p_val );
 			
@@ -1779,13 +1860,8 @@
 			
 			bif->if_seqno_schedule = batman_time;
 			
-			bif->own_ogm_out->ext_msg = NO;
-			bif->own_ogm_out->bat_type = BAT_TYPE_OGM;
+                        bif->if_seqno = (primary_if && primary_if != bif) ? primary_if->if_seqno : my_seqno;
 			
-			bif->own_ogm_out->ogx_flag = NO;
-			
-			bif->if_seqno   = primary_if ? primary_if->if_seqno : my_seqno;
-			
 			bif->aggregation_len = sizeof( struct bat_header );
 			
 			
@@ -1795,16 +1871,7 @@
 			bif->if_ant_diversity_conf = -1;
 			bif->if_linklayer_conf = -1;
 			bif->if_singlehomed_conf = -1;
-			
-			
-			if ( cmd == OPT_APPLY ) {
-				
-				if ( list_empty( &if_list ) )
-					primary_if = bif;
-				
-				list_add_tail( &bif->list, &if_list );
-			}
-			
+						
 		}
 		
 		if ( cmd == OPT_CHECK )
@@ -1846,12 +1913,11 @@
 	} else if ( cmd == OPT_POST  &&  opt  &&  !opt->parent_name ) {
 		
 		check_interfaces(); //will always be called whenever a parameter is changed (due to OPT_POST)
-		
+		/*
 		if ( !on_the_fly ) {
 			
 			// add rule for hosts and announced interfaces and networks
 			if ( prio_rules ) { 
-				add_del_rule( 0, 0, RT_TABLE_INTERFACES, RT_PRIO_INTERFACES, 0, RTA_DST, ADD, TRACK_STANDARD );
 				add_del_rule( 0, 0, RT_TABLE_HOSTS,      RT_PRIO_HOSTS,      0, RTA_DST, ADD, TRACK_STANDARD );
 				add_del_rule( 0, 0, RT_TABLE_NETWORKS,   RT_PRIO_NETWORKS,   0, RTA_DST, ADD, TRACK_STANDARD );
 			}
@@ -1861,6 +1927,7 @@
 				cleanup_all( CLEANUP_FAILURE );
 			
 		}
+		*/
 	}
 	
 	return SUCCESS;
@@ -1944,7 +2011,8 @@
 		
 	{ODI,5,0,ARG_DEV,		0,  A_PMN,A_ADM,A_DYI,A_CFA,A_ANY,	0,		0, 		0,		0, 		opt_dev,
 			"<interface-name>", "add or change device or its configuration, options for specified device are:"},
-		
+
+#ifndef LESS_OPTIONS
 	{ODI,5,ARG_DEV,ARG_DEV_TTL,	't',A_CS1,A_ADM,A_DYI,A_CFA,A_ANY,	0,		MIN_TTL,	MAX_TTL,	DEF_TTL,	opt_dev,
 			ARG_VALUE_FORM,	"set TTL of generated OGMs"},
 		
@@ -1961,61 +2029,87 @@
 			ARG_VALUE_FORM,	0/*"set number of broadcast antennas (e.g. for antenna-diversity use /d=2 /c=400 aggreg_interval=100)"*/},
 		
 		
+	{ODI,5,ARG_DEV,ARG_DEV_HIDE,	'h',A_CS1,A_ADM,A_DYI,A_CFA,A_ANY,	0,		0,		1,		0,		opt_dev,
+			ARG_VALUE_FORM,	"disable/enable hiding of OGMs generated to non link-neighboring nodes. Default for non-primary interfaces"},
+#endif
+
 	{ODI,5,ARG_DEV,ARG_DEV_LL,	'l',A_CS1,A_ADM,A_DYI,A_CFA,A_ANY,	0,		VAL_DEV_LL_LAN,	VAL_DEV_LL_WLAN,0,		opt_dev,
 			ARG_VALUE_FORM,	"manually set device type for linklayer specific optimization (1=lan, 2=wlan)"},
 		
-	{ODI,5,ARG_DEV,ARG_DEV_HIDE,	'h',A_CS1,A_ADM,A_DYI,A_CFA,A_ANY,	0,		0,		1,		0,		opt_dev,
-			ARG_VALUE_FORM,	"disable/enable hiding of OGMs generated to non link-neighboring nodes. Default for non-primary interfaces"},
-		
 	{ODI,5,0,ARG_INTERFACES,	0,  A_PS0,A_USR,A_DYI,A_ARG,A_ANY,	0,		0,		1,		0,		opt_dev_show,
 			0,		"show configured interfaces"},
 		
-	{ODI,5,0,ARG_OGI_INTERVAL, 	'o',A_PS1,A_ADM,A_DYI,A_CFA,A_ANY,	&my_ogi,	MIN_OGI,	MAX_OGI,	DEF_OGI,	0,
-			ARG_VALUE_FORM,	"set interval in ms with which new originator message (OGM) are send"},
-		
-	{ODI,5,0,"path_window_size",	0,  A_PS1,A_ADM,A_DYI,A_CFA,A_ANY,	&my_pws,	MIN_PWS, 	MAX_PWS,	DEF_PWS,	opt_if_soft,
+	{ODI,5,0,ARG_LWS,       	0,  A_PS1,A_ADM,A_DYI,A_CFA,A_ANY,	&local_lws,	MIN_LWS, 	MAX_LWS,	DEF_LWS,	opt_lws,
+			ARG_VALUE_FORM,	"set link window size (LWS) for link-quality calculation (link metric)"},
+
+#ifndef LESS_OPTIONS
+
+	{ODI,5,0,ARG_RTQ_LOUNGE, 	0,  A_PS1,A_ADM,A_DYI,A_CFA,A_ANY,	&local_rtq_lounge,MIN_RTQ_LOUNGE,MAX_RTQ_LOUNGE,DEF_RTQ_LOUNGE, opt_lws,
+			ARG_VALUE_FORM, "set local LLS buffer size to artificially delay OGM processing for ordered link-quality calulation"},
+
+	{ODI,5,0,ARG_PWS,       	0,  A_PS1,A_ADM,A_DYI,A_CFA,A_ANY,	&my_pws,	MIN_PWS, 	MAX_PWS,	DEF_PWS,	opt_if_soft,
 			ARG_VALUE_FORM,	"set path window size (PWS) for end2end path-quality calculation (path metric)"},
-		
-	{ODI,5,0,"link_window_size",	0,  A_PS1,A_ADM,A_DYI,A_CFA,A_ANY,	&my_lws,	MIN_LWS, 	MAX_LWS,	DEF_LWS,	opt_lws,
-			ARG_VALUE_FORM,	"set link window size (LWS) for link-quality calculation (link metric)"},
-	
-	{ODI,5,0,"path_hysteresis",	0,  A_PS1,A_ADM,A_DYI,A_CFA,A_ANY,	&path_hystere,	MIN_PATH_HYST, 	MAX_PATH_HYST,	DEF_PATH_HYST,	0,
+
+	{ODI,5,0,ARG_PATH_LOUNGE,	0,  A_PS1,A_ADM,A_DYI,A_CFA,A_ANY,	&my_path_lounge,MIN_PATH_LOUNGE,MAX_PATH_LOUNGE,DEF_PATH_LOUNGE,opt_purge,
+			ARG_VALUE_FORM, "set default PLS buffer size to artificially delay my OGM processing for ordered path-quality calulation"},
+
+	{ODI,5,0,ARG_PATH_HYST, 	0,  A_PS1,A_ADM,A_DYI,A_CFA,A_ANY,	&my_path_hystere,MIN_PATH_HYST,	MAX_PATH_HYST,	DEF_PATH_HYST,	opt_purge,
 			ARG_VALUE_FORM,	"use hysteresis to delay route switching to alternative next-hop neighbors with better path metric"},
-		
-	{ODI,5,0,"purge_timeout", 	0,  A_PS1,A_ADM,A_DYI,A_CFA,A_ANY,	&purge_to,	MIN_PURGE_TO,	MAX_PURGE_TO,	DEF_PURGE_TO,	0,
+
+
+	{ODI,5,0,ARG_RCNT_PWS,	        0,  A_PS1,A_ADM,A_DYI,A_CFA,A_ANY,	&my_rcnt_pws,   MIN_RCNT_PWS,   MAX_RCNT_PWS,   DEF_RCNT_PWS,   opt_purge,
+			ARG_VALUE_FORM, ""},
+
+/*
+	{ODI,5,0,ARG_RCNT_LOUNGE,       0,  A_PS1,A_ADM,A_DYI,A_CFA,A_ANY,	&my_rcnt_lounge,MIN_RCNT_LOUNGE,MAX_RCNT_LOUNGE,DEF_RCNT_LOUNGE,opt_purge,
+			ARG_VALUE_FORM, ""},
+*/
+
+	{ODI,5,0,ARG_RCNT_HYST, 	0,  A_PS1,A_ADM,A_DYI,A_CFA,A_ANY,	&my_rcnt_hystere,MIN_RCNT_HYST,	MAX_RCNT_HYST,	DEF_RCNT_HYST,	opt_purge,
+			ARG_VALUE_FORM,	"use hysteresis to delay fast-route switching to alternative next-hop neighbors with a recently extremely better path metric"},
+
+	{ODI,5,0,ARG_RCNT_FK,	        0,  A_PS1,A_ADM,A_DYI,A_CFA,A_ANY,	&my_rcnt_fk,    MIN_RCNT_FK,    MAX_RCNT_FK,    DEF_RCNT_FK,    opt_purge,
+			ARG_VALUE_FORM,	"configure threshold faktor for dead-path detection"},
+
+
+	{ODI,5,0,ARG_DROP_2HLOOP,	0,  A_PS1,A_ADM,A_DYI,A_CFA,A_ANY,	&drop_2hop_loop,MIN_DROP_2HLOOP,MAX_DROP_2HLOOP,DEF_DROP_2HLOOP,0,
+			ARG_VALUE_FORM,	"drop OGMs received via two-hop loops"},
+
+
+	{ODI,5,0,ARG_ASYM_EXP,		0,  A_PS1,A_ADM,A_DYI,A_CFA,A_ANY,	&my_asym_exp,	MIN_ASYM_EXP,	MAX_ASYM_EXP,	DEF_ASYM_EXP,	0,
+			ARG_VALUE_FORM,	"ignore OGMs (rcvd via asymmetric links) with TQ^<val> to radically reflect asymmetric-links"},
+
+	{ODI,5,0,"asocial_device",	0,  A_PS1,A_ADM,A_DYI,A_CFA,A_ANY,	&Asocial_device,MIN_ASOCIAL,	MAX_ASOCIAL,	DEF_ASOCIAL,	0,
+			ARG_VALUE_FORM,	"disable/enable asocial mode for devices unwilling to forward other nodes' traffic"},
+
+	{ODI,5,0,ARG_WL_CLONES,		0,  A_PS1,A_ADM,A_DYI,A_CFA,A_ANY,	&wl_clones,	MIN_WL_CLONES,	MAX_WL_CLONES,	DEF_WL_CLONES,	opt_if_soft,
+			ARG_VALUE_FORM,	"broadcast OGMs per ogm-interval for wireless devices with\n"
+			"	given probability [%] (eg 200% will broadcast the same OGM twice)"},
+
+	{ODI,5,0,ARG_ASYM_WEIGHT,	0,  A_PS1,A_ADM,A_DYI,A_CFA,A_ANY,	&my_asym_weight,	MIN_ASYM_WEIGHT,MAX_ASYM_WEIGHT,DEF_ASYM_WEIGHT,0,
+			ARG_VALUE_FORM,	"ignore OGMs (rcvd via asymmetric links) with given probability [%] to better reflect asymmetric-links"},
+
+	{ODI,5,0,ARG_HOP_PENALTY,	0,  A_PS1,A_ADM,A_DYI,A_CFA,A_ANY,	&my_hop_penalty,	MIN_HOP_PENALTY,MAX_HOP_PENALTY,DEF_HOP_PENALTY,0,
+			ARG_VALUE_FORM,	"ignore OGMs with given probability [%] to better reflect path-hop distance"},
+
+                        // there SHOULD! be a minimal lateness_penalty >= 1 ! Otherwise a shorter path with equal path-cost than a longer path will never dominate
+	{ODI,5,0,ARG_LATE_PENAL,	0,  A_PS1,A_ADM,A_DYI,A_CFA,A_ANY,	&my_late_penalty,MIN_LATE_PENAL,MAX_LATE_PENAL, DEF_LATE_PENAL, opt_purge,
+			ARG_VALUE_FORM,	"penalize non-first rcvd OGMs "},
+
+	{ODI,5,0,ARG_PURGE_TO,  	0,  A_PS1,A_ADM,A_DYI,A_CFA,A_ANY,	&purge_to,	MIN_PURGE_TO,	MAX_PURGE_TO,	DEF_PURGE_TO,	0,
 			ARG_VALUE_FORM,	"timeout in seconds for purging stale originators"},
-	
-	{ODI,5,0,"dad_timeout", 	0,  A_PS1,A_ADM,A_DYI,A_CFA,A_ANY,	&dad_to,	MIN_DAD_TO,	MAX_DAD_TO,	DEF_DAD_TO,	0,
+
+#endif
+	{ODI,5,0,ARG_DAD_TO,    	0,  A_PS1,A_ADM,A_DYI,A_CFA,A_ANY,	&dad_to,	MIN_DAD_TO,	MAX_DAD_TO,	DEF_DAD_TO,	0,
 			ARG_VALUE_FORM,	"duplicate address (DAD) detection timout in seconds"},
-		
+
 	{ODI,5,0,"seqno", 		0,  A_PS1,A_ADM,A_DYI,A_CFA,A_ANY,	&my_seqno,	MIN_SEQNO,	MAX_SEQNO,	DEF_SEQNO,	opt_seqno,0,0},
-		
-	{ODI,5,0,ARG_WL_CLONES,		0,  A_PS1,A_ADM,A_DYI,A_CFA,A_ANY,	&wl_clones,	0,		400,		200,		opt_if_soft,
-			ARG_VALUE_FORM,	"broadcast OGMs per ogm-interval for wireless devices with\n"
-			"	given probability [%] (eg 200% will broadcast the same OGM twice)"},
-		
-	{ODI,5,0,ARG_ASYM_WEIGHT,	0,  A_PS1,A_ADM,A_DYI,A_CFA,A_ANY,	&asym_weight,	MIN_ASYM_WEIGHT,MAX_ASYM_WEIGHT,DEF_ASYM_WEIGHT,0,
-			ARG_VALUE_FORM,	"ignore OGMs (rcvd via asymmetric links) with given probability [%] to better reflect asymmetric-links"},
-		
-	{ODI,5,0,"lateness_penalty",	0,  A_PS1,A_ADM,A_DYI,A_CFA,A_ANY,	&lateness_penalty,0,		100,		2		,0,
-			ARG_VALUE_FORM,	"penalize non-firsr rcvd OGMs "},
-		
-	{ODI,5,0,"link_lounge_size", 	0,  A_PS1,A_ADM,A_DYI,A_CFA,A_ANY,	&my_link_lounge,MIN_LOUNGE_SIZE,3,		1,		0,
-			ARG_VALUE_FORM, "set local LLS buffer size to artificially delay OGM processing for ordered link-quality calulation"},
-		
-	{ODI,5,0,"path_lounge_size", 	0,  A_PS1,A_ADM,A_DYI,A_CFA,A_ANY,	&Default_lounge,MIN_LOUNGE_SIZE,MAX_LOUNGE_SIZE,1,		0,
-			ARG_VALUE_FORM, "set default PLS buffer size to artificially delay OGM processing for ordered path-quality calulation"},
-		
+
+
 	{ODI,5,0,"ttl",			't',A_PS1,A_ADM,A_DYI,A_CFA,A_ANY,	&Ttl,		MIN_TTL,	MAX_TTL,	DEF_TTL,	opt_if_soft,
 			ARG_VALUE_FORM,	"set time-to-live (TTL) for OGMs of primary interface"},
 		
-	{ODI,5,0,ARG_ASYM_EXP,		0,  A_PS1,A_ADM,A_DYI,A_CFA,A_ANY,	&asym_exp,	MIN_ASYM_EXP,	MAX_ASYM_EXP,	DEF_ASYM_EXP,	0,
-			ARG_VALUE_FORM,	"ignore OGMs (rcvd via asymmetric links) with TQ^<val> to radically reflect asymmetric-links"},
 		
-	{ODI,5,0,"asocial_device",	0,  A_PS1,A_ADM,A_DYI,A_CFA,A_ANY,	&Asocial_device,NO,		YES,		NO,		0,
-			ARG_VALUE_FORM,	"disable/enable asocial mode for devices unwilling to forward other nodes' traffic"},
-		
-		
 	{ODI,5,0,"flush_all",		0,  A_PS0,A_ADM,A_DYN,A_ARG,A_ANY,	0,		0, 		0,		0, 		opt_purge,
 			0,		"purge all neighbors and routes on the fly"}
 };

Modified: trunk/batman-experimental/originator.h
===================================================================
--- trunk/batman-experimental/originator.h	2010-04-12 19:06:37 UTC (rev 1633)
+++ trunk/batman-experimental/originator.h	2010-04-15 08:16:16 UTC (rev 1634)
@@ -17,60 +17,108 @@
  *
  */
 
+#define WA_SCALE_FACTOR 1000	/* scale factor used to increase precision of integer division */
+#define PROBE_TO100	1
+#define PROBE_RANGE	100
 
+
 #define MIN_SEQNO 0
 #define DEF_SEQNO 0 /* causes seqno to be randomized */
 #define MAX_SEQNO ((uint16_t)-1)
 
 
-extern int32_t my_pws; // my path window size used to quantify the end to end path quality between me and other nodes
 #define MAX_PWS 250      /* TBD: should not be larger until ogm->ws and neigh_node.packet_count (and related variables) is only 8 bit */
-#define MIN_PWS 1
+#define MIN_PWS 10
 #define DEF_PWS 100  /* NBRF: NeighBor Ranking sequence Frame) sliding packet range of received orginator messages in squence numbers (should be a multiple of our word size) */
+#define ARG_PWS "path_window_size"
+extern int32_t my_pws; // my path window size used to quantify the end to end path quality between me and other nodes
 
-extern int32_t my_lws; // my link window size used to quantify the link qualities to direct neighbors
-#define DEF_LWS 100
+
+#define DEF_LWS 20
 #define MAX_LWS 250
 #define MIN_LWS 1
+#define ARG_LWS "link_window_size"
+extern int32_t local_lws; // my link window size used to quantify the link qualities to direct neighbors
 
-#define ARG_OGI_INTERVAL "ogm_interval"
-extern int32_t my_ogi; // my originator interval
-#define DEF_OGI 1000
-#define MIN_OGI 200
-#define MAX_OGI 10000 
 
-extern int32_t my_link_lounge;
-extern int32_t Default_lounge;
+// the default link_lounge_size of 2 is good to compensate for ogi ~ but <= aggreg_interval
+#define MIN_RTQ_LOUNGE 0
+#define MAX_RTQ_LOUNGE 10
+#define DEF_RTQ_LOUNGE 2
+#define ARG_RTQ_LOUNGE "link_lounge_size"
+extern int32_t local_rtq_lounge;
 
-#define MIN_LOUNGE_SIZE 0
-#define MAX_LOUNGE_SIZE (SQN_LOUNGE_SIZE-1)
+#define RQ_LINK_LOUNGE 0  /* may also be rtq_link_lounge */
 
 
-//#define PURGE_SAFETY_PERIOD 25000 //25000
-//#define PURGE_TIMEOUT ((MAX_OGI*MAX_PWS) + PURGE_SAFETY_PERIOD) /* 10 minutes + safety_period */ 
-//extern int32_t purge_to
-#define DEF_PURGE_TO  100000
+#define MIN_PATH_LOUNGE 0
+#define MAX_PATH_LOUNGE (SQN_LOUNGE_SIZE-1)
+#define DEF_PATH_LOUNGE 8
+#define ARG_PATH_LOUNGE "path_lounge_size"
+extern int32_t my_path_lounge;
+
+
+#define MIN_PATH_HYST	0
+#define MAX_PATH_HYST	(PROBE_RANGE/PROBE_TO100)/2
+#define DEF_PATH_HYST	0
+#define ARG_PATH_HYST   "path_hysteresis"
+
+#define MIN_RCNT_HYST	0
+#define MAX_RCNT_HYST	(PROBE_RANGE/PROBE_TO100)/2
+#define DEF_RCNT_HYST	1
+#define ARG_RCNT_HYST   "fast_path_hysteresis"
+
+#define DEF_RCNT_PWS 20
+#define MIN_RCNT_PWS 2
+#define MAX_RCNT_PWS MAX_PWS
+#define ARG_RCNT_PWS "fast_path_window_size"
+
+#define DEF_RCNT_LOUNGE DEF_PATH_LOUNGE
+#define MIN_RCNT_LOUNGE MIN_PATH_LOUNGE
+#define MAX_RCNT_LOUNGE MAX_PATH_LOUNGE
+#define ARG_RCNT_LOUNGE "fast_path_lounge_size"
+
+#define DEF_RCNT_FK 150
+#define MIN_RCNT_FK 100
+#define MAX_RCNT_FK 1000
+#define ARG_RCNT_FK "fast_path_faktor"
+
+#define MIN_LATE_PENAL 0
+#define MAX_LATE_PENAL 100
+#define DEF_LATE_PENAL 1
+#define ARG_LATE_PENAL "lateness_penalty"
+
+#define MIN_DROP_2HLOOP NO
+#define MAX_DROP_2HLOOP YES
+#define DEF_DROP_2HLOOP NO
+#define ARG_DROP_2HLOOP "drop_two_hop_loops"
+
+#define DEF_PURGE_TO  100
 #define MIN_PURGE_TO  10
 #define MAX_PURGE_TO  864000 /*10 days*/
+#define ARG_PURGE_TO  "purge_timeout"
+// extern int32_t purge_to;
 
-//extern int32_t dad_to;
 #define DEF_DAD_TO 100
 #define MIN_DAD_TO 1
 #define MAX_DAD_TO 3600
-//#define DEF_DAD_TO 100
-//#define MIN_DAD_TO 10 /* if this is changed, be careful with PURGE_TIMEOUT */
-//#define MAX_DAD_TO (PURGE_TIMEOUT/2)
+#define ARG_DAD_TO "dad_timeout"
+extern int32_t dad_to;
 
-extern int32_t Ttl;
+#define MIN_ASOCIAL NO
+#define MAX_ASOCIAL YES
+#define DEF_ASOCIAL NO
+
 #define DEF_TTL 50                /* Time To Live of OGM broadcast messages */
 #define MAX_TTL 63
 #define MIN_TTL 1
+extern int32_t Ttl;
 
-#define ARG_WL_CLONES   "ogm_broadcasts"
-extern int32_t wl_clones;
 #define DEF_WL_CLONES 200
 #define MIN_WL_CLONES 0
 #define MAX_WL_CLONES 400
+#define ARG_WL_CLONES   "ogm_broadcasts"
+extern int32_t wl_clones;
 
 #define DEF_LAN_CLONES 100
 
@@ -80,30 +128,31 @@
 #define MAX_ASYM_WEIGHT	100
 #define ARG_ASYM_WEIGHT	"asymmetric_weight"
 
+#define DEF_HOP_PENALTY 1
+#define MIN_HOP_PENALTY 0
+#define MAX_HOP_PENALTY 100
+#define ARG_HOP_PENALTY "hop_penalty"
+
+
 #define DEF_ASYM_EXP	1
 #define MIN_ASYM_EXP	0
 #define MAX_ASYM_EXP	3
 #define ARG_ASYM_EXP	"asymmetric_exp"
 
 
-#define WA_SCALE_FACTOR 1000	/* scale factor used to increase precision of integer division */
-#define PROBE_TO100	1
-#define PROBE_RANGE	100
-
-#define MIN_PATH_HYST	0
-#define MAX_PATH_HYST	(PROBE_RANGE/PROBE_TO100)/2
-#define DEF_PATH_HYST	0
-
-
 extern struct batman_if *primary_if;
 extern uint32_t primary_addr;
 
 
-extern struct hashtable_t *orig_hash;
+//extern struct hashtable_t *orig_hash;
+extern struct avl_tree orig_avl;
+
 extern struct list_head_first if_list;
 
 extern struct list_head_first link_list;
+extern struct avl_tree link_avl;
 
+
 struct orig_node *get_orig_node( uint32_t addr, uint8_t create );
 
 int tq_rate( struct orig_node *orig_node_neigh, struct batman_if *iif, int range );

Modified: trunk/batman-experimental/os.h
===================================================================
--- trunk/batman-experimental/os.h	2010-04-12 19:06:37 UTC (rev 1633)
+++ trunk/batman-experimental/os.h	2010-04-15 08:16:16 UTC (rev 1634)
@@ -21,14 +21,6 @@
 #define _BATMAN_OS_H
 
 
-/* get_time functions MUST be called at least every 2*MAX_SELECT_TIMEOUT_MS to allow for properly working time-drift checks */
-
-/* overlaps after approximately 138 years */
-//#define get_time_sec()  get_time( NO, NULL  ) 
-
-/* overlaps after 49 days, 17 hours, 2 minutes, and 48 seconds */
-//#define get_time_msec() get_time( YES, NULL ) 
-
 # define timercpy(d, a) (d)->tv_sec = (a)->tv_sec; (d)->tv_usec = (a)->tv_usec; 
 
 
@@ -51,6 +43,20 @@
 
 void cleanup_all( int status );
 
+/*
+ * PARANOIA ERROR CODES:
+ * Negative numbers are used as SIGSEV error codes !
+ * Currently used numbers are
+ * for core programs:		-500000 ... -500198
+ */
+#ifdef NOPARANOIA
+#define paranoia( ... )
+#else
+#define paranoia( code , problem ); do { if ( problem ) { cleanup_all( code ); } }while(0)
+#endif
+
+
+
 void update_batman_time( struct timeval *precise_tv );
 
 char *get_human_uptime( uint32_t reference );
@@ -95,9 +101,8 @@
  *
  * Things you should leave as is unless your know what you are doing !
  *
- * RT_TABLE_INTERFACES	routing table for announced (non-primary) interfaces IPs and other unique IP addresses
- * RT_TABLE_NETWORKS	routing table for announced networks
  * RT_TABLE_HOSTS	routing table for routes towards originators
+ * RT_TABLE_NETWORKS	routing table for announced networks
  * RT_TABLE_TUNNEL	routing table for the tunnel towards the internet gateway
  * RT_PRIO_DEFAULT	standard priority for routing rules
  * RT_PRIO_UNREACH	standard priority for unreachable rules
@@ -105,82 +110,41 @@
  *
  ***/
 
+#define RT_TABLE_HOSTS      -1
+#define RT_TABLE_NETWORKS   -2
+#define RT_TABLE_TUNNEL     -3
 
 
-extern int32_t Rt_table;
-#define ARG_RT_TABLE "rt_table_offset"
-#define DEF_RT_TABLE 64
-#define MIN_RT_TABLE 2
-#define MAX_RT_TABLE 240
 
-#define RT_TABLE_INTERFACES (Rt_table + 0)
-#define RT_TABLE_NETWORKS   (Rt_table + 1)
-#define RT_TABLE_HOSTS      (Rt_table + 2)
-#define RT_TABLE_TUNNEL     (Rt_table + 4)
-
-
-extern int32_t Rt_prio;
-#define ARG_RT_PRIO "prio_rules_offset"
-#define MIN_RT_PRIO 3
-#define MAX_RT_PRIO 32765
-#define DEF_RT_PRIO 6500
-
-#define RT_PRIO_INTERFACES (Rt_prio + 0  )
-#define RT_PRIO_HOSTS      (Rt_prio + 100)
-#define RT_PRIO_NETWORKS   (Rt_prio + 199)
-#define RT_PRIO_TUNNEL     (Rt_prio + 300)
-
-
-extern int32_t prio_rules;
-#define ARG_PRIO_RULES "prio_rules"
-
-
-#define ARG_THROW_RULES "throw_rules"
-
-#define ARG_NO_POLICY_RT "no_policy_routing"
-
-#define ARG_PEDANTIC_CLEANUP "pedantic_cleanup"
-
-
-
 extern uint8_t if_conf_soft_changed; // temporary enabled to trigger changed interface configuration
 extern uint8_t if_conf_hard_changed; // temporary enabled to trigger changed interface configuration
 
 extern int Mtu_min;
 
 
-struct rules_node {
+struct routes_node {
 	struct list_head list;
-	uint32_t network;
-	uint8_t netmask;
-	uint8_t rt_table;
-	uint32_t prio;
-	char *iif;
-	int8_t rule_t;
+	uint32_t dest;
+	uint16_t netmask;
+	uint16_t rt_table;
+	int16_t rta_type;
 	int8_t track_t;
 };
 
- 
-struct routes_node {
+
+struct rules_node {
 	struct list_head list;
-	uint32_t dest;
-	uint8_t netmask;
-	uint8_t rt_table;
-	int8_t route_t;
+	uint32_t prio;
+	char *iif;
+	uint32_t network;
+	int16_t netmask;
+	int16_t rt_table;
+	int16_t rta_type;
 	int8_t track_t;
 };
 
 
-/***
- *
- * route types: 0 = RTN_UNICAST, 1 = THROW, 2 = UNREACHABLE
- *
- ***/
-#define RT_UNICAST	0
-#define RT_THROW 	1
-#define RT_UNREACH	2
 
-
 //track types:
 enum {
 	TRACK_NO,
@@ -192,7 +156,8 @@
 	TRACK_TUNNEL
 };
 
-void add_del_route( uint32_t dest, uint8_t netmask, uint32_t router, uint32_t source, int32_t ifi, char *dev, uint8_t rt_table, int8_t route_type, int8_t del, int8_t track );
+void add_del_route( uint32_t dest, int16_t mask, uint32_t gw, uint32_t src, int32_t ifi, char *dev,
+                    int16_t rt_table_macro, int16_t rta_type, int8_t del, int8_t track_t );
 
 /***
  *
@@ -203,7 +168,7 @@
  *
  ***/
  
-void add_del_rule( uint32_t network, uint8_t netmask, uint8_t rt_table, uint32_t prio, char *iif, int8_t rule_type, int8_t del, int8_t track );
+// void add_del_rule( uint32_t network, uint8_t netmask, int16_t rt_macro, uint32_t prio, char *iif, int8_t rule_type, int8_t del, int8_t track_t );
 
 enum {
  IF_RULE_SET_TUNNEL,
@@ -245,167 +210,6 @@
 #define ARG_GW_CLASS "gateway_class"
 
 #ifndef	NOTUNNEL
-
-
-#define ARG_UNRESP_GW_CHK "unresp_gateway_check"
-
-#define ARG_TWO_WAY_TUNNEL "two_way_tunnel"
-
-#define ARG_ONE_WAY_TUNNEL "one_way_tunnel"
-
-#define ARG_GW_HYSTERESIS "gateway_hysteresis"
-#define MIN_GW_HYSTERE    1
-#define MAX_GW_HYSTERE    PROBE_RANGE/PROBE_TO100
-#define DEF_GW_HYSTERE    2
-
-
-#define BATMAN_TUN_PREFIX "bat"
-#define MAX_BATMAN_TUN_INDEX 20 
-
-#define TUNNEL_DATA 0x01
-#define TUNNEL_IP_REQUEST 0x02
-#define TUNNEL_IP_INVALID 0x03
-#define TUNNEL_IP_REPLY 0x06
-
-#define GW_STATE_UNKNOWN  0x01
-#define GW_STATE_VERIFIED 0x02
-
-#define ONE_MINUTE                60000
-
-#define GW_STATE_UNKNOWN_TIMEOUT  (1  * ONE_MINUTE)
-#define GW_STATE_VERIFIED_TIMEOUT (5  * ONE_MINUTE)
-
-#define IP_LEASE_TIMEOUT          (1 * ONE_MINUTE)
-
-#define MAX_TUNNEL_IP_REQUESTS 60 //12
-#define TUNNEL_IP_REQUEST_TIMEOUT 1000 // msec
-
-	
-struct tun_request_type {
-	uint32_t lease_ip;
-	uint16_t lease_lt;
-} __attribute__((packed));
-
-struct tun_data_type {
-	unsigned char ip_packet[MAX_MTU];
-} __attribute__((packed));
-
-struct tun_packet_start {
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-	unsigned int type:4;
-	unsigned int version:4;  // should be the first field in the packet in network byte order
-#elif __BYTE_ORDER == __BIG_ENDIAN
-	unsigned int version:4;
-	unsigned int type:4;
-#else
-# error "Please fix <bits/endian.h>"
-#endif
-} __attribute__((packed));
-
-struct tun_packet
-{
-	uint8_t  reserved1;
-	uint8_t  reserved2;
-	uint8_t  reserved3;
-
-	struct tun_packet_start start;
-#define TP_TYPE  start.type
-#define TP_VERS  start.version	
-
-	union
-	{
-		struct tun_request_type trt;
-		struct tun_data_type tdt;
-	}tt;
-#define LEASE_IP  tt.trt.lease_ip
-#define LEASE_LT  tt.trt.lease_lt
-#define IP_PACKET tt.tdt.ip_packet
-} __attribute__((packed));
-
-
-#define TX_RP_SIZE (sizeof(struct tun_packet_start) + sizeof(struct tun_request_type))
-#define TX_DP_SIZE (sizeof(struct tun_packet_start) + sizeof(struct tun_data_type))
-
-
-struct gwc_args {
-	uint32_t gw_state_stamp;
-	uint8_t gw_state;
-	uint8_t prev_gw_state;
-	uint32_t orig;
-	struct gw_node *gw_node;	// pointer to gw node
-	struct sockaddr_in gw_addr;	// gateway ip
-	char  gw_str[ADDR_STR_LEN];	// string of gateway ip
-	struct sockaddr_in my_addr; 	// primary_ip
-	uint32_t my_tun_addr;		// ip used for bat0 tunnel interface
-	char  my_tun_str[ADDR_STR_LEN];	// string of my_tun_addr
-	int32_t mtu_min;
-	uint8_t tunnel_type;
-	int32_t udp_sock;
-	int32_t tun_fd;
-	int32_t tun_ifi;
-	char tun_dev[IFNAMSIZ];		// was tun_if
-	uint32_t tun_ip_request_stamp;
-	uint32_t tun_ip_lease_stamp;
-	uint32_t tun_ip_lease_duration;
-	uint32_t send_tun_ip_requests;
-	uint32_t pref_addr;
-	//	uint32_t last_invalidip_warning;
-};
-
-
-struct gws_args
-{
-	int8_t netmask;
-	int32_t port;
-	int32_t owt;
-	int32_t twt;
-	int32_t lease_time;
-	int mtu_min;
-	uint32_t my_tun_ip;
-	uint32_t my_tun_netmask;
-	uint32_t my_tun_ip_h;
-	uint32_t my_tun_suffix_mask_h;
-	struct sockaddr_in  client_addr;
-	struct gw_client **gw_client_list;
-	int32_t sock;
-	int32_t tun_fd;
-	int32_t tun_ifi;
-	char tun_dev[IFNAMSIZ];
-};
-
-
-#define DEF_GWTUN_NETW_PREFIX  "169.254.0.0" /* 0x0000FEA9 */
-
-#define MIN_GWTUN_NETW_MASK 20
-#define MAX_GWTUN_NETW_MASK 30
-#define DEF_GWTUN_NETW_MASK 22
-
-#define MIN_TUN_LTIME 60 /*seconds*/
-#define MAX_TUN_LTIME 60000
-#define DEF_TUN_LTIME 600
-#define ARG_TUN_LTIME "tunnel_lease_time"
-
-
-#define MIN_RT_CLASS 0
-#define MAX_RT_CLASS 3
-
-// field accessor and flags for gateway announcement extension packets
-#define EXT_GW_FIELD_GWTYPES ext_related
-#define EXT_GW_FIELD_GWFLAGS def8
-#define EXT_GW_FIELD_GWPORT  d16.def16
-#define EXT_GW_FIELD_GWADDR  d32.def32
-
-// the flags for gw extension messsage gwtypes:
-#define TWO_WAY_TUNNEL_FLAG   0x01
-#define ONE_WAY_TUNNEL_FLAG   0x02
-
-struct tun_orig_data {
-	
-	int16_t  tun_array_len;
-	struct ext_packet tun_array[];
-	
-};
-
 struct plugin_v1 *tun_get_plugin_v1( void );
 #endif
 

Modified: trunk/batman-experimental/plugin.c
===================================================================
--- trunk/batman-experimental/plugin.c	2010-04-12 19:06:37 UTC (rev 1633)
+++ trunk/batman-experimental/plugin.c	2010-04-15 08:16:16 UTC (rev 1634)
@@ -336,9 +336,6 @@
 		pn->plugin = p;
 		pn->dlhandle = dlhandle;
 		
-		if ( pn->plugin_v1 )
-			Link_flags |= pn->plugin_v1->link_flags;
-		
 		list_add_tail( &pn->list, &plugin_list );
 		
 		dbgf_all( DBGT_INFO, "%s SUCCESS", pn->plugin_v1->plugin_name );
@@ -359,15 +356,13 @@
 static void deactivate_plugin( void *p ) {
 	
 	if ( !is_plugin_active( p ) ) {
-		cleanup_all( -500146 );
+		cleanup_all( -500190 );
 		//dbg( DBGL_SYS, DBGT_ERR, "deactivate_plugin(): requested to deactivate inactive plugin !");
 		//return;
 	}
 	
 	struct list_head *list_pos, *tmp_pos, *prev_pos = (struct list_head*)&plugin_list;
 		
-	Link_flags = 0;
-
 	list_for_each_safe( list_pos, tmp_pos, &plugin_list ) {
 			
 		struct plugin_node *pn = list_entry( list_pos, struct plugin_node, list );
@@ -379,7 +374,7 @@
 			if ( pn->version != PLUGIN_VERSION_01 )
 				cleanup_all( -500098 );
 			
-			dbgf( DBGL_CHANGES, DBGT_INFO, "deactivating plugin %s", pn->plugin_v1->plugin_name );
+			dbg( DBGL_CHANGES, DBGT_INFO, "deactivating plugin %s", pn->plugin_v1->plugin_name );
 			
 			if ( pn->plugin_v1->cb_cleanup )
 				(*( pn->plugin_v1->cb_cleanup )) ();
@@ -392,9 +387,6 @@
 			
 		} else {
 			
-			if ( pn->plugin_v1 )
-				Link_flags |= pn->plugin_v1->link_flags;
-			
 			prev_pos = &pn->list;
 			
 		}
@@ -405,7 +397,6 @@
 
 static int8_t activate_dyn_plugin( const char* name ) {
 	
-	//get_plugin_v1 get_plugin_v1;
 	struct plugin_v1* (*get_plugin_v1) ( void ) = NULL;
 	
 	void *dlhandle;
@@ -449,13 +440,22 @@
 	}
 	
 	dbgf_all( DBGT_INFO, "survived dlopen()!" );
-	
-	
-	if ( !( (*(void **)(&get_plugin_v1)) = dlsym( dlhandle, "get_plugin_v1"))  ) {
-		
+
+
+        typedef struct plugin_v1* (*sdl_init_function_type) ( void );
+
+        union {
+                sdl_init_function_type func;
+                void * obj;
+        } alias;
+
+        alias.obj = dlsym( dlhandle, "get_plugin_v1");
+
+	if ( !( get_plugin_v1 = alias.func )  ) {
 		dbgf( DBGL_SYS, DBGT_ERR, "dlsym( %s ) failed: %s", name, dlerror() );
 		return FAILURE;
 	}
+
 	
 	if ( !(pv1 = get_plugin_v1()) ) {
 

Modified: trunk/batman-experimental/plugin.h
===================================================================
--- trunk/batman-experimental/plugin.h	2010-04-12 19:06:37 UTC (rev 1633)
+++ trunk/batman-experimental/plugin.h	2010-04-15 08:16:16 UTC (rev 1634)
@@ -46,7 +46,6 @@
 	void (*cb_plugin_handler[PLUGIN_CB_SIZE]) (void*);
 	
 	//some other attributes
-	uint8_t link_flags;
 
 };
 

Modified: trunk/batman-experimental/posix/posix.c
===================================================================
--- trunk/batman-experimental/posix/posix.c	2010-04-12 19:06:37 UTC (rev 1633)
+++ trunk/batman-experimental/posix/posix.c	2010-04-15 08:16:16 UTC (rev 1634)
@@ -38,6 +38,7 @@
 #include "metrics.h"
 #include "plugin.h"
 #include "schedule.h"
+//#include "avl.h"
 
 # define timercpy(d, a) (d)->tv_sec = (a)->tv_sec; (d)->tv_usec = (a)->tv_usec; 
 
@@ -53,6 +54,14 @@
 }
 #endif
 
+/* get_time functions MUST be called at least every 2*MAX_SELECT_TIMEOUT_MS to allow for properly working time-drift checks */
+
+/* overlaps after approximately 138 years */
+//#define get_time_sec()  get_time( NO, NULL  )
+
+/* overlaps after 49 days, 17 hours, 2 minutes, and 48 seconds */
+//#define get_time_msec() get_time( YES, NULL )
+
 void update_batman_time( struct timeval *precise_tv ) {
 	
 	timeradd( &max_tv, &new_tv, &acceptable_p_tv );
@@ -176,7 +185,9 @@
 
 void print_animation( void ) {
 
-	Trash = system( "clear" );
+	int trash;
+
+	trash = system( "clear" );
 	BAT_LOGO_END( 0, 500 );
 
 	sym_print( 0, 3, "." );
@@ -379,25 +390,26 @@
 void cleanup_all( int status ) {
 	
 	static int cleaning_up = NO;
-	
-	if ( status < 0 ) {
-			/*
-	 * Negative numbers are used as SIGSEV error codes !
-	 * Currently used numbers are 
-	 * for core programs:		-500000 ... -500156
-	 */
-		dbg( DBGL_SYS, DBGT_ERR, 
-		     "Terminating with error code %d ! Please notify a developer", status );
+
+        if (status < 0) {
+                dbg(DBGL_SYS, DBGT_ERR, "Terminating with error code %d ! Please notify a developer", status);
+
+                dbg(DBGL_SYS, DBGT_ERR, "raising SIGSEGV to simplify debugging ...");
+
+                errno = 0;
+                if (raise(SIGSEGV)) {
+                        dbg(DBGL_SYS, DBGT_ERR, "raising SIGSEGV failed: %s...", strerror(errno));
+                }
+
+        }
+
+
+        if (!cleaning_up) {
+
+                cleaning_up = YES;
+
+                // first, restore defaults...
 		
-		raise( SIGSEGV );
-	}
-	
-	if ( !cleaning_up ) {
-	
-		cleaning_up = YES;
-	
-		// first, restore defaults...
-		
 		stop = 1;
 		
 		cleanup_schedule();
@@ -421,13 +433,11 @@
 			remove_outstanding_ogms( bif );
 			
 			list_del( (struct list_head *)&if_list, list_pos, &if_list );
-			
-			debugFree( list_pos, 1214 );
+
+                        //debugFree(bif->own_ogm_out, 1209);
+                        debugFree(bif, 1214);
 		}
 
-		hash_destroy( orig_hash );
-		
-		
 		// last, close debugging system and check for forgotten resources...
 		cleanup_control();
 		
@@ -462,28 +472,27 @@
 
 	My_pid = getpid();
 
-	
-	char *d = getenv(BMX_ENV_DEBUG);
+/*	char *d = getenv(BMX_ENV_DEBUG);
 	if ( d  &&  strtol(d, NULL , 10) >= DBGL_MIN  &&  strtol(d, NULL , 10) <= DBGL_MAX )
 		debug_level = strtol(d, NULL , 10);
+*/
 	
-	
 	srand( My_pid );
 
 	init_set_bits_table256();
 	
-	orig_hash = hash_new( 128, compare_key, choose_key, 4 );
-	
 	signal( SIGINT, handler );
 	signal( SIGTERM, handler );
 	signal( SIGPIPE, SIG_IGN );
 	signal( SIGSEGV, segmentation_fault );
 	
+	init_control();
+
 	init_profile();
 	
 	init_route();
 	
-	init_control();
+//	init_control();
 	
 	init_route_args();
 	

Modified: trunk/batman-experimental/posix/tunnel.c
===================================================================
--- trunk/batman-experimental/posix/tunnel.c	2010-04-12 19:06:37 UTC (rev 1633)
+++ trunk/batman-experimental/posix/tunnel.c	2010-04-15 08:16:16 UTC (rev 1634)
@@ -33,16 +33,73 @@
 #include <linux/if_tun.h> /* TUNSETPERSIST, ... */
 #include <linux/if.h>     /* ifr_if, ifr_tun */
 #include <fcntl.h>        /* open(), O_RDWR */
+#include <asm/types.h>
+#include <sys/socket.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
 
 
+
 #include "batman.h"
 #include "os.h"
 #include "originator.h"
 #include "plugin.h"
 #include "schedule.h"
 
-static int32_t Tun_persist;
 
+#define ARG_UNRESP_GW_CHK "unresp_gateway_check"
+
+#define ARG_TWO_WAY_TUNNEL "two_way_tunnel"
+
+#define ARG_ONE_WAY_TUNNEL "one_way_tunnel"
+
+#define ARG_GW_HYSTERESIS "gateway_hysteresis"
+#define MIN_GW_HYSTERE    1
+#define MAX_GW_HYSTERE    PROBE_RANGE/PROBE_TO100
+#define DEF_GW_HYSTERE    2
+
+
+#define BATMAN_TUN_PREFIX "bat"
+#define MAX_BATMAN_TUN_INDEX 20
+
+#define TUNNEL_DATA 0x01
+#define TUNNEL_IP_REQUEST 0x02
+#define TUNNEL_IP_INVALID 0x03
+#define TUNNEL_IP_REPLY 0x06
+
+#define GW_STATE_UNKNOWN  0x01
+#define GW_STATE_VERIFIED 0x02
+
+#define ONE_MINUTE                60000
+
+#define GW_STATE_UNKNOWN_TIMEOUT  (1  * ONE_MINUTE)
+#define GW_STATE_VERIFIED_TIMEOUT (5  * ONE_MINUTE)
+
+#define IP_LEASE_TIMEOUT          (1 * ONE_MINUTE)
+
+#define MAX_TUNNEL_IP_REQUESTS 60 //12
+#define TUNNEL_IP_REQUEST_TIMEOUT 1000 // msec
+
+#define DEF_GWTUN_NETW_PREFIX  "169.254.0.0" /* 0x0000FEA9 */
+
+#define MIN_GWTUN_NETW_MASK 20
+#define MAX_GWTUN_NETW_MASK 30
+#define DEF_GWTUN_NETW_MASK 22
+
+#define MIN_TUN_LTIME 60 /*seconds*/
+#define MAX_TUN_LTIME 60000
+#define DEF_TUN_LTIME 600
+#define ARG_TUN_LTIME "tunnel_lease_time"
+
+#define DEF_TUN_PERSIST 1
+
+
+#define MIN_RT_CLASS 0
+#define MAX_RT_CLASS 3
+
+
+static int32_t Tun_persist = DEF_TUN_PERSIST;
+
 static int32_t my_gw_port = 0;
 static uint32_t my_gw_addr = 0;
 
@@ -73,11 +130,131 @@
 
 static uint32_t gw_tunnel_netmask;
 
-static int32_t Tun_leasetime;
+static int32_t Tun_leasetime = DEF_TUN_LTIME;
 
 
 static uint32_t pref_gateway = 0;
 
+
+
+
+struct tun_request_type {
+	uint32_t lease_ip;
+	uint16_t lease_lt;
+} __attribute__((packed));
+
+struct tun_data_type {
+	unsigned char ip_packet[MAX_MTU];
+} __attribute__((packed));
+
+struct tun_packet_start {
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+	unsigned int type:4;
+	unsigned int version:4;  // should be the first field in the packet in network byte order
+#elif __BYTE_ORDER == __BIG_ENDIAN
+	unsigned int version:4;
+	unsigned int type:4;
+#else
+# error "Please fix <bits/endian.h>"
+#endif
+} __attribute__((packed));
+
+struct tun_packet
+{
+	uint8_t  reserved1;
+	uint8_t  reserved2;
+	uint8_t  reserved3;
+
+	struct tun_packet_start start;
+#define TP_TYPE  start.type
+#define TP_VERS  start.version
+
+	union
+	{
+		struct tun_request_type trt;
+		struct tun_data_type tdt;
+		struct iphdr iphdr;
+	}tt;
+#define LEASE_IP  tt.trt.lease_ip
+#define LEASE_LT  tt.trt.lease_lt
+#define IP_PACKET tt.tdt.ip_packet
+#define IP_HDR    tt.iphdr
+} __attribute__((packed));
+
+
+#define TX_RP_SIZE (sizeof(struct tun_packet_start) + sizeof(struct tun_request_type))
+#define TX_DP_SIZE (sizeof(struct tun_packet_start) + sizeof(struct tun_data_type))
+
+
+struct gwc_args {
+	uint32_t gw_state_stamp;
+	uint8_t gw_state;
+	uint8_t prev_gw_state;
+	uint32_t orig;
+	struct gw_node *gw_node;	// pointer to gw node
+	struct sockaddr_in gw_addr;	// gateway ip
+	char  gw_str[ADDR_STR_LEN];	// string of gateway ip
+	struct sockaddr_in my_addr; 	// primary_ip
+	uint32_t my_tun_addr;		// ip used for bat0 tunnel interface
+	char  my_tun_str[ADDR_STR_LEN];	// string of my_tun_addr
+	int32_t mtu_min;
+	uint8_t tunnel_type;
+	int32_t udp_sock;
+	int32_t tun_fd;
+	int32_t tun_ifi;
+	char tun_dev[IFNAMSIZ];		// was tun_if
+	uint32_t tun_ip_request_stamp;
+	uint32_t tun_ip_lease_stamp;
+	uint32_t tun_ip_lease_duration;
+	uint32_t send_tun_ip_requests;
+	uint32_t pref_addr;
+	//	uint32_t last_invalidip_warning;
+};
+
+
+struct gws_args
+{
+	int8_t netmask;
+	int32_t port;
+	int32_t owt;
+	int32_t twt;
+	int32_t lease_time;
+	int mtu_min;
+	uint32_t my_tun_ip;
+	uint32_t my_tun_netmask;
+	uint32_t my_tun_ip_h;
+	uint32_t my_tun_suffix_mask_h;
+	struct sockaddr_in  client_addr;
+	struct gw_client **gw_client_list;
+	int32_t sock;
+	int32_t tun_fd;
+	int32_t tun_ifi;
+	char tun_dev[IFNAMSIZ];
+};
+
+
+
+// field accessor and flags for gateway announcement extension packets
+#define EXT_GW_FIELD_GWTYPES ext_related
+#define EXT_GW_FIELD_GWFLAGS def8
+#define EXT_GW_FIELD_GWPORT  d16.def16
+#define EXT_GW_FIELD_GWADDR  d32.def32
+
+// the flags for gw extension messsage gwtypes:
+#define TWO_WAY_TUNNEL_FLAG   0x01
+#define ONE_WAY_TUNNEL_FLAG   0x02
+
+struct tun_orig_data {
+
+	int16_t  tun_array_len;
+	struct ext_packet tun_array[];
+
+};
+
+
+
+
+
 static uint16_t my_gw_ext_array_len = 0;
 static struct ext_packet my_gw_extension_packet; //currently only one gw_extension_packet considered
 static struct ext_packet *my_gw_ext_array = &my_gw_extension_packet;
@@ -468,7 +645,8 @@
 		// memorize new gw_msg
 		update_gw_list( on, gw_array_len, gw_array  );
 		
-	} else if ( tuno  &&  gw_array  &&  (tuno->tun_array_len != gw_array_len || memcmp( tuno->tun_array, gw_array, gw_array_len * sizeof(struct ext_packet)))) {
+	} else if ( tuno  &&  gw_array  &&
+                (tuno->tun_array_len != gw_array_len || memcmp( tuno->tun_array, gw_array, gw_array_len * sizeof(struct ext_packet)))) {
 		
 		// update existing gw_msg
 		update_gw_list( on, gw_array_len, gw_array  );
@@ -477,6 +655,7 @@
 	
 	/* restart gateway selection if routing class 3 and we have more packets than curr_gateway */
 	if (	curr_gateway  &&
+                on->router &&
 		routing_class == 3  &&
 		tuno  &&
 		tuno->tun_array[0].EXT_GW_FIELD_GWFLAGS  &&
@@ -484,15 +663,15 @@
 		curr_gateway->orig_node != on  &&
 		(	( pref_gateway == on->orig )  ||
 			( pref_gateway != curr_gateway->orig_node->orig  &&  
-			  curr_gateway->orig_node->router->accepted_sqr.wa_val + (gw_hysteresis*PROBE_TO100)
-				<= on->router->accepted_sqr.wa_val  ) ) ) {
+			  curr_gateway->orig_node->router->longtm_sqr.wa_val + (gw_hysteresis*PROBE_TO100)
+				<= on->router->longtm_sqr.wa_val  ) ) ) {
 		
 		dbg( DBGL_CHANGES, DBGT_INFO, "Restart gateway selection. %s gw found! "
 		     "%d OGMs from new GW %s (compared to %d from old GW %s)",
 		     pref_gateway == on->orig ? "Preferred":"Better",
-		     on->router ? on->router->accepted_sqr.wa_val : 255,  
+		     on->router->longtm_sqr.wa_val,
 		     on->orig_str, 
-		     pref_gateway != on->orig ? curr_gateway->orig_node->router->accepted_sqr.wa_val : 255, 
+		     pref_gateway != on->orig ? curr_gateway->orig_node->router->longtm_sqr.wa_val : 255,
 		     pref_gateway != on->orig ? curr_gateway->orig_node->orig_str : "???" );
 	
 		curr_gateway = NULL;
@@ -525,7 +704,7 @@
 		if ( gwc_args->pref_addr == 0  || gwc_args->pref_addr != tp->LEASE_IP ) {
 
 			if ( gwc_args->pref_addr /*== 0 ?????*/ )
-				add_del_route( 0, 0, 0, 0, gwc_args->tun_ifi, gwc_args->tun_dev, RT_TABLE_TUNNEL, RT_UNICAST, DEL, TRACK_TUNNEL );
+				add_del_route( 0, 0, 0, 0, gwc_args->tun_ifi, gwc_args->tun_dev, RT_TABLE_TUNNEL, RTN_UNICAST, DEL, TRACK_TUNNEL );
 			
 			if ( set_tun_addr( gwc_args->udp_sock, tp->LEASE_IP, gwc_args->tun_dev ) < 0 ) {
 		
@@ -534,7 +713,12 @@
 			}
 	
 			/* kernel deletes routes after resetting the interface ip */
-			add_del_route( 0, 0, 0, 0, gwc_args->tun_ifi, gwc_args->tun_dev, RT_TABLE_TUNNEL, RT_UNICAST, ADD, TRACK_TUNNEL );
+			add_del_route( 0, 0, 0, 0, gwc_args->tun_ifi, gwc_args->tun_dev, RT_TABLE_TUNNEL, RTN_UNICAST, ADD, TRACK_TUNNEL );
+			
+			// critical syntax: may be used for nameserver updates
+			dbg( DBGL_CHANGES, DBGT_INFO, "GWT: GW-client tunnel init succeeded - type: 2WT  dev: %s  IP: %s  MTU: %d  GWIP: %s", 
+			     gwc_args->tun_dev, ipStr( tp->LEASE_IP ) , gwc_args->mtu_min,  ipStr( gwc_args->gw_addr.sin_addr.s_addr) );
+			
 		}
 
 		gwc_args->tun_ip_lease_stamp = batman_time;
@@ -689,7 +873,7 @@
 		
 		tp_len = tp_data_len + sizeof(tp.start);
 		
-		if ( tp_data_len < (int32_t)sizeof(struct iphdr) || ((struct iphdr *)(tp.IP_PACKET))->version != 4 ) {
+		if ( tp_data_len < (int32_t)sizeof(struct iphdr) || tp.IP_HDR.version != 4 ) {
 			
 			dbgf( DBGL_SYS, DBGT_ERR, "Received Invalid packet type via tunnel !" );
 			continue;
@@ -741,10 +925,10 @@
 			     unresp_gw_chk  &&  
 			     gwc_args->gw_state == GW_STATE_UNKNOWN  &&   
 			     gwc_args->gw_state_stamp == 0 ) {
-		
-				if( ( (((struct iphdr  *)(tp.IP_PACKET))->protocol == IPPROTO_TCP )) || 
-				    ( (((struct iphdr  *)(tp.IP_PACKET))->protocol == IPPROTO_UDP) && 
-				      (((struct udphdr *)(tp.IP_PACKET + ((struct iphdr *)(tp.IP_PACKET))->ihl*4))->dest == dns_port)  )
+
+                                if ((tp.IP_HDR.protocol == IPPROTO_TCP) ||
+                                       ( (tp.IP_HDR.protocol == IPPROTO_UDP) &&
+				      (((struct udphdr *)((uint8_t*)&tp.IP_HDR) + (tp.IP_HDR.ihl*4))->dest == dns_port)  )
 				  ) {
 					gwc_args->gw_state_stamp = batman_time;
 				  }
@@ -817,16 +1001,14 @@
 
 			// got data from gateway
 			if ( tp.TP_TYPE == TUNNEL_DATA ) {
-				
-				if ( tp_data_len >= (int32_t)sizeof(struct iphdr) && 
-				     ((struct iphdr *)(tp.IP_PACKET))->version == 4 ) {
 
+                                if (tp_data_len >= (int32_t)sizeof (struct iphdr) && tp.IP_HDR.version == 4) {
+
 					     if ( write( gwc_args->tun_fd, tp.IP_PACKET, tp_data_len ) < 0 ) {
 						dbgf( DBGL_SYS, DBGT_ERR, "can't write packet: %s", strerror(errno) );
-					     }
+                                        }
 
-					if ( unresp_gw_chk && 
-					     ((struct iphdr *)(tp.IP_PACKET))->protocol != IPPROTO_ICMP  ) {
+                                        if (unresp_gw_chk && tp.IP_HDR.protocol != IPPROTO_ICMP) {
 				
 						gwc_args->gw_state = GW_STATE_VERIFIED;
 						gwc_args->gw_state_stamp = batman_time;
@@ -836,10 +1018,10 @@
 
 						if( gwc_args->prev_gw_state != gwc_args->gw_state ) {
 							
-							dbgf( DBGL_CHANGES, DBGT_INFO, 
-							     "changed GW state: from %d to %d, incoming IP protocol: %d", 
-							     gwc_args->prev_gw_state, gwc_args->gw_state,
-							     ((struct iphdr *)(tp.IP_PACKET))->protocol );
+							dbgf( DBGL_CHANGES, DBGT_INFO,
+                                                                "changed GW state: from %d to %d, incoming IP protocol: %d",
+                                                                gwc_args->prev_gw_state, gwc_args->gw_state,
+                                                                tp.IP_HDR.protocol);
 							
 							gwc_args->prev_gw_state = gwc_args->gw_state;
 						}
@@ -903,7 +1085,7 @@
 		update_interface_rules( IF_RULE_CLR_TUNNEL );
 		
 		if ( gwc_args->my_tun_addr )
-			add_del_route( 0, 0, 0, 0, gwc_args->tun_ifi, gwc_args->tun_dev, RT_TABLE_TUNNEL, RT_UNICAST, DEL, TRACK_TUNNEL );
+			add_del_route( 0, 0, 0, 0, gwc_args->tun_ifi, gwc_args->tun_dev, RT_TABLE_TUNNEL, RTN_UNICAST, DEL, TRACK_TUNNEL );
 			
 		if ( gwc_args->tun_fd ) {
 			del_dev_tun( gwc_args->tun_fd, gwc_args->tun_dev, gwc_args->my_tun_addr, __FUNCTION__ );
@@ -915,6 +1097,9 @@
 			set_fd_hook( gwc_args->udp_sock, gwc_recv_udp, YES /*delete*/ );
 		}
 		
+		// critical syntax: may be used for nameserver updates
+		dbg( DBGL_CHANGES, DBGT_INFO, "GWT: GW-client tunnel closed " );
+		
 		debugFree( gwc_args, 1207 );
 		gwc_args = NULL;
 	
@@ -1066,9 +1251,13 @@
 		gwc_args->my_tun_addr = gwc_args->my_addr.sin_addr.s_addr;
 		addr_to_str( gwc_args->my_tun_addr, gwc_args->my_tun_str );
 
-		add_del_route( 0, 0, 0, 0, gwc_args->tun_ifi, gwc_args->tun_dev, RT_TABLE_TUNNEL, RT_UNICAST, ADD, TRACK_TUNNEL );
+		add_del_route( 0, 0, 0, 0, gwc_args->tun_ifi, gwc_args->tun_dev, RT_TABLE_TUNNEL, RTN_UNICAST, ADD, TRACK_TUNNEL );
 
+		// critical syntax: may be used for nameserver updates
+		dbg( DBGL_CHANGES, DBGT_INFO, "GWT: GW-client tunnel init succeeded - type: 1WT  dev: %s  IP: %s  MTU: %d", 
+		     gwc_args->tun_dev, ipStr( gwc_args->my_addr.sin_addr.s_addr ) , gwc_args->mtu_min  );
 		
+		
 	} else /*if ( gwc_args->tunnel_type & TWO_WAY_TUNNEL_FLAG )*/ {
 		
 		register_task( 0, gwc_maintain_twt, NULL );
@@ -1080,6 +1269,9 @@
 	
 gwc_init_failure:
 	
+	// critical syntax: may be used for nameserver updates
+	dbg( DBGL_CHANGES, DBGT_INFO, "GWT: GW-client tunnel init failed" );
+	
 	gwc_cleanup();
 	curr_gateway = NULL;
 	
@@ -1256,7 +1448,7 @@
 	
 		if ( tp.TP_TYPE == TUNNEL_DATA ) {
 			
-			if ( !(tp_data_len >= (int32_t)sizeof(struct iphdr) && ((struct iphdr *)(tp.IP_PACKET))->version == 4 ) ) {
+			if ( !(tp_data_len >= (int32_t)sizeof(struct iphdr) && tp.IP_HDR.version == 4 ) ) {
 	
 				dbgf( DBGL_SYS, DBGT_ERR, "Invalid packet type via tunnel" );
 				continue;
@@ -1354,7 +1546,7 @@
 		
 		tp_len = tp_data_len + sizeof(tp.start);
 		
-		if ( !(gws_args->twt) || tp_data_len < (int32_t)sizeof(struct iphdr) || ((struct iphdr *)(tp.IP_PACKET))->version != 4 ) {
+		if ( !(gws_args->twt) || tp_data_len < (int32_t)sizeof(struct iphdr) || tp.IP_HDR.version != 4 ) {
 		
 			dbgf( DBGL_SYS, DBGT_ERR, "Invalid packet type for client tunnel" );
 			continue;
@@ -1406,7 +1598,7 @@
 		
 		if ( gws_args->tun_ifi )
 			add_del_route( gws_args->my_tun_ip, gws_args->netmask, 
-			               0, 0, gws_args->tun_ifi, gws_args->tun_dev, 254, RT_UNICAST, DEL, TRACK_TUNNEL );
+			               0, 0, gws_args->tun_ifi, gws_args->tun_dev, 254, RTN_UNICAST, DEL, TRACK_TUNNEL );
 			
 		if ( gws_args->tun_fd ) {
 			del_dev_tun( gws_args->tun_fd, gws_args->tun_dev, gws_args->my_tun_ip, __FUNCTION__ );
@@ -1425,6 +1617,10 @@
 			
 		}
 		
+		// critical syntax: may be used for nameserver updates
+		dbg( DBGL_CHANGES, DBGT_INFO, "GWT: GW-server tunnel closed - dev: %s  IP: %s/%d  MTU: %d", 
+		     gws_args->tun_dev, ipStr( gws_args->my_tun_ip ), gws_args->netmask , gws_args->mtu_min  );
+		
 		debugFree( gws_args, 1223 );
 		gws_args = NULL;
 	
@@ -1435,7 +1631,7 @@
 
 static int32_t gws_init( void ) {
 	
-	char str[16], str2[16];
+	//char str[16], str2[16];
 	
 	if ( probe_tun() == FAILURE )
 		goto gws_init_failure;
@@ -1469,10 +1665,10 @@
 	gws_args->my_tun_ip_h = ntohl( gw_tunnel_prefix );
 	gws_args->my_tun_suffix_mask_h = ntohl( ~gws_args->my_tun_netmask );
 	
-	addr_to_str( gws_args->my_tun_ip, str );
-	addr_to_str( gws_args->my_tun_netmask, str2 );
-	dbgf( DBGL_CHANGES, DBGT_INFO, "my_tun_ip %s, my_tun_netmask: %s", str, str2);
+	//addr_to_str( gws_args->my_tun_ip, str );
+	//addr_to_str( gws_args->my_tun_netmask, str2 );
 	
+	
 	gws_args->client_addr.sin_family = AF_INET;
 	gws_args->client_addr.sin_port = htons(gws_args->port);
 	
@@ -1535,7 +1731,7 @@
 	}
 	
 	add_del_route( gws_args->my_tun_ip, gws_args->netmask, 
-	               0, 0, gws_args->tun_ifi, gws_args->tun_dev, 254, RT_UNICAST, ADD, TRACK_TUNNEL );
+	               0, 0, gws_args->tun_ifi, gws_args->tun_dev, 254, RTN_UNICAST, ADD, TRACK_TUNNEL );
 	
 	register_task( 5000, gws_garbage_collector, NULL );
 	
@@ -1552,10 +1748,17 @@
 	
 	my_gw_ext_array_len = 1;
 
+	// critical syntax: may be used for nameserver updates
+	dbg( DBGL_CHANGES, DBGT_INFO, "GWT: GW-server tunnel init succeeded - dev: %s  IP: %s/%d  MTU: %d", 
+	     gws_args->tun_dev, ipStr( gws_args->my_tun_ip ), gws_args->netmask , gws_args->mtu_min  );
+	
 	return SUCCESS;
 	
 gws_init_failure:
-		
+	
+	// critical syntax: may be used for nameserver updates
+	dbg( DBGL_CHANGES, DBGT_INFO, "GWT: GW-server tunnel init failed" );
+	
 	gws_cleanup();
 		
 	return FAILURE;
@@ -1644,7 +1847,7 @@
 
 	if ( routing_class == 0  ||  curr_gateway ||
 	     ((routing_class == 1 || routing_class == 2 ) && 
-	      ( batman_time_sec < (((uint32_t)(my_ogi*my_pws))/(CHOOSE_GW_DELAY_DIVISOR*1000))  )) ) {
+	      ( batman_time_sec < COMMON_OBSERVATION_WINDOW  )) ) {
 
 		return;
 	}
@@ -1676,24 +1879,24 @@
 				get_gw_speeds( tuno->tun_array[0].EXT_GW_FIELD_GWFLAGS, &download_speed, &upload_speed );
 
 		// is this voodoo ???
-			tmp_gw_factor = ( ( ( on->router->accepted_sqr.wa_val/PROBE_TO100 ) *
-			                    ( on->router->accepted_sqr.wa_val/PROBE_TO100 ) ) ) * 
+			tmp_gw_factor = ( ( ( on->router->longtm_sqr.wa_val/PROBE_TO100 ) *
+			                    ( on->router->longtm_sqr.wa_val/PROBE_TO100 ) ) ) *
 						( download_speed / 64 ) ;
 		
 				if ( tmp_gw_factor > max_gw_factor || 
 				     ( tmp_gw_factor == max_gw_factor  && 
-				       on->router->accepted_sqr.wa_val > best_wa_val ) )
+				       on->router->longtm_sqr.wa_val > best_wa_val ) )
 					tmp_curr_gw = gw_node;
 		
 				break;
 
 				case 2:   /* stable connection (use best statistic) */
-				     if ( on->router->accepted_sqr.wa_val > best_wa_val )
+				     if ( on->router->longtm_sqr.wa_val > best_wa_val )
 					     tmp_curr_gw = gw_node;
 					break;
 
 					default:  /* fast-switch (use best statistic but change as soon as a better gateway appears) */
-				     if ( on->router->accepted_sqr.wa_val > best_wa_val )
+				     if ( on->router->longtm_sqr.wa_val > best_wa_val )
 							tmp_curr_gw = gw_node;
 						break;
 
@@ -1702,7 +1905,7 @@
 		if ( tuno->tun_array[0].EXT_GW_FIELD_GWFLAGS > max_gw_class )
 			max_gw_class = tuno->tun_array[0].EXT_GW_FIELD_GWFLAGS;
 
-		best_wa_val = MAX( best_wa_val, on->router->accepted_sqr.wa_val );
+		best_wa_val = MAX( best_wa_val, on->router->longtm_sqr.wa_val );
 		
 		
 		if ( tmp_gw_factor > max_gw_factor )
@@ -1716,7 +1919,7 @@
 			dbg( DBGL_SYS, DBGT_INFO, 
 			     "Preferred gateway found: %s (gw_flags: %i, packet_count: %i, ws: %i, gw_product: %i)", 
 			     on->orig_str, tuno->tun_array[0].EXT_GW_FIELD_GWFLAGS, 
-			     on->router->accepted_sqr.wa_val/PROBE_TO100, on->pws, tmp_gw_factor );
+			     on->router->longtm_sqr.wa_val/PROBE_TO100, on->pws, tmp_gw_factor );
 	
 			break;
 
@@ -1792,8 +1995,8 @@
 			
 			dbg_printf( cn, "%s %-15s %15s %3i, gw_class %2i - %i%s/%i%s, reliability: %i, supported tunnel types %s, %s \n",
 				curr_gateway == gw_node ? "=>" : "  ",
-				ipStr(on->orig) , ipStr(on->router->addr),
-			        gw_node->orig_node->router->accepted_sqr.wa_val/PROBE_TO100,
+				ipStr(on->orig) , ipStr(on->router->nnkey_addr),
+			        gw_node->orig_node->router->longtm_sqr.wa_val/PROBE_TO100,
 				tuno->tun_array[0].EXT_GW_FIELD_GWFLAGS,
 				download_speed > 2048 ? download_speed / 1024 : download_speed,
 				download_speed > 2048 ? "MBit" : "KBit",
@@ -1852,7 +2055,7 @@
 	
 	if ( cmd == OPT_APPLY ) {
 		
-		if ( Gateway_class  &&  routing_class )
+		if ( /* Gateway_class  && */ routing_class )
 			check_apply_parent_option( DEL, OPT_APPLY, _save, get_option(0,0,ARG_GW_CLASS), 0, cn );
 	
 	}
@@ -1879,8 +2082,10 @@
 			pref_gateway = test_ip;
 		
 			/* use routing class 3 if none specified */
+/*
 			if ( pref_gateway && !routing_class && !Gateway_class )
 				check_apply_parent_option( ADD, OPT_APPLY, _save, get_option(0,0,ARG_RT_CLASS), "3", cn );
+*/
 			
 		}
 		
@@ -1966,7 +2171,7 @@
 		
 			Gateway_class = gateway_class;
 			
-			if ( gateway_class  &&  routing_class )
+			if ( gateway_class  /*&&  routing_class*/ )
 				check_apply_parent_option( DEL, OPT_APPLY, _save, get_option(0,0,ARG_RT_CLASS), 0, cn );
 	
 			dbg( DBGL_SYS, DBGT_INFO, "gateway class: %i -> propagating: %s", gateway_class, gwarg );
@@ -2016,15 +2221,19 @@
  
 	{ODI,5,0,ARG_UNRESP_GW_CHK,	0,  A_PS1,A_ADM,A_DYI,A_CFA,A_ANY,	&unresp_gw_chk,	0, 		1,		1, 		0,
 			ARG_VALUE_FORM,"disable/enable unresponsive GW check (only relevant for GW clients in TWT mode)"},
- 
+
+#ifndef LESS_OPTIONS
 	{ODI,5,0,ARG_TUN_LTIME, 	0,  A_PS1,A_ADM,A_DYI,A_CFA,A_ANY,	&Tun_leasetime, MIN_TUN_LTIME, MAX_TUN_LTIME,	DEF_TUN_LTIME, 0,
 			ARG_VALUE_FORM,"set leasetime in seconds of virtual two-way-tunnel IPs"},
-  
+#endif
+
 	{ODI,4,0,ARG_GWTUN_NETW,	0,  A_PS1,A_ADM,A_INI,A_CFA,A_ANY,	0,		0, 		0,		0, 		opt_gwtun_netw,
 			ARG_PREFIX_FORM,"set network used by two-way-tunnel gateway nodes\n"},
 
-	{ODI,5,0,"tun_persist", 	0,  A_PS1,A_ADM,A_INI,A_CFA,A_ANY,	&Tun_persist, 	0,		1,		1,		0,
+#ifndef LESS_OPTIONS
+	{ODI,5,0,"tun_persist", 	0,  A_PS1,A_ADM,A_INI,A_CFA,A_ANY,	&Tun_persist, 	0,		1,		DEF_TUN_PERSIST,0,
 			ARG_VALUE_FORM,"disable/enable ioctl TUNSETPERSIST for GW tunnels (disabling was required for openVZ emulation)" },
+#endif
  
 	{ODI,5,0,ARG_GATEWAYS,		0,  A_PS0,A_USR,A_DYN,A_ARG,A_END,	0,		0, 		0,		0, 		opt_gateways,0,
 			"show currently available gateways\n"}

Modified: trunk/batman-experimental/schedule.c
===================================================================
--- trunk/batman-experimental/schedule.c	2010-04-12 19:06:37 UTC (rev 1633)
+++ trunk/batman-experimental/schedule.c	2010-04-15 08:16:16 UTC (rev 1634)
@@ -35,11 +35,18 @@
 #include "plugin.h"
 #include "schedule.h"
 
+int32_t my_ogi;   /* orginator message interval in miliseconds */
+int32_t ogi_pwrsave;
+
 static int32_t pref_udpd_size = DEF_UDPD_SIZE;
 
 //static int32_t aggr_p_ogi;
 static int32_t aggr_interval;
 
+#ifndef NOPARANOIA
+#define DEF_SIM_PARA NO
+static int32_t sim_paranoia = DEF_SIM_PARA;
+#endif
 
 
 static SIMPEL_LIST( send_list );
@@ -199,7 +206,9 @@
 uint32_t whats_next( void ) {
 	
 	struct list_head *list_pos, *tmp_pos, *prev_pos = (struct list_head*)&task_list;
-		
+
+        paranoia( -500175, sim_paranoia );
+
 	list_for_each_safe( list_pos, tmp_pos, &task_list ) {
 			
 		struct task_node *tn = list_entry( list_pos, struct task_node, list );
@@ -232,63 +241,51 @@
 	prof_start( PROF_send_aggregated_ogms );
 
 	struct list_head *if_pos;
-
 	uint8_t iftype;
 
 	/* send all the aggregated packets (which fit into max packet size) */
 	
 	/* broadcast via lan interfaces first */
 	for ( iftype = VAL_DEV_LL_LAN; iftype <= VAL_DEV_LL_WLAN; iftype++ ) {
-		
-		list_for_each(if_pos, &if_list) {
-		
-			struct batman_if *bif = list_entry(if_pos, struct batman_if, list);
-		
-			dbgf_all( DBGT_INFO, "dev: %s, linklayer %d iftype %d len %d ...",
-			         bif->dev, bif->if_linklayer, iftype, bif->aggregation_len);
 
-			if ( bif->if_linklayer == iftype  &&  
-			     bif->aggregation_len > (int32_t)sizeof( struct bat_header ) ) 
-			{
-				
-				((struct bat_header*)&(bif->aggregation_out))->version = COMPAT_VERSION;
-				
-				((struct bat_header*)&(bif->aggregation_out))->link_flags = Link_flags;
-				
-				
-				((struct bat_header*)&(bif->aggregation_out))->size =
-					(bif->aggregation_len)/4;
-				
-				
-				if ( bif->aggregation_len > MAX_UDPD_SIZE  ||  (bif->aggregation_len)%4 != 0) {
-					
-					dbg( DBGL_SYS, DBGT_ERR, "trying to send strange packet length %d oktets",
-					     bif->aggregation_len );
-					
-					cleanup_all( -500016 );
-				}
-				
-				if (bif->if_active ) {
-					
-					if ( send_udp_packet( bif->aggregation_out, bif->aggregation_len,
-					                      &bif->if_netwbrc_addr, bif->if_unicast_sock ) < 0 ) 
-					{
-						
-						dbg_mute( 60, DBGL_SYS, DBGT_ERR, 
-						          "send_aggregated_ogms() cant send via dev %s %s fd %d",
-						          bif->dev, bif->if_ip_str, bif->if_unicast_sock);
-					
-					}
-				}
-				
-				bif->aggregation_len = sizeof( struct bat_header );
-				
-			}
-		
-		}
+                list_for_each(if_pos, &if_list) {
 
-	}
-	
+                        struct batman_if *bif = list_entry(if_pos, struct batman_if, list);
+
+                        dbgf_all(DBGT_INFO, "dev: %s, linklayer %d iftype %d len %d min_len %d...",
+                                bif->dev, bif->if_linklayer, iftype, bif->aggregation_len,
+                                (int32_t)sizeof ( struct bat_header));
+
+                        if (bif->if_linklayer == iftype &&
+                                bif->aggregation_len > (int32_t)sizeof ( struct bat_header)) {
+
+                                struct bat_header *bat_hdr = (struct bat_header *) bif->aggregation_out;
+                                bat_hdr->version = COMPAT_VERSION;
+                                bat_hdr->link_flags = 0;
+                                bat_hdr->size = (bif->aggregation_len) / 4;
+
+                                if (bif->aggregation_len > MAX_UDPD_SIZE || (bif->aggregation_len) % 4 != 0) {
+
+                                        dbg(DBGL_SYS, DBGT_ERR, "trying to send strange packet length %d oktets",
+                                                bif->aggregation_len);
+
+                                        cleanup_all(-500016);
+                                }
+
+                                if (send_udp_packet(bif->aggregation_out, bif->aggregation_len,
+                                        &bif->if_netwbrc_addr, bif->if_unicast_sock) < 0) {
+                                        dbg_mute(60, DBGL_SYS, DBGT_ERR,
+                                                "send_aggregated_ogms() cant send via dev %s %s fd %d",
+                                                bif->dev, bif->if_ip_str, bif->if_unicast_sock);
+                                }
+
+                                bif->aggregation_len = sizeof ( struct bat_header);
+
+                        }
+ 
+                }
+        }
+
 	prof_stop( PROF_send_aggregated_ogms );
 	return;
 }
@@ -303,7 +300,7 @@
 	list_for_each( list_pos, &send_list ) {
 		
 		struct send_node *send_node = list_entry( list_pos, struct send_node, list );
-		struct bat_packet_ogm *ogm = ((struct bat_packet_ogm *)(send_node->ogm_buff));
+		struct bat_packet_ogm *ogm = send_node->ogm;
 		
 		dbg_printf( cn, "%-15s   (seqno %5d  ttl %3d)  at %u \n", 
 		         ipStr( ogm->orig ), ntohs(ogm->ogm_seqno), ogm->ogm_ttl, send_node->send_time );
@@ -368,11 +365,6 @@
 
 
 
-
-
-
-
-
 void remove_outstanding_ogms( struct batman_if *bif ) {
 	struct send_node *send_node;
 	struct list_head *send_pos, *send_temp, *send_prev;
@@ -389,19 +381,16 @@
 		if ( send_node->if_outgoing  ==  bif ) {
 			
 			list_del( send_prev, send_pos, &send_list );
+                        debugFree(send_node, 1502);
 			
-			if ( !send_node->own_if )
-				debugFree( send_node, 1502 );
-			
 		} else {
+                        send_prev = send_pos;
 			
-			send_prev = send_pos;
-			
 		}
 	}
 }
 	
-static void send_outstanding_ogms( void *unused ) {
+static void aggregate_outstanding_ogms( void *unused ) {
 
 	prof_start( PROF_send_outstanding_ogms );
 	struct send_node *send_node;
@@ -414,24 +403,10 @@
 	int dbg_if_out = 0;
 #define	MAX_DBG_IF_SIZE 200
 	static char dbg_if_str[ MAX_DBG_IF_SIZE ];
-	
-	//check that aggregation interval is not getting to big
-	//uint16_t aggr_interval = (my_ogi/aggr_p_ogi > 3*MIN_OGI) ? 3*MIN_OGI :  (my_ogi/aggr_p_ogi);
 
-	register_task( (aggr_interval + rand_num( aggr_interval/2 )) - (aggr_interval/4), send_outstanding_ogms, NULL );
+        // ensuring that aggreg_interval is really an upper boundary
+	register_task( aggr_interval - 1 - rand_num( aggr_interval/10 ), aggregate_outstanding_ogms, NULL );
 	
-	if ( list_empty( &send_list )  ||  
-	     GREAT_U32( (list_entry( (&send_list)->next, struct send_node, list ))->send_time, batman_time ) ) {
-		
-		prof_stop( PROF_send_outstanding_ogms );
-		return;
-	}
-	
-	dbgf_all( DBGT_INFO, 
-	         "now %u, aggreg_interval %d, send_list holds packets to send",
-	         batman_time, aggr_interval );
-
-	
 	prev_list_head = (struct list_head *)&send_list;
 	
 	list_for_each_safe( send_pos, send_temp, &send_list ) {
@@ -476,11 +451,11 @@
 			// keep care to not aggregate more packets than would fit into max packet size
 			aggregated_size += send_node->ogm_buff_len;
 
-			directlink =     (((struct bat_packet_ogm *)send_node->ogm_buff)->flags & DIRECTLINK_FLAG );
-			unidirectional = (((struct bat_packet_ogm *)send_node->ogm_buff)->flags & UNIDIRECTIONAL_FLAG );
-			cloned =         (((struct bat_packet_ogm *)send_node->ogm_buff)->flags & CLONED_FLAG );
+			directlink =     (send_node->ogm->flags & DIRECTLINK_FLAG );
+			unidirectional = (send_node->ogm->flags & UNIDIRECTIONAL_FLAG );
+			cloned =         (send_node->ogm->flags & CLONED_FLAG );
 
-			ttl = ((struct bat_packet_ogm *)send_node->ogm_buff)->ogm_ttl;
+			ttl = send_node->ogm->ogm_ttl;
 			if_singlehomed = ( (send_node->own_if && send_node->if_outgoing->if_singlehomed) ? 1 : 0 );
 			
 			
@@ -508,7 +483,7 @@
 				//TODO: send only pure bat_packet_ogm, no extension headers.
 				memcpy( send_node->if_outgoing->aggregation_out + 
 					send_node->if_outgoing->aggregation_len,
-						send_node->ogm_buff, send_node->ogm_buff_len );
+						send_node->ogm, send_node->ogm_buff_len );
 
 				send_node->if_outgoing->aggregation_len += send_node->ogm_buff_len;
 			
@@ -518,35 +493,44 @@
 	
 				list_for_each(if_pos, &if_list) {
 
-					bif = list_entry(if_pos, struct batman_if, list);
+					struct bat_packet_ogm *ogm;
 
+                                        bif = list_entry(if_pos, struct batman_if, list);
+
 					if ( !bif->if_active )
 						continue;
 					
 					if ( ( send_node->send_bucket >= bif->if_send_clones ) ||
 					     ( if_singlehomed && send_node->if_outgoing != bif ) )
 						continue;
-					
+
+                                        if (
+                                                // power-save mode enabled:
+                                                ogi_pwrsave > my_ogi &&
+                                                // we alone:
+                                                GREAT_U32(batman_time, bif->if_last_link_activity + COMMON_OBSERVATION_WINDOW) &&
+                                                (// not yet time for a neighbor-discovery hardbeat?:
+                                                send_node->own_if == 0 ||
+                                                send_node->if_outgoing != bif ||
+                                                LSEQ_U32(batman_time, bif->if_next_pwrsave_hardbeat)
+                                                ))
+                                                continue;
+
+
 					if ( (send_node->send_bucket + 100) < bif->if_send_clones )
 						send_node_done = NO;
 					
+                                        ogm = (struct bat_packet_ogm*) (bif->aggregation_out + bif->aggregation_len);
 					
-					memcpy( (bif->aggregation_out + bif->aggregation_len),
-						send_node->ogm_buff, send_node->ogm_buff_len );
+                                        memcpy( ogm, send_node->ogm, send_node->ogm_buff_len );
 					
-					
 					if ( send_node->iteration > bif->if_ant_diversity )
-						((struct bat_packet_ogm *)
-						 (bif->aggregation_out + bif->aggregation_len))->flags |= CLONED_FLAG;
-					
-					
+						ogm->flags |= CLONED_FLAG;
+										
 					if ( ( directlink ) && ( send_node->if_outgoing == bif ) )
-						((struct bat_packet_ogm *)
-						 (bif->aggregation_out + bif->aggregation_len))->flags |= DIRECTLINK_FLAG; 
-					
+						ogm->flags |= DIRECTLINK_FLAG;
 					else
-						((struct bat_packet_ogm *)
-						 (bif->aggregation_out + bif->aggregation_len))->flags &= ~DIRECTLINK_FLAG;
+						ogm->flags &= ~DIRECTLINK_FLAG;
 					
 					
 					bif->aggregation_len += send_node->ogm_buff_len;
@@ -568,8 +552,8 @@
 			dbgf_all( DBGT_INFO, 
 			         "OG %-16s, seqno %5d, TTL %2d, IDF %d, UDF %d, CLF %d "
 			         "iter %d len %3d max agg_size %3d IFs %s", 
-			         ipStr( ((struct bat_packet_ogm *)send_node->ogm_buff)->orig ), 
-			         ntohs( ((struct bat_packet_ogm *)send_node->ogm_buff)->ogm_seqno ), 
+			         ipStr( send_node->ogm->orig ), 
+			         ntohs( send_node->ogm->ogm_seqno ), 
 			         ttl, directlink, unidirectional, cloned, send_node->iteration,
 			         send_node->ogm_buff_len, aggregated_size, dbg_if_str );
 				
@@ -582,22 +566,15 @@
 		// trigger next seqno now where the first one of the current seqno has been send
 		if (  send_node->own_if  &&  send_node->iteration == 1  ) {
 			send_node->if_outgoing->if_seqno++;
+                        send_node->if_outgoing->send_own = 1;
 		}
 		
 		// remove all the finished packets from send_list
 		if ( send_node_done ) {
 	
 			list_del( prev_list_head, send_pos, &send_list );
+                        debugFree(send_node, 1502);
 		
-			if ( !send_node->own_if ) {
-				
-				debugFree( send_node, 1502 );
-				
-			} else {
-				// trigger the scheduling of the next own OGMs at the end of this function
-				send_node->if_outgoing->send_own = 1;
-			}
-		
 		} else {
 		
 			prev_list_head = &send_node->list;	
@@ -618,20 +595,31 @@
 	list_for_each(if_pos, &if_list) {
 			
 		bif = list_entry(if_pos, struct batman_if, list);
-				
-		// if own OGMs have been send during this call, schedule next one now
-		if ( bif->send_own ) 
-			schedule_own_ogm( bif );
 
-		bif->send_own = 0;
-		
-		
 		if ( bif->aggregation_len != sizeof( struct bat_header ) ) {
 			dbgf( DBGL_SYS, DBGT_ERR, 
 			     "finished with dev %s and packet_out_len %d > %d",
-			     bif->dev, bif->aggregation_len, sizeof( struct bat_header ) );
+			     bif->dev, bif->aggregation_len, (int)sizeof( struct bat_header ) );
 		}
-		
+
+
+                // if own OGMs need to be send, schedule next one now
+		if ( bif->send_own ) {
+
+                        schedule_own_ogm( bif );
+
+                        if (GREAT_U32(batman_time, bif->if_next_pwrsave_hardbeat))
+                                bif->if_next_pwrsave_hardbeat = batman_time + ((uint32_t) (ogi_pwrsave));
+
+                        bif->send_own = 0;
+                }
+
+
+                // this timestamp may become invalid after U32 wrap-around
+                if (GREAT_U32(batman_time, bif->if_last_link_activity + (2 * COMMON_OBSERVATION_WINDOW)))
+                        bif->if_last_link_activity = batman_time - COMMON_OBSERVATION_WINDOW;
+
+
 	}
 
 	prof_stop( PROF_send_outstanding_ogms );
@@ -644,7 +632,7 @@
 
 	prof_start( PROF_schedule_rcvd_ogm );
 	
-	struct send_node *send_node_new, *send_packet_tmp = NULL;
+	struct send_node *send_packet_tmp = NULL;
 	struct list_head *list_pos, *prev_list_head;
 	
 	uint8_t with_unidirectional_flag = 0;
@@ -718,13 +706,14 @@
 	for( i=0; i<=EXT_TYPE_MAX; i++ )
 		snd_ext_total_len += mb->snd_ext_len[i];
 
-	send_node_new = debugMalloc( sizeof(struct send_node) + sizeof(struct bat_packet_ogm) + snd_ext_total_len, 504 );
-	memset( send_node_new, 0, sizeof( struct send_node ) );
-	INIT_LIST_HEAD( &send_node_new->list );
+	struct send_node *sn = debugMalloc( sizeof(struct send_node) + sizeof(struct bat_packet_ogm) + snd_ext_total_len, 504 );
+	memset( sn, 0, sizeof( struct send_node ) );
+	INIT_LIST_HEAD( &sn->list );
 
-	send_node_new->ogm_buff_len = sizeof(struct bat_packet_ogm) + snd_ext_total_len;
+	sn->ogm_buff_len = sizeof(struct bat_packet_ogm) + snd_ext_total_len;
+        sn->ogm = (struct bat_packet_ogm*)sn->_attached_ogm_buff;
 
-	memcpy( send_node_new->ogm_buff, mb->bp.ogm, sizeof(struct bat_packet_ogm) );
+	memcpy( sn->ogm, mb->bp.ogm, sizeof(struct bat_packet_ogm) );
 
 	/* primary-interface-extension messages do not need to be rebroadcastes */
 	/* other extension messages only if not unidirectional and ttl > 1 */
@@ -735,7 +724,7 @@
 		
 		if ( mb->snd_ext_len[i] ) {
 			
-			memcpy( &(send_node_new->ogm_buff[p]), 
+			memcpy( &(((unsigned char*)(sn->ogm))[p]),
 			        (unsigned char *)(mb->snd_ext_array[i]), 
 			        mb->snd_ext_len[i] );
 			
@@ -743,35 +732,34 @@
 		}
 	}
 	
-	if ( p != send_node_new->ogm_buff_len ) {
-		dbgf( DBGL_SYS, DBGT_ERR, "incorrect msg lengths %d != %d", p, send_node_new->ogm_buff_len );
+	if ( p != sn->ogm_buff_len ) {
+		dbgf( DBGL_SYS, DBGT_ERR, "incorrect msg lengths %d != %d", p, sn->ogm_buff_len );
 	}
 	
-	((struct bat_packet_ogm *)send_node_new->ogm_buff)->ogm_ttl--;
-	((struct bat_packet_ogm *)send_node_new->ogm_buff)->prev_hop_id = neigh_id;
-	((struct bat_packet_ogm *)send_node_new->ogm_buff)->bat_size = (send_node_new->ogm_buff_len)>>2;
+	sn->ogm->ogm_ttl--;
+	sn->ogm->prev_hop_id = neigh_id;
+	sn->ogm->bat_size = (sn->ogm_buff_len)>>2;
 
-	send_node_new->send_time = batman_time;
-	send_node_new->own_if = 0;
+	sn->send_time = batman_time;
+	sn->own_if = 0;
 
-	send_node_new->if_outgoing = mb->iif;
+	sn->if_outgoing = mb->iif;
 
-	((struct bat_packet_ogm *)send_node_new->ogm_buff)->flags = 0x00;
+	sn->ogm->flags = 0x00;
 	
 	if ( with_unidirectional_flag )
-		((struct bat_packet_ogm *)send_node_new->ogm_buff)->flags |= UNIDIRECTIONAL_FLAG;
+		sn->ogm->flags |= UNIDIRECTIONAL_FLAG;
 
 	if ( directlink )
-		((struct bat_packet_ogm *)send_node_new->ogm_buff)->flags |= DIRECTLINK_FLAG;
+		sn->ogm->flags |= DIRECTLINK_FLAG;
 
 	
 	if ( oCtx & HAS_CLONED_FLAG )
-		((struct bat_packet_ogm *)send_node_new->ogm_buff)->flags |= CLONED_FLAG;
+		sn->ogm->flags |= CLONED_FLAG;
 
 	
 	/* change sequence number to network order */
-	((struct bat_packet_ogm *)send_node_new->ogm_buff)->ogm_seqno = 
-		htons( ((struct bat_packet_ogm *)send_node_new->ogm_buff)->ogm_seqno );
+        sn->ogm->ogm_seqno = htons(sn->ogm->ogm_seqno);
 	
 
 	prev_list_head = (struct list_head *)&send_list;
@@ -780,9 +768,9 @@
 
 		send_packet_tmp = list_entry( list_pos, struct send_node, list );
 
-		if ( GREAT_U32(send_packet_tmp->send_time, send_node_new->send_time) ) {
+		if ( GREAT_U32(send_packet_tmp->send_time, sn->send_time) ) {
 
-			list_add_before( prev_list_head, list_pos, &send_node_new->list );
+			list_add_before( prev_list_head, list_pos, &sn->list );
 			break;
 
 		}
@@ -791,8 +779,8 @@
 
 	}
 
-	if ( ( send_packet_tmp == NULL ) || ( LSEQ_U32(send_packet_tmp->send_time, send_node_new->send_time) ) )
-		list_add_tail( &send_node_new->list, &send_list );
+	if ( ( send_packet_tmp == NULL ) || ( LSEQ_U32(send_packet_tmp->send_time, sn->send_time) ) )
+		list_add_tail( &sn->list, &send_list );
 
 		
 	prof_stop( PROF_schedule_rcvd_ogm );
@@ -887,10 +875,11 @@
 				ext_p = 0;
 				ext_type++;
 			}
-		
 
-			if ( (int32_t)(sizeof(struct bat_packet_ogm) + done_p)  !=  ((((struct bat_packet_common *)pos)->bat_size)<<2) ) {
 
+                        if ((int32_t) (sizeof (struct bat_packet_ogm) + done_p) !=
+                                ((((struct bat_packet_common *) pos)->bat_size) << 2)) {
+
 				udp_len = udp_len - ((((struct bat_packet_common *)pos)->bat_size)<<2);
 				pos = pos + ((((struct bat_packet_common *)pos)->bat_size)<<2);
 
@@ -898,7 +887,7 @@
 				     "Drop packet! Rcvd corrupted packet size via NB %s: "
 				     "processed bytes: %d , indicated bytes %d, flags. %X, remaining bytes %d",
 				     mb->neigh_str,
-				     (sizeof(struct bat_packet_ogm) + done_p), 
+				     (int)(sizeof(struct bat_packet_ogm) + done_p),
 				     ((((struct bat_packet_common *)pos)->bat_size)<<2), 
 				     ((struct bat_packet_ogm *)pos)->flags, udp_len );
 
@@ -983,35 +972,32 @@
 		((((struct bat_header *)pos)->size)<<2) > mb->total_length )
 	{
 	
-		if ( mb->total_length >= (int32_t)(sizeof(struct bat_header) /*+ sizeof(struct bat_packet_common) */) )
+		if ( mb->total_length >= (int32_t)(sizeof(struct bat_header) /*+ sizeof(struct bat_packet_common) */) ) {
 			dbg_mute( 60, DBGL_SYS, DBGT_WARN, 
 			     "Drop packet: rcvd incompatible batman packet via NB %s "
-			     "(version? %i, link_flags? %X, reserved? %X, size? %i), "
+			     "(version? %i, reserved? %X, size? %i), "
 			     "rcvd udp_len %d  My version is %d",
 			     mb->neigh_str,
 			     ((struct bat_header *)pos)->version,
-			     ((struct bat_header *)pos)->link_flags,
 			     ((struct bat_header *)pos)->reserved,
 			     ((struct bat_header *)pos)->size,
 			     mb->total_length, COMPAT_VERSION );
-			
-		else
+
+                } else {
 			dbg_mute( 40, DBGL_SYS, DBGT_ERR, "Rcvd to small packet via NB %s, rcvd udp_len %i",
 			     mb->neigh_str, mb->total_length );
-		
+                }
+
 		prof_stop( PROF_process_packet );
 		return;
 	
 	}
-	
-	
-	mb->link_flags = ((struct bat_header *)pos)->link_flags;
-	mb->neigh = rcvd_neighbor;
 
-	dbgf_all( DBGT_INFO, "version? %i, link_flags? %X, "
+        mb->neigh = rcvd_neighbor;
+
+	dbgf_all( DBGT_INFO, "version? %i, "
 	         "reserved? %X, size? %i, rcvd udp_len %d via NB %s %s %s", 
 	         ((struct bat_header *)pos)->version, 
-	         ((struct bat_header *)pos)->link_flags,
 	         ((struct bat_header *)pos)->reserved,
 	         ((struct bat_header *)pos)->size,
 	         mb->total_length, mb->neigh_str, mb->iif->dev, mb->unicast?"UNICAST":"BRC" );
@@ -1073,6 +1059,8 @@
 
 	}
 
+        mb->iif->if_last_link_activity = batman_time;
+
 	strip_packet( mb, pos, udp_len );
 	
 	prof_stop( PROF_process_packet );
@@ -1390,56 +1378,82 @@
 
 
 
-void schedule_own_ogm( struct batman_if *batman_if ) {
+void schedule_own_ogm( struct batman_if *bif ) {
 
 	prof_start( PROF_schedule_own_ogm );
 
-	struct send_node *send_node_new, *send_packet_tmp = NULL;
+	struct send_node *send_packet_tmp = NULL;
 	struct list_head *list_pos, *prev_list_head;
-	
-	send_node_new = batman_if->own_send_node;
-	memset( send_node_new, 0, sizeof( struct send_node) );
 
-	INIT_LIST_HEAD( &send_node_new->list );
+        int sn_size = sizeof (struct send_node) +
+                ((bif == primary_if) ? MAX_UDPD_SIZE + 1 : sizeof (struct bat_packet_ogm) + sizeof (struct ext_packet));
 
-	send_node_new->send_time = batman_if->if_seqno_schedule + my_ogi;
+        struct send_node *sn = (struct send_node*) debugMalloc(sn_size, 209);
+
+        memset(sn, 0, sizeof (struct send_node) + sizeof (struct bat_packet_ogm) );
+
+        INIT_LIST_HEAD( &sn->list );
+
+        sn->ogm = (struct bat_packet_ogm*) sn->_attached_ogm_buff;
+
+        sn->ogm->ext_msg = NO;
+        sn->ogm->bat_type = BAT_TYPE_OGM;
+        sn->ogm->ogx_flag = NO;
+        sn->ogm->ogm_ttl = bif->if_ttl;
+	sn->ogm->ogm_pws = my_pws;
+        sn->ogm->orig = bif->if_addr;
+	//sn->ogm->ogm_path_lounge = Signal_lounge;
+
+
+
+	sn->send_time = bif->if_seqno_schedule + my_ogi;
 	
-	if ( LESS_U32( send_node_new->send_time, batman_time ) || 
-	     GREAT_U32( send_node_new->send_time, batman_time + my_ogi ) ) 
+	if ( LESS_U32( sn->send_time, batman_time ) ||
+	     GREAT_U32( sn->send_time, batman_time + my_ogi ) )
 	{
 		dbg_mute( 50, DBGL_SYS, DBGT_WARN, 
 		          "strange own OGM schedule, rescheduling IF %10s SQN %d from %d to %d. "
-		          "Maybe --%s too small, --%s to big or too much --%s", 
-		          batman_if->dev, batman_if->if_seqno, send_node_new->send_time, batman_time + my_ogi,
-		          ARG_OGI_INTERVAL, ARG_AGGR_ITERVAL, ARG_WL_CLONES );
+		          "Maybe we just woke up from power-save mode, --%s too small, --%s to big or too much --%s",
+		          bif->dev, bif->if_seqno, sn->send_time, batman_time + my_ogi,
+		          ARG_OGI, ARG_AGGR_IVAL, ARG_WL_CLONES );
 	
-		send_node_new->send_time = batman_time + my_ogi;// - (my_ogi/(2*aggr_p_ogi));
+		sn->send_time = batman_time + my_ogi;// - (my_ogi/(2*aggr_p_ogi));
 	}
 	
-	batman_if->if_seqno_schedule = send_node_new->send_time;
+	bif->if_seqno_schedule = sn->send_time;
 	
-	dbgf_all( DBGT_INFO, "for %s seqno %d at %d", batman_if->dev, batman_if->if_seqno, send_node_new->send_time );
+	dbgf_all( DBGT_INFO, "for %s seqno %d at %d", bif->dev, bif->if_seqno, sn->send_time );
 	
 	
-	send_node_new->if_outgoing = batman_if;
-	send_node_new->own_if = 1;
+	sn->if_outgoing = bif;
+	sn->own_if = 1;
 
 	uint32_t ogm_len = sizeof(struct bat_packet_ogm);
-	unsigned char *what_p;
-	int32_t what_len;
 
 	/* only primary interfaces send usual extension messages */
-	if (  batman_if == primary_if  ) {
+	if (  bif == primary_if  ) {
 		
 		uint16_t t;
 		for ( t=0; t<=EXT_TYPE_MAX; t++ ) {
+                        
+                        int32_t what_len=0;
 		
-			if ( (what_len = cb_snd_ext_hook( t, send_node_new->ogm_buff + ogm_len )) != FAILURE )
-				ogm_len += what_len;
-			
-			else
+			if ( (what_len = cb_snd_ext_hook( t, (unsigned char*)sn->ogm + ogm_len )) == FAILURE )
 				cleanup_all( -500040 - t );
-			
+
+                        if ( ogm_len+what_len > (uint32_t) pref_udpd_size) {
+
+                                dbg(DBGL_SYS, DBGT_ERR,
+                                        "%s=%d  exceeded by needed ogm + extension header length (%d+%d) "
+                                        "due to additional extension header 0x%X"
+                                        "you may increase %s or specify less tpye-0x%X extension headers",
+                                        ARG_UDPD_SIZE, pref_udpd_size, ogm_len, what_len, t, ARG_UDPD_SIZE, t);
+
+                                cleanup_all(-500192);
+                                //break;
+                        }
+
+                        ogm_len += what_len;
 		}
 		
 	/* all non-primary interfaces send primary-interface extension message */
@@ -1448,22 +1462,19 @@
 		my_pip_extension_packet.EXT_PIP_FIELD_ADDR = primary_addr;
 		my_pip_extension_packet.EXT_PIP_FIELD_PIPSEQNO = htons( primary_if->if_seqno );
 		
-		what_len = sizeof(struct ext_packet);
-		what_p = (unsigned char *)&my_pip_extension_packet;
-
-		memcpy( (send_node_new->ogm_buff + ogm_len), what_p, what_len );
-		ogm_len += what_len;
+		memcpy( (unsigned char*)sn->ogm + ogm_len, &my_pip_extension_packet, sizeof(struct ext_packet) );
+		ogm_len += sizeof(struct ext_packet);
 		
 	}
 
 	
-	send_node_new->ogm_buff_len = ogm_len;
+	sn->ogm_buff_len = ogm_len;
 	
-	batman_if->own_ogm_out->ogm_seqno = htons( batman_if->if_seqno );
-	batman_if->own_ogm_out->bat_size = ogm_len/4;
-	batman_if->own_ogm_out->flags = 0;
+	sn->ogm->ogm_seqno = htons( bif->if_seqno );
+	sn->ogm->bat_size = ogm_len/4;
+	sn->ogm->flags = 0;
 
-	batman_if->own_ogm_out->ogm_misc = MIN( s_curr_avg_cpu_load , 255 );
+	sn->ogm->ogm_misc = MIN( s_curr_avg_cpu_load , 255 );
 	
 	prev_list_head = (struct list_head *)&send_list;
 
@@ -1471,9 +1482,9 @@
 
 		send_packet_tmp = list_entry( list_pos, struct send_node, list );
 
-		if ( GREAT_U32(send_packet_tmp->send_time, send_node_new->send_time) ) {
+		if ( GREAT_U32(send_packet_tmp->send_time, sn->send_time) ) {
 
-			list_add_before( prev_list_head, list_pos, &send_node_new->list );
+			list_add_before( prev_list_head, list_pos, &sn->list );
 			break;
 
 		}
@@ -1482,21 +1493,21 @@
 
 	}
 
-	if ( ( send_packet_tmp == NULL ) || ( LSEQ_U32(send_packet_tmp->send_time, send_node_new->send_time) ) )
-		list_add_tail( &send_node_new->list, &send_list );
+	if ( ( send_packet_tmp == NULL ) || ( LSEQ_U32(send_packet_tmp->send_time, sn->send_time) ) )
+		list_add_tail( &sn->list, &send_list );
 
 	list_for_each( list_pos, &link_list ) {
 
 		struct link_node *ln = list_entry(list_pos, struct link_node, list);
 		
-		struct link_node_dev *lndev = get_lndev( ln, batman_if, NO/*create*/ );
+		struct link_node_dev *lndev = get_lndev( ln, bif, NO/*create*/ );
 		
-		if ( lndev )
-			update_queued_metric( 0, my_link_lounge, batman_if->if_seqno - OUT_SEQNO_OFFSET,
-			                      &lndev->rtq_sqr, my_lws,
-			                      batman_if->if_addr , ln->orig_node->orig, batman_if, "schedule_own_ogm()" );
-		
-	}
+		if ( lndev) {
+                        update_lounged_metric(0, local_rtq_lounge,
+                                bif->if_seqno - OUT_SEQNO_OFFSET, bif->if_seqno - OUT_SEQNO_OFFSET,
+                                &lndev->rtq_sqr, local_lws);
+                }
+        }
 	
 
 	prof_stop( PROF_schedule_own_ogm );
@@ -1510,20 +1521,25 @@
 	
 	{ODI,5,0,0,			0,  0,0,0,0,0,				0,		0,		0,		0,		0,
 			0,		"\nScheduling options:"},
-		
-	//dispatch.c		
-		/*	
-	{ODI,5,0,"aggreg_per_ogi",	0,  A_PS1,A_ADM,A_DYI,A_CFA,A_ANY,	&aggr_p_ogi,	MIN_AGGR_P_OGI,	MAX_AGGR_P_OGI,	DEF_AGGR_P_OGI,	0,
-			ARG_VALUE_FORM,	"set number of OGM aggregations per originator interval"},
-		*/
-//dispatch.c
-	{ODI,5,0,ARG_AGGR_ITERVAL,	0,  A_PS1,A_ADM,A_DYI,A_CFA,A_ANY,	&aggr_interval,	40,		4000,		300,		0,
+
+	{ODI,5,0,ARG_OGI, 	        'o',A_PS1,A_ADM,A_DYI,A_CFA,A_ANY,	&my_ogi,	MIN_OGI,	MAX_OGI,	DEF_OGI,	0,
+			ARG_VALUE_FORM,	"set interval in ms with which new originator message (OGM) are send"},
+
+	{ODI,5,0,ARG_OGI_PWRSAVE, 	0,A_PS1,A_ADM,A_DYI,A_CFA,A_ANY,	&ogi_pwrsave,   MIN_OGI,	MAX_OGI,	MIN_OGI,      	0,
+			ARG_VALUE_FORM,	"enable power-saving feature by setting increased OGI when no other nodes are in range"},
+
+	{ODI,5,0,ARG_AGGR_IVAL,	        0,  A_PS1,A_ADM,A_DYI,A_CFA,A_ANY,	&aggr_interval,	MIN_AGGR_IVAL,  MAX_AGGR_IVAL,  DEF_AGGR_IVAL,	0,
 			ARG_VALUE_FORM,	"set aggregation interval (SHOULD be smaller than the half of your and others OGM interval)"},
 		
-		
-// dispatch.c
 	{ODI,5,0,ARG_UDPD_SIZE,		0,  A_PS1,A_ADM,A_DYI,A_CFA,A_ANY,	&pref_udpd_size,MIN_UDPD_SIZE,	MAX_UDPD_SIZE,	DEF_UDPD_SIZE,	0,
 			ARG_VALUE_FORM,	"set preferred udp-data size for send packets"}
+#ifndef LESS_OPTIONS
+#ifndef NOPARANOIA
+	,{ODI,5,0,"simulate_cleanup",	0,  A_PS1,A_ADM,A_DYI,A_ARG,A_ANY,	&sim_paranoia,   NO,	        YES,	        DEF_SIM_PARA,  	0,
+			ARG_VALUE_FORM,	"simulate paranoia and cleanup_all for testing"}
+#endif
+#endif
+
 };
 
 
@@ -1543,7 +1559,7 @@
 
 void start_schedule( void ) {
 	
-	register_task( 50+rand_num(100), send_outstanding_ogms, NULL );
+	register_task( 50+rand_num(100), aggregate_outstanding_ogms, NULL );
 }
 
 
@@ -1556,10 +1572,9 @@
 		struct send_node *send_node = list_entry( list_pos, struct send_node, list );
 		
 		list_del( (struct list_head *)&send_list, list_pos, &send_list );
+
+                debugFree(send_node, 1106);
 		
-		if ( !send_node->own_if )
-			debugFree( send_node, 1106 );
-		
 	}
 	
 	list_for_each_safe( list_pos, list_pos_tmp, &task_list ) {

Modified: trunk/batman-experimental/schedule.h
===================================================================
--- trunk/batman-experimental/schedule.h	2010-04-12 19:06:37 UTC (rev 1633)
+++ trunk/batman-experimental/schedule.h	2010-04-15 08:16:16 UTC (rev 1634)
@@ -17,9 +17,20 @@
  *
  */
 
+#define ARG_OGI "ogm_interval"
+#define DEF_OGI 1000
+#define MIN_OGI 50
+#define MAX_OGI 100000
+extern int32_t my_ogi; // my originator interval
 
-#define ARG_AGGR_ITERVAL "aggreg_interval"
+#define ARG_OGI_PWRSAVE "ogi_power_save"
 
+
+#define MIN_AGGR_IVAL 35
+#define MAX_AGGR_IVAL 4000
+#define DEF_AGGR_IVAL 500
+#define ARG_AGGR_IVAL "aggreg_interval"
+
 void init_schedule( void );
 void start_schedule( void );
 void change_selects( void );



More information about the commits mailing list