diff --git a/modules b/modules
index 767695e3de6e1ea04aa74f260bcb70a9dc300bbd..e44f5244f59d248fb0f3ce4e6b410ab18214957a 100644
--- a/modules
+++ b/modules
@@ -17,4 +17,4 @@ PACKAGES_LUCI_BRANCH=openwrt-18.06
 PACKAGES_LUCI_COMMIT=4ba85e3d82b684262c570e38a72d2dc3bb712a13
 
 PACKAGES_GLUON_REPO=https://github.com/freifunk-gluon/packages.git
-PACKAGES_GLUON_COMMIT=be2c35785994e443d895225c7240474a46f64f5e
+PACKAGES_GLUON_COMMIT=270320709166620d6f7ed0fdeb9a140966ae3fec
diff --git a/package/gluon-core/files/etc/sysctl.d/30-gluon-core.conf b/package/gluon-core/files/etc/sysctl.d/30-gluon-core.conf
index 12d569a0f449eb9c4b25c6778fb3f9ac6cb26b9f..c4013fe873884945a7c39f663cdf2b06e2df3143 100644
--- a/package/gluon-core/files/etc/sysctl.d/30-gluon-core.conf
+++ b/package/gluon-core/files/etc/sysctl.d/30-gluon-core.conf
@@ -1 +1,2 @@
 vm.panic_on_oom=1
