/** \brief Indicate some packet was sent to some neighbor. This function should be called for each transmitted (non-ACK) packet so neighbor statistics in the neighbor table can be updated. The fields which are updated are: - numTx - numTxACK - asn \param[in] l2_dest MAC destination address of the packet, i.e. the neighbor who I just sent the packet to. \param[in] numTxAttempts Number of transmission attempts to this neighbor. \param[in] was_finally_acked TRUE iff the packet was ACK'ed by the neighbor on final transmission attempt. \param[in] asnTs ASN of the last transmission attempt. */ void neighbors_indicateTx(open_addr_t* l2_dest, uint8_t numTxAttempts, bool was_finally_acked, asn_t* asnTs) { uint8_t i; // don't run through this function if packet was sent to broadcast address if (packetfunctions_isBroadcastMulticast(l2_dest)==TRUE) { return; } // loop through neighbor table for (i=0;i<MAXNUMNEIGHBORS;i++) { if (isThisRowMatching(l2_dest,i)) { // handle roll-over case if (neighbors_vars.neighbors[i].numTx>(0xff-numTxAttempts)) { neighbors_vars.neighbors[i].numWraps++; //counting the number of times that tx wraps. neighbors_vars.neighbors[i].numTx/=2; neighbors_vars.neighbors[i].numTxACK/=2; } // update statistics neighbors_vars.neighbors[i].numTx += numTxAttempts; if (was_finally_acked==TRUE) { neighbors_vars.neighbors[i].numTxACK++; memcpy(&neighbors_vars.neighbors[i].asn,asnTs,sizeof(asn_t)); } break; } } }
/** \brief Indicate I just received a RPL DIO from a neighbor. This function should be called for each received a DIO is received so neighbor routing information in the neighbor table can be updated. The fields which are updated are: - DAGrank \param[in] msg The received message with msg->payload pointing to the DIO header. */ void neighbors_indicateRxDIO(OpenQueueEntry_t* msg) { uint8_t i; uint8_t temp_8b; // take ownership over the packet msg->owner = COMPONENT_NEIGHBORS; // update rank of that neighbor in table neighbors_vars.dio = (icmpv6rpl_dio_ht*)(msg->payload); // retrieve rank temp_8b = *(msg->payload+2); neighbors_vars.dio->rank = (temp_8b << 8) + *(msg->payload+3); if (isNeighbor(&(msg->l2_nextORpreviousHop))==TRUE) { for (i=0;i<MAXNUMNEIGHBORS;i++) { if (isThisRowMatching(&(msg->l2_nextORpreviousHop),i)) { if ( neighbors_vars.dio->rank > neighbors_vars.neighbors[i].DAGrank && neighbors_vars.dio->rank - neighbors_vars.neighbors[i].DAGrank >(DEFAULTLINKCOST*2*MINHOPRANKINCREASE) ) { // the new DAGrank looks suspiciously high, only increment a bit neighbors_vars.neighbors[i].DAGrank += (DEFAULTLINKCOST*2*MINHOPRANKINCREASE); openserial_printError(COMPONENT_NEIGHBORS,ERR_LARGE_DAGRANK, (errorparameter_t)neighbors_vars.dio->rank, (errorparameter_t)neighbors_vars.neighbors[i].DAGrank); } else { neighbors_vars.neighbors[i].DAGrank = neighbors_vars.dio->rank; } break; } } } // update my routing information neighbors_updateMyDAGrankAndNeighborPreference(); }
void neighbors_receiveDIO(OpenQueueEntry_t* msg,icmpv6rpl_dio_t* dio) { uint8_t i; // uint8_t temp_linkCost; msg->owner = COMPONENT_NEIGHBORS; if (isNeighbor(&(msg->l2_nextORpreviousHop))==TRUE) { for (i=0;i<MAXNUMNEIGHBORS;i++) { if (isThisRowMatching(&(msg->l2_nextORpreviousHop),i)) { //neighbors_vars.neighbors[i].DAGrank = *((uint8_t*)(msg->payload)); //poipoi xv is the rang big endian?? neighbors_vars.neighbors[i].DAGrank = dio->rank; // poipoi: single hop /* if (neighbors_vars.neighbors[i].DAGrank==0x00) { neighbors_vars.neighbors[i].parentPreference=MAXPREFERENCE; if (neighbors_vars.neighbors[i].numTxACK==0) { temp_linkCost=15; //TODO: evaluate using RSSI? } else { temp_linkCost=linkcost_calcETX(neighbors_vars.neighbors[i].numTx,neighbors_vars.neighbors[i].numTxACK); } if (idmanager_getIsDAGroot()==FALSE) { neighbors_vars.myDAGrank=neighbors_vars.neighbors[i].DAGrank+temp_linkCost; } } else { neighbors_vars.neighbors[i].parentPreference=0; }*/ break; } } } // poipoi: single hop neighbors_updateMyDAGrankAndNeighborPreference(); }
/** \brief Indicate whether some neighbor is a stable neighbor \param[in] address The address of the neighbor, a full 128-bit IPv6 addres. \returns TRUE if that neighbor is stable, FALSE otherwise. */ bool neighbors_isStableNeighbor(open_addr_t* address) { uint8_t i; open_addr_t temp_addr_64b; open_addr_t temp_prefix; bool returnVal; // by default, not stable returnVal = FALSE; // but neighbor's IPv6 address in prefix and EUI64 switch (address->type) { case ADDR_128B: packetfunctions_ip128bToMac64b(address,&temp_prefix,&temp_addr_64b); break; default: openserial_printCritical(COMPONENT_NEIGHBORS,ERR_WRONG_ADDR_TYPE, (errorparameter_t)address->type, (errorparameter_t)0); return returnVal; } // iterate through neighbor table for (i=0;i<MAXNUMNEIGHBORS;i++) { if (isThisRowMatching(&temp_addr_64b,i) && neighbors_vars.neighbors[i].stableNeighbor==TRUE) { returnVal = TRUE; break; } } return returnVal; }
/** \brief Indicate some (non-ACK) packet was received from a neighbor. This function should be called for each received (non-ACK) packet so neighbor statistics in the neighbor table can be updated. The fields which are updated are: - numRx - rssi - asn - stableNeighbor - switchStabilityCounter \param[in] l2_src MAC source address of the packet, i.e. the neighbor who sent the packet just received. \param[in] rssi RSSI with which this packet was received. \param[in] asnTs ASN at which this packet was received. \param[in] joinPrioPresent Whether a join priority was present in the received packet. \param[in] joinPrio The join priority present in the packet, if any. */ void neighbors_indicateRx(open_addr_t* l2_src, int8_t rssi, asn_t* asnTs, bool joinPrioPresent, uint8_t joinPrio) { uint8_t i; bool newNeighbor; // update existing neighbor newNeighbor = TRUE; for (i=0;i<MAXNUMNEIGHBORS;i++) { if (isThisRowMatching(l2_src,i)) { // this is not a new neighbor newNeighbor = FALSE; // update numRx, rssi, asn neighbors_vars.neighbors[i].numRx++; neighbors_vars.neighbors[i].rssi=rssi; memcpy(&neighbors_vars.neighbors[i].asn,asnTs,sizeof(asn_t)); //update jp if (joinPrioPresent==TRUE){ neighbors_vars.neighbors[i].joinPrio=joinPrio; } // update stableNeighbor, switchStabilityCounter if (neighbors_vars.neighbors[i].stableNeighbor==FALSE) { if (neighbors_vars.neighbors[i].rssi>BADNEIGHBORMAXRSSI) { neighbors_vars.neighbors[i].switchStabilityCounter++; if (neighbors_vars.neighbors[i].switchStabilityCounter>=SWITCHSTABILITYTHRESHOLD) { neighbors_vars.neighbors[i].switchStabilityCounter=0; neighbors_vars.neighbors[i].stableNeighbor=TRUE; } } else { neighbors_vars.neighbors[i].switchStabilityCounter=0; } } else if (neighbors_vars.neighbors[i].stableNeighbor==TRUE) { if (neighbors_vars.neighbors[i].rssi<GOODNEIGHBORMINRSSI) { neighbors_vars.neighbors[i].switchStabilityCounter++; if (neighbors_vars.neighbors[i].switchStabilityCounter>=SWITCHSTABILITYTHRESHOLD) { neighbors_vars.neighbors[i].switchStabilityCounter=0; neighbors_vars.neighbors[i].stableNeighbor=FALSE; } } else { neighbors_vars.neighbors[i].switchStabilityCounter=0; } } // stop looping break; } } // register new neighbor if (newNeighbor==TRUE) { registerNewNeighbor(l2_src, rssi, asnTs, joinPrioPresent,joinPrio); } }
bool isNeighbor(open_addr_t* neighbor) { uint8_t i=0; for (i=0;i<MAXNUMNEIGHBORS;i++) { if (isThisRowMatching(neighbor,i)) { return TRUE; } } return FALSE; }
bool neighbors_isPreferredParent(open_addr_t* address) { uint8_t i; INTERRUPT_DECLARATION(); DISABLE_INTERRUPTS(); for (i=0;i<MAXNUMNEIGHBORS;i++) { if (isThisRowMatching(address,i) && neighbors_vars.neighbors[i].parentPreference==MAXPREFERENCE) { ENABLE_INTERRUPTS(); return TRUE; } } ENABLE_INTERRUPTS(); return FALSE; }
/** \brief Indicate whether some neighbor is a preferred neighbor. \param[in] address The EUI64 address of the neighbor. \returns TRUE if that neighbor is preferred, FALSE otherwise. */ bool neighbors_isPreferredParent(open_addr_t* address) { uint8_t i; bool returnVal; INTERRUPT_DECLARATION(); DISABLE_INTERRUPTS(); // by default, not preferred returnVal = FALSE; // iterate through neighbor table for (i=0;i<MAXNUMNEIGHBORS;i++) { if (isThisRowMatching(address,i) && neighbors_vars.neighbors[i].parentPreference==MAXPREFERENCE) { returnVal = TRUE; break; } } ENABLE_INTERRUPTS(); return returnVal; }
bool neighbors_isStableNeighbor(open_addr_t* address) { uint8_t i; open_addr_t temp_addr_64b; open_addr_t temp_prefix; switch (address->type) { case ADDR_128B: packetfunctions_ip128bToMac64b(address,&temp_prefix,&temp_addr_64b); break; default: openserial_printError(COMPONENT_NEIGHBORS,ERR_WRONG_ADDR_TYPE, (errorparameter_t)address->type, (errorparameter_t)0); return FALSE; } for (i=0;i<MAXNUMNEIGHBORS;i++) { if (isThisRowMatching(&temp_addr_64b,i) && neighbors_vars.neighbors[i].stableNeighbor==TRUE) { return TRUE; } } return FALSE; }
void neighbors_indicateTx(open_addr_t* dest, uint8_t numTxAttempts, bool was_finally_acked, asn_t* asnTimestamp) { uint8_t i=0; if (packetfunctions_isBroadcastMulticast(dest)==FALSE) { for (i=0;i<MAXNUMNEIGHBORS;i++) { if (isThisRowMatching(dest,i)) { if (neighbors_vars.neighbors[i].numTx==255) { neighbors_vars.neighbors[i].numTx/=2; neighbors_vars.neighbors[i].numTxACK/=2; } neighbors_vars.neighbors[i].numTx += numTxAttempts; if (was_finally_acked==TRUE) { neighbors_vars.neighbors[i].numTxACK++; memcpy(&neighbors_vars.neighbors[i].asn,asnTimestamp,sizeof(asn_t)); } return; } } } }
void neighbors_indicateRx(open_addr_t* l2_src, int8_t rssi, asn_t* asnTimestamp) { uint8_t i=0; while (i<MAXNUMNEIGHBORS) { if (isThisRowMatching(l2_src,i)) { neighbors_vars.neighbors[i].numRx++; neighbors_vars.neighbors[i].rssi=rssi; memcpy(&neighbors_vars.neighbors[i].asn,asnTimestamp,sizeof(asn_t)); if (neighbors_vars.neighbors[i].stableNeighbor==FALSE) { if (neighbors_vars.neighbors[i].rssi>BADNEIGHBORMAXRSSI) { neighbors_vars.neighbors[i].switchStabilityCounter++; if (neighbors_vars.neighbors[i].switchStabilityCounter>=SWITCHSTABILITYTHRESHOLD) { neighbors_vars.neighbors[i].switchStabilityCounter=0; neighbors_vars.neighbors[i].stableNeighbor=TRUE; } } else { neighbors_vars.neighbors[i].switchStabilityCounter=0; } } else if (neighbors_vars.neighbors[i].stableNeighbor==TRUE) { if (neighbors_vars.neighbors[i].rssi<GOODNEIGHBORMINRSSI) { neighbors_vars.neighbors[i].switchStabilityCounter++; if (neighbors_vars.neighbors[i].switchStabilityCounter>=SWITCHSTABILITYTHRESHOLD) { neighbors_vars.neighbors[i].switchStabilityCounter=0; neighbors_vars.neighbors[i].stableNeighbor=FALSE; } } else { neighbors_vars.neighbors[i].switchStabilityCounter=0; } } return; } i++; } // this is a new neighbor: register registerNewNeighbor(l2_src, rssi, asnTimestamp); }