bool rreqtable_is_redundant(struct aodvv2_packet_data *packet_data) { struct aodvv2_rreq_entry *comparable_rreq; timex_t now; bool result; mutex_lock(&rreqt_mutex); comparable_rreq = _get_comparable_rreq(packet_data); /* if there is no comparable rreq stored, add one and return false */ if (comparable_rreq == NULL) { _add_rreq(packet_data); result = false; } else { int seqnum_comparison = seqnum_cmp(packet_data->origNode.seqnum, comparable_rreq->seqnum); /* * If two RREQs have the same * metric type and OrigNode and Targnode addresses, the information from * the one with the older Sequence Number is not needed in the table */ if (seqnum_comparison == -1) { result = true; } if (seqnum_comparison == 1) { /* Update RREQ table entry with new seqnum value */ comparable_rreq->seqnum = packet_data->origNode.seqnum; } /* * in case they have the same Sequence Number, the one with the greater * Metric value is not needed */ if (seqnum_comparison == 0) { if (comparable_rreq->metric <= packet_data->origNode.metric) { result = true; } /* Update RREQ table entry with new metric value */ comparable_rreq->metric = packet_data->origNode.metric; } /* Since we've changed RREQ info, update the timestamp */ vtimer_now(&now); comparable_rreq->timestamp = now; result = true; } mutex_unlock(&rreqt_mutex); return result; }
static enum rfc5444_result _cb_rerr_blocktlv_addresstlvs_okay(struct rfc5444_reader_tlvblock_context *cont) { #if ENABLE_DEBUG /* cppcheck-suppress unusedVariable as nbuf is needed by VDEBUG. */ struct netaddr_str nbuf; #endif struct aodvv2_routing_entry_t *unreachable_entry; struct rfc5444_reader_tlvblock_entry *tlv; VDEBUG("%s()\n", __func__); VDEBUG("\tmessage type: %d\n", cont->type); VDEBUG("\taddr: %s\n", netaddr_to_string(&nbuf, &cont->addr)); /* Out of buffer size for more unreachable nodes. We're screwed, basically. */ if (num_unreachable_nodes == AODVV2_MAX_UNREACHABLE_NODES) { return RFC5444_OKAY; } /* gather packet data */ packet_data.origNode.addr = cont->addr; /* handle this unreachable node's SeqNum TLV */ /* cppcheck: suppress false positive on non-trivially initialized arrays. * this is a known bug: http://trac.cppcheck.net/ticket/5497 */ /* cppcheck-suppress arrayIndexOutOfBounds */ tlv = _rerr_address_consumer_entries[RFC5444_MSGTLV_UNREACHABLE_NODE_SEQNUM].tlv; if (tlv) { VDEBUG("\ttlv RFC5444_MSGTLV_UNREACHABLE_NODE_SEQNUM: %d\n", *tlv->single_value); packet_data.origNode.seqnum = *tlv->single_value; } /* Check if there is an entry for unreachable node in our routing table */ unreachable_entry = routingtable_get_entry(&packet_data.origNode.addr, packet_data.metricType); if (unreachable_entry) { VDEBUG("\t found possibly unreachable entry.\n"); /* check if route to unreachable node has to be marked as broken and RERR has to be forwarded */ if (netaddr_cmp(&unreachable_entry->nextHopAddr, &packet_data.sender) == 0 && (!tlv || seqnum_cmp(unreachable_entry->seqnum, packet_data.origNode.seqnum) == 0)) { unreachable_entry->state = ROUTE_STATE_INVALID; unreachable_nodes[num_unreachable_nodes].addr = packet_data.origNode.addr; unreachable_nodes[num_unreachable_nodes].seqnum = packet_data.origNode.seqnum; num_unreachable_nodes++; } /* remove entry from FIB */ fib_remove_entry(packet_data.origNode.addr._addr, sizeof(ipv6_addr_t)); } return RFC5444_OKAY; }
bool routingtable_offers_improvement(struct aodvv2_routing_entry_t *rt_entry, struct node_data *node_data) { /* (TODO only guaranteed for AODVV2_DEFAULT_METRIC_TYPE!)*/ bool is_loop_free = node_data->metric <= rt_entry->metric; int stale = seqnum_cmp(node_data->seqnum, rt_entry->seqnum); if ((stale == 1) /* New info is more recent and MUST be used */ || ((stale == 0) && (node_data->metric < rt_entry->metric)) /* New info offers a better route and SHOULD be used */ || ((stale == 0) && (node_data->metric >= rt_entry->metric) /* Route is not an improvement, */ && (rt_entry->state == ROUTE_STATE_INVALID) /* but repairs an invalid route */ && is_loop_free) /* and contains no loops */ ) { return true; } return false; }