Add code for periodic maintenance
This commit is contained in:
parent
4334011653
commit
650a9e8827
5 changed files with 50 additions and 12 deletions
37
ffd/ffd.c
37
ffd/ffd.c
|
@ -215,7 +215,7 @@ static void handle_tlv_hello(const ffd_tlv_hello_t *tlv_hello, size_t len, handl
|
||||||
uint16_t seqno = ntohs(tlv_hello->seqno);
|
uint16_t seqno = ntohs(tlv_hello->seqno);
|
||||||
|
|
||||||
if (neigh->last_hello.tv_sec) {
|
if (neigh->last_hello.tv_sec) {
|
||||||
int timediff = timespec_diff(&now, &neigh->last_hello)/10;
|
int timediff = timespec_diff(&now, &neigh->last_hello);
|
||||||
uint16_t seqexp = neigh->last_seqno + (timediff - neigh->hello_interval/2)/neigh->hello_interval;
|
uint16_t seqexp = neigh->last_seqno + (timediff - neigh->hello_interval/2)/neigh->hello_interval;
|
||||||
|
|
||||||
/* cast to int16_t to ensure correct handling of seqno wrapping */
|
/* cast to int16_t to ensure correct handling of seqno wrapping */
|
||||||
|
@ -268,10 +268,11 @@ static void handle_tlv_ihu(const ffd_tlv_ihu_t *tlv_ihu, size_t len, handle_tlv_
|
||||||
}
|
}
|
||||||
|
|
||||||
ffd_neigh_t *neigh = get_tlv_neigh(arg);
|
ffd_neigh_t *neigh = get_tlv_neigh(arg);
|
||||||
|
neigh->ihu_interval = ntohs(tlv_ihu->interval);
|
||||||
neigh->last_ihu = now;
|
neigh->last_ihu = now;
|
||||||
neigh->txcost = ntohs(tlv_ihu->rxcost);
|
neigh->txcost = ntohs(tlv_ihu->rxcost);
|
||||||
|
|
||||||
fprintf(stderr, "debug: accepted IHU, txcost is %u, cost is %u now.\n", neigh->txcost, ffd_neigh_get_cost(neigh));
|
fprintf(stderr, "debug: accepted IHU, txcost is %u, cost is %u now.\n", ffd_neigh_get_txcost(neigh), ffd_neigh_get_cost(neigh));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_tlv_node_id(const ffd_tlv_node_id_t *tlv_node_id, size_t len, handle_tlv_arg_t *arg) {
|
static void handle_tlv_node_id(const ffd_tlv_node_id_t *tlv_node_id, size_t len, handle_tlv_arg_t *arg) {
|
||||||
|
@ -470,6 +471,19 @@ static void send_updates(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void maintenance(void) {
|
||||||
|
ffd_iface_t *iface;
|
||||||
|
for (iface = iface_list; iface; iface = iface->next) {
|
||||||
|
ffd_neigh_t *neigh;
|
||||||
|
for (neigh = iface->neigh_list; neigh; neigh = neigh->next) {
|
||||||
|
fprintf(stderr, "debug: maintenance: %02x:%02x:%02x:%02x:%02x:%02x[%s]: %u (rx %u/tx %u)\n",
|
||||||
|
neigh->addr.d[0], neigh->addr.d[1], neigh->addr.d[2],
|
||||||
|
neigh->addr.d[3], neigh->addr.d[4], neigh->addr.d[5],
|
||||||
|
iface->name, ffd_neigh_get_cost(neigh), ffd_neigh_get_rxcost(neigh), ffd_neigh_get_txcost(neigh));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
if (!check_config())
|
if (!check_config())
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -484,34 +498,43 @@ int main() {
|
||||||
|
|
||||||
struct timespec next_hello = now;
|
struct timespec next_hello = now;
|
||||||
struct timespec next_update = now;
|
struct timespec next_update = now;
|
||||||
|
struct timespec next_maintenance = now;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
update_netifs();
|
update_netifs();
|
||||||
|
|
||||||
int hello_timeout = timespec_diff(&next_hello, &now);
|
int hello_timeout = timespec_diff(&next_hello, &now);
|
||||||
int update_timeout = timespec_diff(&next_update, &now);
|
|
||||||
|
|
||||||
if (hello_timeout <= 0) {
|
if (hello_timeout <= 0) {
|
||||||
ffd_send_hellos();
|
ffd_send_hellos();
|
||||||
|
|
||||||
add_interval(&next_hello, FFD_HELLO_INTERVAL);
|
add_interval(&next_hello, FFD_HELLO_INTERVAL);
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int update_timeout = timespec_diff(&next_update, &now);
|
||||||
if (update_timeout <= 0) {
|
if (update_timeout <= 0) {
|
||||||
fprintf(stderr, "Sending periodic update.\n");
|
fprintf(stderr, "Sending periodic update.\n");
|
||||||
send_updates();
|
send_updates();
|
||||||
|
|
||||||
add_interval(&next_update, FFD_UPDATE_INTERVAL);
|
add_interval(&next_update, FFD_UPDATE_INTERVAL);
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int maintenance_timeout = timespec_diff(&next_maintenance, &now);
|
||||||
|
if (maintenance_timeout <= 0) {
|
||||||
|
maintenance();
|
||||||
|
|
||||||
|
add_interval(&next_maintenance, FFD_MAINTENANCE_INTERVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int timeout = min(min(hello_timeout, update_timeout), maintenance_timeout);
|
||||||
|
if (timeout <= 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
struct pollfd fds[1];
|
struct pollfd fds[1];
|
||||||
|
|
||||||
fds[0].fd = sockfd;
|
fds[0].fd = sockfd;
|
||||||
fds[0].events = POLLIN;
|
fds[0].events = POLLIN;
|
||||||
|
|
||||||
poll(fds, 1, min(hello_timeout, update_timeout));
|
poll(fds, 1, 10*timeout);
|
||||||
|
|
||||||
update_time();
|
update_time();
|
||||||
|
|
||||||
|
|
|
@ -39,9 +39,14 @@
|
||||||
|
|
||||||
#define FFD_HELLO_INTERVAL 400
|
#define FFD_HELLO_INTERVAL 400
|
||||||
#define FFD_IHU_INTERVAL (3*FFD_HELLO_INTERVAL)
|
#define FFD_IHU_INTERVAL (3*FFD_HELLO_INTERVAL)
|
||||||
|
|
||||||
#define FFD_UPDATE_INTERVAL 6000
|
#define FFD_UPDATE_INTERVAL 6000
|
||||||
|
|
||||||
|
#define FFD_HELLO_TIMEOUT(interval) (16*(interval))
|
||||||
|
#define FFD_IHU_TIMEOUT(interval) ((interval)*7/2)
|
||||||
|
#define FFD_UPDATE_TIMEOUT(interval) ((interval)*7/2)
|
||||||
|
|
||||||
|
#define FFD_MAINTENANCE_INTERVAL FFD_HELLO_INTERVAL
|
||||||
|
|
||||||
|
|
||||||
#define FFD_UPDATE_WITH_DATA 0x01
|
#define FFD_UPDATE_WITH_DATA 0x01
|
||||||
|
|
||||||
|
@ -94,6 +99,8 @@ typedef struct _ffd_neigh_t {
|
||||||
uint16_t hello_interval;
|
uint16_t hello_interval;
|
||||||
uint16_t last_seqno;
|
uint16_t last_seqno;
|
||||||
struct timespec last_hello;
|
struct timespec last_hello;
|
||||||
|
|
||||||
|
uint16_t ihu_interval;
|
||||||
struct timespec last_ihu;
|
struct timespec last_ihu;
|
||||||
|
|
||||||
uint16_t txcost;
|
uint16_t txcost;
|
||||||
|
|
11
ffd/neigh.c
11
ffd/neigh.c
|
@ -53,7 +53,7 @@ uint16_t ffd_neigh_get_rxcost(const ffd_neigh_t *neigh) {
|
||||||
if (!neigh->hello_log || !neigh->hello_interval)
|
if (!neigh->hello_log || !neigh->hello_interval)
|
||||||
return 0xffff;
|
return 0xffff;
|
||||||
|
|
||||||
int timediff = timespec_diff(&now, &neigh->last_hello)/10;
|
int timediff = timespec_diff(&now, &neigh->last_hello);
|
||||||
int shift = (timediff - neigh->hello_interval/2)/neigh->hello_interval;
|
int shift = (timediff - neigh->hello_interval/2)/neigh->hello_interval;
|
||||||
int received = __builtin_popcount(neigh->hello_log << shift);
|
int received = __builtin_popcount(neigh->hello_log << shift);
|
||||||
|
|
||||||
|
@ -63,11 +63,18 @@ uint16_t ffd_neigh_get_rxcost(const ffd_neigh_t *neigh) {
|
||||||
return (0x1000/received);
|
return (0x1000/received);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint16_t ffd_neigh_get_txcost(const ffd_neigh_t *neigh) {
|
||||||
|
if (timespec_diff(&now, &neigh->last_ihu) > FFD_IHU_TIMEOUT(neigh->ihu_interval))
|
||||||
|
return 0xffff;
|
||||||
|
else
|
||||||
|
return neigh->txcost;
|
||||||
|
}
|
||||||
|
|
||||||
uint16_t ffd_neigh_get_cost(const ffd_neigh_t *neigh) {
|
uint16_t ffd_neigh_get_cost(const ffd_neigh_t *neigh) {
|
||||||
if (!neigh) /* self */
|
if (!neigh) /* self */
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
uint16_t txcost = neigh->txcost;
|
uint16_t txcost = ffd_neigh_get_txcost(neigh);
|
||||||
if (txcost < 256)
|
if (txcost < 256)
|
||||||
txcost = 256;
|
txcost = 256;
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,7 @@ ffd_neigh_t* ffd_neigh_get(ffd_iface_t *iface, const eth_addr_t *addr);
|
||||||
void ffd_neigh_free_list(ffd_neigh_t *neigh);
|
void ffd_neigh_free_list(ffd_neigh_t *neigh);
|
||||||
|
|
||||||
uint16_t ffd_neigh_get_rxcost(const ffd_neigh_t *neigh);
|
uint16_t ffd_neigh_get_rxcost(const ffd_neigh_t *neigh);
|
||||||
|
uint16_t ffd_neigh_get_txcost(const ffd_neigh_t *neigh);
|
||||||
uint16_t ffd_neigh_get_cost(const ffd_neigh_t *neigh);
|
uint16_t ffd_neigh_get_cost(const ffd_neigh_t *neigh);
|
||||||
void ffd_neigh_reset(ffd_iface_t *iface, ffd_neigh_t *neigh);
|
void ffd_neigh_reset(ffd_iface_t *iface, ffd_neigh_t *neigh);
|
||||||
|
|
||||||
|
|
|
@ -53,9 +53,9 @@ static inline bool are_eth_addrs_equal(const eth_addr_t *address1, const eth_add
|
||||||
return (a[0]==b[0] && a[1]==b[1] && a[2]==b[2] && a[3]==b[3] && a[4]==b[4] && a[5]==b[5]);
|
return (a[0]==b[0] && a[1]==b[1] && a[2]==b[2] && a[3]==b[3] && a[4]==b[4] && a[5]==b[5]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* returns (tp1 - tp2) in milliseconds */
|
/* returns (tp1 - tp2) in centiseconds */
|
||||||
static inline int timespec_diff(const struct timespec *tp1, const struct timespec *tp2) {
|
static inline int timespec_diff(const struct timespec *tp1, const struct timespec *tp2) {
|
||||||
return ((tp1->tv_sec - tp2->tv_sec))*1000 + (tp1->tv_nsec - tp2->tv_nsec)/1e6;
|
return ((tp1->tv_sec - tp2->tv_sec))*100 + (tp1->tv_nsec - tp2->tv_nsec)/1e7;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int max(int a, int b) {
|
static inline int max(int a, int b) {
|
||||||
|
|
Reference in a new issue