/*---------------------------------------------------------------------------*/ uip_ds6_nbr_t * uip_ds6_nbr_add(const uip_ipaddr_t *ipaddr, const uip_lladdr_t *lladdr, uint8_t isrouter, uint8_t state) { uip_ds6_nbr_t *nbr = nbr_table_add_lladdr(ds6_neighbors, (linkaddr_t*)lladdr); if(nbr) { uip_ipaddr_copy(&nbr->ipaddr, ipaddr); nbr->isrouter = isrouter; nbr->state = state; #if UIP_CONF_IPV6_QUEUE_PKT uip_packetqueue_new(&nbr->packethandle); #endif /* UIP_CONF_IPV6_QUEUE_PKT */ /* timers are set separately, for now we put them in expired state */ stimer_set(&nbr->reachable, 0); stimer_set(&nbr->sendns, 0); nbr->nscount = 0; PRINTF("Adding neighbor with ip addr "); PRINT6ADDR(ipaddr); PRINTF(" link addr "); PRINTLLADDR(lladdr); PRINTF(" state %u\n", state); NEIGHBOR_STATE_CHANGED(nbr); return nbr; } else { PRINTF("uip_ds6_nbr_add drop ip addr "); PRINT6ADDR(ipaddr); PRINTF(" link addr (%p) ", lladdr); PRINTLLADDR(lladdr); PRINTF(" state %u\n", state); return NULL; } }
/*---------------------------------------------------------------------------*/ static int parse(struct net_buf *buf) { frame802154_t frame; int hdr_len; hdr_len = frame802154_parse(packetbuf_dataptr(buf), packetbuf_datalen(buf), &frame); if(hdr_len && packetbuf_hdrreduce(buf, hdr_len)) { packetbuf_set_attr(buf, PACKETBUF_ATTR_FRAME_TYPE, frame.fcf.frame_type); if(frame.fcf.dest_addr_mode) { if(frame.dest_pid != mac_src_pan_id && frame.dest_pid != FRAME802154_BROADCASTPANDID) { /* Packet to another PAN */ PRINTF("15.4: for another pan %u (0x%x)\n", frame.dest_pid, frame.dest_pid); return FRAMER_FAILED; } if(!is_broadcast_addr(frame.fcf.dest_addr_mode, frame.dest_addr)) { packetbuf_set_addr(buf, PACKETBUF_ADDR_RECEIVER, (linkaddr_t *)&frame.dest_addr); } } packetbuf_set_addr(buf, PACKETBUF_ADDR_SENDER, (linkaddr_t *)&frame.src_addr); packetbuf_set_attr(buf, PACKETBUF_ATTR_PENDING, frame.fcf.frame_pending); /* packetbuf_set_attr(PACKETBUF_ATTR_RELIABLE, frame.fcf.ack_required);*/ packetbuf_set_attr(buf, PACKETBUF_ATTR_PACKET_ID, frame.seq); #if LLSEC802154_SECURITY_LEVEL if(frame.fcf.security_enabled) { packetbuf_set_attr(buf, PACKETBUF_ATTR_SECURITY_LEVEL, frame.aux_hdr.security_control.security_level); packetbuf_set_attr(buf, PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1, frame.aux_hdr.frame_counter.u16[0]); packetbuf_set_attr(buf, PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3, frame.aux_hdr.frame_counter.u16[1]); #if LLSEC802154_USES_EXPLICIT_KEYS packetbuf_set_attr(buf, PACKETBUF_ATTR_KEY_ID_MODE, frame.aux_hdr.security_control.key_id_mode); packetbuf_set_attr(buf, PACKETBUF_ATTR_KEY_INDEX, frame.aux_hdr.key_index); packetbuf_set_attr(buf, PACKETBUF_ATTR_KEY_SOURCE_BYTES_0_1, frame.aux_hdr.key_source.u16[0]); #endif /* LLSEC802154_USES_EXPLICIT_KEYS */ } #endif /* LLSEC802154_SECURITY_LEVEL */ PRINTF("15.4-IN: %2X ", frame.fcf.frame_type); PRINTLLADDR((const uip_lladdr_t *)packetbuf_addr(buf, PACKETBUF_ADDR_SENDER)); PRINTF(" "); PRINTLLADDR((const uip_lladdr_t *)packetbuf_addr(buf, PACKETBUF_ADDR_RECEIVER)); PRINTF(" %d %u (%u)\n", hdr_len, packetbuf_datalen(buf), packetbuf_totlen(buf)); #ifdef FRAMER_802154_HANDLER if(FRAMER_802154_HANDLER(&frame)) { return FRAMER_FRAME_HANDLED; } #endif return hdr_len; } return FRAMER_FAILED; }
/*---------------------------------------------------------------------------*/ static uint8_t input_packet(struct net_buf *buf) { frame802154_t frame; int len; len = packetbuf_datalen(buf); PRINTF("6MAC: received %d bytes\n", len); if(frame802154_parse(packetbuf_dataptr(buf), len, &frame) && packetbuf_hdrreduce(buf, len - frame.payload_len)) { if(frame.fcf.dest_addr_mode) { if(frame.dest_pid != mac_src_pan_id && frame.dest_pid != FRAME802154_BROADCASTPANDID) { /* Not broadcast or for our PAN */ PRINTF("6MAC: for another pan %u (0x%x)\n", frame.dest_pid, frame.dest_pid); goto error; } if(!is_broadcast_addr(frame.fcf.dest_addr_mode, frame.dest_addr)) { packetbuf_set_addr(buf, PACKETBUF_ADDR_RECEIVER, (linkaddr_t *)&frame.dest_addr); #if !NETSTACK_CONF_BRIDGE_MODE if(!linkaddr_cmp(packetbuf_addr(buf, PACKETBUF_ADDR_RECEIVER), &linkaddr_node_addr)) { /* Not for this node */ PRINTF("6MAC: not for us, we are "); PRINTLLADDR((uip_lladdr_t *)&linkaddr_node_addr); PRINTF(" recipient is "); PRINTLLADDR((uip_lladdr_t *)packetbuf_addr(buf, PACKETBUF_ADDR_RECEIVER)); PRINTF("\n"); goto error; } #endif } } packetbuf_set_addr(buf, PACKETBUF_ADDR_SENDER, (linkaddr_t *)&frame.src_addr); PRINTF("6MAC-IN: type 0x%X sender ", frame.fcf.frame_type); PRINTLLADDR((uip_lladdr_t *)packetbuf_addr(buf, PACKETBUF_ADDR_SENDER)); PRINTF(" receiver "); PRINTLLADDR((uip_lladdr_t *)packetbuf_addr(buf, PACKETBUF_ADDR_RECEIVER)); PRINTF(" len %u\n", packetbuf_datalen(buf)); return NETSTACK_MAC.input(buf); } else { PRINTF("6MAC: failed to parse hdr\n"); } error: return 0; }
/*---------------------------------------------------------------------------*/ 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 */ }
/*---------------------------------------------------------------------------*/ 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 ntp_client_send(struct uip_udp_conn *udpconn, uip_ipaddr_t srv_ipaddr, struct ntp_msg clientmsg) { clientmsg.status = MODE_CLIENT | (NTP_VERSION << 3) | LI_ALARM; clock_get_time(&ts); //TODO: could be in danger when timer change! clientmsg.xmttime.int_partl = uip_htonl(ts.sec + JAN_1970); clientmsg.xmttime.fractionl = uip_htonl(ts.nsec); uip_udp_packet_sendto(udpconn, &clientmsg, sizeof(struct ntp_msg), &srv_ipaddr, UIP_HTONS(SERVER_PORT)); PRINTF("Sent timestamp: %ld sec %ld nsec to ", ts.sec, ts.nsec); #ifdef UIP_CONF_IPV6 PRINT6ADDR(&udpconn->ripaddr); #else PRINTLLADDR(&udpconn->ripaddr); #endif /* UIP_CONF_IPV6 */ PRINTF("\n"); }
/*---------------------------------------------------------------------------*/ 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 */ }
/*---------------------------------------------------------------------------*/ static void set_rime_addr(void) { int i; union { u8_t u8[8]; }eui64; //rimeaddr_t lladdr; int8u *stm32w_eui64 = ST_RadioGetEui64(); { int8u c; for(c = 0; c < 8; c++) { // Copy the EUI-64 to lladdr converting from Little-Endian to Big-Endian. eui64.u8[c] = stm32w_eui64[7 - c]; } } PRINTF("\n\rRadio EUI-64:"); PRINTLLADDR(eui64); PRINTF("\n\r"); #if UIP_CONF_IPV6 memcpy(&uip_lladdr.addr, &eui64, sizeof(uip_lladdr.addr)); #endif #if UIP_CONF_IPV6 rimeaddr_set_node_addr((rimeaddr_t *)&eui64); #else rimeaddr_set_node_addr((rimeaddr_t *)&eui64.u8[8-RIMEADDR_SIZE]); #endif printf("Rime started with address "); for(i = 0; i < sizeof(rimeaddr_t) - 1; i++) { printf("%d.", rimeaddr_node_addr.u8[i]); } printf("%d\n", rimeaddr_node_addr.u8[i]); }
/*---------------------------------------------------------------------------*/ rpl_parent_t * rpl_add_parent(rpl_dag_t *dag, rpl_dio_t *dio, uip_ipaddr_t *addr) { rpl_parent_t *p = NULL; /* Is the parent known by ds6? Drop this request if not. * Typically, the parent is added upon receiving a DIO. */ const uip_lladdr_t *lladdr = uip_ds6_nbr_lladdr_from_ipaddr(addr); PRINTF("RPL: rpl_add_parent lladdr %p ", lladdr); PRINTLLADDR(lladdr); PRINTF(" "); PRINT6ADDR(addr); PRINTF("\n"); if(lladdr != NULL) { /* Add parent in rpl_parents */ p = nbr_table_add_lladdr(rpl_parents, (linkaddr_t *)lladdr); if(p == NULL) { PRINTF("RPL: rpl_add_parent p NULL\n"); } else { uip_ds6_nbr_t *nbr; nbr = rpl_get_nbr(p); p->dag = dag; p->rank = dio->rank; p->dtsn = dio->dtsn; /* Check whether we have a neighbor that has not gotten a link metric yet */ if(nbr != NULL && nbr->link_metric == 0) { nbr->link_metric = RPL_INIT_LINK_METRIC * RPL_DAG_MC_ETX_DIVISOR; } #if RPL_DAG_MC != RPL_DAG_MC_NONE memcpy(&p->mc, &dio->mc, sizeof(p->mc)); #endif /* RPL_DAG_MC != RPL_DAG_MC_NONE */ } } return p; }
/* Attempt to associate to a network form an incoming EB */ static int tsch_associate(const struct input_packet *input_eb, rtimer_clock_t timestamp) { frame802154_t frame; struct ieee802154_ies ies; uint8_t hdrlen; int i; if(input_eb == NULL || tsch_packet_parse_eb(input_eb->payload, input_eb->len, &frame, &ies, &hdrlen, 0) == 0) { PRINTF("TSCH:! failed to parse EB (len %u)\n", input_eb->len); return 0; } current_asn = ies.ie_asn; tsch_join_priority = ies.ie_join_priority + 1; #if TSCH_JOIN_SECURED_ONLY if(frame.fcf.security_enabled == 0) { PRINTF("TSCH:! parse_eb: EB is not secured\n"); return 0; } #endif /* TSCH_JOIN_SECURED_ONLY */ #if TSCH_SECURITY_ENABLED if(!tsch_security_parse_frame(input_eb->payload, hdrlen, input_eb->len - hdrlen - tsch_security_mic_len(&frame), &frame, (linkaddr_t*)&frame.src_addr, ¤t_asn)) { PRINTF("TSCH:! parse_eb: failed to authenticate\n"); return 0; } #endif /* TSCH_SECURITY_ENABLED */ #if !TSCH_SECURITY_ENABLED if(frame.fcf.security_enabled == 1) { PRINTF("TSCH:! parse_eb: we do not support security, but EB is secured\n"); return 0; } #endif /* !TSCH_SECURITY_ENABLED */ #if TSCH_JOIN_MY_PANID_ONLY /* Check if the EB comes from the PAN ID we expect */ if(frame.src_pid != IEEE802154_PANID) { PRINTF("TSCH:! parse_eb: PAN ID %x != %x\n", frame.src_pid, IEEE802154_PANID); return 0; } #endif /* TSCH_JOIN_MY_PANID_ONLY */ /* There was no join priority (or 0xff) in the EB, do not join */ if(ies.ie_join_priority == 0xff) { PRINTF("TSCH:! parse_eb: no join priority\n"); return 0; } /* TSCH timeslot timing */ for(i = 0; i < tsch_ts_elements_count; i++) { if(ies.ie_tsch_timeslot_id == 0) { tsch_timing[i] = US_TO_RTIMERTICKS(tsch_default_timing_us[i]); } else { tsch_timing[i] = US_TO_RTIMERTICKS(ies.ie_tsch_timeslot[i]); } } /* TSCH hopping sequence */ if(ies.ie_channel_hopping_sequence_id == 0) { memcpy(tsch_hopping_sequence, TSCH_DEFAULT_HOPPING_SEQUENCE, sizeof(TSCH_DEFAULT_HOPPING_SEQUENCE)); ASN_DIVISOR_INIT(tsch_hopping_sequence_length, sizeof(TSCH_DEFAULT_HOPPING_SEQUENCE)); } else { if(ies.ie_hopping_sequence_len <= sizeof(tsch_hopping_sequence)) { memcpy(tsch_hopping_sequence, ies.ie_hopping_sequence_list, ies.ie_hopping_sequence_len); ASN_DIVISOR_INIT(tsch_hopping_sequence_length, ies.ie_hopping_sequence_len); } else { PRINTF("TSCH:! parse_eb: hopping sequence too long (%u)\n", ies.ie_hopping_sequence_len); return 0; } } #if TSCH_CHECK_TIME_AT_ASSOCIATION > 0 /* Divide by 4k and multiply again to avoid integer overflow */ uint32_t expected_asn = 4096 * TSCH_CLOCK_TO_SLOTS(clock_time() / 4096, tsch_timing_timeslot_length); /* Expected ASN based on our current time*/ int32_t asn_threshold = TSCH_CHECK_TIME_AT_ASSOCIATION * 60ul * TSCH_CLOCK_TO_SLOTS(CLOCK_SECOND, tsch_timing_timeslot_length); int32_t asn_diff = (int32_t)current_asn.ls4b - expected_asn; if(asn_diff > asn_threshold) { PRINTF("TSCH:! EB ASN rejected %lx %lx %ld\n", current_asn.ls4b, expected_asn, asn_diff); return 0; } #endif #if TSCH_INIT_SCHEDULE_FROM_EB /* Create schedule */ if(ies.ie_tsch_slotframe_and_link.num_slotframes == 0) { #if TSCH_SCHEDULE_WITH_6TISCH_MINIMAL PRINTF("TSCH: parse_eb: no schedule, setting up minimal schedule\n"); tsch_schedule_create_minimal(); #else PRINTF("TSCH: parse_eb: no schedule\n"); #endif } else { /* First, empty current schedule */ tsch_schedule_remove_all_slotframes(); /* We support only 0 or 1 slotframe in this IE */ int num_links = ies.ie_tsch_slotframe_and_link.num_links; if(num_links <= FRAME802154E_IE_MAX_LINKS) { int i; struct tsch_slotframe *sf = tsch_schedule_add_slotframe( ies.ie_tsch_slotframe_and_link.slotframe_handle, ies.ie_tsch_slotframe_and_link.slotframe_size); for(i = 0; i < num_links; i++) { tsch_schedule_add_link(sf, ies.ie_tsch_slotframe_and_link.links[i].link_options, LINK_TYPE_ADVERTISING, &tsch_broadcast_address, ies.ie_tsch_slotframe_and_link.links[i].timeslot, ies.ie_tsch_slotframe_and_link.links[i].channel_offset); } } else { PRINTF("TSCH:! parse_eb: too many links in schedule (%u)\n", num_links); return 0; } } #endif /* TSCH_INIT_SCHEDULE_FROM_EB */ if(tsch_join_priority < TSCH_MAX_JOIN_PRIORITY) { struct tsch_neighbor *n; /* Add coordinator to list of neighbors, lock the entry */ n = tsch_queue_add_nbr((linkaddr_t *)&frame.src_addr); if(n != NULL) { tsch_queue_update_time_source((linkaddr_t *)&frame.src_addr); #ifdef TSCH_CALLBACK_JOINING_NETWORK TSCH_CALLBACK_JOINING_NETWORK(); #endif /* Set PANID */ frame802154_set_pan_id(frame.src_pid); /* Synchronize on EB */ tsch_slot_operation_sync(timestamp - tsch_timing[tsch_ts_tx_offset], ¤t_asn); /* Update global flags */ tsch_is_associated = 1; tsch_is_pan_secured = frame.fcf.security_enabled; /* Association done, schedule keepalive messages */ tsch_schedule_keepalive(); PRINTF("TSCH: association done, sec %u, PAN ID %x, asn-%x.%lx, jp %u, timeslot id %u, hopping id %u, slotframe len %u with %u links, from ", tsch_is_pan_secured, frame.src_pid, current_asn.ms1b, current_asn.ls4b, tsch_join_priority, ies.ie_tsch_timeslot_id, ies.ie_channel_hopping_sequence_id, ies.ie_tsch_slotframe_and_link.slotframe_size, ies.ie_tsch_slotframe_and_link.num_links); PRINTLLADDR((const uip_lladdr_t *)&frame.src_addr); PRINTF("\n"); return 1; } } PRINTF("TSCH:! did not associate.\n"); return 0; }
/*---------------------------------------------------------------------------*/ uip_ds6_nbr_t * uip_ds6_nbr_add(uip_ipaddr_t *ipaddr, uip_lladdr_t *lladdr, uint8_t isrouter, uint8_t state) { int r; r = uip_ds6_list_loop ((uip_ds6_element_t *)uip_ds6_nbr_cache, UIP_DS6_NBR_NB, sizeof(uip_ds6_nbr_t), ipaddr, 128, (uip_ds6_element_t **)&locnbr); if(r == FREESPACE) { locnbr->isused = 1; uip_ipaddr_copy(&locnbr->ipaddr, ipaddr); if(lladdr != NULL) { memcpy(&locnbr->lladdr, lladdr, UIP_LLADDR_LEN); } else { memset(&locnbr->lladdr, 0, UIP_LLADDR_LEN); } locnbr->isrouter = isrouter; locnbr->state = state; #if UIP_CONF_IPV6_QUEUE_PKT uip_packetqueue_new(&locnbr->packethandle); #endif /* UIP_CONF_IPV6_QUEUE_PKT */ /* timers are set separately, for now we put them in expired state */ stimer_set(&locnbr->reachable, 0); stimer_set(&locnbr->sendns, 0); locnbr->nscount = 0; PRINTF("Adding neighbor with ip addr "); PRINT6ADDR(ipaddr); PRINTF("link addr "); PRINTLLADDR((&(locnbr->lladdr))); PRINTF("state %u\n", state); NEIGHBOR_STATE_CHANGED(locnbr); locnbr->last_lookup = clock_time(); return locnbr; } else if(r == NOSPACE) { /* We did not find any empty slot on the neighbor list, so we need to remove one old entry to make room. */ uip_ds6_nbr_t *n, *oldest; clock_time_t oldest_time; oldest = NULL; oldest_time = clock_time(); for(n = uip_ds6_nbr_cache; n < &uip_ds6_nbr_cache[UIP_DS6_NBR_NB]; n++) { if(n->isused) { if(n->last_lookup < oldest_time) { oldest = n; oldest_time = n->last_lookup; } } } if(oldest != NULL) { uip_ds6_nbr_rm(oldest); return uip_ds6_nbr_add(ipaddr, lladdr, isrouter, state); } } PRINTF("uip_ds6_nbr_add drop\n"); return NULL; }
/*---------------------------------------------------------------------------*/ static uint8_t process_request() { uint8_t len; uint8_t count; /* How many did we pack? */ uint8_t i; uint8_t left; uint8_t entry_size; left = VIZTOOL_MAX_PAYLOAD_LEN - 1; len = 2; /* start filling the buffer from position [2] */ count = 0; if(buf[0] == REQUEST_TYPE_ND) { /* Neighbors */ PRINTF("Neighbors\n"); for(i = buf[1]; i < UIP_DS6_NBR_NB; i++) { if(uip_ds6_nbr_cache[i].isused) { entry_size = sizeof(i) + sizeof(uip_ipaddr_t) + sizeof(uip_lladdr_t) + sizeof(uip_ds6_nbr_cache[i].state); PRINTF("%02u: ", i); PRINT6ADDR(&uip_ds6_nbr_cache[i].ipaddr); PRINTF(" - "); PRINTLLADDR(&uip_ds6_nbr_cache[i].lladdr); PRINTF(" - %u\n", uip_ds6_nbr_cache[i].state); memcpy(buf + len, &i, sizeof(i)); len += sizeof(i); memcpy(buf + len, &uip_ds6_nbr_cache[i].ipaddr, sizeof(uip_ipaddr_t)); len += sizeof(uip_ipaddr_t); memcpy(buf + len, &uip_ds6_nbr_cache[i].lladdr, sizeof(uip_lladdr_t)); len += sizeof(uip_lladdr_t); memcpy(buf + len, &uip_ds6_nbr_cache[i].state, sizeof(uip_ds6_nbr_cache[i].state)); len += sizeof(uip_ds6_nbr_cache[i].state); count++; left -= entry_size; if(left < entry_size) { break; } } } } else if(buf[0] == REQUEST_TYPE_RT) { uint32_t flip = 0; PRINTF("Routing table\n"); for(i = buf[1]; i < UIP_DS6_ROUTE_NB; i++) { if(uip_ds6_routing_table[i].isused) { entry_size = sizeof(i) + sizeof(uip_ds6_routing_table[i].ipaddr) + sizeof(uip_ds6_routing_table[i].length) + sizeof(uip_ds6_routing_table[i].metric) + sizeof(uip_ds6_routing_table[i].nexthop) + sizeof(uip_ds6_routing_table[i].state.lifetime) + sizeof(uip_ds6_routing_table[i].state.learned_from); memcpy(buf + len, &i, sizeof(i)); len += sizeof(i); memcpy(buf + len, &uip_ds6_routing_table[i].ipaddr, sizeof(uip_ds6_routing_table[i].ipaddr)); len += sizeof(uip_ds6_routing_table[i].ipaddr); memcpy(buf + len, &uip_ds6_routing_table[i].length, sizeof(uip_ds6_routing_table[i].length)); len += sizeof(uip_ds6_routing_table[i].length); memcpy(buf + len, &uip_ds6_routing_table[i].metric, sizeof(uip_ds6_routing_table[i].metric)); len += sizeof(uip_ds6_routing_table[i].metric); memcpy(buf + len, &uip_ds6_routing_table[i].nexthop, sizeof(uip_ds6_routing_table[i].nexthop)); len += sizeof(uip_ds6_routing_table[i].nexthop); PRINT6ADDR(&uip_ds6_routing_table[i].ipaddr); PRINTF(" - %02x", uip_ds6_routing_table[i].length); PRINTF(" - %02x", uip_ds6_routing_table[i].metric); PRINTF(" - "); PRINT6ADDR(&uip_ds6_routing_table[i].nexthop); flip = uip_htonl(uip_ds6_routing_table[i].state.lifetime); memcpy(buf + len, &flip, sizeof(flip)); len += sizeof(flip); PRINTF(" - %08lx", uip_ds6_routing_table[i].state.lifetime); memcpy(buf + len, &uip_ds6_routing_table[i].state.learned_from, sizeof(uip_ds6_routing_table[i].state.learned_from)); len += sizeof(uip_ds6_routing_table[i].state.learned_from); PRINTF(" - %02x [%u]\n", uip_ds6_routing_table[i].state.learned_from, entry_size); count++; left -= entry_size; if(left < entry_size) { break; } } } } else if (buf[0] == REQUEST_TYPE_DRT) { uint32_t flip = 0; PRINTF("Default Routes\n"); for(i = buf[1]; i < UIP_DS6_DEFRT_NB; i++) { if(uip_ds6_defrt_list[i].isused) { entry_size = sizeof(i) + sizeof(uip_ds6_defrt_list[i].ipaddr) + sizeof(uip_ds6_defrt_list[i].isinfinite); memcpy(buf + len, &i, sizeof(i)); len += sizeof(i); memcpy(buf + len, &uip_ds6_defrt_list[i].ipaddr, sizeof(uip_ds6_defrt_list[i].ipaddr)); len += sizeof(uip_ds6_defrt_list[i].ipaddr); memcpy(buf + len, &uip_ds6_defrt_list[i].isinfinite, sizeof(uip_ds6_defrt_list[i].isinfinite)); len += sizeof(uip_ds6_defrt_list[i].isinfinite); PRINT6ADDR(&uip_ds6_defrt_list[i].ipaddr); PRINTF(" - %u\n", uip_ds6_defrt_list[i].isinfinite); count++; left -= entry_size; if(left < entry_size) { break; } } } } else if (buf[0] == REQUEST_TYPE_ADDR) { PRINTF("Unicast Addresses\n"); for(i = buf[1]; i < UIP_DS6_ADDR_NB; i++) { if(uip_ds6_if.addr_list[i].isused) { entry_size = sizeof(i) + sizeof(uip_ds6_if.addr_list[i].ipaddr); memcpy(buf + len, &i, sizeof(i)); len += sizeof(i); memcpy(buf + len, &uip_ds6_if.addr_list[i].ipaddr, sizeof(uip_ds6_if.addr_list[i].ipaddr)); len += sizeof(uip_ds6_if.addr_list[i].ipaddr); PRINT6ADDR(&uip_ds6_if.addr_list[i].ipaddr); PRINTF("\n"); count++; left -= entry_size; if(left < entry_size) { break; } } } } else if (buf[0] == REQUEST_TYPE_TOTALS) { memset(&buf[2], 0, 4); for(i = 0; i < UIP_DS6_ADDR_NB; i++) { if(uip_ds6_if.addr_list[i].isused) { buf[2]++; } } for(i = 0; i < UIP_DS6_NBR_NB; i++) { if(uip_ds6_nbr_cache[i].isused) { buf[3]++; } } for(i = 0; i < UIP_DS6_ROUTE_NB; i++) { if(uip_ds6_routing_table[i].isused) { buf[4]++; } } for(i = 0; i < UIP_DS6_DEFRT_NB; i++) { if(uip_ds6_defrt_list[i].isused) { buf[5]++; } } len += 4; count = 4; } else { return 0; } buf[1] = count; return len; }
/* Parse a IEEE 802.15.4e TSCH Enhanced Beacon (EB) */ int tsch_packet_parse_eb(const uint8_t *buf, int buf_size, frame802154_t *frame, struct ieee802154_ies *ies, uint8_t *hdr_len, int frame_without_mic) { uint8_t curr_len = 0; int ret; if(frame == NULL || buf_size < 0) { return 0; } /* Parse 802.15.4-2006 frame, i.e. all fields before Information Elements */ if((ret = frame802154_parse((uint8_t *)buf, buf_size, frame)) == 0) { PRINTF("TSCH:! parse_eb: failed to parse frame\n"); return 0; } if(frame->fcf.frame_version < FRAME802154_IEEE802154E_2012 || frame->fcf.frame_type != FRAME802154_BEACONFRAME) { PRINTF("TSCH:! parse_eb: frame is not a valid TSCH beacon. Frame version %u, type %u, FCF %02x %02x\n", frame->fcf.frame_version, frame->fcf.frame_type, buf[0], buf[1]); PRINTF("TSCH:! parse_eb: frame was from 0x%x/", frame->src_pid); PRINTLLADDR((const uip_lladdr_t *)&frame->src_addr); PRINTF(" to 0x%x/", frame->dest_pid); PRINTLLADDR((const uip_lladdr_t *)&frame->dest_addr); PRINTF("\n"); return 0; } if(hdr_len != NULL) { *hdr_len = ret; } curr_len += ret; if(ies != NULL) { memset(ies, 0, sizeof(struct ieee802154_ies)); ies->ie_join_priority = 0xff; /* Use max value in case the Beacon does not include a join priority */ } if(frame->fcf.ie_list_present) { /* Calculate space needed for the security MIC, if any, before attempting to parse IEs */ int mic_len = 0; #if LLSEC802154_ENABLED if(!frame_without_mic) { mic_len = tsch_security_mic_len(frame); if(buf_size < curr_len + mic_len) { return 0; } } #endif /* LLSEC802154_ENABLED */ /* Parse information elements. We need to substract the MIC length, as the exact payload len is needed while parsing */ if((ret = frame802154e_parse_information_elements(buf + curr_len, buf_size - curr_len - mic_len, ies)) == -1) { PRINTF("TSCH:! parse_eb: failed to parse IEs\n"); return 0; } curr_len += ret; } if(hdr_len != NULL) { *hdr_len += ies->ie_payload_ie_offset; } return curr_len; }
/*---------------------------------------------------------------------------*/ uip_ds6_nbr_t * uip_ds6_nbr_add(uip_ipaddr_t * ipaddr, uip_lladdr_t * lladdr, u8_t isrouter, u8_t state) { int r; r = uip_ds6_list_loop ((uip_ds6_element_t *) uip_ds6_nbr_cache, UIP_DS6_NBR_NB, sizeof(uip_ds6_nbr_t), ipaddr, 128, (uip_ds6_element_t **) &locnbr); // printf("r %d\n", r); if(r == FREESPACE) { locnbr->isused = 1; uip_ipaddr_copy(&(locnbr->ipaddr), ipaddr); if(lladdr != NULL) { memcpy(&(locnbr->lladdr), lladdr, UIP_LLADDR_LEN); } else { memset(&(locnbr->lladdr), 0, UIP_LLADDR_LEN); } locnbr->isrouter = isrouter; locnbr->state = state; /* timers are set separately, for now we put them in expired state */ stimer_set(&(locnbr->reachable), 0); stimer_set(&(locnbr->sendns), 0); locnbr->nscount = 0; PRINTF("Adding neighbor with ip addr"); PRINT6ADDR(ipaddr); PRINTF("link addr"); PRINTLLADDR((&(locnbr->lladdr))); PRINTF("state %u\n", state); NEIGHBOR_STATE_CHANGED(locnbr); locnbr->last_lookup = clock_time(); // printf("add %p\n", locnbr); return locnbr; } else if(r == NOSPACE) { /* We did not find any empty slot on the neighbor list, so we need to remove one old entry to make room. */ uip_ds6_nbr_t *n, *oldest; clock_time_t oldest_time; oldest = NULL; oldest_time = clock_time(); for(n = uip_ds6_nbr_cache; n < &uip_ds6_nbr_cache[UIP_DS6_NBR_NB]; n++) { if(n->isused) { if((n->last_lookup < oldest_time) && (uip_ds6_is_nbr_garbage_collectible(n))) { /* We do not want to remove any non-garbage-collectible entry */ oldest = n; oldest_time = n->last_lookup; } } } if(oldest != NULL) { // printf("rm3\n"); uip_ds6_nbr_rm(oldest); locdefrt = uip_ds6_defrt_lookup(&oldest->ipaddr); uip_ds6_defrt_rm(locdefrt); uip_ds6_reg_cleanup_defrt(locdefrt); return uip_ds6_nbr_add(ipaddr, lladdr, isrouter, state); } } PRINTF("uip_ds6_nbr_add drop\n"); return NULL; }
/*---------------------------------------------------------------------------*/ static int create_frame(struct net_buf *buf, int do_create) { frame802154_t params; int hdr_len; /* init to zeros */ memset(¶ms, 0, sizeof(params)); /* Build the FCF. */ params.fcf.frame_type = packetbuf_attr(buf, PACKETBUF_ATTR_FRAME_TYPE); params.fcf.frame_pending = packetbuf_attr(buf, PACKETBUF_ATTR_PENDING); if(packetbuf_holds_broadcast(buf)) { params.fcf.ack_required = 0; } else { params.fcf.ack_required = packetbuf_attr(buf, PACKETBUF_ATTR_MAC_ACK); } params.fcf.panid_compression = 0; /* Insert IEEE 802.15.4 (2006) version bits. */ params.fcf.frame_version = FRAME802154_IEEE802154_2006; #if LLSEC802154_SECURITY_LEVEL if(packetbuf_attr(buf, PACKETBUF_ATTR_SECURITY_LEVEL)) { params.fcf.security_enabled = 1; } /* Setting security-related attributes */ params.aux_hdr.security_control.security_level = packetbuf_attr(buf, PACKETBUF_ATTR_SECURITY_LEVEL); params.aux_hdr.frame_counter.u16[0] = packetbuf_attr(buf, PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1); params.aux_hdr.frame_counter.u16[1] = packetbuf_attr(buf, PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3); #if LLSEC802154_USES_EXPLICIT_KEYS params.aux_hdr.security_control.key_id_mode = packetbuf_attr(buf, PACKETBUF_ATTR_KEY_ID_MODE); params.aux_hdr.key_index = packetbuf_attr(buf, PACKETBUF_ATTR_KEY_INDEX); params.aux_hdr.key_source.u16[0] = packetbuf_attr(buf, PACKETBUF_ATTR_KEY_SOURCE_BYTES_0_1); #endif /* LLSEC802154_USES_EXPLICIT_KEYS */ #endif /* LLSEC802154_SECURITY_LEVEL */ /* Increment and set the data sequence number. */ if(!do_create) { /* Only length calculation - no sequence number is needed and should not be consumed. */ } else if(packetbuf_attr(buf, PACKETBUF_ATTR_MAC_SEQNO)) { params.seq = packetbuf_attr(buf, PACKETBUF_ATTR_MAC_SEQNO); } else { params.seq = framer_802154_next_seqno(); packetbuf_set_attr(buf, PACKETBUF_ATTR_MAC_SEQNO, params.seq); } /* Complete the addressing fields. */ /** \todo For phase 1 the addresses are all long. We'll need a mechanism in the rime attributes to tell the mac to use long or short for phase 2. */ if(LINKADDR_SIZE == 2) { /* Use short address mode if linkaddr size is short. */ params.fcf.src_addr_mode = FRAME802154_SHORTADDRMODE; } else { params.fcf.src_addr_mode = FRAME802154_LONGADDRMODE; } params.dest_pid = mac_dst_pan_id; if(packetbuf_holds_broadcast(buf)) { /* Broadcast requires short address mode. */ params.fcf.dest_addr_mode = FRAME802154_SHORTADDRMODE; params.dest_addr[0] = 0xFF; params.dest_addr[1] = 0xFF; } else { linkaddr_copy((linkaddr_t *)¶ms.dest_addr, packetbuf_addr(buf, PACKETBUF_ADDR_RECEIVER)); /* Use short address mode if linkaddr size is small */ if(LINKADDR_SIZE == 2) { params.fcf.dest_addr_mode = FRAME802154_SHORTADDRMODE; } else { params.fcf.dest_addr_mode = FRAME802154_LONGADDRMODE; } } /* Set the source PAN ID to the global variable. */ params.src_pid = mac_src_pan_id; /* * Set up the source address using only the long address mode for * phase 1. */ linkaddr_copy((linkaddr_t *)¶ms.src_addr, &linkaddr_node_addr); params.payload = packetbuf_dataptr(buf); params.payload_len = packetbuf_datalen(buf); hdr_len = frame802154_hdrlen(¶ms); if(!do_create) { /* Only calculate header length */ return hdr_len; } else if(packetbuf_hdralloc(buf, hdr_len)) { frame802154_create(¶ms, packetbuf_hdrptr(buf), hdr_len); PRINTF("15.4-OUT: %2X ", params.fcf.frame_type); PRINTLLADDR((const uip_lladdr_t *)params.dest_addr); PRINTF(" %d %u (%u)\n", hdr_len, packetbuf_datalen(buf), packetbuf_totlen(buf)); return hdr_len; } else { PRINTF("15.4-OUT: too large header: %u\n", hdr_len); return FRAMER_FAILED; } }
/*---------------------------------------------------------------------------*/ static uint8_t send_packet(struct net_buf *buf, mac_callback_t sent, void *ptr) { frame802154_t params; uint8_t len; uint8_t ret = 0; /* init to zeros */ memset(¶ms, 0, sizeof(params)); /* Build the FCF. */ params.fcf.frame_type = FRAME802154_DATAFRAME; params.fcf.security_enabled = 0; params.fcf.frame_pending = 0; params.fcf.ack_required = packetbuf_attr(buf, PACKETBUF_ATTR_RELIABLE); params.fcf.panid_compression = 0; /* Insert IEEE 802.15.4 (2003) version bit. */ params.fcf.frame_version = FRAME802154_IEEE802154_2003; /* Increment and set the data sequence number. */ params.seq = mac_dsn++; /* Complete the addressing fields. */ /** \todo For phase 1 the addresses are all long. We'll need a mechanism in the rime attributes to tell the mac to use long or short for phase 2. */ params.fcf.src_addr_mode = FRAME802154_LONGADDRMODE; params.dest_pid = mac_dst_pan_id; if(packetbuf_holds_broadcast(buf)) { /* Broadcast requires short address mode. */ params.fcf.dest_addr_mode = FRAME802154_SHORTADDRMODE; params.dest_addr[0] = 0xFF; params.dest_addr[1] = 0xFF; } else { linkaddr_copy((linkaddr_t *)¶ms.dest_addr, packetbuf_addr(buf, PACKETBUF_ADDR_RECEIVER)); params.fcf.dest_addr_mode = FRAME802154_LONGADDRMODE; } /* Set the source PAN ID to the global variable. */ params.src_pid = mac_src_pan_id; /* * Set up the source address using only the long address mode for * phase 1. */ #if NETSTACK_CONF_BRIDGE_MODE linkaddr_copy((linkaddr_t *)¶ms.src_addr,packetbuf_addr(PACKETBUF_ADDR_SENDER)); #else linkaddr_copy((linkaddr_t *)¶ms.src_addr, &linkaddr_node_addr); #endif params.payload = packetbuf_dataptr(buf); params.payload_len = packetbuf_datalen(buf); len = frame802154_hdrlen(¶ms); if(packetbuf_hdralloc(buf, len)) { frame802154_create(¶ms, packetbuf_hdrptr(buf), len); PRINTF("6MAC-UT: type %X dest ", params.fcf.frame_type); PRINTLLADDR((uip_lladdr_t *)params.dest_addr); PRINTF(" len %u datalen %u (totlen %u)\n", len, packetbuf_datalen(buf), packetbuf_totlen(buf)); ret = NETSTACK_RADIO.send(buf, packetbuf_hdrptr(buf), packetbuf_totlen(buf)); if(sent) { switch(ret) { case RADIO_TX_OK: sent(buf, ptr, MAC_TX_OK, 1); break; case RADIO_TX_ERR: sent(buf, ptr, MAC_TX_ERR, 1); break; case RADIO_TX_COLLISION: sent(buf, ptr, MAC_TX_COLLISION, 1); break; } } } else { PRINTF("6MAC-UT: too large header: %u\n", len); } return ret; }