Browse Source

1

congestion
Evgeny 6 months ago
parent
commit
58eea06f60
  1. 197
      src/route_bgp.c

197
src/route_bgp.c

@ -114,6 +114,8 @@ static void route_bgp_broadcast_withdraw(struct ROUTE_BGP* bgp, uint64_t node_id
// ============================================================================
static void route_bgp_start_link_nat_check(struct ROUTE_BGP* bgp, struct ETCP_LINK* link);
static void route_bgp_handle_nat_info(struct ROUTE_BGP* bgp, struct ETCP_CONN* from_conn, const uint8_t* data, size_t len);
static void route_bgp_handle_nat_check_req(struct ROUTE_BGP* bgp, struct ETCP_CONN* from_conn, const uint8_t* data, size_t len);
static void route_bgp_receive_cbk(struct ETCP_CONN* from_conn, struct ll_entry* entry) {
if (!from_conn || !entry || entry->len < 2) {
@ -158,100 +160,9 @@ static void route_bgp_receive_cbk(struct ETCP_CONN* from_conn, struct ll_entry*
} else if (subcmd == ROUTE_SUBCMD_PING_RESP) {
route_ping_handle_resp(bgp, from_conn, data, entry->len);
} else if (subcmd == ROUTE_SUBCMD_NAT_INFO) {
if (entry->len >= sizeof(struct BGP_NAT_INFO) && bgp && bgp->local_node) {
const struct BGP_NAT_INFO* info = (const struct BGP_NAT_INFO*)data;
uint32_t nat_ip = (info->nat_ip[0] << 24) | (info->nat_ip[1] << 16) |
(info->nat_ip[2] << 8) | info->nat_ip[3];
uint16_t nat_port = ((info->nat_port >> 8) & 0xFF) | ((info->nat_port & 0xFF) << 8);
uint8_t socket_id = info->socket_id;
// Update socket in local_node and ETCP_SOCKET
uint8_t* dynamic = (uint8_t*)&bgp->local_node->node + sizeof(struct NODEINFO);
dynamic += bgp->local_node->node.node_name_len;
struct NODEINFO_IPV4_SOCKET* sockets = (struct NODEINFO_IPV4_SOCKET*)dynamic;
for (int i = 0; i < bgp->local_node->node.local_v4_sockets; i++) {
if (sockets[i].id == socket_id) {
uint8_t old_type = sockets[i].type;
uint32_t old_ip = (sockets[i].addr[0] << 24) | (sockets[i].addr[1] << 16) |
(sockets[i].addr[2] << 8) | sockets[i].addr[3];
uint16_t old_port = sockets[i].port;
memcpy(sockets[i].addr, info->nat_ip, 4);
sockets[i].port = nat_port;
uint8_t verified_type;
if (info->nat_type == NAT_TYPE_OPEN) {
verified_type = NAT_VERIFIED_OPEN;
} else if (info->nat_type == NAT_TYPE_RESTRICTED) {
verified_type = NAT_VERIFIED_RESTRICTED;
} else {
verified_type = NAT_VERIFIED_UNKNOWN;
}
sockets[i].type = verified_type;
// Update ETCP_SOCKET
struct ETCP_SOCKET* es = bgp->instance->etcp_sockets;
while (es) {
if (es->sock_id == socket_id) {
es->nat_type = verified_type;
break;
}
es = es->next;
}
// Check if NAT actually changed - only update nodeinfo if changed
if (old_ip != nat_ip || old_port != nat_port || old_type != verified_type) {
bgp->local_node->dirty = 1;
bgp->local_node->node.ver = (bgp->local_node->node.ver + 1) % 255 + 1;
// Broadcast updated nodeinfo to all peers immediately
if (bgp->senders_list) {
struct ll_entry* se = bgp->senders_list->head;
while (se) {
struct ROUTE_BGP_CONN_ITEM* item = (struct ROUTE_BGP_CONN_ITEM*)se->data;
if (item && item->conn) {
route_bgp_send_nodeinfo(bgp->local_node, item->conn);
}
se = se->next;
}
}
}
break;
}
}
// Save nat_type to all links of this connection
struct ETCP_LINK* l = from_conn->links;
while (l) {
l->nat_type = info->nat_type;
l = l->next;
}
DEBUG_INFO(DEBUG_CATEGORY_BGP, "NAT_INFO from %s: socket_id=%u type=%s ip=%u.%u.%u.%u %s port=%u",
from_conn->log_name, socket_id,
info->nat_type == NAT_TYPE_OPEN ? "OPEN" : "RESTRICTED",
(info->nat_ip[0]), (info->nat_ip[1]),
(info->nat_ip[2]), (info->nat_ip[3]), ip_to_str(&info->nat_ip, AF_INET).str,
(unsigned)nat_port);
}
route_bgp_handle_nat_info(bgp, from_conn, data, entry->len);
} else if (subcmd == ROUTE_SUBCMD_NAT_CHECK_REQ) {
if (entry->len >= sizeof(struct BGP_NAT_CHECK_REQ) && bgp) {
const struct BGP_NAT_CHECK_REQ* req = (const struct BGP_NAT_CHECK_REQ*)data;
uint8_t socket_id = req->socket_id;
// Find link by remote_socket_id in the connection
struct ETCP_LINK* target_link = NULL;
struct ETCP_LINK* l = from_conn->links;
while (l) {
if (l->remote_socket_id == socket_id) {
target_link = l;
break;
}
l = l->next;
}
if (!target_link) {
DEBUG_WARN(DEBUG_CATEGORY_BGP, "NAT_CHECK_REQ from %s: no link with remote_socket_id=%u",
from_conn->log_name, socket_id);
} else if (target_link->nat_check_status == NAT_CHECK_IN_PROGRESS) {
DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "NAT_CHECK_REQ from %s: check already in progress for socket_id=%u",
from_conn->log_name, socket_id);
} else {
DEBUG_INFO(DEBUG_CATEGORY_BGP, "NAT_CHECK_REQ from %s: restarting NAT check for socket_id=%u",
from_conn->log_name, socket_id);
route_bgp_start_link_nat_check(bgp, target_link);
}
}
route_bgp_handle_nat_check_req(bgp, from_conn, data, entry->len);
}
queue_dgram_free(entry);
@ -958,6 +869,106 @@ static void route_bgp_handle_request_table(struct ROUTE_BGP* bgp, struct ETCP_CO
route_bgp_add_to_senders(bgp, conn);
}
static void route_bgp_handle_nat_info(struct ROUTE_BGP* bgp, struct ETCP_CONN* from_conn, const uint8_t* data, size_t len) {
if (!bgp || !from_conn || !data || len < sizeof(struct BGP_NAT_INFO) || !bgp->local_node) return;
const struct BGP_NAT_INFO* info = (const struct BGP_NAT_INFO*)data;
uint32_t nat_ip = (info->nat_ip[0] << 24) | (info->nat_ip[1] << 16) |
(info->nat_ip[2] << 8) | info->nat_ip[3];
uint16_t nat_port = ((info->nat_port >> 8) & 0xFF) | ((info->nat_port & 0xFF) << 8);
uint8_t socket_id = info->socket_id;
uint8_t* dynamic = (uint8_t*)&bgp->local_node->node + sizeof(struct NODEINFO);
dynamic += bgp->local_node->node.node_name_len;
struct NODEINFO_IPV4_SOCKET* sockets = (struct NODEINFO_IPV4_SOCKET*)dynamic;
for (int i = 0; i < bgp->local_node->node.local_v4_sockets; i++) {
if (sockets[i].id == socket_id) {
uint8_t old_type = sockets[i].type;
uint32_t old_ip = (sockets[i].addr[0] << 24) | (sockets[i].addr[1] << 16) |
(sockets[i].addr[2] << 8) | sockets[i].addr[3];
uint16_t old_port = sockets[i].port;
memcpy(sockets[i].addr, info->nat_ip, 4);
sockets[i].port = nat_port;
uint8_t verified_type;
if (info->nat_type == NAT_TYPE_OPEN) {
verified_type = NAT_VERIFIED_OPEN;
} else if (info->nat_type == NAT_TYPE_RESTRICTED) {
verified_type = NAT_VERIFIED_RESTRICTED;
} else {
verified_type = NAT_VERIFIED_UNKNOWN;
}
sockets[i].type = verified_type;
struct ETCP_SOCKET* es = bgp->instance->etcp_sockets;
while (es) {
if (es->sock_id == socket_id) {
es->nat_type = verified_type;
break;
}
es = es->next;
}
if (old_ip != nat_ip || old_port != nat_port || old_type != verified_type) {
bgp->local_node->dirty = 1;
bgp->local_node->node.ver = (bgp->local_node->node.ver + 1) % 255 + 1;
if (bgp->senders_list) {
struct ll_entry* se = bgp->senders_list->head;
while (se) {
struct ROUTE_BGP_CONN_ITEM* item = (struct ROUTE_BGP_CONN_ITEM*)se->data;
if (item && item->conn) {
route_bgp_send_nodeinfo(bgp->local_node, item->conn);
}
se = se->next;
}
}
}
break;
}
}
struct ETCP_LINK* l = from_conn->links;
while (l) {
l->nat_type = info->nat_type;
l = l->next;
}
DEBUG_INFO(DEBUG_CATEGORY_BGP, "NAT_INFO from %s: socket_id=%u type=%s ip=%u.%u.%u.%u %s port=%u",
from_conn->log_name, socket_id,
info->nat_type == NAT_TYPE_OPEN ? "OPEN" : "RESTRICTED",
(info->nat_ip[0]), (info->nat_ip[1]),
(info->nat_ip[2]), (info->nat_ip[3]), ip_to_str(&info->nat_ip, AF_INET).str,
(unsigned)nat_port);
}
static void route_bgp_handle_nat_check_req(struct ROUTE_BGP* bgp, struct ETCP_CONN* from_conn, const uint8_t* data, size_t len) {
if (!bgp || !from_conn || !data || len < sizeof(struct BGP_NAT_CHECK_REQ)) return;
const struct BGP_NAT_CHECK_REQ* req = (const struct BGP_NAT_CHECK_REQ*)data;
uint8_t socket_id = req->socket_id;
struct ETCP_LINK* target_link = NULL;
struct ETCP_LINK* l = from_conn->links;
while (l) {
if (l->remote_socket_id == socket_id) {
target_link = l;
break;
}
l = l->next;
}
if (!target_link) {
DEBUG_WARN(DEBUG_CATEGORY_BGP, "NAT_CHECK_REQ from %s: no link with remote_socket_id=%u",
from_conn->log_name, socket_id);
} else if (target_link->nat_check_status == NAT_CHECK_IN_PROGRESS) {
DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "NAT_CHECK_REQ from %s: check already in progress for socket_id=%u",
from_conn->log_name, socket_id);
} else {
DEBUG_INFO(DEBUG_CATEGORY_BGP, "NAT_CHECK_REQ from %s: restarting NAT check for socket_id=%u",
from_conn->log_name, socket_id);
route_bgp_start_link_nat_check(bgp, target_link);
}
}
void route_bgp_send_nat_info(struct ETCP_CONN* conn, uint8_t socket_id, uint32_t nat_ip, uint16_t nat_port, uint8_t nat_type) {
if (!conn) return;
struct BGP_NAT_INFO* pkt = u_calloc(1, sizeof(struct BGP_NAT_INFO));

Loading…
Cancel
Save