13 #include "../src/meshlink.h"
14 #include "netns_utils.h"
19 /// Create meshlink instances and network namespaces for a list of peers
20 static void create_peers(peer_config_t *peers, int npeers, const char *prefix) {
21 // We require root for network namespaces
26 for(int i = 0; i < npeers; i++) {
27 assert(asprintf(&peers[i].netns_name, "%s%d", prefix, i) > 0);
29 assert(asprintf(&command,
30 "/bin/ip netns delete %1$s 2>/dev/null || true;"
31 "/bin/ip netns add %1$s;"
32 "/bin/ip netns exec %1$s ip link set dev lo up;",
33 peers[i].netns_name));
35 assert(system(command) == 0);
38 char *netns_path = NULL;
39 assert(asprintf(&netns_path, "/run/netns/%s", peers[i].netns_name));
41 peers[i].netns = open(netns_path, O_RDONLY);
42 assert(peers[i].netns != -1);
45 char *conf_path = NULL;
46 assert(asprintf(&conf_path, "%s_conf.%d", prefix, i + 1) > 0);
48 assert(meshlink_destroy(conf_path));
50 meshlink_open_params_t *params = meshlink_open_params_init(conf_path, peers[i].name, prefix, peers[i].devclass);
52 assert(meshlink_open_params_set_netns(params, peers[i].netns));
54 peers[i].mesh = meshlink_open_ex(params);
55 assert(peers[i].mesh);
59 meshlink_enable_discovery(peers[i].mesh, false);
63 /// Set up a LAN topology where all peers can see each other directly
64 static void setup_lan_topology(peer_config_t *peers, int npeers) {
65 // Set up the LAN bridge
68 assert(asprintf(&command,
69 "/bin/ip netns exec %1$s /bin/ip link add eth0 type bridge;"
70 "/bin/ip netns exec %1$s /bin/ip link set eth0 up;",
71 peers[0].netns_name));
73 assert(system(command) == 0);
76 // Add an interface to each peer that is connected to the bridge
77 for(int i = 1; i < npeers; i++) {
79 assert(asprintf(&command,
80 "/bin/ip netns exec %1$s /bin/ip link add eth0 type veth peer eth%3$d netns %2$s;"
81 "/bin/ip netns exec %1$s /bin/ip link set dev eth0 up;"
82 "/bin/ip netns exec %2$s /bin/ip link set dev eth%3$d master eth0 up;",
83 peers[i].netns_name, peers[0].netns_name, i));
85 assert(system(command) == 0);
89 // Configure addresses
90 for(int i = 0; i < npeers; i++) {
91 change_peer_ip(&peers[i]);
95 /// Set up an indirect topology where all peers can only access the relay
96 static void setup_indirect_topology(peer_config_t *peers, int npeers) {
97 // Add an interface to each peer that is connected to the relay
98 for(int i = 1; i < npeers; i++) {
100 assert(asprintf(&command,
101 "/bin/ip netns exec %1$s /bin/ip link add eth0 type veth peer eth%3$d netns %2$s;"
102 "/bin/ip netns exec %1$s ip addr flush dev eth0;"
103 "/bin/ip netns exec %1$s ip addr add 192.168.%3$d.2/24 dev eth0;"
104 "/bin/ip netns exec %1$s /bin/ip link set dev eth0 up;"
105 "/bin/ip netns exec %2$s ip addr flush dev eth%3$d;"
106 "/bin/ip netns exec %2$s ip addr add 192.168.%3$d.1/24 dev eth%3$d;"
107 "/bin/ip netns exec %2$s /bin/ip link set dev eth%3$d up;",
108 peers[i].netns_name, peers[0].netns_name, i));
110 assert(system(command) == 0);
115 /// Give a peer a unique IP address
116 void change_peer_ip(peer_config_t *peer) {
117 char *command = NULL;
118 assert(asprintf(&command,
119 "/bin/ip netns exec %1$s ip addr flush dev eth0;"
120 "/bin/ip netns exec %1$s ip addr add 203.0.113.%2$d/24 dev eth0;",
121 peer->netns_name, ip));
124 assert(system(command) == 0);
128 /// Let the first peer in a list invite all the subsequent peers
129 static void invite_peers(peer_config_t *peers, int npeers) {
130 assert(meshlink_start(peers[0].mesh));
132 for(int i = 1; i < npeers; i++) {
133 char *invitation = meshlink_invite_ex(peers[0].mesh, NULL, peers[i].name, MESHLINK_INVITE_LOCAL | MESHLINK_INVITE_NUMERIC);
135 printf("%s\n", invitation);
136 assert(meshlink_join(peers[i].mesh, invitation));
140 meshlink_stop(peers[0].mesh);
143 /// Close meshlink instances and clean up
144 static void close_peers(peer_config_t *peers, int npeers) {
145 for(int i = 0; i < npeers; i++) {
146 meshlink_close(peers[i].mesh);
147 close(peers[i].netns);
148 free(peers[i].netns_name);
152 /// Set up relay, peer and NUT that are directly connected
153 peer_config_t *setup_relay_peer_nut(const char *prefix) {
154 static peer_config_t peers[] = {
155 {"relay", DEV_CLASS_BACKBONE, NULL, 0, NULL},
156 {"peer", DEV_CLASS_STATIONARY, NULL, 0, NULL},
157 {"nut", DEV_CLASS_STATIONARY, NULL, 0, NULL},
160 create_peers(peers, 3, prefix);
161 setup_lan_topology(peers, 3);
162 invite_peers(peers, 3);
167 /// Set up relay, peer and NUT that are directly connected
168 peer_config_t *setup_relay_peer_nut_indirect(const char *prefix) {
169 static peer_config_t peers[] = {
170 {"relay", DEV_CLASS_BACKBONE, NULL, 0, NULL},
171 {"peer", DEV_CLASS_STATIONARY, NULL, 0, NULL},
172 {"nut", DEV_CLASS_STATIONARY, NULL, 0, NULL},
175 create_peers(peers, 3, prefix);
176 setup_indirect_topology(peers, 3);
177 assert(meshlink_add_invitation_address(peers[0].mesh, "192.168.1.1", NULL));
178 assert(meshlink_add_invitation_address(peers[0].mesh, "192.168.2.1", NULL));
179 invite_peers(peers, 3);
184 void close_relay_peer_nut(peer_config_t *peers) {
185 close_peers(peers, 3);