mirror of
https://github.com/ntop/n2n.git
synced 2024-09-20 00:51:10 +02:00
increased resilience to supernode failure (#660)
This commit is contained in:
parent
1bcc64ccb3
commit
23a9c871f8
|
@ -426,6 +426,7 @@ struct peer_info {
|
||||||
SN_SELECTION_CRITERION_DATA_TYPE selection_criterion;
|
SN_SELECTION_CRITERION_DATA_TYPE selection_criterion;
|
||||||
uint64_t last_valid_time_stamp;
|
uint64_t last_valid_time_stamp;
|
||||||
char *ip_addr;
|
char *ip_addr;
|
||||||
|
uint8_t local;
|
||||||
|
|
||||||
UT_hash_handle hh; /* makes this structure hashable */
|
UT_hash_handle hh; /* makes this structure hashable */
|
||||||
};
|
};
|
||||||
|
|
|
@ -31,6 +31,7 @@ static void send_register (n2n_edge_t *eee, const n2n_sock_t *remote_peer, const
|
||||||
|
|
||||||
static void check_peer_registration_needed (n2n_edge_t *eee,
|
static void check_peer_registration_needed (n2n_edge_t *eee,
|
||||||
uint8_t from_supernode,
|
uint8_t from_supernode,
|
||||||
|
uint8_t via_multicast,
|
||||||
const n2n_mac_t mac,
|
const n2n_mac_t mac,
|
||||||
const n2n_ip_subnet_t *dev_addr,
|
const n2n_ip_subnet_t *dev_addr,
|
||||||
const n2n_desc_t *dev_desc,
|
const n2n_desc_t *dev_desc,
|
||||||
|
@ -42,6 +43,7 @@ static void edge_cleanup_routes (n2n_edge_t *eee);
|
||||||
|
|
||||||
static void check_known_peer_sock_change (n2n_edge_t *eee,
|
static void check_known_peer_sock_change (n2n_edge_t *eee,
|
||||||
uint8_t from_supernode,
|
uint8_t from_supernode,
|
||||||
|
uint8_t via_multicast,
|
||||||
const n2n_mac_t mac,
|
const n2n_mac_t mac,
|
||||||
const n2n_ip_subnet_t *dev_addr,
|
const n2n_ip_subnet_t *dev_addr,
|
||||||
const n2n_desc_t *dev_desc,
|
const n2n_desc_t *dev_desc,
|
||||||
|
@ -531,6 +533,7 @@ static struct peer_info* find_peer_by_sock (const n2n_sock_t *sock, struct peer_
|
||||||
*/
|
*/
|
||||||
static void register_with_new_peer (n2n_edge_t *eee,
|
static void register_with_new_peer (n2n_edge_t *eee,
|
||||||
uint8_t from_supernode,
|
uint8_t from_supernode,
|
||||||
|
uint8_t via_multicast,
|
||||||
const n2n_mac_t mac,
|
const n2n_mac_t mac,
|
||||||
const n2n_ip_subnet_t *dev_addr,
|
const n2n_ip_subnet_t *dev_addr,
|
||||||
const n2n_desc_t *dev_desc,
|
const n2n_desc_t *dev_desc,
|
||||||
|
@ -551,6 +554,8 @@ static void register_with_new_peer (n2n_edge_t *eee,
|
||||||
scan->sock = *peer;
|
scan->sock = *peer;
|
||||||
scan->timeout = eee->conf.register_interval; /* TODO: should correspond to the peer supernode registration timeout */
|
scan->timeout = eee->conf.register_interval; /* TODO: should correspond to the peer supernode registration timeout */
|
||||||
scan->last_valid_time_stamp = initial_time_stamp();
|
scan->last_valid_time_stamp = initial_time_stamp();
|
||||||
|
if(via_multicast)
|
||||||
|
scan->local = 1;
|
||||||
|
|
||||||
HASH_ADD_PEER(eee->pending_peers, scan);
|
HASH_ADD_PEER(eee->pending_peers, scan);
|
||||||
|
|
||||||
|
@ -607,7 +612,6 @@ static void register_with_new_peer (n2n_edge_t *eee,
|
||||||
memcpy(&(scan->dev_addr), dev_addr, sizeof(n2n_ip_subnet_t));
|
memcpy(&(scan->dev_addr), dev_addr, sizeof(n2n_ip_subnet_t));
|
||||||
}
|
}
|
||||||
if(dev_desc) memcpy(scan->dev_desc, dev_desc, N2N_DESC_SIZE);
|
if(dev_desc) memcpy(scan->dev_desc, dev_desc, N2N_DESC_SIZE);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -616,6 +620,7 @@ static void register_with_new_peer (n2n_edge_t *eee,
|
||||||
/** Update the last_seen time for this peer, or get registered. */
|
/** Update the last_seen time for this peer, or get registered. */
|
||||||
static void check_peer_registration_needed (n2n_edge_t *eee,
|
static void check_peer_registration_needed (n2n_edge_t *eee,
|
||||||
uint8_t from_supernode,
|
uint8_t from_supernode,
|
||||||
|
uint8_t via_multicast,
|
||||||
const n2n_mac_t mac,
|
const n2n_mac_t mac,
|
||||||
const n2n_ip_subnet_t *dev_addr,
|
const n2n_ip_subnet_t *dev_addr,
|
||||||
const n2n_desc_t *dev_desc,
|
const n2n_desc_t *dev_desc,
|
||||||
|
@ -638,7 +643,7 @@ static void check_peer_registration_needed (n2n_edge_t *eee,
|
||||||
|
|
||||||
if(scan == NULL) {
|
if(scan == NULL) {
|
||||||
/* Not in known_peers - start the REGISTER process. */
|
/* Not in known_peers - start the REGISTER process. */
|
||||||
register_with_new_peer(eee, from_supernode, mac, dev_addr, dev_desc, peer);
|
register_with_new_peer(eee, from_supernode, via_multicast, mac, dev_addr, dev_desc, peer);
|
||||||
} else {
|
} else {
|
||||||
/* Already in known_peers. */
|
/* Already in known_peers. */
|
||||||
time_t now = time(NULL);
|
time_t now = time(NULL);
|
||||||
|
@ -646,9 +651,12 @@ static void check_peer_registration_needed (n2n_edge_t *eee,
|
||||||
if(!from_supernode)
|
if(!from_supernode)
|
||||||
scan->last_p2p = now;
|
scan->last_p2p = now;
|
||||||
|
|
||||||
|
if(via_multicast)
|
||||||
|
scan->local = 1;
|
||||||
|
|
||||||
if((now - scan->last_seen) > 0 /* >= 1 sec */) {
|
if((now - scan->last_seen) > 0 /* >= 1 sec */) {
|
||||||
/* Don't register too often */
|
/* Don't register too often */
|
||||||
check_known_peer_sock_change(eee, from_supernode, mac, dev_addr, dev_desc, peer, now);
|
check_known_peer_sock_change(eee, from_supernode, via_multicast, mac, dev_addr, dev_desc, peer, now);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -761,6 +769,7 @@ int is_empty_ip_address (const n2n_sock_t * sock) {
|
||||||
*/
|
*/
|
||||||
static void check_known_peer_sock_change (n2n_edge_t *eee,
|
static void check_known_peer_sock_change (n2n_edge_t *eee,
|
||||||
uint8_t from_supernode,
|
uint8_t from_supernode,
|
||||||
|
uint8_t via_multicast,
|
||||||
const n2n_mac_t mac,
|
const n2n_mac_t mac,
|
||||||
const n2n_ip_subnet_t *dev_addr,
|
const n2n_ip_subnet_t *dev_addr,
|
||||||
const n2n_desc_t *dev_desc,
|
const n2n_desc_t *dev_desc,
|
||||||
|
@ -796,7 +805,7 @@ static void check_known_peer_sock_change (n2n_edge_t *eee,
|
||||||
HASH_DEL(eee->known_peers, scan);
|
HASH_DEL(eee->known_peers, scan);
|
||||||
free(scan);
|
free(scan);
|
||||||
|
|
||||||
register_with_new_peer(eee, from_supernode, mac, dev_addr, dev_desc, peer);
|
register_with_new_peer(eee, from_supernode, via_multicast, mac, dev_addr, dev_desc, peer);
|
||||||
} else {
|
} else {
|
||||||
/* Don't worry about what the supernode reports, it could be seeing a different socket. */
|
/* Don't worry about what the supernode reports, it could be seeing a different socket. */
|
||||||
}
|
}
|
||||||
|
@ -1191,7 +1200,6 @@ static void send_register (n2n_edge_t * eee,
|
||||||
reg.dev_addr.net_bitlen = mask2bitlen(ntohl(eee->device.device_mask));
|
reg.dev_addr.net_bitlen = mask2bitlen(ntohl(eee->device.device_mask));
|
||||||
memcpy(reg.dev_desc, eee->conf.dev_desc, N2N_DESC_SIZE);
|
memcpy(reg.dev_desc, eee->conf.dev_desc, N2N_DESC_SIZE);
|
||||||
|
|
||||||
|
|
||||||
idx = 0;
|
idx = 0;
|
||||||
encode_REGISTER(pktbuf, &idx, &cmn, ®);
|
encode_REGISTER(pktbuf, &idx, &cmn, ®);
|
||||||
|
|
||||||
|
@ -1304,6 +1312,9 @@ static void send_grat_arps (n2n_edge_t * eee) {
|
||||||
*/
|
*/
|
||||||
void update_supernode_reg (n2n_edge_t * eee, time_t now) {
|
void update_supernode_reg (n2n_edge_t * eee, time_t now) {
|
||||||
|
|
||||||
|
struct peer_info *peer, *tmp_peer;
|
||||||
|
int cnt = 0;
|
||||||
|
|
||||||
if(eee->sn_wait && (now > (eee->last_register_req + (eee->conf.register_interval/10)))) {
|
if(eee->sn_wait && (now > (eee->last_register_req + (eee->conf.register_interval/10)))) {
|
||||||
/* fall through */
|
/* fall through */
|
||||||
traceEvent(TRACE_DEBUG, "update_supernode_reg: doing fast retry.");
|
traceEvent(TRACE_DEBUG, "update_supernode_reg: doing fast retry.");
|
||||||
|
@ -1327,13 +1338,22 @@ void update_supernode_reg (n2n_edge_t * eee, time_t now) {
|
||||||
// privileges. as we are not able to check for sufficent privileges here, we only do it
|
// privileges. as we are not able to check for sufficent privileges here, we only do it
|
||||||
// if port is sufficently high or unset. uncovered: privileged port and sufficent privileges
|
// if port is sufficently high or unset. uncovered: privileged port and sufficent privileges
|
||||||
if((eee->conf.local_port == 0) || (eee->conf.local_port > 1024)) {
|
if((eee->conf.local_port == 0) || (eee->conf.local_port > 1024)) {
|
||||||
// do not explicitly disconnect every time as the condition descibed is rare
|
// do not explicitly disconnect every time as the condition described is rare, so ...
|
||||||
|
// ... check that there are no external peers (indicating a working socket) ...
|
||||||
|
HASH_ITER(hh, eee->known_peers, peer, tmp_peer)
|
||||||
|
if(!peer->local) {
|
||||||
|
cnt++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(!cnt) {
|
||||||
|
// ... and then count the connection retries
|
||||||
(eee->close_socket_counter)++;
|
(eee->close_socket_counter)++;
|
||||||
if(eee->close_socket_counter >= N2N_CLOSE_SOCKET_COUNTER_MAX) {
|
if(eee->close_socket_counter >= N2N_CLOSE_SOCKET_COUNTER_MAX) {
|
||||||
eee->close_socket_counter = 0;
|
eee->close_socket_counter = 0;
|
||||||
supernode_disconnect(eee);
|
supernode_disconnect(eee);
|
||||||
traceEvent(TRACE_DEBUG, "update_supernode_reg disconnected supernode");
|
traceEvent(TRACE_DEBUG, "update_supernode_reg disconnected supernode");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
supernode_connect(eee);
|
supernode_connect(eee);
|
||||||
traceEvent(TRACE_DEBUG, "update_supernode_reg reconnected to supernode");
|
traceEvent(TRACE_DEBUG, "update_supernode_reg reconnected to supernode");
|
||||||
|
@ -1349,8 +1369,16 @@ void update_supernode_reg (n2n_edge_t * eee, time_t now) {
|
||||||
|
|
||||||
send_register_super(eee);
|
send_register_super(eee);
|
||||||
}
|
}
|
||||||
|
|
||||||
register_with_local_peers(eee);
|
register_with_local_peers(eee);
|
||||||
|
|
||||||
|
// if supernode repeatedly not responding (already waiting), safeguard the
|
||||||
|
// current known connections to peers by re-registering
|
||||||
|
if(eee->sn_wait)
|
||||||
|
HASH_ITER(hh, eee->known_peers, peer, tmp_peer)
|
||||||
|
if((now - peer->last_seen) > REGISTER_SUPER_INTERVAL_DFL)
|
||||||
|
send_register(eee, &(peer->sock), peer->mac_addr);
|
||||||
|
|
||||||
eee->sn_wait = 1;
|
eee->sn_wait = 1;
|
||||||
|
|
||||||
eee->last_register_req = now;
|
eee->last_register_req = now;
|
||||||
|
@ -1877,24 +1905,33 @@ static int send_packet (n2n_edge_t * eee,
|
||||||
n2n_sock_str_t sockbuf;
|
n2n_sock_str_t sockbuf;
|
||||||
n2n_sock_t destination;
|
n2n_sock_t destination;
|
||||||
macstr_t mac_buf;
|
macstr_t mac_buf;
|
||||||
|
struct peer_info *peer, *tmp_peer;
|
||||||
|
|
||||||
/* hexdump(pktbuf, pktlen); */
|
/* hexdump(pktbuf, pktlen); */
|
||||||
|
|
||||||
is_p2p = find_peer_destination(eee, dstMac, &destination);
|
is_p2p = find_peer_destination(eee, dstMac, &destination);
|
||||||
|
|
||||||
if(is_p2p)
|
|
||||||
++(eee->stats.tx_p2p);
|
|
||||||
else {
|
|
||||||
++(eee->stats.tx_sup);
|
|
||||||
|
|
||||||
if(!memcmp(dstMac, broadcast_mac, N2N_MAC_SIZE))
|
|
||||||
++(eee->stats.tx_sup_broadcast);
|
|
||||||
}
|
|
||||||
|
|
||||||
traceEvent(TRACE_INFO, "Tx PACKET to %s (dest=%s) [%u B]",
|
traceEvent(TRACE_INFO, "Tx PACKET to %s (dest=%s) [%u B]",
|
||||||
sock_to_cstr(sockbuf, &destination),
|
sock_to_cstr(sockbuf, &destination),
|
||||||
macaddr_str(mac_buf, dstMac), pktlen);
|
macaddr_str(mac_buf, dstMac), pktlen);
|
||||||
|
|
||||||
|
if(is_p2p)
|
||||||
|
++(eee->stats.tx_p2p);
|
||||||
|
else
|
||||||
|
++(eee->stats.tx_sup);
|
||||||
|
|
||||||
|
if(!memcmp(dstMac, broadcast_mac, N2N_MAC_SIZE)) {
|
||||||
|
++(eee->stats.tx_sup_broadcast);
|
||||||
|
|
||||||
|
// if no supernode around, foward the broadcast to all known peers
|
||||||
|
if(eee->sn_wait) {
|
||||||
|
HASH_ITER(hh, eee->known_peers, peer, tmp_peer)
|
||||||
|
/* s = */ sendto_sock(eee, pktbuf, pktlen, &peer->sock);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
// fall through otherwise
|
||||||
|
}
|
||||||
|
|
||||||
/* s = */ sendto_sock(eee, pktbuf, pktlen, &destination);
|
/* s = */ sendto_sock(eee, pktbuf, pktlen, &destination);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -2227,7 +2264,8 @@ void process_udp (n2n_edge_t *eee, const struct sockaddr_in *sender_sock, const
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update the sender in peer table entry */
|
/* Update the sender in peer table entry */
|
||||||
check_peer_registration_needed(eee, from_supernode, pkt.srcMac, NULL, NULL, orig_sender);
|
check_peer_registration_needed(eee, from_supernode, via_multicast,
|
||||||
|
pkt.srcMac, NULL, NULL, orig_sender);
|
||||||
|
|
||||||
handle_PACKET(eee, from_supernode, &pkt, orig_sender, udp_buf + idx, udp_size - idx);
|
handle_PACKET(eee, from_supernode, &pkt, orig_sender, udp_buf + idx, udp_size - idx);
|
||||||
break;
|
break;
|
||||||
|
@ -2280,7 +2318,8 @@ void process_udp (n2n_edge_t *eee, const struct sockaddr_in *sender_sock, const
|
||||||
sock_to_cstr(sockbuf1, &sender), sock_to_cstr(sockbuf2, orig_sender));
|
sock_to_cstr(sockbuf1, &sender), sock_to_cstr(sockbuf2, orig_sender));
|
||||||
}
|
}
|
||||||
|
|
||||||
check_peer_registration_needed(eee, from_supernode, reg.srcMac, ®.dev_addr, (const n2n_desc_t*)®.dev_desc, orig_sender);
|
check_peer_registration_needed(eee, from_supernode, via_multicast,
|
||||||
|
reg.srcMac, ®.dev_addr, (const n2n_desc_t*)®.dev_desc, orig_sender);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2742,6 +2781,9 @@ int run_edge_loop (n2n_edge_t *eee, int *keep_running) {
|
||||||
// finished processing select data
|
// finished processing select data
|
||||||
update_supernode_reg(eee, now);
|
update_supernode_reg(eee, now);
|
||||||
|
|
||||||
|
numPurged = 0;
|
||||||
|
// keep, i.e. do not purge, the known peers while no supernode supernode connection
|
||||||
|
if(!eee->sn_wait)
|
||||||
numPurged = purge_expired_nodes(&eee->known_peers,
|
numPurged = purge_expired_nodes(&eee->known_peers,
|
||||||
eee->sock, NULL,
|
eee->sock, NULL,
|
||||||
&last_purge_known,
|
&last_purge_known,
|
||||||
|
|
Loading…
Reference in New Issue
Block a user