Commit f96bfcdd authored by Marco Mariani's avatar Marco Mariani

prototype for neighbours cost updates (on unix socket stream)

parent f4c88749
Pipeline #298 skipped
......@@ -9,10 +9,10 @@ CFLAGS = $(CDEBUGFLAGS) $(DEFINES) $(EXTRA_DEFINES)
LDLIBS = -lrt
SRCS = babeld.c net.c kernel.c util.c interface.c source.c neighbour.c \
route.c xroute.c message.c resend.c configuration.c local.c
route.c xroute.c message.c resend.c configuration.c local.c re6st.c
OBJS = babeld.o net.o kernel.o util.o interface.o source.o neighbour.o \
route.o xroute.o message.o resend.o configuration.o local.o
route.o xroute.o message.o resend.o configuration.o local.o re6st.o
babeld: $(OBJS)
$(CC) $(CFLAGS) $(LDFLAGS) -o babeld $(OBJS) $(LDLIBS)
......
......@@ -52,6 +52,7 @@ THE SOFTWARE.
#include "resend.h"
#include "configuration.h"
#include "local.h"
#include "re6st.h"
struct timeval now;
......@@ -81,6 +82,7 @@ int protocol_port;
unsigned char protocol_group[16];
int protocol_socket = -1;
int kernel_socket = -1;
int re6st_socket = -1;
static int kernel_routes_changed = 0;
static int kernel_link_changed = 0;
static int kernel_addr_changed = 0;
......@@ -92,7 +94,7 @@ static volatile sig_atomic_t exiting = 0, dumping = 0, reopening = 0;
static int accept_local_connections(fd_set *readfds);
static int kernel_routes_callback(int changed, void *closure);
static void init_signals(void);
static void dump_tables(FILE *out);
void dump_tables(FILE *out);
static int reopen_logfile(void);
int
......@@ -366,6 +368,13 @@ main(int argc, char **argv)
goto fail_pid;
}
rc = re6st_setup_socket(1);
if(rc < 0) {
fprintf(stderr, "re6st_setup_socket failed.\n");
re6st_setup_socket(0);
goto fail_pid;
}
rc = finalise_config();
if(rc < 0) {
fprintf(stderr, "Couldn't finalise configuration.\n");
......@@ -624,6 +633,8 @@ main(int argc, char **argv)
}
}
re6st_accept_connection(re6st_socket);
#ifndef NO_LOCAL_INTERFACE
accept_local_connections(&readfds);
......@@ -1045,7 +1056,7 @@ dump_xroute_callback(struct xroute *xroute, void *closure)
xroute->metric);
}
static void
void
dump_tables(FILE *out)
{
struct neighbour *neigh;
......
......@@ -80,6 +80,8 @@ THE SOFTWARE.
#endif
#endif
#include <stdio.h>
extern struct timeval now;
extern int debug;
extern time_t reboot_time;
......@@ -99,8 +101,11 @@ extern int protocol_port, local_server_port;
extern unsigned char protocol_group[16];
extern int protocol_socket;
extern int kernel_socket;
extern int re6st_socket;
extern int max_request_hopcount;
void schedule_neighbours_check(int msecs, int override);
void schedule_interfaces_check(int msecs, int override);
int resize_receive_buffer(int size);
void dump_tables(FILE *out);
......@@ -36,6 +36,7 @@ THE SOFTWARE.
#include "message.h"
#include "resend.h"
#include "local.h"
#include "re6st.h"
struct neighbour *neighs = NULL;
......@@ -51,6 +52,40 @@ find_neighbour_nocreate(const unsigned char *address, struct interface *ifp)
return NULL;
}
int
dump_neighbours(int socket)
{
FILE *fp = tmpfile();
int ret;
struct neighbour *current;
fprintf(fp, "Head Neighbour: %p\n", neighs);
FOR_ALL_NEIGHBOURS(current) {
fprintf(fp, "Next Neighbour: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x, interface index: %d\n",
current->address[0],
current->address[1],
current->address[2],
current->address[3],
current->address[4],
current->address[5],
current->address[6],
current->address[7],
current->address[8],
current->address[9],
current->address[10],
current->address[11],
current->address[12],
current->address[13],
current->address[14],
current->address[15],
current->ifp->ifindex);
}
ret = re6st_send_file(fp, socket);
fclose(fp);
return ret;
}
void
flush_neighbour(struct neighbour *neigh)
{
......@@ -103,6 +138,7 @@ find_neighbour(const unsigned char *address, struct interface *ifp)
neigh->rtt = 0;
neigh->rtt_time = zero;
neigh->ifp = ifp;
neigh->cost_multiplier = 1;
neigh->next = neighs;
neighs = neigh;
local_notify_neighbour(neigh, LOCAL_ADD);
......@@ -357,6 +393,11 @@ neighbour_cost(struct neighbour *neigh)
}
cost += neighbour_rttcost(neigh);
if (neigh->cost_multiplier != 1) {
debugf("Old cost: %i\n", cost);
cost *= neigh->cost_multiplier;
debugf("New cost: %i\n", cost);
}
return MIN(cost, INFINITY);
}
......
......@@ -39,6 +39,7 @@ struct neighbour {
unsigned int rtt;
struct timeval rtt_time;
struct interface *ifp;
unsigned short cost_multiplier;
};
extern struct neighbour *neighs;
......@@ -57,3 +58,5 @@ unsigned neighbour_rxcost(struct neighbour *neigh);
unsigned neighbour_rttcost(struct neighbour *neigh);
unsigned neighbour_cost(struct neighbour *neigh);
int valid_rtt(struct neighbour *neigh);
int dump_neighbours(int socket);
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
#include <strings.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/sysctl.h>
#include <sys/socket.h>
#include <net/if.h>
#include <linux/un.h>
#include <stdint.h>
#include "babeld.h"
#include "interface.h"
#include "neighbour.h"
#include "util.h"
#include "re6st.h"
/*
* Data received from the UPDATECOST message
*/
struct re6st_cost_modifier {
unsigned char ipv6[16];
uint32_t n_interface_index; // network order
uint16_t n_cost_multiplier; // network order
uint16_t padding; // explicit alignment
};
static void
re6st_set_nonblock(int socket)
{
/* Set socket to non-blocking */
int flags = 0;
if ((flags = fcntl(socket, F_GETFL, 0)) < 0)
{
perror("fcntl");
exit(1);
}
if (fcntl(socket, F_SETFL, flags | O_NONBLOCK) < 0)
{
perror("fcntl");
exit(1);
}
}
static void
re6st_set_block(int socket)
{
/* Set socket to blocking */
int flags = 0;
if ((flags = fcntl(re6st_socket, F_GETFL, 0)) < 0)
{
perror("fcntl");
exit(1);
}
if (fcntl(re6st_socket, F_SETFL, flags & ~O_NONBLOCK) < 0)
{
perror("fcntl");
exit(1);
}
}
int
re6st_setup_socket(int setup)
{
int re6st_len;
const char *re6st_file = "/var/lib/babel-re6st.sock";
struct sockaddr_un re6st_local_addr;
if(setup) {
debugf("setting up RE6ST socket\n");
if(re6st_socket < 0) {
re6st_socket = socket(AF_UNIX, SOCK_STREAM, 0);
if(re6st_socket < 0) {
perror("re6st_socket error");
return -1;
}
}
memset(&re6st_local_addr, 0, sizeof(struct sockaddr_un));
re6st_local_addr.sun_family = AF_UNIX;
strncpy(re6st_local_addr.sun_path, re6st_file, UNIX_PATH_MAX);
unlink(re6st_local_addr.sun_path);
re6st_len = strlen(re6st_local_addr.sun_path) + sizeof(re6st_local_addr.sun_family);
bind(re6st_socket, (struct sockaddr *)&re6st_local_addr, re6st_len);
if (listen(re6st_socket, 5) == -1) {
perror("re6st_socket listen failed");
exit(1);
}
return 1;
} else {
close(re6st_socket);
re6st_socket = -1;
return 1;
}
}
int
re6st_send_file(FILE *fp, int socket)
{
fseek(fp, 0L, SEEK_END);
uint32_t content_size = ftell(fp);
char *content = malloc(content_size + 1);
rewind(fp);
if (!fread(content, 1, content_size, fp)) {
if (ferror(fp)) {
perror("Error reading from temp file");
free(content);
return 0;
}
};
re6st_set_block(socket);
uint32_t content_size_sent = htonl(content_size);
if (send(socket, &content_size_sent, 4, 0) == -1) {
perror("send");
debugf("errno: %i", errno);
};
if (send(socket, content, content_size, 0) == -1) {
perror("send");
debugf("errno: %i", errno);
};
free(content);
return 1;
}
static int
re6st_send_dump_tables(int socket)
{
int ret;
FILE *fp = tmpfile();
dump_tables(fp);
ret = re6st_send_file(fp, socket);
fclose(fp);
return ret;
}
void
apply_cost_modifiers(struct re6st_cost_modifier *costs, int element_count) {
debugf("Received %i cost modifiers\n", element_count);
int i;
struct neighbour *neigh;
for (i=0; i<element_count; i++) {
struct re6st_cost_modifier *cost = (costs+i);
int interface_index = ntohl(cost->n_interface_index);
int cost_multiplier = ntohs(cost->n_cost_multiplier);
debugf("Neigh %d: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x, interface: %i, cost: %i\n",
i,
cost->ipv6[0],
cost->ipv6[1],
cost->ipv6[2],
cost->ipv6[3],
cost->ipv6[4],
cost->ipv6[5],
cost->ipv6[6],
cost->ipv6[7],
cost->ipv6[8],
cost->ipv6[9],
cost->ipv6[10],
cost->ipv6[11],
cost->ipv6[12],
cost->ipv6[13],
cost->ipv6[14],
cost->ipv6[15],
interface_index,
cost_multiplier);
FOR_ALL_NEIGHBOURS(neigh) {
if (!memcmp(cost->ipv6, neigh->address, 16) && (interface_index == neigh->ifp->ifindex)) {
debugf("Neighbour address and interface match. Setting cost multiplier to %i\n", cost_multiplier);
neigh->cost_multiplier = cost_multiplier;
}
}
}
}
int
re6st_accept_connection(int socket)
{
re6st_set_nonblock(socket);
debugf("Accept re6st connection on socket %d\n", socket);
int newsock = -1;
newsock = accept(socket, NULL, NULL);
if (newsock < 0) {
if (errno != EINTR && errno != EAGAIN) {
perror("accept(re6st_socket)");
return -1;
}
return 0;
}
int n = 0;
uint32_t payload_size = 0;
n = recv(newsock, &payload_size, 4, 0);
payload_size = ntohl(payload_size);
if (n == 0) {
// remote has closed connection
return 0;
}
debugf("PAYLOAD SIZE: %i\n", payload_size);
char *payload;
payload = malloc(payload_size + 1);
int remaining = payload_size;
while (remaining) {
debugf("looping recv\n");
n = recv(newsock, payload + payload_size - remaining, remaining, 0);
if (n == 0) {
// remote has closed connection
free(payload);
return 0;
}
if (n == -1) {
if (errno == EAGAIN) {
continue;
} else {
return 0;
}
}
remaining -= n;
};
payload[payload_size] = 0;
if (!strncmp(payload, "DUMP TABLES", payload_size)) {
re6st_send_dump_tables(newsock);
} else if (!strncmp(payload, "DUMP NEIGHBOURS", payload_size)) {
dump_neighbours(newsock);
} else if (!strncmp(payload, "UPDATE COSTS", 12)) {
apply_cost_modifiers((struct re6st_cost_modifier *)(payload+12), (payload_size-12)/sizeof(struct re6st_cost_modifier));
} else {
debugf("Unknown protocol command %s", payload);
}
free(payload);
close(newsock);
return 1;
}
int re6st_setup_socket(int setup);
int re6st_accept_connection(int socket);
int re6st_send_file(FILE *fp, int socket);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment