diff options
-rw-r--r-- | ffd/announce.c | 3 | ||||
-rw-r--r-- | ffd/ffd.c | 61 | ||||
-rw-r--r-- | ffd/ffd.h | 10 | ||||
-rw-r--r-- | ffd/send.c | 18 | ||||
-rw-r--r-- | ffd/tlv_types.h | 6 |
5 files changed, 89 insertions, 9 deletions
diff --git a/ffd/announce.c b/ffd/announce.c index 0d7b1bc..26ced28 100644 --- a/ffd/announce.c +++ b/ffd/announce.c @@ -116,6 +116,9 @@ void ffd_announce_update(ffd_announce_t *announce) { announce->selected = select_nexthop(announce); announce->metric = get_metric(announce); + if (!announce->selected) + ffd_send_seqno_request_for(NULL, announce); + /* triggered updates */ int diff = announce->metric.metric - announce->last_metric; @@ -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); } else { - if (!feasible && nexthop == announce->selected) + if (!feasible && nexthop == announce->selected) { + ffd_send_seqno_request_for(neigh, announce); 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) { @@ -369,6 +376,8 @@ static void handle_tlv_announce_req(const ffd_tlv_announce_req_t *tlv_req, size_ return; } + fprintf(stderr, "debug: received announce request\n"); + 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); } @@ -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) { switch (type) { 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); return; + case TLV_SEQNO_REQ: + handle_tlv_seqno_req(data, len, arg); + return; + default: fprintf(stderr, "debug: received unknown TLV %u on %s.\n", type, ((handle_tlv_arg_t*)arg)->iface->name); 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 }; - if (!arg.iface) { - fprintf(stderr, "debug: received packet on unknown interface.\n"); + if (!arg.iface) return; - } if (!ffd_tlv_parse(packet, handle_tlv, &arg)) { fprintf(stderr, "debug: received invalid packet.\n"); @@ -39,7 +39,7 @@ #define FFD_HELLO_INTERVAL 400 #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_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_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_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_ */ @@ -300,3 +300,21 @@ void ffd_send_announce_request(ffd_iface_t *iface, ffd_neigh_t *neigh, ffd_node_ 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); +} diff --git a/ffd/tlv_types.h b/ffd/tlv_types.h index 07eba53..af3e853 100644 --- a/ffd/tlv_types.h +++ b/ffd/tlv_types.h @@ -70,20 +70,18 @@ typedef struct __attribute__((packed)) _ffd_tlv_update_t { } ffd_tlv_update_t; typedef struct __attribute__((packed)) _ffd_tlv_announce_req_t { - ffd_node_id_t node; uint8_t flags; uint8_t reserved; + ffd_node_id_t node; uint16_t type; uint16_t key; } ffd_tlv_announce_req_t; typedef struct __attribute__((packed)) _ffd_tlv_seqno_req_t { + uint16_t seqno; ffd_node_id_t node; - uint8_t flags; - uint8_t reserved; uint16_t type; uint16_t key; - uint16_t seqno; } ffd_tlv_seqno_req_t; #endif /* _FFD_TLV_TYPES_H_ */ |