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:
parent
366faaea76
commit
b2942b3c53
5 changed files with 86 additions and 22 deletions
57
cluster.c
57
cluster.c
|
|
@ -38,7 +38,8 @@
|
|||
*/
|
||||
|
||||
// Module variables.
|
||||
extern int cluster_sockfd; // The filedescriptor for the cluster communications port.
|
||||
extern int cluster_sockfd; // The filedescriptor for the cluster communications multicast.
|
||||
extern int cluster_sockfd2; // The filedescriptor for the cluster communications p2p.
|
||||
|
||||
in_addr_t my_address = 0; // The network address of my ethernet port.
|
||||
static int walk_session_number = 0; // The next session to send when doing the slow table walk.
|
||||
|
|
@ -103,9 +104,10 @@ int cluster_init()
|
|||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(config->cluster_port);
|
||||
addr.sin_addr.s_addr = INADDR_ANY;
|
||||
addr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
opt = 1;
|
||||
setsockopt(cluster_sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
|
||||
setsockopt(cluster_sockfd, SOL_IP, IP_PKTINFO, &opt, sizeof(opt)); // recvfromto
|
||||
|
||||
opt = fcntl(cluster_sockfd, F_GETFL, 0);
|
||||
fcntl(cluster_sockfd, F_SETFL, opt | O_NONBLOCK);
|
||||
|
|
@ -117,21 +119,33 @@ int cluster_init()
|
|||
}
|
||||
|
||||
strcpy(ifr.ifr_name, config->cluster_interface);
|
||||
if (ioctl(cluster_sockfd, SIOCGIFADDR, &ifr) < 0)
|
||||
if (ioctl(cluster_sockfd, SIOCGIFADDR, &ifr) == 0)
|
||||
{
|
||||
LOG(0, 0, 0, "Failed to get interface address for (%s): %s\n", config->cluster_interface, strerror(errno));
|
||||
return -1;
|
||||
memcpy(&interface_addr, &ifr.ifr_addr, sizeof(interface_addr));
|
||||
my_address = interface_addr.sin_addr.s_addr;
|
||||
}
|
||||
else
|
||||
{
|
||||
struct in_addr myaddr;
|
||||
if (inet_aton(config->cluster_interface, &myaddr) != 0)
|
||||
{
|
||||
memset(&interface_addr, 0, sizeof(interface_addr));
|
||||
interface_addr.sin_family = AF_INET;
|
||||
interface_addr.sin_addr = myaddr;
|
||||
my_address = myaddr.s_addr;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(0, 0, 0, "Failed to get interface address for (%s): %s\n", config->cluster_interface, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(&interface_addr, &ifr.ifr_addr, sizeof(interface_addr));
|
||||
my_address = interface_addr.sin_addr.s_addr;
|
||||
|
||||
// Join multicast group.
|
||||
mreq.imr_multiaddr.s_addr = config->cluster_address;
|
||||
mreq.imr_interface = interface_addr.sin_addr;
|
||||
|
||||
|
||||
opt = 0; // Turn off multicast loopback.
|
||||
opt = 1; // Turn on multicast loopback.
|
||||
setsockopt(cluster_sockfd, IPPROTO_IP, IP_MULTICAST_LOOP, &opt, sizeof(opt));
|
||||
|
||||
opt = 7; // Highest priority to avoid getting hit by high-traffic
|
||||
|
|
@ -161,6 +175,21 @@ int cluster_init()
|
|||
config->cluster_last_hb = TIME;
|
||||
config->cluster_seq_number = -1;
|
||||
|
||||
cluster_sockfd2 = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
|
||||
addr.sin_addr.s_addr = my_address;
|
||||
opt = 1;
|
||||
setsockopt(cluster_sockfd2, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
|
||||
|
||||
if (bind(cluster_sockfd2, (void *) &addr, sizeof(addr)) < 0)
|
||||
{
|
||||
LOG(0, 0, 0, "Failed to bind cluster socket2: %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
opt = fcntl(cluster_sockfd2, F_GETFL, 0);
|
||||
fcntl(cluster_sockfd2, F_SETFL, opt | O_NONBLOCK);
|
||||
|
||||
return cluster_sockfd;
|
||||
}
|
||||
|
||||
|
|
@ -173,6 +202,7 @@ int cluster_init()
|
|||
static int cluster_send_data(void *data, int datalen)
|
||||
{
|
||||
struct sockaddr_in addr = {0};
|
||||
struct in_addr myaddr = { .s_addr = my_address };
|
||||
|
||||
if (!cluster_sockfd) return -1;
|
||||
if (!config->cluster_address) return 0;
|
||||
|
|
@ -183,7 +213,7 @@ static int cluster_send_data(void *data, int datalen)
|
|||
|
||||
LOG(5, 0, 0, "Cluster send data: %d bytes\n", datalen);
|
||||
|
||||
if (sendto(cluster_sockfd, data, datalen, MSG_NOSIGNAL, (void *) &addr, sizeof(addr)) < 0)
|
||||
if (sendtofrom(cluster_sockfd, data, datalen, MSG_NOSIGNAL, (void *) &addr, sizeof(addr), &myaddr) < 0)
|
||||
{
|
||||
LOG(0, 0, 0, "sendto: %s\n", strerror(errno));
|
||||
return -1;
|
||||
|
|
@ -254,8 +284,7 @@ static int peer_send_data(in_addr_t peer, uint8_t *data, int size)
|
|||
{
|
||||
struct sockaddr_in addr = {0};
|
||||
|
||||
if (!cluster_sockfd) return -1;
|
||||
if (!config->cluster_address) return 0;
|
||||
if (!cluster_sockfd2) return -1;
|
||||
|
||||
if (!peer) // Odd??
|
||||
return -1;
|
||||
|
|
@ -266,7 +295,7 @@ static int peer_send_data(in_addr_t peer, uint8_t *data, int size)
|
|||
|
||||
LOG_HEX(5, "Peer send", data, size);
|
||||
|
||||
if (sendto(cluster_sockfd, data, size, MSG_NOSIGNAL, (void *) &addr, sizeof(addr)) < 0)
|
||||
if (sendto(cluster_sockfd2, data, size, MSG_NOSIGNAL, (void *) &addr, sizeof(addr)) < 0)
|
||||
{
|
||||
LOG(0, 0, 0, "sendto: %s\n", strerror(errno));
|
||||
return -1;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue