0
0
mirror of https://github.com/bmx-routing/bmx7 synced 2025-10-06 00:02:44 +02:00

BMX7 initial release candidate

This commit is contained in:
Axel Neumann
2015-07-21 14:09:24 +02:00
parent 55c9aba1fc
commit 2865a2fe21
63 changed files with 9751 additions and 9610 deletions

5
.gitignore vendored Normal file
View File

@@ -0,0 +1,5 @@
*.o
*.so
bmx6
core
gmon.out

16
Android.mk Normal file
View File

@@ -0,0 +1,16 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
include $(LOCAL_PATH)/Common.mk
LOCAL_SRC_FILES := $(SRC_C)
# -pedantic yields a lot of warnings from the NDK includes
LOCAL_CFLAGS := $(filter-out -pedantic,$(CFLAGS))
# Separate, since changing it on its own will break the Android app
LOCAL_MODULE := bmx6
LOCAL_FORCE_STATIC_EXECUTABLE := true
include $(BUILD_EXECUTABLE)

6
Application.mk Normal file
View File

@@ -0,0 +1,6 @@
# Older platforms don't have fdprintf and vfdprintf
APP_PLATFORM := android-8
# GCC 4.8/4.9 build arm binaries that crashed due to memory alignment issues.
# Clang build binaries that ran fine.
NDK_TOOLCHAIN_VERSION := clang

85
Common.mk Normal file
View File

@@ -0,0 +1,85 @@
GIT_REV ?= $(shell [ -r .git ] && git --no-pager log -n 1 --oneline | cut -d " " -f 1 || echo 0)
CFLAGS += -pedantic -Wall -W -Wno-unused-parameter -Os -g3 -std=gnu99 -DGIT_REV=\"$(GIT_REV)\"
# CFLAGS += -DHAVE_CONFIG_H
# CFLAGS += -DCRYPTLIB=POLARSSL_1_3_4 # POLARSSL_1_2_5 POLARSSL_1_2_9 POLARSSL_1_3_3 POLARSSL_1_3_4 CYASSL_2_8_0
# optinal defines:
# CFLAGS += -static
# CFLAGS += -pg # "-pg" with openWrt causes "gcrt1.o: No such file"! Needs ld -o myprog /lib/gcrt0.o myprog.o utils.o -lc_p, grep: http://www.cs.utah.edu/dept/old/texinfo/as/gprof.html
# paranoid defines (helps bug hunting during development):
# CFLAGS += -DEXTREME_PARANOIA -DEXIT_ON_ERROR -DPROFILING
# CFLAGS += -DNO_KEY_GEN # use openssl instead, like:
# openssl genrsa -out /etc/bmx6/rsa.pem 1024
# openssl rsa -in /etc/bmx6/rsa.pem -inform PEM -out /etc/bmx6/rsa.der -outform DER
# Some test cases:
# CFLAGS += -DTEST_LINK_ID_COLLISION_DETECTION
# CFLAGS += -DTEST_DEBUG # (testing syntax of __VA_ARGS__ dbg...() macros)
# CFLAGS += -DTEST_DEBUG_MALLOC # allocates a never freed byte which should be reported at bmx6 termination
# CFLAGS += -DAVL_5XLINKED -DAVL_DEBUG -DAVL_TEST
# optional defines (you may disable these features if you dont need them)
# CFLAGS += -DNO_DEBUG_TRACK
# CFLAGS += -DNO_DEBUG_SYS
# CFLAGS += -DLESS_OPTIONS
# CFLAGS += -DNO_DYN_PLUGIN
# CFLAGS += -DNO_TRACE_FUNCTION_CALLS
# CFLAGS += -DDEBUG_ALL
# CFLAGS += -DTRAFFIC_DUMP
# CFLAGS += -DDEBUG_DUMP
# CFLAGS += -DDEBUG_MALLOC
# CFLAGS += -DMEMORY_USAGE
# experimental or advanced defines (please dont touch):
# CFLAGS += -DNO_ASSERTIONS # (disable syntax error checking and error-code creation!)
# CFLAGS += -DEXTREME_PARANOIA # (check difficult syntax errors)
# CFLAGS += -DEXIT_ON_ERROR # (exit and return code due to unusual behavior)
# CFLAGS += -DTEST_DEBUG
# CFLAGS += -DWITH_UNUSED # (includes yet unused stuff and buggy stuff)
# CFLAGS += -DPROFILING # (no static functions -> better profiling and cores)
# CFLAGS += -DNO_CTAOCRYPT_DIR # for backward compatibility with old cyassl versions
# CFLAGS += -DCORE_LIMIT=20000 # equals ulimit -c 20000
#EXTRA_CFLAGS +=
#EXTRA_LDFLAGS +=
# add as much features and test cases as possible:
#EXTRA_CFLAGS += -DMOST
#for profiling:
#EXTRA_CFLAGS="-DPROFILING -pg"
#for very poor embedded stuff (reducing binary size and cpu footprint):
#EXTRA_CFLAGS="-DNO_DEBUG_TRACK -DNO_TRACE_FUNCTION_CALLS -DNO_ASSERTIONS"
#for small embedded stuff the defaults are just fine.
#for normal machines (adding features and facilitating debugging):
#EXTRA_CFLAGS="-DDEBUG_ALL -DTRAFFIC_DUMP -DDEBUG_DUMP -DEBUG_MALLOC -DMEMORY_USAGE"
CFLAGS += $(shell echo "$(EXTRA_CFLAGS)" | grep -q "DMOST" && echo "-pg -DCORE_LIMIT=20000 -DEXTREME_PARANOIA -DEXIT_ON_ERROR -DPROFILING -DDEBUG_ALL -DTRAFFIC_DUMP -DDEBUG_DUMP -DDEBUG_MALLOC -DMEMORY_USAGE " )
LDFLAGS += -g3
LDFLAGS += $(shell echo "$(CFLAGS) $(EXTRA_CFLAGS)" | grep -q "DNO_DYNPLUGIN" || echo "-Wl,-export-dynamic -ldl" )
LDFLAGS += $(shell echo "$(CFLAGS) $(EXTRA_CFLAGS)" | grep -q "DPROFILING" && echo "-pg -lc" )
LDFLAGS += -lz -lm
LDFLAGS += $(shell echo "$(CFLAGS) $(EXTRA_CFLAGS)" | grep -q "CYASSL" && echo "-lcyassl" || echo "-lpolarssl")
SBINDIR = $(INSTALL_PREFIX)/usr/sbin
SRC_C = bmx.c key.c node.c crypt.c sec.c content.c msg.c z.c desc.c metrics.c ogm.c link.c iptools.c tools.c plugin.c list.c allocate.c avl.c hna.c control.c schedule.c ip.c prof.c
SRC_H = bmx.h key.h node.h crypt.h sec.h content.h msg.h z.h desc.h metrics.h ogm.h link.h iptools.h tools.h plugin.h list.h allocate.h avl.h hna.h control.h schedule.h ip.h prof.h
SRC_C += $(shell echo "$(CFLAGS) $(EXTRA_CFLAGS)" | grep -q "DTRAFFIC_DUMP" && echo dump.c )
SRC_H += $(shell echo "$(CFLAGS) $(EXTRA_CFLAGS)" | grep -q "DTRAFFIC_DUMP" && echo dump.h )
OBJS = $(SRC_C:.c=.o)
PACKAGE_NAME := bmx6
BINARY_NAME := bmx6

104
Makefile
View File

@@ -14,102 +14,7 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA
GIT_REV = $(shell ( [ "$(REVISION_VERSION)" ] && echo "$(REVISION_VERSION)" ) || ( [ -d .git ] && git --no-pager log -n 1 --oneline|cut -d " " -f 1 ) || echo 0)
CFLAGS += -pedantic -Wall -W -Wno-unused-parameter -Os -g3 -std=gnu99
CFLAGS += -DHAVE_CONFIG_H
CFLAGS += -DGIT_REV=\"$(GIT_REV)\"
# CFLAGS += -DCRYPTLIB=POLARSSL_1_2_5 # POLARSSL_1_2_5 POLARSSL_1_2_9 POLARSSL_1_3_3 CYASSL_2_8_0
#-DHAVE_CONFIG_H
# optinal defines:
# CFLAGS += -static
# CFLAGS += -pg # "-pg" with openWrt causes "gcrt1.o: No such file"! Needs ld -o myprog /lib/gcrt0.o myprog.o utils.o -lc_p, grep: http://www.cs.utah.edu/dept/old/texinfo/as/gprof.html
# paranoid defines (helps bug hunting during development):
# CFLAGS += -DEXTREME_PARANOIA -DEXIT_ON_ERROR -DPROFILING
# Some test cases:
# CFLAGS += -DTEST_LINK_ID_COLLISION_DETECTION
# CFLAGS += -DTEST_DEBUG # (testing syntax of __VA_ARGS__ dbg...() macros)
# CFLAGS += -DTEST_DEBUG_MALLOC # allocates a never freed byte which should be reported at bmx6 termination
# CFLAGS += -DAVL_5XLINKED -DAVL_DEBUG -DAVL_TEST
# optional defines (you may disable these features if you dont need them)
# CFLAGS += -DNO_KEY_GEN # use openssl instead, like:
# openssl genrsa -out /etc/bmx6/rsa.pem 1024
# openssl rsa -in /etc/bmx6/rsa.pem -inform PEM -out /etc/bmx6/rsa.der -outform DER
# CFLAGS += -DNO_DEBUG_TRACK
# CFLAGS += -DNO_DEBUG_SYS
# CFLAGS += -DLESS_OPTIONS
# CFLAGS += -DNO_DYN_PLUGIN
# CFLAGS += -DNO_TRACE_FUNCTION_CALLS
# CFLAGS += -DDEBUG_ALL
# CFLAGS += -DTRAFFIC_DUMP
# CFLAGS += -DDEBUG_DUMP
# CFLAGS += -DDEBUG_MALLOC
# CFLAGS += -DMEMORY_USAGE
# experimental or advanced defines (please dont touch):
# CFLAGS += -DNO_ASSERTIONS # (disable syntax error checking and error-code creation!)
# CFLAGS += -DEXTREME_PARANOIA # (check difficult syntax errors)
# CFLAGS += -DEXIT_ON_ERROR # (exit and return code due to unusual behavior)
# CFLAGS += -DTEST_DEBUG
# CFLAGS += -DWITH_UNUSED # (includes yet unused stuff and buggy stuff)
# CFLAGS += -DPROFILING # (no static functions -> better profiling and cores)
# CFLAGS += -DNO_CTAOCRYPT_DIR # for backward compatibility with old cyassl versions
# CFLAGS += -DCORE_LIMIT=20000 # equals ulimit -c 20000
#EXTRA_CFLAGS +=
#EXTRA_LDFLAGS +=
# add as much features and test cases as possible:
#EXTRA_CFLAGS += -DMOST
#for profiling:
#EXTRA_CFLAGS="-DPROFILING -pg"
#for very poor embedded stuff (reducing binary size and cpu footprint):
#EXTRA_CFLAGS="-DNO_DEBUG_TRACK -DNO_TRACE_FUNCTION_CALLS -DNO_ASSERTIONS"
#for small embedded stuff the defaults are just fine.
#for normal machines (adding features and facilitating debugging):
#EXTRA_CFLAGS="-DDEBUG_ALL -DTRAFFIC_DUMP -DDEBUG_DUMP -DEBUG_MALLOC -DMEMORY_USAGE"
CFLAGS += $(shell echo "$(EXTRA_CFLAGS)" | grep -q "DMOST" && echo "-pg -DCORE_LIMIT=20000 -DEXTREME_PARANOIA -DEXIT_ON_ERROR -DPROFILING -DDEBUG_ALL -DTRAFFIC_DUMP -DDEBUG_DUMP -DDEBUG_MALLOC -DMEMORY_USAGE " )
LDFLAGS += -g3
LDFLAGS += $(shell echo "$(CFLAGS) $(EXTRA_CFLAGS)" | grep -q "DNO_DYNPLUGIN" || echo "-Wl,-export-dynamic -ldl" )
LDFLAGS += $(shell echo "$(CFLAGS) $(EXTRA_CFLAGS)" | grep -q "DPROFILING" && echo "-pg -lc" )
LDFLAGS += -lz -lm
LDFLAGS += $(shell echo "$(CFLAGS) $(EXTRA_CFLAGS)" | grep -q "CYASSL" && echo "-lcyassl" || echo "-lpolarssl")
SBINDIR = $(INSTALL_PREFIX)/usr/sbin
SRC_FILES= "\(\.c\)\|\(\.h\)\|\(Makefile\)\|\(INSTALL\)\|\(LIESMICH\)\|\(README\)\|\(THANKS\)\|\(./posix\)\|\(./linux\)\|\(./man\)\|\(./doc\)"
SRC_C = bmx.c node.c crypt.c sec.c msg.c z.c metrics.c iptools.c tools.c plugin.c list.c allocate.c avl.c hna.c control.c schedule.c ip.c prof.c
SRC_H = bmx.h node.h crypt.h sec.h msg.h z.h metrics.h iptools.h tools.h plugin.h list.h allocate.h avl.h hna.h control.h schedule.h ip.h prof.h
SRC_C += $(shell echo "$(CFLAGS) $(EXTRA_CFLAGS)" | grep -q "DTRAFFIC_DUMP" && echo dump.c )
SRC_H += $(shell echo "$(CFLAGS) $(EXTRA_CFLAGS)" | grep -q "DTRAFFIC_DUMP" && echo dump.h )
OBJS= $(SRC_C:.c=.o)
#
#
PACKAGE_NAME= bmx6
BINARY_NAME= bmx6
include Common.mk
all:
@@ -120,7 +25,6 @@ libs: all
$(MAKE) -C lib all CORE_CFLAGS='$(CFLAGS)'
$(BINARY_NAME): $(OBJS) Makefile
$(CC) $(OBJS) -o $@ $(LDFLAGS) $(EXTRA_LDFLAGS)
@@ -132,14 +36,11 @@ $(BINARY_NAME): $(OBJS) Makefile
strip: all
strip $(BINARY_NAME)
strip $(BINARY_NAME)
strip_libs: all libs
$(MAKE) -C lib strip
install: all
mkdir -p $(SBINDIR)
install -m 0755 $(BINARY_NAME) $(SBINDIR)
@@ -148,7 +49,6 @@ install_libs: all
$(MAKE) -C lib install CORE_CFLAGS='$(CFLAGS)'
clean:
rm -f $(BINARY_NAME) *.o posix/*.o linux/*.o cyassl/*.o

View File

@@ -12,10 +12,10 @@ The following intro provides kind of tutorial to get started.
* [Autoconfiguration](#address-auto-and-manual-configuration)
* [Unicast Host Network Announcements (UHNA)](#unicast-host-network-announcements-uhna)
* [Tunnel Announcements](#tunnel-announcements)
* [Bmx6 Plugins](#bmx6-plugins)
* [Bmx6 Plugins](#bmx6-plugins)
* [Config Plugin](#config-plugin)
* [Json Plugin](#json-plugin)
* [SMS Plugin](#sms-plugin)
* [SMS Plugin](#sms-plugin)
* [Table plugin](#table-plugin)
* [Quagga Plugin](#quagga-plugin)
@@ -23,7 +23,7 @@ The following intro provides kind of tutorial to get started.
Note: This document is written using Markdown syntax. Modifications should be
synced via README.md file in bmx6 repositories [bmx6.net][bmx6] and [github.com][github].
Nice syntax examples are [here][syntax].
[bmx6]: http://bmx6.net
[github]: https://github.com/axn/bmx6
[syntax]: http://daringfireball.net/projects/markdown/syntax.text
@@ -39,18 +39,19 @@ The following tools are needed to obtain, compile, and install bmx6:
* make
The following Linux-kernel modules are needed (depending on used bmx6 features)
* ipv6
* ipv6
* tunnel6
* ip6_tunnel
The polorssl crypto library is needed for cryptographic operations:
Tested with debian and cyassl-2.8.0:
Tested with debian and polarssl-1.3.3:
<pre>
wget https://polarssl.org/code/releases/polarssl-1.3.3-gpl.tgz
tar xzvf polarssl-1.3.3-gpl.tgz
cd polarssl-1.3.3
make
make install
sudo make install
# compile bmx6 with: make EXTRA_CFLAGS="-DCRYPTLIB=POLARSSL1_3_3"
</pre>
@@ -156,13 +157,13 @@ Status, network, and statistic information are accessible with dedicated paramet
<pre>
root@mlc1001:~# bmx6 -c status
version compatibility codeVersion globalId primaryIp myLocalId uptime cpu nodes
version compatibility codeVersion globalId primaryIp myLocalId uptime cpu nodes
BMX6-0.1-alpha 16 9 mlc1001.7A7422752001EC4AC4C8 fd66:66:66:0:a2cd:efff:fe10:101 24100101 0:00:40:37 0.1 4
</pre>
So apart from version, compatibility number, and code, the status reveals the daemon's [Global ID](wiki#global-id) and [Local ID](wiki#local-id), its primary (self-configured) IPv6 address, the time since when it is running (40 minutes), its current cpu consumption (0.1%) and the total number of 4 learned nodes in the network (including itself).
These desired types can be combined. Also the above given example shows kind of shortcut.
These desired types can be combined. Also the above given example shows kind of shortcut.
The long argument would be:
`bmx6 connect show=status`. A more informative case using the long form would be:
@@ -180,10 +181,10 @@ mlc1000.0AE58311046412F248CD fe80::a2cd:efff:fe10:1 eth1 100 100 1
mlc1002.91DCF042934B5913BB00 fe80::a2cd:efff:fe10:201 eth1 100 100 1 2 1 BB100201
originators:
globalId blocked primaryIp routes viaIp viaDev metric lastDesc lastRef
mlc1000.0AE58311046412F248CD 0 fd66:66:66:0:a2cd:efff:fe10:1 1 fe80::a2cd:efff:fe10:1 eth1 999M 3193 3
mlc1000.0AE58311046412F248CD 0 fd66:66:66:0:a2cd:efff:fe10:1 1 fe80::a2cd:efff:fe10:1 eth1 999M 3193 3
mlc1001.7A7422752001EC4AC4C8 0 fd66:66:66:0:a2cd:efff:fe10:101 0 :: --- 128G 3197 0
mlc1002.91DCF042934B5913BB00 0 fd66:66:66:0:a2cd:efff:fe10:201 1 fe80::a2cd:efff:fe10:201 eth1 999M 3196 3
mlc1003.09E796BC491D386248C3 0 fd66:66:66:0:a2cd:efff:fe10:301 1 fe80::a2cd:efff:fe10:201 eth1 576M 22 3
mlc1002.91DCF042934B5913BB00 0 fd66:66:66:0:a2cd:efff:fe10:201 1 fe80::a2cd:efff:fe10:201 eth1 999M 3196 3
mlc1003.09E796BC491D386248C3 0 fd66:66:66:0:a2cd:efff:fe10:301 1 fe80::a2cd:efff:fe10:201 eth1 576M 22 3
</pre>
Only if relevant information for a requested type is available it will be shown.
@@ -282,19 +283,19 @@ Checking new status of interfaces, links, and originator:
<pre>
root@mlc1001:~# bmx6 -cd8
status:
version compatibility codeVersion globalId primaryIp myLocalId uptime cpu nodes
BMX6-0.1-alpha 16 9 mlc1001.7A7422752001EC4AC4C8 fd66:66:66:0:a2cd:efff:fe10:102 06100101 0:02:26:00 0.1 4
version compatibility codeVersion globalId primaryIp myLocalId uptime cpu nodes
BMX6-0.1-alpha 16 9 mlc1001.7A7422752001EC4AC4C8 fd66:66:66:0:a2cd:efff:fe10:102 06100101 0:02:26:00 0.1 4
interfaces:
devName state type rateMin rateMax llocalIp globalIp multicastIp primary
eth2 UP ethernet 100M 100M fe80::a2cd:efff:fe10:102/64 fd66:66:66:0:a2cd:efff:fe10:102/64 ff02::2 1
devName state type rateMin rateMax llocalIp globalIp multicastIp primary
eth2 UP ethernet 100M 100M fe80::a2cd:efff:fe10:102/64 fd66:66:66:0:a2cd:efff:fe10:102/64 ff02::2 1
links:
globalId llocalIp viaDev rxRate txRate bestTxLink routes wantsOgms nbLocalId
mlc1000.0AE58311046412F248CD fe80::a2cd:efff:fe10:2 eth2 89 88 1 3 1 9B100001
globalId llocalIp viaDev rxRate txRate bestTxLink routes wantsOgms nbLocalId
mlc1000.0AE58311046412F248CD fe80::a2cd:efff:fe10:2 eth2 89 88 1 3 1 9B100001
originators:
globalId blocked primaryIp routes viaIp viaDev metric lastDesc lastRef
mlc1000.0AE58311046412F248CD 0 fd66:66:66:0:a2cd:efff:fe10:1 1 fe80::a2cd:efff:fe10:2 eth2 81757K 18 0
mlc1001.7A7422752001EC4AC4C8 0 fd66:66:66:0:a2cd:efff:fe10:102 0 :: --- 128G 80 0
mlc1002.91DCF042934B5913BB00 0 fd66:66:66:0:a2cd:efff:fe10:201 1 fe80::a2cd:efff:fe10:2 eth2 83620K 14 4
globalId blocked primaryIp routes viaIp viaDev metric lastDesc lastRef
mlc1000.0AE58311046412F248CD 0 fd66:66:66:0:a2cd:efff:fe10:1 1 fe80::a2cd:efff:fe10:2 eth2 81757K 18 0
mlc1001.7A7422752001EC4AC4C8 0 fd66:66:66:0:a2cd:efff:fe10:102 0 :: --- 128G 80 0
mlc1002.91DCF042934B5913BB00 0 fd66:66:66:0:a2cd:efff:fe10:201 1 fe80::a2cd:efff:fe10:2 eth2 83620K 14 4
mlc1003.09E796BC491D386248C3 0 fd66:66:66:0:a2cd:efff:fe10:301 1 fe80::a2cd:efff:fe10:2 eth2 81488K 9 0
</pre>
@@ -346,10 +347,10 @@ the EUI64 suffix (the suffix creation is currently reconsidered and may change s
The same first 56 bits but extended with 0xff00 are also used to create tunnel interfaces.
There are different options to controll the auto configuration.
1. A different auto-configuration prefix can be used using the <pre> --ipAutoPrefix </pre>
1. A different auto-configuration prefix can be used using the <pre> --ipAutoPrefix </pre>
option given with a /56 prefix.
2. Auto configuratin can be disabled using the <pre> --globalPrefix </pre> option.
2. Auto configuratin can be disabled using the <pre> --globalPrefix </pre> option.
Then bmx6 checks if an ip in this range is alredy configured on the interfaces and uses it.
If no IP is configured in the given range then the inteface will NOT be used.
@@ -431,7 +432,7 @@ Therefore, each announcements message is decorated with a route-type field indic
### Tunnel requirements ###
The following Linux-kernel modules are needed for tunnel-based overlay networking:
* ipv6
* ipv6
* tunnel6
* ip6_tunnel
@@ -496,11 +497,11 @@ With the above configured tunnel selection policy, tunnels are selected in the f
1. prefix-length of announced tunnels (networks that are more specific than others).
2. the resulting tunnelMetric (combination of the advertised bandwidth, path metric in the bmx6 cloud, and locally specified prefereces like hysteresis or bonus)
The disadvantage of this simple config is that other nodes can easily redirect your tunnel selections
to specific networks by announcing more precise tunnel networks (larger prefix length).
The disadvantage of this simple config is that other nodes can easily redirect your tunnel selections
to specific networks by announcing more precise tunnel networks (larger prefix length).
To prevent this, the selection policy can be split into several and more precise search directives.
Imagine the following address assignment policy for IPv4 tunnel addresses in a mesh cloud (the general
Imagine the following address assignment policy for IPv4 tunnel addresses in a mesh cloud (the general
idea can be straight translated to IPv6).
* Nodes in the mesh cloud announce their private and local address ranges with a prefix length of 24 and somewhere in the range of 10.254.0.0/16.
@@ -531,13 +532,13 @@ idea can be straight translated to IPv6).
* The default route announcements from two well known GWs (with hostname pepe and paula) should be strictly preferred over unknown GWs.
* So, if available, move them to new table (with lower priority than main and higher priority than used for the backup tunnel rule configured above)
<pre>
bmx6 -c tunOut=v4DefaultPepe /network=0.0.0.0/0 /maxPrefixLen=0 /name=pepe /hysteresis=30 /tableRule=40000/140
bmx6 -c tunOut=v4DefaultPaula /network=0.0.0.0/0 /maxPrefixLen=0 /name=paula /hysteresis=30 /tableRule=40000/140
bmx6 -c tunOut=v4DefaultPepe /network=0.0.0.0/0 /maxPrefixLen=0 /gwName=pepe /hysteresis=30 /tableRule=40000/140
bmx6 -c tunOut=v4DefaultPaula /network=0.0.0.0/0 /maxPrefixLen=0 /gwName=paula /hysteresis=30 /tableRule=40000/140
</pre>
* Finally, GW Paula turned out to be more stable. Therefore I want to prefer GW Paula over Pepe:
<pre>
bmx6 -c tunOut=v4DefaultPaula /network=0.0.0.0/0 /maxPrefixLen=0 /name=paula /hysteresis=30 /bonus=100
bmx6 -c tunOut=v4DefaultPaula /network=0.0.0.0/0 /maxPrefixLen=0 /gwName=paula /hysteresis=30 /bonus=100
</pre>
#### Gateway Nodes ####
@@ -576,7 +577,7 @@ These requirements are described in the corresponding plugin section.
#### Requirements ####
uci libs are needed for the bmx6-config plugin.
To install it do:
To install try (old version):
<pre>
wget http://downloads.openwrt.org/sources/uci-0.7.5.tar.gz
tar xzvf uci-0.7.5.tar.gz
@@ -584,13 +585,15 @@ cd uci-0.7.5
make
sudo make install
</pre>
or check: http://www.wakoond.hu/2013/06/using-uci-on-ubuntu.html
Depending on your system there happens to be an error during compilation.
Then edit cli.c and change line 465 to: char *argv[MAX_ARGS+2];
#### Compile and Install ####
<pre>
make -C lib/bmx6_uci_config/
make -C lib/bmx6_uci_config/
sudo make -C lib/bmx6_uci_config/ install
</pre>
@@ -621,7 +624,7 @@ cd json-c..
To compile and install only the bmx6 json plugins:
<pre>
make -C lib/bmx6_json/
make -C lib/bmx6_json/
sudo make -C lib/bmx6_json/ install
</pre>
@@ -720,7 +723,7 @@ the file lib/bmx6_quagga/patches/README in the bmx6 sources.
To compile and install the bmx6 part of the quagga plugin simply do:
<pre>
make -C lib/bmx6_quagga/
make -C lib/bmx6_quagga/
sudo make -C lib/bmx6_quagga/ install
</pre>

View File

@@ -209,10 +209,12 @@ void *_debugMalloc(uint32_t length, int32_t tag, uint8_t reset)
if (!length)
return NULL;
if (reset)
memory = calloc(1, length + sizeof(struct chunkHeader) + sizeof(MAGIC_TRAILER_T));
else
if (reset) {
memory = malloc(length + sizeof(struct chunkHeader) + sizeof(MAGIC_TRAILER_T));
memset(memory, 0, length + sizeof(struct chunkHeader) + sizeof(MAGIC_TRAILER_T));
} else {
memory = malloc(length + sizeof(struct chunkHeader) + sizeof(MAGIC_TRAILER_T));
}
if (memory == NULL)
{
@@ -338,7 +340,9 @@ void _debugFree(void *memoryParameter, int tag)
#endif //#ifdef MEMORY_USAGE
free(chunkHeader);
if (!terminating)
free(chunkHeader);
}
@@ -349,7 +353,9 @@ void * _malloc( size_t length ) {
}
void * _calloc( size_t length ) {
return calloc( 1, length );
void *mem = malloc( length );
memset( mem, 0, length);
return mem;
}
void * _realloc( void *mem, size_t length ) {
@@ -357,8 +363,9 @@ void * _realloc( void *mem, size_t length ) {
}
void _free( void *mem ) {
free( mem );
if (!terminating)
free( mem );
}
#endif
#endif

View File

@@ -29,7 +29,7 @@ extern uint32_t debugMalloc_objects;
#ifdef DEBUG_MALLOC
// currently used memory tags: -300000, -300001 .. -300664
// currently used memory tags: -300000, -300001 .. -300768
#define debugMalloc( length,tag ) _debugMalloc( (length), (tag), 0 )
#define debugMallocReset( length,tag ) _debugMalloc( (length), (tag), 1 )
#define debugRealloc( mem,length,tag ) _debugRealloc( (mem), (length), (tag) )

6
avl.c
View File

@@ -267,6 +267,7 @@ struct avl_node *avl_rotate_double(struct avl_node *root, int dir)
void avl_insert(struct avl_tree *tree, void *node, int32_t tag)
{
ASSERTION(-502234, !avl_find_item(tree, AVL_ITEM_KEY(tree, node)));
struct avl_node *new = NULL;
@@ -363,6 +364,7 @@ void avl_insert(struct avl_tree *tree, void *node, int32_t tag)
assertion(-502005, (!new->left || avl_next(tree, AVL_ITEM_KEY(tree, new->left->item))==new));
assertion(-502006, (!new->right || avl_next(tree, AVL_ITEM_KEY(tree, new->item))==new->right));
#endif
ASSERTION(-502236, avl_find_item(tree, AVL_ITEM_KEY(tree, node)));
return;
}
@@ -381,7 +383,7 @@ void *avl_remove(struct avl_tree *tree, void *key, int32_t tag)
return NULL;
while (1) {
/*
dbgf_all(DBGT_INFO, "tree.items=%d it->item=%p memcmp(it,key)=%d link[0]=%p link[1]=%p memcmp(link[0],key)=%d memcmp(link[1],key)=%d",
tree->items, it->item,
memcmp(AVL_NODE_KEY(tree, it), key, tree->key_size),
@@ -389,7 +391,7 @@ void *avl_remove(struct avl_tree *tree, void *key, int32_t tag)
(it->down[0] ? memcmp(AVL_NODE_KEY(tree, it->down[0]), key, tree->key_size) : -1),
(it->down[1] ? memcmp(AVL_NODE_KEY(tree, it->down[1]), key, tree->key_size) : -1)
);
*/
if (!(
(cmp = memcmp(AVL_NODE_KEY(tree, it), key, tree->key_size)) ||
(it->down[0] && !memcmp(AVL_NODE_KEY(tree, it->down[0]), key, tree->key_size))))

822
bmx.c

File diff suppressed because it is too large Load Diff

149
bmx.h
View File

@@ -17,6 +17,8 @@
* 02110-1301, USA
*/
#include <sys/time.h>
#include <time.h>
#include <stdint.h>
#include <sys/types.h>
@@ -33,6 +35,18 @@ typedef int8_t IDM_T; // smallest int which size does NOT matter
* dont touch this for compatibility reasons:
*/
/* Android has these under a different name since the NDK target android-8:
*
* glibc defines dprintf(int, const char*, ...), which is poorly named
* and likely to conflict with locally defined debugging printfs
* fdprintf is a better name, and some programs that use fdprintf use a
* #define fdprintf dprintf for compatibility
*/
#ifdef __ANDROID__
#define dprintf fdprintf
#define vdprintf vfdprintf
#endif
#define BMX_BRANCH "BMX6"
#define BRANCH_VERSION "0.1-alpha" //put exactly one distinct word inside the string like "0.3-pre-alpha" or "0.3-rc1" or "0.3"
@@ -54,12 +68,12 @@ typedef int8_t IDM_T; // smallest int which size does NOT matter
#define ARG_COMPATIBILITY "compatibility"
extern int32_t my_compatibility;
#define MIN_PETTINESS 0
#define MAX_PETTINESS 1
#define DEF_PETTINESS 0
#define ARG_PETTINESS "pettiness"
#define MIN_CONFORMANCE_TOLERANCE 0
#define MAX_CONFORMANCE_TOLERANCE 1
#define DEF_CONFORMANCE_TOLERANCE 0
#define ARG_CONFORMANCE_TOLERANCE "conformanceTolerance"
extern int32_t my_pettiness;
extern int32_t my_conformance_tolerance;
extern uint32_t my_runtimeKey;
#define MAX_HOSTNAME_LEN 32
@@ -86,17 +100,8 @@ extern uint32_t rev_u32;
#define IPX_STR_LEN INET6_ADDRSTRLEN
#define IPX_PREFIX_STR_LEN (INET6_ADDRSTRLEN + 4)
typedef uint16_t DEVADV_SQN_T;
#define DEVADV_SQN_DISABLED 0 // dev-adv are not provided by this node!
#define DEVADV_SQN_DAD_RANGE 256
#define DEVADV_SQN_MAX ((DEVADV_SQN_T)-1)
typedef uint8_t DEVADV_IDX_T;
//#define DEVADV_IDX_BIT_SIZE (8*sizeof(DEVADV_IDX_T))
#define DEVADV_IDX_INVALID 0
#define DEVADV_IDX_ALL 0
#define DEVADV_IDX_MIN 1
#define DEVADV_IDX_MAX ((DEVADV_IDX_T)-1)
typedef struct in6_addr LOCAL_IP_T;
typedef uint32_t IP4_T;
@@ -110,11 +115,6 @@ struct net_key {
IPX_T ip; //address
} __attribute__((packed));
struct dev_ip_key {
IPX_T ip; // copy of dev->if_llocal_addr->ip_addr
DEVADV_IDX_T idx;
} __attribute__((packed));
typedef union {
uint8_t u8[GEN_ADDR_LEN];
@@ -153,35 +153,19 @@ extern const struct net_key ZERO_NET6_KEY;
#define ARG_HOSTNAME "hostname"
#define MY_DESC_CAPABILITIES_CV16 0x0200 //capability flag for compatibility with CV16 txInterval field
#define MY_DESC_CAPABILITIES (MY_DESC_CAPABILITIES_CV16 | 0)
extern uint16_t my_desc_capabilities;
#define MIN_TX_INTERVAL 35
#define MAX_TX_INTERVAL 10000 // < U16_MAX due to metricalgo->ogm_interval field
#define DEF_TX_INTERVAL 500
#define ARG_TX_INTERVAL "txInterval"
extern int32_t my_tx_interval;
#define DEF_TX_DELAY ((2*my_tx_interval) + rand_num(my_tx_interval))
#define ARG_OGM_INTERVAL "ogmInterval"
#define DEF_OGM_INTERVAL 5000
#define MIN_OGM_INTERVAL 200
#define MAX_OGM_INTERVAL 60000 // 60000 = 1 minutes
extern int32_t my_ogm_interval;
#define DEF_DAD_TO 20000//(MAX_OGM_INTERVAL + MAX_TX_INTERVAL)
#define MIN_DAD_TO 100
#define MAX_DAD_TO 360000000
@@ -206,6 +190,9 @@ typedef uint16_t SQN_T;
#define SQN_MAX ((SQN_T)-1)
#define MAX_SQN_RANGE 8192 // the maxumim of all .._SQN_RANGE ranges, should never be more than SQN_MAX/4
typedef uint32_t PKT_SQN_T;
#define PKT_SQN_MAX ((PKT_SQN_T)-1)
// OGMs:
typedef uint16_t OGM_SQN_T;
@@ -217,37 +204,23 @@ typedef uint16_t OGM_SQN_T;
#define OGM_IIDOFFST_MASK ((1<<OGM_IIDOFFST_BIT_SIZE)-1)
// aggregations of OGMs:
typedef uint8_t AGGREG_SQN_T;
#define AGGREG_SQN_BIT_SIZE (8)
typedef uint16_t AGGREG_SQN_T;
#define AGGREG_SQN_BIT_SIZE (16)
#define AGGREG_SQN_MASK ((1<<AGGREG_SQN_BIT_SIZE)-1)
#define AGGREG_SQN_MAX AGGREG_SQN_MASK
#define AGGREG_SQN_CACHE_RANGE 64
#define AGGREG_SQN_CACHE_WARN (AGGREG_SQN_CACHE_RANGE/2)
#define AGGREG_ARRAY_BYTE_SIZE (AGGREG_SQN_CACHE_RANGE/8)
typedef uint8_t OGM_DEST_T;
#define OGM_DEST_BIT_SIZE (8)
#define OGM_DEST_MASK ((1<<OGM_DEST_BIT_SIZE)-1)
#define OGM_DEST_MAX OGM_DEST_MASK
#define OGM_DEST_ARRAY_BIT_SIZE (1<<OGM_DEST_BIT_SIZE)
#define LOCALS_MAX (1<<OGM_DEST_BIT_SIZE) // because each local needs a bit to be indicated in the ogm.dest_field
#define AGGREG_SQN_CACHE_MASK 0xFF
#define AGGREG_SQN_CACHE_RANGE (AGGREG_SQN_CACHE_MASK+1) //32
typedef uint32_t PKT_SQN_T;
#define PKT_SQN_MAX ((PKT_SQN_T)-1)
typedef uint16_t LINKADV_SQN_T;
#define LINKADV_SQN_DAD_RANGE 256
#define LINKADV_SQN_MAX ((LINKADV_SQN_T)-1)
typedef uint16_t INT_NEIGH_ID_T;
#define INT_NEIGH_ID_BIT_SIZE (12)
#define LOCALS_MAX (1<<INT_NEIGH_ID_BIT_SIZE) // because each local needs a bit to be indicated in the ogm.dest_field
@@ -272,15 +245,15 @@ typedef uint16_t HELLO_SQN_T;
typedef uint32_t BURST_SQN_T;
// descriptions
typedef uint32_t DESC_SQN_T;
#define DESC_SQN_SAVE_INTERVAL 100
#define DESC_SQN_REBOOT_ADDS 10
#define ARG_DSQN_PATH "descSqnPath"
#define DEF_DSQN_PATH "/etc/bmx6/descSqn"
@@ -299,8 +272,7 @@ typedef uint32_t DESC_SQN_T;
#define MAX_UDPD_SIZE 1400
#define MAX_UDPD_SIZE (1280 /*min IPv6 MTU*/ - sizeof(struct ip6_hdr) - sizeof(struct udphdr))
@@ -337,11 +309,10 @@ typedef uint32_t DESC_SQN_T;
#define ARG_SHOW "show"
#define ARG_ORIGINATORS "originators"
#define ARG_STATUS "status"
#define ARG_LINKS "links"
#define ARG_CREDITS "credits"
#define ARG_DESCREFS "references"
#define MAX_DBG_STR_SIZE 1500
#define MAX_DBG_STR_SIZE 2000
#define OUT_SEQNO_OFFSET 1
enum NoYes {
@@ -375,6 +346,9 @@ enum ADGSN {
#define XMAX( a, b ) ( (a>b) ? (a) : (b) )
#define XMIN( a, b ) ( (a<b) ? (a) : (b) )
#define XOR2( a, b ) ( (a) ? (a) : (b) )
#define XOR3( a, b, c ) ( (a) ? (a) : ( (b) ? (b) : (c) ) )
#define XOR4( a, b, c, d ) ( (a) ? (a) : ( (b) ? (b) : ( (c) ? (c) : (d) ) ) )
#define U64_MAX ((uint64_t)(-1))
#define U32_MAX ((uint32_t)(-1))
@@ -525,12 +499,12 @@ extern struct avl_tree status_tree;
int16_t field_format_get_items(const struct field_format *format);
int64_t field_get_value(const struct field_format *format, uint16_t min_msg_size, uint8_t *data, uint32_t pos_bit, uint32_t bits);
int64_t field_get_value(const struct field_format *format, uint32_t min_msg_size, uint8_t *data, uint32_t pos_bit, uint32_t bits);
char *field_dbg_value(const struct field_format *format, uint16_t min_msg_size, uint8_t *data, uint32_t pos_bit, uint32_t bits);
char *field_dbg_value(const struct field_format *format, uint32_t min_msg_size, uint8_t *data, uint32_t pos_bit, uint32_t bits);
uint32_t fields_dbg_lines(struct ctrl_node *cn, uint16_t relevance, uint16_t data_size, uint8_t *data,
uint16_t min_msg_size, const struct field_format *format);
uint32_t fields_dbg_lines(struct ctrl_node *cn, uint16_t relevance, uint32_t data_size, uint8_t *data,
uint32_t min_msg_size, const struct field_format *format);
uint32_t field_iterate(struct field_iterator *it);
@@ -564,6 +538,7 @@ enum {
#define goto_error( where, what ) do { goto_error_code=what; goto where; }while(0)
#define goto_error_return( where, what, ret ) do { goto_error_code=what; goto_error_ret=ret; goto where; }while(0)
#ifdef NO_ASSERTIONS
#define paranoia( ... )
@@ -578,7 +553,7 @@ enum {
/*
* ASSERTION / PARANOIA ERROR CODES:
* Negative numbers are used as SIGSEV error codes !
* Currently used numbers are: -500000 -500001 ... -502230
* Currently used numbers are: -500000 -500001 ... -502500
*/
//#define paranoia( code , problem ) do { if ( (problem) ) { cleanup_all( code ); } }while(0)
@@ -605,6 +580,11 @@ enum {
#define EXITERROR( code , condition )
#endif
#define TEST_FUNCTION(X) ( ((void(*)(void*))&(X)) != NULL )
#define TEST_VALUE(X) (((uint32_t)X) != 1234543210)
#define TEST_STRUCT(X) (sizeof(X) > 0)
#define TEST_VARIABLE(X) ((void*)&X != NULL )
#endif//NO_ASSERTIONS
@@ -627,22 +607,10 @@ enum {
#define FUNCTION_CALL_BUFFER_SIZE 64
//extern char* function_call_buffer_name_array[FUNCTION_CALL_BUFFER_SIZE];
//extern TIME_T function_call_buffer_time_array[FUNCTION_CALL_BUFFER_SIZE];
//extern uint8_t function_call_buffer_pos;
void trace_function_call(const char *);
#define TRACE_FUNCTION_CALL trace_function_call ( __FUNCTION__ )
extern uint32_t test_magic_number;
//#define TEST_FUNCTION(X) ( ((void(*)(void*))&trace_function_call) != ((void(*)(void*))&(X)) )
#define TEST_FUNCTION(X) ( ((void(*)(void*))&(X)) != NULL )
#define TEST_VALUE(X) (((uint32_t)X) != test_magic_number)
#define TEST_STRUCT(X) (sizeof(X) > 0)
#define TEST_VARIABLE(X) ((void*)&X != NULL )
#else
#define TRACE_FUNCTION_CALL
@@ -656,7 +624,7 @@ void cleanup_all( int32_t status );
char *get_human_uptime( uint32_t reference );
DESC_SQN_T getDescriptionSqn( char* newPath, uint8_t ass );
DESC_SQN_T newDescriptionSqn( char* newPath, uint8_t ass );
/***********************************************************
@@ -668,5 +636,4 @@ DESC_SQN_T getDescriptionSqn( char* newPath, uint8_t ass );
IDM_T validate_param(int32_t probe, int32_t min, int32_t max, char *name);
int32_t opt_status(uint8_t cmd, uint8_t _save, struct opt_type *opt, struct opt_parent *patch, struct ctrl_node *cn);
int32_t opt_update_description(uint8_t cmd, uint8_t _save, struct opt_type *opt, struct opt_parent *patch, struct ctrl_node *cn);
int32_t opt_purge_originators(uint8_t cmd, uint8_t _save, struct opt_type *opt, struct opt_parent *patch, struct ctrl_node *cn);
int32_t opt_flush_all(uint8_t cmd, uint8_t _save, struct opt_type *opt, struct opt_parent *patch, struct ctrl_node *cn);

1057
content.c Normal file

File diff suppressed because it is too large Load Diff

127
content.h Normal file
View File

@@ -0,0 +1,127 @@
/*
* Copyright (c) 2010 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
*/
#include <stdint.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <linux/if.h>
//TODO: set REQ_TO to 1 (in a non-packet-loss testenvironment this may be set to 1000 for testing)
#define DEF_TX_CONTENT_REQ_TO ((DEF_TX_MIN_INTERVAL*3)/2)
#define DEF_TX_CONTENT_ADV_TO 200
#define MAX_DESC_TYPE_CONTENT_OCCURANCE 10
#define ARG_CONTENTS "contents"
#define DEF_UNSOLICITED_CONTENT_ADVS 1
#define MIN_UNSOLICITED_CONTENT_ADVS 0
#define MAX_UNSOLICITED_CONTENT_ADVS 1
#define ARG_UNSOLICITED_CONTENT_ADVS "unsolicitedContentAdvs"
extern struct avl_tree content_tree;
#define DSC_MSG_CHASH_FORMAT { \
{FIELD_TYPE_STRING_BINARY, -1, 160, 1, FIELD_RELEVANCE_LOW, "chash"}, \
FIELD_FORMAT_END }
struct dsc_msg_chash {
SHA1_T chash; // hash over frame data (without frame-header, but including hdr_content_adv and all body data) as transmitted via content_adv
} __attribute__((packed));
struct dsc_hdr_chash {
SHA1_T expanded_chash; // hash over zero-frame_hdr_content_adv and frame body data with all resolved, re-assembled, uncompressed.
// So for a dsc_hdr/msg_chash frame with a single uncompressed and non-nested chash this would equal the chash of dsc_msg_chash which MUST be omitted.
// Otherwise it provides a checksum over the final data.
union {
struct {
#if __BYTE_ORDER == __LITTLE_ENDIAN
unsigned int gzip : 1; // only contents are compressed, all resolved and re-assembled contents are compressed (NOT the hashes)
unsigned int maxNesting : 2;
unsigned int expanded_type : 5;
unsigned int expanded_length : 24;
#elif __BYTE_ORDER == __BIG_ENDIAN
unsigned int expanded_length : 24;
unsigned int expanded_type : 5;
unsigned int maxNesting : 2;
unsigned int gzip : 1;
#else
#error "Please fix <bits/endian.h>"
#endif
} __attribute((packed)) i;
uint32_t u32;
} u;
struct dsc_msg_chash msg[];
} __attribute__((packed));
struct frame_msg_content_adv {
SHA1_T chash; // hash over frame data (without frame-header, but including hdr_content_adv and all body data) as transmitted via content_adv
} __attribute__((packed));
struct frame_hdr_content_adv {
#if __BYTE_ORDER == __LITTLE_ENDIAN
unsigned int gzip : 1; // only contents are compressed, all resolved and re-assembled contents are compressed (NOT the hashes)
unsigned int maxNesting : 2;
unsigned int reserved : 5;
#elif __BYTE_ORDER == __BIG_ENDIAN
unsigned int reserved : 5;
unsigned int maxNesting : 2;
unsigned int gzip : 1;
#else
#error "Please fix <bits/endian.h>"
#endif
uint8_t content[]; //hashes if nested, otherwise raw content data
} __attribute__((packed));
// for FRAME_TYPE_REF_REQ:
struct msg_content_req {
SHA1_T chash;
} __attribute__((packed));
//TODO: Use this destination header!!!
struct hdr_content_req { // 20 bytes
GLOBAL_ID_T dest_kHash;
struct msg_content_req msg[];
} __attribute__((packed));
void descContent_destroy(struct desc_content *dc);
struct desc_content* descContent_create(uint8_t *dsc, uint32_t dlen, struct key_node *key);
struct content_node * content_get(SHA1_T *chash);
void *contents_data(struct desc_content *contents, uint8_t type);
uint32_t contents_dlen(struct desc_content *contents, uint8_t type);
struct content_node * content_add_hash(SHA1_T *chash);
struct content_node * content_add_body(uint8_t *body, uint32_t body_len, uint8_t compressed, uint8_t nested, uint8_t force);
int32_t create_chash_tlv(struct tlv_hdr *tlv, uint8_t *f_data, uint32_t f_len, uint8_t f_type, uint8_t fzip, uint8_t level);
void content_purge_unused(struct content_node *onlyCn);
void init_content(void);

View File

@@ -37,11 +37,13 @@
#include "crypt.h"
#include "avl.h"
#include "node.h"
#include "link.h"
#include "ip.h"
#include "plugin.h"
#include "schedule.h"
#include "tools.h"
#include "allocate.h"
#include "hna.h"
#define CODE_CATEGORY_NAME "control"
@@ -2630,6 +2632,8 @@ int32_t opt_show_parameter(uint8_t cmd, uint8_t _save, struct opt_type *opt, str
struct opt_type *opt = NULL;
dbg_printf(cn, "PARAMETERS:\n");
while ((opt = list_iterate(&opt_list, opt))) {
struct opt_parent *p = NULL;
@@ -2638,13 +2642,18 @@ int32_t opt_show_parameter(uint8_t cmd, uint8_t _save, struct opt_type *opt, str
struct opt_child *c = NULL;
assertion(-501231, (opt->name && opt->cfg_t != A_ARG));
dbg_printf(cn, " %-22s %-20s %s%s\n", opt->name, p->val,
char pdef[14];
sprintf(pdef, "%d", opt->idef);
dbg_printf(cn, " %-22s %-20s (%s) %s%s\n", opt->name, p->val, (opt->sdef ? opt->sdef : pdef),
(p->ref ? "resolved from " : ""), (p->ref ? p->ref : ""));
while ((c = list_iterate(&p->childs_instance_list, c))) {
dbg_printf(cn, " %s%-18s %-20s %s%s\n",
LONG_OPT_ARG_DELIMITER_STR, c->opt->name, c->val,
char cdef[14];
sprintf(cdef, "%d", c->opt->idef);
dbg_printf(cn, " %s%-18s %-20s (%s) %s%s\n",
LONG_OPT_ARG_DELIMITER_STR, c->opt->name, c->val, (c->opt->sdef ? c->opt->sdef : cdef),
(c->ref ? "resolved from " : ""), (c->ref ? c->ref : ""));
}
}
@@ -2694,6 +2703,7 @@ int32_t opt_debug(uint8_t cmd, uint8_t _save, struct opt_type *opt, struct opt_p
check_apply_parent_option(ADD, OPT_APPLY, 0, get_option(0, 0, ARG_SHOW), ARG_STATUS, cn);
check_apply_parent_option(ADD, OPT_APPLY, 0, get_option(0, 0, ARG_SHOW), ARG_INTERFACES, cn);
check_apply_parent_option(ADD, OPT_APPLY, 0, get_option(0, 0, ARG_SHOW), ARG_LINKS, cn);
check_apply_parent_option(ADD, OPT_APPLY, 0, get_option(0, 0, ARG_SHOW), ARG_CREDITS, cn);
check_apply_parent_option(ADD, OPT_APPLY, 0, get_option(0, 0, ARG_SHOW), ARG_ORIGINATORS, cn);
} else if ( ival == DBGL_PROFILE ) {
@@ -2739,7 +2749,7 @@ int32_t opt_help(uint8_t cmd, uint8_t _save, struct opt_type *opt, struct opt_pa
prog_name, ARG_RESET_CHAR , ARG_RESET_CHAR);
dbg_printf(cn, " e.g. %s %s=eth1 %s=wlan0 d=3\n", prog_name, ARG_DEV, ARG_DEV);
dbg_printf(cn, " e.g. %s -c %s=%s %s=%s %s=%s %s=%s\n",
prog_name, ARG_SHOW, ARG_STATUS, ARG_SHOW, ARG_INTERFACES, ARG_SHOW, ARG_LINKS, ARG_SHOW, ARG_ORIGINATORS);
prog_name, ARG_SHOW, ARG_STATUS, ARG_SHOW, ARG_INTERFACES, ARG_SHOW, ARG_LINKS, ARG_SHOW, ARG_ORIGINATORS, ARG_CREDITS);
dbg_printf(cn, " e.g. %s -c %s=%cwlan0 %s=%s \n", prog_name, ARG_DEV, ARG_RESET_CHAR, ARG_SHOW, ARG_INTERFACES );
dbg_printf(cn, "\n");

View File

@@ -647,7 +647,7 @@ CRYPTKEY_T *cryptKeyFromDer( char *keyPath ) {
(rsa_copy(rsa, pk_rsa(pk))) ||
(rsa_check_privkey(rsa))
) {
dbgf_sys(DBGT_ERR, "failed opening private key=%s err=%d", keyPath, ret);
dbgf_sys(DBGT_ERR, "failed opening private key=%s err=-%X", keyPath, -ret);
pk_free(&pk);
cryptKeyFree(&ckey);
return NULL;
@@ -708,13 +708,13 @@ int cryptKeyMakeDer( int32_t keyBitSize, char *path ) {
(ret = rsa_check_privkey(pk_rsa(pk))))
goto_error(finish, "Failed making rsa key! ret=%d");
if ((derSz = pk_write_key_der(&pk, derBuf, sizeof(derBuf))) < 0)
if ((derSz = pk_write_key_der(&pk, derBuf, sizeof(derBuf))) <= 0)
goto_error(finish, "Failed translating rsa key to der! derSz=%d");
#else
# error "Please fix CRYPTLIB"
#endif
unsigned char *derStart = derBuf + sizeof(derBuf) - derSz - 1;
unsigned char *derStart = derBuf + sizeof(derBuf) - derSz;
if (!(keyFile = fopen(path, "wb")) || ((int)fwrite(derStart, 1, derSz, keyFile)) != derSz )

View File

@@ -28,13 +28,14 @@
#define POLARSSL_1_2_5 1125
#define POLARSSL_1_2_9 1129
#define POLARSSL_1_3_3 1133
#define POLARSSL_1_3_4 1134
#define POLARSSL_MAX 1999
#define CYASSL_MIN 2000
#define CYASSL_2_8_0 2280
#define CYASSL_MAX 2999
#ifndef CRYPTLIB
#define CRYPTLIB POLARSSL_1_2_5
#define CRYPTLIB POLARSSL_1_3_4
#endif
#define CRYPT_DER_BUF_SZ 16000

961
desc.c Normal file
View File

@@ -0,0 +1,961 @@
/*
* Copyright (c) 2010 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
*/
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <unistd.h>
#include <time.h>
#include <errno.h>
#include <stdint.h>
#include <netinet/udp.h>
#include <netinet/ip6.h>
#include "list.h"
#include "control.h"
#include "bmx.h"
#include "crypt.h"
#include "avl.h"
#include "node.h"
#include "key.h"
#include "sec.h"
#include "metrics.h"
#include "ogm.h"
#include "msg.h"
#include "desc.h"
#include "content.h"
#include "z.h"
#include "ip.h"
#include "schedule.h"
#include "tools.h"
#include "iptools.h"
#include "plugin.h"
#include "allocate.h"
#include "prof.h"
#define CODE_CATEGORY_NAME "desc"
int32_t desc_root_size_out = DEF_DESC_ROOT_SIZE;
int32_t vrt_frame_data_size_out = DEF_VRT_FRAME_DATA_SIZE;
int32_t vrt_frame_data_size_in = DEF_VRT_FRAME_DATA_SIZE;
int32_t desc_vbodies_size_out = DEF_DESC_VBODIES_SIZE;
int32_t desc_vbodies_size_in = DEF_DESC_VBODIES_SIZE;
int32_t vrt_frame_max_nesting = 2;
int32_t unsolicitedDescAdvs = DEF_UNSOLICITED_DESC_ADVS;
IDM_T process_description_tlvs(struct packet_buff *pb, struct orig_node *on, struct desc_content *dcOld, struct desc_content *dcNew, uint8_t op, uint8_t filter)
{
TRACE_FUNCTION_CALL;
assertion(-500370, (op == TLV_OP_DEL || op == TLV_OP_TEST || op == TLV_OP_NEW || op == TLV_OP_DEBUG ||
(op >= TLV_OP_CUSTOM_MIN && op <= TLV_OP_CUSTOM_MAX) || (op >= TLV_OP_PLUGIN_MIN && op <= TLV_OP_PLUGIN_MAX)));
int32_t result;
int8_t blocked = NO;
assertion(-500807, (dcNew && dcNew->desc_frame && dcNew->dhn));
assertion(-502047, IMPLIES(op == TLV_OP_DEL || op == TLV_OP_NEW, on && dcNew));
if (filter <= description_tlv_db->handl_max && !contents_data(dcNew, filter))
return TLV_RX_DATA_DONE;
struct rx_frame_iterator it = {
.caller = __FUNCTION__, .op = op, .pb = pb, .db = description_tlv_db, .process_filter = filter,
.on = on, .dcOld = dcOld, .dcNew = dcNew,
.f_type = -1, .frames_length = 0, .frames_in = NULL
};
dbgf_track(DBGT_INFO, "op=%s nodeId=%s filter=%d",
tlv_op_str(op), nodeIdAsStringFromDescAdv(dcNew->desc_frame), filter);
while ((result = rx_frame_iterate(&it)) > TLV_RX_DATA_DONE) {
if (result == TLV_RX_DATA_BLOCKED)
blocked = YES;
}
assertion( -502048, (result==TLV_RX_DATA_DONE || result==TLV_RX_DATA_REBOOTED || result==TLV_RX_DATA_REJECTED || result==TLV_RX_DATA_FAILURE));
if ((op >= TLV_OP_CUSTOM_MIN && op <= TLV_OP_CUSTOM_MAX) || (op >= TLV_OP_PLUGIN_MIN && op <= TLV_OP_PLUGIN_MAX))
return result;
if (result==TLV_RX_DATA_REBOOTED || result==TLV_RX_DATA_REJECTED || result == TLV_RX_DATA_FAILURE || blocked) {
assertion(-501355, (op == TLV_OP_TEST));
dbgf_sys(DBGT_WARN, "problematic description_ltv from %s, near type=%d=%s frame_data_length=%d pos=%d %s %s",
pb ? pb->i.llip_str : DBG_NIL,
it.f_type, (((uint8_t)it.f_type) <= description_tlv_db->handl_max) ? description_tlv_db->handls[it.f_type].name : "",
it.f_dlen, it._f_pos_next, blocked ? "BLOCKED" : "", tlv_rx_result_str(result));
return (result == TLV_RX_DATA_DONE ? TLV_RX_DATA_BLOCKED : result);
}
return TLV_RX_DATA_DONE;
}
IDM_T desc_frame_changed( struct rx_frame_iterator *it, uint8_t type )
{
struct desc_content *rOld = it->dcOld;
struct desc_content *rNew = it->dcNew;
struct key_node *kn = (rOld ? rOld->key : (rNew ? rNew->key : NULL));
assertion(-502274, (kn));
IDM_T changed = (contents_dlen(rOld, type) != contents_dlen(rNew, type) ||
(contents_dlen(rOld, type) && memcmp(contents_data(rOld, type), contents_data(rNew, type), contents_dlen(rNew, type))));
dbgf_track(DBGT_INFO, "orig=%s %s type=%d (%s) old_len=%d new_len=%d",
cryptShaAsString(&kn->kHash), changed ? " CHANGED" : "UNCHANGED",
type, it->db->handls[type].name, contents_dlen(rOld, type), contents_dlen(rNew, type));
return changed;
}
SHA1_T *nodeIdFromDescAdv(uint8_t *desc_adv)
{
return &(((struct dsc_hdr_chash*) (desc_adv + sizeof(struct tlv_hdr)))->expanded_chash);
}
char *nodeIdAsStringFromDescAdv(uint8_t *desc_adv)
{
return cryptShaAsString(nodeIdFromDescAdv(desc_adv));
}
void update_orig_dhash(struct desc_content *dcNew)
{
assertion(-502469, (dcNew->key));
struct key_node *kn = dcNew->key;
struct orig_node *on = kn->currOrig;
struct desc_content *dcOld = on ? on->descContent : NULL;
assertion(-502470, (dcNew && dcNew->key && !dcNew->orig));
assertion(-502471, (dcNew && dcNew->unresolvedContentCounter == 0 && dcNew->contentRefs_tree.items));
assertion(-502225, IMPLIES(on, on->descContent != dcNew));
assertion(-502225, IMPLIES(on, on->descContent->orig == on));
assertion(-502472, IMPLIES(on, on->descContent->descSqn < dcNew->descSqn));
ASSERTION(-502473, (process_description_tlvs(NULL, on, dcOld, dcNew, TLV_OP_TEST, FRAME_TYPE_PROCESS_ALL) == TLV_RX_DATA_DONE));
if (on) {
cb_plugin_hooks(PLUGIN_CB_DESCRIPTION_DESTROY, on);
on->descContent = dcNew;
dcNew->orig = on;
dcOld->orig = NULL;
} else {
on = debugMallocReset(sizeof( struct orig_node) + (sizeof(void*) * plugin_data_registries[PLUGIN_DATA_ORIG]), -300128);
on->k.nodeId = dcNew->key->kHash;
on->key = dcNew->key;
on->descContent = dcNew;
dcNew->orig = on;
dcNew->key->currOrig = on;
init_neighTrust(on);
avl_insert(&orig_tree, on, -300148);
cb_plugin_hooks(PLUGIN_CB_STATUS, NULL);
}
kn->nextDesc = NULL;
process_description_tlvs(NULL, on, dcOld, dcNew, TLV_OP_NEW, FRAME_TYPE_PROCESS_ALL);
if (dcOld)
dhash_node_reject(dcOld->dhn);
on->updated_timestamp = bmx_time;
cb_plugin_hooks(PLUGIN_CB_DESCRIPTION_CREATED, on);
if (unsolicitedDescAdvs) {
schedule_tx_task(FRAME_TYPE_DESC_ADVS, NULL, NULL, NULL, dcNew->desc_frame_len, &dcNew->dhn->dhash, sizeof(DHASH_T));
schedule_tx_task(FRAME_TYPE_DHASH_ADV, NULL, NULL, NULL, SCHEDULE_MIN_MSG_SIZE, &dcNew->dhn->dhash, sizeof(DHASH_T));
}
}
void process_description_tlvs_del( struct orig_node *on, struct desc_content *dcOld, uint8_t ft_start, uint8_t ft_end ) {
int8_t t;
assertion(-502068, (on && dcOld && dcOld->dhn && dcOld->key));
for (t = ft_start; t <= ft_end; t++) {
if ( t== BMX_DSC_TLV_CONTENT_HASH )
continue;
if (contents_data(dcOld, t)) {
int tlv_result = process_description_tlvs(NULL, on, NULL, dcOld, TLV_OP_DEL, t);
assertion(-501360, (tlv_result == TLV_RX_DATA_DONE));
}
}
}
void update_my_description(void)
{
// MUST be checked here because:
// description may have changed (relevantly for ogm_aggregation)
// during current call of task_next() in bmx() main loop
if (!my_description_changed)
return;
TRACE_FUNCTION_CALL;
prof_start(update_my_description, main);
assertion(-502082, (!terminating));
assertion(-502275, (myKey));
dbgf_track(DBGT_INFO, DBG_NIL);
// add all tlv options:
struct tx_frame_iterator tx = {
.caller = __FUNCTION__, .db = description_tlv_db, .prev_out_type = -1,
.frames_out_ptr = debugMallocReset(desc_root_size_out, -300627),
.frames_out_max = desc_root_size_out,
.frames_out_pref = desc_root_size_out,
.frame_cache_array = debugMallocReset(vrt_frame_data_size_out, -300586),
.frame_cache_size = vrt_frame_data_size_out,
};
for (; tx.frame_type <= tx.db->handl_max; tx.frame_type++) {
int32_t result;
assertion(-502083, IMPLIES((tx.db->handls[tx.frame_type]).name, (tx.db->handls[tx.frame_type]).tx_frame_handler));
result = tx_frame_iterate(NO/*iterate_msg*/, &tx);
assertion_dbg(-500798, result>=TLV_TX_DATA_DONE, "frame_type=%d result=%s", tx.frame_type, tlv_tx_result_str(result));
}
ASSERTION(-502315, (test_description_signature(tx.frames_out_ptr, tx.frames_out_pos)));
struct desc_content *dcNew = descContent_create(tx.frames_out_ptr, tx.frames_out_pos, myKey);
assertion(-502316, (dcNew && dcNew->dhn));
assertion(-502317, (dcNew->key == myKey && myKey->nextDesc == dcNew));
assertion(-502318, (dcNew->contentRefs_tree.items && !dcNew->unresolvedContentCounter));
assertion(-502319, IMPLIES(myKey->currOrig, myKey->currOrig->descContent->dhn));
dbgf_sys(DBGT_INFO, "nodeId=%s dhashOld=%s dhashNew=%s",
cryptShaAsString(&myKey->kHash),
cryptShaAsString(myKey->currOrig ? &myKey->currOrig->descContent->dhn->dhash : NULL),
cryptShaAsString(&dcNew->dhn->dhash));
keyNode_updCredits(NULL, myKey, NULL);
assertion(-502320, (myKey->currOrig->descContent == dcNew));
my_description_changed = NO;
if (myBurstSqn > ((BURST_SQN_T)(-1000)))
myBurstSqn = 0;
debugFree(tx.frames_out_ptr, -300585);
debugFree(tx.frame_cache_array, -300585);
prof_stop();
}
STATIC_FUNC
int32_t opt_show_descriptions(uint8_t cmd, uint8_t _save, struct opt_type *opt,
struct opt_parent *patch, struct ctrl_node *cn)
{
TRACE_FUNCTION_CALL;
if ( cmd == OPT_APPLY ) {
struct avl_node *an = NULL;
struct dhash_node *dhn;
char *name = NULL;
int32_t type_filter = DEF_DESCRIPTION_TYPE;
int32_t relevance = DEF_RELEVANCE;
struct opt_child *c = NULL;
while ((c = list_iterate(&patch->childs_instance_list, c))) {
if (!strcmp(c->opt->name, ARG_DESCRIPTION_TYPE)) {
type_filter = strtol(c->val, NULL, 10);
} else if (!strcmp(c->opt->name, ARG_RELEVANCE)) {
relevance = strtol(c->val, NULL, 10);
} else if (!strcmp(c->opt->name, ARG_DESCRIPTION_NAME)) {
name = c->val;
}
}
dbg_printf( cn, "descriptions:" );
while ((dhn = avl_iterate_item(&dhash_tree, &an))) {
struct desc_content *dc = dhn->descContent;
if (name && (!dc->orig || strcmp(name, dc->orig->k.hostname)))
continue;
dbg_printf(cn, "\ndescSha=%s nodeId=%s name=%s state=%s contents=%d/%d rejected=%d neighRefs=%d:",
cryptShaAsString(&dhn->dhash), cryptShaAsString(dc ? &dc->key->kHash: NULL),
dc && dc->orig ? dc->orig->k.hostname : NULL, dc ? dc->key->bookedState->secName : NULL,
dc ? dc->contentRefs_tree.items : 0, dc ? (int)(dc->unresolvedContentCounter + dc->contentRefs_tree.items) : -1,
dhn->rejected, dhn->neighRefs_tree.items);
if (!dc || !dc->contentRefs_tree.items || dc->unresolvedContentCounter)
continue;
struct rx_frame_iterator it = {.caller = __FUNCTION__, .on = NULL, .dcNew = dc,
.op = TLV_OP_PLUGIN_MIN, .db = description_tlv_db, .process_filter = type_filter, .f_type = -1,};
int32_t result;
while ((result = rx_frame_iterate(&it)) > TLV_RX_DATA_DONE) {
dbg_printf(cn, "\n %s (%s): ", it.f_handl->name, dc->final[it.f_type].desc_tlv_body_len ? "inline" : "referenced");
fields_dbg_lines(cn, relevance, it.f_msgs_len, it.f_msg,
it.f_handl->min_msg_size, it.f_handl->msg_format);
}
}
dbg_printf( cn, "\n" );
}
return SUCCESS;
}
int32_t opt_update_dext_method(uint8_t cmd, uint8_t _save, struct opt_type *opt, struct opt_parent *patch, struct ctrl_node *cn)
{
TRACE_FUNCTION_CALL;
if ( cmd == OPT_APPLY )
my_description_changed = YES;
return SUCCESS;
}
STATIC_FUNC
int32_t create_dsc_tlv_version(struct tx_frame_iterator *it)
{
TRACE_FUNCTION_CALL;
struct dsc_msg_version *dsc = (struct dsc_msg_version *)tx_iterator_cache_msg_ptr(it);
dsc->capabilities = htons(my_desc_capabilities);
uint32_t rev_u32;
sscanf(GIT_REV, "%8X", &rev_u32);
dsc->codeRevision = htonl(rev_u32);
dsc->comp_version = my_compatibility;
dsc->descSqn = newDescriptionSqn( NULL, 1);
return sizeof(struct dsc_msg_version);
}
STATIC_FUNC
int32_t process_dsc_tlv_version(struct rx_frame_iterator *it)
{
TRACE_FUNCTION_CALL;
assertion(-502321, IMPLIES(it->op == TLV_OP_NEW || it->op == TLV_OP_DEL, it->on));
if (it->op != TLV_OP_TEST && it->op != TLV_OP_NEW)
return it->f_dlen;
DESC_SQN_T newSqn = ntohl(((struct dsc_msg_version*)it->f_data)->descSqn);
if (it->dcOld && newSqn <= it->dcOld->descSqn)
return TLV_RX_DATA_FAILURE;
if (it->op == TLV_OP_NEW && it->on->neigh) {
it->on->neigh->burstSqn = 0;
if (it->dcOld && newSqn >= (it->dcOld->descSqn + DESC_SQN_REBOOT_ADDS))
keyNode_schedLowerWeight(it->on->key, KCPromoted);
}
return sizeof(struct dsc_msg_version);
}
STATIC_FUNC
int32_t create_dsc_tlv_names(struct tx_frame_iterator *it)
{
TRACE_FUNCTION_CALL;
dbgf_all(DBGT_INFO, "%s", my_Hostname);
int32_t nameLen = strlen(my_Hostname);
if (nameLen<=0 || nameLen>=255 || nameLen >= MAX_HOSTNAME_LEN)
return TLV_TX_DATA_IGNORED;
if (nameLen > tx_iterator_cache_data_space_pref(it, 0, 0))
return TLV_TX_DATA_FULL;
struct description_msg_name *msg = (struct description_msg_name *) tx_iterator_cache_msg_ptr(it);
msg->type = 0;
msg->len = nameLen;
memcpy(msg->name, my_Hostname, nameLen);
return sizeof(struct description_msg_name) + nameLen;
}
STATIC_FUNC
int32_t process_dsc_tlv_names(struct rx_frame_iterator *it)
{
TRACE_FUNCTION_CALL;
char name[MAX_HOSTNAME_LEN];
dbgf_all(DBGT_INFO, "op=%s", tlv_op_str(it->op) );
struct description_msg_name *msg = (struct description_msg_name *) it->f_msg;
if (msg->type != 0 || msg->len >= MAX_HOSTNAME_LEN)
return TLV_RX_DATA_FAILURE;
memcpy(name, msg->name, msg->len);
name[msg->len]=0;
if (validate_name_string(name, msg->len+1, NULL) == FAILURE)
return TLV_RX_DATA_FAILURE;
if (IMPLIES(!my_conformance_tolerance, it->f_dlen != (int)(sizeof(struct description_msg_name) + msg->len)))
return TLV_RX_DATA_FAILURE;
if ((it->op==TLV_OP_NEW || it->op == TLV_OP_DEL)) {
memset(it->on->k.hostname, 0, sizeof(it->on->k.hostname));
}
if (it->op == TLV_OP_NEW) {
strcpy(it->on->k.hostname, name);
}
return TLV_RX_DATA_PROCESSED;
}
STATIC_FUNC
int32_t tx_msg_description_request(struct tx_frame_iterator *it)
{
TRACE_FUNCTION_CALL;
struct tx_task_node *ttn = it->ttn;
struct hdr_description_request *hdr = ((struct hdr_description_request*) tx_iterator_cache_hdr_ptr(it));
struct msg_description_request *msg = ((struct msg_description_request*) tx_iterator_cache_msg_ptr(it));
DHASH_T *dhash = NULL;
IDM_T wanted = NO;;
if (memcmp((((uint8_t*) ttn->key.data) + sizeof(DESC_SQN_T)), ((uint8_t *) & ZERO_CYRYPSHA1), (sizeof(CRYPTSHA1_T) - sizeof(DESC_SQN_T)))) {
struct dhash_node *dhn = avl_find_item(&dhash_tree, (dhash = (DHASH_T*) ttn->key.data));
wanted = (dhn && !dhn->descContent && !dhn->rejected && dhn->neighRefs_tree.items);
} else {
DESC_SQN_T *descSqn = (DESC_SQN_T*) ttn->key.data;
struct key_node *neighKn = keyNode_get(&ttn->key.f.groupId);
assertion(-502322, IMPLIES(neighKn && neighKn->bookedState->i.c >= KCTracked, neighKn->content));
wanted = (neighKn && neighKn->bookedState->i.c >= KCTracked && neighKn->content->f_body &&
(neighKn->nextDesc ? neighKn->nextDesc->descSqn < *descSqn : (neighKn->currOrig ? neighKn->currOrig->descContent->descSqn < *descSqn : YES)));
}
assertion(-500855, (tx_iterator_cache_data_space_pref(it, 0, 0) >= ((int) (sizeof(struct msg_description_request)))));
dbgf_track(DBGT_INFO, "%s dev=%s to khash=%s iterations=%d requesting dhash=%s send=%d",
it->db->handls[ttn->key.f.type].name, ttn->key.f.p.dev->label_cfg.str, cryptShaAsString(&ttn->key.f.groupId),
ttn->tx_iterations, cryptShaAsString(dhash), wanted);
if (!wanted)
return TLV_TX_DATA_DONE;
msg->dhash = dhash ? *dhash : ZERO_CYRYPSHA1;
if (hdr->msg == msg) {
assertion(-500854, (is_zero(hdr, sizeof(*hdr))));
hdr->dest_kHash = ttn->key.f.groupId;
} else {
assertion(-500871, (cryptShasEqual(&hdr->dest_kHash, &ttn->key.f.groupId)));
}
dbgf_track(DBGT_INFO, "created msg=%d", ((int) ((((char*) msg) - ((char*) hdr) - sizeof( *hdr)) / sizeof(*msg))));
return sizeof(struct msg_description_request);
}
STATIC_FUNC
int32_t rx_msg_description_request(struct rx_frame_iterator *it)
{
TRACE_FUNCTION_CALL;
struct packet_buff *pb = it->pb;
struct hdr_description_request *hdr = (struct hdr_description_request*) (it->f_data);
struct msg_description_request *msg = (struct msg_description_request*) (it->f_msg);
assertion(-502171, (pb->i.iif));
if (cryptShasEqual(&hdr->dest_kHash, &myKey->kHash)) {
dbgf_track(DBGT_INFO, "%s NB %s destination_dhash=%s requested_dhash=%s",
it->f_handl->name, pb->i.llip_str, cryptShaAsString(&hdr->dest_kHash), cryptShaAsString(&msg->dhash));
struct dhash_node *dhn = cryptShasEqual(&msg->dhash, (void*) &ZERO_CYRYPSHA1) ? myKey->currOrig->descContent->dhn : avl_find_item(&dhash_tree, &msg->dhash);
if (dhn && dhn->descContent && dhn->descContent->orig && (((TIME_T) (bmx_time - dhn->referred_by_me_timestamp)) <= DEF_DESC0_REFERRED_TO) &&
(pb->i.verifiedLink|| dhn == myKey->currOrig->descContent->dhn)) {
dhn->referred_by_me_timestamp = bmx_time;
schedule_tx_task(FRAME_TYPE_DESC_ADVS, NULL, NULL, pb->i.iif, dhn->descContent->desc_frame_len, &dhn->dhash, sizeof(DHASH_T));
} else {
dbgf_sys(DBGT_WARN, "UNVERIFIED neigh=%s llip=%s or UNKNOWN dhash=%s or OUTDATED dhn=%d dc=%d on=%d",
pb->i.verifiedLink? cryptShaAsString(&pb->i.verifiedLink->k.linkDev->key.local->local_id) : NULL,
pb->i.llip_str, cryptShaAsString(&msg->dhash), !!dhn, (dhn && dhn->descContent), (dhn && dhn->descContent && dhn->descContent->orig));
}
}
return sizeof(struct msg_description_request);
}
STATIC_FUNC
int32_t tx_frame_description_adv(struct tx_frame_iterator *it)
{
TRACE_FUNCTION_CALL;
DHASH_T *dhash = (DHASH_T*)it->ttn->key.data;
struct dhash_node *dhn = avl_find_item(&dhash_tree, dhash);
struct desc_content *dc = dhn ? dhn->descContent : NULL;
if (!dc || !dc->orig) {
dbgf_sys(DBGT_WARN, "%s dhash=%s!", dc ? "UnKnown" : "UnPromoted", cryptShaAsString(dhash));
return TLV_TX_DATA_DONE;
}
assertion(-502060, (dc->desc_frame_len == it->ttn->frame_msgs_length));
assertion(-502061, (dc->desc_frame_len <= tx_iterator_cache_data_space_max(it, 0, 0)));
memcpy(tx_iterator_cache_msg_ptr(it), dc->desc_frame, dc->desc_frame_len);
dc->dhn->referred_by_me_timestamp = bmx_time;
dbgf_track(DBGT_INFO, "dhash=%s id=%s descr_size=%d",
cryptShaAsString(dhash), cryptShaAsString(&dc->key->kHash), dc->desc_frame_len);
return dc->desc_frame_len;
}
STATIC_FUNC
int32_t rx_frame_description_adv(struct rx_frame_iterator *it)
{
TRACE_FUNCTION_CALL;
int32_t goto_error_code;
struct key_node *kn;
GLOBAL_ID_T *nodeId = NULL;
struct dsc_msg_version *versMsg;
DHASH_T dhash;
struct dhash_node *dhn = NULL;
struct desc_content *dc = NULL;
cryptShaAtomic(it->f_data, it->f_dlen, &dhash);
if (!(nodeId = get_desc_id(it->f_data, it->f_dlen, NULL, &versMsg)))
goto_error(finish, TLV_RX_DATA_FAILURE);
if (!(kn = keyNode_get(nodeId)) || (kn->bookedState->i.c < KCTracked) || !kn->content || !kn->content->f_body)
goto_error(finish, it->f_dlen);
if ((kn->nextDesc && kn->nextDesc->descSqn >= ntohl(versMsg->descSqn)) ||
(kn->currOrig && kn->currOrig->descContent->descSqn >= ntohl(versMsg->descSqn)))
goto_error(finish, it->f_dlen);
if ((dhn = avl_find_item(&dhash_tree, &dhash)) && (dhn->descContent || dhn->rejected))
goto_error(finish, it->f_dlen);
if (!test_description_signature(it->f_data, it->f_dlen))
goto_error(finish, TLV_RX_DATA_FAILURE);
if ((dc = descContent_create(it->f_data, it->f_dlen, kn)) && !dc->unresolvedContentCounter)
keyNode_updCredits(NULL, kn, NULL);
goto_error(finish, it->f_dlen);
finish:
if (dhn)
dhn->referred_by_others_timestamp = bmx_time;
dbgf_track(DBGT_INFO, "rcvd dhash=%s nodeId=%s via_dev=%s via_ip=%s dc=%d",
memAsHexString(&dhash, sizeof(SHA1_T)), cryptShaAsString(nodeId),
it->pb->i.iif->label_cfg.str, it->pb->i.llip_str, !!dc);
return goto_error_code;
}
STATIC_FUNC
int32_t tx_msg_dhash_request(struct tx_frame_iterator *it)
{
TRACE_FUNCTION_CALL;
struct hdr_dhash_request *hdr = ((struct hdr_dhash_request*) tx_iterator_cache_hdr_ptr(it));
struct msg_dhash_request *msg = ((struct msg_dhash_request*) tx_iterator_cache_msg_ptr(it));
DHASH_T *dhash = ((DHASH_T*) it->ttn->key.data);
struct dhash_node *dhn = avl_find_item(&dhash_tree, dhash);
struct reference_node *ref;
if (!dhn || dhn->rejected || !dhn->neighRefs_tree.items || ((ref = avl_find_item(&it->ttn->neigh->refsByDhash_tree, &dhn)) && ref->claimedKey))
return TLV_TX_DATA_DONE;
if (hdr->msg == msg) {
assertion(-502287, (is_zero(hdr, sizeof(*hdr))));
hdr->dest_nodeId = it->ttn->key.f.groupId;
} else {
assertion(-502288, (cryptShasEqual(&hdr->dest_nodeId, &it->ttn->key.f.groupId)));
}
msg->dhash = *dhash;
return sizeof(struct msg_dhash_request);
}
STATIC_FUNC
int32_t rx_frame_dhash_request(struct rx_frame_iterator *it)
{
TRACE_FUNCTION_CALL;
struct neigh_node *nn = it->pb->i.verifiedLink->k.linkDev->key.local;
struct hdr_dhash_request *hdr = (struct hdr_dhash_request*) (it->f_data);
struct msg_dhash_request *msg = (struct msg_dhash_request*) (it->f_msg);
if (cryptShasEqual(&hdr->dest_nodeId, &myKey->kHash)) {
for (; msg < &(hdr->msg[it->f_msgs_fixed]); msg++) {
if ((avl_find(&dhash_tree, &msg->dhash)))
schedule_tx_task(FRAME_TYPE_DHASH_ADV, NULL, NULL, nn->best_tp_link->k.myDev, SCHEDULE_MIN_MSG_SIZE, &msg->dhash, sizeof(DHASH_T));
}
}
return TLV_RX_DATA_PROCESSED;
}
STATIC_FUNC
void dhash_tree_maintain(void)
{
struct dhash_node *dhn = NULL;
DHASH_T dhash = ZERO_CYRYPSHA1;
while ((dhn = avl_next_item(&dhash_tree, &dhash))) {
dhash = dhn->dhash;
if (dhn->descContent || dhn->rejected)
continue;
struct neigh_node *nn = NULL;
struct reference_node *ref;
while (dhn && (ref = avl_next_item(&dhn->neighRefs_tree, &nn))) {
struct key_node *claimedKey = ref->claimedKey;
nn = ref->neigh;
assertion(-502500, IMPLIES(claimedKey, avl_find(&claimedKey->neighRefs_tree, &nn)));
if (((AGGREG_SQN_T) ((nn->ogm_aggreg_max - ref->aggSqn)) >= nn->ogm_aggreg_size) && !claimedKey) {
if (dhn->neighRefs_tree.items == 1)
dhn = NULL;
refNode_destroy(ref, NO);
} else if (!claimedKey) {
schedule_tx_task(FRAME_TYPE_DHASH_REQ, &nn->local_id, nn, nn->best_tp_link->k.myDev, SCHEDULE_MIN_MSG_SIZE, &dhn->dhash, sizeof(dhn->dhash));
} else if (claimedKey->content && !claimedKey->content->f_body) {
assertion(-502323, (claimedKey->bookedState->i.c >= KCTracked));
//schedule_tx_task(FRAME_TYPE_CONTENT_REQ, &nn->local_id, nn, nn->best_tp_link->k.myDev, SCHEDULE_MIN_MSG_SIZE, &ck->kHash, sizeof(ck->kHash));
} else if (claimedKey->content) {
assertion(-502324, (claimedKey->bookedState->i.c >= KCTracked && claimedKey->content->f_body));
schedule_tx_task(FRAME_TYPE_DESC_REQ, &nn->local_id, nn, nn->best_tp_link->k.myDev, SCHEDULE_MIN_MSG_SIZE, &dhn->dhash, sizeof(dhn->dhash));
}
}
}
}
STATIC_FUNC
int32_t tx_msg_dhash_adv(struct tx_frame_iterator *it)
{
TRACE_FUNCTION_CALL;
struct msg_dhash_adv *msg = ((struct msg_dhash_adv*) tx_iterator_cache_msg_ptr(it));
struct dhash_node *dhn;
if ((dhn = avl_find_item(&dhash_tree, ((DHASH_T*)it->ttn->key.data)))) {
msg->dhash = dhn->dhash;
if (dhn->descContent) {
msg->descSqn = htonl(dhn->descContent->descSqn);
msg->kHash = dhn->descContent->key->kHash;
} //else: notify requesting node of stale dhash.
return sizeof(struct msg_dhash_adv);
}
return TLV_TX_DATA_DONE;
}
STATIC_FUNC
int32_t rx_msg_dhash_adv(struct rx_frame_iterator *it)
{
TRACE_FUNCTION_CALL;
struct msg_dhash_adv *msg = (struct msg_dhash_adv*) (it->f_msg);
struct neigh_node *nn = it->pb->i.verifiedLink->k.linkDev->key.local;
AGGREG_SQN_T aggSqnInvalidMax = (nn->ogm_aggreg_max - AGGREG_SQN_CACHE_RANGE);
struct reference_node *ref;
if (!msg->descSqn) {
if ((ref = avl_find_item(&nn->refsByDhash_tree, &msg->dhash)))
ref->aggSqn = aggSqnInvalidMax; // do not try to resolve this anymore
} else {
refNode_update(nn, aggSqnInvalidMax, &msg->dhash, &msg->kHash, ntohl(msg->descSqn));
}
return TLV_RX_DATA_PROCESSED;
}
STATIC_FUNC
int32_t opt_dsqn_path(uint8_t cmd, uint8_t _save, struct opt_type *opt, struct opt_parent *patch, struct ctrl_node *cn)
{
static uint8_t checked = NO;
if ( (cmd == OPT_CHECK || cmd == OPT_SET_POST) && initializing && !checked ) {
if (!newDescriptionSqn((cmd==OPT_CHECK ? patch->val : DEF_DSQN_PATH), 0))
return FAILURE;
checked = YES;
}
return SUCCESS;
}
int32_t opt_update_description(uint8_t cmd, uint8_t _save, struct opt_type *opt, struct opt_parent *patch, struct ctrl_node *cn)
{
TRACE_FUNCTION_CALL;
if ( cmd == OPT_APPLY )
my_description_changed = YES;
return SUCCESS;
}
STATIC_FUNC
struct opt_type desc_options[]=
{
// ord parent long_name shrt Attributes *ival min max default *func,*syntax,*help
#ifndef LESS_OPTIONS
{ODI,0,ARG_DESC_ROOT_SIZE, 0, 9,0,A_PS1,A_ADM,A_DYI,A_CFA,A_ANY, &desc_root_size_out,MIN_DESC_ROOT_SIZE, MAX_DESC_ROOT_SIZE, DEF_DESC_ROOT_SIZE,0, opt_update_dext_method,
ARG_VALUE_FORM, HLP_DESC_ROOT_SIZE},
{ODI,0,ARG_VRT_FRAME_DATA_SIZE_OUT,0, 9,0,A_PS1,A_ADM,A_DYI,A_CFA,A_ANY, &vrt_frame_data_size_out,MIN_VRT_FRAME_DATA_SIZE,MAX_VRT_FRAME_DATA_SIZE,DEF_VRT_FRAME_DATA_SIZE,0, opt_update_dext_method,
ARG_VALUE_FORM, HLP_VRT_FRAME_DATA_SIZE_OUT},
{ODI,0,ARG_VRT_FRAME_DATA_SIZE_IN, 0, 9,0,A_PS1,A_ADM,A_DYI,A_CFA,A_ANY, &vrt_frame_data_size_in,MIN_VRT_FRAME_DATA_SIZE,MAX_VRT_FRAME_DATA_SIZE,DEF_VRT_FRAME_DATA_SIZE,0, opt_update_dext_method,
ARG_VALUE_FORM, HLP_VRT_FRAME_DATA_SIZE_IN},
{ODI,0,ARG_DESC_VBODIES_SIZE_OUT, 0, 9,0,A_PS1,A_ADM,A_DYI,A_CFA,A_ANY, &desc_vbodies_size_out,MIN_DESC_VBODIES_SIZE,MAX_DESC_VBODIES_SIZE,DEF_DESC_VBODIES_SIZE,0, opt_update_dext_method,
ARG_VALUE_FORM, HLP_DESC_VBODIES_SIZE_OUT},
{ODI,0,ARG_DESC_VBODIES_SIZE_IN, 0, 9,0,A_PS1,A_ADM,A_DYI,A_CFA,A_ANY, &desc_vbodies_size_in,MIN_DESC_VBODIES_SIZE,MAX_DESC_VBODIES_SIZE,DEF_DESC_VBODIES_SIZE,0, opt_update_dext_method,
ARG_VALUE_FORM, HLP_DESC_VBODIES_SIZE_IN},
{ODI,0,ARG_UNSOLICITED_DESC_ADVS, 0, 9,0,A_PS1,A_ADM,A_DYI,A_CFA,A_ANY, &unsolicitedDescAdvs,MIN_UNSOLICITED_DESC_ADVS,MAX_UNSOLICITED_DESC_ADVS,DEF_UNSOLICITED_DESC_ADVS,0,0,
ARG_VALUE_FORM, NULL},
#endif
{ODI, 0, ARG_DESCRIPTIONS, 0, 9,2, A_PS0N,A_USR, A_DYN, A_ARG, A_ANY, 0, 0, 0, 0,0, opt_show_descriptions,
0, HLP_DESCRIPTIONS}
,
{ODI,ARG_DESCRIPTIONS,ARG_DESCRIPTION_TYPE,'t',9,2,A_CS1,A_USR,A_DYN,A_ARG,A_ANY,0, MIN_DESCRIPTION_TYPE,MAX_DESCRIPTION_TYPE,DEF_DESCRIPTION_TYPE,0,opt_show_descriptions,
"<TYPE>", HLP_DESCRIPTION_TYPE}
,
{ODI,ARG_DESCRIPTIONS,ARG_DESCRIPTION_NAME,'n',9,2,A_CS1,A_USR,A_DYN,A_ARG,A_ANY,0, 0, 0, 0,0, opt_show_descriptions,
"<NAME>", "only show description of nodes with given name"}
,
{ODI,ARG_DESCRIPTIONS,ARG_RELEVANCE, 'r',9,2,A_CS1,A_USR,A_DYN,A_ARG,A_ANY,0, MIN_RELEVANCE, MAX_RELEVANCE, DEF_RELEVANCE,0, opt_show_descriptions,
ARG_VALUE_FORM, HLP_ARG_RELEVANCE},
{ODI,0,ARG_DSQN_PATH, 0, 9,1,A_PS1,A_ADM,A_INI,A_CFA,A_ANY, 0, 0, 0, 0,DEF_DSQN_PATH,opt_dsqn_path,
ARG_DIR_FORM, "set path to file containing latest used description SQN of this node"},
{ODI,0,"descUpdate", 0, 9,1,A_PS0,A_ADM,A_DYN,A_ARG,A_ANY, 0, 0, 0, 0,0, opt_update_description,
0, "update own description"}
,
};
void init_desc( void )
{
register_options_array( desc_options, sizeof( desc_options ), CODE_CATEGORY_NAME );
struct frame_handl handl;
memset(&handl, 0, sizeof ( handl));
static const struct field_format version_format[] = VERSION_MSG_FORMAT;
handl.name = "DSC_VERSION";
handl.alwaysMandatory = 1;
handl.min_msg_size = sizeof (struct dsc_msg_version);
handl.fixed_msg_size = 1;
handl.dextReferencing = (int32_t*)&fref_never;
handl.dextCompression = (int32_t*)&never_fzip;
handl.tx_frame_handler = create_dsc_tlv_version;
handl.rx_frame_handler = process_dsc_tlv_version;
handl.msg_format = version_format;
register_frame_handler(description_tlv_db, BMX_DSC_TLV_VERSION, &handl);
static const struct field_format names_format[] = DESCRIPTION_MSG_NAME_FORMAT;
handl.name = "DSC_NAMES";
handl.min_msg_size = sizeof(struct description_msg_name);
handl.fixed_msg_size = 0;
handl.dextReferencing = (int32_t*)&fref_dflt;
handl.dextCompression = (int32_t*)&dflt_fzip;
handl.tx_frame_handler = create_dsc_tlv_names;
handl.rx_frame_handler = process_dsc_tlv_names;
handl.msg_format = names_format;
register_frame_handler(description_tlv_db, BMX_DSC_TLV_NAMES, &handl);
handl.name = "DESC_REQ";
handl.rx_processUnVerifiedLink = 1;
handl.data_header_size = sizeof( struct hdr_description_request);
handl.min_msg_size = sizeof(struct msg_description_request);
handl.fixed_msg_size = 1;
handl.tx_msg_handler = tx_msg_description_request;
handl.rx_msg_handler = rx_msg_description_request;
register_frame_handler(packet_frame_db, FRAME_TYPE_DESC_REQ, &handl);
handl.name = "DESC_ADV";
handl.rx_processUnVerifiedLink = 1;
handl.min_msg_size = (
sizeof(struct tlv_hdr) + sizeof(struct dsc_hdr_chash) +
sizeof(struct tlv_hdr) + sizeof(struct dsc_msg_signature) +
sizeof(struct tlv_hdr) + sizeof(struct dsc_msg_version) );
handl.tx_packet_prepare_always = update_my_description;
handl.tx_frame_handler = tx_frame_description_adv;
handl.rx_frame_handler = rx_frame_description_adv;
register_frame_handler(packet_frame_db, FRAME_TYPE_DESC_ADVS, &handl);
handl.name = "DHASH_REQ";
handl.data_header_size = sizeof( struct hdr_dhash_request);
handl.min_msg_size = sizeof (struct msg_dhash_request);
handl.fixed_msg_size = 1;
handl.tx_packet_prepare_always = dhash_tree_maintain;
handl.tx_msg_handler = tx_msg_dhash_request;
handl.rx_frame_handler = rx_frame_dhash_request;
register_frame_handler(packet_frame_db, FRAME_TYPE_DHASH_REQ, &handl);
handl.name = "DHASH_ADV";
handl.min_msg_size = sizeof (struct msg_dhash_adv);
handl.fixed_msg_size = 1;
handl.tx_msg_handler = tx_msg_dhash_adv;
handl.rx_msg_handler = rx_msg_dhash_adv;
register_frame_handler(packet_frame_db, FRAME_TYPE_DHASH_ADV, &handl);
}

155
desc.h Normal file
View File

@@ -0,0 +1,155 @@
/*
* Copyright (c) 2010 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
*/
#include <stdint.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <linux/if.h>
#define ARG_DESC_ROOT_SIZE "descRootSizeOut"
extern int32_t desc_root_size_out;
#define HLP_DESC_ROOT_SIZE "set maximum size for own description and references"
#define MIN_DESC_ROOT_SIZE (MIN_UDPD_SIZE - sizeof(struct packet_header) - (2*sizeof(struct tlv_hdr)))
#define MAX_DESC_ROOT_SIZE (MAX_UDPD_SIZE - sizeof(struct packet_header) - (2*sizeof(struct tlv_hdr)))
#define DEF_DESC_ROOT_SIZE MAX_DESC_ROOT_SIZE
#define REF_CONTENT_BODY_SIZE_OUT (desc_root_size_out - sizeof(struct frame_hdr_content_adv))
#define REF_CONTENT_BODY_SIZE_MAX (MAX_DESC_ROOT_SIZE - sizeof(struct frame_hdr_content_adv))
extern int32_t vrt_frame_max_nesting;
#define ARG_VRT_FRAME_DATA_SIZE_OUT "descVirtFrameSizeOut"
#define HLP_VRT_FRAME_DATA_SIZE_OUT "set maximum virtual size for own description frames"
#define ARG_VRT_FRAME_DATA_SIZE_IN "descVirtFrameSizeIn"
#define HLP_VRT_FRAME_DATA_SIZE_IN "set maximum virtual size for other description frames"
#define MIN_VRT_FRAME_DATA_SIZE (MIN_DESC_ROOT_SIZE)
#define MAX_VRT_FRAME_DATA_SIZE (4*((REF_CONTENT_BODY_SIZE_MAX / sizeof(SHA1_T)) * REF_CONTENT_BODY_SIZE_MAX))
#define DEF_VRT_FRAME_DATA_SIZE (2*((REF_CONTENT_BODY_SIZE_MAX / sizeof(SHA1_T)) * REF_CONTENT_BODY_SIZE_MAX))
extern int32_t vrt_frame_data_size_in;
extern int32_t vrt_frame_data_size_out;
#define ARG_DESC_VBODIES_SIZE_OUT "descVirtSizeOut"
#define HLP_DESC_VBODIES_SIZE_OUT "set maximum virtual size for own description"
#define ARG_DESC_VBODIES_SIZE_IN "descVirtSizeIn"
#define HLP_DESC_VBODIES_SIZE_IN "set maximum virtual size for other node descriptions"
#define MIN_DESC_VBODIES_SIZE (MIN_DESC_ROOT_SIZE)
// this should be the max possible with a reference depth of 1 :
#define MAX_DESC_VBODIES_SIZE (10 * MAX_VRT_FRAME_DATA_SIZE)
#define DEF_DESC_VBODIES_SIZE ( 4 * MAX_VRT_FRAME_DATA_SIZE)
extern int32_t desc_vbodies_size_in;
extern int32_t desc_vbodies_size_out;
#define MIN_DESC0_REFERRED_TO 10000
#define MAX_DESC0_REFERRED_TO 100000
#define DEF_DESC0_REFERRED_TO 10000
#define DEF_UNSOLICITED_DESC_ADVS 1
#define MIN_UNSOLICITED_DESC_ADVS 0
#define MAX_UNSOLICITED_DESC_ADVS 1
#define ARG_UNSOLICITED_DESC_ADVS "unsolicitedDescAdvs"
#define ARG_DSQN_PATH "descSqnPath"
#define DEF_DSQN_PATH "/etc/bmx6/descSqn"
#define ARG_DESCRIPTIONS "descriptions"
#define HLP_DESCRIPTIONS "show node descriptions\n"
#define ARG_DESCRIPTION_NAME "name"
#define ARG_DESCRIPTION_TYPE "type"
#define DEF_DESCRIPTION_TYPE FRAME_TYPE_PROCESS_ALL
#define MIN_DESCRIPTION_TYPE 0
#define MAX_DESCRIPTION_TYPE FRAME_TYPE_PROCESS_ALL
#define HLP_DESCRIPTION_TYPE "show description extension(s) of given type (0..253=type 254=none 255=all) \n"
struct msg_dhash_adv {
DHASH_T dhash;
GLOBAL_ID_T kHash;
DESC_SQN_T descSqn;
} __attribute__((packed));
struct msg_dhash_request {
DHASH_T dhash;
} __attribute__((packed));
struct hdr_dhash_request { // 20 bytes
GLOBAL_ID_T dest_nodeId;
struct msg_dhash_request msg[];
} __attribute__((packed));
struct msg_description_request { // 2 bytes
DHASH_T dhash;
} __attribute__((packed));
struct hdr_description_request { // 20 bytes
DHASH_T dest_kHash;
struct msg_description_request msg[];
} __attribute__((packed));
#define VERSION_MSG_FORMAT { \
{FIELD_TYPE_UINT, -1, 8, 1, FIELD_RELEVANCE_HIGH, "comp_version" }, \
{FIELD_TYPE_HEX, -1, 8, 1, FIELD_RELEVANCE_MEDI, "capabilities" }, \
{FIELD_TYPE_UINT, -1, (8*sizeof(DESC_SQN_T)), 0, FIELD_RELEVANCE_HIGH, "descSqn" }, \
{FIELD_TYPE_HEX, -1, 32, 0, FIELD_RELEVANCE_HIGH, "codeRevision" }, \
FIELD_FORMAT_END}
struct description_msg_name {
uint8_t type;
uint8_t len;
char name[];
} __attribute__((packed));
#define DESCRIPTION_MSG_NAME_FORMAT { \
{FIELD_TYPE_UINT, -1, 8, 1, FIELD_RELEVANCE_HIGH, "type"}, \
{FIELD_TYPE_STRING_SIZE, -1, 8, 0, FIELD_RELEVANCE_LOW, "len"}, \
{FIELD_TYPE_STRING_BINARY, -1, 0, 1, FIELD_RELEVANCE_LOW, "name" }, \
FIELD_FORMAT_END }
void process_description_tlvs_del(struct orig_node *on, struct desc_content *dcOld, uint8_t ft_start, uint8_t ft_end);
IDM_T process_description_tlvs(struct packet_buff *pb, struct orig_node *on, struct desc_content *dcOld, struct desc_content *dcNew, uint8_t op, uint8_t filter);
void update_my_description(void);
void update_orig_dhash(struct desc_content *dc);
SHA1_T *nodeIdFromDescAdv(uint8_t *desc_adv);
char *nodeIdAsStringFromDescAdv(uint8_t *desc_adv);
IDM_T desc_frame_changed(struct rx_frame_iterator *it, uint8_t type);
int32_t opt_update_dext_method(uint8_t cmd, uint8_t _save, struct opt_type *opt, struct opt_parent *patch, struct ctrl_node *cn);
int32_t opt_update_description(uint8_t cmd, uint8_t _save, struct opt_type *opt, struct opt_parent *patch, struct ctrl_node *cn);
void init_desc(void);

60
dump.c
View File

@@ -44,7 +44,6 @@ static int64_t curr_dump_period = DEF_DUMP_PERIOD;
static int32_t next_dump_period = DEF_DUMP_PERIOD;
static int32_t prev_dump_period = DEF_DUMP_PERIOD;
static int32_t dump_regression_exp = DEF_DUMP_REGRESSION_EXP;
static uint32_t dump_iteration = 0;
static IDM_T dump_terminating = NO;
@@ -63,8 +62,8 @@ void update_traffic_statistics_data(struct dump_data *data)
for (t = 0; t < DUMP_TYPE_ARRSZ; t++) {
data->pre_all[i][t] = (((int64_t)(data->tmp_all[i][t])) * 1000) / curr_dump_period;
data->avg_all[i][t] -= (data->avg_all[i][t] >> dump_regression_exp);
data->avg_all[i][t] += ((data->pre_all[i][t]) >> dump_regression_exp);
data->avg_all[i][t] -= (data->avg_all[i][t] / devStatRegression);
data->avg_all[i][t] += ((data->pre_all[i][t]) / devStatRegression);
data->tmp_all[i][t] = 0;
}
@@ -72,8 +71,8 @@ void update_traffic_statistics_data(struct dump_data *data)
for (t = 0; t < FRAME_TYPE_ARRSZ; t++) {
data->pre_frame[i][t] = (((int64_t)(data->tmp_frame[i][t])) * 1000) / curr_dump_period;
data->avg_frame[i][t] -= (data->avg_frame[i][t] >> dump_regression_exp);
data->avg_frame[i][t] += ((data->pre_frame[i][t]) >> dump_regression_exp);
data->avg_frame[i][t] -= (data->avg_frame[i][t] / devStatRegression);
data->avg_frame[i][t] += ((data->pre_frame[i][t]) / devStatRegression);
data->tmp_frame[i][t] = 0;
}
}
@@ -146,10 +145,10 @@ void dump(struct packet_buff *pb)
struct rx_frame_iterator it = {
.caller = __FUNCTION__, .onOld = NULL, .op = 0, .pb = NULL, .dbgl = DBGL_ALL,
.caller = __FUNCTION__, .op = 0,
.db = packet_frame_db, .process_filter = FRAME_TYPE_PROCESS_NONE,
.frame_type = -1, .frames_in = (((uint8_t*) phdr) + sizeof (struct packet_header)),
.frames_length = (plength - sizeof (struct packet_header)), .frames_pos = 0 };
.f_type = -1, .frames_in = (((uint8_t*) phdr) + sizeof (struct packet_header)),
.frames_length = (plength - sizeof (struct packet_header)), ._f_pos_next = 0 };
int32_t result;
uint16_t pkt_pos = sizeof (struct packet_header);
@@ -160,46 +159,46 @@ void dump(struct packet_buff *pb)
char *tname;
int16_t frame_msgs = -1;
if (!(tname = it.db->handls[it.frame_type].name)) {
sprintf(tnum, "%d", it.frame_type);
if (!(tname = it.db->handls[it.f_type].name)) {
sprintf(tnum, "%d", it.f_type);
tname = tnum;
}
if (it.db->handls[it.frame_type].fixed_msg_size) {
frame_msgs = it.frame_msgs_length / it.db->handls[it.frame_type].min_msg_size;
if (it.db->handls[it.f_type].fixed_msg_size) {
frame_msgs = it.f_msgs_len / it.db->handls[it.f_type].min_msg_size;
}
dbgf(DBGL_DUMP, DBGT_NONE, "%s frame_type=%-12s data_header_size=%-3d msgs=%-3d frame_length=%-4d",
direction == DUMP_DIRECTION_IN ? "in " : "out", tname,
it.db->handls[it.frame_type].data_header_size, frame_msgs, it.frame_length);
it.db->handls[it.f_type].data_header_size, frame_msgs, it._f_len);
dbgf(DBGL_DUMP, DBGT_NONE, "%s data [%3d...%3d]:%s",
direction == DUMP_DIRECTION_IN ? "in hex" : "out hex",
pkt_pos, pkt_pos + it.frame_length - 1, memAsHexString(((uint8_t*) phdr) + pkt_pos, it.frame_length));
pkt_pos, pkt_pos + it._f_len - 1, memAsHexString(((uint8_t*) phdr) + pkt_pos, it._f_len));
//assertion(-500991, (it.hands->hands[it.frame_type].min_msg_size));
assertion(-500992, (it.frame_msgs_length >= 0));
assertion(-500992, (it.f_msgs_len >= 0));
(*dev_plugin_data)->tmp_frame[direction][it.frame_type] += (it.frame_length << IMPROVE_ROUNDOFF);
(*dev_plugin_data)->tmp_frame[direction][it.f_type] += (it._f_len << IMPROVE_ROUNDOFF);
dump_all.tmp_frame[direction][it.frame_type] += (it.frame_length << IMPROVE_ROUNDOFF);
dump_all.tmp_frame[direction][it.f_type] += (it._f_len << IMPROVE_ROUNDOFF);
(*dev_plugin_data)->tmp_all[direction][DUMP_TYPE_FRAME_HEADER] += ((it.frame_length - it.frame_data_length) << IMPROVE_ROUNDOFF);
(*dev_plugin_data)->tmp_all[direction][DUMP_TYPE_FRAME_HEADER] += ((it._f_len - it.f_dlen) << IMPROVE_ROUNDOFF);
dump_all.tmp_all[direction][DUMP_TYPE_FRAME_HEADER] += ((it.frame_length - it.frame_data_length) << IMPROVE_ROUNDOFF);
dump_all.tmp_all[direction][DUMP_TYPE_FRAME_HEADER] += ((it._f_len - it.f_dlen) << IMPROVE_ROUNDOFF);
pkt_pos += it.frame_length;
pkt_pos += it._f_len;
}
if (result != TLV_RX_DATA_DONE) {
dbgf(DBGL_DUMP, DBGT_NONE, "%s ERROR frame_type=%d frame_length=%d frame_data_length=%d result=%s - ignoring further frames!!",
direction == DUMP_DIRECTION_IN ? "in " : "out", it.frame_type, it.frame_length, it.frame_data_length, tlv_rx_result_str(result));
direction == DUMP_DIRECTION_IN ? "in " : "out", it.f_type, it._f_len, it.f_dlen, tlv_rx_result_str(result));
dbgf(DBGL_DUMP, DBGT_NONE, "%s data [%3d...%3d]:%s",
direction == DUMP_DIRECTION_IN ? "in hex" : "out hex",
pkt_pos, pkt_pos + it.frame_length - 1, memAsHexString(((uint8_t*) phdr) + pkt_pos, it.frame_length));
pkt_pos, pkt_pos + it._f_len - 1, memAsHexString(((uint8_t*) phdr) + pkt_pos, it._f_len));
}
assertion(-500990, (IMPLIES(direction == DUMP_DIRECTION_OUT, result == TLV_RX_DATA_DONE)));
@@ -212,11 +211,8 @@ void dbg_traffic_statistics(struct dump_data *data, struct ctrl_node *cn, char*
{
uint16_t t;
dbg_printf(cn, "%-20s \n", dbg_name);
for (t = 0; t < DUMP_TYPE_ARRSZ; t++) {
dbg_printf(cn, "%13s %5d (%3d) %5d (%3d) %5d (%3d) | %5d (%3d) %5d (%3d) %5d (%3d)\n",
dbg_printf(cn, "%-11s %15s %5d (%3d) %5d (%3d) %5d (%3d) | %5d (%3d) %5d (%3d) %5d (%3d)\n", dbg_name,
t == DUMP_TYPE_UDP_PAYLOAD ? "UDP_PAYLOAD" : (t == DUMP_TYPE_PACKET_HEADER ? "PACKET_HEADER" : "FRAME_HEADER"),
@@ -270,11 +266,10 @@ void dbg_traffic_statistics(struct dump_data *data, struct ctrl_node *cn, char*
if (!tname) {
sprintf(tnum, "%d", t);
tname = tnum;
}
}
dbg_printf(cn, "%13s %5d (%3d) %5d (%3d) %5d (%3d) | %5d (%3d) %5d (%3d) %5d (%3d)\n",
tname,
dbg_printf(cn, "%-11s %15s %5d (%3d) %5d (%3d) %5d (%3d) | %5d (%3d) %5d (%3d) %5d (%3d)\n", dbg_name, tname,
((data->pre_frame[DUMP_DIRECTION_IN][t] + data->pre_frame[DUMP_DIRECTION_OUT][t]) >> IMPROVE_ROUNDOFF),
@@ -329,10 +324,10 @@ int32_t opt_traffic_statistics(uint8_t cmd, uint8_t _save, struct opt_type *opt,
struct dev_node *dev;
struct avl_node *an = NULL;
dbg_printf(cn, "iteration=%d as [Bytes/sec], averaged over %.1f secs and as weighted averages\n",
dbg_printf(cn, "TRAFFIC: iteration=%d as [Bytes/sec], averaged over %.1f secs and as weighted averages\n",
dump_iteration, (float)curr_dump_period / 1000);
dbg_printf(cn, "%20s ( %% ) in ( %% ) out ( %% ) | all ( %% ) in ( %% ) out ( %% )\n"," ");
dbg_printf(cn, "%-30s all ( %% ) in ( %% ) out ( %% ) | all ( %% ) in ( %% ) out ( %% )\n", "dev");
if (!strcmp(patch->val, ARG_DUMP_ALL) || !strcmp(patch->val, ARG_DUMP_SUMMARY))
dbg_traffic_statistics(&dump_all, cn, ARG_DUMP_ALL);
@@ -366,9 +361,6 @@ struct opt_type dump_options[]=
{ODI, 0, ARG_DUMP_PERIOD, 0, 9,1, A_PS1, A_ADM, A_DYI, A_ARG, A_ANY, &next_dump_period, MIN_DUMP_PERIOD, MAX_DUMP_PERIOD, DEF_DUMP_PERIOD,0, 0,
ARG_VALUE_FORM, "set duration in ms for how long traffic is measured for calculating interval averages"}
,
{ODI, 0, ARG_DUMP_REGRESSION_EXP, 0, 9,1, A_PS1, A_ADM, A_DYI, A_ARG, A_ANY, &dump_regression_exp,MIN_DUMP_REGRESSION_EXP,MAX_DUMP_REGRESSION_EXP,DEF_DUMP_REGRESSION_EXP,0,0,
ARG_VALUE_FORM, "set regression exponent for traffic-dump statistics "}
,
{ODI, 0, ARG_DUMP, 0, 9,2, A_PS1, A_USR, A_DYN, A_ARG, A_ANY, 0, 0, 0, 0,0, opt_traffic_statistics,
"<DEV>", "show traffic statistics for given device name, summary, or all\n"}

4
dump.h
View File

@@ -37,10 +37,6 @@
#define ARG_DUMP_SUMMARY "summary"
#define DEF_DUMP_REGRESSION_EXP 4
#define MIN_DUMP_REGRESSION_EXP 0
#define MAX_DUMP_REGRESSION_EXP 20
#define ARG_DUMP_REGRESSION_EXP "trafficRegressionExponent"
#define DUMP_TYPE_UDP_PAYLOAD 0

510
hna.c

File diff suppressed because it is too large Load Diff

16
hna.h
View File

@@ -59,7 +59,7 @@ extern struct avl_tree tun_in_tree;
#define ARG_TUN_OUT_TIMEOUT "tunOutTimeout"
#define MIN_TUN_OUT_TO 0
#define MAX_TUN_OUT_TO 3600000
#define MAX_TUN_OUT_TO REGISTER_TASK_TIMEOUT_MAX
#define DEF_TUN_OUT_TO 60000
#define TDN_STATE_CATCHALL 1
@@ -109,7 +109,7 @@ extern struct avl_tree tun_in_tree;
#define MAX_TUN_OUT_IPMETRIC INT32_MAX
#define MIN_TUN_OUT_IPMETRIC 0
#define ARG_TUN_OUT_HOSTNAME "gwName"
#define ARG_TUN_OUT_GWNAME "gwName"
#define ARG_TUN_OUT_PKID "gwId"
#define ARG_TUN_OUT_TRULE "tableRule"
@@ -394,7 +394,7 @@ struct tun_search_node {
// struct tun_search_key tunSearchKey;
char nameKey[NETWORK_NAME_LEN];
uint32_t bmx6RouteBits;
uint64_t bmx6RouteBits;
uint16_t exportDistance;
uint8_t exportOnly;
struct net_key net;
@@ -411,7 +411,7 @@ struct tun_search_node {
uint32_t iprule;
GLOBAL_ID_T global_id;
char nodeName[MAX_HOSTNAME_LEN];
char gwName[MAX_HOSTNAME_LEN];
struct net_key srcRtNet;
// IFNAME_T tunName;
@@ -496,7 +496,11 @@ struct tun_dev_node {
int32_t ifIdx;
uint16_t curr_mtu; // DEF_TUN_OUT_MTU == orig_mtu
uint16_t orig_mtu;
struct avl_tree tun_bit_tree[2];
struct user_net_device_stats stats;
IDM_T stats_captured;
struct avl_tree tun_bit_tree[2];
};
struct tun_in_node {
@@ -523,7 +527,7 @@ struct tun_in_node {
struct avl_tree tun_dev_tree;
};
char* bmx6RouteBits2String(uint32_t bmx6_route_bits);
char* bmx6RouteBits2String(uint64_t bmx6_route_bits);
void set_tunXin6_net_adv_list(uint8_t del, struct list_head *adv_list);

428
iid.c Normal file
View File

@@ -0,0 +1,428 @@
/*
* Copyright (c) 2010 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
*/
#define _GNU_SOURCE
#include <arpa/inet.h>
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/if.h> /* ifr_if, ifr_tun */
#include <linux/rtnetlink.h>
#include <time.h>
#include "list.h"
#include "control.h"
#include "bmx.h"
#include "crypt.h"
#include "avl.h"
#include "node.h"
#include "iid.h"
#include "key.h"
#include "sec.h"
#include "metrics.h"
#include "msg.h"
#include "ip.h"
#include "hna.h"
#include "schedule.h"
#include "tools.h"
#include "iptools.h"
#include "plugin.h"
#include "allocate.h"
#include "z.h"
#define CODE_CATEGORY_NAME "iid"
/***********************************************************
IID Infrastructure
************************************************************/
int32_t ogmIid = DEF_OGM_SQN_RANGE;
struct iid_repos my_iid_repos = {0, 0, 0, 0,
{NULL}};
int8_t iid_extend_repos(struct iid_repos *rep)
{
TRACE_FUNCTION_CALL;
dbgf_all(DBGT_INFO, "sizeof iid: %zu, tot_used %d arr_size %d ",
(rep == &my_iid_repos) ? sizeof(IID_NODE_T__*) : sizeof(IID_T), rep->tot_used, rep->arr_size);
assertion(-500217, (rep != &my_iid_repos || IID_SPREAD_FK != 1 || rep->tot_used == rep->arr_size));
if (rep->arr_size + IID_REPOS_SIZE_BLOCK >= IID_REPOS_SIZE_WARN) {
dbgf_sys(DBGT_WARN, "%d", rep->arr_size);
if (rep->arr_size + IID_REPOS_SIZE_BLOCK >= IID_REPOS_SIZE_MAX)
return FAILURE;
}
int field_size = (rep == &my_iid_repos) ? sizeof(IID_NODE_T__*) : sizeof(struct iid_ref);
if (rep->arr_size) {
rep->arr.u8 = debugRealloc(rep->arr.u8, (rep->arr_size + IID_REPOS_SIZE_BLOCK) * field_size, -300035);
} else {
rep->arr.u8 = debugMalloc(IID_REPOS_SIZE_BLOCK * field_size, -300085);
rep->tot_used = IID_RSVD_MAX + 1;
rep->min_free = IID_RSVD_MAX + 1;
rep->max_free = IID_RSVD_MAX + 1;
}
memset(&(rep->arr.u8[rep->arr_size * field_size]), 0, IID_REPOS_SIZE_BLOCK * field_size);
rep->arr_size += IID_REPOS_SIZE_BLOCK;
return SUCCESS;
}
void iid_purge_repos(struct iid_repos *rep)
{
TRACE_FUNCTION_CALL;
if (rep->arr.u8)
debugFree(rep->arr.u8, -300135);
memset(rep, 0, sizeof( struct iid_repos));
}
void iid_free(struct iid_repos *rep, IID_T iid)
{
TRACE_FUNCTION_CALL;
int m = (rep == &my_iid_repos);
assertion(-500330, (iid > IID_RSVD_MAX));
assertion(-500228, (iid < rep->arr_size && iid < rep->max_free && rep->tot_used > IID_RSVD_MAX));
assertion(-500229, ((m ? (rep->arr.node[iid] != NULL) : (rep->arr.ref[iid].myIID4x) != 0)));
if (m) {
rep->arr.node[iid] = NULL;
} else {
rep->arr.ref[iid].myIID4x = 0;
rep->arr.ref[iid].referred_by_neigh_timestamp_sec = 0;
}
rep->min_free = XMIN(rep->min_free, iid);
if (rep->max_free == iid + 1) {
IID_T i;
for (i = iid; i > IID_MIN_USED; i--) {
if (m ? (rep->arr.node[i - 1] != NULL) : (rep->arr.ref[i - 1].myIID4x) != 0)
break;
}
rep->max_free = i;
}
rep->tot_used--;
dbgf_all(DBGT_INFO, "mine %d, iid %d tot_used %d, min_free %d max_free %d",
m, iid, rep->tot_used, rep->min_free, rep->max_free);
if (rep->tot_used > 0 && rep->tot_used <= IID_MIN_USED) {
assertion(-500362, (rep->tot_used == IID_MIN_USED && rep->max_free == IID_MIN_USED && rep->min_free == IID_MIN_USED));
iid_purge_repos(rep);
}
}
IID_NODE_T__* iid_get_node_by_myIID4x(IID_T myIID4x)
{
TRACE_FUNCTION_CALL;
if (my_iid_repos.max_free <= myIID4x)
return NULL;
IID_NODE_T__ *dhn = my_iid_repos.arr.node[myIID4x];
assertion(-500328, (!dhn || dhn->myIID4orig == myIID4x));
if (dhn && !dhn->key__) {
dbgf_track(DBGT_INFO, "myIID4x %d INVALIDATED %d sec ago",
myIID4x, (bmx_time - dhn->referred_by_me_timestamp) / 1000);
return NULL;
}
return dhn;
}
IID_NODE_T__* iid_get_node_by_neighIID4x(IID_NEIGH_T *nn, IID_T neighIID4x)
{
TRACE_FUNCTION_CALL;
assertion(-502331, (ogmIid));
if (!nn || nn->neighIID4x_repos.max_free <= neighIID4x) {
dbgf_all(DBGT_INFO, "neighIID4x=%d to large for neighIID4x_repos of neigh=%s",
neighIID4x, nn ? cryptShaAsString(&nn->local_id) : "???");
return NULL;
}
struct iid_ref *ref = &(nn->neighIID4x_repos.arr.ref[neighIID4x]);
if (!ref->myIID4x) {
dbgf_all(DBGT_WARN, "neighIID4x=%d not recorded by neighIID4x_repos", neighIID4x);
} else if (((((uint16_t) bmx_time_sec) - ref->referred_by_neigh_timestamp_sec) >
((MIN_DHASH_TO - (MIN_DHASH_TO / DHASH_TO_TOLERANCE_FK)) / 1000))) {
dbgf_track(DBGT_WARN, "neighIID4x=%d outdated in neighIID4x_repos, now_sec=%d, ref_sec=%d",
neighIID4x, bmx_time_sec, ref->referred_by_neigh_timestamp_sec);
} else {
ref->referred_by_neigh_timestamp_sec = bmx_time_sec;
if (ref->myIID4x < my_iid_repos.max_free) {
IID_NODE_T__ *dhn = my_iid_repos.arr.node[ref->myIID4x];
if (dhn)
return dhn;
dbgf_track(DBGT_WARN, "neighIID4x=%d -> myIID4x=%d empty!", neighIID4x, ref->myIID4x);
} else {
dbgf_track(DBGT_WARN, "neighIID4x=%d -> myIID4x=%d to large!", neighIID4x, ref->myIID4x);
}
}
return NULL;
}
STATIC_FUNC
void _iid_set(struct iid_repos *rep, IID_T IIDpos, IID_T myIID4x, IID_NODE_T__ *dhn)
{
TRACE_FUNCTION_CALL;
assertion(-500530, (rep && XOR(myIID4x, dhn))); // eihter the one ore the other !!
assertion(-500531, (!dhn || rep == &my_iid_repos));
assertion(-500535, (IIDpos >= IID_MIN_USED));
rep->tot_used++;
rep->max_free = XMAX(rep->max_free, IIDpos + 1);
IID_T min = rep->min_free;
if (min == IIDpos) {
for (min++; min < rep->arr_size; min++) {
if (myIID4x ? !(rep->arr.ref[min].myIID4x) : !(rep->arr.node[min]))
break;
}
}
assertion(-500244, (min <= rep->max_free));
rep->min_free = min;
if (myIID4x) {
rep->arr.ref[IIDpos].myIID4x = myIID4x;
rep->arr.ref[IIDpos].referred_by_neigh_timestamp_sec = bmx_time_sec;
} else {
rep->arr.node[IIDpos] = dhn;
dhn->referred_by_me_timestamp = bmx_time;
}
}
IID_T iid_new_myIID4x(IID_NODE_T__ *dhn)
{
TRACE_FUNCTION_CALL;
IID_T mid;
#ifndef NO_ASSERTIONS
IDM_T warn = 0;
#endif
assertion(-500216, (my_iid_repos.tot_used <= my_iid_repos.arr_size));
while (my_iid_repos.arr_size <= my_iid_repos.tot_used * IID_SPREAD_FK)
iid_extend_repos(&my_iid_repos);
if (IID_SPREAD_FK > 1) {
uint32_t random = rand_num(my_iid_repos.arr_size);
// Never put random function intro MAX()! It would be called twice
mid = XMAX(IID_MIN_USED, random);
while (my_iid_repos.arr.node[mid]) {
mid++;
if (mid >= my_iid_repos.arr_size) {
mid = IID_MIN_USED;
assertion(-500533, (!(warn++)));
}
}
} else {
mid = my_iid_repos.min_free;
}
_iid_set(&my_iid_repos, mid, 0, dhn);
return mid;
}
IDM_T iid_set_neighIID4x(struct iid_repos *neigh_rep, IID_T neighIID4x, IID_T myIID4x)
{
TRACE_FUNCTION_CALL;
assertion(-502332, (ogmIid));
assertion(-500326, (neighIID4x > IID_RSVD_MAX));
assertion(-500327, (myIID4x > IID_RSVD_MAX));
assertion(-500384, (neigh_rep && neigh_rep != &my_iid_repos));
assertion(-500245, (my_iid_repos.max_free > myIID4x));
IID_NODE_T__ *dhn = my_iid_repos.arr.node[myIID4x];
assertion(-500485, (dhn && dhn->descContent && dhn->descContent->orig));
dhn->referred_by_me_timestamp = bmx_time;
if (neigh_rep->max_free > neighIID4x) {
struct iid_ref *ref = &(neigh_rep->arr.ref[neighIID4x]);
if (ref->myIID4x > IID_RSVD_MAX) {
if (ref->myIID4x == myIID4x ||
(((uint16_t) (((uint16_t) bmx_time_sec) - ref->referred_by_neigh_timestamp_sec)) >=
((MIN_DHASH_TO - (MIN_DHASH_TO / DHASH_TO_TOLERANCE_FK)) / 1000))) {
ref->myIID4x = myIID4x;
ref->referred_by_neigh_timestamp_sec = bmx_time_sec;
return SUCCESS;
}
IID_NODE_T__ *dhn_old;
dhn_old = my_iid_repos.arr.node[ref->myIID4x]; // avoid -DNO_DEBUG_SYS warnings
dbgf_sys(DBGT_ERR, "demanding mapping: neighIID4x=%d to myIID4x=%d "
"(global_id=%s updated=%d last_referred_by_me=%d) "
"already used for ref->myIID4x=%d (last_referred_by_neigh_sec=%d %s=%s last_referred_by_me=%jd)! Reused faster than allowed!!",
neighIID4x, myIID4x, cryptShaAsString(&dhn->key__->orig__->nodeId), dhn->key__->orig__->updated_timestamp,
dhn->referred_by_me_timestamp,
ref->myIID4x,
ref->referred_by_neigh_timestamp_sec,
(!dhn_old ? "???" : (dhn_old->key__ && dhn_old->key__->orig__ ? cryptShaAsString(&dhn_old->key__->orig__->nodeId) :
(is_zero(&dhn_old->dhash, sizeof(dhn_old->dhash)) ? "FREED" : "INVALIDATED"))),
dhn_old ? cryptShaAsString(&dhn_old->dhash) : "???",
dhn_old ? (int64_t) dhn_old->referred_by_me_timestamp : -1
);
// EXITERROR(-500701, (0));
return FAILURE;
}
assertion(-500242, (ref->myIID4x == IID_RSVD_UNUSED));
}
while (neigh_rep->arr_size <= neighIID4x) {
if (
neigh_rep->arr_size > IID_REPOS_SIZE_BLOCK &&
neigh_rep->arr_size > my_iid_repos.arr_size &&
neigh_rep->tot_used < neigh_rep->arr_size / (2 * IID_SPREAD_FK)) {
dbgf_sys(DBGT_WARN, "IID_REPOS USAGE WARNING neighIID4x %d myIID4x %d arr_size %d used %d",
neighIID4x, myIID4x, neigh_rep->arr_size, neigh_rep->tot_used);
}
iid_extend_repos(neigh_rep);
}
assertion(-500243, ((neigh_rep->arr_size > neighIID4x &&
(neigh_rep->max_free <= neighIID4x || neigh_rep->arr.ref[neighIID4x].myIID4x == IID_RSVD_UNUSED))));
_iid_set(neigh_rep, neighIID4x, myIID4x, NULL);
return SUCCESS;
}
void iid_free_neighIID4x_by_myIID4x(struct iid_repos *rep, IID_T myIID4x)
{
TRACE_FUNCTION_CALL;
assertion(-500282, (rep != &my_iid_repos));
assertion(-500328, (myIID4x > IID_RSVD_MAX));
IID_T p;
uint16_t removed = 0;
for (p = IID_RSVD_MAX + 1; p < rep->max_free; p++) {
if (rep->arr.ref[p].myIID4x == myIID4x) {
if (removed++) {
// there could indeed be several (if the neigh has timeouted this node and learned it again later)
dbgf(DBGL_TEST, DBGT_INFO, "removed %d. stale rep->arr.sid[%d] = %d", removed, p, myIID4x);
}
iid_free(rep, p);
}
}
}
void iid_purge_dhash(IID_T myIID4orig)
{
TRACE_FUNCTION_CALL;
struct avl_node *an;
struct neigh_node *local;
iid_free(&my_iid_repos, myIID4orig);
//reset all neigh_node->oid_repos[x]=dhn->mid4o entries
for (an = NULL; (local = avl_iterate_item(&local_tree, &an));)
iid_free_neighIID4x_by_myIID4x(&local->neighIID4x_repos, myIID4orig);
}
void iid_init(void)
{
assertion(-502333, (OGMS_IID_PER_AGGREG_PREF <= OGMS_IID_PER_AGGREG_MAX));
}

117
iid.h Normal file
View File

@@ -0,0 +1,117 @@
typedef struct neigh_node IID_NEIGH_T;
typedef struct desc_content IID_NODE_T__;
#define IID_REPOS_SIZE_BLOCK 32
#define IID_REPOS_SIZE_MAX ((IID_T)(-1))
#define IID_REPOS_SIZE_WARN 1024
#define IID_RSVD_UNUSED 0
#define IID_RSVD_MAX 0
#define IID_MIN_USED 1
#define IID_SPREAD_FK 1 /*default=2 , 1 means no spreading #define IID_REPOS_USAGE_WARNING 10 */
#define OGMS_IID_PER_AGGREG_MAX (SIGNED_FRAMES_SIZE_MAX - (\
sizeof(struct tlv_hdr) + \
sizeof (struct hdr_ogm_adv) + \
(OGM_JUMPS_PER_AGGREGATION * sizeof(struct msg_ogm_iid_adv)))) \
/ sizeof(struct msg_ogm_iid_adv)
#define OGMS_IID_PER_AGGREG_PREF (SIGNED_FRAMES_SIZE_PREF - (\
sizeof(struct tlv_hdr) + \
sizeof (struct hdr_ogm_adv) + \
(OGM_JUMPS_PER_AGGREGATION * sizeof(struct msg_ogm_iid_adv)))) \
/ sizeof(struct msg_ogm_iid_adv)
#define MIN_OGM_IID 0
#define MAX_OGM_IID 1
#define DEF_OGM_IID 0
#define ARG_OGM_IID "iidOgms"
extern int32_t ogmIid;
struct msg_ogm_iid_adv // 4 bytes
{
union {
struct {
#if __BYTE_ORDER == __LITTLE_ENDIAN
unsigned int sqn : 16;
unsigned int mtcMantissa : 5;
unsigned int mtcExponent : 5;
unsigned int iidOffset : 6;
#elif __BYTE_ORDER == __BIG_ENDIAN
unsigned int iidOffset : 6;
unsigned int mtcExponent : 5;
unsigned int mtcMantissa : 5;
unsigned int sqn : 16;
#else
#error "Please fix <bits/endian.h>"
#endif
} o;
struct {
#if __BYTE_ORDER == __LITTLE_ENDIAN
unsigned int iid : 16;
unsigned int mtcU10 : 10;
unsigned int iidOffset : 6;
#elif __BYTE_ORDER == __BIG_ENDIAN
unsigned int iidOffset : 6;
unsigned int mtcU10 : 10;
unsigned int iid : 16;
#else
#error "Please fix <bits/endian.h>"
#endif
} j;
uint32_t u32;
} u;
} __attribute__((packed));
struct ogm_aggreg_node {
IID_T *iidsArr;
uint16_t iidsNum;
uint16_t iidJumps;
AGGREG_SQN_T sqn;
uint8_t tx_round;
};
struct iid_ref {
IID_T myIID4x;
uint16_t referred_by_neigh_timestamp_sec;
};
struct iid_repos {
IID_T arr_size; // the number of allocated array fields
IID_T min_free; // the first unused array field from the beginning of the array (might be outside of allocated space)
IID_T max_free; // the first unused array field after the last used field in the array (might be outside of allocated space)
IID_T tot_used; // the total number of used fields in the array
union {
uint8_t *u8;
IID_NODE_T__ **node;
struct iid_ref *ref;
} arr;
};
extern struct iid_repos my_iid_repos;
int8_t iid_extend_repos(struct iid_repos *rep);
void iid_purge_repos(struct iid_repos *rep);
void iid_free(struct iid_repos *rep, IID_T iid);
void iid_free_neighIID4x_by_myIID4x(struct iid_repos *rep, IID_T myIID4x);
IDM_T iid_set_neighIID4x(struct iid_repos *neigh_rep, IID_T neighIID4x, IID_T myIID4x);
IID_T iid_new_myIID4x(IID_NODE_T__ *dhn);
IID_NODE_T__* iid_get_node_by_neighIID4x(IID_NEIGH_T *nn, IID_T neighIID4x);
IID_NODE_T__* iid_get_node_by_myIID4x(IID_T myIID4x);
void iid_purge_dhash(IID_T myIID4orig);

610
ip.c

File diff suppressed because it is too large Load Diff

129
ip.h
View File

@@ -42,9 +42,9 @@
#define RTNL_RCV_MAX 66560 // 266240 // 133120 // less causes lost messages !!??
extern uint32_t udpRxBytesMean, udpRxPacketsMean, udpTxBytesMean, udpTxPacketsMean;
struct ifname {
@@ -53,11 +53,16 @@ struct ifname {
typedef struct ifname IFNAME_T;
#define ARG_DEVSTAT_PERIOD "devStatPeriod"
#define MIN_DEVSTAT_PERIOD 100
#define MAX_DEVSTAT_PERIOD 100000
#define DEF_DEVSTAT_PERIOD 5000
#define HLP_DEVSTAT_PERIOD "interface traffic-statistics period"
#define ARG_DEVSTAT_REGRESSION "devStatRegression"
#define MIN_DEVSTAT_REGRESSION 1
#define MAX_DEVSTAT_REGRESSION 100
#define DEF_DEVSTAT_REGRESSION 10
#define HLP_DEVSTAT_REGRESSION "arithmetic-mean regression for interface traffic-statistics"
extern int32_t devStatRegression;
#define DEF_DEVSTAT_PERIOD 1000
#define DEVSTAT_PRECISION 10000
#define ARG_LLOCAL_PREFIX "llocalPrefix"
#define HLP_LLOCAL_PREFIX "specify link-local prefix for interfaces"
@@ -163,11 +168,11 @@ typedef struct ifname IFNAME_T;
#define MAX_IP_RULE_TUN U16_MAX //64000
#define DEF_IP_RULE_TUN 32766
#define RT_TABLE_MAX -1
//#define RT_TABLE_HOSTS -1
#define RT_TABLE_HNA -1
#define RT_TABLE_TUN -2
#define RT_TABLE_MIN -2
#define BMX_TABLE_MAX -1
//#define BMX_TABLE_HOSTS -1
#define BMX_TABLE_HNA -1
#define BMX_TABLE_TUN -2
#define BMX_TABLE_MIN -2
//#define ARG_IP_TABLE_HOST "tableHosts"
//#define DEF_IP_TABLE_HOST 60 //avoid conflicts with bmxd and others
@@ -199,9 +204,11 @@ typedef struct ifname IFNAME_T;
#define MAX_BASE_PORT 60000
#define ARG_PEDANTIC_CLEANUP "pedanticCleanup"
#define DEF_PEDANTIC_CLEANUP NO
#define SYSCTL_IP6_FORWARD 1
#define SYSCTL_IP4_RP_FILTER 2
#define SYSCTL_IP4_FORWARD 1
#define SYSCTL_IP4_SEND_REDIRECT 0
#define SYSCTL_IP4_ACCEPT_LOCAL 1
#define DEF_TUN_OUT_PERSIST 1
@@ -228,6 +235,7 @@ typedef struct ifname IFNAME_T;
extern struct net_key autoconf_prefix_cfg;
extern IPX_T my_primary_ip;
#define AF_CFG AF_INET6
#define ZERO_NETCFG_KEY ZERO_NET6_KEY
@@ -269,6 +277,39 @@ extern struct avl_tree dev_name_tree;
//extern IDM_T dev_soft_conf_changed; // temporary enabled to trigger changed interface configuration
#define IFCONFIG_PATH_PROCNET_DEV "/proc/net/dev"
struct user_net_device_stats {
unsigned long long rx_packets; /* total packets received */
unsigned long long tx_packets; /* total packets transmitted */
// unsigned long long rx_bytes; /* total bytes received */
// unsigned long long tx_bytes; /* total bytes transmitted */
// unsigned long rx_errors; /* bad packets received */
// unsigned long tx_errors; /* packet transmit problems */
// unsigned long rx_dropped; /* no space in linux buffers */
// unsigned long tx_dropped; /* no space available in linux */
// unsigned long rx_multicast; /* multicast packets received */
// unsigned long rx_compressed;
// unsigned long tx_compressed;
// unsigned long collisions;
/* detailed rx_errors: */
// unsigned long rx_length_errors;
// unsigned long rx_over_errors; /* receiver ring buff overflow */
// unsigned long rx_crc_errors; /* recved pkt with crc error */
// unsigned long rx_frame_errors; /* recv'd frame alignment error */
// unsigned long rx_fifo_errors; /* recv'r fifo overrun */
// unsigned long rx_missed_errors; /* receiver missed packet */
/* detailed tx_errors */
// unsigned long tx_aborted_errors;
// unsigned long tx_carrier_errors;
// unsigned long tx_fifo_errors;
// unsigned long tx_heartbeat_errors;
// unsigned long tx_window_errors;
};
struct nlh_req {
struct nlmsghdr nlh;
};
@@ -373,19 +414,13 @@ struct if_addr_node {
struct tx_link_node {
struct list_head tx_tasks_list[FRAME_TYPE_ARRSZ]; // scheduled frames and messages
};
struct dev_node {
struct if_link_node *if_link;
struct if_addr_node *if_llocal_addr; // non-zero but might be global for ipv4 or loopback interfaces
struct if_addr_node *if_global_addr; // might be zero for non-primary interfaces
void (* tx_task) (void *);
int32_t tx_task_items;
int8_t hard_conf_changed;
int8_t soft_conf_changed;
struct net_key autoIP6Configured;
@@ -393,36 +428,28 @@ struct dev_node {
uint8_t active;
uint8_t activate_again;
uint8_t activate_cancelled;
uint8_t tmp_flag_for_to_be_send_adv;
uint32_t udpOutCurrPackets;
uint32_t udpOutPrevPackets;
uint32_t udpInCurrPackets;
uint32_t udpInPrevPackets;
uint32_t udpOutCurrBytes;
uint32_t udpOutPrevBytes;
uint32_t udpInCurrBytes;
uint32_t udpInPrevBytes;
// DEVADV_IDX_T dev_adv_idx; //TODO: Remove (use llip_key.idx instead)
int16_t dev_adv_msg;
uint32_t udpTxPacketsCurr;
uint32_t udpTxPacketsMean;
uint32_t udpRxPacketsCurr;
uint32_t udpRxPacketsMean;
uint32_t udpTxBytesCurr;
uint32_t udpTxBytesMean;
uint32_t udpRxBytesCurr;
uint32_t udpRxBytesMean;
IFNAME_T name_phy_cfg; //key for dev_name_tree
IFNAME_T label_cfg;
LinkNode dummyLink;
struct dev_ip_key llip_key;
// IPX_T llocal_ip_key; //TODO: Remove (use llip_key.ip instead)
DevKey llipKey;
MAC_T mac;
char ip_llocal_str[IPX_STR_LEN];
char ip_global_str[IPX_STR_LEN];
char ip_brc_str[IPX_STR_LEN];
int32_t ip4_rp_filter_orig;
int32_t ip4_send_redirects_orig;
struct sockaddr_storage llocal_unicast_addr;
struct sockaddr_storage tx_netwbrc_addr;
@@ -433,9 +460,6 @@ struct dev_node {
HELLO_SQN_T link_hello_sqn;
struct list_head tx_task_lists[FRAME_TYPE_ARRSZ]; // scheduled frames and messages
struct avl_tree tx_task_interval_tree;
int8_t linklayer_conf;
int8_t linklayer;
@@ -492,7 +516,9 @@ struct dev_node {
#define BMX6_ROUTE_OLSR 28
#define BMX6_ROUTE_BMX6 29
#define BMX6_ROUTE_BATMAN 30
#define BMX6_ROUTE_MAX 31
#define BMX6_ROUTE_MAX_KNOWN 30
#define BMX6_ROUTE_MAX_SUPP 63
#define ARG_ROUTE_UNSPEC "unspecified"
#define ARG_ROUTE_REDIRECT "redirect"
@@ -535,14 +561,14 @@ struct sys_route_dict {
};
#define set_rt_dict( S, T, C, N, B ) do { \
S[ T ].sys2Name = N; \
S[ T ].sys2Char = C; \
S[ T ].sys2Name = N; \
S[ T ].sys2bmx = B; \
S[ B ].bmx2sys = T; \
} while (0)
extern struct sys_route_dict bmx6_rt_dict[BMX6_ROUTE_MAX];
extern struct sys_route_dict bmx6_rt_dict[];
//iproute() commands:
@@ -572,7 +598,7 @@ extern struct sys_route_dict bmx6_rt_dict[BMX6_ROUTE_MAX];
#define IP_ROUTE_HOST 36
#define IP_ROUTE_HNA 37
#define IP_ROUTE_TUNS 38
#define IP_ROUTE_MAX (IP_ROUTE_TUNS + BMX6_ROUTE_MAX)
#define IP_ROUTE_MAX (IP_ROUTE_TUNS + BMX6_ROUTE_MAX_SUPP)
@@ -620,7 +646,7 @@ struct rtnl_get_node {
// core:
IDM_T rtnl_rcv( int fd, uint32_t pid, uint32_t seq, uint8_t cmd, uint8_t quiet, void (*func) (struct nlmsghdr *nh, void *data) ,void *data);
int rtnl_rcv(int fd, uint32_t pid, uint32_t seq, uint8_t cmd, uint8_t quiet, void (*func) (struct nlmsghdr *nh, void *data), void *data);
uint32_t get_if_index(IFNAME_T *name);
IDM_T kernel_set_flags(char *name, int fd, int get_req, int set_req, uint16_t up_flags, uint16_t down_flags);
@@ -640,6 +666,9 @@ int32_t kernel_get_ifidx( char *name );
IDM_T kernel_set_mtu(char *name, uint16_t mtu);
IDM_T kernel_get_route(uint8_t quiet, uint8_t family, uint32_t table, void (*func) (struct nlmsghdr *nh, void *data) );
// from net-tools: ifconfig.c and lib/interface.c
IDM_T kernel_get_ifstats(struct user_net_device_stats *stats, char *target);
struct sockaddr_storage set_sockaddr_storage(uint8_t af, IPX_T *ipx, int32_t port);
void set_ipexport( void (*func) (int8_t del, const struct net_key *dst, uint32_t oif_idx, IPX_T *via, uint32_t metric, uint8_t distance) );
@@ -649,7 +678,7 @@ IDM_T iproute(uint8_t cmd, int8_t del, uint8_t quiet, const struct net_key *dst,
void ip_flush_routes(uint8_t family, int32_t table_macro);
void ip_flush_rules(uint8_t family, int32_t table_macro);
IDM_T check_proc_sys_net(char *file, int32_t desired, int32_t *backup);
IDM_T check_proc_sys_net(char *file, int32_t desired);
void sysctl_config(struct dev_node *dev_node);

1208
key.c Normal file

File diff suppressed because it is too large Load Diff

71
key.h Normal file
View File

@@ -0,0 +1,71 @@
/*
* Copyright (c) 2014 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
*/
#define DEF_LINK_PURGE_TO 20000
#define MIN_LINK_PURGE_TO (MAX_TX_MIN_INTERVAL*2)
#define MAX_LINK_PURGE_TO 864000000 /*10 days*/
#define ARG_LINK_PURGE_TO "linkPurgeTimeout"
#define MIN_OGM_PURGE_TO (MAX_OGM_INTERVAL + MAX_TX_MIN_INTERVAL)
#define MAX_OGM_PURGE_TO 864000000 /*10 days*/
#define DEF_OGM_PURGE_TO 100000
#define ARG_OGM_PURGE_TO "purgeTimeout"
extern int32_t link_purge_to;
extern int32_t tracked_timeout;
extern int32_t neigh_qualifying_to;
// Key Weight:
enum KColumns {
KCListed,
KCTracked,
KCCertified,
KCPromoted,
KCNeighbor,
KCSize,
};
// Key Credits:
enum KRows {
KRQualifying,
KRFriend,
KRRecommended,
KRAlien,
KRSize,
};
extern struct KeyState keyMatrix[KCSize][KRSize];
extern uint32_t key_tree_deletions_chk, key_tree_deletions_cntr;
void keyNode_schedLowerWeight(struct key_node *kn, int8_t weight);
struct key_node *keyNode_updCredits(GLOBAL_ID_T *kHash, struct key_node *kn, struct key_credits *kc);
void keyNode_delCredits(GLOBAL_ID_T *kHash, struct key_node *kn, struct key_credits *kc);
#define KEYNODES_BLOCKING_ID 10
#define keyNodes_block_and_sync( a, b ) keyNodes_block_and_sync_( __FUNCTION__, (a), (b) )
uint32_t keyNodes_block_and_sync_(const char *f, uint32_t id, IDM_T force);
void keyNode_fixTimeouts();
struct key_node *keyNode_get(GLOBAL_ID_T *kHask);
void keyNodes_cleanup(int8_t keyStateColumn, struct key_node *except);
void init_key(void);

View File

@@ -1,6 +1,6 @@
CFLAGS += $(CORE_CFLAGS) -fpic -I../../
LDFLAGS += -shared
LDFLAGS +=
#-Wl,-soname,bmxd_config
PLUGIN_NAME = bmx6_json
@@ -19,7 +19,7 @@ all: $(PLUGIN_FULLNAME) Makefile
$(PLUGIN_FULLNAME): $(OBJS) Makefile
$(CC) $(LDFLAGS) -ljson-c $(EXTRA_LDFLAGS) $(OBJS) -o $(PLUGIN_FULLNAME) || $(CC) $(LDFLAGS) -ljson $(EXTRA_LDFLAGS) $(OBJS) -o $(PLUGIN_FULLNAME)
$(CC) -shared $(OBJS) $(LDFLAGS) -ljson-c $(EXTRA_LDFLAGS) -o $(PLUGIN_FULLNAME) || $(CC) -shared $(OBJS) $(LDFLAGS) -ljson $(EXTRA_LDFLAGS) -o $(PLUGIN_FULLNAME)
ln -f -s $(THISDIR)/$(PLUGIN_FULLNAME) $(THISDIR)/../$(PLUGIN_FULLNAME)
%.o: %.c %.h Makefile

View File

@@ -37,6 +37,7 @@
#include "crypt.h"
#include "avl.h"
#include "node.h"
#include "link.h"
#include "msg.h"
#include "plugin.h"
#include "schedule.h"
@@ -416,7 +417,7 @@ void json_originator_event_hook(int32_t cb_id, struct orig_node *orig)
if ((on = orig)) {
sprintf(path_name, "%s/%s", json_orig_dir, cryptShaAsString(&on->nodeId));
sprintf(path_name, "%s/%s", json_orig_dir, cryptShaAsString(&on->k.nodeId));
if ((fd = open(path_name, O_RDONLY)) > 0 && close(fd) == 0) {
@@ -434,7 +435,7 @@ void json_originator_event_hook(int32_t cb_id, struct orig_node *orig)
struct avl_node *it = NULL;
while ((on = orig ? orig : avl_iterate_item(&orig_tree, &it))) {
sprintf(path_name, "%s/%s", json_orig_dir, cryptShaAsString(&on->nodeId));
sprintf(path_name, "%s/%s", json_orig_dir, cryptShaAsString(&on->k.nodeId));
if ((fd = open(path_name, O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) < 0) {
@@ -450,7 +451,7 @@ void json_originator_event_hook(int32_t cb_id, struct orig_node *orig)
char status_name[sizeof (((struct status_handl *) NULL)->status_name)] = ARG_ORIGINATORS;
if ((handl = avl_find_item(&status_tree, status_name)) &&
(data_len = ((*(handl->frame_creator))(handl, on)))) {
(data_len = ((*(handl->frame_creator))(handl, on->key)))) {
json_object *jdesc_fields = NULL;
@@ -486,7 +487,6 @@ void json_description_event_hook(int32_t cb_id, struct orig_node *on)
TRACE_FUNCTION_CALL;
assertion(-501306, (on));
assertion(-501270, IMPLIES(cb_id == PLUGIN_CB_DESCRIPTION_CREATED, (on && on->dhn && on->dhn->desc_frame)));
assertion(-501273, (cb_id == PLUGIN_CB_DESCRIPTION_DESTROY || cb_id == PLUGIN_CB_DESCRIPTION_CREATED));
assertion(-501274, IMPLIES(initializing, cb_id == PLUGIN_CB_DESCRIPTION_CREATED));
assertion(-501275, (json_desc_dir));
@@ -495,7 +495,7 @@ void json_description_event_hook(int32_t cb_id, struct orig_node *on)
int fd;
char path_name[MAX_PATH_SIZE];
sprintf(path_name, "%s/%s", json_desc_dir, cryptShaAsString(&on->nodeId));
sprintf(path_name, "%s/%s", json_desc_dir, cryptShaAsString(&on->k.nodeId));
if (cb_id == PLUGIN_CB_DESCRIPTION_DESTROY) {
@@ -517,17 +517,18 @@ void json_description_event_hook(int32_t cb_id, struct orig_node *on)
}
json_object *jorig = json_object_new_object();
json_object_object_add(jorig, "descSha", json_object_new_string(cryptShaAsString(&on->dhn->dhash)));
json_object_object_add(jorig, "descSha", json_object_new_string(cryptShaAsString(&on->descContent->dhn->dhash)));
/*
json_object *jblocked = json_object_new_int(on->blocked);
json_object_object_add(jorig, "blocked", jblocked);
if (on->dhn && on->dhn->dext && on->dhn->dext->dlen) {
if (on->dhn && on->dhn->contents && on->dhn->contents->__dlen) {
struct rx_frame_iterator it = {
.caller = __FUNCTION__, .onOld = on, .dhnNew = on->dhn, .op = TLV_OP_PLUGIN_MIN,
.db = description_tlv_db, .process_filter = FRAME_TYPE_PROCESS_ALL,
.frame_type = -1, .frames_in = on->dhn->dext->data, .frames_length = on->dhn->dext->dlen,
.f_type = -1, .frames_in = on->dhn->contents->__data, .frames_length = on->dhn->contents->__dlen,
};
json_object *jextensions = NULL;
@@ -537,11 +538,11 @@ void json_description_event_hook(int32_t cb_id, struct orig_node *on)
json_object * jext_fields;
if ((jext_fields = fields_dbg_json(
FIELD_RELEVANCE_MEDI, YES, it.frame_msgs_length, it.msg,
it.handl->min_msg_size, it.handl->msg_format))) {
FIELD_RELEVANCE_MEDI, YES, it.f_mlen, it.f_msg,
it.f_handl->min_msg_size, it.f_handl->msg_format))) {
json_object *jext = json_object_new_object();
json_object_object_add(jext, it.handl->name, jext_fields);
json_object_object_add(jext, it.f_handl->name, jext_fields);
jextensions = jextensions ? jextensions : json_object_new_array();
@@ -553,7 +554,7 @@ void json_description_event_hook(int32_t cb_id, struct orig_node *on)
json_object_object_add(jorig, "extensions", jextensions);
}
*/
dprintf(fd, "%s\n", json_object_to_json_string(jorig));
dbgf_all(DBGT_INFO, "creating json-description=%s", path_name);

View File

@@ -5,8 +5,8 @@ LDFLAGS += -shared
PLUGIN_NAME = bmx6_quagga
SRC_C = quagga.c
SRC_H = quagga.h
SRC_C = quagga.c ../../redist.c
SRC_H = quagga.h ../../redist.h
OBJS= $(SRC_C:.c=.o)
PLUGIN_FULLNAME = $(PLUGIN_NAME).so

View File

@@ -48,9 +48,10 @@
#include "iptools.h"
#include "ip.h"
#include "hna.h"
#include "redist.h"
#include "allocate.h"
#include "quagga.h"
#include "redist.c"
#define CODE_CATEGORY_NAME "quagga"
@@ -94,11 +95,11 @@ static AVL_TREE(redist_out_tree, struct redist_out_node, k);
//static AVL_TREE(export_opt_tree, struct export_opt_node, nameKey);
static LIST_SIMPEL(tunXin6_net_adv_list, struct tunXin6_net_adv_node, list, list);
static LIST_SIMPEL(quagga_net_adv_list, struct tunXin6_net_adv_node, list, list);
static struct zebra_cfg zcfg;
static struct sys_route_dict zapi_rt_dict[BMX6_ROUTE_MAX];
static struct sys_route_dict zapi_rt_dict[BMX6_ROUTE_MAX_SUPP+1];
STATIC_FUNC void zsock_write(void* zpacket);
@@ -205,12 +206,12 @@ void zdata_parse_route(struct zdata *zd)
if (tmp) {
tmp->cnt += (zd->cmd == ZEBRA_IPV4_ROUTE_ADD || zd->cmd == ZEBRA_IPV6_ROUTE_ADD) ? (+1) : (-1);
redist_dbg(DBGL_SYS, DBGT_INFO, __FUNCTION__, tmp, zapi_rt_dict, zebraCmd2Str[zd->cmd], "OLD");
redist_dbg(DBGL_CHANGES, DBGT_INFO, __FUNCTION__, tmp, zapi_rt_dict, zebraCmd2Str[zd->cmd], "OLD");
} else {
tmp = debugMallocReset(sizeof (zrn), -300472);
*tmp = zrn;
tmp->cnt += 1;
redist_dbg(DBGL_SYS, DBGT_INFO, __FUNCTION__, tmp, zapi_rt_dict, zebraCmd2Str[zd->cmd], "NEW");
redist_dbg(DBGL_CHANGES, DBGT_INFO, __FUNCTION__, tmp, zapi_rt_dict, zebraCmd2Str[zd->cmd], "NEW");
assertion(-501406, (zd->cmd == ZEBRA_IPV4_ROUTE_ADD || zd->cmd == ZEBRA_IPV6_ROUTE_ADD));
avl_insert(&zroute_tree, tmp, -300473);
}
@@ -276,7 +277,7 @@ void zdata_parse(void)
if (changed_routes) {
if ( redistribute_routes(&redist_out_tree, &zroute_tree, &redist_opt_tree, zapi_rt_dict) )
update_tunXin6_net_adv_list(&redist_out_tree, &tunXin6_net_adv_list);
update_tunXin6_net_adv_list(&redist_out_tree, &quagga_net_adv_list);
}
}
}
@@ -435,7 +436,7 @@ void zsock_send_redist_request(void)
assertion(-501413, (zcfg.socket > 0));
int route_type;
for (route_type = 0; route_type < BMX6_ROUTE_MAX; route_type++) {
for (route_type = 0; route_type <= BMX6_ROUTE_MAX_KNOWN; route_type++) {
uint8_t new = bit_get((uint8_t*) & zcfg.bmx6_redist_bits_new, (sizeof (zcfg.bmx6_redist_bits_new) * 8), route_type);
uint8_t old = bit_get((uint8_t*) & zcfg.bmx6_redist_bits_old, (sizeof (zcfg.bmx6_redist_bits_old) * 8), route_type);
@@ -562,8 +563,8 @@ void zsock_disconnect(void)
my_description_changed = YES;
}
while (tunXin6_net_adv_list.items) {
struct tunXin6_net_adv_node *tn = list_del_head(&tunXin6_net_adv_list);
while (quagga_net_adv_list.items) {
struct tunXin6_net_adv_node *tn = list_del_head(&quagga_net_adv_list);
debugFree(tn, -300515);
}
@@ -815,7 +816,7 @@ int32_t opt_redistribute(uint8_t cmd, uint8_t _save, struct opt_type *opt, struc
zsock_send_redist_request();
if ( redistribute_routes(&redist_out_tree, &zroute_tree, &redist_opt_tree, zapi_rt_dict) )
update_tunXin6_net_adv_list(&redist_out_tree, &tunXin6_net_adv_list);
update_tunXin6_net_adv_list(&redist_out_tree, &quagga_net_adv_list);
}
changed = NO;
@@ -879,7 +880,7 @@ static void quagga_cleanup( void )
if (zcfg.socket)
zsock_disconnect();
set_tunXin6_net_adv_list(DEL, &tunXin6_net_adv_list);
set_tunXin6_net_adv_list(DEL, &quagga_net_adv_list);
}
@@ -888,7 +889,7 @@ static void quagga_cleanup( void )
static int32_t quagga_init( void )
{
assertion(-501424, (ZEBRA_ROUTE_MAX <= BMX6_ROUTE_MAX));
assertion(-501424, (ZEBRA_ROUTE_MAX <= BMX6_ROUTE_MAX_KNOWN));
memset(&zapi_rt_dict, 0, sizeof(zapi_rt_dict));
set_rt_dict(zapi_rt_dict, ZEBRA_ROUTE_SYSTEM, 'X', ARG_ROUTE_SYSTEM, BMX6_ROUTE_SYSTEM);
@@ -913,7 +914,7 @@ static int32_t quagga_init( void )
register_options_array(quagga_options, sizeof ( quagga_options), CODE_CATEGORY_NAME);
set_tunXin6_net_adv_list(ADD, &tunXin6_net_adv_list);
set_tunXin6_net_adv_list(ADD, &quagga_net_adv_list);
return SUCCESS;

View File

@@ -191,8 +191,8 @@ struct zebra_cfg {
char *zread_buff;
uint16_t zread_buff_len;
uint16_t zread_len;
uint32_t bmx6_redist_bits_new;
uint32_t bmx6_redist_bits_old;
uint64_t bmx6_redist_bits_new;
uint64_t bmx6_redist_bits_old;
//...
};

View File

@@ -37,6 +37,8 @@
#include "avl.h"
#include "node.h"
#include "msg.h"
#include "content.h"
#include "desc.h"
#include "plugin.h"
#include "schedule.h"
#include "tools.h"
@@ -71,7 +73,7 @@ void check_for_changed_sms(void *unused)
struct sms_node * sms = NULL;
struct avl_node *an = NULL;
int32_t max_sms_data_len = (use_referencing(&description_tlv_db->handls[BMX_DSC_TLV_SMS])) ? MAX_SMS_DATA_LEN_REF : MAX_SMS_DATA_LEN;
int32_t max_sms_data_len = (use_refLevel(&description_tlv_db->handls[BMX_DSC_TLV_SMS])) ? MAX_SMS_DATA_LEN_REF : MAX_SMS_DATA_LEN;
char name[MAX_SMS_NAME_LEN];
char data[max_sms_data_len + 1];
@@ -214,7 +216,7 @@ int create_description_sms(struct tx_frame_iterator *it)
struct sms_node *sms;
uint8_t *data = tx_iterator_cache_msg_ptr(it);
int32_t max_size = tx_iterator_cache_data_space_pref(it);
int32_t max_size = tx_iterator_cache_data_space_pref(it, 0, 100);
int pos = 0;
while ((sms = avl_iterate_item(&sms_tree, &an))) {
@@ -245,34 +247,31 @@ int create_description_sms(struct tx_frame_iterator *it)
STATIC_FUNC
int process_description_sms(struct rx_frame_iterator *it)
{
struct orig_node *on = it->onOld;
uint8_t op = it->op;
int pos = 0;
int mlen;
if (op == TLV_OP_NEW || op == TLV_OP_DEL)
rm_dir_content(smsRx_dir, cryptShaAsString(&on->nodeId));
if (it->op == TLV_OP_NEW || it->op == TLV_OP_DEL)
rm_dir_content(smsRx_dir, cryptShaAsString(&it->on->k.nodeId));
do {
if (pos + (int)sizeof ( struct description_msg_sms) > it->frame_msgs_length)
if (pos + (int)sizeof ( struct description_msg_sms) > it->f_msgs_len)
return TLV_RX_DATA_FAILURE;
struct description_msg_sms *sms = (struct description_msg_sms *) (it->frame_data + pos);
struct description_msg_sms *sms = (struct description_msg_sms *) (it->f_data + pos);
mlen = sizeof ( struct description_msg_sms) +ntohs(sms->text_len);
if (pos + mlen > it->frame_msgs_length)
if (pos + mlen > it->f_msgs_len)
return TLV_RX_DATA_FAILURE;
if (validate_name_string(sms->name, sizeof (sms->name), NULL) != SUCCESS)
return TLV_RX_DATA_FAILURE;
if (op == TLV_OP_NEW) {
if (it->op == TLV_OP_NEW) {
int fd;
char path_name[MAX_PATH_SIZE];
sprintf(path_name, "%s/%s:%s", smsRx_dir, cryptShaAsString(&on->nodeId), sms->name);
sprintf(path_name, "%s/%s:%s", smsRx_dir, cryptShaAsString(&it->on->k.nodeId), sms->name);
if ((fd = open(path_name, O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) < 0) {
@@ -289,9 +288,9 @@ int process_description_sms(struct rx_frame_iterator *it)
}
}
} while ((pos = pos + mlen) < it->frame_msgs_length);
} while ((pos = pos + mlen) < it->f_msgs_len);
if (pos != it->frame_msgs_length)
if (pos != it->f_msgs_len)
return TLV_RX_DATA_FAILURE;
return pos;

View File

@@ -32,7 +32,7 @@
#define DEF_SMS_FZIP TYP_FZIP_DO
#define ARG_SMS_FREF "refSms"
#define DEF_SMS_FREF TYP_FREF_DO
#define DEF_SMS_FREF TYP_FREF_DO1
struct sms_node {

View File

@@ -5,8 +5,8 @@ LDFLAGS += -shared
PLUGIN_NAME = bmx6_table
SRC_C = table.c
SRC_H = table.h
SRC_C = table.c ../../redist.c
SRC_H = table.h ../../redist.h
OBJS= $(SRC_C:.c=.o)
PLUGIN_FULLNAME = $(PLUGIN_NAME).so

View File

@@ -48,9 +48,9 @@
#include "iptools.h"
#include "ip.h"
#include "hna.h"
#include "redist.h"
#include "allocate.h"
#include "table.h"
#include "redist.c"
#define CODE_CATEGORY_NAME "table"
@@ -60,58 +60,64 @@ static AVL_TREE(redist_in_tree, struct redist_in_node, k);
static AVL_TREE(redist_opt_tree, struct redistr_opt_node, nameKey);
static AVL_TREE(redist_out_tree, struct redist_out_node, k);
static LIST_SIMPEL(tunXin6_net_adv_list, struct tunXin6_net_adv_node, list, list);
static LIST_SIMPEL(table_net_adv_list, struct tunXin6_net_adv_node, list, list);
static struct sys_route_dict rtredist_rt_dict[BMX6_ROUTE_MAX];
static struct sys_route_dict rtredist_rt_dict[BMX6_ROUTE_MAX_SUPP+1];
int32_t rtredist_delay = DEF_REDIST_DELAY;
int rtevent_sk = 0;
int32_t rtredist_delay = 200;
STATIC_FUNC
void redist_table_routes(void* laterp)
void redist_table_routes(IDM_T forceChanged)
{
struct redist_in_node *rin;
struct redist_in_node rii;
struct avl_node *an=NULL;
memset(&rii, 0, sizeof (rii));
while ((rin = avl_next_item(&redist_in_tree, &rii.k))) {
rii = *rin;
ASSERTION(-502300, matching_redist_opt(rin, &redist_opt_tree, rtredist_rt_dict));
if (!forceChanged && rin->old != (!!rin->cnt))
forceChanged = YES;
if (rin->cnt <= 0)
debugFree( avl_remove(&redist_in_tree, &rin->k, -300551), -300554);
}
if ( forceChanged) {
if ( redistribute_routes(&redist_out_tree, &redist_in_tree, &redist_opt_tree, rtredist_rt_dict) )
update_tunXin6_net_adv_list(&redist_out_tree, &table_net_adv_list);
}
while ((rin=avl_iterate_item(&redist_in_tree, &an)))
rin->old = 1;
dbgf(forceChanged ? DBGL_SYS : DBGL_CHANGES, DBGT_INFO, " %sCHANGED out.items=%d in.items=%d opt.items=%d net_advs=%d",
forceChanged ? "" : "UN",
redist_out_tree.items, redist_in_tree.items, redist_opt_tree.items, table_net_adv_list.items);
}
STATIC_FUNC
void schedule_table_routes(void* laterp)
{
static IDM_T scheduled = NO;
if ( laterp && !scheduled) {
scheduled = YES;
task_register(rtredist_delay, redist_table_routes, NULL, -300550);
task_register(rtredist_delay, schedule_table_routes, NULL, -300550);
} else if ( !laterp ) {
dbgf_track(DBGT_INFO, " ");
scheduled = NO;
task_remove(redist_table_routes, NULL);
IDM_T changed = NO;
struct redist_in_node *rin;
struct redist_in_node rii;
struct avl_node *an=NULL;
memset(&rii, 0, sizeof (rii));
while ((rin = avl_next_item(&redist_in_tree, &rii.k))) {
rii = *rin;
if (rin->old != rin->cnt)
changed = YES;
if (rin->cnt <= 0)
debugFree( avl_remove(&redist_in_tree, &rin->k, -300551), -300554);
}
if ( changed) {
if ( redistribute_routes(&redist_out_tree, &redist_in_tree, &redist_opt_tree, rtredist_rt_dict) )
update_tunXin6_net_adv_list(&redist_out_tree, &tunXin6_net_adv_list);
}
while ((rin=avl_iterate_item(&redist_in_tree, &an)))
rin->old = 1;
dbgf_track(DBGT_INFO, "%sCHANGED out.items=%d in.items=%d opt.items=%d net_advs=%d",
changed ? "" : "UN",
redist_out_tree.items, redist_in_tree.items, redist_opt_tree.items, tunXin6_net_adv_list.items);
task_remove(schedule_table_routes, NULL);
redist_table_routes(NO);
}
}
@@ -129,52 +135,65 @@ void get_route_list_nlhdr(struct nlmsghdr *nh, void *unused )
struct net_key net = {.af=rtm->rtm_family, .mask=rtm->rtm_dst_len,
.ip=(rtm->rtm_family==AF_INET6) ? *((IPX_T *) RTA_DATA(rtap)) : ip4ToX(*((IP4_T *) RTA_DATA(rtap))) };
dbgf_sys(DBGT_INFO, "%s route=%s table=%d protocol=%s", nh->nlmsg_type==RTM_NEWROUTE?"ADD":"DEL",
netAsStr(&net), rtm->rtm_table, rtredist_rt_dict[rtm->rtm_protocol].sys2Name);
dbgf_track(DBGT_INFO, "%s route=%s table=%d protocol=%s", nh->nlmsg_type==RTM_NEWROUTE?"ADD":"DEL",
netAsStr(&net), rtm->rtm_table, memAsHexStringSep(&rtm->rtm_protocol, 1, 0, NULL));
struct redist_in_node new = {.k = {.table = rtm->rtm_table, .inType = rtm->rtm_protocol, .net = net}};
struct redist_in_node *rin = avl_find_item(&redist_in_tree, &new.k);
assertion(-501527, IMPLIES(nh->nlmsg_type==RTM_DELROUTE, rin && rin->cnt>0));
if (rin) {
rin->cnt += (nh->nlmsg_type==RTM_NEWROUTE ? 1 : -1);
} else {
ASSERTION(-502301, (rin->roptn && rin->roptn == matching_redist_opt(&new, &redist_opt_tree, rtredist_rt_dict)));
assertion(-501527, IMPLIES(nh->nlmsg_type==RTM_DELROUTE, (rin->cnt>0)));
rin->cnt += (nh->nlmsg_type==RTM_NEWROUTE ? 1 : -1);
schedule_table_routes((void*)1);
} else if ((new.roptn = matching_redist_opt(&new, &redist_opt_tree, rtredist_rt_dict))) {
assertion(-502302, (nh->nlmsg_type == RTM_NEWROUTE));
rin = debugMalloc(sizeof(new), -300552);
*rin = new;
rin->cnt = 1;
avl_insert(&redist_in_tree, rin, -300553);
schedule_table_routes((void*)1);
}
redist_table_routes((void*)1);
}
rtap = RTA_NEXT(rtap, rtl);
}
}
STATIC_FUNC
int32_t sync_redist_routes(IDM_T cleanup, IDM_T resync);
static void recv_rtevent_netlink_sk(int sk)
{
TRACE_FUNCTION_CALL;
char buf[4096]; //test this with a very small value !!
struct sockaddr_nl sa;
struct iovec iov = {.iov_base = buf, .iov_len = sizeof (buf)};
assertion(-501528, (sk==rtevent_sk));
// char buf[4096]; //test this with a very small value !!
// struct sockaddr_nl sa;
// struct iovec iov = {.iov_base = buf, .iov_len = sizeof(buf)};
// assertion(-501528, (sk==rtevent_sk));
dbgf_all(DBGT_INFO, "detected changed routes! Going to check...");
/*
struct msghdr msg; // = {(void *) & sa, sizeof (sa), &iov, 1, NULL, 0, 0};
memset( &msg, 0, sizeof( struct msghdr));
msg.msg_name = (void *)&sa;
msg.msg_namelen = sizeof(sa); /* Length of address data. */
msg.msg_iov = &iov; /* Vector of data to send/receive into. */
msg.msg_iovlen = 1; /* Number of elements in the vector. */
msg.msg_namelen = sizeof(sa); // Length of address data.
msg.msg_iov = &iov; // Vector of data to send/receive into.
msg.msg_iovlen = 1; // Number of elements in the vector.
*/
int result = rtnl_rcv( sk, 0, 0, IP_ROUTE_GET, NO, get_route_list_nlhdr, NULL );
rtnl_rcv( sk, 0, 0, IP_ROUTE_GET, NO, get_route_list_nlhdr, NULL );
if (result != SUCCESS)
sync_redist_routes(NO, YES);
}
static int open_rtevent_netlink_sk(void)
STATIC_FUNC
int open_rtevent_netlink_sk(void)
{
int rtevent_sk = 0;
struct sockaddr_nl sa;
int32_t unix_opts;
memset (&sa, 0, sizeof(sa));
@@ -202,19 +221,94 @@ static int open_rtevent_netlink_sk(void)
return -1;
}
int oldBuff=0;
socklen_t oldSize = sizeof(oldBuff);
int buffsize = 66560; // 532480; // 266240; // 133120 // 66560 // RTNL_RCV_MAX //seems all too small for 2K+ routes and heavy CPU load
int newBuff=0;
socklen_t newSize = sizeof(newBuff);
if (
getsockopt(rtevent_sk, SOL_SOCKET, SO_RCVBUF, &oldBuff, &oldSize) < 0 ||
setsockopt(rtevent_sk, SOL_SOCKET, SO_RCVBUFFORCE, &buffsize, sizeof(buffsize)) < 0 ||
getsockopt(rtevent_sk, SOL_SOCKET, SO_RCVBUF, &newBuff, &newSize) < 0 ||
newBuff < RTNL_RCV_MAX) {
dbgf_sys(DBGT_WARN, "can't setsockopts buffsize from=%d to=%d now=%d %s", oldBuff, buffsize, newBuff, strerror(errno));
rtevent_sk = 0;
return -1;
}
dbgf_sys(DBGT_ERR, "setsockopts buffsize from=%d to=%d now=%d", oldBuff, buffsize, newBuff);
set_fd_hook( rtevent_sk, recv_rtevent_netlink_sk, ADD);
return rtevent_sk;
}
static void close_rtevent_netlink_sk(void)
STATIC_FUNC
int close_rtevent_netlink_sk(int rtevent_sk)
{
set_fd_hook(rtevent_sk, recv_rtevent_netlink_sk, DEL);
if ( rtevent_sk > 0 )
close( rtevent_sk );
rtevent_sk = 0;
return 0;
}
STATIC_FUNC
int32_t sync_redist_routes(IDM_T cleanup, IDM_T resync)
{
static int rtevent_sk = 0;
if (cleanup) {
rtevent_sk = close_rtevent_netlink_sk(rtevent_sk);
set_tunXin6_net_adv_list(DEL, &table_net_adv_list);
while (redist_in_tree.items)
debugFree(avl_remove_first_item(&redist_in_tree, -300487), -300488);
while (redist_out_tree.items) {
debugFree(avl_remove_first_item(&redist_out_tree, -300513), -300514);
my_description_changed = YES;
}
while (table_net_adv_list.items)
debugFree(list_del_head(&table_net_adv_list), -300515);
} else if (resync) {
dbgf_sys(DBGT_ERR, "rt-events out of sync. Trying to resync...");
rtevent_sk = close_rtevent_netlink_sk(rtevent_sk);
while (redist_in_tree.items)
debugFree(avl_remove_first_item(&redist_in_tree, -300487), -300488);
rtevent_sk = open_rtevent_netlink_sk();
kernel_get_route(NO, AF_INET, 0, get_route_list_nlhdr);
kernel_get_route(NO, AF_INET6, 0, get_route_list_nlhdr);
redist_table_routes(YES);
} else {
kernel_get_route(NO, AF_INET, 0, get_route_list_nlhdr);
kernel_get_route(NO, AF_INET6, 0, get_route_list_nlhdr);
set_tunXin6_net_adv_list(ADD, &table_net_adv_list);
rtevent_sk = open_rtevent_netlink_sk();
}
return rtevent_sk;
}
STATIC_FUNC
@@ -233,30 +327,15 @@ int32_t opt_redistribute(uint8_t cmd, uint8_t _save, struct opt_type *opt, struc
dbgf_track(DBGT_INFO, "Initializing...");
kernel_get_route(NO, AF_INET, 0, get_route_list_nlhdr);
kernel_get_route(NO, AF_INET6, 0, get_route_list_nlhdr);
/*
struct redist_in_node *rin;
struct avl_node *an=NULL;
while ((rin=avl_iterate_item(&redist_in_tree, &an))) {
dbgf_track(DBGT_INFO, "current routes: net=%s table=%d cnt=%d",
netAsStr(&rin->k.net), rin->k.table, rin->cnt);
}
*/
set_tunXin6_net_adv_list(ADD, &tunXin6_net_adv_list);
open_rtevent_netlink_sk();
set_fd_hook( rtevent_sk, recv_rtevent_netlink_sk, ADD);
sync_redist_routes(NO, NO);
initialized = YES;
}
if (cmd == OPT_SET_POST && initialized && changed) {
dbgf_track(DBGT_INFO, "Updating...");
redist_table_routes(NULL);
// redist_table_routes(YES);
sync_redist_routes(NO, YES);
changed = NO;
}
@@ -265,21 +344,7 @@ int32_t opt_redistribute(uint8_t cmd, uint8_t _save, struct opt_type *opt, struc
dbgf_track(DBGT_INFO, "Cleaning up...");
set_tunXin6_net_adv_list(DEL, &tunXin6_net_adv_list);
set_fd_hook(rtevent_sk, recv_rtevent_netlink_sk, DEL);
close_rtevent_netlink_sk();
while (redist_in_tree.items)
debugFree(avl_remove_first_item(&redist_in_tree, -300487), -300488);
while (redist_out_tree.items) {
debugFree(avl_remove_first_item(&redist_out_tree, -300513), -300514);
my_description_changed = YES;
}
while (tunXin6_net_adv_list.items)
debugFree(list_del_head(&tunXin6_net_adv_list), -300515);
sync_redist_routes(YES, NO);
initialized = NO;
changed = NO;
@@ -292,6 +357,9 @@ int32_t opt_redistribute(uint8_t cmd, uint8_t _save, struct opt_type *opt, struc
static struct opt_type rtredist_options[]= {
// ord parent long_name shrt Attributes *ival min max default *func,*syntax,*help
{ODI,0,ARG_REDIST_DELAY, 0,9,1, A_PS1, A_ADM, A_DYI, A_CFA, A_ANY, &rtredist_delay,MIN_REDIST_DELAY,MAX_REDIST_DELAY,DEF_REDIST_DELAY,0, 0,
ARG_VALUE_FORM, HLP_REDIST_DELAY}
,
{ODI,0,ARG_REDIST, 0,9,2,A_PM1N,A_ADM,A_DYI,A_CFA,A_ANY, 0, 0, 0, 0,0, opt_redistribute,
ARG_NAME_FORM, HLP_REDIST},
{ODI,ARG_REDIST,ARG_REDIST_NET, 'n',9,2,A_CS1,A_ADM,A_DYI,A_CFA,A_ANY, 0, 0, 0, 0,0, opt_redistribute,
@@ -308,6 +376,10 @@ static struct opt_type rtredist_options[]= {
ARG_VALUE_FORM, HLP_REDIST_AGGREGATE},
{ODI,ARG_REDIST,ARG_REDIST_BW, 'b',9,2,A_CS1,A_ADM,A_DYI,A_CFA,A_ANY, 0, 0, 0, 0,0, opt_redistribute,
ARG_VALUE_FORM, HLP_REDIST_BW},
{ODI,ARG_REDIST,ARG_ROUTE_SYS, 0,9,2,A_CS1,A_ADM,A_DYI,A_CFA,A_ANY, 0, 0, BMX6_ROUTE_MAX_SUPP,0,0, opt_redistribute,
ARG_VALUE_FORM, HLP_ROUTE_SYS},
{ODI,ARG_REDIST,ARG_ROUTE_ALL, 0,9,2,A_CS1,A_ADM,A_DYI,A_CFA,A_ANY, 0, 0, 1, 0,0, opt_redistribute,
ARG_VALUE_FORM, HLP_ROUTE_TYPE},
{ODI,ARG_REDIST,ARG_ROUTE_KERNEL, 0,9,2,A_CS1,A_ADM,A_DYI,A_CFA,A_ANY, 0, 0, 1, 0,0, opt_redistribute,
ARG_VALUE_FORM, HLP_ROUTE_TYPE},
{ODI,ARG_REDIST,ARG_ROUTE_BOOT, 0,9,2,A_CS1,A_ADM,A_DYI,A_CFA,A_ANY, 0, 0, 1, 0,0, opt_redistribute,

View File

@@ -15,6 +15,13 @@
* 02110-1301, USA
*/
#define ARG_REDIST_DELAY "redistTableDelay"
#define HLP_REDIST_DELAY "delay processing (and announcement) of changed table routes in ms to aggregate shortly following changes"
#define MIN_REDIST_DELAY 100
#define MAX_REDIST_DELAY 3600000
#define DEF_REDIST_DELAY 2200
#define ARG_REDIST "redistTable"
#define HLP_REDIST "arbitrary but unique name for redistributed table network(s) depending on sub criterias"

View File

@@ -1,15 +1,15 @@
2009-08-10 - bmx6_config plugin for openWrt universial configuraton interface (UCI)
bmx6_config plugin for openWrt universial configuraton interface (UCI)
- plugin for dynamic interaction with uci
( http://downloads.openwrt.org/sources/uci-0.7.5.tar.gz )
- to compile first install uci:
- To compile first install uci (old version):
wget http://downloads.openwrt.org/sources/uci-0.7.5.tar.gz
sometimes theres an error: edit cli.c # change line 465 to: char *argv[MAX_ARGS+2];
tar xzvf uci-0.7.5.tar.gz; cd uci-0.7.5; make; sudo make install
- Alternatively check: http://www.wakoond.hu/2013/06/using-uci-on-ubuntu.html
- default configuration backend is: /etc/config/bmx6
- Default configuration backend is: /etc/config/bmx6
- see lib/bmx6_config/etc_config for a simple (bmx)
and an advanced (bmx-advanced) example

View File

@@ -1,6 +1,6 @@
CFLAGS += $(CORE_CFLAGS) -fpic -I../../
LDFLAGS += -shared -luci
CFLAGS += $(CORE_CFLAGS) -fpic -I../../ -I/usr/local/include/uci/
LDFLAGS += -luci
#-Wl,-soname,bmx6_config
PLUGIN_NAME = bmx6_config
@@ -19,7 +19,7 @@ all: $(PLUGIN_FULLNAME) Makefile
$(PLUGIN_FULLNAME): $(OBJS) Makefile
$(CC) $(LDFLAGS) $(EXTRA_LDFLAGS) $(OBJS) -o $(PLUGIN_FULLNAME)
$(CC) -shared $(OBJS) $(LDFLAGS) $(EXTRA_LDFLAGS) -o $(PLUGIN_FULLNAME)
ln -f -s $(THISDIR)/$(PLUGIN_FULLNAME) $(THISDIR)/../$(PLUGIN_FULLNAME)
%.o: %.c %.h Makefile

866
link.c Normal file
View File

@@ -0,0 +1,866 @@
/*
* Copyright (c) 2010 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
*/
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
//#include "math.h"
#include "list.h"
#include "control.h"
#include "bmx.h"
#include "crypt.h"
#include "avl.h"
#include "node.h"
#include "key.h"
#include "metrics.h"
#include "ogm.h"
#include "link.h"
#include "msg.h"
#include "content.h"
#include "ip.h"
#include "plugin.h"
#include "schedule.h"
#include "tools.h"
#include "iptools.h"
#include "allocate.h"
#define CODE_CATEGORY_NAME "metric"
static int32_t my_link_window = DEF_HELLO_SQN_WINDOW;
//int32_t link_ignore_min = DEF_LINK_IGNORE_MIN;
//int32_t link_ignore_max = DEF_LINK_IGNORE_MAX;
STATIC_FUNC
UMETRIC_T timeaware_rx_probe(LinkNode *link)
{
if (((TIME_T) (bmx_time - link->rx_probe_record.hello_time_max)) < RP_ADV_DELAY_TOLERANCE)
return link->rx_probe_record.hello_umetric;
if (((TIME_T) (bmx_time - link->rx_probe_record.hello_time_max)) < RP_ADV_DELAY_RANGE) {
return (link->rx_probe_record.hello_umetric *
((UMETRIC_T) (RP_ADV_DELAY_RANGE - (bmx_time - link->rx_probe_record.hello_time_max)))) /
RP_ADV_DELAY_RANGE;
}
return 0;
}
STATIC_FUNC
UMETRIC_T timeaware_tx_probe(LinkNode *link)
{
if (((TIME_T) (bmx_time - link->rp_time_max)) < TP_ADV_DELAY_TOLERANCE)
return link->tx_probe_umetric;
if (((TIME_T) (bmx_time - link->rp_time_max)) < TP_ADV_DELAY_RANGE) {
return ((link->tx_probe_umetric * ((UMETRIC_T) (TP_ADV_DELAY_RANGE - (bmx_time - link->rp_time_max)))) / TP_ADV_DELAY_RANGE);
}
return 0;
}
STATIC_FUNC
void lndev_assign_best(struct neigh_node *onlyLocal, LinkNode *onlyLink )
{
TRACE_FUNCTION_CALL;
assertion(-501133, (IMPLIES(onlyLink, onlyLocal && onlyLocal == onlyLink->k.linkDev->key.local)));
ASSERTION(-500792, (IMPLIES(onlyLink, onlyLink->k.linkDev == avl_find_item(&onlyLocal->linkDev_tree, &onlyLink->k.linkDev->key.devIdx))));
dbgf_all(DBGT_INFO, "only_local=%s link: nbLlIp=%s nbIdx=%d mydev=%s",
onlyLocal ? cryptShaAsString(&onlyLocal->local_id) : 0,
onlyLink ? ip6AsStr(&onlyLink->k.linkDev->key.llocal_ip) : DBG_NIL,
onlyLink ? onlyLink->k.linkDev->key.devIdx : 0,
onlyLink ? onlyLink->k.myDev->label_cfg.str : DBG_NIL);
struct avl_node *local_an = NULL;
struct neigh_node *local;
while ((local = onlyLocal) || (local = avl_iterate_item(&local_tree, &local_an))) {
// assertion(-500794, (local->linkDev_tree.items));
LinkDevNode *linkDev = NULL;
struct avl_node *link_an = NULL;
UMETRIC_T old_timeaware_tx_probe = 0;
if (local->best_rp_link)
local->best_rp_link->timeaware_rx_probe = timeaware_rx_probe(local->best_rp_link);
if (local->best_tp_link) {
old_timeaware_tx_probe = local->best_tp_link->timeaware_tx_probe;
local->best_tp_link->timeaware_tx_probe = timeaware_tx_probe(local->best_tp_link);
}
dbgf_all(DBGT_INFO, "local_id=%s", cryptShaAsString(&local->local_id));
while ((onlyLink && (linkDev = onlyLink->k.linkDev)) || (linkDev = avl_iterate_item(&local->linkDev_tree, &link_an))) {
LinkNode *currLink = NULL;
dbgf_all(DBGT_INFO, "link=%s", ip6AsStr(&linkDev->key.llocal_ip));
while ((onlyLink && (currLink = onlyLink)) || (currLink = avl_next_item(&linkDev->link_tree, (currLink ? &currLink->k : NULL)))) {
dbgf_all(DBGT_INFO, "lndev=%s items=%d",
currLink->k.myDev->label_cfg.str, linkDev->link_tree.items);
currLink->timeaware_rx_probe = timeaware_rx_probe(currLink);
currLink->timeaware_tx_probe = timeaware_tx_probe(currLink);
if (!local->best_rp_link || local->best_rp_link->timeaware_rx_probe < currLink->timeaware_rx_probe)
local->best_rp_link = currLink;
if (!local->best_tp_link || local->best_tp_link->timeaware_tx_probe < currLink->timeaware_tx_probe)
local->best_tp_link = currLink;
if (onlyLink)
break;
}
if (onlyLink)
break;
}
// assertion(-500406, (local->best_rp_link));
// assertion(-501086, (local->best_tp_link));
if (!local->best_tp_link || local->best_tp_link->timeaware_tx_probe == 0)
local->best_tp_link = local->best_rp_link;
if (sendLinkRevisedOgms && local->best_tp_link && local->best_tp_link->timeaware_tx_probe > old_timeaware_tx_probe) {
struct reference_node *ref = NULL;
while ((ref = avl_next_item(&local->refsByKhash_tree, ref ? &ref->claimedKey : NULL))) {
assertion(-502422, (ref->dhn));
if (ref->dhn->descContent && ref->dhn->descContent->orig)
process_ogm_metric(ref);
}
}
if(onlyLocal)
break;
}
}
void purge_linkDevs(LinkDevKey *onlyLinkDev, struct dev_node *only_dev, IDM_T purgeLocal)
{
TRACE_FUNCTION_CALL;
LinkDevNode *linkDev;
LinkDevKey linkDevKey;
memset(&linkDevKey, 0, sizeof(linkDevKey));
dbgf_all(DBGT_INFO, "only_link_key=%s llip=%s only_dev=%s purgeLocal=%d",
onlyLinkDev ? cryptShaAsString(&onlyLinkDev->local->local_id) : "---", ip6AsStr(onlyLinkDev ? &onlyLinkDev->llocal_ip : NULL),
only_dev ? only_dev->label_cfg.str : DBG_NIL, purgeLocal);
while ((linkDev = (onlyLinkDev ? avl_find_item(&link_dev_tree, onlyLinkDev) : avl_next_item(&link_dev_tree, &linkDevKey)))) {
struct neigh_node *local = linkDev->key.local;
LinkKey linkKey = {NULL,NULL};
LinkNode *link;
assertion(-500940, local);
assertion(-500941, local == avl_find_item(&local_tree, &linkDev->key.local->local_id));
assertion(-500942, linkDev == avl_find_item(&local->linkDev_tree, &linkDev->key.devIdx));
linkDevKey = linkDev->key;
while ((link = avl_next_item(&linkDev->link_tree, &linkKey))) {
linkKey = link->k;
if ((!only_dev || only_dev == link->k.myDev)
//&& (!only_expired || (((TIME_T) (bmx_time - link->pkt_time_max)) > (TIME_T) link_purge_to))
) {
dbgf_track(DBGT_INFO, "purging nbLlIp=%s nbIdx=%d dev=%s",
ip6AsStr(&linkDev->key.llocal_ip), linkDev->key.devIdx, link->k.myDev->label_cfg.str);
purge_orig_router(NULL, NULL, link, NO);
if (link == local->best_rp_link)
local->best_rp_link = NULL;
if (link == local->best_tp_link)
local->best_tp_link = NULL;
avl_remove(&link_tree, &link->k, -300221);
avl_remove(&linkDev->link_tree, &link->k, -300749);
debugFree(link, -300044);
}
}
assertion(-500323, (only_dev || !linkDev->link_tree.items));
if (!linkDev->link_tree.items) {
dbgf_track(DBGT_INFO, "purging: linkDev local_id=%s link_ip=%s only_dev=%s, local->linkDevs=%d",
cryptShaAsString(&linkDev->key.local->local_id), ip6AsStr(&linkDev->key.llocal_ip),
only_dev ? only_dev->label_cfg.str : "???", local->linkDev_tree.items);
avl_remove(&link_dev_tree, &linkDev->key, -300193);
avl_remove(&local->linkDev_tree, &linkDev->key.devIdx, -300330);
assertion(-502423, IMPLIES(!local->linkDev_tree.items, !local->best_rp_link));
assertion(-502424, IMPLIES(!local->linkDev_tree.items, !local->best_tp_link));
debugFree(linkDev, -300045);
if (purgeLocal && !local->linkDev_tree.items)
keyNode_schedLowerWeight(local->on->key, KCPromoted);
}
if (onlyLinkDev)
break;
}
lndev_assign_best(NULL, NULL);
cb_plugin_hooks(PLUGIN_CB_LINKS_EVENT, NULL);
assertion(-502425, IMPLIES(!only_dev && !onlyLinkDev, !link_tree.items));
assertion(-502426, IMPLIES(!only_dev && !onlyLinkDev, !link_dev_tree.items));
}
STATIC_FUNC
IDM_T updateNeighDevId(struct neigh_node *nn, struct desc_content *contents)
{
struct dsc_msg_llip* msg = (struct dsc_msg_llip*) contents_data(contents, BMX_DSC_TLV_LLIP);
uint16_t m, msgs = 0;
LinkDevNode *ldn;
DEVIDX_T idx = 0;
struct avl_node *an = NULL;
if (!contents || (msgs = contents_dlen(contents, BMX_DSC_TLV_LLIP) / sizeof(struct dsc_msg_llip))) {
for (an = NULL; (ldn = avl_iterate_item(&nn->linkDev_tree, &an));)
ldn->purge = YES;
for (m = 0; m < msgs; m++) {
for (an = NULL; (ldn = avl_iterate_item(&nn->linkDev_tree, &an));) {
if (is_ip_equal(&ldn->key.llocal_ip, &msg[m].ip6))
ldn->purge = NO;
}
}
while ((ldn = avl_next_item(&nn->linkDev_tree, &idx))) {
idx = ldn->key.devIdx;
if (ldn->purge)
purge_linkDevs(&ldn->key, NULL, YES);
}
}
return SUCCESS;
}
LinkNode *getLinkNode(struct dev_node *dev, IPX_T *llip, DEVIDX_T idx, struct neigh_node *verifiedNeigh)
{
TRACE_FUNCTION_CALL;
LinkNode *link = NULL;
LinkDevNode *linkDev = NULL;
dbgf_all(DBGT_INFO, "llip=%s local_id=%s local=%s",
ip6AsStr(llip), cryptShaAsString(&verifiedNeigh->local_id), verifiedNeigh ? "yes" : "no");
if (!(linkDev = avl_find_item(&verifiedNeigh->linkDev_tree, &idx))) {
linkDev = debugMallocReset(sizeof(LinkDevNode), -300024);
AVL_INIT_TREE(linkDev->link_tree, LinkNode, k);
linkDev->key.llocal_ip = *llip;
linkDev->key.devIdx = idx;
linkDev->key.local = verifiedNeigh;
avl_insert(&link_dev_tree, linkDev, -300147);
avl_insert(&verifiedNeigh->linkDev_tree, linkDev, -300334);
dbgf_track(DBGT_INFO, "creating new link=%s (total %d)", ip6AsStr(llip), link_dev_tree.items);
updateNeighDevId(verifiedNeigh, verifiedNeigh->on->descContent);
} else if (!is_ip_equal(&linkDev->key.llocal_ip, llip)) {
dbgf_mute(25 , DBGL_SYS, DBGT_ERR, "changed NB=%s devIdx=%d llIp: %s->%s",
cryptShaAsString(&verifiedNeigh->local_id), idx, ip6AsStr(&linkDev->key.llocal_ip), ip6AsStr(llip));
purge_linkDevs(&linkDev->key, NULL, NO);
return NULL;
}
linkDev->pkt_time_max = bmx_time;
LinkKey linkKey = {.linkDev = linkDev, .myDev = dev};
if (!(link = avl_find_item(&linkDev->link_tree, &linkKey))) {
link = debugMallocReset(sizeof(LinkNode), -300023);
link->k = linkKey;
dbgf_track(DBGT_INFO, "creating new lndev %16s %s", ip6AsStr(&linkDev->key.llocal_ip), dev->name_phy_cfg.str);
avl_insert(&linkDev->link_tree, link, -300750);
ASSERTION(-500489, !avl_find(&link_tree, &link->k));
avl_insert(&link_tree, link, -300220);
lndev_assign_best(linkDev->key.local, link);
cb_plugin_hooks(PLUGIN_CB_LINKS_EVENT, NULL);
}
assertion(-502196, (link->k.linkDev == linkDev));
lndev_assign_best(NULL, NULL);
return link;
}
STATIC_FUNC
void update_link_probe_record(LinkNode *link, HELLO_SQN_T sqn, uint8_t probe)
{
TRACE_FUNCTION_CALL;
LinkDevNode *linkDev = link->k.linkDev;
struct lndev_probe_record *lpr = &link->rx_probe_record;
ASSERTION(-501049, ((sizeof (((struct lndev_probe_record*) NULL)->hello_array)) * 8 == MAX_HELLO_SQN_WINDOW));
assertion(-501050, (probe <= 1));
ASSERTION(-501055, (bits_get(lpr->hello_array, MAX_HELLO_SQN_WINDOW, 0, MAX_HELLO_SQN_WINDOW - 1, HELLO_SQN_MASK) == lpr->hello_sum));
if ((linkDev->hello_time_max || linkDev->hello_sqn_max) && linkDev->hello_sqn_max != sqn &&
((HELLO_SQN_MASK)&(linkDev->hello_sqn_max - sqn)) < HELLO_SQN_TOLERANCE)
return;
if (((HELLO_SQN_MASK)&(sqn - lpr->hello_sqn_max)) >= my_link_window) {
memset(lpr->hello_array, 0, MAX_HELLO_SQN_WINDOW/8);
ASSERTION(-500159, is_zero(lpr->hello_array, MAX_HELLO_SQN_WINDOW / 8));
if (probe)
bit_set(lpr->hello_array, MAX_HELLO_SQN_WINDOW, sqn, 1);
lpr->hello_sum = probe;
dbgf_all(DBGT_INFO, "probe=%d probe_sum=%d %d",
probe, lpr->hello_sum, bits_get(lpr->hello_array, MAX_HELLO_SQN_WINDOW, 0, MAX_HELLO_SQN_WINDOW - 1, HELLO_SQN_MASK));
ASSERTION(-501058, (bits_get(lpr->hello_array, MAX_HELLO_SQN_WINDOW, 0, MAX_HELLO_SQN_WINDOW - 1, HELLO_SQN_MASK) == lpr->hello_sum));
} else {
if (sqn != lpr->hello_sqn_max) {
HELLO_SQN_T prev_sqn_min = (HELLO_SQN_MASK)&(lpr->hello_sqn_max + 1 - ((HELLO_SQN_T) my_link_window));
HELLO_SQN_T new_sqn_min_minus_one = (HELLO_SQN_MASK)&(sqn - ((HELLO_SQN_T) my_link_window));
dbgf_all(DBGT_INFO, "prev_min=%5d prev_max=%d new_min=%5d sqn=%5d sum=%3d bits=%3d %s",
prev_sqn_min,lpr->hello_sqn_max, new_sqn_min_minus_one+1, sqn, lpr->hello_sum,
bits_get(lpr->hello_array, MAX_HELLO_SQN_WINDOW, 0, MAX_HELLO_SQN_WINDOW - 1, HELLO_SQN_MASK),
bits_print(lpr->hello_array, MAX_HELLO_SQN_WINDOW, 0, MAX_HELLO_SQN_WINDOW - 1, HELLO_SQN_MASK));
lpr->hello_sum -= bits_get(lpr->hello_array, MAX_HELLO_SQN_WINDOW, prev_sqn_min, new_sqn_min_minus_one, HELLO_SQN_MASK);
dbgf_all(DBGT_INFO, "prev_min=%5d prev_max=%d new_min=%5d sqn=%5d sum=%3d bits=%3d %s",
prev_sqn_min,lpr->hello_sqn_max, new_sqn_min_minus_one+1, sqn, lpr->hello_sum,
bits_get(lpr->hello_array, MAX_HELLO_SQN_WINDOW, 0, MAX_HELLO_SQN_WINDOW - 1, HELLO_SQN_MASK),
bits_print(lpr->hello_array, MAX_HELLO_SQN_WINDOW, 0, MAX_HELLO_SQN_WINDOW - 1, HELLO_SQN_MASK));
bits_clear(lpr->hello_array, MAX_HELLO_SQN_WINDOW, prev_sqn_min, new_sqn_min_minus_one, HELLO_SQN_MASK);
dbgf_all(DBGT_INFO, "prev_min=%5d prev_max=%d new_min=%5d sqn=%5d sum=%3d bits=%3d %s\n",
prev_sqn_min,lpr->hello_sqn_max, new_sqn_min_minus_one+1, sqn, lpr->hello_sum,
bits_get(lpr->hello_array, MAX_HELLO_SQN_WINDOW, 0, MAX_HELLO_SQN_WINDOW - 1, HELLO_SQN_MASK),
bits_print(lpr->hello_array, MAX_HELLO_SQN_WINDOW, 0, MAX_HELLO_SQN_WINDOW - 1, HELLO_SQN_MASK));
}
ASSERTION(-501057, (bits_get(lpr->hello_array, MAX_HELLO_SQN_WINDOW, 0, MAX_HELLO_SQN_WINDOW - 1, HELLO_SQN_MASK) == lpr->hello_sum));
if (!bit_get(lpr->hello_array, MAX_HELLO_SQN_WINDOW, sqn) && probe) {
bit_set(lpr->hello_array, MAX_HELLO_SQN_WINDOW, sqn, 1);
lpr->hello_sum++;
}
ASSERTION(-501056, (bits_get(lpr->hello_array, MAX_HELLO_SQN_WINDOW, 0, MAX_HELLO_SQN_WINDOW - 1, HELLO_SQN_MASK) == lpr->hello_sum));
}
lpr->hello_sqn_max = sqn;
lpr->hello_umetric = (UMETRIC_MAX / my_link_window) * lpr->hello_sum;
lpr->hello_time_max = bmx_time;
linkDev->hello_sqn_max = sqn;
linkDev->hello_time_max = bmx_time;
lndev_assign_best(linkDev->key.local, link);
dbgf_all(DBGT_INFO, "%s metric %ju", ip6AsStr(&linkDev->key.llocal_ip), link->timeaware_rx_probe);
}
STATIC_FUNC
int32_t opt_link_metric(uint8_t cmd, uint8_t _save, struct opt_type *opt, struct opt_parent *patch, struct ctrl_node *cn)
{
TRACE_FUNCTION_CALL;
static int32_t my_link_window_prev = DEF_HELLO_SQN_WINDOW;
if (cmd == OPT_APPLY && !strcmp(opt->name, ARG_HELLO_SQN_WINDOW)) {
LinkNode *link;
struct avl_node *an;
for (an = NULL; (link = avl_iterate_item(&link_tree, &an));) {
struct lndev_probe_record *lpr = &link->rx_probe_record;
if (my_link_window < my_link_window_prev) {
HELLO_SQN_T prev_sqn_min = (HELLO_SQN_MASK)&(lpr->hello_sqn_max + 1 - my_link_window_prev);
HELLO_SQN_T new_sqn_min_minus_one = (HELLO_SQN_MASK)&(lpr->hello_sqn_max - my_link_window);
lpr->hello_sum -= bits_get(lpr->hello_array, MAX_HELLO_SQN_WINDOW, prev_sqn_min, new_sqn_min_minus_one, HELLO_SQN_MASK);
bits_clear(lpr->hello_array, MAX_HELLO_SQN_WINDOW, prev_sqn_min, new_sqn_min_minus_one, HELLO_SQN_MASK);
}
assertion(-501053, (bits_get(lpr->hello_array, MAX_HELLO_SQN_WINDOW, 0, MAX_HELLO_SQN_WINDOW - 1, HELLO_SQN_MASK) == lpr->hello_sum));
assertion(-501061, (lpr->hello_sum <= ((uint32_t)my_link_window)));
lpr->hello_umetric = (UMETRIC_MAX / my_link_window) * lpr->hello_sum;
}
lndev_assign_best(NULL, NULL);
cb_plugin_hooks(PLUGIN_CB_LINKS_EVENT, NULL);
my_link_window_prev = my_link_window;
}
return SUCCESS;
}
STATIC_FUNC
int process_dsc_tlv_llip(struct rx_frame_iterator *it)
{
TRACE_FUNCTION_CALL;
uint8_t op = it->op;
if (op == TLV_OP_TEST) {
uint16_t m = 0;
struct dsc_msg_llip *msg = (struct dsc_msg_llip *)it->f_data;
if (it->f_msgs_fixed > DEVIDX_MAX)
return TLV_RX_DATA_FAILURE;
for (m = 0; m < it->f_msgs_fixed; m++) {
if (!is_ip_valid(&(msg[m].ip6), AF_INET6))
return TLV_RX_DATA_FAILURE;
if( !is_ip_net_equal(&(msg[m].ip6), &IP6_LINKLOCAL_UC_PREF, IP6_LINKLOCAL_UC_PLEN, AF_INET6))
return TLV_RX_DATA_FAILURE;
IDM_T TODO_check_for_each_becoming_neighbor_if_llip_is_unused_then_add_linkDev_and_update_neighDevId_otherwise_ignore;
}
}
if ((op == TLV_OP_NEW || op == TLV_OP_DEL) && it->on->neigh)
updateNeighDevId(it->on->neigh, (op == TLV_OP_NEW ? it->dcNew : NULL));
return it->f_msgs_len;
}
STATIC_FUNC
int create_dsc_tlv_llip(struct tx_frame_iterator *it)
{
TRACE_FUNCTION_CALL;
struct dsc_msg_llip *msg = (struct dsc_msg_llip *)tx_iterator_cache_msg_ptr(it);
int m = 0;
struct avl_node *an = NULL;
struct dev_node *dev;
if ((int)(dev_ip_tree.items * sizeof(struct dsc_msg_llip)) > tx_iterator_cache_data_space_pref(it, 0, 0))
return TLV_TX_DATA_FULL;
while ((dev = avl_iterate_item(&dev_ip_tree, &an))) {
if (!dev->active || dev->linklayer == TYP_DEV_LL_LO)
continue;
if (m > 0 && is_ip_equal(&msg[m-1].ip6, &dev->llipKey.llip))
continue;
msg[m++].ip6 = dev->llipKey.llip;
}
return m * (sizeof(struct dsc_msg_llip));
}
STATIC_FUNC
int32_t tx_msg_hello_adv(struct tx_frame_iterator *it)
{
TRACE_FUNCTION_CALL;
assertion(-500771, (tx_iterator_cache_data_space_pref(it, 0, 0) >= ((int) sizeof(struct msg_hello_adv))));
struct tx_task_node *ttn = it->ttn;
struct msg_hello_adv *adv = (struct msg_hello_adv *) (tx_iterator_cache_msg_ptr(it));
HELLO_SQN_T sqn_in = ttn->key.f.p.dev->link_hello_sqn = ((HELLO_SQN_MASK)&(ttn->key.f.p.dev->link_hello_sqn + 1));
adv->hello_sqn = htons(sqn_in);
dbgf_all(DBGT_INFO, "%s %s SQN %d", ttn->key.f.p.dev->label_cfg.str, ttn->key.f.p.dev->ip_llocal_str, sqn_in);
return sizeof(struct msg_hello_adv);
}
STATIC_FUNC
void schedule_hello_adv(void)
{
static TIME_T next = 0;
if (doNowOrLater(&next, txCasualInterval, 0))
schedule_tx_task(FRAME_TYPE_HELLO_ADV, NULL, NULL, NULL, SCHEDULE_MIN_MSG_SIZE, 0, 0);
}
STATIC_FUNC
int32_t rx_msg_hello_adv(struct rx_frame_iterator *it)
{
TRACE_FUNCTION_CALL;
struct packet_buff *pb = it->pb;
assertion(-502427, (pb->i.verifiedLink));
LinkNode *link = pb->i.verifiedLink;
struct msg_hello_adv *msg = (struct msg_hello_adv*) (it->f_msg);
HELLO_SQN_T hello_sqn = ntohs(msg->hello_sqn);
DEVIDX_T devIdx = link->k.linkDev->key.devIdx;
char *goto_error_code = NULL;
int goto_error_ret = TLV_RX_DATA_PROCESSED;
if (devIdx < DEVIDX_MIN || devIdx > DEVIDX_MAX) {
goto_error_return( finish, "Invalid LinkDevIdx!", TLV_RX_DATA_FAILURE);
}
update_link_probe_record(link, hello_sqn, 1);
finish:
dbgf_mute(10, goto_error_code ? DBGL_SYS : DBGL_ALL, goto_error_code ? DBGT_ERR : DBGT_INFO,
"NB=%s via llip=%s dev=%s SQN=%d linkDevIdx=%d problem=%s",
cryptShaAsShortStr(&pb->p.hdr.keyHash), pb->i.llip_str, pb->i.iif->label_cfg.str, hello_sqn, devIdx, goto_error_code);
return goto_error_ret;
}
STATIC_FUNC
void schedule_hello_reply(void)
{
LinkNode *link;
struct avl_node *an = NULL;
while ((link = avl_iterate_item(&link_tree, &an))) {
schedule_tx_task(ogmIid ? FRAME_TYPE_HELLO_REPLY_IID : FRAME_TYPE_HELLO_REPLY_DHASH, &link->k.linkDev->key.local->local_id,
link->k.linkDev->key.local, link->k.myDev, SCHEDULE_MIN_MSG_SIZE, &link->k.linkDev->key.devIdx, sizeof(DEVIDX_T));
}
}
STATIC_FUNC
int32_t tx_msg_hello_reply(struct tx_frame_iterator *it)
{
TRACE_FUNCTION_CALL;
DEVIDX_T *nbDevIdx = ((DEVIDX_T*) it->ttn->key.data);
struct neigh_node *neigh = it->ttn->neigh;
LinkDevNode *ldn = avl_find_item(&neigh->linkDev_tree, nbDevIdx);
LinkKey lk = {.linkDev = ldn, .myDev = it->ttn->key.f.p.dev};
LinkNode *link = ldn ? avl_find_item(&link_tree, &lk) : NULL;
if (!link || !ldn || ldn->key.devIdx < DEVIDX_MIN) {
dbgf_track(DBGT_INFO, "yet unestablished devIdx=%d link=%p ldn=%p dev=%p neigh=%p for neigh=%s llip=%s dev=%s",
(ldn ? ldn->key.devIdx : 0), link, ldn, lk.myDev, neigh, cryptShaAsString(&neigh->local_id),
ip6AsStr(&ldn->key.llocal_ip), (lk.myDev ? lk.myDev->label_cfg.str : NULL));
return TLV_TX_DATA_DONE;
}
if (ogmIid && it->frame_type == FRAME_TYPE_HELLO_REPLY_IID) {
/*
struct msg_hello_reply_iid* msg = ((struct msg_hello_reply_iid*) tx_iterator_cache_msg_ptr(it));
msg->dest_transmitterIid4x = neigh->on->dhn->myIID4orig;
msg->u.d.receiverDevId = ldn->neighDevId;
msg->u.d.rxLq_63range = (link->timeaware_rx_probe * 63) / UMETRIC_MAX;
msg->u.u16 = htons(msg->u.u16);
return sizeof(struct msg_hello_reply_iid);
*/
} else if (!ogmIid && it->frame_type == FRAME_TYPE_HELLO_REPLY_DHASH) {
struct msg_hello_reply_dhash* msg = ((struct msg_hello_reply_dhash*) tx_iterator_cache_msg_ptr(it));
msg->dest_dhash = neigh->on->descContent->dhn->dhash;
msg->u.d.receiverDevIdx = ldn->key.devIdx;
msg->u.d.rxLq_63range = (link->timeaware_rx_probe * 63) / UMETRIC_MAX;
msg->u.u16 = htons(msg->u.u16);
neigh->on->descContent->dhn->referred_by_me_timestamp = bmx_time;
return sizeof(struct msg_hello_reply_dhash);
}
return TLV_TX_DATA_DONE;
}
STATIC_FUNC
int32_t rx_msg_hello_reply(struct rx_frame_iterator *it)
{
TRACE_FUNCTION_CALL;
struct packet_buff *pb = it->pb;
assertion(-502431, (pb->i.verifiedLink));
struct msg_hello_reply_dhash msg;
if (!ogmIid && it->f_type == FRAME_TYPE_HELLO_REPLY_DHASH) {
if (!cryptShasEqual(&(((struct msg_hello_reply_dhash *) it->f_msg)->dest_dhash), &myKey->currOrig->descContent->dhn->dhash))
return TLV_RX_DATA_PROCESSED;
msg.u.u16 = ntohs(((struct msg_hello_reply_dhash *) it->f_msg)->u.u16);
} else if (ogmIid && it->f_type == FRAME_TYPE_HELLO_REPLY_IID) {
/*
if (self->dhn != iid_get_node_by_neighIID4x(neigh, ((struct msg_hello_reply_iid *) it->f_msg)->dest_transmitterIid4x))
return TLV_RX_DATA_PROCESSED;
msg.u.u16 = ntohs(((struct msg_hello_reply_iid *) it->f_msg)->u.u16);
*/
} else {
return TLV_RX_DATA_PROCESSED;
}
LinkNode *link = pb->i.verifiedLink;
struct neigh_node *neigh = link->k.linkDev->key.local;
if (msg.u.d.receiverDevIdx != link->k.myDev->llipKey.devIdx)
return TLV_RX_DATA_PROCESSED;
link->rp_time_max = bmx_time;
link->tx_probe_umetric = (UMETRIC_MAX * ((UMETRIC_T) (msg.u.d.rxLq_63range))) / 63;
lndev_assign_best(neigh, link);
return TLV_RX_DATA_PROCESSED;
}
struct link_status {
GLOBAL_ID_T *shortId;
GLOBAL_ID_T *globalId;
char* name;
IPX_T neighLocalIp;
uint16_t neighIdx;
IPX_T localIp;
IFNAME_T dev;
uint16_t idx;
uint8_t rxRate;
uint8_t bestRxLink;
uint8_t txRate;
uint8_t bestTxLink;
uint8_t routes;
AGGREG_SQN_T aggSqnSize;
AGGREG_SQN_T aggSqnMax;
uint8_t aggSqnRcvd;
HELLO_SQN_T lastHelloSqn;
TIME_T lastHelloAdv;
};
static const struct field_format link_status_format[] = {
FIELD_FORMAT_INIT(FIELD_TYPE_POINTER_SHORT_ID, link_status, shortId, 1, FIELD_RELEVANCE_HIGH),
FIELD_FORMAT_INIT(FIELD_TYPE_POINTER_GLOBAL_ID, link_status, globalId, 1, FIELD_RELEVANCE_LOW),
FIELD_FORMAT_INIT(FIELD_TYPE_POINTER_CHAR, link_status, name, 1, FIELD_RELEVANCE_HIGH),
FIELD_FORMAT_INIT(FIELD_TYPE_IPX, link_status, neighLocalIp, 1, FIELD_RELEVANCE_HIGH),
FIELD_FORMAT_INIT(FIELD_TYPE_UINT, link_status, neighIdx, 1, FIELD_RELEVANCE_HIGH),
FIELD_FORMAT_INIT(FIELD_TYPE_IPX, link_status, localIp, 1, FIELD_RELEVANCE_MEDI),
FIELD_FORMAT_INIT(FIELD_TYPE_STRING_CHAR, link_status, dev, 1, FIELD_RELEVANCE_HIGH),
FIELD_FORMAT_INIT(FIELD_TYPE_UINT, link_status, idx, 1, FIELD_RELEVANCE_HIGH),
FIELD_FORMAT_INIT(FIELD_TYPE_UINT, link_status, rxRate, 1, FIELD_RELEVANCE_HIGH),
FIELD_FORMAT_INIT(FIELD_TYPE_UINT, link_status, bestRxLink, 1, FIELD_RELEVANCE_MEDI),
FIELD_FORMAT_INIT(FIELD_TYPE_UINT, link_status, txRate, 1, FIELD_RELEVANCE_HIGH),
FIELD_FORMAT_INIT(FIELD_TYPE_UINT, link_status, bestTxLink, 1, FIELD_RELEVANCE_HIGH),
FIELD_FORMAT_INIT(FIELD_TYPE_UINT, link_status, routes, 1, FIELD_RELEVANCE_HIGH),
FIELD_FORMAT_INIT(FIELD_TYPE_UINT, link_status, aggSqnSize, 1, FIELD_RELEVANCE_MEDI),
FIELD_FORMAT_INIT(FIELD_TYPE_UINT, link_status, aggSqnMax, 1, FIELD_RELEVANCE_MEDI),
FIELD_FORMAT_INIT(FIELD_TYPE_UINT, link_status, aggSqnRcvd, 1, FIELD_RELEVANCE_MEDI),
FIELD_FORMAT_INIT(FIELD_TYPE_UINT, link_status, lastHelloSqn, 1, FIELD_RELEVANCE_MEDI),
FIELD_FORMAT_INIT(FIELD_TYPE_UINT, link_status, lastHelloAdv, 1, FIELD_RELEVANCE_MEDI),
FIELD_FORMAT_END
};
static int32_t link_status_creator(struct status_handl *handl, void *data)
{
struct avl_node *linkDev_it, *local_it;
LinkDevNode *linkDev;
struct neigh_node *local;
uint32_t max_size = link_tree.items * sizeof (struct link_status);
uint32_t i = 0;
struct link_status *status = ((struct link_status*) (handl->data = debugRealloc(handl->data, max_size, -300358)));
memset(status, 0, max_size);
for (local_it = NULL; (local = avl_iterate_item(&local_tree, &local_it));) {
struct orig_node *on = local->on;
assertion(-502210, (on));
for (linkDev_it = NULL; (linkDev = avl_iterate_item(&local->linkDev_tree, &linkDev_it));) {
LinkNode *link = NULL;
while ((link = avl_next_item(&linkDev->link_tree, (link ? &link->k : NULL)))) {
status[i].globalId = &on->k.nodeId;
status[i].shortId = &on->k.nodeId;
status[i].name = on->k.hostname;
status[i].neighLocalIp = linkDev->key.llocal_ip;
status[i].neighIdx = linkDev->key.devIdx;
status[i].dev = link->k.myDev->label_cfg;
status[i].idx = link->k.myDev->llipKey.devIdx;
status[i].localIp = link->k.myDev->llipKey.llip;
status[i].rxRate = ((link->timeaware_rx_probe * 100) / UMETRIC_MAX);
status[i].bestRxLink = (link == local->best_rp_link);
status[i].txRate = ((link->timeaware_tx_probe * 100) / UMETRIC_MAX);
status[i].bestTxLink = (link == local->best_tp_link);
status[i].routes = link->orig_routes;
status[i].aggSqnSize = local->ogm_aggreg_size;
status[i].aggSqnMax = local->ogm_aggreg_max;
status[i].aggSqnRcvd = bit_get(local->ogm_aggreg_sqns, AGGREG_SQN_CACHE_RANGE, local->ogm_aggreg_max);
status[i].lastHelloSqn = linkDev->hello_sqn_max;
status[i].lastHelloAdv = ((TIME_T) (bmx_time - linkDev->hello_time_max)) / 1000;
i++;
assertion(-501225, (max_size >= i * sizeof (struct link_status)));
}
}
}
return i * sizeof (struct link_status);
}
STATIC_FUNC
struct opt_type link_options[]=
{
{ODI,0,ARG_LINKS, 0, 9,1,A_PS0N,A_USR,A_DYN,A_ARG,A_ANY, 0, 0, 0, 0,0, opt_status,
0, "show links\n"},
{ODI,0,ARG_HELLO_SQN_WINDOW, 0, 9,1,A_PS1,A_ADM,A_DYI,A_CFA,A_ANY, &my_link_window, MIN_HELLO_SQN_WINDOW, MAX_HELLO_SQN_WINDOW,DEF_HELLO_SQN_WINDOW,0, opt_link_metric,
ARG_VALUE_FORM, "set link window size (LWS) for link-quality calculation (link metric)"}
};
STATIC_FUNC
int32_t init_link( void )
{
register_options_array(link_options, sizeof (link_options), CODE_CATEGORY_NAME);
register_status_handl(sizeof(struct link_status), 1, link_status_format, ARG_LINKS, link_status_creator);
struct frame_handl handl;
memset(&handl, 0, sizeof( handl));
static const struct field_format llip_format[] = DESCRIPTION_MSG_LLIP_FORMAT;
handl.name = "DSC_LLIP";
handl.min_msg_size = sizeof(struct dsc_msg_llip);
handl.fixed_msg_size = 1;
handl.positionMandatory = 0;
handl.dextCompression = (int32_t*) & dflt_fzip;
handl.dextReferencing = (int32_t*) & fref_dflt;
handl.tx_frame_handler = create_dsc_tlv_llip;
handl.rx_frame_handler = process_dsc_tlv_llip;
handl.msg_format = llip_format;
register_frame_handler(description_tlv_db, BMX_DSC_TLV_LLIP, &handl);
handl.name = "HELLO_ADV";
handl.min_msg_size = sizeof(struct msg_hello_adv);
handl.fixed_msg_size = 1;
handl.tx_packet_prepare_casuals = schedule_hello_adv;
handl.tx_msg_handler = tx_msg_hello_adv;
handl.rx_msg_handler = rx_msg_hello_adv;
register_frame_handler(packet_frame_db, FRAME_TYPE_HELLO_ADV, &handl);
handl.name = "HELLO_REPLY";
handl.min_msg_size = sizeof (struct msg_hello_reply_dhash);
handl.fixed_msg_size = 1;
handl.tx_packet_prepare_casuals = schedule_hello_reply;
handl.tx_msg_handler = tx_msg_hello_reply;
handl.rx_msg_handler = rx_msg_hello_reply;
register_frame_handler(packet_frame_db, FRAME_TYPE_HELLO_REPLY_DHASH, &handl);
return SUCCESS;
}
STATIC_FUNC
void cleanup_link( void )
{
}
struct plugin *link_get_plugin( void ) {
static struct plugin link_plugin;
memset( &link_plugin, 0, sizeof ( struct plugin ) );
link_plugin.plugin_name = CODE_CATEGORY_NAME;
link_plugin.plugin_size = sizeof ( struct plugin );
link_plugin.cb_init = init_link;
link_plugin.cb_cleanup = cleanup_link;
return &link_plugin;
}

48
link.h Normal file
View File

@@ -0,0 +1,48 @@
#define DEF_LINK_METRIC_FLAGS (0x0)
#define ARG_LINK_METRIC_FLAGS "linkMetricFlags"
#define ARG_LINKS "links"
struct dsc_msg_llip {
IP6_T ip6;
} __attribute__((packed));
#define DESCRIPTION_MSG_LLIP_FORMAT { \
{FIELD_TYPE_IPX6, -1, 128, 1, FIELD_RELEVANCE_HIGH, "address" }, \
FIELD_FORMAT_END }
struct msg_hello_adv { // 2 bytes
HELLO_SQN_T hello_sqn;
} __attribute__((packed));
struct msg_hello_reply_data {
#if __BYTE_ORDER == __LITTLE_ENDIAN
unsigned int rxLq_63range : 6;
unsigned int receiverDevIdx : DEVIDX_BITS;
#elif __BYTE_ORDER == __BIG_ENDIAN
unsigned int receiverDevIdx : DEVIDX_BITS;
unsigned int rxLq_63range : 6;
#else
#error "Please fix <bits/endian.h>"
#endif
} __attribute__((packed));
struct msg_hello_reply_dhash {
DHASH_T dest_dhash;
union {
struct msg_hello_reply_data d;
uint16_t u16;
} u;
} __attribute__((packed));
//IDM_T updateNeighDevId(struct neigh_node *nn, struct desc_content *contents);
LinkNode *getLinkNode(struct dev_node *dev, IPX_T *llip, DEVIDX_T idx, struct neigh_node *verifiedNeigh);
void purge_linkDevs(LinkDevKey *onlyLinkDev, struct dev_node *only_dev, IDM_T purgeLocal);
struct plugin *link_get_plugin(void);

907
metrics.c

File diff suppressed because it is too large Load Diff

118
metrics.h
View File

@@ -22,8 +22,6 @@
*/
#define MIN_DESC_METRICALGO 0
#define MAX_DESC_METRICALGO 1
#define DEF_DESC_METRICALGO 1
@@ -76,64 +74,46 @@
#define ARG_PATH_TP_EXP_DIVISOR "txExpDivisor"
#define CHR_PATH_TP_EXP_DIVISOR 't'
#define MAX_PATH_WINDOW 250 /* 250 TBD: should not be larger until ogm->ws and neigh_node.packet_count (and related variables) is only 8 bit */
#define MIN_PATH_WINDOW 1
#define DEF_PATH_WINDOW 5 /* 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_PATH_WINDOW "pathWindow"
//extern int32_t my_path_window; // my path window size used to quantify the end to end path quality between me and other nodes
#define MIN_PATH_LQ_TX_R255 0
#define MAX_PATH_LQ_TX_R255 254
#define DEF_PATH_LQ_TX_R255 ((255*2)/3)
#define ARG_PATH_LQ_TX_R255 "pathLqXThreshold"
#define MIN_PATH_LOUNGE 0
#define MAX_PATH_LOUNGE 10
#define DEF_PATH_LOUNGE 1
#define ARG_PATH_LOUNGE "pathLounge"
//extern int32_t my_path_lounge;
#define MIN_PATH_LQ_TY_R255 0
#define MAX_PATH_LQ_TY_R255 254
#define DEF_PATH_LQ_TY_R255 ((255*1)/3)
#define ARG_PATH_LQ_TY_R255 "pathLqYThreshold"
#define DEF_PATH_REGRESSION_SLOW 1
#define MIN_PATH_REGRESSION_SLOW 1
#define MAX_PATH_REGRESSION_SLOW 255
#define ARG_PATH_REGRESSION_SLOW "pathRegression"
#define MIN_PATH_LQ_T1_R255 1
#define MAX_PATH_LQ_T1_R255 255
#define DEF_PATH_LQ_T1_R255 ((255*9)/10)
#define ARG_PATH_LQ_T1_R255 "pathLq1Threshold"
//#define RP_LINK_LOUNGE 0 /* may also be rtq_link_lounge */
/*
// this deactivates OGM-Acks on the link:
#define MIN_LINK_IGNORE_MIN 0
#define MAX_LINK_IGNORE_MIN 100
#define DEF_LINK_IGNORE_MIN 50
#define ARG_LINK_IGNORE_MIN "link_ignore_min"
//extern int32_t link_ignore_min;
// this activates OGM-Acks on the link:
#define MIN_LINK_IGNORE_MAX 0
#define MAX_LINK_IGNORE_MAX 255
#define DEF_LINK_IGNORE_MAX 100
#define ARG_LINK_IGNORE_MAX "link_ignore_max"
//extern int32_t link_ignore_max;
*/
#define MIN_PATH_HYST 0
#define MAX_PATH_HYST 255
#define DEF_PATH_HYST 0
#define ARG_PATH_HYST "pathHysteresis"
#define MIN_OGM_METRIC_HYST 0
#define MAX_OGM_METRIC_HYST 64000
#define DEF_OGM_METRIC_HYST 10
#define ARG_OGM_METRIC_HYST "pathMetricHysteresis"
//extern int32_t my_path_hystere;
#define MIN_OGM_SQN_LATE_HYST 0
#define MAX_OGM_SQN_LATE_HYST 64000
#define DEF_OGM_SQN_LATE_HYST 2500
#define ARG_OGM_SQN_LATE_HYST "pathLateHysteresis"
#define MIN_LATE_PENAL 0
#define MAX_LATE_PENAL 100
#define DEF_LATE_PENAL 1
#define ARG_LATE_PENAL "latenessPenalty"
//extern int32_t my_late_penalty;
#define MIN_OGM_SQN_BEST_HYST 0
#define MAX_OGM_SQN_BEST_HYST 255
#define DEF_OGM_SQN_BEST_HYST 5
#define ARG_OGM_SQN_BEST_HYST "pathSqnBestHysteresis"
#define DEF_HOP_PENALTY 0 //(U8_MAX/20) <=> 5% penalty on metric per hop
#define MIN_HOP_PENALTY 0 // smaller values than 4 do not show effect
#define MAX_HOP_PENALTY U8_MAX
#define ARG_HOP_PENALTY "hopPenalty"
#define MAX_HOP_PENALTY_PRECISION_EXP 8
#define DEF_OGM_HOP_PENALTY 0 //(U8_MAX/20) <=> 5% penalty on metric per hop
#define MIN_OGM_HOP_PENALTY 0 // smaller values than 4 do not show effect
#define MAX_OGM_HOP_PENALTY U8_MAX
#define ARG_OGM_HOP_PENALTY "pathHopPenalty"
#define MAX_OGM_HOP_PENALTY_PRECISION_EXP 8
//extern int32_t my_hop_penalty;
@@ -162,9 +142,6 @@
#define DEF_PATH_METRIC_FLAGS (0x0)
#define ARG_PATH_METRIC_FLAGS "pathMetricFlags"
#define DEF_LINK_METRIC_FLAGS (0x0)
#define ARG_LINK_METRIC_FLAGS "linkMetricFlags"
@@ -189,16 +166,17 @@ struct mandatory_tlv_metricalgo { // 16 bytes
unsigned int tp_exp_numerator : 2;
unsigned int tp_exp_divisor : 2;
#else
# error "Please fix <bits/endian.h>"
#error "Please fix <bits/endian.h>"
#endif
uint8_t reserved2; // 1 byte
uint8_t path_window_size; // 1 byte
uint8_t path_lounge_size; // 1 byte
uint8_t regression; // 1 byte
uint8_t hystere; // 1 byte
uint8_t hop_penalty; // 1 byte
uint8_t late_penalty; // 1 byte
uint8_t lq_tx_point_r255;
uint8_t lq_ty_point_r255;
uint8_t lq_t1_point_r255;
uint8_t hop_penalty; // 1 byte
uint8_t ogm_sqn_best_hystere;
uint16_t ogm_sqn_late_hystere;
uint16_t ogm_metric_hystere; // 2 byte
} __attribute__((packed));
@@ -217,13 +195,13 @@ struct description_tlv_metricalgo {
{FIELD_TYPE_UINT, -1, 2, 1, FIELD_RELEVANCE_HIGH, ARG_PATH_RP_EXP_DIVISOR }, \
{FIELD_TYPE_UINT, -1, 2, 1, FIELD_RELEVANCE_HIGH, ARG_PATH_TP_EXP_NUMERATOR }, \
{FIELD_TYPE_UINT, -1, 2, 1, FIELD_RELEVANCE_HIGH, ARG_PATH_TP_EXP_DIVISOR }, \
{FIELD_TYPE_UINT, -1, 8, 1, FIELD_RELEVANCE_LOW, "reserved2"}, \
{FIELD_TYPE_UINT, -1, 8, 1, FIELD_RELEVANCE_HIGH, ARG_PATH_WINDOW}, \
{FIELD_TYPE_UINT, -1, 8, 1, FIELD_RELEVANCE_HIGH, ARG_PATH_LOUNGE}, \
{FIELD_TYPE_UINT, -1, 8, 1, FIELD_RELEVANCE_HIGH, ARG_PATH_REGRESSION_SLOW}, \
{FIELD_TYPE_UINT, -1, 8, 1, FIELD_RELEVANCE_LOW , ARG_PATH_HYST}, \
{FIELD_TYPE_UINT, -1, 8, 1, FIELD_RELEVANCE_HIGH, ARG_HOP_PENALTY}, \
{FIELD_TYPE_UINT, -1, 8, 1, FIELD_RELEVANCE_LOW , ARG_LATE_PENAL}, \
{FIELD_TYPE_UINT, -1, 8, 1, FIELD_RELEVANCE_HIGH, ARG_PATH_LQ_TX_R255}, \
{FIELD_TYPE_UINT, -1, 8, 1, FIELD_RELEVANCE_HIGH, ARG_PATH_LQ_TY_R255}, \
{FIELD_TYPE_UINT, -1, 8, 1, FIELD_RELEVANCE_HIGH, ARG_PATH_LQ_T1_R255}, \
{FIELD_TYPE_UINT, -1, 8, 1, FIELD_RELEVANCE_HIGH, ARG_OGM_HOP_PENALTY}, \
{FIELD_TYPE_UINT, -1, 8, 1, FIELD_RELEVANCE_HIGH, ARG_OGM_SQN_BEST_HYST}, \
{FIELD_TYPE_UINT, -1, 16, 1, FIELD_RELEVANCE_HIGH, ARG_OGM_SQN_LATE_HYST}, \
{FIELD_TYPE_UINT, -1, 16, 1, FIELD_RELEVANCE_HIGH, ARG_OGM_METRIC_HYST}, \
FIELD_FORMAT_END }
@@ -231,7 +209,6 @@ extern struct host_metricalgo link_rp_metric_algo;
extern UMETRIC_T UMETRIC_NBDISCOVERY_MIN;
extern UMETRIC_T TX_UMETRIC_OGM_ACK_MIN;
@@ -258,9 +235,8 @@ IDM_T fmetric_cmp(FMETRIC_U16_T a, unsigned char cmp, FMETRIC_U16_T b);
//void apply_metric_algo(UMETRIC_T *out, struct link_dev_node *link, const UMETRIC_T *path, struct host_metricalgo *algo);
UMETRIC_T apply_metric_algo(UMETRIC_T *tr, UMETRIC_T *umetric_max, const UMETRIC_T *path, struct host_metricalgo *algo);
UMETRIC_T apply_lndev_metric_algo(LinkNode *link, const UMETRIC_T *path, struct host_metricalgo *algo);
void lndev_assign_best(struct neigh_node *onlyLocal, LinkNode *onlyLink );
void update_link_probe_record(LinkNode *link, HELLO_SQN_T sqn, uint8_t probe);
IDM_T update_path_metrics(struct packet_buff *pb, struct orig_node *on, OGM_SQN_T in_sqn, UMETRIC_T *in_umetric);

5125
msg.c

File diff suppressed because it is too large Load Diff

975
msg.h

File diff suppressed because it is too large Load Diff

1501
node.c

File diff suppressed because it is too large Load Diff

460
node.h
View File

@@ -23,43 +23,18 @@
#include <netinet/in.h>
#include <linux/if.h>
#include <linux/rtnetlink.h>
#include <netinet/ip.h>
#include <netinet/ip6.h>
#include <netinet/udp.h>
/*
* from iid.h:
*/
typedef uint16_t IID_T;
typedef struct neigh_node IID_NEIGH_T;
typedef struct dhash_node IID_NODE_T;
#define IID_REPOS_SIZE_BLOCK 32
#define IID_REPOS_SIZE_MAX ((IID_T)(-1))
#define IID_REPOS_SIZE_WARN 1024
#define IID_RSVD_UNUSED 0
#define IID_RSVD_MAX 0
#define IID_MIN_USED 1
#define IID_SPREAD_FK 1 /*default=2 , 1 means no spreading #define IID_REPOS_USAGE_WARNING 10 */
struct iid_ref {
IID_T myIID4x;
uint16_t referred_by_neigh_timestamp_sec;
};
struct iid_repos {
IID_T arr_size; // the number of allocated array fields
IID_T min_free; // the first unused array field from the beginning of the array (might be outside of allocated space)
IID_T max_free; // the first unused array field after the last used field in the array (might be outside of allocated space)
IID_T tot_used; // the total number of used fields in the array
union {
uint8_t *u8;
IID_NODE_T **node;
struct iid_ref *ref;
} arr;
};
@@ -113,6 +88,7 @@ typedef uint64_t UMETRIC_T;
struct float_u16 {
union {
struct {
#if __BYTE_ORDER == __LITTLE_ENDIAN
uint8_t mantissa_fm16;
@@ -128,15 +104,14 @@ struct float_u16 {
uint8_t u8[2];
uint16_t u16;
}val;
} val;
};
typedef struct float_u16 FMETRIC_U16_T;
struct float_u8 {
union {
struct {
@@ -158,9 +133,7 @@ typedef struct float_u8 FMETRIC_U8_T;
typedef uint16_t ALGO_T;
struct host_metricalgo {
FMETRIC_U16_T fmetric_u16_min;
UMETRIC_T umetric_min;
@@ -171,37 +144,35 @@ struct host_metricalgo {
uint8_t algo_tp_exp_numerator;
uint8_t algo_tp_exp_divisor;
uint8_t lq_tx_point_r255;
uint8_t lq_ty_point_r255;
uint8_t lq_t1_point_r255;
uint8_t window_size; // MUST be given as multiple of sqn_steps
uint8_t lounge_size; // MUST be given as multiple of sqn_steps e.g. 6
uint8_t regression; // e.g. 16
// uint8_t fast_regression; // e.g. 2
// uint8_t fast_regression_impact; // e.g. 8
uint8_t hystere;
uint8_t hop_penalty;
uint8_t late_penalty;
uint8_t ogm_hop_penalty;
uint8_t ogm_sqn_best_hystere;
uint16_t ogm_sqn_late_hystere;
uint16_t ogm_metric_hystere;
};
struct lndev_probe_record {
HELLO_SQN_T hello_sqn_max; // SQN which has been applied (if equals wa_pos) then wa_unscaled MUST NOT be set again!
uint8_t hello_array[MAX_HELLO_SQN_WINDOW/8];
uint8_t hello_array[MAX_HELLO_SQN_WINDOW / 8];
uint32_t hello_sum;
UMETRIC_T hello_umetric;
TIME_T hello_time_max;
};
struct metric_record {
SQN_T sqn_bit_mask;
SQN_T clr; // SQN upto which waightedAverageVal has been purged
SQN_T clr; // SQN upto which waightedAverageVal has been purged
SQN_T set; // SQN which has been applied (if equals wa_pos) then wa_unscaled MUST NOT be set again!
// UMETRIC_T umetric;
// UMETRIC_T umetric_fast;
// UMETRIC_T umetric;
// UMETRIC_T umetric_fast;
UMETRIC_T umetric;
// UMETRIC_T umetric_prev;
// UMETRIC_T umetric_prev;
};
#define ZERO_METRIC_RECORD {0, 0, 0, 0,0,0}
@@ -210,7 +181,6 @@ struct metric_record {
/*
* from node.h:
*/
@@ -220,43 +190,42 @@ typedef CRYPTSHA1_T DHASH_T;
typedef CRYPTSHA1_T RHASH_T;
#define DEF_LINK_PURGE_TO 100000
#define MIN_LINK_PURGE_TO (MAX_TX_INTERVAL*2)
#define MAX_LINK_PURGE_TO 864000000 /*10 days*/
#define ARG_LINK_PURGE_TO "linkPurgeTimeout"
#define MIN_OGM_PURGE_TO (MAX_OGM_INTERVAL + MAX_TX_INTERVAL)
#define MAX_OGM_PURGE_TO 864000000 /*10 days*/
#define DEF_OGM_PURGE_TO 100000
#define ARG_OGM_PURGE_TO "purgeTimeout"
typedef CRYPTSHA1_T GLOBAL_ID_T;
typedef CRYPTSHA1_T LOCAL_ID_T;
typedef uint16_t DEVIDX_T;
#define DEVIDX_INVALID 0
#define DEVIDX_MIN 1
#define DEVIDX_BITS 10
#define DEVIDX_MASK ((1<<DEVIDX_BITS)-1)
#define DEVIDX_MAX DEVIDX_MASK
typedef struct {
DEVADV_IDX_T dev_idx;
LOCAL_ID_T local_id;
LOCAL_IP_T llip;
DEVIDX_T devIdx;
} __attribute__((packed)) DevKey;
typedef struct {
LOCAL_IP_T llocal_ip;
DEVIDX_T devIdx;
struct neigh_node *local; // set immediately
} __attribute__((packed)) LinkDevKey;
typedef struct {
LinkDevKey key;
IPX_T link_ip;
uint8_t purge;
TIME_T pkt_time_max;
TIME_T hello_time_max;
HELLO_SQN_T hello_sqn_max;
struct neigh_node *local; // set immediately
struct list_head link_list; // list with one link_node_dev element per link
struct avl_tree link_tree;
} LinkDevNode;
typedef struct {
LinkDevNode *linkDev;
struct dev_node *myDev;
@@ -270,176 +239,134 @@ typedef struct {
UMETRIC_T timeaware_tx_probe;
struct lndev_probe_record rx_probe_record;
UMETRIC_T timeaware_rx_probe;
int32_t orig_routes;
struct list_head tx_task_lists[FRAME_TYPE_ARRSZ]; // scheduled frames and messages
int16_t myLinkId;
TIME_T pkt_time_max;
TIME_T rp_time_max;
} LinkNode;
struct neigh_node {
LOCAL_ID_T local_id;
struct avl_tree linkDev_tree;
LinkNode *best_rp_link;
LinkNode *best_tp_link;
LinkNode *best_link;
TIME_T packet_time;
LINKADV_SQN_T packet_link_sqn_ref; //indicating the maximum existing link_adv_sqn
BURST_SQN_T burstSqn;
// the latest received link_adv:
LINKADV_SQN_T link_adv_sqn;
TIME_T link_adv_time;
uint16_t link_adv_msgs;
int16_t neighLinkId;
int16_t myLinkId;
OGM_DEST_T internalNeighId;
struct msg_link_adv *link_adv;
DEVADV_SQN_T link_adv_dev_sqn_ref;
INT_NEIGH_ID_T internalNeighId;
// the latest received dev_adv:
DEVADV_SQN_T dev_adv_sqn;
uint16_t dev_adv_msgs;
struct msg_dev_adv *dev_adv;
// the latest received rp_adv:
TIME_T rp_adv_time;
IDM_T rp_ogm_request_rcvd;
int32_t orig_routes;
struct orig_node *on;
// the old neigh_node:
struct dhash_node *dhn; //TODO remove and use on;
CRYPTKEY_T *pktKey;
IID_T neighIID4me;
struct orig_node *on;
CRYPTKEY_T *pktKey;
struct iid_repos neighIID4x_repos;
TIME_T ogm_new_aggregation_rcvd;
AGGREG_SQN_T ogm_aggregation_cleard_max;
uint8_t ogm_aggregations_not_acked[AGGREG_ARRAY_BYTE_SIZE];
uint8_t ogm_aggregations_rcvd[AGGREG_ARRAY_BYTE_SIZE];
struct avl_tree refsByDhash_tree;
struct avl_tree refsByKhash_tree;
TIME_T ogm_aggreg_time;
AGGREG_SQN_T ogm_aggreg_max;
AGGREG_SQN_T ogm_aggreg_size;
uint8_t ogm_aggreg_sqns[(AGGREG_SQN_CACHE_RANGE / 8)];
};
struct content_usage_node {
struct {
uint32_t expanded_type;
struct content_node *content;
struct desc_content *descContent;
} __attribute__((packed)) k;
struct router_node {
// struct link_dev_key key_2BRemoved;
struct neigh_node *local_key;
struct metric_record mr;
OGM_SQN_T ogm_sqn_last;
UMETRIC_T ogm_umetric_last;
UMETRIC_T best_path_metric; //TODO removed
LinkNode *best_path_link;
};
struct dext_tree_key {
struct desc_extension *dext;
} __attribute__((packed));
struct dext_tree_node {
struct dext_tree_key dext_key;
uint8_t rf_types[(BMX_DSC_TLV_ARRSZ/8) + (BMX_DSC_TLV_ARRSZ%8)];
uint8_t maxUsedLevel;
uint8_t maxAllowedLevel;
uint16_t dup;
};
#define MAX_DESC_LEN (INT32_MAX-1)
#define MAX_REF_NESTING 2
struct ref_node {
SHA1_T rhash;
//struct frame_header_long *frame_hdr;
struct content_node {
SHA1_T chash;
struct key_node *key;
uint8_t *f_body;
uint32_t f_body_len;
uint8_t nested;
uint8_t compression;
uint8_t gzip;
uint8_t reserved;
uint32_t last_usage;
uint32_t usage_counter;
struct avl_tree dext_tree;
struct avl_tree usage_tree;
};
struct desc_tlv_body {
struct refnl_node {
struct list_node list;
struct ref_node *refn;
union {
struct content_usage_node *cun;
uint8_t *desc_tlv_body;
} u;
uint16_t desc_tlv_body_len;
};
struct dext_type_data {
uint32_t len;
uint32_t pos;
};
struct desc_content {
IDM_T cntr;
struct key_node *key;
struct orig_node *orig;
uint8_t *desc_frame;
uint16_t desc_frame_len;
int32_t ref_content_len;
DESC_SQN_T descSqn;
struct desc_extension {
struct list_head refnl_list;
struct dhash_node *dhn;
uint8_t max_nesting;
uint8_t *data;
uint32_t dlen;
struct dext_type_data dtd[BMX_DSC_TLV_ARRSZ];
struct avl_tree contentRefs_tree;
uint32_t unresolvedContentCounter;
uint8_t max_nesting;
struct desc_tlv_body final[BMX_DSC_TLV_ARRSZ];
};
void *dext_dptr( struct desc_extension *dext, uint8_t type);
struct dhash_node {
DHASH_T dhash;
TIME_T referred_by_me_timestamp; // last time this node was referred
TIME_T referred_by_others_timestamp;
struct desc_content *descContent;
uint8_t rejected;
struct avl_tree neighRefs_tree;
};
struct orig_node {
// filled in by validate_new_link_desc0():
GLOBAL_ID_T nodeId;
struct {
char hostname[MAX_HOSTNAME_LEN];
struct dhash_node *dhn;
GLOBAL_ID_T nodeId;
} __attribute__((packed)) k;
// struct dhash_node *dhn; //TODO: remove
// int32_t currKeySupportsPerOrig;
struct desc_content *descContent;
struct key_node *key;
struct neigh_node *neigh;
TIME_T updated_timestamp; // last time this on's desc was succesfully updated
OGM_SQN_T ogmSqn_rangeMin;
OGM_SQN_T ogmSqn_rangeSize;
// filled in by process_desc0_tlvs()->
IPX_T primary_ip;
char primary_ip_str[IPX_STR_LEN];
uint8_t blocked; // blocked description
uint8_t added; // added description
// uint8_t blocked; // blocked description
// uint8_t added; // added description
struct host_metricalgo *path_metricalgo;
char *hostname;
uint32_t *trustedNeighsBitArray;
// calculated by update_path_metric()
uint32_t *trustedNeighsBitArray;
OGM_SQN_T ogmSqn_maxRcvd;
IDM_T ogmAggregActive;
AGGREG_SQN_T ogmAggregSqn;
OGM_SQN_T ogmSqn_next;
UMETRIC_T ogmMetric_next;
OGM_SQN_T ogmSqn_send;
// UMETRIC_T ogmMetric_send;
UMETRIC_T *metricSqnMaxArr; // TODO: remove
struct avl_tree rt_tree;
struct router_node *curr_rt_local; // the currently used local neighbor for routing
TIME_T ogmSqnTime;
OGM_SQN_T ogmSqn;
UMETRIC_T ogmMetric;
LinkNode *curr_rt_link; // the configured route in the kernel!
//size of plugin data is defined during intialization and depends on registered PLUGIN_DATA_ORIG hooks
@@ -447,42 +374,81 @@ struct orig_node {
};
struct dhash_node {
DHASH_T dhash;
TIME_T referred_by_me_timestamp; // last time this dhn was referred
struct neigh_node *local; //TODO: remove and use on!
IID_T myIID4orig;
struct orig_node *on;
uint8_t *desc_frame;
uint16_t desc_frame_len;
struct desc_extension *dext;
struct deprecated_globalId_node *deprecated_globalId;
struct reference_node {
struct dhash_node *dhn;
struct neigh_node *neigh;
struct key_node *claimedKey;
TIME_T mentionedRefTime;
DESC_SQN_T claimedDescSqn;
OGM_SQN_T ogmSqnMax;
TIME_T ogmSqnTime;
TIME_T ogmBestSinceSqn;
AGGREG_SQN_T aggSqn;
FMETRIC_U16_T ogmMetricMax;
uint8_t scheduled_ogm_processing;
uint8_t shown;
};
struct deprecated_globalId_node {
GLOBAL_ID_T globalId;
struct avl_tree deprecated_dhash_tree;
struct key_credits {
uint8_t nQualifying;
uint8_t friend;
uint8_t pktId;
uint8_t pktSign;
struct orig_node *recom;
struct reference_node *ref;
};
struct key_node {
GLOBAL_ID_T kHash;
struct KeyState *bookedState;
struct KeyState *decreasedEffectiveState;
struct content_node *content;
uint8_t dirFriend; //[0,1,2=supportHisDirSupKeys]
TIME_T pktIdTime;
TIME_T pktSignTime;
TIME_T nQTime;
TIME_T TAPTime;
struct avl_tree neighRefs_tree;
struct orig_node *currOrig;
struct desc_content *nextDesc;
struct avl_tree recommendations_tree; //ofMyDirect2SupportedKeys
};
struct schedDecreasedEffectiveState_node {
struct key_node *kn;
};
struct packet_header
{
uint8_t comp_version;
uint8_t reserved;
} __attribute__((packed,__may_alias__));
struct KeyState {
struct {
int16_t numSet;
int16_t numSec;
uint16_t flags;
uint8_t c;
uint8_t r;
struct KeyState *up;
struct KeyState *down;
struct KeyState *left;
struct KeyState *right;
} i;
char *setName;
char *rowName;
char *secName;
int16_t prefBase;
int16_t(* prefGet) (struct key_node *kn);
int16_t maxSet;
void (*setInAction) (GLOBAL_ID_T *kHash, struct key_node **kn, struct KeyState *next);
void (*setOutAction) (struct key_node **kn, struct KeyState *next);
int8_t(* colMaintain) (struct key_node *kn);
int8_t(* colCond) (uint8_t asRow, struct key_node *kn);
int8_t(* rowCond) (struct key_node *kn, struct key_credits *kc);
};
struct packet_header {
uint8_t comp_version;
uint8_t reserved;
CRYPTSHA1_T keyHash;
} __attribute__((packed, __may_alias__));
struct packet_buff {
@@ -500,13 +466,9 @@ struct packet_buff {
//filled in by rx_packet():
IPX_T llip;
char llip_str[INET6_ADDRSTRLEN];
struct dhash_node *verifiedLinkDhn;
LinkNode *verifiedLink;
// LinkDevNode *linkDev;
// IID_T transmittersIID;
// uint32_t rx_counter;
struct key_node *claimedKey;
LinkNode *verifiedLink;
} i;
union {
@@ -517,66 +479,40 @@ struct packet_buff {
};
extern struct packet_buff *curr_rx_packet;
extern struct key_node *myKey;
extern struct orig_node *self;
extern struct iid_repos my_iid_repos;
//extern struct avl_tree dhash_tree;
extern struct avl_tree deprecated_dhash_tree;
extern struct avl_tree deprecated_globalId_tree;
extern struct avl_tree local_tree;
extern struct avl_tree link_dev_tree;
extern struct avl_tree link_tree;
extern struct avl_tree orig_tree;
extern struct avl_tree key_tree;
extern struct avl_tree dhash_tree;
extern uint32_t content_tree_unresolveds;
/***********************************************************
Data Infrastructure
************************************************************/
void iid_purge_repos( struct iid_repos *rep );
void iid_free(struct iid_repos *rep, IID_T iid);
void iid_free_neighIID4x_by_myIID4x( struct iid_repos *rep, IID_T myIID4x);
IDM_T iid_set_neighIID4x(struct iid_repos *neigh_rep, IID_T neighIID4x, IID_T myIID4x);
IID_T iid_new_myIID4x( IID_NODE_T *dhn );
IID_NODE_T* iid_get_node_by_neighIID4x(IID_NEIGH_T *nn, IID_T neighIID4x, IDM_T verbose);
IID_NODE_T* iid_get_node_by_myIID4x( IID_T myIID4x );
void refNode_destroy(struct reference_node *ref, IDM_T reAssessState);
struct reference_node *refNode_update(struct neigh_node *neigh, AGGREG_SQN_T aggSqn, DHASH_T *descHash, struct CRYPTSHA1_T *claimedKey, DESC_SQN_T claimedSqn);
struct dhash_node* dhash_node_create(DHASH_T *dhash, struct neigh_node *neigh);
void dhash_node_reject(struct dhash_node *dhn);
void dhash_clean_data(struct dhash_node *dhn);
LinkNode *getLinkNode(struct dev_node *dev, IPX_T *llip, LINKADV_SQN_T link_sqn, struct dhash_node *verifiedLinkDhn, DEVADV_IDX_T dev_idx);
int purge_orig_router(struct orig_node *onlyOrig, struct neigh_node *onlyNeigh, LinkNode *onlyLink, IDM_T onlyUseless);
void neigh_destroy(struct neigh_node *local);
struct neigh_node *neigh_create(struct orig_node *on);
void badlist_neighbor_if_verified(struct packet_buff *pb);
IDM_T badlist_neighbor(struct packet_buff *pb, DHASH_T *dhash);
void purge_deprecated_globalId_tree( GLOBAL_ID_T *globalId );
//void purge_deprecated_dhash_tree( struct dhash_node *onlyDhn, IDM_T onlyExpired );
void deprecate_dhash_iid( struct dhash_node *dhn, DHASH_T *dhash, GLOBAL_ID_T *globalId );
void purge_orig_router(struct orig_node *onlyOrig, struct neigh_node *onlyNeigh, LinkNode *onlyLink, IDM_T only_useless);
void purge_link_route_orig_nodes(struct dev_node *only_dev, IDM_T only_expired, struct orig_node *except_on);
void block_orig_node(IDM_T block, struct orig_node *on);
void free_orig_node(struct orig_node *on);
struct orig_node *init_orig_node(GLOBAL_ID_T *id);
void destroy_orig_node(struct orig_node *on);
void init_self(void);
SHA1_T *nodeIdFromDescAdv( uint8_t *desc_adv );
char *nodeIdAsStringFromDescAdv( uint8_t *desc_adv );
void purge_local_node(struct neigh_node *local);
void purge_linkDevs(LinkDevKey *onlyLinkDev, struct dev_node *only_dev, IDM_T only_expired);
struct dhash_node *get_dhash_tree_node(DHASH_T *dhash);
void update_orig_dhash(struct orig_node *on, struct dhash_node *dhn);
struct dhash_node* create_dext_dhash(uint8_t *desc_frame, uint32_t desc_frame_len, struct desc_extension* dext, DHASH_T *dhash);
LOCAL_ID_T new_local_id(struct dev_node *dev);
void node_tasks(void);
void cleanup_node(void);
void init_node(void);

603
ogm.c Normal file
View File

@@ -0,0 +1,603 @@
/*
* Copyright (c) 2010 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
*/
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
//#include "math.h"
#include "list.h"
#include "control.h"
#include "bmx.h"
#include "crypt.h"
#include "avl.h"
#include "node.h"
#include "sec.h"
#include "metrics.h"
#include "ogm.h"
#include "msg.h"
#include "desc.h"
#include "ip.h"
#include "plugin.h"
#include "schedule.h"
#include "tools.h"
#include "iptools.h"
#include "allocate.h"
#include "prof.h"
#define CODE_CATEGORY_NAME "ogm"
int32_t ogmIid = NO;
static int32_t ogmSqnRange = DEF_OGM_SQN_RANGE;
static int32_t minMyOgmInterval = DEF_OGM_INTERVAL; /* orginator message interval in miliseconds */
static int32_t maxMyOgmIFactor = DEF_OGM_IFACTOR;
AGGREG_SQN_T ogm_aggreg_sqn_max = 0;
AGGREG_SQN_T ogm_aggreg_sqn_max_window_size = 0;
AGGREG_SQN_T ogm_aggreg_sqn_send = 0;
int32_t sendLinkRevisedOgms = DEF_SEND_LINK_REVISED_OGMS;
STATIC_FUNC
struct avl_tree **ogm_aggreg_origs(AGGREG_SQN_T aggSqn)
{
static struct avl_tree *ogm_aggreg_orig_trees[AGGREG_SQN_CACHE_RANGE] = {NULL};
return &ogm_aggreg_orig_trees[(AGGREG_SQN_CACHE_MASK & aggSqn)];
}
void remove_ogm( struct orig_node *on )
{
if (on->ogmAggregActive) {
AGGREG_SQN_T aggregSqn = on->ogmAggregSqn;
struct avl_tree *aggregSqnOrigs = *ogm_aggreg_origs(aggregSqn);
ASSERTION(-502280, (aggregSqnOrigs && aggregSqnOrigs->items && avl_find(aggregSqnOrigs, &on->k.nodeId)));
on->ogmAggregActive = 0;
avl_remove(aggregSqnOrigs, &on->k.nodeId, -300760);
if (!aggregSqnOrigs->items) {
debugFree(aggregSqnOrigs, -300761);
*ogm_aggreg_origs(aggregSqn) = (struct avl_tree*) NULL;
}
while (ogm_aggreg_sqn_max_window_size && (ogm_aggreg_sqn_max - (ogm_aggreg_sqn_max_window_size - 1)) == aggregSqn && !(*ogm_aggreg_origs(aggregSqn))) {
ogm_aggreg_sqn_max_window_size--;
aggregSqn++;
}
}
}
STATIC_FUNC
void schedule_ogm_aggregations(void)
{
assertion(-502276, ((ogm_aggreg_sqn_max - ogm_aggreg_sqn_send) <= 1));
assertion(-502471, ((*ogm_aggreg_origs(ogm_aggreg_sqn_max))));
assertion(-502275, ((*ogm_aggreg_origs(ogm_aggreg_sqn_max))->items));
if (ogm_aggreg_sqn_max > ogm_aggreg_sqn_send) {
ogm_aggreg_sqn_send = ogm_aggreg_sqn_max;
uint16_t sz = (*ogm_aggreg_origs(ogm_aggreg_sqn_max))->items * sizeof(struct msg_ogm_dhash_adv);
schedule_tx_task(FRAME_TYPE_OGM_DHASH_ADV, NULL, NULL, NULL, sz, &ogm_aggreg_sqn_max, sizeof(ogm_aggreg_sqn_max));
}
}
STATIC_FUNC
void schedule_ogm( struct orig_node *on, OGM_SQN_T ogmSqn, UMETRIC_T um )
{
assertion(-502281, (on && ogmSqn && um));
if ((ogmSqn > on->ogmSqn) || (ogmSqn == on->ogmSqn && um > on->ogmMetric)) {
if (on->ogmAggregActive && on->ogmAggregSqn == ogm_aggreg_sqn_max && ogm_aggreg_sqn_max > ogm_aggreg_sqn_send) {
ASSERTION(-502282, (avl_find((*ogm_aggreg_origs(ogm_aggreg_sqn_max)), &on->k.nodeId)));
} else {
remove_ogm(on);
assertion(-502283, ((ogm_aggreg_sqn_max - ogm_aggreg_sqn_send) <= 1));
if (ogm_aggreg_sqn_max == ogm_aggreg_sqn_send) {
if (ogm_aggreg_sqn_max_window_size >= AGGREG_SQN_CACHE_RANGE) {
struct avl_tree *origs;
while ((origs = *ogm_aggreg_origs(ogm_aggreg_sqn_max + 1))) {
struct orig_node *o = avl_first_item(origs);
dbgf_sys(DBGT_WARN, "Removing scheduled ogmSqn=%d hostname=%s ogmAggActive=%d ogmAggSqn=%d ogmAggSqnMax=%d",
o->ogmSqn, o->k.hostname, o->ogmAggregActive, o->ogmAggregSqn, ogm_aggreg_sqn_max);
assertion(-502472, (o->ogmAggregActive && o->ogmAggregSqn == ((AGGREG_SQN_T)(ogm_aggreg_sqn_max+1-AGGREG_SQN_CACHE_RANGE))));
remove_ogm(o);
}
assertion(-502473, (ogm_aggreg_sqn_max_window_size < AGGREG_SQN_CACHE_RANGE));
}
ogm_aggreg_sqn_max++;
ogm_aggreg_sqn_max_window_size++;
}
if (!(*ogm_aggreg_origs(ogm_aggreg_sqn_max))) {
(*ogm_aggreg_origs(ogm_aggreg_sqn_max)) = debugMallocReset(sizeof(struct avl_tree), -300762);
AVL_INIT_TREE((*(*ogm_aggreg_origs(ogm_aggreg_sqn_max))), struct orig_node, k.nodeId );
}
avl_insert((*ogm_aggreg_origs(ogm_aggreg_sqn_max)), on, -300763);
on->ogmAggregActive = 1;
on->ogmAggregSqn = ogm_aggreg_sqn_max;
}
assertion(-502284, ((ogm_aggreg_sqn_max - ogm_aggreg_sqn_send) == 1));
on->ogmSqn = ogmSqn;
on->ogmMetric = um;
if ((*ogm_aggreg_origs(ogm_aggreg_sqn_max))->items >= OGMS_DHASH_PER_AGGREG_PREF)
schedule_ogm_aggregations();
}
}
STATIC_FUNC
void schedule_my_originator_message(void)
{
TRACE_FUNCTION_CALL;
struct orig_node *on = myKey->currOrig;
if ((on->ogmSqn + 1) > ogmSqnRange) {
my_description_changed = YES;
} else {
schedule_ogm(on, on->ogmSqn + 1, UMETRIC_MAX);
}
}
STATIC_FUNC
void revise_ogm_aggregations(void)
{
assertion(-502276, ((ogm_aggreg_sqn_max - ogm_aggreg_sqn_send) <= 1));
static TIME_T myNextHitchhike = 0;
static TIME_T myNextGuarantee = 0;
TIME_T myGuaranteedInterval = ((minMyOgmInterval * maxMyOgmIFactor) / 100);
IDM_T myNextNow = doNowOrLater(&myNextGuarantee, myGuaranteedInterval, (myKey->currOrig->ogmSqn == 0));
if (myNextNow ||
(ogm_aggreg_sqn_max > ogm_aggreg_sqn_send && *ogm_aggreg_origs(ogm_aggreg_sqn_max) && (*ogm_aggreg_origs(ogm_aggreg_sqn_max))->items)) {
if (doNowOrLater(&myNextHitchhike, minMyOgmInterval, myNextNow)) {
doNowOrLater(&myNextGuarantee, myGuaranteedInterval, YES); //sync the two timeouts!
schedule_my_originator_message();
}
dbgf(myNextNow ? DBGL_CHANGES : DBGL_ALL, DBGT_INFO, "myNextNow=%d myGuaranteedInterval=%d sqnMax=%d sqnSend=%d size=%d max=%d",
myNextNow, myGuaranteedInterval, ogm_aggreg_sqn_max, ogm_aggreg_sqn_send,
(*ogm_aggreg_origs(ogm_aggreg_sqn_max)) ? (*ogm_aggreg_origs(ogm_aggreg_sqn_max))->items : 0,
OGMS_DHASH_PER_AGGREG_PREF);
schedule_ogm_aggregations();
}
}
STATIC_FUNC
int32_t tx_frame_ogm_aggreg_sqn(struct tx_frame_iterator *it)
{
TRACE_FUNCTION_CALL;
assertion(-500771, (tx_iterator_cache_data_space_pref(it, 0, 0) >= ((int) sizeof(struct msg_ogm_aggreg_sqn_adv))));
dbgf_all(DBGT_INFO, "max=%d size=%d", ogm_aggreg_sqn_max, ogm_aggreg_sqn_max_window_size);
struct msg_ogm_aggreg_sqn_adv *adv = (struct msg_ogm_aggreg_sqn_adv *) (tx_iterator_cache_msg_ptr(it));
adv->max = htons(ogm_aggreg_sqn_max);
adv->size = htons(ogm_aggreg_sqn_max_window_size);
return sizeof(struct msg_ogm_aggreg_sqn_adv);
}
STATIC_FUNC
int32_t rx_frame_ogm_aggreg_sqn(struct rx_frame_iterator *it)
{
assertion(-502285, (it && it->f_type == FRAME_TYPE_OGM_AGG_SQN_ADV));
assertion(-502286, (it->pb->i.verifiedLink && it->pb->i.verifiedLink->k.linkDev->key.local));
AGGREG_SQN_T max = ntohs(((struct msg_ogm_aggreg_sqn_adv *) it->f_msg)->max);
AGGREG_SQN_T sz = ntohs(((struct msg_ogm_aggreg_sqn_adv *) it->f_msg)->size);
struct neigh_node *nn = it->pb->i.verifiedLink->k.linkDev->key.local;
dbgf_all(DBGT_INFO, "from neigh=%s max=%d/%d sz=%d/%d time=%d",
nn->on->k.hostname, max, nn->ogm_aggreg_max, sz, nn->ogm_aggreg_size, nn->ogm_aggreg_time);
if ((AGGREG_SQN_MASK & (nn->ogm_aggreg_max - (max + 1))) >= AGGREG_SQN_CACHE_RANGE) {
sz = XMIN(sz, AGGREG_SQN_CACHE_RANGE);
if (nn->ogm_aggreg_time && ((AGGREG_SQN_MASK & (max - nn->ogm_aggreg_max)) < AGGREG_SQN_CACHE_RANGE))
sz = XMIN(sz, (nn->ogm_aggreg_size + (max - nn->ogm_aggreg_max)));
else
sz = XMIN(sz, 1);
nn->ogm_aggreg_size = sz;
if (max != nn->ogm_aggreg_max) {
if ((AGGREG_SQN_MASK & (max - nn->ogm_aggreg_max)) >= sz) {
memset(nn->ogm_aggreg_sqns, 0, sizeof(nn->ogm_aggreg_sqns));
} else {
bits_clear(nn->ogm_aggreg_sqns, AGGREG_SQN_CACHE_RANGE,
((AGGREG_SQN_MASK)& (nn->ogm_aggreg_max + 1)), max, AGGREG_SQN_MASK);
}
nn->ogm_aggreg_max = max;
nn->ogm_aggreg_time = bmx_time;
}
}
return TLV_RX_DATA_PROCESSED;
}
STATIC_FUNC
void schedule_ogm_req(void)
{
struct neigh_node *nn = NULL;
while ((nn = avl_next_item(&local_tree, nn ? &nn->local_id : NULL))) {
if (nn->orig_routes && nn->best_tp_link && (nn->ogm_aggreg_time || nn->ogm_aggreg_max)) { //ever updated:
AGGREG_SQN_T cnt = 0;
for (cnt = 0; cnt < nn->ogm_aggreg_size; cnt++) {
AGGREG_SQN_T sqn = (nn->ogm_aggreg_max - cnt);
if (!bit_get(nn->ogm_aggreg_sqns, AGGREG_SQN_CACHE_RANGE, sqn)) {
struct dev_node *dev = nn->best_tp_link->k.myDev;
schedule_tx_task(FRAME_TYPE_OGM_REQ, &nn->local_id, nn, dev, SCHEDULE_MIN_MSG_SIZE, &sqn, sizeof(sqn));
}
}
}
}
}
STATIC_FUNC
int32_t tx_msg_ogm_aggreg_request(struct tx_frame_iterator *it)
{
AGGREG_SQN_T *sqn = (AGGREG_SQN_T *)it->ttn->key.data;
struct hdr_ogm_aggreg_req *hdr = (struct hdr_ogm_aggreg_req *) tx_iterator_cache_hdr_ptr(it);
struct msg_ogm_aggreg_req *msg = (struct msg_ogm_aggreg_req *) tx_iterator_cache_msg_ptr(it);
IDM_T known = bit_get(it->ttn->neigh->ogm_aggreg_sqns, AGGREG_SQN_CACHE_RANGE, *sqn);
dbgf_track(DBGT_INFO, "sqn=%d known=%d to neigh=%s", *sqn, known, it->ttn->neigh->on->k.hostname);
if (known) {
return TLV_TX_DATA_DONE;
} else {
if (hdr->msg == msg) {
assertion(-502287, (is_zero(hdr, sizeof (*hdr))));
hdr->dest_nodeId = it->ttn->key.f.groupId;
} else {
assertion(-502288, (cryptShasEqual(&hdr->dest_nodeId, &it->ttn->key.f.groupId)));
}
msg->sqn = htons(*sqn);
return sizeof(struct msg_ogm_aggreg_req);
}
}
STATIC_FUNC
int32_t rx_msg_ogm_aggreg_request(struct rx_frame_iterator *it)
{
TRACE_FUNCTION_CALL;
struct hdr_ogm_aggreg_req *hdr = (struct hdr_ogm_aggreg_req*) (it->f_data);
struct msg_ogm_aggreg_req *msg = (struct msg_ogm_aggreg_req*) (it->f_msg);
AGGREG_SQN_T sqn = ntohs(msg->sqn);
if (cryptShasEqual(&hdr->dest_nodeId, &myKey->kHash) && (((AGGREG_SQN_T)(ogm_aggreg_sqn_max - sqn)) < ogm_aggreg_sqn_max_window_size) ) {
struct neigh_node *nn = it->pb->i.verifiedLink->k.linkDev->key.local;
uint16_t ogms = (*ogm_aggreg_origs(sqn)) ? (*ogm_aggreg_origs(sqn))->items : 0;
schedule_tx_task(FRAME_TYPE_OGM_DHASH_ADV, NULL, NULL, nn->best_tp_link->k.myDev, (ogms * sizeof(struct msg_ogm_dhash_adv)), &sqn, sizeof(sqn));
dbgf_track(DBGT_INFO, "sqn=%d ogms=%d", sqn, ogms);
}
return TLV_RX_DATA_PROCESSED;
}
STATIC_FUNC
int32_t tx_frame_ogm_dhash_aggreg_advs(struct tx_frame_iterator *it)
{
struct hdr_ogm_adv *hdr = ((struct hdr_ogm_adv*) tx_iterator_cache_hdr_ptr(it));
AGGREG_SQN_T *sqn = ((AGGREG_SQN_T *)it->ttn->key.data);
struct avl_tree *origs = (*ogm_aggreg_origs(*sqn));
uint16_t ogms = origs ? origs->items : 0;
struct avl_node *an = NULL;
struct orig_node *on;
struct msg_ogm_dhash_adv *msg;
assertion(-500771, (tx_iterator_cache_data_space_pref(it, 0, 0) >= (int)(ogms * sizeof(struct msg_ogm_dhash_adv))));
hdr->aggregation_sqn = htons(*sqn);
for (msg = hdr->msg; (origs && (on = avl_iterate_item(origs, &an))); msg++) {
msg->dhash = on->descContent->dhn->dhash;
msg->sqn = htons(on->ogmSqn);
msg->metric.val.u16 = htons(umetric_to_fmetric(on->ogmMetric).val.u16);
on->descContent->dhn->referred_by_me_timestamp = bmx_time;
}
dbgf_all(DBGT_INFO, "aggSqn=%d aggSqnMax=%d ogms=%d", *sqn, ogm_aggreg_sqn_max, ogms);
return (ogms * sizeof(struct msg_ogm_dhash_adv));
}
STATIC_FUNC
UMETRIC_T lndev_best_via_router(struct neigh_node *local, struct orig_node *on, UMETRIC_T *ogm_metric, LinkNode **bestPathLink)
{
assertion(-502474, (local->linkDev_tree.items));
UMETRIC_T metric_best = 0;
struct avl_node *linkDev_an = NULL;
LinkDevNode *linkDev;
while ((linkDev = avl_iterate_item(&local->linkDev_tree, &linkDev_an))) {
LinkNode *link = NULL;
while ((link = avl_next_item(&linkDev->link_tree, (link ? &link->k : NULL)))) {
UMETRIC_T um = apply_lndev_metric_algo(link, ogm_metric, on->path_metricalgo);
if (metric_best <= um) {
metric_best = um;
*bestPathLink = link;
}
}
}
assertion(-501088, (*bestPathLink));
return metric_best;
}
void process_ogm_metric(void *voidRef)
{
struct reference_node *ref = voidRef;
assertion(-502475, (ref));
assertion(-502476, (ref->dhn));
if (ref->scheduled_ogm_processing) {
ref->scheduled_ogm_processing = 0;
task_remove(process_ogm_metric, (void*)ref);
}
if (!ref->dhn->descContent || !ref->dhn->descContent->orig)
return;
struct orig_node *on = ref->dhn->descContent->orig;
IDM_T neighTrust = verify_neighTrust(on, ref->neigh);
IDM_T valid_metric = is_fmetric_valid(ref->ogmMetricMax);
UMETRIC_T ogmMetric = valid_metric ? fmetric_to_umetric(ref->ogmMetricMax) : 0;
dbgf_all(DBGT_INFO, "orig=%s via neigh=%s ogmMtc=%ju, ogmSqn=%d knownSqn=%d",
cryptShaAsShortStr(&on->k.nodeId), cryptShaAsShortStr(&ref->neigh->local_id), ogmMetric, ref->ogmSqnMax, on->ogmSqn);
if (!neighTrust || !valid_metric || ogmMetric < on->path_metricalgo->umetric_min)
return;
static int count = 0;
assertion(-502477, (count <= 2)); //this one calls itself via schedule_ogm()->schedule_ogm_aggregations()->process_ogm()
if (ref->ogmSqnMax >= on->ogmSqn) {
LinkNode *best_rt_link = NULL;
UMETRIC_T best_rt_metric = lndev_best_via_router(ref->neigh, on, &ogmMetric, &best_rt_link);
assertion(-502478, (best_rt_metric && best_rt_link));
if (
((ref->ogmSqnMax >= (on->ogmSqn + 2))) ||
((ref->ogmSqnMax >= (on->ogmSqn + 1)) && (((TIME_T)(bmx_time - ref->ogmSqnTime)) >= on->path_metricalgo->ogm_sqn_late_hystere)) ||
((ref->ogmSqnMax >= (on->ogmSqn + 0)) && (best_rt_link == on->curr_rt_link)) ||
((ref->ogmSqnMax >= (on->ogmSqn + 0)) && (best_rt_metric > on->ogmMetric) && ref->ogmBestSinceSqn && (((OGM_SQN_T) (ref->ogmSqnMax - ref->ogmBestSinceSqn)) >= on->path_metricalgo->ogm_sqn_best_hystere)) ||
((ref->ogmSqnMax >= (on->ogmSqn + 0)) && (best_rt_metric > ((on->ogmMetric * (100 + on->path_metricalgo->ogm_metric_hystere))/100)))
) {
if (best_rt_link != on->curr_rt_link) {
if (on->curr_rt_link)
cb_route_change_hooks(DEL, on);
on->curr_rt_link = best_rt_link;
cb_route_change_hooks(ADD, on);
}
schedule_ogm(on, ref->ogmSqnMax, best_rt_metric);
ref->ogmBestSinceSqn = 0;
} else {
if ((ref->ogmSqnMax >= (on->ogmSqn + 1)) && (((TIME_T)(bmx_time - ref->ogmSqnTime)) < on->path_metricalgo->ogm_sqn_late_hystere)) {
ref->scheduled_ogm_processing++;
task_register((on->path_metricalgo->ogm_sqn_late_hystere - ((TIME_T) (bmx_time - ref->ogmSqnTime))), process_ogm_metric, ref, -300764);
}
if ((best_rt_metric > on->ogmMetric) && !ref->ogmBestSinceSqn)
ref->ogmBestSinceSqn = ref->ogmSqnMax;
else if (best_rt_metric <= on->ogmMetric)
ref->ogmBestSinceSqn = 0;
}
}
}
STATIC_FUNC
int32_t rx_frame_ogm_dhash_aggreg_advs(struct rx_frame_iterator *it)
{
struct hdr_ogm_adv *hdr = ((struct hdr_ogm_adv*) it->f_data);
struct msg_ogm_dhash_adv *msg = hdr->msg;
AGGREG_SQN_T aggSqn = ntohs(hdr->aggregation_sqn);
struct neigh_node *nn = it->pb->i.verifiedLink->k.linkDev->key.local;
IDM_T new = ((AGGREG_SQN_T) (nn->ogm_aggreg_max - aggSqn)) < nn->ogm_aggreg_size && !bit_get(nn->ogm_aggreg_sqns, AGGREG_SQN_CACHE_RANGE, aggSqn);
dbgf_all(DBGT_INFO, "new=%d neigh=%s aggSqn=%d/%d/%d msgs=%d", new, nn->on->k.hostname, aggSqn, nn->ogm_aggreg_max, nn->ogm_aggreg_size, it->f_msgs_fixed);
if (new) {
bit_set(nn->ogm_aggreg_sqns, AGGREG_SQN_CACHE_RANGE, aggSqn, 1);
for (; msg < &(hdr->msg[it->f_msgs_fixed]); msg++) {
struct reference_node *ref;
if ((ref = refNode_update(nn, aggSqn, &msg->dhash, NULL, 0))) {
OGM_SQN_T ogmSqn = ntohs(msg->sqn);
FMETRIC_U16_T ogmMtc = {.val = {.u16 = ntohs(msg->metric.val.u16)}};
struct orig_node *on = ref->dhn->descContent ? ref->dhn->descContent->orig : NULL;
dbgf_all(DBGT_INFO, "dhash=%s hostname=%s ogmSqn=%d ogmMtc=%d",
cryptShaAsShortStr(&msg->dhash), on ? on->k.hostname : NULL, ogmSqn, ogmMtc.val.u16);
if (ogmSqn > ref->ogmSqnMax || (ogmSqn == ref->ogmSqnMax && ogmMtc.val.u16 > ref->ogmMetricMax.val.u16 )) {
if (ogmSqn > ref->ogmSqnMax) {
ref->ogmSqnMax = ogmSqn;
ref->ogmSqnTime = bmx_time;
}
ref->ogmMetricMax = ogmMtc;
if (on)
process_ogm_metric(ref);
}
}
}
}
return TLV_RX_DATA_PROCESSED;
}
STATIC_FUNC
struct opt_type ogm_options[]=
{
{ODI, 0, ARG_OGM_SQN_RANGE, 0, 9,0, A_PS1, A_ADM, A_DYI, A_CFA, A_ANY,&ogmSqnRange, MIN_OGM_SQN_RANGE, MAX_OGM_SQN_RANGE, DEF_OGM_SQN_RANGE,0, 0,
ARG_VALUE_FORM, "set average OGM sequence number range (affects frequency of bmx6 description updates)"},
{ODI,0,ARG_SEND_LINK_REVISED_OGMS, 0, 9,1,A_PS1,A_ADM,A_DYI,A_CFA,A_ANY, &sendLinkRevisedOgms,MIN_SEND_REVISED_OGMS, 1, DEF_SEND_LINK_REVISED_OGMS,0, NULL,
ARG_VALUE_FORM, "send revised ogms with better metric (but unchanged sqn)"},
{ODI,0,ARG_OGM_INTERVAL, 'o',9,1, A_PS1, A_ADM, A_DYI, A_CFA, A_ANY, &minMyOgmInterval, MIN_OGM_INTERVAL, MAX_OGM_INTERVAL, DEF_OGM_INTERVAL,0, 0,
ARG_VALUE_FORM, "set interval in ms with which new originator message (OGM) are send"},
{ODI,0,ARG_OGM_IFACTOR, 0,9,1, A_PS1, A_ADM, A_DYI, A_CFA, A_ANY, &maxMyOgmIFactor, MIN_OGM_IFACTOR, MAX_OGM_IFACTOR, DEF_OGM_IFACTOR, 0, 0,
ARG_VALUE_FORM, "set factor (relative to ogmInterval) for max delay of own ogms"},
};
int32_t init_ogm( void )
{
register_options_array(ogm_options, sizeof(ogm_options), CODE_CATEGORY_NAME);
struct frame_handl handl;
memset(&handl, 0, sizeof ( handl));
handl.name = "AGGREG_SQN_ADV";
handl.min_msg_size = sizeof(struct msg_ogm_aggreg_sqn_adv);
handl.fixed_msg_size = 1;
// this might schedule a new tx_packet because schedule_tx_packet() believes
// the stuff we are about to send now is still waiting to be send.
handl.tx_packet_prepare_casuals = revise_ogm_aggregations;
handl.tx_frame_handler = tx_frame_ogm_aggreg_sqn;
handl.rx_frame_handler = rx_frame_ogm_aggreg_sqn;
register_frame_handler(packet_frame_db, FRAME_TYPE_OGM_AGG_SQN_ADV, &handl);
handl.name = "OGM_AGGREG_REQ";
handl.data_header_size = sizeof(struct hdr_ogm_aggreg_req);
handl.min_msg_size = sizeof(struct msg_ogm_aggreg_req);
handl.fixed_msg_size = 1;
handl.tx_packet_prepare_casuals = schedule_ogm_req;
handl.tx_msg_handler = tx_msg_ogm_aggreg_request;
handl.rx_msg_handler = rx_msg_ogm_aggreg_request;
register_frame_handler(packet_frame_db, FRAME_TYPE_OGM_REQ, &handl);
handl.name = "OGM_DHASH_ADV";
handl.data_header_size = sizeof(struct hdr_ogm_adv);
handl.min_msg_size = sizeof(struct msg_ogm_dhash_adv);
handl.fixed_msg_size = 1;
handl.tx_frame_handler = tx_frame_ogm_dhash_aggreg_advs;
handl.rx_frame_handler = rx_frame_ogm_dhash_aggreg_advs;
register_frame_handler(packet_frame_db, FRAME_TYPE_OGM_DHASH_ADV, &handl);
return SUCCESS;
}

99
ogm.h Normal file
View File

@@ -0,0 +1,99 @@
/*
* Copyright (c) 2010 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
*/
extern int32_t ogmIid;
extern uint32_t ogms_pending;
#define ARG_OGM_IFACTOR "ogmIntervalFactor"
#define DEF_OGM_IFACTOR 120
#define MIN_OGM_IFACTOR 100
#define MAX_OGM_IFACTOR 10000
#define ARG_OGM_INTERVAL "ogmInterval"
#define DEF_OGM_INTERVAL 6000
#define MIN_OGM_INTERVAL 200
#define MAX_OGM_INTERVAL 60000 // 60000 = 1 minutes
#define _DEF_OGM_SQN_DIV 5
#define _MIN_OGM_SQN_RANGE 32
#define _MAX_OGM_SQN_RANGE 8192 // changing this will cause compatibility trouble
#define MIN_OGM_SQN_RANGE _MIN_OGM_SQN_RANGE + (_MIN_OGM_SQN_RANGE/(2*_DEF_OGM_SQN_DIV))
#define MAX_OGM_SQN_RANGE _MAX_OGM_SQN_RANGE - (_MAX_OGM_SQN_RANGE/(2*_DEF_OGM_SQN_DIV))
#define DEF_OGM_SQN_RANGE MAX_OGM_SQN_RANGE
#define ARG_OGM_SQN_RANGE "ogmSqnRange"
#define MIN_OGM_AGGREG_HISTORY 2
#define MAX_OGM_AGGREG_HISTORY AGGREG_SQN_CACHE_RANGE
#define DEF_OGM_AGGREG_HISTORY 20
#define ARG_OGM_AGGREG_HISTORY "ogmAggregHistory"
#define MIN_SEND_REVISED_OGMS 0
#define DEF_SEND_LINK_REVISED_OGMS 0
#define ARG_SEND_LINK_REVISED_OGMS "sendRevisedOgms"
extern int32_t sendLinkRevisedOgms;
#define OGM_JUMPS_PER_AGGREGATION 10
#define OGMS_DHASH_PER_AGGREG_PREF (SIGNED_FRAMES_SIZE_PREF - (\
sizeof(struct tlv_hdr) + \
sizeof (struct hdr_ogm_adv))) \
/ sizeof(struct msg_ogm_dhash_adv)
#define OGM_IID_RSVD_JUMP (OGM_IIDOFFST_MASK) // 63 //255 // resulting from ((2^transmitterIIDoffset_bit_range)-1)
struct msg_ogm_aggreg_sqn_adv {
AGGREG_SQN_T max;
uint16_t size;
} __attribute__((packed));
struct msg_ogm_aggreg_req {
AGGREG_SQN_T sqn;
} __attribute__((packed));
struct hdr_ogm_aggreg_req {
GLOBAL_ID_T dest_nodeId;
struct msg_ogm_aggreg_req msg[];
} __attribute__((packed));
struct msg_ogm_dhash_adv {
DHASH_T dhash;
FMETRIC_U16_T metric;
uint16_t sqn;
} __attribute__((packed));
struct hdr_ogm_adv {
AGGREG_SQN_T aggregation_sqn;
struct msg_ogm_dhash_adv msg[];
} __attribute__((packed));
void remove_ogm(struct orig_node *on);
void process_ogm_metric(void *voidRef);
int32_t init_ogm(void);

View File

@@ -123,11 +123,10 @@ void cb_route_change_hooks(uint8_t del, struct orig_node *dest)
TRACE_FUNCTION_CALL;
struct list_node *list_pos;
struct cb_route_change_node *con, *prev_con = NULL;
struct neigh_node *local_router = dest->curr_rt_local->local_key;
struct neigh_node *local_router = dest->curr_rt_link->k.linkDev->key.local;
assertion(-500674, (dest && dest->dhn && dest->dhn->desc_frame_len));
local_router->orig_routes = local_router->orig_routes + (del ? -1 : +1);
local_router->orig_routes += (del ? -1 : +1);
dest->curr_rt_link->orig_routes += (del ? -1 : +1);
assertion(-501320, (local_router->orig_routes >= 0 && local_router->orig_routes < (int) orig_tree.items));

31
prof.c
View File

@@ -37,6 +37,8 @@
#include "prof.h"
#include "schedule.h"
#define CODE_CATEGORY_NAME "profiling"
static AVL_TREE(prof_tree, struct prof_ctx, k);
void prof_init( struct prof_ctx *sp)
@@ -89,13 +91,13 @@ int prof_check(struct prof_ctx *p, int childs)
!p || (p->active_prof && !!p->active_childs == childs && prof_check(p->parent, 1) == SUCCESS))
return SUCCESS;
dbgf_sys(DBGT_ERR, "func=%p name=%s parent_func=%p neigh=%p orig=%p parent_active_childs=%d childs=%d",
p->k.func, p->name, p->parent_func, (void*)p->k.neigh, (void*)p->k.orig, p->active_childs, childs);
dbgf_sys(DBGT_ERR, "func=%d name=%s parent_func=%d neigh=%p orig=%p parent_active_childs=%d childs=%d",
!!p->k.func, p->name, !!p->parent_func, (void*)p->k.neigh, (void*)p->k.orig, p->active_childs, childs);
return FAILURE;
}
void prof_start( struct prof_ctx *p)
void prof_start_( struct prof_ctx *p)
{
assertion(-502122, (!p->active_prof));
assertion(-502123, (!p->clockBeforePStart));
@@ -113,7 +115,9 @@ void prof_start( struct prof_ctx *p)
ASSERTION(-502125, (prof_check(p, 0) == SUCCESS));
}
void prof_stop( struct prof_ctx *p)
void prof_stop_( struct prof_ctx *p)
{
assertion(-502126, (p->active_prof));
ASSERTION(-502127, (prof_check(p, 0) == SUCCESS));
@@ -158,7 +162,7 @@ void prof_update_all( void *unused) {
dbgf_all(DBGT_INFO, "updating %s active=%d", pn->name, active);
if (active)
prof_stop(pn);
prof_stop_(pn);
pn->clockPrevPeriod = pn->clockRunningPeriod;
pn->clockPrevTotal += pn->clockRunningPeriod;
@@ -166,7 +170,7 @@ void prof_update_all( void *unused) {
pn->clockRunningPeriod = 0;
if (active)
prof_start(pn);
prof_start_(pn);
}
prof_check_disabled = NO;
@@ -208,8 +212,8 @@ struct prof_status *prof_status_iterate(struct prof_ctx *pn, struct prof_status
{
dbgf_all(DBGT_INFO, "dbg pn=%s status=%p", pn->name, (void*)status);
status->neighId = pn->k.neigh ? &pn->k.neigh->dhn->on->nodeId : NULL;
status->origId = &pn->k.orig ? &pn->k.orig->nodeId : NULL;
status->neighId = pn->k.neigh ? &pn->k.neigh->local_id: NULL;
status->origId = pn->k.orig ? &pn->k.orig->k.nodeId : NULL;
status->parent = pn->parent ? pn->parent->name : NULL;
status->name = pn->name;
sprintf(status->sysCurrCpu, DBG_NIL);
@@ -286,11 +290,20 @@ int32_t prof_status_creator(struct status_handl *handl, void *data)
return status_size;
}
#define ARG_CPU_PROFILING "cpu"
static struct opt_type prof_options[]=
{
// ord parent long_name shrt Attributes *ival min max default *func,*syntax,*help
{ODI,0,ARG_CPU_PROFILING, 0, 9,1,A_PS0N,A_USR,A_DYN,A_ARG,A_ANY, 0, 0, 0, 0,0, opt_status,
0, "show cpu usage of relevant functions\n"}
};
void init_prof( void )
{
register_status_handl(sizeof (struct prof_status), 1, prof_status_format, "cpu", prof_status_creator);
register_status_handl(sizeof (struct prof_status), 1, prof_status_format, ARG_CPU_PROFILING, prof_status_creator);
register_options_array(prof_options, sizeof( prof_options), CODE_CATEGORY_NAME);
task_register(5000, prof_update_all, NULL, -300649);

13
prof.h
View File

@@ -46,8 +46,17 @@ struct prof_ctx {
void prof_free( struct prof_ctx *p);
void prof_start( struct prof_ctx *p);
void prof_stop( struct prof_ctx *p);
void prof_start_(struct prof_ctx *p);
void prof_stop_(struct prof_ctx *p);
#define prof_start( thisFunc, parentFunc ) \
extern int main(int argc, char *argv[]); \
static struct prof_ctx prof_ctx_ = {.k = { .func = (void(*)(void))thisFunc}, .name = __FUNCTION__, .parent_func = (void (*) (void))parentFunc}; \
prof_start_(&prof_ctx_)
#define prof_stop() prof_stop_( &prof_ctx_ )
void init_prof( void );

162
redist.c
View File

@@ -16,6 +16,37 @@
*/
#define _GNU_SOURCE
#include <stdio.h>
#include <stdarg.h>
#include <syslog.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/un.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <paths.h>
#include <netinet/in.h>
#include "list.h"
#include "control.h"
#include "bmx.h"
#include "crypt.h"
#include "avl.h"
#include "node.h"
#include "metrics.h"
#include "msg.h"
#include "ip.h"
#include "hna.h"
#include "schedule.h"
#include "plugin.h"
#include "tools.h"
#include "iptools.h"
#include "allocate.h"
#include "redist.h"
@@ -23,9 +54,9 @@ void redist_dbg(int8_t dbgl, int8_t dbgt, const char *func, struct redist_in_nod
{
dbgf(dbgl, dbgt, "%s %s %s old=%d cnt=%d %s route=%s via=%s type=%s table=%d ifidx=%d metric=%d distance=%d flags=%X message=%X",
func, misc1, misc2, zrn->old, zrn->cnt,
(zrn->cnt > 1 || zrn->cnt < 0) ? "INVALID" : (zrn->old != zrn->cnt) ? "CHANGED" : "UNCHANGED",
(zrn->cnt < 0) ? "INVALID" : (zrn->old != (!!zrn->cnt)) ? "CHANGED" : "UNCHANGED",
netAsStr(&zrn->k.net), ipXAsStr(zrn->k.net.af, &zrn->k.via),
zrn->k.inType < BMX6_ROUTE_MAX ? zapi_rt_dict[zrn->k.inType].sys2Name : memAsHexStringSep(&zrn->k.inType, 1, 0, NULL),
zrn->k.inType < BMX6_ROUTE_MAX_KNOWN ? zapi_rt_dict[zrn->k.inType].sys2Name : memAsHexStringSep(&zrn->k.inType, 1, 0, NULL),
zrn->k.table, zrn->k.ifindex, zrn->metric, zrn->distance, zrn->flags, zrn->message);
}
@@ -97,7 +128,7 @@ void redist_rm_overlapping(struct avl_tree *redist_out_tree)
if (is_ip_net_equal(&ovlp->k.net.ip, &routn->k.net.ip, ovlp->k.net.mask, routn->k.net.af)) {
routn->new = 0;
ovlp->minAggregatePrefixLen = XMAX(ovlp->minAggregatePrefixLen, routn->minAggregatePrefixLen);
dbgf_track(DBGT_INFO, "disable overlapping net=%s in favor of net=%s",
dbgf_all(DBGT_INFO, "disable overlapping net=%s in favor of net=%s",
netAsStr(&routn->k.net), netAsStr(&ovlp->k.net));
break;
}
@@ -174,8 +205,67 @@ void redist_rm_aggregatable(struct avl_tree *redist_out_tree)
}
}
struct redistr_opt_node *matching_redist_opt(struct redist_in_node *rin, struct avl_tree *redist_opt_tree, struct sys_route_dict *rt_dict)
{
struct redistr_opt_node *roptn;
struct avl_node *ropti;
for (ropti = NULL; (roptn = avl_iterate_item(redist_opt_tree, &ropti));) {
if (roptn->net.af && roptn->net.af != rin->k.net.af) {
dbgf_all(DBGT_INFO, "skipping %s AF", roptn->nameKey);
continue;
}
if (roptn->table != rin->k.table) {
dbgf_all(DBGT_INFO, "skipping %s table", roptn->nameKey);
continue;
}
if (roptn->bandwidth.val.u8 == 0) {
dbgf_all(DBGT_INFO, "skipping %s bandwidth", roptn->nameKey);
continue;
}
if (rin->k.inType > BMX6_ROUTE_MAX_SUPP) {
dbgf_all(DBGT_INFO, "skipping unsupported routeType=%d", rin->k.inType);
continue;
}
if (/*roptn->bmx6_redist_bits &&*/
!roptn->bmx6_redist_all &&
!bit_get(((uint8_t*) & roptn->bmx6_redist_bits),
sizeof (roptn->bmx6_redist_bits)*8, rt_dict[rin->k.inType].sys2bmx)) {
dbgf_all(DBGT_INFO, "skipping %s redist bits", roptn->nameKey);
continue;
}
if (roptn->bmx6_redist_sys && roptn->bmx6_redist_sys != rin->k.inType) {
dbgf_all(DBGT_INFO, "skipping %s redist sys=%d != %d", roptn->nameKey, roptn->bmx6_redist_sys, rin->k.inType);
continue;
}
if ((roptn->net.mask != MIN_REDIST_PREFIX ||
roptn->netPrefixMin != DEF_REDIST_PREFIX_MIN ||
roptn->netPrefixMax != DEF_REDIST_PREFIX_MAX)
&& !(
(roptn->netPrefixMax == TYP_REDIST_PREFIX_NET ?
roptn->net.mask >= rin->k.net.mask : roptn->netPrefixMax >= rin->k.net.mask) &&
(roptn->netPrefixMin == TYP_REDIST_PREFIX_NET ?
roptn->net.mask <= rin->k.net.mask : roptn->netPrefixMin <= rin->k.net.mask) &&
is_ip_net_equal(&roptn->net.ip, &rin->k.net.ip, XMIN(roptn->net.mask, rin->k.net.mask), roptn->net.af))) {
dbgf_all(DBGT_INFO, "skipping %s prefix", roptn->nameKey);
continue;
}
return roptn;
}
return NULL;
}
IDM_T redistribute_routes(struct avl_tree *redist_out_tree, struct avl_tree *redist_in_tree, struct avl_tree *redist_opt_tree, struct sys_route_dict *rt_dict)
{
@@ -187,12 +277,11 @@ IDM_T redistribute_routes(struct avl_tree *redist_out_tree, struct avl_tree *red
struct avl_node *rii;
struct redistr_opt_node *roptn;
struct avl_node *ropti;
struct redist_out_node *routn;
struct avl_node *routi;
struct redist_out_node routf;
struct redist_out_node routf;
for (routi = NULL; (routn = avl_iterate_item(redist_out_tree, &routi));) {
routn->new = 0;
@@ -201,54 +290,19 @@ IDM_T redistribute_routes(struct avl_tree *redist_out_tree, struct avl_tree *red
for (rii = NULL; (rin = avl_iterate_item(redist_in_tree, &rii));) {
for (ropti = NULL; (roptn = avl_iterate_item(redist_opt_tree, &ropti));) {
ASSERTION(-502479, IMPLIES(rin->roptn, rin->roptn == matching_redist_opt(rin, redist_opt_tree, rt_dict)));
if (roptn->net.af && roptn->net.af != rin->k.net.af) {
dbgf_all(DBGT_INFO, "skipping %s AF", roptn->nameKey);
continue;
}
if ((roptn = rin->roptn ? rin->roptn : matching_redist_opt(rin, redist_opt_tree, rt_dict))) {
if (roptn->table != rin->k.table) {
dbgf_all(DBGT_INFO, "skipping %s table", roptn->nameKey);
continue;
}
memset(&routf, 0, sizeof (routf));
if (roptn->bandwidth.val.u8 == 0) {
dbgf_all(DBGT_INFO, "skipping %s bandwidth", roptn->nameKey);
continue;
}
if (/*roptn->bmx6_redist_bits &&*/
!bit_get(((uint8_t*) & roptn->bmx6_redist_bits),
sizeof (roptn->bmx6_redist_bits)*8, rt_dict[rin->k.inType].sys2bmx)) {
dbgf_all(DBGT_INFO, "skipping %s redist bits", roptn->nameKey);
continue;
}
if ((roptn->net.mask != MIN_REDIST_PREFIX ||
roptn->netPrefixMin != DEF_REDIST_PREFIX_MIN ||
roptn->netPrefixMax != DEF_REDIST_PREFIX_MAX)
&& !(
(roptn->netPrefixMax == TYP_REDIST_PREFIX_NET ?
roptn->net.mask >= rin->k.net.mask : roptn->netPrefixMax >= rin->k.net.mask) &&
(roptn->netPrefixMin == TYP_REDIST_PREFIX_NET ?
roptn->net.mask <= rin->k.net.mask : roptn->netPrefixMin <= rin->k.net.mask) &&
is_ip_net_equal(&roptn->net.ip, &rin->k.net.ip, XMIN(roptn->net.mask, rin->k.net.mask), roptn->net.af))) {
dbgf_all(DBGT_INFO, "skipping %s prefix", roptn->nameKey);
continue;
}
memset(&routf, 0, sizeof (routf));
routf.k.bmx6_route_type = rt_dict[rin->k.inType].sys2bmx;
routf.k.net = roptn->net.mask >= rin->k.net.mask ? roptn->net : rin->k.net;
routf.k.bandwidth = roptn->bandwidth;
routf.k.bmx6_route_type = rt_dict[rin->k.inType].sys2bmx;
routf.k.net = roptn->net.mask >= rin->k.net.mask ? roptn->net : rin->k.net;
routf.k.bandwidth = roptn->bandwidth;
if ( roptn->tunInDev )
strcpy(routf.k.tunInDev.str, roptn->tunInDev);
routf.k.must_be_one = 1; // to let alv_next_item find the first one
routf.minAggregatePrefixLen = roptn->minAggregatePrefixLen;
routf.k.must_be_one = 1; // to let alv_next_item find the first one
routf.minAggregatePrefixLen = roptn->minAggregatePrefixLen;
if (!(routn = avl_find_item(redist_out_tree, &routf.k))) {
*(routn = debugMalloc(sizeof (routf), -300505)) = routf;
@@ -264,8 +318,6 @@ IDM_T redistribute_routes(struct avl_tree *redist_out_tree, struct avl_tree *red
routn->new = 1;
routn->minAggregatePrefixLen = XMAX(routn->minAggregatePrefixLen, roptn->minAggregatePrefixLen);
break;
}
}
@@ -429,9 +481,17 @@ int32_t opt_redist(uint8_t cmd, uint8_t _save, struct opt_type *opt, struct opt_
} else if (!strcmp(c->opt->name, ARG_REDIST_HYSTERESIS)) {
ron->hysteresis = c->val ? strtol(c->val, NULL, 10) : DEF_REDIST_HYSTERESIS;
} else if (!strcmp(c->opt->name, ARG_ROUTE_ALL)) {
ron->bmx6_redist_all = (c->val && strtol(c->val, NULL, 10) == 1 ) ? 1 : 0;
} else if (!strcmp(c->opt->name, ARG_ROUTE_SYS)) {
ron->bmx6_redist_sys = c->val ? strtol(c->val, NULL, 10) : 0;
} else {
uint8_t t;
for (t = 0; t < BMX6_ROUTE_MAX; t++) {
for (t = 0; t <= BMX6_ROUTE_MAX_KNOWN; t++) {
if (bmx6_rt_dict[t].sys2Name && !strcmp(c->opt->name, bmx6_rt_dict[t].sys2Name)) {
bit_set((uint8_t*) &ron->bmx6_redist_bits,
sizeof (ron->bmx6_redist_bits) * 8,

View File

@@ -86,7 +86,11 @@
#define NETWORK_NAME_LEN 32
#define HLP_ROUTE_TYPE "redistribute route type (mandatory to enable at least one type)"
#define ARG_ROUTE_ALL "all"
#define ARG_ROUTE_SYS "sys"
#define HLP_ROUTE_TYPE "redistribute bmx route type (mandatory to enable at least one type)"
#define HLP_ROUTE_SYS "filter redistributed routes based on system id (ignored if unset, recommends: /all=1)"
@@ -122,16 +126,19 @@ struct redist_in_node {
int8_t cnt;
uint8_t old;
uint32_t metric;
uint8_t distance;
uint8_t distance;
struct redistr_opt_node *roptn;
};
struct redistr_opt_node {
char nameKey[NETWORK_NAME_LEN];
struct net_key net;
uint32_t bmx6_redist_bits;
uint64_t bmx6_redist_bits;
uint32_t hysteresis;
uint32_t table;
uint8_t netPrefixMin;
uint8_t bmx6_redist_all;
uint8_t bmx6_redist_sys;
uint8_t netPrefixMin;
uint8_t netPrefixMax;
uint8_t minAggregatePrefixLen;
FMETRIC_U8_T bandwidth;
@@ -142,4 +149,5 @@ void redist_dbg(int8_t dbgl, int8_t dbgt, const char *func, struct redist_in_nod
void update_tunXin6_net_adv_list(struct avl_tree *redist_out_tree, struct list_head *tunXin6_net_adv_list );
IDM_T redistribute_routes(struct avl_tree *redist_out_tree, struct avl_tree *zroute_tree, struct avl_tree *redist_opt_tree, struct sys_route_dict *zapi_rt_dict);
int32_t opt_redist(uint8_t cmd, uint8_t _save, struct opt_type *opt, struct opt_parent *patch, struct ctrl_node *cn, struct avl_tree *redist_opt_tree, uint8_t *changed);
int32_t opt_redist(uint8_t cmd, uint8_t _save, struct opt_type *opt, struct opt_parent *patch, struct ctrl_node *cn, struct avl_tree *redist_opt_tree, uint8_t *changed);
struct redistr_opt_node *matching_redist_opt(struct redist_in_node *rin, struct avl_tree *redist_opt_tree, struct sys_route_dict *rt_dict);

View File

@@ -39,6 +39,7 @@
#include "plugin.h"
#include "schedule.h"
#include "allocate.h"
#include "key.h"
@@ -65,29 +66,21 @@ void upd_time(struct timeval *precise_tv)
gettimeofday( &curr_tv, NULL );
IDM_T larger;
if ( (larger=timercmp( &curr_tv, &acceptable_max_tv, > )) || timercmp( &curr_tv, &acceptable_min_tv, < ) ) {
if ( timercmp( &curr_tv, &acceptable_max_tv, > ) ) {
if (larger)
timersub( &curr_tv, &acceptable_max_tv, &diff_tv );
else
timersub( &acceptable_min_tv, &curr_tv, &diff_tv );
timersub( &curr_tv, &acceptable_max_tv, &diff_tv );
timeradd( &start_time_tv, &diff_tv, &start_time_tv );
dbg_sys(DBGT_WARN, "critical system time drift detected: ++ca %ld s, %ld us! Correcting reference!",
diff_tv.tv_sec, diff_tv.tv_usec );
dbg_sys(DBGT_WARN, "critical system time drift detected: %s approx %ld s, %ld us! Correcting reference!",
larger ? "++" : "--", diff_tv.tv_sec, diff_tv.tv_usec );
if ( diff_tv.tv_sec > CRITICAL_PURGE_TIME_DRIFT )
purge_link_route_orig_nodes(NULL, NO, self);
} else if ( timercmp( &curr_tv, &acceptable_min_tv, < ) ) {
timersub( &acceptable_min_tv, &curr_tv, &diff_tv );
timersub( &start_time_tv, &diff_tv, &start_time_tv );
dbg_sys(DBGT_WARN, "critical system time drift detected: --ca %ld s, %ld us! Correcting reference!",
diff_tv.tv_sec, diff_tv.tv_usec );
if ( diff_tv.tv_sec > CRITICAL_PURGE_TIME_DRIFT )
purge_link_route_orig_nodes(NULL, NO, self);
keyNodes_cleanup(KCPromoted, myKey);
}
timersub( &curr_tv, &start_time_tv, &bmx_tv );
@@ -104,10 +97,20 @@ void upd_bmx_time(struct timeval *tv)
{
static struct timeval tmp;
upd_time((tv = tv ? tv : &tmp));
while (1) {
upd_time((tv = tv ? tv : &tmp));
bmx_time = ( (tv->tv_sec * 1000) + (tv->tv_usec / 1000) );
bmx_time_sec = tv->tv_sec;
bmx_time = ( (tv->tv_sec * 1000) + (tv->tv_usec / 1000) );
bmx_time_sec = tv->tv_sec;
if (bmx_time)
break;
else //Never return zero bmx_time. To Simplifying timeout processing.
usleep(100);
}
keyNode_fixTimeouts();
}
@@ -301,8 +304,6 @@ void wait4Event(TIME_T timeout)
{
TRACE_FUNCTION_CALL;
static struct packet_buff pb;
TIME_T last_get_time_result = 0;
static uint32_t addr_len = sizeof (pb.i.addr);
@@ -335,15 +336,6 @@ loop4Event:
//which should be removed before debugging
//dbgf_all( DBGT_INFO, "timeout %d", timeout );
if ( bmx_time < last_get_time_result ) {
last_get_time_result = bmx_time;
dbg_sys(DBGT_WARN, "detected Timeoverlap..." );
goto wait4Event_end;
}
last_get_time_result = bmx_time;
if ( selected < 0 ) {
static TIME_T last_interrupted_syscall = 0;
@@ -378,28 +370,9 @@ loop4Event:
goto loop4Event;
}
/*
// check for changed interface status...
if ( FD_ISSET( ifevent_sk, &tmp_wait_set ) ) {
dbgf_track(DBGT_INFO, "detected changed interface status! Going to check interfaces!");
recv_ifevent_netlink_sk( );
keyNodes_block_and_sync(0, YES);
dev_check2();
//do NOT delay checking of interfaces to not miss ifdown/up of interfaces !!
if (kernel_if_config() ) //just call if changed!
dev_check(YES);
goto wait4Event_end;
}
*/
// check for received packets...
struct avl_node *it = NULL;
while ((pb.i.iif = avl_iterate_item(&dev_ip_tree, &it))) {
@@ -414,7 +387,7 @@ loop4Event:
errno=0;
pb.i.length = recvfrom( pb.i.iif->rx_mcast_sock, pb.p.data,
sizeof(pb.p.data) - 1, 0,
(struct sockaddr *)&pb.i.addr, &addr_len );
(struct sockaddr *)&pb.i.addr, (socklen_t*)&addr_len );
if ( pb.i.length < 0 && ( errno == EWOULDBLOCK || errno == EAGAIN ) ) {
@@ -440,7 +413,7 @@ loop4Event:
errno=0;
pb.i.length = recvfrom( pb.i.iif->rx_fullbrc_sock, pb.p.data,
sizeof(pb.p.data) - 1, 0,
(struct sockaddr *)&pb.i.addr, &addr_len );
(struct sockaddr *)&pb.i.addr, (socklen_t*)&addr_len );
if ( pb.i.length < 0 && ( errno == EWOULDBLOCK || errno == EAGAIN ) ) {
@@ -503,7 +476,7 @@ loop4Event:
if ( tv_stamp == NULL )
ioctl( pb.i.iif->unicast_sock, SIOCGSTAMP, &(pb.i.tv_stamp) );
else
timercpy( tv_stamp, &(pb.i.tv_stamp) );
timercpy( &(pb.i.tv_stamp), tv_stamp );
rx_packet( &pb );
@@ -585,12 +558,29 @@ loop4ActiveClients:
}
wait4Event_end:
keyNodes_block_and_sync(0, YES);
dbgf_all( DBGT_INFO, "end of function");
return;
}
IDM_T doNowOrLater(TIME_T *nextScheduled, TIME_T interval, IDM_T now)
{
if (((TIME_T) (*nextScheduled - (bmx_time + 1))) >= ((TIME_T) interval) || now) {
*nextScheduled = interval +
((((TIME_T) ((*nextScheduled + interval) - (bmx_time + 1))) >= ((TIME_T) interval)) ?
bmx_time : *nextScheduled);
return YES;
} else {
return NO;
}
}
void init_schedule( void ) {
gettimeofday( &start_time_tv, NULL );
curr_tv = start_time_tv;

View File

@@ -25,24 +25,6 @@ struct task_node {
void *data; //NULL or pointer to data to be given to function. Data will be freed after functio is called.
};
#define TX_TASK_MAX_DATA_LEN 20
struct tx_task_content {
struct dev_node *dev; // the outgoing interface to be used for transmitting
LinkDevNode *linkDev;
uint8_t data[TX_TASK_MAX_DATA_LEN];
uint16_t type;
} __attribute__((packed));
struct tx_task_node {
struct list_node list;
struct tx_task_content task;
uint16_t frame_msgs_length;
int16_t tx_iterations;
TIME_T considered_ts;
TIME_T send_ts;
};
void upd_time( struct timeval *precise_tv );
@@ -54,3 +36,4 @@ IDM_T task_remove(void (* task) (void *), void *data);
TIME_T task_next( void );
void wait4Event( TIME_T timeout );
IDM_T doNowOrLater(TIME_T *nextScheduled, TIME_T interval, IDM_T now);

962
sec.c

File diff suppressed because it is too large Load Diff

90
sec.h
View File

@@ -40,15 +40,15 @@
#define ARG_DESC_SIGN "descSignLen"
#define MIN_DESC_SIGN 512
#define MAX_DESC_SIGN 4096
#define DEF_DESC_SIGN 3072
#define DEF_DESC_SIGN 2048
#define HLP_DESC_SIGN "sign own descriptions with given RSA key length"
#define ARG_DESC_VERIFY "descVerificationLen"
#define MIN_DESC_VERIFY 512
#define MAX_DESC_VERIFY 4096
#define DEF_DESC_VERIFY 4096
#define HLP_DESC_VERIFY "verify description signatures up-to given RSA key length"
#define ARG_DESC_VERIFY_MAX "descVerificationLenMax"
#define MIN_DESC_VERIFY_MAX 512
#define MAX_DESC_VERIFY_MAX 4096
#define DEF_DESC_VERIFY_MAX 4096
#define HLP_DESC_VERIFY_MAX "verify description signatures up-to given RSA key length"
#define ARG_PACKET_SIGN "packetSignLen"
#define MIN_PACKET_SIGN 0
@@ -62,7 +62,7 @@ extern int32_t packetSigning;
// assuming 70 days to crack RSA512 keys (2009!) with a single dual-core machine,
// means can be cracked in
// ~6000 secs with ~1000 machines, or
// ~600 secs with ~10000 machines, or
// ~600 secs with ~10000 machines, or
// ~60 secs with ~100000 machines
// However, this would be for RSA512 but RSA896 is used by default!!:
#define MIN_PACKET_SIGN_LT (60) // one minute, needs ~100000 machines to crack RSA512 before end of life
@@ -72,12 +72,17 @@ extern int32_t packetSigning;
#define ARG_PACKET_VERIFY "packetVerification"
#define MIN_PACKET_VERIFY 0
#define MAX_PACKET_VERIFY 4096
#define DEF_PACKET_VERIFY 1024
#define HLP_PACKET_VERIFY "verify incoming packet signature up-to given RSA key length"
#define ARG_PACKET_VERIFY_MAX "packetVerificationLenMax"
#define MIN_PACKET_VERIFY_MAX 0
#define MAX_PACKET_VERIFY_MAX 4096
#define DEF_PACKET_VERIFY_MAX 2048
#define HLP_PACKET_VERIFY_MAX "verify incoming packet signature up-to given RSA key length"
#define ARG_PACKET_VERIFY_MIN "packetVerificationLenMax"
#define MIN_PACKET_VERIFY_MIN 0
#define MAX_PACKET_VERIFY_MIN 4096
#define DEF_PACKET_VERIFY_MIN 0
#define HLP_PACKET_VERIFY_MIN "require incoming packet signature of at least given RSA key length"
extern CRYPTKEY_T *my_PubKey;
extern CRYPTKEY_T *my_PktKey;
@@ -89,8 +94,8 @@ extern CRYPTKEY_T *my_PktKey;
FIELD_FORMAT_END }
struct dsc_msg_pubkey {
uint8_t type;
uint8_t key[];
uint8_t type;
uint8_t key[];
} __attribute__((packed));
@@ -100,30 +105,8 @@ struct dsc_msg_pubkey {
FIELD_FORMAT_END }
struct dsc_msg_signature {
uint8_t type;
uint8_t signature[];
} __attribute__((packed));
#define FRAME_MSG_SIGNATURE_FORMAT { \
{FIELD_TYPE_STRING_BINARY, -1, 8*sizeof(CRYPTSHA1_T), 1, FIELD_RELEVANCE_HIGH, "dhash"}, \
{FIELD_TYPE_UINT, -1, 8*sizeof(uint8_t), 1, FIELD_RELEVANCE_HIGH, "type"}, \
{FIELD_TYPE_STRING_BINARY, -1, 0, 1, FIELD_RELEVANCE_HIGH, "signature" }, \
FIELD_FORMAT_END }
struct frame_msg_signature {
CRYPTSHA1_T dhash;
uint8_t type;
uint8_t signature[];
} __attribute__((packed));
#define DESCRIPTION_MSG_SHA_FORMAT { \
{FIELD_TYPE_UINT, -1, 32, 0, FIELD_RELEVANCE_HIGH, "dataLen"}, \
{FIELD_TYPE_STRING_BINARY, -1, 8*sizeof(SHA1_T), 1, FIELD_RELEVANCE_HIGH, "dataSha"}, \
FIELD_FORMAT_END }
struct dsc_msg_sha {
uint32_t dataLen;
CRYPTSHA1_T dataSha;
uint8_t type;
uint8_t signature[];
} __attribute__((packed));
@@ -134,20 +117,29 @@ struct dsc_msg_sha {
FIELD_FORMAT_END }
struct dsc_msg_trust {
CRYPTSHA1_T globalId;
uint16_t reserved;
CRYPTSHA1_T globalId;
uint16_t reserved;
} __attribute__((packed));
void free_internalNeighId(OGM_DEST_T ini);
OGM_DEST_T allocate_internalNeighId(struct neigh_node *nn);
struct dsc_msg_version {
uint8_t comp_version;
uint8_t capabilities;
DESC_SQN_T descSqn;
uint32_t codeRevision;
} __attribute__((packed));
GLOBAL_ID_T *get_desc_id(uint8_t *desc_adv, uint32_t desc_len, struct dsc_msg_signature **signpp, struct dsc_msg_version **verspp);
struct content_node *test_description_signature(uint8_t *desc, uint32_t desc_len);
IDM_T setted_pubkey(struct desc_content *dc, uint8_t type, GLOBAL_ID_T *globalId);
IDM_T supportedKnownKey(CRYPTSHA1_T *pkhash);
INT_NEIGH_ID_T allocate_internalNeighId(struct neigh_node *nn);
void free_internalNeighId(INT_NEIGH_ID_T ini);
uint32_t *init_neighTrust(struct orig_node *on);
IDM_T verify_neighTrust(struct orig_node *on, struct neigh_node *neigh);
IDM_T supported_pubkey( CRYPTSHA1_T *pkhash );
IDM_T setted_pubkey(struct dhash_node *dhn, uint8_t type, GLOBAL_ID_T *globalId);
int process_signature(int32_t sig_msg_length, struct dsc_msg_signature *sig_msg, uint8_t *desc_frame, int32_t desc_frame_len, struct dsc_msg_pubkey *pkey_msg);
void init_sec( void );
void cleanup_sec( void );
void init_sec(void);
void cleanup_sec(void);

64
tools.c
View File

@@ -272,7 +272,7 @@ void init_set_bits_table256(void)
// clears byte range between and including begin and end
// accept overlap of begin and end
void byte_clear(uint8_t *array, uint16_t array_size, uint16_t begin, uint16_t end)
void byte_clear(uint8_t *array, uint32_t array_size, uint32_t begin, uint32_t end)
{
assertion(-500436, (array_size % 2 == 0));
@@ -300,21 +300,21 @@ uint8_t bits_count(uint32_t v)
return c;
}
uint8_t bit_get(const uint8_t *array, const uint16_t array_bit_size, uint16_t bit)
uint8_t bit_get(const uint8_t *array, const uint32_t array_bit_size, uint32_t bit)
{
bit = bit % array_bit_size;
uint16_t byte_pos = bit / 8;
uint32_t byte_pos = bit / 8;
uint8_t bit_pos = bit % 8;
return (array[byte_pos] & (0x01 << (7 - bit_pos))) ? 1 : 0;
}
void bit_set(uint8_t *array, uint16_t array_bit_size, uint16_t bit, IDM_T value)
void bit_set(uint8_t *array, uint32_t array_bit_size, uint32_t bit, IDM_T value)
{
bit = bit % array_bit_size;
uint16_t byte_pos = bit / 8;
uint32_t byte_pos = bit / 8;
uint8_t bit_pos = bit % 8;
if (value)
@@ -326,22 +326,23 @@ void bit_set(uint8_t *array, uint16_t array_bit_size, uint16_t bit, IDM_T value)
}
uint16_t bits_get(uint8_t *array, uint16_t array_bit_size, uint16_t begin_bit, uint16_t end_bit)
uint32_t bits_get(uint8_t *array, uint32_t array_bit_size, uint32_t beg_bit, uint32_t end_bit, uint32_t range_mask)
{
assertion(-501058, ((uint16_t) (end_bit - begin_bit)) < array_bit_size);
assertion(-502491, (array_bit_size % 8 == 0));
assertion(-502492, ((range_mask & (end_bit - beg_bit)) < array_bit_size));
uint16_t begin_byte = (begin_bit % array_bit_size) / 8;
uint16_t end_byte = (end_bit % array_bit_size) / 8;
uint16_t array_byte_size = array_bit_size / 8;
uint32_t begin_byte = (beg_bit % array_bit_size) / 8;
uint32_t end_byte = (end_bit % array_bit_size) / 8;
uint32_t array_byte_size = array_bit_size / 8;
uint16_t counted = 0;
uint16_t pos = begin_byte;
uint32_t counted = 0;
uint32_t pos = begin_byte;
do {
uint8_t val = array[pos];
if (pos == begin_byte)
val = val & (0xFF >> (begin_bit % 8));
val = val & (0xFF >> (beg_bit % 8));
if (pos == end_byte)
val = val & (0xFF << (7-(end_bit % 8)));
@@ -357,19 +358,19 @@ uint16_t bits_get(uint8_t *array, uint16_t array_bit_size, uint16_t begin_bit, u
// clears bit range between and including begin and end
void bits_clear(uint8_t *array, uint16_t array_bit_size, uint16_t beg_bit, uint16_t end_bit, uint16_t range_mask)
void bits_clear(uint8_t *array, uint32_t array_bit_size, uint32_t beg_bit, uint32_t end_bit, uint32_t range_mask)
{
assertion(-500435, (array_bit_size % 8 == 0));
assertion(-501060, ((range_mask & (end_bit - beg_bit)) < array_bit_size));
uint16_t array_byte_size = array_bit_size / 8;
uint32_t array_byte_size = array_bit_size / 8;
beg_bit = beg_bit % array_bit_size;
end_bit = end_bit % array_bit_size;
uint16_t beg_byte = beg_bit/8;
uint16_t end_byte = end_bit/8;
uint32_t beg_byte = beg_bit/8;
uint32_t end_byte = end_bit/8;
if (beg_byte == end_byte ? (beg_bit % 8) > (end_bit % 8) : (beg_byte + 1) % array_byte_size != end_byte)
@@ -393,15 +394,18 @@ uint16_t bits_get(uint8_t *array, uint16_t array_bit_size, uint16_t begin_bit, u
}
}
char* bits_print(uint8_t *array, uint16_t array_bit_size, uint16_t begin_bit, uint16_t end_bit)
char* bits_print(uint8_t *array, uint32_t array_bit_size, uint32_t beg_bit, uint32_t end_bit, uint32_t range_mask)
{
assertion(-502493, (array_bit_size % 8 == 0));
assertion(-502494, ((range_mask & (end_bit - beg_bit)) < array_bit_size));
#define BITS_PRINT_MAX 256
assertion(-501059, ((uint16_t) (end_bit - begin_bit)) < array_bit_size);
assertion(-501059, ((uint32_t) (end_bit - beg_bit)) < array_bit_size);
uint16_t c = 0;
static char output[BITS_PRINT_MAX + 4];
uint16_t pos = (begin_bit % array_bit_size);
uint32_t pos = (beg_bit % array_bit_size);
do {
sprintf(&output[c], "%s", bit_get(array, array_bit_size, pos) ? "1" : "0");
@@ -422,9 +426,9 @@ char* bits_print(uint8_t *array, uint16_t array_bit_size, uint16_t begin_bit, ui
uint8_t is_zero(void *data, int len)
uint8_t is_zero(void *data, int32_t len)
{
int i;
int32_t i;
char *d = data;
for (i = 0; i < len && !d[i]; i++);
@@ -579,6 +583,22 @@ void wordCopy( char *out, char *in ) {
}
}
uint8_t *find_array_data(uint8_t *arr, uint32_t arrLen, uint8_t *element, uint32_t elemLen) {
uint32_t p;
if (!arr || !arrLen || !element || !elemLen)
return NULL;
for(p=0; p < arrLen; p+=elemLen ) {
if ( !memcmp(&arr[p], element, elemLen) )
return &arr[p];
}
return NULL;
}
#ifdef WITH_UNUSED

13
tools.h
View File

@@ -67,17 +67,17 @@ float fast_inverse_sqrt(float x);
uint32_t rand_num(const uint32_t limit);
void byte_clear(uint8_t *array, uint16_t array_size, uint16_t begin, uint16_t range);
void byte_clear(uint8_t *array, uint32_t array_size, uint32_t begin, uint32_t end);
uint8_t bits_count(uint32_t v);
uint8_t bit_get(const uint8_t *array, const uint16_t array_bit_size, uint16_t bit);
uint8_t bit_get(const uint8_t *array, const uint32_t array_bit_size, uint32_t bit);
void bit_set(uint8_t *array, uint16_t array_bit_size, uint16_t bit, IDM_T value);
void bit_set(uint8_t *array, uint32_t array_bit_size, uint32_t bit, IDM_T value);
uint16_t bits_get(uint8_t *array, uint16_t array_bit_size, uint16_t begin_bit, uint16_t end_bit);
uint32_t bits_get(uint8_t *array, uint32_t array_bit_size, uint32_t beg_bit, uint32_t end_bit, uint32_t range_mask);
void bits_clear(uint8_t *array, uint16_t array_bit_size, uint16_t beg_bit, uint16_t end_bit, uint16_t range_mask);
void bits_clear(uint8_t *array, uint32_t array_bit_size, uint32_t beg_bit, uint32_t end_bit, uint32_t range_mask);
char* bits_print(uint8_t *array, uint16_t array_bit_size, uint16_t begin_bit, uint16_t end_bit);
char* bits_print(uint8_t *array, uint32_t array_bit_size, uint32_t beg_bit, uint32_t end_bit, uint32_t range_mask);
uint8_t is_zero(void *data, int len);
@@ -91,6 +91,7 @@ int32_t check_file(char *path, uint8_t regular, uint8_t read, uint8_t write, uin
int32_t check_dir( char *path, uint8_t create, uint8_t write );
int32_t rm_dir_content(char* dir_name, char* prefix);
uint8_t *find_array_data(uint8_t *arr, uint32_t arrLen, uint8_t *element, uint32_t elemLen);
void init_tools(void);

41
z.c
View File

@@ -98,14 +98,14 @@ int32_t z_compress( uint8_t *src, int32_t slen, uint8_t **dst, uint32_t dpos, ui
//decompress:
/*
* on success and when finished, returns new compressed size and adds to (*dst) + dpos
* Therefore src and *dst can point to same memory area.
* on failure returns -1 and (*dst) is untouched
* if dst == NULL then dst is untouched
* on success and when finished, returns new decompressed size and adds to (*dstA) + dpos
* Therefore src and *dstA can point to same memory area.
* on failure returns -1 and (*dstA) is untouched
* if dstA == NULL then dstA is untouched
*/
int32_t z_decompress( uint8_t *src, uint32_t slen, uint8_t **dst, uint32_t dpos) {
int32_t z_decompress( uint8_t *src, uint32_t slen, uint8_t *dstB, uint32_t dstBlen)
{
uint8_t *tmp = NULL;
int32_t tlen = 0;
int z_ret;
@@ -117,33 +117,22 @@ int32_t z_decompress( uint8_t *src, uint32_t slen, uint8_t **dst, uint32_t dpos)
strm.avail_in = slen;
strm.next_in = (Bytef*)src;
do {
tmp = debugRealloc(tmp, tlen + Z_CHUNK_SIZE, -300576);
strm.avail_out = dstBlen;
strm.next_out = dstB;
strm.avail_out = Z_CHUNK_SIZE;
strm.next_out = tmp;
if ((((z_ret = inflate(&strm, Z_NO_FLUSH)) != Z_OK) && z_ret != Z_STREAM_END && strm.avail_out == 0)) {
// if (err==Z_STREAM_ERROR || err==Z_NEED_DICT || err==Z_DATA_ERROR || err==Z_MEM_ERROR) {
dbgf_sys(DBGT_ERR, "slen=%d tlen=%d avaoi_out=%d z_ret=%d error: %s ???", slen, tlen, strm.avail_out, z_ret, strerror(errno));
tlen = FAILURE;
if (tlen >= (INT32_MAX - Z_CHUNK_SIZE) || (((z_ret=inflate(&strm, Z_NO_FLUSH)) != Z_OK) && z_ret != Z_STREAM_END)) {
// if (err==Z_STREAM_ERROR || err==Z_NEED_DICT || err==Z_DATA_ERROR || err==Z_MEM_ERROR) {
dbgf_sys(DBGT_ERR, "slen=%d tlen=%d z_ret=%d error: %s ???", slen, tlen, z_ret, strerror(errno));
tlen = FAILURE;
break;
}
} else {
tlen += (Z_CHUNK_SIZE - strm.avail_out);
} while (strm.avail_out == 0);
tlen += (dstBlen - strm.avail_out);
}
// clean up and return:
(void)inflateEnd(&strm);
if (dst && tmp && tlen > 0) {
*dst = debugRealloc(*dst, dpos + tlen, -300577);
memcpy( (*dst) + dpos, tmp, tlen);
}
if(tmp)
debugFree(tmp, -300578);
dbgf(tlen>0?DBGL_CHANGES:DBGL_SYS, tlen>0?DBGT_INFO:DBGT_ERR, "slen=%d tlen=%d", slen, tlen);

4
z.h
View File

@@ -15,8 +15,8 @@
* 02110-1301, USA
*/
#define Z_CHUNK_SIZE 16384
#define Z_CHUNK_SIZE (2*16384)
int32_t z_compress( uint8_t *src, int32_t slen, uint8_t **dst, uint32_t dpos, uint8_t *darr, int32_t darr_max_size);
int32_t z_decompress( uint8_t *src, uint32_t len, uint8_t **dst, uint32_t dst_pos);
int32_t z_decompress(uint8_t *src, uint32_t slen, uint8_t *dstB, uint32_t dstBlen);