Send and handle seqno requests
This commit is contained in:
parent
ec21d1874e
commit
e912f03740
5 changed files with 89 additions and 9 deletions
|
@ -116,6 +116,9 @@ void ffd_announce_update(ffd_announce_t *announce) {
|
||||||
announce->selected = select_nexthop(announce);
|
announce->selected = select_nexthop(announce);
|
||||||
announce->metric = get_metric(announce);
|
announce->metric = get_metric(announce);
|
||||||
|
|
||||||
|
if (!announce->selected)
|
||||||
|
ffd_send_seqno_request_for(NULL, announce);
|
||||||
|
|
||||||
/* triggered updates */
|
/* triggered updates */
|
||||||
int diff = announce->metric.metric - announce->last_metric;
|
int diff = announce->metric.metric - announce->last_metric;
|
||||||
|
|
||||||
|
|
61
ffd/ffd.c
61
ffd/ffd.c
|
@ -336,8 +336,15 @@ static void handle_tlv_update(const ffd_tlv_update_t *tlv_update, size_t len, ha
|
||||||
nexthop = new_nexthop(announce, neigh);
|
nexthop = new_nexthop(announce, neigh);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (!feasible && nexthop == announce->selected)
|
if (!feasible && nexthop == announce->selected) {
|
||||||
|
ffd_send_seqno_request_for(neigh, announce);
|
||||||
nexthop = NULL;
|
nexthop = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!feasible && nexthop && nexthop != announce->selected) {
|
||||||
|
if (ms.metric + ffd_neigh_get_cost(neigh) < announce->metric.metric)
|
||||||
|
ffd_send_seqno_request_for(neigh, announce);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((tlv_update->flags & FFD_UPDATE_WITH_DATA) && !announce->data) {
|
if ((tlv_update->flags & FFD_UPDATE_WITH_DATA) && !announce->data) {
|
||||||
|
@ -369,6 +376,8 @@ static void handle_tlv_announce_req(const ffd_tlv_announce_req_t *tlv_req, size_
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "debug: received announce request\n");
|
||||||
|
|
||||||
if (ffd_is_node_id_unspec(&tlv_req->node)) {
|
if (ffd_is_node_id_unspec(&tlv_req->node)) {
|
||||||
ffd_send_update(NULL, get_tlv_neigh(arg), NULL, tlv_req->flags & FFD_UPDATE_WITH_DATA);
|
ffd_send_update(NULL, get_tlv_neigh(arg), NULL, tlv_req->flags & FFD_UPDATE_WITH_DATA);
|
||||||
}
|
}
|
||||||
|
@ -382,6 +391,48 @@ static void handle_tlv_announce_req(const ffd_tlv_announce_req_t *tlv_req, size_
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void handle_tlv_seqno_req(const ffd_tlv_seqno_req_t *tlv_req, size_t len, handle_tlv_arg_t *arg) {
|
||||||
|
if (len < sizeof(ffd_tlv_seqno_req_t)) {
|
||||||
|
fprintf(stderr, "warn: received short seqno request TLV.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "debug: received seqno request\n");
|
||||||
|
|
||||||
|
ffd_announce_t *announce = ffd_announce_find(&tlv_req->node, ntohs(tlv_req->type), ntohs(tlv_req->key));
|
||||||
|
|
||||||
|
if (!announce) {
|
||||||
|
fprintf(stderr, "debug: received seqno request for unknown announce\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!announce->selected) {
|
||||||
|
fprintf(stderr, "debug: received seqno request for starved announce\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ffd_neigh_t *neigh = get_tlv_neigh(arg);
|
||||||
|
|
||||||
|
if (announce->selected->neigh == neigh)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ((int16_t)(ntohs(tlv_req->seqno)-announce->selected->metric_seqno.seqno) <= 0) {
|
||||||
|
fprintf(stderr, "debug: received seqno request, seqno already ok\n");
|
||||||
|
ffd_send_update(NULL, neigh, announce, false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!announce->selected->neigh) {
|
||||||
|
fprintf(stderr, "debug: incrementing seqno\n");
|
||||||
|
announce->selected->metric_seqno.seqno++;
|
||||||
|
ffd_send_update(NULL, neigh, announce, false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "debug: received seqno request, forwarding\n");
|
||||||
|
ffd_send_seqno_request(announce->selected->neigh, announce, ntohs(tlv_req->seqno));
|
||||||
|
}
|
||||||
|
|
||||||
static void handle_tlv(ffd_tlv_type_t type, const void *data, size_t len, void *arg) {
|
static void handle_tlv(ffd_tlv_type_t type, const void *data, size_t len, void *arg) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case TLV_ACK_REQ:
|
case TLV_ACK_REQ:
|
||||||
|
@ -412,6 +463,10 @@ static void handle_tlv(ffd_tlv_type_t type, const void *data, size_t len, void *
|
||||||
handle_tlv_announce_req(data, len, arg);
|
handle_tlv_announce_req(data, len, arg);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
case TLV_SEQNO_REQ:
|
||||||
|
handle_tlv_seqno_req(data, len, arg);
|
||||||
|
return;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "debug: received unknown TLV %u on %s.\n", type, ((handle_tlv_arg_t*)arg)->iface->name);
|
fprintf(stderr, "debug: received unknown TLV %u on %s.\n", type, ((handle_tlv_arg_t*)arg)->iface->name);
|
||||||
return;
|
return;
|
||||||
|
@ -442,10 +497,8 @@ static void receive_packet(void) {
|
||||||
|
|
||||||
handle_tlv_arg_t arg = { .iface = get_iface(from.sll_ifindex), .addr = (const eth_addr_t*)&from.sll_addr };
|
handle_tlv_arg_t arg = { .iface = get_iface(from.sll_ifindex), .addr = (const eth_addr_t*)&from.sll_addr };
|
||||||
|
|
||||||
if (!arg.iface) {
|
if (!arg.iface)
|
||||||
fprintf(stderr, "debug: received packet on unknown interface.\n");
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
if (!ffd_tlv_parse(packet, handle_tlv, &arg)) {
|
if (!ffd_tlv_parse(packet, handle_tlv, &arg)) {
|
||||||
fprintf(stderr, "debug: received invalid packet.\n");
|
fprintf(stderr, "debug: received invalid packet.\n");
|
||||||
|
|
10
ffd/ffd.h
10
ffd/ffd.h
|
@ -39,7 +39,7 @@
|
||||||
|
|
||||||
#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 3000
|
||||||
|
|
||||||
#define FFD_HELLO_TIMEOUT(interval) (16*(interval))
|
#define FFD_HELLO_TIMEOUT(interval) (16*(interval))
|
||||||
#define FFD_IHU_TIMEOUT(interval) ((interval)*7/2)
|
#define FFD_IHU_TIMEOUT(interval) ((interval)*7/2)
|
||||||
|
@ -195,5 +195,13 @@ void ffd_send_hellos(void);
|
||||||
void ffd_send_update(ffd_iface_t *iface, ffd_neigh_t *neigh, ffd_announce_t *announce, bool with_data);
|
void ffd_send_update(ffd_iface_t *iface, ffd_neigh_t *neigh, ffd_announce_t *announce, bool with_data);
|
||||||
void ffd_send_retract(ffd_neigh_t *neigh, ffd_node_id_t node, uint16_t type, uint16_t key);
|
void ffd_send_retract(ffd_neigh_t *neigh, ffd_node_id_t node, uint16_t type, uint16_t key);
|
||||||
void ffd_send_announce_request(ffd_iface_t *iface, ffd_neigh_t *neigh, ffd_node_id_t node, uint16_t type, uint16_t key, bool with_data);
|
void ffd_send_announce_request(ffd_iface_t *iface, ffd_neigh_t *neigh, ffd_node_id_t node, uint16_t type, uint16_t key, bool with_data);
|
||||||
|
void ffd_send_seqno_request(ffd_neigh_t *neigh, ffd_announce_t *announce, uint16_t seqno);
|
||||||
|
|
||||||
|
static inline void ffd_send_seqno_request_for(ffd_neigh_t *neigh, ffd_announce_t *announce) {
|
||||||
|
if (FFD_IS_INFINITY(announce->feasibility_distance))
|
||||||
|
return;
|
||||||
|
|
||||||
|
ffd_send_seqno_request(neigh, announce, announce->feasibility_distance.seqno+1);
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* _FFD_FFD_H_ */
|
#endif /* _FFD_FFD_H_ */
|
||||||
|
|
18
ffd/send.c
18
ffd/send.c
|
@ -300,3 +300,21 @@ void ffd_send_announce_request(ffd_iface_t *iface, ffd_neigh_t *neigh, ffd_node_
|
||||||
|
|
||||||
send_any(iface, neigh, packet);
|
send_any(iface, neigh, packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ffd_send_seqno_request(ffd_neigh_t *neigh, ffd_announce_t *announce, uint16_t seqno) {
|
||||||
|
ffd_packet_t *packet = alloca(sizeof(ffd_packet_t)+FFD_PACKET_MAX);
|
||||||
|
|
||||||
|
packet->version_magic = htons(FFD_VERSION_MAGIC);
|
||||||
|
packet->len = 0;
|
||||||
|
|
||||||
|
ffd_tlv_seqno_req_t *req = ffd_tlv_add(packet, FFD_PACKET_MAX, TLV_SEQNO_REQ, sizeof(ffd_tlv_seqno_req_t));
|
||||||
|
if (!req)
|
||||||
|
return;
|
||||||
|
|
||||||
|
req->seqno = htons(seqno);
|
||||||
|
req->node = announce->node;
|
||||||
|
req->type = htons(announce->type);
|
||||||
|
req->key = htons(announce->key);
|
||||||
|
|
||||||
|
send_any(NULL, neigh, packet);
|
||||||
|
}
|
||||||
|
|
|
@ -70,20 +70,18 @@ typedef struct __attribute__((packed)) _ffd_tlv_update_t {
|
||||||
} ffd_tlv_update_t;
|
} ffd_tlv_update_t;
|
||||||
|
|
||||||
typedef struct __attribute__((packed)) _ffd_tlv_announce_req_t {
|
typedef struct __attribute__((packed)) _ffd_tlv_announce_req_t {
|
||||||
ffd_node_id_t node;
|
|
||||||
uint8_t flags;
|
uint8_t flags;
|
||||||
uint8_t reserved;
|
uint8_t reserved;
|
||||||
|
ffd_node_id_t node;
|
||||||
uint16_t type;
|
uint16_t type;
|
||||||
uint16_t key;
|
uint16_t key;
|
||||||
} ffd_tlv_announce_req_t;
|
} ffd_tlv_announce_req_t;
|
||||||
|
|
||||||
typedef struct __attribute__((packed)) _ffd_tlv_seqno_req_t {
|
typedef struct __attribute__((packed)) _ffd_tlv_seqno_req_t {
|
||||||
|
uint16_t seqno;
|
||||||
ffd_node_id_t node;
|
ffd_node_id_t node;
|
||||||
uint8_t flags;
|
|
||||||
uint8_t reserved;
|
|
||||||
uint16_t type;
|
uint16_t type;
|
||||||
uint16_t key;
|
uint16_t key;
|
||||||
uint16_t seqno;
|
|
||||||
} ffd_tlv_seqno_req_t;
|
} ffd_tlv_seqno_req_t;
|
||||||
|
|
||||||
#endif /* _FFD_TLV_TYPES_H_ */
|
#endif /* _FFD_TLV_TYPES_H_ */
|
||||||
|
|
Reference in a new issue