cluster: Support running multiple instances on the same host

With IP_MULTICAST_LOOP they can see each other. We "just" have to make sure
they use different IP addresses and route metrics to distinguish from each
other.
This commit is contained in:
Samuel Thibault 2025-03-17 20:51:06 +01:00
parent 366faaea76
commit b2942b3c53
5 changed files with 86 additions and 22 deletions

View file

@ -92,7 +92,8 @@ int daefd = -1; // Socket listening for DAE connections.
int snoopfd = -1; // UDP file handle for sending out intercept data
int *radfds = NULL; // RADIUS requests file handles
int rand_fd = -1; // Random data source
int cluster_sockfd = -1; // Intra-cluster communications socket.
int cluster_sockfd = -1; // Intra-cluster multicast communications socket.
int cluster_sockfd2 = -1; // Intra-cluster p2p communications socket.
int epollfd = -1; // event polling
time_t basetime = 0; // base clock
char hostname[MAXHOSTNAME] = ""; // us.
@ -2386,6 +2387,9 @@ static void initdae(void)
addr.sin_family = AF_INET;
addr.sin_port = htons(config->radius_dae_port);
daefd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
#ifdef SO_REUSEPORT
setsockopt(daefd, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on));
#endif
setsockopt(daefd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
setsockopt(daefd, SOL_IP, IP_PKTINFO, &on, sizeof(on)); // recvfromto
if (bind(daefd, (struct sockaddr *) &addr, sizeof(addr)) < 0)
@ -2407,6 +2411,9 @@ static int initudp(int * pudpfd, in_addr_t ip_bind, in_addr_t ip_dest, uint16_t
addr.sin_port = htons(L2TPPORT);
addr.sin_addr.s_addr = ip_bind;
(*pudpfd) = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
#ifdef SO_REUSEPORT
setsockopt((*pudpfd), SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on));
#endif
setsockopt((*pudpfd), SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
{
int flags = fcntl((*pudpfd), F_GETFL, 0);
@ -5845,8 +5852,8 @@ static int still_busy(void)
return 0;
}
// the base set of fds polled: cli, cluster, tun, udp (MAX_UDPFD), control, dae, netlink, udplac, pppoedisc, pppoesess, dhcpv6, icmpv6
#define BASE_FDS (11 + MAX_UDPFD)
// the base set of fds polled: cli, cluster, cluster2, tun, udp (MAX_UDPFD), control, dae, netlink, udplac, pppoedisc, pppoesess, dhcpv6, icmpv6
#define BASE_FDS (12 + MAX_UDPFD)
// additional polled fds
#ifdef BGP
@ -5883,8 +5890,8 @@ static void mainloop(void)
exit(1);
}
LOG(4, 0, 0, "Beginning of main loop. clifd=%d, cluster_sockfd=%d, tunfd=%d, udpfd=%d, controlfd=%d, daefd=%d, rtnlfd=%d , udplacfd=%d, pppoefd=%d, pppoesessfd=%d\n",
clifd, cluster_sockfd, tunfd, udpfd[0], controlfd, daefd, rtnlfd, udplacfd, pppoediscfd, pppoesessfd);
LOG(4, 0, 0, "Beginning of main loop. clifd=%d, cluster_sockfd=%d, cluster_sockfd=%d, tunfd=%d, udpfd=%d, controlfd=%d, daefd=%d, rtnlfd=%d , udplacfd=%d, pppoefd=%d, pppoesessfd=%d\n",
clifd, cluster_sockfd, cluster_sockfd2, tunfd, udpfd[0], controlfd, daefd, rtnlfd, udplacfd, pppoediscfd, pppoesessfd);
/* setup our fds to poll for input */
{
@ -5905,6 +5912,10 @@ static void mainloop(void)
e.data.ptr = &d[i++];
epoll_ctl(epollfd, EPOLL_CTL_ADD, cluster_sockfd, &e);
d[i].type = FD_TYPE_CLUSTER2;
e.data.ptr = &d[i++];
epoll_ctl(epollfd, EPOLL_CTL_ADD, cluster_sockfd2, &e);
d[i].type = FD_TYPE_TUN;
e.data.ptr = &d[i++];
epoll_ctl(epollfd, EPOLL_CTL_ADD, tunfd, &e);
@ -6009,7 +6020,7 @@ static void mainloop(void)
int pppoesess_ready = 0;
int pppoesess_pkts = 0;
int tun_ready = 0;
int cluster_ready = 0;
int cluster_ready = 0, cluster_ready2 = 0;
int udp_pkts[MAX_UDPFD + 1] = INIT_TABUDPVAR;
int tun_pkts = 0;
int cluster_pkts = 0;
@ -6043,6 +6054,7 @@ static void mainloop(void)
// these are handled below, with multiple interleaved reads
case FD_TYPE_CLUSTER: cluster_ready++; break;
case FD_TYPE_CLUSTER2: cluster_ready2++; break;
case FD_TYPE_TUN: tun_ready++; break;
case FD_TYPE_UDP: udp_ready[d->index]++; break;
case FD_TYPE_PPPOESESS: pppoesess_ready++; break;
@ -6283,6 +6295,22 @@ static void mainloop(void)
n--;
}
}
// cluster2
if (cluster_ready2)
{
alen = sizeof(addr);
if ((s = recvfrom(cluster_sockfd2, p, size_bufp, MSG_WAITALL, (void *) &addr, &alen)) > 0)
{
processcluster(p, s, addr.sin_addr.s_addr);
cluster_pkts++;
}
else
{
cluster_ready2 = 0;
n--;
}
}
}
if (udp_pkts[0] > 1 || tun_pkts > 1 || cluster_pkts > 1)