+net.ipv4.tcp_ecn=1
diff --git a/package/gluon-core/luasrc/usr/lib/lua/gluon/iputil.lua b/package/gluon-core/luasrc/usr/lib/lua/gluon/iputil.lua
new file mode 100644
index 0000000000000000000000000000000000000000..39e0897afda7f609dd4406fd10f77d9c029d012e
--- /dev/null
+++ b/package/gluon-core/luasrc/usr/lib/lua/gluon/iputil.lua
@@ -0,0 +1,96 @@
+local bit = require 'bit'
+local string = string
+local tonumber = tonumber
+local table = table
+module 'gluon.iputil'
+
+function IPv6(address)
+	--[[
+	(c) 2008 Jo-Philipp Wich <xm@leipzig.freifunk.net>
+	(c) 2008 Steven Barth <steven@midlink.org>
+
+	Licensed under the Apache License, Version 2.0 (the "License").
+	You may obtain a copy of the License at
+
+	http://www.apache.org/licenses/LICENSE-2.0
+	]]--
+	local data = {}
+
+	local borderl = address:sub(1, 1) == ":" and 2 or 1
+	local borderh, zeroh, chunk, block
+
+	if #address > 45 then return nil end
+
+	repeat
+		borderh = address:find(":", borderl, true)
+		if not borderh then break end
+
+		block = tonumber(address:sub(borderl, borderh - 1), 16)
+		if block and block <= 0xFFFF then
+			data[#data+1] = block
+		else
+			if zeroh or borderh - borderl > 1 then return nil end
+			zeroh = #data + 1
+		end
+
+		borderl = borderh + 1
+	until #data == 7
+
+	chunk = address:sub(borderl)
+	if #chunk > 0 and #chunk <= 4 then
+		block = tonumber(chunk, 16)
+		if not block or block > 0xFFFF then return nil end
+
+		data[#data+1] = block
+	elseif #chunk > 4 then
+		if #data == 7 or #chunk > 15 then return nil end
+		borderl = 1
+		for i=1, 4 do
+			borderh = chunk:find(".", borderl, true)
+			if not borderh and i < 4 then return nil end
+			borderh = borderh and borderh - 1
+
+			block = tonumber(chunk:sub(borderl, borderh))
+			if not block or block > 255 then return nil end
+
+			if i == 1 or i == 3 then
+				data[#data+1] = block * 256
+			else
+				data[#data] = data[#data] + block
+			end
+
+			borderl = borderh and borderh + 2
+		end
+	end
+
+	if zeroh then
+		if #data == 8 then return nil end
+		while #data < 8 do
+			table.insert(data, zeroh, 0)
+		end
+	end
+
+	if #data == 8 then
+		return data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8]
+	end
+end
+
+function mac_to_ip(prefix, mac)
+	local m1, m2, m3, m6, m7, m8 = string.match(mac, '(%x%x):(%x%x):(%x%x):(%x%x):(%x%x):(%x%x)')
+	local m4 = 0xff
+	local m5 = 0xfe
+	m1 = bit.bxor(tonumber(m1, 16), 0x02)
+
+	local h1 = 0x100 * m1 + tonumber(m2, 16)
+	local h2 = 0x100 * tonumber(m3, 16) + m4
+	local h3 = 0x100 * m5 + tonumber(m6, 16)
+	local h4 = 0x100 * tonumber(m7, 16) + tonumber(m8, 16)
+
+	local prefix, plen = string.match(prefix, '(.*)/(%d+)')
+	plen = tonumber(plen, 10)
+
+	local p1, p2, p3, p4, p5, p6, p7, p8 = IPv6(prefix)
+
+	return string.format("%x:%x:%x:%x:%x:%x:%x:%x/%d", p1, p2, p3, p4, h1, h2, h3, h4, 128)
+end
+
diff --git a/package/gluon-iptables-clamp-mss-to-pmtu/files/lib/gluon/mesh-vpn/iptables-mss.rules b/package/gluon-iptables-clamp-mss-to-pmtu/files/lib/gluon/mesh-vpn/iptables-mss.rules
index a4ff50b13dd02d05250a8a4d300e56b95ad71a20..a61a900df5ccded0d164d43fac1c3567fada6443 100644
--- a/package/gluon-iptables-clamp-mss-to-pmtu/files/lib/gluon/mesh-vpn/iptables-mss.rules
+++ b/package/gluon-iptables-clamp-mss-to-pmtu/files/lib/gluon/mesh-vpn/iptables-mss.rules
@@ -1,3 +1,3 @@
 *mangle
--A FORWARD -o mesh-vpn -p tcp -m tcp --tcp-flags SYN,RST SYN -d 64:ff9b::/96 -j TCPMSS --clamp-mss-to-pmtu
+-A FORWARD -o mesh-vpn+ -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
 COMMIT
diff --git a/package/gluon-l3roamd/files/etc/init.d/gluon-l3roamd b/package/gluon-l3roamd/files/etc/init.d/gluon-l3roamd
index c64f3b1d8b5a1e2a7e841cb9d859420ceca1299d..fb1ecdfc04897bb053c4bbc85bad6db368716da7 100755
--- a/package/gluon-l3roamd/files/etc/init.d/gluon-l3roamd
+++ b/package/gluon-l3roamd/files/etc/init.d/gluon-l3roamd
@@ -5,10 +5,39 @@ START=55
 USE_PROCD=1
 PROG=/usr/sbin/l3roamd
 
+echotol3roamd() {
+	local count=0
+	local line="$1"
+	while ! (echo -e "$line" | uc /var/run/l3roamd.sock >/dev/null 2>&1)
+	do
+		sleep 1
+		echo retrying to connect to l3roamd in PID $$, waited ${count}s >&2
+		count=$((count+1))
+	done
+	return 0
+}
+
+
+
+reload_service() {
+	for i in $(ubus call network.interface dump | jsonfilter -e "@.interface[@.proto='gluon_mesh' && @.up=true].device")
+	do
+		echotol3roamd "add_meshif $i"
+	done
+
+	for i in $(echotol3roamd "get_meshifs"| jsonfilter -e "@.mesh_interfaces[@]")
+	do
+		if ! ubus call network.interface dump | jsonfilter -e "@.interface[@.proto='gluon_mesh' && @.up=true].device"|grep -q $i
+		then
+			echotol3roamd "del_meshif $i"
+		fi
+	done
+}
+
 start_service () {
 	local interfaces=$(
-		for dev in $(gluon-list-mesh-interfaces); do echo " -m $dev"; done
-		[ "$(ifstatus local_node | jsonfilter -e '@.up')" = 'true' ] && echo ' -i local-node'
+	for dev in $(gluon-list-mesh-interfaces); do echo " -m $dev"; done
+	[ "$(ifstatus local_node | jsonfilter -e '@.up')" = 'true' ] && echo ' -i local-node'
 	)
 	/sbin/sysctl -w net.ipv6.neigh.default.gc_thresh1=2
 	/sbin/sysctl -w net.ipv4.neigh.default.gc_thresh1=2
diff --git a/package/gluon-mesh-babel/files/etc/init.d/gluon-mesh-babel b/package/gluon-mesh-babel/files/etc/init.d/gluon-mesh-babel
index e902f8cb468fa8cf61974b1988669b959f889c23..2d04ff5386b053b45d4ca56ecfd4c98016711825 100755
--- a/package/gluon-mesh-babel/files/etc/init.d/gluon-mesh-babel
+++ b/package/gluon-mesh-babel/files/etc/init.d/gluon-mesh-babel
@@ -22,11 +22,15 @@ start_service() {
 echotobabel() {
 	local count=0
 	local line="$1"
-	while ! (echo -e "$line" | nc ::1 "$PORT" >/dev/null 2>&1)
+	local maxretries=10
+	while ! (echo -e "$line" | busybox nc ::1 "$PORT" >/dev/null 2>&1)
 	do
 		sleep 1
 		echo retrying to connect to babeld in PID $$, waited ${count}s >&2
 		count=$((count+1))
+		if [ $count -gt $maxretries ]; then
+			return 1
+		fi
 	done
 	return 0
 }
diff --git a/package/gluon-mesh-babel/luasrc/lib/gluon/upgrade/300-gluon-mesh-babel-ip6 b/package/gluon-mesh-babel/luasrc/lib/gluon/upgrade/300-gluon-mesh-babel-ip6
index 7ab3f5ec25c6fa1445825a9a2a60e017f0a2c348..1d3f538176f573965fc0aebc935217b8b36d5bdf 100755
--- a/package/gluon-mesh-babel/luasrc/lib/gluon/upgrade/300-gluon-mesh-babel-ip6
+++ b/package/gluon-mesh-babel/luasrc/lib/gluon/upgrade/300-gluon-mesh-babel-ip6
@@ -1,102 +1,11 @@
 #!/usr/bin/lua
 
-local bit = require 'bit'
 local sysconfig = require 'gluon.sysconfig'
 local uci = require('simple-uci').cursor()
 local site = require 'gluon.site'
+local iputil = require 'gluon.iputil'
 
-
-function IPv6(address)
-	--[[
-	(c) 2008 Jo-Philipp Wich <xm@leipzig.freifunk.net>
-	(c) 2008 Steven Barth <steven@midlink.org>
-
-	Licensed under the Apache License, Version 2.0 (the "License").
-	You may obtain a copy of the License at
-
-	http://www.apache.org/licenses/LICENSE-2.0
-	]]--
-	local data = {}
-
-	local borderl = address:sub(1, 1) == ":" and 2 or 1
-	local borderh, zeroh, chunk, block
-
-	if #address > 45 then return nil end
-
-	repeat
-		borderh = address:find(":", borderl, true)
-		if not borderh then break end
-
-		block = tonumber(address:sub(borderl, borderh - 1), 16)
-		if block and block <= 0xFFFF then
-			data[#data+1] = block
-		else
-			if zeroh or borderh - borderl > 1 then return nil end
-			zeroh = #data + 1
-		end
-
-		borderl = borderh + 1
-	until #data == 7
-
-	chunk = address:sub(borderl)
-	if #chunk > 0 and #chunk <= 4 then
-		block = tonumber(chunk, 16)
-		if not block or block > 0xFFFF then return nil end
-
-		data[#data+1] = block
-	elseif #chunk > 4 then
-		if #data == 7 or #chunk > 15 then return nil end
-		borderl = 1
-		for i=1, 4 do
-			borderh = chunk:find(".", borderl, true)
-			if not borderh and i < 4 then return nil end
-			borderh = borderh and borderh - 1
-
-			block = tonumber(chunk:sub(borderl, borderh))
-			if not block or block > 255 then return nil end
-
-			if i == 1 or i == 3 then
-				data[#data+1] = block * 256
-			else
-				data[#data] = data[#data] + block
-			end
-
-			borderl = borderh and borderh + 2
-		end
-	end
-
-	if zeroh then
-		if #data == 8 then return nil end
-		while #data < 8 do
-			table.insert(data, zeroh, 0)
-		end
-	end
-
-	if #data == 8 then
-		return data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8]
-	end
-end
-
-function mac_to_ip(prefix, mac)
-	local m1, m2, m3, m6, m7, m8 = string.match(mac, '(%x%x):(%x%x):(%x%x):(%x%x):(%x%x):(%x%x)')
-	local m4 = 0xff
-	local m5 = 0xfe
-	m1 = bit.bxor(tonumber(m1, 16), 0x02)
-
-	local h1 = 0x100 * m1 + tonumber(m2, 16)
-	local h2 = 0x100 * tonumber(m3, 16) + m4
-	local h3 = 0x100 * m5 + tonumber(m6, 16)
-	local h4 = 0x100 * tonumber(m7, 16) + tonumber(m8, 16)
-
-	local prefix, plen = string.match(prefix, '(.*)/(%d+)')
-	plen = tonumber(plen, 10)
-
-	local p1, p2, p3, p4, p5, p6, p7, p8 = IPv6(prefix)
-
-	return string.format("%x:%x:%x:%x:%x:%x:%x:%x/%d", p1, p2, p3, p4, h1, h2, h3, h4, 128)
-end
-
-local ip = mac_to_ip(site.node_prefix6(), sysconfig.primary_mac)
+local ip = iputil.mac_to_ip(site.node_prefix6(), sysconfig.primary_mac)
 
 uci:set('network', 'loopback', 'ip6addr', ip)
 uci:save('network')
diff --git a/package/gluon-mesh-babel/src/respondd.c b/package/gluon-mesh-babel/src/respondd.c
index 733e9abb795dd4e0eb0393994698401aa86565f7..075aa0649951bd6ab33db5533cf14795da6f9cdb 100644
--- a/package/gluon-mesh-babel/src/respondd.c
+++ b/package/gluon-mesh-babel/src/respondd.c
@@ -47,6 +47,7 @@
 #include <sys/ioctl.h>
 #include <sys/socket.h>
 #include <sys/un.h>
+#include <ifaddrs.h>
 
 #include <linux/ethtool.h>
 #include <linux/if_addr.h>
@@ -78,30 +79,41 @@
 
 static struct babelhelper_ctx bhelper_ctx = {};
 
-static int obtain_ifmac(unsigned char *ifmac, const char *ifname) {
-	struct ifreq ifr = {};
-	int sock;
+static void obtain_if_addr(const char *ifname, char *lladdr) {
+	struct ifaddrs *ifaddr, *ifa;
+	int family, n;
 
-	sock=socket(PF_INET, SOCK_STREAM, 0);
-	if (-1==sock) {
-		perror("socket() ");
-		return 1;
+	if (getifaddrs(&ifaddr) == -1) {
+		perror("getifaddrs");
+		exit(EXIT_FAILURE);
 	}
 
-	strncpy(ifr.ifr_name, ifname, IFNAMSIZ-1);
+	for (ifa = ifaddr, n = 0; ifa != NULL; ifa = ifa->ifa_next, n++) {
+		if (ifa->ifa_addr == NULL)
+			continue;
+
+		family = ifa->ifa_addr->sa_family;
+
+		if ( (family == AF_INET6) && ( ! strncmp(ifname, ifa->ifa_name, strlen(ifname)) ) ) {
+			char lhost[INET6_ADDRSTRLEN];
+			struct in6_addr *address = &((struct sockaddr_in6*)ifa->ifa_addr)->sin6_addr;
+			if (inet_ntop(AF_INET6, address, lhost, INET6_ADDRSTRLEN) == NULL) {
+				fprintf(stderr, "obtain_if_addr: could not convert ip to string\n");
+				goto cleanup;
+			}
 
-	printf("obtaining hw address for nic: %s %s\n", ifname, ifr.ifr_name);
-	if (-1==ioctl(sock, SIOCGIFHWADDR, &ifr)) {
-		perror("ioctl(SIOCGIFHWADDR) ");
-		close(sock);
-		return 1;
+			if (! strncmp("fe80:", lhost, 5) ) {
+				snprintf( lladdr, NI_MAXHOST, "%s", lhost );
+				goto cleanup;
+			}
+		}
 	}
-	close(sock);
 
-	memcpy(ifmac, ifr.ifr_hwaddr.sa_data, 6);
-	return 0;
+cleanup:
+	freeifaddrs(ifaddr);
 }
 
+
 static char*  get_line_from_run(const char* command) {
 	FILE *fp;
 	char *line = NULL;
@@ -167,34 +179,11 @@ static bool interface_file_exists(const char *ifname, const char *name) {
 	return !access(path, F_OK);
 }
 
-struct in6_addr mac2ipv6(uint8_t mac[6], char * prefix) {
-	struct in6_addr address = {};
-	inet_pton(AF_INET6, prefix, &address);
-
-	address.s6_addr[8] = mac[0] ^ 0x02;
-	address.s6_addr[9] = mac[1];
-	address.s6_addr[10] = mac[2];
-	address.s6_addr[11] = 0xff;
-	address.s6_addr[12] = 0xfe;
-	address.s6_addr[13] = mac[3];
-	address.s6_addr[14] = mac[4];
-	address.s6_addr[15] = mac[5];
-
-	return address;
-}
-
 static void mesh_add_if(const char *ifname, struct json_object *wireless,
 		struct json_object *tunnel, struct json_object *other) {
-	char str_ip[INET6_ADDRSTRLEN] = {};
-	unsigned char mac[6] = {};
+	char str_ip[NI_MAXHOST] = {};
 
-	if (obtain_ifmac(mac, ifname)) {
-		printf("could not obtain mac for device: %s", ifname);
-		return;
-	}
-
-	struct in6_addr lladdr = mac2ipv6(mac, "fe80::");
-	inet_ntop(AF_INET6, &lladdr.s6_addr, str_ip, INET6_ADDRSTRLEN);
+	obtain_if_addr(ifname, str_ip);
 
 	struct json_object *address = json_object_new_string(str_ip);
 
@@ -206,6 +195,8 @@ static void mesh_add_if(const char *ifname, struct json_object *wireless,
 		json_object_array_add(other, address);
 
 }
+
+
 static bool handle_neighbour(char **data, void *obj) {
 	if (data[NEIGHBOUR]) {
 		struct json_object *neigh = json_object_new_object();
@@ -221,17 +212,10 @@ static bool handle_neighbour(char **data, void *obj) {
 
 		struct json_object *nif = 0;
 		if (data[IF] && !json_object_object_get_ex(obj, data[IF], &nif)) {
-			nif = json_object_new_object();
-
-			unsigned char ifmac[6] = {};
-			char str_ip[INET6_ADDRSTRLEN] = {};
+			char str_ip[NI_MAXHOST] = {};
+			obtain_if_addr( (const char*)data[IF], str_ip );
 
-			if (obtain_ifmac(ifmac, (const char*)data[IF])) {
-				printf("could not obtain mac for device: %s", data[IF]);
-				return false;
-			}
-			struct in6_addr lladdr = mac2ipv6(ifmac, "fe80::");
-			inet_ntop(AF_INET6, &lladdr.s6_addr, str_ip, INET6_ADDRSTRLEN);
+			nif = json_object_new_object();
 
 			json_object_object_add(nif, "ll-addr", json_object_new_string(str_ip));
 			json_object_object_add(nif, "protocol", json_object_new_string("babel"));