diff options
Diffstat (limited to 'ffd/ffd.c')
-rw-r--r-- | ffd/ffd.c | 61 |
1 files changed, 57 insertions, 4 deletions
@@ -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"); |