backported supernode selection by MAC address to 3.0 as it also fixes a rarely occuring bug found in general supernode selection

This commit is contained in:
Logan oos Even 2021-11-01 16:40:17 +05:45
parent 8d4b771d87
commit 0177e14026
4 changed files with 50 additions and 9 deletions

4
edge.8
View File

@ -105,6 +105,10 @@ compress outgoing data packets, -z1 = lzo1x, disabled by default
\fB\-\-select-rtt\fR
select supernode by round trip time if several to choose from (federation),
defaults to load-based selection strategy if not provided.
.TP
\fB\-\-select-mac\fR
select supernode by MAC address if several to choose from (federation),
lowest MAC address first.
.SH TAP DEVICE AND OVERLAY NETWORK CONFIGURATION
.TP
\fB\-a \fR[\fImode\fR]<\fIip\fR>[\fI/n\fR]

View File

@ -288,7 +288,7 @@ typedef char n2n_version_t[N2N_VERSION_STRING_SIZE];
#define SN_SELECTION_STRATEGY_LOAD 1
#define SN_SELECTION_STRATEGY_RTT 2
#define SN_SELECTION_STRATEGY_MAC 3 /* REVISIT: not implemented yet */
#define SN_SELECTION_STRATEGY_MAC 3
typedef struct n2n_ip_subnet {

View File

@ -232,6 +232,7 @@ static void help (int level) {
"\n [-r] enable packet forwarding through n2n community"
"\n [-E] accept multicast MAC addresses"
"\n [--select-rtt] select supernode by round trip time"
"\n [--select-mac] select supernode by MAC address"
#ifndef WIN32
"\n [-f] do not fork but run in foreground"
#endif
@ -290,7 +291,8 @@ static void help (int level) {
"-z2 = zstd, "
#endif
"disabled by default\n");
printf("--select-rtt | supernode selection based on round trip time (default:\n"
printf("--select-rtt | supernode selection based on round trip time\n"
"--select-mac | supernode selection based on MAC address (default:\n"
" | by load)\n");
printf ("\n");
@ -737,7 +739,14 @@ static int setOption (int optkey, char *optargument, n2n_tuntap_priv_config_t *e
break;
}
case ']': /* password for management port */ {
case ']': /* mac-address-based supernode selection strategy */ {
// overwrites the default load-based strategy
conf->sn_selection_strategy = SN_SELECTION_STRATEGY_MAC;
break;
}
case '{': /* password for management port */ {
conf->mgmt_password_hash = pearson_hash_64((uint8_t*)optargument, strlen(optargument));
break;
@ -797,7 +806,8 @@ static const struct option long_options[] =
{ "verbose", no_argument, NULL, 'v' },
{ "help", no_argument, NULL, '@' }, /* internal special character '@' to identify long help case */
{ "select-rtt", no_argument, NULL, '[' }, /* '[' rtt selection strategy */
{ "management-password", required_argument, NULL, ']' }, /* ']' management port password */
{ "select-mac", no_argument, NULL, ']' }, /* ']' mac selection strategy */
{ "management-password", required_argument, NULL, '{' }, /* '{' management port password */
{ NULL, 0, NULL, 0 }
};

View File

@ -88,7 +88,17 @@ int sn_selection_criterion_calculate (n2n_edge_t *eee, peer_info_t *peer, SN_SEL
}
case SN_SELECTION_STRATEGY_RTT: {
peer->selection_criterion = (SN_SELECTION_CRITERION_DATA_TYPE)(time_stamp() >> 22) - common_data;
peer->selection_criterion = (SN_SELECTION_CRITERION_DATA_TYPE)((uint32_t)time_stamp() >> 22) - common_data;
break;
}
case SN_SELECTION_STRATEGY_MAC: {
peer->selection_criterion = 0;
memcpy(&peer->selection_criterion, /* leftbound, don't mess with pointer arithmetics */
peer->mac_addr,
N2N_MAC_SIZE);
peer->selection_criterion = be64toh(peer->selection_criterion);
peer->selection_criterion >>= (sizeof(peer->selection_criterion) - N2N_MAC_SIZE) * 8; /* rightbound */
break;
}
@ -120,7 +130,12 @@ int sn_selection_criterion_common_data_default (n2n_edge_t *eee) {
}
case SN_SELECTION_STRATEGY_RTT: {
eee->sn_selection_criterion_common_data = (SN_SELECTION_CRITERION_DATA_TYPE)(time_stamp() >> 22);
eee->sn_selection_criterion_common_data = (SN_SELECTION_CRITERION_DATA_TYPE)((uint32_t)time_stamp() >> 22);
break;
}
case SN_SELECTION_STRATEGY_MAC: {
eee->sn_selection_criterion_common_data = 0;
break;
}
@ -145,8 +160,15 @@ static SN_SELECTION_CRITERION_DATA_TYPE sn_selection_criterion_common_read (n2n_
/* Function that compare two selection_criterion fields and sorts them in ascending order. */
static int sn_selection_criterion_sort (peer_info_t *a, peer_info_t *b) {
int ret = 0;
// comparison function for sorting supernodes in ascending order of their selection_criterion.
return (a->selection_criterion - b->selection_criterion);
if(a->selection_criterion > b->selection_criterion)
ret = 1;
else if(a->selection_criterion < b->selection_criterion)
ret = -2;
return ret;
}
@ -177,7 +199,7 @@ SN_SELECTION_CRITERION_DATA_TYPE sn_selection_criterion_gather_data (n2n_sn_t *s
data += tmp;
}
return htobe32(data);
return htobe64(data);
}
@ -195,7 +217,7 @@ extern char * sn_selection_criterion_str (n2n_edge_t *eee, selection_criterion_s
// keep off the super-big values (used for "bad" or "good" or "undetermined" supernodes,
// easier to sort to the end of the list).
// Alternatively, typecast to (int16_t) and check for greater or equal zero
if(peer->selection_criterion < (UINT32_MAX >> 2)) {
if(peer->selection_criterion < (UINT64_MAX >> 2)) {
switch(eee->conf.sn_selection_strategy) {
@ -209,6 +231,11 @@ extern char * sn_selection_criterion_str (n2n_edge_t *eee, selection_criterion_s
break;
}
case SN_SELECTION_STRATEGY_MAC: {
chars = snprintf(out, SN_SELECTION_CRITERION_BUF_SIZE, "%s", (int64_t)peer->selection_criterion > 0 ? "active" : "");
break;
}
default: {
// this should never happen
traceEvent(TRACE_ERROR, "selection_criterion unknown selection strategy configuration");