alfred: Start up alfred without valid interfaces

The alfred server always needs interfaces to operate on. But these
interfaces might not exist at the moment when the daemon process is
started. This situation stopped the startup process after the init scripts
waited for a longer period of polling the system state.

But alfred is able to deal with interfaces which disappeared at runtime but
existed at startup. To force a similar behavior for the alfred startup, the
parameter "--force" or "-f" is used. The extra polling code is therefore no
longer needed in the init scripts.

Signed-off-by: Sven Eckelmann <sven@narfation.org>
This commit is contained in:
Sven Eckelmann 2021-02-15 21:17:53 +01:00
parent 993f03cecb
commit ad85bc8142
6 changed files with 272 additions and 50 deletions

View File

@ -4,7 +4,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=alfred
PKG_VERSION:=2021.0
PKG_RELEASE:=2
PKG_RELEASE:=3
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://downloads.open-mesh.org/batman/releases/batman-adv-$(PKG_VERSION)

View File

@ -13,53 +13,9 @@ facters_dir="/etc/alfred"
enable=0
vis_enable=0
wait_for_dir() {
local ifce="$1" dir="$2"
if ! [ -d "$dir" ] ; then
timeout=30
echo "waiting $timeout secs for $ifce interface..."
for i in $(seq $timeout); do
sleep 1
[ -d "$dir" ] && break
if [ $i = $timeout ] ; then
echo "$ifce not detected, alfred not starting."
return 1
fi
done
fi
return 0
}
wait_for_ll_address() {
local iface="$1"
local timeout=30
echo "waiting $timeout secs for $iface address..."
for i in $(seq $timeout); do
# We look for
# - the link-local address (starts with fe80)
# - without tentative flag (bit 0x40 in the flags field; the first char of the fifth field is evaluated)
# - on interface $iface
if awk '
BEGIN { RET=1 }
$1 ~ /^fe80/ && $5 ~ /^[012389ab]/ && $6 == "'"$iface"'" { RET=0 }
END { exit RET }
' /proc/net/if_inet6; then
return 0
fi
sleep 1
done
echo "$iface address not detected, alfred not starting."
return 1
}
append_interface()
{
append "interfaces" "$1" ","
wait_for_ll_address "$1"
}
alfred_start() {
@ -72,7 +28,7 @@ alfred_start() {
config_get_bool disabled "$section" disabled 0
[ $disabled = 0 ] || return 1
args=""
args="-f"
config_list_foreach "$section" "interface" append_interface
if [ -z "$interfaces" ]; then
@ -87,10 +43,6 @@ alfred_start() {
config_get batmanif "$section" batmanif
append args "-b $batmanif"
if [ "$batmanif" != "none" ]; then
wait_for_dir "$batmanif" "/sys/devices/virtual/net/$batmanif" || return 1
fi
append alfred_args "$args"
enable=1

View File

@ -0,0 +1,29 @@
From: Sven Eckelmann <sven@narfation.org>
Date: Mon, 15 Feb 2021 19:56:22 +0100
Subject: alfred: Show error message for invalid batadv interface
The alfred server process always stopped without any informational message
when the provided batman-adv was not "none" and was not accessible. This
made it extremely hard to debug the reason why alfred directly stopped
after launching it.
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Forwarded: https://patchwork.open-mesh.org/project/b.a.t.m.a.n./patch/20210215200126.140253-1-sven@narfation.org/
diff --git a/server.c b/server.c
index fc27246b845af75bd1f459f8bb553aef87cc24d5..efac5ad399df52f8c444711a14bcf4814e38a3bf 100644
--- a/server.c
+++ b/server.c
@@ -385,8 +385,11 @@ int alfred_server(struct globals *globals)
}
if (strcmp(globals->mesh_iface, "none") != 0 &&
- batadv_interface_check(globals->mesh_iface) < 0)
+ batadv_interface_check(globals->mesh_iface) < 0) {
+ fprintf(stderr, "Can't start server: batman-adv interface %s not found\n",
+ globals->mesh_iface);
return -1;
+ }
num_socks = netsock_open_all(globals);
if (num_socks <= 0) {

View File

@ -0,0 +1,72 @@
From: Sven Eckelmann <sven@narfation.org>
Date: Mon, 15 Feb 2021 20:16:15 +0100
Subject: alfred: Allow exactly one interface for secondary mode
A primary alfred daemon allows syncing over more than one interface. But
the secondary alfred daemon needs exactly one interface. But the check for
this property was insufficient because it allowed paramters like
"-i wlan0,asd" when wlan0 is valid and asd is not valid.
The better solution is to really use the number of interfaces given to
alfred instead of the number of interfaces evaluated as "valid".
Fixes: 67ae5f57eedd ("alfred: Add support for multiple interfaces per master")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Forwarded: https://patchwork.open-mesh.org/project/b.a.t.m.a.n./patch/20210215200126.140253-2-sven@narfation.org/
diff --git a/alfred.h b/alfred.h
index 1e2c05835cbfba02ebabefe55afc29f7ef8e12b1..7d6b0b35b5c8b8c3b087589880c390eb035584be 100644
--- a/alfred.h
+++ b/alfred.h
@@ -182,6 +182,7 @@ int unix_sock_req_data_finish(struct globals *globals,
int vis_update_data(struct globals *globals);
/* netsock.c */
int netsock_open_all(struct globals *globals);
+size_t netsocket_count_interfaces(struct globals *globals);
void netsock_close_all(struct globals *globals);
int netsock_set_interfaces(struct globals *globals, char *interfaces);
struct interface *netsock_first_interface(struct globals *globals);
diff --git a/netsock.c b/netsock.c
index 367b20730500a1c24448200a24149b64059f3381..84b0ec3827e491eead997f58b2b8f26c5b18b843 100644
--- a/netsock.c
+++ b/netsock.c
@@ -471,6 +471,17 @@ int netsock_open_all(struct globals *globals)
return num_socks;
}
+size_t netsocket_count_interfaces(struct globals *globals)
+{
+ struct interface *interface;
+ size_t count = 0;
+
+ list_for_each_entry(interface, &globals->interfaces, list)
+ count++;
+
+ return count;
+}
+
void netsock_reopen(struct globals *globals)
{
struct interface *interface;
diff --git a/server.c b/server.c
index efac5ad399df52f8c444711a14bcf4814e38a3bf..eb2bc8aeb787e4bf028c8f9e3a523a18c6992be1 100644
--- a/server.c
+++ b/server.c
@@ -371,6 +371,7 @@ int alfred_server(struct globals *globals)
int maxsock, ret, recvs;
struct timespec last_check, now, tv;
fd_set fds, errfds;
+ size_t num_interfaces;
int num_socks;
if (create_hashes(globals))
@@ -397,7 +398,8 @@ int alfred_server(struct globals *globals)
return -1;
}
- if (num_socks > 1 && globals->opmode == OPMODE_SECONDARY) {
+ num_interfaces = netsocket_count_interfaces(globals);
+ if (num_interfaces > 1 && globals->opmode == OPMODE_SECONDARY) {
fprintf(stderr, "More than one interface specified in secondary mode\n");
return -1;
}

View File

@ -0,0 +1,67 @@
From: Sven Eckelmann <sven@narfation.org>
Date: Mon, 15 Feb 2021 20:34:54 +0100
Subject: alfred: Save global mode flags in bitfield
The verbose and ipv4mode entries in the globals structure is only used to
save a boolean information. So just use a bit in a bitfield to store this
information instead of a full int.
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Forwarded: https://patchwork.open-mesh.org/project/b.a.t.m.a.n./patch/20210215200126.140253-3-sven@narfation.org/
diff --git a/alfred.h b/alfred.h
index 7d6b0b35b5c8b8c3b087589880c390eb035584be..c64ff17ab9be8a16b3e1c86070b93235c226a004 100644
--- a/alfred.h
+++ b/alfred.h
@@ -115,8 +115,8 @@ struct globals {
enum clientmode clientmode;
int clientmode_arg;
int clientmode_version;
- int verbose;
- int ipv4mode;
+ uint8_t verbose:1;
+ uint8_t ipv4mode:1;
int unix_sock;
const char *unix_path;
diff --git a/main.c b/main.c
index 7b866cc4275797beb7f614dd1a19ea0099e1281b..f25b6cc11975b8523abf6c59b77a86e94684b03b 100644
--- a/main.c
+++ b/main.c
@@ -9,6 +9,7 @@
#include <arpa/inet.h>
#include <getopt.h>
#include <signal.h>
+#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -181,8 +182,8 @@ static struct globals *alfred_init(int argc, char *argv[])
globals->clientmode_version = 0;
globals->mesh_iface = "bat0";
globals->unix_path = ALFRED_SOCK_PATH_DEFAULT;
- globals->verbose = 0;
- globals->ipv4mode = 0;
+ globals->verbose = false;
+ globals->ipv4mode = false;
globals->update_command = NULL;
globals->sync_period.tv_sec = ALFRED_INTERVAL;
globals->sync_period.tv_nsec = 0;
@@ -252,7 +253,7 @@ static struct globals *alfred_init(int argc, char *argv[])
globals->unix_path = optarg;
break;
case 'd':
- globals->verbose++;
+ globals->verbose = true;
break;
case 'c':
globals->update_command = optarg;
@@ -268,7 +269,7 @@ static struct globals *alfred_init(int argc, char *argv[])
printf(" ** Setting sync interval to: %.9f seconds (%ld.%09ld)\n", sync_period, globals->sync_period.tv_sec, globals->sync_period.tv_nsec);
break;
case '4':
- globals->ipv4mode = 1;
+ globals->ipv4mode = true;
inet_pton(AF_INET, optarg, &alfred_mcast.ipv4);
printf(" ** IPv4 Multicast Mode: %x\n", alfred_mcast.ipv4.s_addr);
break;

View File

@ -0,0 +1,102 @@
From: Sven Eckelmann <sven@narfation.org>
Date: Mon, 15 Feb 2021 20:52:17 +0100
Subject: alfred: Allow start of server without valid interface
The alfred server always needs interfaces to operate on. But these
interfaces might not exist at the moment when the daemon process is
started. This caused an error and stopped the process.
But alfred is able to deal with interfaces which disappeared at runtime but
existed at startup. To force a similar behavior for the alfred startup, the
parameter "--force" or "-f" is introduced.
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Forwarded: https://patchwork.open-mesh.org/project/b.a.t.m.a.n./patch/20210215200126.140253-4-sven@narfation.org/
diff --git a/alfred.h b/alfred.h
index c64ff17ab9be8a16b3e1c86070b93235c226a004..ac082536bd6565756835489194be9b80fe0dd653 100644
--- a/alfred.h
+++ b/alfred.h
@@ -117,6 +117,7 @@ struct globals {
int clientmode_version;
uint8_t verbose:1;
uint8_t ipv4mode:1;
+ uint8_t force:1;
int unix_sock;
const char *unix_path;
diff --git a/main.c b/main.c
index f25b6cc11975b8523abf6c59b77a86e94684b03b..e190d4274a0fe2abdb2c462a5bdefb3e199d4797 100644
--- a/main.c
+++ b/main.c
@@ -164,6 +164,7 @@ static struct globals *alfred_init(int argc, char *argv[])
{"version", no_argument, NULL, 'v'},
{"verbose", no_argument, NULL, 'd'},
{"sync-period", required_argument, NULL, 'p'},
+ {"force", no_argument, NULL, 'f'},
{NULL, 0, NULL, 0},
};
@@ -184,6 +185,7 @@ static struct globals *alfred_init(int argc, char *argv[])
globals->unix_path = ALFRED_SOCK_PATH_DEFAULT;
globals->verbose = false;
globals->ipv4mode = false;
+ globals->force = false;
globals->update_command = NULL;
globals->sync_period.tv_sec = ALFRED_INTERVAL;
globals->sync_period.tv_nsec = 0;
@@ -191,7 +193,7 @@ static struct globals *alfred_init(int argc, char *argv[])
time_random_seed();
- while ((opt = getopt_long(argc, argv, "ms:r:hi:b:vV:M:I:u:dc:p:4:", long_options,
+ while ((opt = getopt_long(argc, argv, "ms:r:hi:b:vV:M:I:u:dc:p:4:f", long_options,
&opt_ind)) != -1) {
switch (opt) {
case 'r':
@@ -273,6 +275,9 @@ static struct globals *alfred_init(int argc, char *argv[])
inet_pton(AF_INET, optarg, &alfred_mcast.ipv4);
printf(" ** IPv4 Multicast Mode: %x\n", alfred_mcast.ipv4.s_addr);
break;
+ case 'f':
+ globals->force = true;
+ break;
case 'h':
default:
alfred_usage();
diff --git a/man/alfred.8 b/man/alfred.8
index 25591be9ece1f8de572be8f639576861e318005f..e965db8260086cc83bc78ad95f97bc368a6cb170 100644
--- a/man/alfred.8
+++ b/man/alfred.8
@@ -72,6 +72,9 @@ Collect data from the network and prints it on the network
\fB\-d\fP, \fB\-\-verbose\fP
Show extra information in the data output
.TP
+\fB\-d\fP, \fB\-\-force\fP
+Start server even when batman-adv or interface(s) are not yet available.
+.TP
\fB\-V\fP, \fB\-\-req\-version\fP \fIversion\fP
Specify the data version set for \fB\-s\fP
diff --git a/server.c b/server.c
index eb2bc8aeb787e4bf028c8f9e3a523a18c6992be1..b4925e7e16ba7465662a5dbf12432916fed8bd03 100644
--- a/server.c
+++ b/server.c
@@ -386,14 +386,15 @@ int alfred_server(struct globals *globals)
}
if (strcmp(globals->mesh_iface, "none") != 0 &&
- batadv_interface_check(globals->mesh_iface) < 0) {
+ batadv_interface_check(globals->mesh_iface) < 0 &&
+ !globals->force) {
fprintf(stderr, "Can't start server: batman-adv interface %s not found\n",
globals->mesh_iface);
return -1;
}
num_socks = netsock_open_all(globals);
- if (num_socks <= 0) {
+ if (num_socks <= 0 && !globals->force) {
fprintf(stderr, "Failed to open interfaces\n");
return -1;
}