Commit b8e3dadc authored by Cédric Le Ninivin's avatar Cédric Le Ninivin Committed by Killian Lufau

ctl: add command to change the cost multiplier of a neighbour

To be pushed upstream.
Co-authored-by: Julien Muchembled's avatarJulien Muchembled <jm@nexedi.com>
parent 2c161784
......@@ -73,6 +73,69 @@ ctl_resize_buffer(struct ctl_buffer *buffer, size_t n)
return 0;
}
static int
ctl_set_cost_multiplier(struct ctl_buffer *buffer, void *packet, size_t length)
{
struct {
uint8_t address[16];
uint32_t ifindex;
uint16_t cost_multiplier;
} __attribute__((packed)) *request = packet;
unsigned ifindex = ntohl(request->ifindex);
struct neighbour *neigh;
struct {
uint16_t type;
uint32_t length;
uint8_t flags;
} __attribute__((packed)) *response;
uint8_t unknown = 1, changed = 0;
size_t end = buffer->end + sizeof *response;
if(ctl_resize_buffer(buffer, end))
return -1;
FOR_ALL_NEIGHBOURS(neigh)
if(neigh->ifp->ifindex == ifindex &&
!memcmp(request->address, neigh->address, sizeof request->address)) {
struct babel_route *route;
struct route_stream *routes;
unsigned short cost_multiplier;
cost_multiplier = ntohs(request->cost_multiplier);
unknown = 0;
changed = neigh->cost_multiplier != cost_multiplier;
if(!cost_multiplier && changed) {
routes = route_stream(1);
if(!routes)
return -1;
while((route = route_stream_next(routes)))
if(route->neigh == neigh) {
changed = 0;
break;
}
route_stream_done(routes);
}
if(changed) {
routes = route_stream(0);
if(!routes)
return -1;
neigh->cost_multiplier = cost_multiplier;
while((route = route_stream_next(routes)))
if(route->neigh == neigh)
update_route_metric(route);
route_stream_done(routes);
}
break;
}
response = (void *)(buffer->data + buffer->end);
response->type = htons(CTL_MSG_SET_COST_MULTIPLIER);
response->length = htonl(sizeof *response - 6);
response->flags = changed << 1 | unknown;
buffer->end = end;
return 0;
}
static int
ctl_dump_interface(struct ctl_buffer *buffer, struct interface *ifp)
{
......@@ -102,6 +165,7 @@ ctl_dump_neighbour(struct ctl_buffer *buffer, struct neighbour *neigh)
neigh_dump->rttcost = htonl(neighbour_rttcost(neigh));
neigh_dump->channel = htonl(neigh->ifp->channel);
neigh_dump->if_up = htons(if_up(neigh->ifp));
neigh_dump->cost_multiplier = htons(neigh->cost_multiplier);
buffer->end = end;
return 0;
}
......@@ -244,6 +308,9 @@ ctl_work(struct ctl *ctl)
case CTL_MSG_DUMP:
ret = ctl_dump(&ctl->buffer_out, p, length);
break;
case CTL_MSG_SET_COST_MULTIPLIER:
ret = ctl_set_cost_multiplier(&ctl->buffer_out, p, length);
break;
}
else if(length < CTL_MAX_SIZE)
return;
......
......@@ -28,6 +28,7 @@ THE SOFTWARE.
#define CTL_VERSION 1
#define CTL_MSG_DUMP 1
#define CTL_MSG_SET_COST_MULTIPLIER 2
#define CTL_DUMP_INTERFACE (1 << 0)
#define CTL_DUMP_NEIGHBOUR (1 << 1)
......@@ -57,6 +58,7 @@ struct ctl_dump_neighbour {
uint16_t rttcost;
int32_t channel;
uint16_t if_up;
uint16_t cost_multiplier;
} __attribute__((packed));
......
......@@ -114,6 +114,7 @@ find_neighbour(const unsigned char *address, struct interface *ifp)
memcpy(&neigh->buf.sin6.sin6_addr, address, 16);
neigh->buf.sin6.sin6_port = htons(protocol_port);
neigh->buf.sin6.sin6_scope_id = ifp->ifindex;
neigh->cost_multiplier = 256;
neigh->next = neighs;
neighs = neigh;
local_notify_neighbour(neigh, LOCAL_ADD);
......@@ -373,6 +374,10 @@ neighbour_cost(struct neighbour *neigh)
cost += neighbour_rttcost(neigh);
if(!neigh->cost_multiplier)
return INFINITY;
cost = cost * neigh->cost_multiplier >> 8 ?: 1;
return MIN(cost, INFINITY);
}
......
......@@ -45,6 +45,7 @@ struct neighbour {
struct timeval rtt_time;
struct interface *ifp;
struct buffered buf;
unsigned short cost_multiplier;
};
extern struct neighbour *neighs;
......
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