/*---------------------------------------------------------------------------*/ void uip_ds6_link_neighbor_callback(int status, int numtx) { const linkaddr_t *dest = packetbuf_addr(PACKETBUF_ADDR_RECEIVER); if(linkaddr_cmp(dest, &linkaddr_null)) { return; } LINK_NEIGHBOR_CALLBACK(dest, status, numtx); #if UIP_DS6_LL_NUD if(status == MAC_TX_OK) { uip_ds6_nbr_t *nbr; nbr = uip_ds6_nbr_ll_lookup((uip_lladdr_t *)dest); if(nbr != NULL && (nbr->state == NBR_STALE || nbr->state == NBR_DELAY || nbr->state == NBR_PROBE)) { nbr->state = NBR_REACHABLE; stimer_set(&nbr->reachable, UIP_ND6_REACHABLE_TIME / 1000); PRINTF("uip-ds6-neighbor : received a link layer ACK : "); PRINTLLADDR((uip_lladdr_t *)dest); PRINTF(" is reachable.\n"); } } #endif /* UIP_DS6_LL_NUD */ }
/*---------------------------------------------------------------------------*/ uip_ds6_nbr_t * rpl_get_nbr(rpl_parent_t *parent) { linkaddr_t *lladdr = NULL; lladdr = nbr_table_get_lladdr(rpl_parents, parent); if(lladdr != NULL) { return uip_ds6_nbr_ll_lookup((uip_lladdr_t*) lladdr); } else { return NULL; } }
/*---------------------------------------------------------------------------*/ uint16_t rpl_get_parent_link_metric(const uip_lladdr_t *addr) { uip_ds6_nbr_t *nbr; nbr = uip_ds6_nbr_ll_lookup(addr); if(nbr != NULL) { return nbr->link_metric; } else { return 0; } }
uint8_t switch_lookup_get_itf_for(const uip_lladdr_t *lladdr) { #if UIP_SWITCH_LOOKUP if(lladdr != NULL && !linkaddr_cmp((linkaddr_t *)lladdr, &linkaddr_null)) { uip_ds6_nbr_t *nbr; nbr = uip_ds6_nbr_ll_lookup(lladdr); if(nbr) { return nbr->ifindex; } } #endif return NETWORK_ITF_UNKNOWN; }
/*---------------------------------------------------------------------------*/ void neighbor_info_packet_sent(int status, int numtx) { const rimeaddr_t *dest; link_metric_t packet_metric; #if UIP_DS6_LL_NUD uip_ds6_nbr_t *nbr; #endif /* UIP_DS6_LL_NUD */ dest = packetbuf_addr(PACKETBUF_ADDR_RECEIVER); if(rimeaddr_cmp(dest, &rimeaddr_null)) { return; } packet_metric = numtx; PRINTF("neighbor-info: packet sent to %d.%d, status=%d, metric=%u\n", dest->u8[sizeof(*dest) - 2], dest->u8[sizeof(*dest) - 1], status, (unsigned)packet_metric); switch(status) { case MAC_TX_OK: add_neighbor(dest); #if UIP_DS6_LL_NUD nbr = uip_ds6_nbr_ll_lookup((uip_lladdr_t *)dest); if(nbr != NULL && (nbr->state == STALE || nbr->state == DELAY || nbr->state == PROBE)) { nbr->state = REACHABLE; // stimer_set(&nbr->reachable, UIP_ND6_REACHABLE_TIME / 1000); PRINTF("neighbor-info : received a link layer ACK : "); PRINTLLADDR((uip_lladdr_t *)dest); PRINTF(" is reachable.\n"); } #endif /* UIP_DS6_LL_NUD */ break; case MAC_TX_NOACK: add_neighbor(dest); printf("neighbor-info: ETX_NOACK_PENALTY\n"); packet_metric = ETX_NOACK_PENALTY; break; default: /* Do not penalize the ETX when collisions or transmission errors occur. */ return; } update_metric(dest, packet_metric); }
void switch_lookup_learn_addr(const uip_lladdr_t *lladdr, uint8_t ifindex) { #if UIP_SWITCH_LOOKUP if(lladdr != NULL && !linkaddr_cmp((linkaddr_t *)lladdr, &linkaddr_null)) { uip_ds6_nbr_t *nbr; nbr = uip_ds6_nbr_ll_lookup(lladdr); if(nbr) { nbr->ifindex = ifindex; } else { LOG6LBR_LLADDR(PACKET, lladdr, "No neighbor found for "); } } else { LOG6LBR_DEBUG("Can not learn broadcast or null addr\n"); } #endif }
/*---------------------------------------------------------------------------*/ void uip_ds6_link_neighbor_callback(int status, int numtx) { const linkaddr_t *dest = packetbuf_addr(PACKETBUF_ADDR_RECEIVER); if(linkaddr_cmp(dest, &linkaddr_null)) { return; } LINK_NEIGHBOR_CALLBACK(dest, status, numtx); #if UIP_DS6_LL_NUD /* From RFC4861, page 72, last paragraph of section 7.3.3: * * "In some cases, link-specific information may indicate that a path to * a neighbor has failed (e.g., the resetting of a virtual circuit). In * such cases, link-specific information may be used to purge Neighbor * Cache entries before the Neighbor Unreachability Detection would do * so. However, link-specific information MUST NOT be used to confirm * the reachability of a neighbor; such information does not provide * end-to-end confirmation between neighboring IP layers." * * However, we assume that receiving a link layer ack ensures the delivery * of the transmitted packed to the IP stack of the neighbour. This is a * fair assumption and allows battery powered nodes save some battery by * not re-testing the state of a neighbour periodically if it * acknowledges link packets. */ if(status == MAC_TX_OK) { uip_ds6_nbr_t *nbr; nbr = uip_ds6_nbr_ll_lookup((uip_lladdr_t *)dest); if(nbr != NULL && nbr->state != NBR_INCOMPLETE) { nbr->state = NBR_REACHABLE; stimer_set(&nbr->reachable, UIP_ND6_REACHABLE_TIME / 1000); PRINTF("uip-ds6-neighbor : received a link layer ACK : "); PRINTLLADDR((uip_lladdr_t *)dest); PRINTF(" is reachable.\n"); } } #endif /* UIP_DS6_LL_NUD */ }
/*---------------------------------------------------------------------------*/ uip_ipaddr_t * uip_ds6_nbr_ipaddr_from_lladdr(const uip_lladdr_t *lladdr) { uip_ds6_nbr_t *nbr = uip_ds6_nbr_ll_lookup(lladdr); return nbr ? &nbr->ipaddr : NULL; }
void eth_input(void) { int processFrame = 0; //Packet type filtering //--------------------- //Keep only IPv6 traffic if(BUF->type != UIP_HTONS(UIP_ETHTYPE_IPV6)) { LOG6LBR_PRINTF(PACKET, PF_IN, "eth_input: Dropping packet type=0x%04x\n", uip_ntohs(BUF->type)); uip_len = 0; return; } if((UIP_IP_BUF->len[0] << 8) + UIP_IP_BUF->len[1] + 40 < uip_len) { #if CONTIKI_TARGET_NATIVE if(ethernet_has_fcs) { uip_len = (UIP_IP_BUF->len[0] << 8) + UIP_IP_BUF->len[1] + 40; } else #endif { LOG6LBR_PRINTF(PACKET, PF_IN, "eth_input: packet size different than reported in IPv6 header, %d vs %d\n", uip_len, (UIP_IP_BUF->len[0] << 8) + UIP_IP_BUF->len[1] + 40); } } else if((UIP_IP_BUF->len[0] << 8) + UIP_IP_BUF->len[1] + 40 > uip_len) { LOG6LBR_PRINTF(PACKET, PF_IN, "eth_input: packet shorter than reported in IPv6 header, %d vs %d\n", uip_len, (UIP_IP_BUF->len[0] << 8) + UIP_IP_BUF->len[1] + 40); uip_len = 0; return; } //Packet source Filtering //----------------------- /* IPv6 uses 33-33-xx-xx-xx-xx prefix for multicast ND stuff */ if((BUF->dest.addr[0] == 0x33) && (BUF->dest.addr[1] == 0x33)) { processFrame = 1; } else if((BUF->dest.addr[0] == 0xFF) && (BUF->dest.addr[1] == 0xFF) && (BUF->dest.addr[2] == 0xFF) && (BUF->dest.addr[3] == 0xFF) && (BUF->dest.addr[4] == 0xFF) && (BUF->dest.addr[5] == 0xFF)) { /* IPv6 does not use broadcast addresses, hence this should not happen */ LOG6LBR_PRINTF(PACKET, PF_IN, "eth_input: Dropping broadcast packet\n"); uip_len = 0; return; } //Destination filtering //--------------------- if(memcmp((uint8_t *) & eth_mac_addr, BUF->dest.addr, 6) == 0) { processFrame = 1; } else { if(!processFrame) { // Also search our neighbor list to see if we should accept it if(uip_ds6_nbr_ll_lookup((const uip_lladdr_t*)BUF->dest.addr)) { processFrame = 1; } } } //Handle packet //------------- if(processFrame) { LOG6LBR_PRINTF(PACKET, PF_IN, "eth_input: Processing frame\n"); send_to_uip(); } else { printf("eth_input: Dropping frame, not for us or any known node\n"); //Drop packet uip_len = 0; } }