--- /dev/null
+#ifdef NDEBUG
+#undef NDEBUG
+#endif
+
+#include <assert.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "meshlink-tiny.h"
+#include "devtools.h"
+#include "netns_utils.h"
+#include "utils.h"
+
+#include "full.h"
+
+static void print_counters(peer_config_t *peers, const char *description) {
+ printf("%s:\n", description);
+ printf(" %9s %9s %9s %9s %9s %9s\n",
+ "in data",
+ "forward",
+ "meta",
+ "out data",
+ "forward",
+ "meta");
+
+ assert(peers[0].full);
+
+ for(int i = 0; i < 3; i++) {
+ meshlink_node_t *node = full_meshlink_get_node(peers[0].mesh, peers[i].name);
+ assert(node);
+ struct devtool_node_status status;
+ full_devtool_reset_node_counters(peers[0].mesh, node, &status);
+ printf(" %5s: %9" PRIu64 " %9" PRIu64 " %9" PRIu64 " %9" PRIu64 " %9" PRIu64 " %9" PRIu64 "\n",
+ node->name,
+ status.in_data,
+ status.in_forward,
+ status.in_meta,
+ status.out_data,
+ status.out_forward,
+ status.out_meta);
+ }
+}
+
+
+int main(void) {
+ init_full();
+
+ meshlink_set_log_cb(NULL, MESHLINK_DEBUG, log_cb);
+
+ // Set up relay, peer and NUT
+ peer_config_t *peers = setup_relay_peer_nut("metering");
+
+ // Ensure DEV_CLASS_STATIONARY uses a 5 minute ping time
+ for(int i = 0; i < 3; i++) {
+ peers[i].full
+ ? full_meshlink_set_dev_class_timeouts(peers[i].mesh, DEV_CLASS_STATIONARY, 300, 5)
+ : meshlink_set_dev_class_timeouts(peers[i].mesh, DEV_CLASS_BACKBONE, 300, 5);
+ }
+
+ for(int i = 0; i < 3; i++) {
+ assert(peers[i].full
+ ? full_meshlink_start(peers[i].mesh)
+ : meshlink_start(peers[i].mesh)
+ );
+ }
+
+ // Measure traffic after 1 minute of PMTU probing
+ sleep(60);
+ print_counters(peers, "PMTU probing (1 min)");
+
+ // Measure traffic after 1 minute of idle
+ for(int i = 0; i < 10; i++) {
+ sleep(60);
+ print_counters(peers, "Idle (1 min)");
+ }
+
+ close_relay_peer_nut(peers);
+}
#define _GNU_SOURCE 1
-#ifndef NDEBUG
+#ifdef NDEBUG
#undef NDEBUG
#endif
#include <sys/stat.h>
#include <fcntl.h>
-#include "../src/meshlink-tiny.h"
+#include "meshlink-tiny.h"
#include "netns_utils.h"
#include "utils.h"
+#include "full.h"
+
static int ip = 1;
/// Create meshlink instances and network namespaces for a list of peers
}
for(int i = 0; i < npeers; i++) {
+ bool full = peers[i].full;
+
assert(asprintf(&peers[i].netns_name, "%s%d", prefix, i) > 0);
char *command = NULL;
assert(asprintf(&command,
char *conf_path = NULL;
assert(asprintf(&conf_path, "%s_conf.%d", prefix, i + 1) > 0);
assert(conf_path);
- assert(meshlink_destroy(conf_path));
+ assert(full ? full_meshlink_destroy(conf_path) : meshlink_destroy(conf_path));
- meshlink_open_params_t *params = meshlink_open_params_init(conf_path, peers[i].name, prefix, peers[i].devclass);
+ meshlink_open_params_t *params = full
+ ? full_meshlink_open_params_init(conf_path, peers[i].name, prefix, peers[i].devclass)
+ : meshlink_open_params_init(conf_path, peers[i].name, prefix, peers[i].devclass);
assert(params);
- assert(meshlink_open_params_set_netns(params, peers[i].netns));
+ assert(full
+ ? full_meshlink_open_params_set_netns(params, peers[i].netns)
+ : meshlink_open_params_set_netns(params, peers[i].netns)
+ );
- peers[i].mesh = meshlink_open_ex(params);
+ peers[i].mesh = full ? full_meshlink_open_ex(params) : meshlink_open_ex(params);
assert(peers[i].mesh);
free(params);
free(conf_path);
+
+ if(full) {
+ full_meshlink_enable_discovery(peers[i].mesh, false);
+ }
}
}
}
}
+/// Set up an indirect topology where all peers can only access the relay
+static void setup_indirect_topology(peer_config_t *peers, int npeers) {
+ // Add an interface to each peer that is connected to the relay
+ for(int i = 1; i < npeers; i++) {
+ char *command = NULL;
+ assert(asprintf(&command,
+ "/bin/ip netns exec %1$s /bin/ip link add eth0 type veth peer eth%3$d netns %2$s;"
+ "/bin/ip netns exec %1$s ip addr flush dev eth0;"
+ "/bin/ip netns exec %1$s ip addr add 192.168.%3$d.2/24 dev eth0;"
+ "/bin/ip netns exec %1$s /bin/ip link set dev eth0 up;"
+ "/bin/ip netns exec %2$s ip addr flush dev eth%3$d;"
+ "/bin/ip netns exec %2$s ip addr add 192.168.%3$d.1/24 dev eth%3$d;"
+ "/bin/ip netns exec %2$s /bin/ip link set dev eth%3$d up;",
+ peers[i].netns_name, peers[0].netns_name, i));
+ assert(command);
+ assert(system(command) == 0);
+ free(command);
+ }
+}
+
/// Give a peer a unique IP address
void change_peer_ip(peer_config_t *peer) {
char *command = NULL;
}
/// Let the first peer in a list invite all the subsequent peers
-static void link_peers(peer_config_t *peers, int npeers) {
+static void invite_peers(peer_config_t *peers, int npeers) {
+ assert(peers[0].full);
+ assert(full_meshlink_start(peers[0].mesh));
+
for(int i = 1; i < npeers; i++) {
- char *export_relay = meshlink_export(peers[0].mesh);
- char *export_peer = meshlink_export(peers[i].mesh);
- assert(export_relay);
- assert(export_peer);
- assert(meshlink_import(peers[0].mesh, export_peer));
- assert(meshlink_import(peers[i].mesh, export_relay));
- free(export_relay);
- free(export_peer);
+ char *invitation = full_meshlink_invite_ex(peers[0].mesh, NULL, peers[i].name, MESHLINK_INVITE_LOCAL | MESHLINK_INVITE_NUMERIC);
+ assert(invitation);
+ printf("%s\n", invitation);
+ assert(peers[i].full ? full_meshlink_join(peers[i].mesh, invitation) : meshlink_join(peers[i].mesh, invitation));
+ free(invitation);
}
+
+ full_meshlink_stop(peers[0].mesh);
}
/// Close meshlink instances and clean up
static void close_peers(peer_config_t *peers, int npeers) {
for(int i = 0; i < npeers; i++) {
- meshlink_close(peers[i].mesh);
+ peers[i].full ? full_meshlink_close(peers[i].mesh) : meshlink_close(peers[i].mesh);
close(peers[i].netns);
free(peers[i].netns_name);
}
/// Set up relay, peer and NUT that are directly connected
peer_config_t *setup_relay_peer_nut(const char *prefix) {
static peer_config_t peers[] = {
- {"relay", DEV_CLASS_BACKBONE},
- {"peer", DEV_CLASS_STATIONARY},
- {"nut", DEV_CLASS_STATIONARY},
+ {"relay", DEV_CLASS_BACKBONE, NULL, 0, true, NULL},
+ {"peer", DEV_CLASS_STATIONARY, NULL, 0, false, NULL},
+ {"nut", DEV_CLASS_STATIONARY, NULL, 0, false, NULL},
};
create_peers(peers, 3, prefix);
setup_lan_topology(peers, 3);
- link_peers(peers, 3);
+ invite_peers(peers, 3);
+
+ return peers;
+}
+
+/// Set up relay, peer and NUT that are directly connected
+peer_config_t *setup_relay_peer_nut_indirect(const char *prefix) {
+ static peer_config_t peers[] = {
+ {"relay", DEV_CLASS_BACKBONE, NULL, 0, true, NULL},
+ {"peer", DEV_CLASS_STATIONARY, NULL, 0, false, NULL},
+ {"nut", DEV_CLASS_STATIONARY, NULL, 0, false, NULL},
+ };
+
+ create_peers(peers, 3, prefix);
+ setup_indirect_topology(peers, 3);
+ assert(full_meshlink_add_invitation_address(peers[0].mesh, "192.168.1.1", NULL));
+ assert(full_meshlink_add_invitation_address(peers[0].mesh, "192.168.2.1", NULL));
+ invite_peers(peers, 3);
return peers;
}
+/// Make all nodes only be able to communicate via TCP
+void set_peers_tcponly(peer_config_t *peers, int npeers) {
+ for(int i = 0; i < npeers; i++) {
+ char *command = NULL;
+ assert(asprintf(&command,
+ "/bin/ip netns exec %1$s iptables -A INPUT -p udp -j DROP;"
+ "/bin/ip netns exec %1$s iptables -A OUTPUT -p udp -j DROP;",
+ peers[i].netns_name));
+ assert(command);
+ assert(system(command) == 0);
+ free(command);
+ }
+}
+
void close_relay_peer_nut(peer_config_t *peers) {
close_peers(peers, 3);
}