/*---------------------------------------------------------------------------*/ void mac_sequence_register_seqno(void) { int i, j; /* Locate possible previous sequence number for this address. */ for(i = 0; i < MAX_SEQNOS; ++i) { if(linkaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_SENDER), &received_seqnos[i].sender)) { i++; break; } } /* Keep the last sequence number for each address as per 802.15.4e. */ for(j = i - 1; j > 0; --j) { memcpy(&received_seqnos[j], &received_seqnos[j - 1], sizeof(struct seqno)); } received_seqnos[0].seqno = packetbuf_attr(PACKETBUF_ATTR_PACKET_ID); linkaddr_copy(&received_seqnos[0].sender, packetbuf_addr(PACKETBUF_ADDR_SENDER)); }
/*---------------------------------------------------------------------------*/ static void recv_from_abc(struct abc_conn *bc) { rimeaddr_t sender; struct broadcast_conn *c = (struct broadcast_conn *)bc; rimeaddr_copy(&sender, packetbuf_addr(PACKETBUF_ADDR_SENDER)); PRINTF("%d.%d: broadcast: from %d.%d\n", rimeaddr_node_addr.u8[0],rimeaddr_node_addr.u8[1], sender.u8[0], sender.u8[1]); c->u->recv(c, &sender); }
//APP Callback function static void app_recv(void) { PROCESS_CONTEXT_BEGIN(&null_app_process); uint8_t *data = packetbuf_dataptr(); rimeaddr_t *sent_sn_addr = packetbuf_addr(PACKETBUF_ADDR_SENDER); uint8_t rx_sn_id = sent_sn_addr->u8[0]; uint8_t pkt_seq = packetbuf_attr(PACKETBUF_ATTR_PACKET_ID); uint8_t payload_len = packetbuf_datalen(); /* uart1_writeb(rx_sn_id); uart1_writeb(pkt_seq); uart1_writeb(payload_len); */ if(node_id != 0) { printf("%u,%u,%u\n",rx_sn_id,pkt_seq,payload_len); } else { //printf("%u,%u,%u,",rx_sn_id,pkt_seq,payload_len); putchar(rx_sn_id); putchar(pkt_seq); putchar(payload_len); //printf("%u",rx_sn_id); uint8_t i = 0; for(i = 0; i < (payload_len); i++) { //printf("%d,",((data[2*i+1]<<8)|data[2*i])); putchar(data[i]); } } /* for(i = 0; i < payload_len; i++) { uart1_writeb(data[i]); } */ uart1_writeb('\n'); PROCESS_CONTEXT_END(&null_app_process); }
/*---------------------------------------------------------------------------*/ static void input_packet(void) { frame802154_t frame; int len; len = packetbuf_datalen(); if(frame802154_parse(packetbuf_dataptr(), len, &frame) && packetbuf_hdrreduce(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\n", frame.dest_pid); return; } if(!is_broadcast_addr(frame.fcf.dest_addr_mode, frame.dest_addr)) { packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, (rimeaddr_t *)&frame.dest_addr); if(!rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &rimeaddr_node_addr)) { /* Not for this node */ PRINTF("6MAC: not for us\n"); return; } } } packetbuf_set_addr(PACKETBUF_ADDR_SENDER, (rimeaddr_t *)&frame.src_addr); PRINTF("6MAC-IN: %2X", frame.fcf.frame_type); PRINTADDR(packetbuf_addr(PACKETBUF_ADDR_SENDER)); PRINTADDR(packetbuf_addr(PACKETBUF_ADDR_RECEIVER)); PRINTF("%u\n", packetbuf_datalen()); NETSTACK_MAC.input(); } else { PRINTF("6MAC: failed to parse hdr\n"); } }
/*---------------------------------------------------------------------------*/ static void fast_c_packet_sent(int mac_status) { /* Check if our parent just ACKed a DAO */ if(fast_c_parent_knows_us == 0 && mac_status == MAC_TX_OK && packetbuf_attr(PACKETBUF_ATTR_NETWORK_ID) == UIP_PROTO_ICMP6 && packetbuf_attr(PACKETBUF_ATTR_CHANNEL) == (ICMP6_RPL << 8 | RPL_CODE_DAO)) { if(!linkaddr_cmp(&fast_c_parent_linkaddr, &linkaddr_null) && linkaddr_cmp(&fast_c_parent_linkaddr, packetbuf_addr(PACKETBUF_ADDR_RECEIVER))) { fast_c_parent_knows_us = 1; } } }
/*---------------------------------------------------------------------------*/ static int create(void) { struct nullmac_hdr *hdr; if(packetbuf_hdralloc(sizeof(struct nullmac_hdr))) { hdr = packetbuf_hdrptr(); linkaddr_copy(&(hdr->sender), &linkaddr_node_addr); linkaddr_copy(&(hdr->receiver), packetbuf_addr(PACKETBUF_ADDR_RECEIVER)); return sizeof(struct nullmac_hdr); } PRINTF("PNULLMAC-UT: too large header: %u\n", sizeof(struct nullmac_hdr)); return FRAMER_FAILED; }
/*---------------------------------------------------------------------------*/ static int read_packet(void) { frame802154_t frame; int len; packetbuf_clear(); len = radio->read(packetbuf_dataptr(), PACKETBUF_SIZE); if(len > 0) { packetbuf_set_datalen(len); if(frame802154_parse(packetbuf_dataptr(), len, &frame) && packetbuf_hdrreduce(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\n", frame.dest_pid); return 0; } if(!is_broadcast_addr(frame.fcf.dest_addr_mode, frame.dest_addr.u8)) { packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &frame.dest_addr); } } packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &frame.src_addr); PRINTF("6MAC-IN: %2X", frame.fcf.frame_type); PRINTADDR(packetbuf_addr(PACKETBUF_ADDR_SENDER)); PRINTADDR(packetbuf_addr(PACKETBUF_ADDR_RECEIVER)); PRINTF("%u\n", packetbuf_datalen()); return packetbuf_datalen(); } else { PRINTF("6MAC: failed to parse hdr\n"); } } return 0; }
void c_multihop_recv(struct pipe *p, struct stackmodule_i *module) { PRINTF("c_multihop_recv \n"); printaddr(module->stack_id); rimeaddr_t *nexthop = NULL; rimeaddr_t esender, ereceiver; /* Copy the packet attributes to avoid them being overwritten or cleared by an application program that uses the packet buffer for its own needs. */ //rimeaddr_copy(&esender, packetbuf_addr(PACKETBUF_ADDR_ESENDER)); rimeaddr_copy(&ereceiver, packetbuf_addr(PACKETBUF_ADDR_ERECEIVER)); if (rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_ERECEIVER), &rimeaddr_node_addr)) { stack[module->stack_id].resend_flg = 1; PRINTF("for us!\n"); p->multihop_param.hop_no = packetbuf_attr(PACKETBUF_ATTR_HOPS); } else { nexthop = c_forward(p, stack[module->stack_id].amodule, stack[module->stack_id].modno); PRINTF("nexthop: %d.%d \n", nexthop->u8[0], nexthop->u8[1]); packetbuf_set_attr(PACKETBUF_ATTR_HOPS, packetbuf_attr(PACKETBUF_ATTR_HOPS) + 1); if (nexthop) { set_node_addr(module->stack_id, 0, 2, nexthop); PRINTF("forwarding to %d.%d\n", nexthop->u8[0], nexthop->u8[1]); if (module->stack_id < STACKNO) { //stack_send(&stack[module->stack_id], module->module_id); stack_send(&stack[module->stack_id], module->module_id); } } } }
/*---------------------------------------------------------------------------*/ void neighbor_info_packet_received(void) { const rimeaddr_t *src; src = packetbuf_addr(PACKETBUF_ADDR_SENDER); if(rimeaddr_cmp(src, &rimeaddr_null)) { return; } PRINTF("neighbor-info: packet received from %d.%d\n", src->u8[sizeof(*src) - 2], src->u8[sizeof(*src) - 1]); add_neighbor(src); }
/*---------------------------------------------------------------------------*/ 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); }
//APP Callback function static void app_recv(void) { PROCESS_CONTEXT_BEGIN(&null_app_process); #ifdef SF_MOTE_TYPE_AP mpu_data_acc_gyro_union data[SAMPLES_PER_FRAME]; // TX info uint8_t i; rimeaddr_t *sent_sn_addr = packetbuf_addr(PACKETBUF_ADDR_SENDER); uint8_t rx_sn_id = sent_sn_addr->u8[0]; uint8_t pkt_seq = packetbuf_attr(PACKETBUF_ATTR_PACKET_ID); //DATA_SIZE; uint8_t payload_len = packetbuf_datalen(); if(payload_len != MPU_DATA_ACC_GYRO_SIZE*SAMPLES_PER_FRAME) { //printf("Ignore packet %u,%u %u\n",rx_sn_id,pkt_seq,payload_len); //return; memcpy((uint8_t*)data,packetbuf_dataptr(),MPU_DATA_ACC_GYRO_SIZE*SAMPLES_PER_FRAME); } else { memcpy((uint8_t*)data,packetbuf_dataptr(),MPU_DATA_ACC_GYRO_SIZE*SAMPLES_PER_FRAME); } for(i=0;i<SAMPLES_PER_FRAME;i++) { // MPU data mpu_data_acc_gyro_union samples = data[i]; MPU_PRINT_BYTE(rx_sn_id); MPU_PRINT_BYTE(0); MPU_PRINT_BYTE(pkt_seq); MPU_PRINT_BYTE(0); print_mpu_sample_acc_gyro(&samples); MPU_PRINT_BYTE('\n'); } #endif PROCESS_CONTEXT_END(&null_app_process); }
/*---------------------------------------------------------------------------*/ static int select_packet(uint16_t *slotframe, uint16_t *timeslot) { /* Select data packets we have a unicast link to */ const linkaddr_t *dest = packetbuf_addr(PACKETBUF_ADDR_RECEIVER); if(packetbuf_attr(PACKETBUF_ATTR_FRAME_TYPE) == FRAME802154_DATAFRAME && !linkaddr_cmp(dest, &linkaddr_null)) { if(slotframe != NULL) { *slotframe = slotframe_handle; } if(timeslot != NULL) { *timeslot = get_node_timeslot(dest); } return 1; } return 0; }
/** * Input callback called by the lower layers to indicate incoming data */ static void dtn_network_input(void) { linkaddr_t source; uint8_t * buffer = NULL; uint8_t length = 0; packetbuf_attr_t rssi = 0; leds_on(LEDS_ALL); /* Create a copy here, because otherwise packetbuf_clear will evaporate the address */ linkaddr_copy(&source, packetbuf_addr(PACKETBUF_ADDR_SENDER)); buffer = packetbuf_dataptr(); length = packetbuf_datalen(); rssi = packetbuf_attr(PACKETBUF_ATTR_RSSI); convergence_layer_incoming_frame(&source, buffer, length, rssi); leds_off(LEDS_ALL); }
/* Returns the latestForwarded_table_entry pointer to the latestForwardedTable * entry representing the neighbor node address passed as a parameter. If * no such neighbor exists, returns NULL. */ latestForwarded_table_entry* latestForwardedTableFind(rimeaddr_t *neighbor_p) { pmesg(200, "%s :: %s :: Line #%d\n", __FILE__, __func__, __LINE__); static uint8_t i = 0; static bool isBroadcast = 0; isBroadcast = rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &rimeaddr_null); if (isBroadcast) return NULL; for (i = 0; i < latestForwardedTableActive; i++) { if (rimeaddr_cmp(&(latestForwardedTable[i].neighbor), neighbor_p)) break; } if(i == latestForwardedTableActive) return NULL; return &(latestForwardedTable[i]); }
/** * Send a probe packet. */ static void send_probe(void) { struct lpp_hdr *hdr; struct announcement_msg *adata; struct announcement *a; /* Set up the probe header. */ packetbuf_clear(); packetbuf_set_datalen(sizeof(struct lpp_hdr)); hdr = packetbuf_dataptr(); hdr->type = TYPE_PROBE; rimeaddr_copy(&hdr->sender, &rimeaddr_node_addr); rimeaddr_copy(&hdr->receiver, packetbuf_addr(PACKETBUF_ADDR_RECEIVER)); /* Construct the announcements */ adata = (struct announcement_msg *)((char *)hdr + sizeof(struct lpp_hdr)); adata->num = 0; for(a = announcement_list(); a != NULL; a = a->next) { adata->data[adata->num].id = a->id; adata->data[adata->num].value = a->value; adata->num++; } packetbuf_set_datalen(sizeof(struct lpp_hdr) + ANNOUNCEMENT_MSG_HEADERLEN + sizeof(struct announcement_data) * adata->num); /* PRINTF("Sending probe\n");*/ /* printf("probe\n");*/ /* XXX should first check access to the medium (CCA - Clear Channel Assessment) and add LISTEN_TIME to off_time_adjustment if there is a packet in the air. */ radio->send(packetbuf_hdrptr(), packetbuf_totlen()); compower_accumulate(&compower_idle_activity); }
/*---------------------------------------------------------------------------*/ int mac_sequence_is_duplicate(void) { int i; /* * Check for duplicate packet by comparing the sequence number of the incoming * packet with the last few ones we saw. */ for(i = 0; i < MAX_SEQNOS; ++i) { if(linkaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_SENDER), &received_seqnos[i].sender)) { if(packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO) == received_seqnos[i].seqno) { /* Duplicate packet. */ return 1; } break; } } return 0; }
/*---------------------------------------------------------------------------*/ static int send_packet(void) { const rimeaddr_t *addr; addr = packetbuf_addr(PACKETBUF_ADDR_RECEIVER); PRINTF("rime-udp: Sending %d bytes to %d.%d\n", packetbuf_totlen(), addr->u8[RIMEADDR_SIZE-2], addr->u8[RIMEADDR_SIZE-1]); if(rimeaddr_cmp(&rimeaddr_null, addr)) { uip_udp_packet_send(broadcast_conn, packetbuf_hdrptr(), packetbuf_totlen()); } else { uip_ip6addr(&unicast_conn->ripaddr, 0xfe80, 0, 0, 0, 0, 0, 0, 0); uip_netif_addr_autoconf_set(&unicast_conn->ripaddr, (uip_lladdr_t *)addr); uip_udp_packet_send(unicast_conn, packetbuf_hdrptr(), packetbuf_totlen()); uip_create_unspecified(&unicast_conn->ripaddr); } return 1; }
/*---------------------------------------------------------------------------*/ 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 send_packet(mac_callback_t sent_callback, void *ptr) { const rimeaddr_t *addr; addr = packetbuf_addr(PACKETBUF_ADDR_RECEIVER); PRINTF("rime-udp: Sending %d bytes to %d.%d\n", packetbuf_totlen(), addr->u8[0], addr->u8[1]); if(rimeaddr_cmp(&rimeaddr_null, addr)) { uip_udp_packet_send(broadcast_conn, packetbuf_hdrptr(), packetbuf_totlen()); mac_call_sent_callback(sent_callback, ptr, MAC_TX_OK, 1); } else { uip_ip6addr(&unicast_conn->ripaddr, 0xfe80, 0, 0, 0, 0, 0, 0, 0); uip_netif_addr_autoconf_set(&unicast_conn->ripaddr, (uip_lladdr_t *)addr); uip_udp_packet_send(unicast_conn, packetbuf_hdrptr(), packetbuf_totlen()); uip_create_unspecified(&unicast_conn->ripaddr); } return; }
/*---------------------------------------------------------------------------*/ void serial_lprf_mac_rf_input(void) { uint8_t bufCnt, *bufPtr = packetbuf_dataptr(); #if (DEVICE_MODE == SERIAL_LPRF_MAC) uint8_t *addrPtr; #endif PUTSTRING("Data Received : "); PUTSTRING(bufPtr); PUTSTRING("\n"); leds_toggle(LEDS_RED); #if (DEVICE_MODE == SERIAL_LPRF_MAC) putchar(SERIAL_LPRF_MAC_PACKET_START_BYTE); putchar(packetbuf_datalen() + 1 + 8); putchar('R'); addrPtr = (uint8_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER); for(bufCnt = 0; bufCnt < 8; bufCnt++) putchar( * (addrPtr + bufCnt)); for(bufCnt = 0; bufCnt < packetbuf_datalen(); bufCnt++) putchar( * (bufPtr + bufCnt)); #endif }
static int parse_announcements(void) { /* Parse incoming announcements */ struct announcement_msg adata; const rimeaddr_t *from; int i; memcpy(&adata, packetbuf_dataptr(), MIN(packetbuf_datalen(), sizeof(adata))); from = packetbuf_addr(PACKETBUF_ADDR_SENDER); /* printf("%d.%d: probe from %d.%d with %d announcements\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], from->u8[0], from->u8[1], adata.num); */ /* for(i = 0; i < packetbuf_datalen(); ++i) { printf("%02x ", ((uint8_t *)packetbuf_dataptr())[i]); } printf("\n"); */ if(adata.num / sizeof(struct announcement_data) > sizeof(struct announcement_msg)) { /* Sanity check. The number of announcements is too large - corrupt packet has been received. */ return 0; } for(i = 0; i < adata.num; ++i) { /* printf("%d.%d: announcement %d: %d\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], adata.data[i].id, adata.data[i].value); */ announcement_heard(from, adata.data[i].id, adata.data[i].value); } return i; }
/*---------------------------------------------------------------------------*/ static void recv_from_abc(struct abc_conn *bc) { if (bc == NULL) { PRINTF("[pbroadcast.c] Error: ABC Connection is NULL\n"); return; } linkaddr_t sender; struct p_broadcast_conn *c = (struct p_broadcast_conn *)bc; linkaddr_copy(&sender, packetbuf_addr(PACKETBUF_ADDR_SENDER)); uint16_t actual_hash = packet_hash(packetbuf_dataptr(), packetbuf_datalen() - sizeof(uint16_t)); uint8_t *hash_ptr = packetbuf_dataptr() + (uintptr_t)(packetbuf_datalen() - sizeof(uint16_t)); uint16_t transmitted_hash = (hash_ptr[1] << 8) + (hash_ptr[0]); PRINTF("[pbroadcast.c] Received message of size %d from %d.%d.\n", packetbuf_datalen() - sizeof(uint16_t), sender.u8[0], sender.u8[1]); PRINTF("[pbroadcast.c] ^ Data: "); DEBUG_DUMP_DATA(packetbuf_dataptr(), packetbuf_datalen()); PRINTF("\n"); PRINTF("[pbroadcast.c] ^ Hash: %02X\n", transmitted_hash); if (actual_hash != transmitted_hash) { PRINTF("[pbroadcast.c] ^ Incorrect hash (expected %02X, but is %02X); discarding received packet.\n", transmitted_hash, actual_hash); return; } if (c->received) { c->received(c, &sender, packetbuf_dataptr(), packetbuf_datalen() - sizeof(uint16_t)); } }
/*---------------------------------------------------------------------------*/ static void input_packet(void) { static struct ctimer ct; if(!we_are_receiving_burst) { off(); } /* printf("cycle_start 0x%02x 0x%02x\n", cycle_start, cycle_start % CYCLE_TIME);*/ #ifdef NETSTACK_DECRYPT NETSTACK_DECRYPT(); #endif /* NETSTACK_DECRYPT */ if(packetbuf_totlen() > 0 && NETSTACK_FRAMER.parse() >= 0) { #if WITH_CONTIKIMAC_HEADER struct hdr *chdr; chdr = packetbuf_dataptr(); if(chdr->id != CONTIKIMAC_ID) { PRINTF("contikimac: failed to parse hdr (%u)\n", packetbuf_totlen()); return; } packetbuf_hdrreduce(sizeof(struct hdr)); packetbuf_set_datalen(chdr->len); #endif /* WITH_CONTIKIMAC_HEADER */ if(packetbuf_datalen() > 0 && packetbuf_totlen() > 0 && (rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &rimeaddr_node_addr) || rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &rimeaddr_null))) { /* This is a regular packet that is destined to us or to the broadcast address. */ /* If FRAME_PENDING is set, we are receiving a packets in a burst */ we_are_receiving_burst = packetbuf_attr(PACKETBUF_ATTR_PENDING); if(we_are_receiving_burst) { on(); /* Set a timer to turn the radio off in case we do not receive a next packet */ ctimer_set(&ct, INTER_PACKET_DEADLINE, recv_burst_off, NULL); } else { off(); ctimer_stop(&ct); } /* Check for duplicate packet by comparing the sequence number of the incoming packet with the last few ones we saw. */ { int i; for(i = 0; i < MAX_SEQNOS; ++i) { if(packetbuf_attr(PACKETBUF_ATTR_PACKET_ID) == received_seqnos[i].seqno && rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_SENDER), &received_seqnos[i].sender)) { /* Drop the packet. */ /* printf("Drop duplicate ContikiMAC layer packet\n");*/ return; } } for(i = MAX_SEQNOS - 1; i > 0; --i) { memcpy(&received_seqnos[i], &received_seqnos[i - 1], sizeof(struct seqno)); } received_seqnos[0].seqno = packetbuf_attr(PACKETBUF_ATTR_PACKET_ID); rimeaddr_copy(&received_seqnos[0].sender, packetbuf_addr(PACKETBUF_ADDR_SENDER)); } #if CONTIKIMAC_CONF_COMPOWER /* Accumulate the power consumption for the packet reception. */ compower_accumulate(¤t_packet); /* Convert the accumulated power consumption for the received packet to packet attributes so that the higher levels can keep track of the amount of energy spent on receiving the packet. */ compower_attrconv(¤t_packet); /* Clear the accumulated power consumption so that it is ready for the next packet. */ compower_clear(¤t_packet); #endif /* CONTIKIMAC_CONF_COMPOWER */ PRINTDEBUG("contikimac: data (%u)\n", packetbuf_datalen()); NETSTACK_MAC.input(); return; } else { PRINTDEBUG("contikimac: data not for us\n"); } } else { PRINTF("contikimac: failed to parse (%u)\n", packetbuf_totlen()); } }
/*---------------------------------------------------------------------------*/ static int send_packet(mac_callback_t mac_callback, void *mac_callback_ptr, struct rdc_buf_list *buf_list, int is_receiver_awake) { rtimer_clock_t t0; rtimer_clock_t encounter_time = 0; int strobes; uint8_t got_strobe_ack = 0; int hdrlen, len; uint8_t is_broadcast = 0; uint8_t is_reliable = 0; uint8_t is_known_receiver = 0; uint8_t collisions; int transmit_len; int ret; uint8_t contikimac_was_on; uint8_t seqno; #if WITH_CONTIKIMAC_HEADER struct hdr *chdr; #endif /* WITH_CONTIKIMAC_HEADER */ /* Exit if RDC and radio were explicitly turned off */ if(!contikimac_is_on && !contikimac_keep_radio_on) { PRINTF("contikimac: radio is turned off\n"); return MAC_TX_ERR_FATAL; } if(packetbuf_totlen() == 0) { PRINTF("contikimac: send_packet data len 0\n"); return MAC_TX_ERR_FATAL; } #if !NETSTACK_CONF_BRIDGE_MODE /* If NETSTACK_CONF_BRIDGE_MODE is set, assume PACKETBUF_ADDR_SENDER is already set. */ packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &rimeaddr_node_addr); #endif if(rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &rimeaddr_null)) { is_broadcast = 1; PRINTDEBUG("contikimac: send broadcast\n"); if(broadcast_rate_drop()) { return MAC_TX_COLLISION; } } else { #if UIP_CONF_IPV6 PRINTDEBUG("contikimac: send unicast to %02x%02x:%02x%02x:%02x%02x:%02x%02x\n", packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[0], packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[1], packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[2], packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[3], packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[4], packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[5], packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[6], packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[7]); #else /* UIP_CONF_IPV6 */ PRINTDEBUG("contikimac: send unicast to %u.%u\n", packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[0], packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[1]); #endif /* UIP_CONF_IPV6 */ } is_reliable = packetbuf_attr(PACKETBUF_ATTR_RELIABLE) || packetbuf_attr(PACKETBUF_ATTR_ERELIABLE); packetbuf_set_attr(PACKETBUF_ATTR_MAC_ACK, 1); #if WITH_CONTIKIMAC_HEADER hdrlen = packetbuf_totlen(); if(packetbuf_hdralloc(sizeof(struct hdr)) == 0) { /* Failed to allocate space for contikimac header */ PRINTF("contikimac: send failed, too large header\n"); return MAC_TX_ERR_FATAL; } chdr = packetbuf_hdrptr(); chdr->id = CONTIKIMAC_ID; chdr->len = hdrlen; /* Create the MAC header for the data packet. */ hdrlen = NETSTACK_FRAMER.create(); if(hdrlen < 0) { /* Failed to send */ PRINTF("contikimac: send failed, too large header\n"); packetbuf_hdr_remove(sizeof(struct hdr)); return MAC_TX_ERR_FATAL; } hdrlen += sizeof(struct hdr); #else /* Create the MAC header for the data packet. */ hdrlen = NETSTACK_FRAMER.create(); if(hdrlen < 0) { /* Failed to send */ PRINTF("contikimac: send failed, too large header\n"); return MAC_TX_ERR_FATAL; } #endif /* Make sure that the packet is longer or equal to the shortest packet length. */ transmit_len = packetbuf_totlen(); if(transmit_len < SHORTEST_PACKET_SIZE) { /* Pad with zeroes */ uint8_t *ptr; ptr = packetbuf_dataptr(); memset(ptr + packetbuf_datalen(), 0, SHORTEST_PACKET_SIZE - packetbuf_totlen()); PRINTF("contikimac: shorter than shortest (%d)\n", packetbuf_totlen()); transmit_len = SHORTEST_PACKET_SIZE; } packetbuf_compact(); #ifdef NETSTACK_ENCRYPT NETSTACK_ENCRYPT(); #endif /* NETSTACK_ENCRYPT */ transmit_len = packetbuf_totlen(); NETSTACK_RADIO.prepare(packetbuf_hdrptr(), transmit_len); /* Remove the MAC-layer header since it will be recreated next time around. */ packetbuf_hdr_remove(hdrlen); if(!is_broadcast && !is_receiver_awake) { #if WITH_PHASE_OPTIMIZATION ret = phase_wait(&phase_list, packetbuf_addr(PACKETBUF_ADDR_RECEIVER), CYCLE_TIME, GUARD_TIME, mac_callback, mac_callback_ptr, buf_list); if(ret == PHASE_DEFERRED) { return MAC_TX_DEFERRED; } if(ret != PHASE_UNKNOWN) { is_known_receiver = 1; } #endif /* WITH_PHASE_OPTIMIZATION */ } /* By setting we_are_sending to one, we ensure that the rtimer powercycle interrupt do not interfere with us sending the packet. */ we_are_sending = 1; /* If we have a pending packet in the radio, we should not send now, because we will trash the received packet. Instead, we signal that we have a collision, which lets the packet be received. This packet will be retransmitted later by the MAC protocol instread. */ if(NETSTACK_RADIO.receiving_packet() || NETSTACK_RADIO.pending_packet()) { we_are_sending = 0; PRINTF("contikimac: collision receiving %d, pending %d\n", NETSTACK_RADIO.receiving_packet(), NETSTACK_RADIO.pending_packet()); return MAC_TX_COLLISION; } /* Switch off the radio to ensure that we didn't start sending while the radio was doing a channel check. */ off(); strobes = 0; /* Send a train of strobes until the receiver answers with an ACK. */ collisions = 0; got_strobe_ack = 0; /* Set contikimac_is_on to one to allow the on() and off() functions to control the radio. We restore the old value of contikimac_is_on when we are done. */ contikimac_was_on = contikimac_is_on; contikimac_is_on = 1; #if !RDC_CONF_HARDWARE_CSMA /* Check if there are any transmissions by others. */ /* TODO: why does this give collisions before sending with the mc1322x? */ if(is_receiver_awake == 0) { int i; for(i = 0; i < CCA_COUNT_MAX_TX; ++i) { t0 = RTIMER_NOW(); on(); #if CCA_CHECK_TIME > 0 while(RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + CCA_CHECK_TIME)) { } #endif if(NETSTACK_RADIO.channel_clear() == 0) { collisions++; off(); break; } off(); t0 = RTIMER_NOW(); while(RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + CCA_SLEEP_TIME)) { } } } if(collisions > 0) { we_are_sending = 0; off(); PRINTF("contikimac: collisions before sending\n"); contikimac_is_on = contikimac_was_on; return MAC_TX_COLLISION; } #endif /* RDC_CONF_HARDWARE_CSMA */ #if !RDC_CONF_HARDWARE_ACK if(!is_broadcast) { /* Turn radio on to receive expected unicast ack. Not necessary with hardware ack detection, and may trigger an unnecessary cca or rx cycle */ on(); } #endif watchdog_periodic(); t0 = RTIMER_NOW(); seqno = packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO); for(strobes = 0, collisions = 0; got_strobe_ack == 0 && collisions == 0 && RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + STROBE_TIME); strobes++) { watchdog_periodic(); if(!is_broadcast && (is_receiver_awake || is_known_receiver) && !RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + MAX_PHASE_STROBE_TIME)) { PRINTF("miss to %d\n", packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[0]); break; } len = 0; { rtimer_clock_t wt; rtimer_clock_t txtime; int ret; txtime = RTIMER_NOW(); ret = NETSTACK_RADIO.transmit(transmit_len); #if RDC_CONF_HARDWARE_ACK /* For radios that block in the transmit routine and detect the ACK in hardware */ if(ret == RADIO_TX_OK) { if(!is_broadcast) { got_strobe_ack = 1; encounter_time = txtime; break; } } else if (ret == RADIO_TX_NOACK) { } else if (ret == RADIO_TX_COLLISION) { PRINTF("contikimac: collisions while sending\n"); collisions++; } wt = RTIMER_NOW(); while(RTIMER_CLOCK_LT(RTIMER_NOW(), wt + INTER_PACKET_INTERVAL)) { } #else /* RDC_CONF_HARDWARE_ACK */ /* Wait for the ACK packet */ wt = RTIMER_NOW(); while(RTIMER_CLOCK_LT(RTIMER_NOW(), wt + INTER_PACKET_INTERVAL)) { } if(!is_broadcast && (NETSTACK_RADIO.receiving_packet() || NETSTACK_RADIO.pending_packet() || NETSTACK_RADIO.channel_clear() == 0)) { uint8_t ackbuf[ACK_LEN]; wt = RTIMER_NOW(); while(RTIMER_CLOCK_LT(RTIMER_NOW(), wt + AFTER_ACK_DETECTECT_WAIT_TIME)) { } len = NETSTACK_RADIO.read(ackbuf, ACK_LEN); if(len == ACK_LEN && seqno == ackbuf[ACK_LEN - 1]) { got_strobe_ack = 1; encounter_time = txtime; break; } else { PRINTF("contikimac: collisions while sending\n"); collisions++; } } #endif /* RDC_CONF_HARDWARE_ACK */ } } off(); PRINTF("contikimac: send (strobes=%u, len=%u, %s, %s), done\n", strobes, packetbuf_totlen(), got_strobe_ack ? "ack" : "no ack", collisions ? "collision" : "no collision"); #if CONTIKIMAC_CONF_COMPOWER /* Accumulate the power consumption for the packet transmission. */ compower_accumulate(¤t_packet); /* Convert the accumulated power consumption for the transmitted packet to packet attributes so that the higher levels can keep track of the amount of energy spent on transmitting the packet. */ compower_attrconv(¤t_packet); /* Clear the accumulated power consumption so that it is ready for the next packet. */ compower_clear(¤t_packet); #endif /* CONTIKIMAC_CONF_COMPOWER */ contikimac_is_on = contikimac_was_on; we_are_sending = 0; /* Determine the return value that we will return from the function. We must pass this value to the phase module before we return from the function. */ if(collisions > 0) { ret = MAC_TX_COLLISION; } else if(!is_broadcast && !got_strobe_ack) { ret = MAC_TX_NOACK; } else { ret = MAC_TX_OK; } #if WITH_PHASE_OPTIMIZATION if(is_known_receiver && got_strobe_ack) { PRINTF("no miss %d wake-ups %d\n", packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[0], strobes); } if(!is_broadcast) { if(collisions == 0 && is_receiver_awake == 0) { phase_update(&phase_list, packetbuf_addr(PACKETBUF_ADDR_RECEIVER), encounter_time, ret); } } #endif /* WITH_PHASE_OPTIMIZATION */ return ret; }
/*---------------------------------------------------------------------------*/ static int create_frame(int type, int do_create) { frame802154_t params; int hdr_len; /* init to zeros */ memset(¶ms, 0, sizeof(params)); if(!initialized) { initialized = 1; mac_dsn = random_rand() & 0xff; } /* Build the FCF. */ params.fcf.frame_type = packetbuf_attr(PACKETBUF_ATTR_FRAME_TYPE); params.fcf.frame_pending = packetbuf_attr(PACKETBUF_ATTR_PENDING); if(packetbuf_holds_broadcast()) { params.fcf.ack_required = 0; } else { params.fcf.ack_required = packetbuf_attr(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 if(packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL)) { params.fcf.security_enabled = 1; } /* Setting security-related attributes */ params.aux_hdr.security_control.security_level = packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL); params.aux_hdr.frame_counter.u16[0] = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1); params.aux_hdr.frame_counter.u16[1] = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3); #if LLSEC802154_USES_EXPLICIT_KEYS params.aux_hdr.security_control.key_id_mode = packetbuf_attr(PACKETBUF_ATTR_KEY_ID_MODE); params.aux_hdr.key_index = packetbuf_attr(PACKETBUF_ATTR_KEY_INDEX); params.aux_hdr.key_source.u16[0] = packetbuf_attr(PACKETBUF_ATTR_KEY_SOURCE_BYTES_0_1); #endif /* LLSEC802154_USES_EXPLICIT_KEYS */ #endif /* LLSEC802154_SECURITY */ /* 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(PACKETBUF_ATTR_MAC_SEQNO)) { params.seq = packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO); } else { /* Ensure that the sequence number 0 is not used as it would bypass the above check. */ if(mac_dsn == 0) { mac_dsn++; } params.seq = mac_dsn++; packetbuf_set_attr(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()) { /* 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(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, packetbuf_addr(PACKETBUF_ADDR_SENDER)); params.payload = packetbuf_dataptr(); params.payload_len = packetbuf_datalen(); hdr_len = frame802154_hdrlen(¶ms); if(!do_create) { /* Only calculate header length */ return hdr_len; } else if(packetbuf_hdralloc(hdr_len)) { frame802154_create(¶ms, packetbuf_hdrptr()); PRINTF("15.4-OUT: %2X", params.fcf.frame_type); PRINTADDR(params.dest_addr); PRINTF("%d %u (%u)\n", hdr_len, packetbuf_datalen(), packetbuf_totlen()); return hdr_len; } else { PRINTF("15.4-OUT: too large header: %u\n", hdr_len); return FRAMER_FAILED; } }
/*---------------------------------------------------------------------------*/ static void send_packet(mac_callback_t sent, void *ptr) { struct rdc_buf_list *q; struct neighbor_queue *n; static uint8_t initialized = 0; static uint16_t seqno; const rimeaddr_t *addr = packetbuf_addr(PACKETBUF_ADDR_RECEIVER); if(!initialized) { initialized = 1; /* Initialize the sequence number to a random value as per 802.15.4. */ seqno = random_rand(); } if(seqno == 0) { /* PACKETBUF_ATTR_MAC_SEQNO cannot be zero, due to a pecuilarity in framer-802154.c. */ seqno++; } packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, seqno++); /* Look for the neighbor entry */ n = neighbor_queue_from_addr(addr); if(n == NULL) { /* Allocate a new neighbor entry */ n = memb_alloc(&neighbor_memb); if(n != NULL) { /* Init neighbor entry */ rimeaddr_copy(&n->addr, addr); n->transmissions = 0; n->collisions = 0; n->deferrals = 0; /* Init packet list for this neighbor */ LIST_STRUCT_INIT(n, queued_packet_list); /* Add neighbor to the list */ list_add(neighbor_list, n); } } if(n != NULL) { /* Add packet to the neighbor's queue */ q = memb_alloc(&packet_memb); if(q != NULL) { q->ptr = memb_alloc(&metadata_memb); if(q->ptr != NULL) { q->buf = queuebuf_new_from_packetbuf(); if(q->buf != NULL) { struct qbuf_metadata *metadata = (struct qbuf_metadata *)q->ptr; /* Neighbor and packet successfully allocated */ if(packetbuf_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS) == 0) { /* Use default configuration for max transmissions */ metadata->max_transmissions = CSMA_MAX_MAC_TRANSMISSIONS; } else { metadata->max_transmissions = packetbuf_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS); } metadata->sent = sent; metadata->cptr = ptr; if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) == PACKETBUF_ATTR_PACKET_TYPE_ACK) { list_push(n->queued_packet_list, q); } else { list_add(n->queued_packet_list, q); } /* If q is the first packet in the neighbor's queue, send asap */ if(list_head(n->queued_packet_list) == q) { ctimer_set(&n->transmit_timer, 0, transmit_packet_list, n); } return; } memb_free(&metadata_memb, q->ptr); PRINTF("csma: could not allocate queuebuf, dropping packet\n"); } memb_free(&packet_memb, q); PRINTF("csma: could not allocate queuebuf, dropping packet\n"); } /* The packet allocation failed. Remove and free neighbor entry if empty. */ if(list_length(n->queued_packet_list) == 0) { list_remove(neighbor_list, n); memb_free(&neighbor_memb, n); } PRINTF("csma: could not allocate packet, dropping packet\n"); } else { PRINTF("csma: could not allocate neighbor, dropping packet\n"); } mac_call_sent_callback(sent, ptr, MAC_TX_ERR, 1); }
/** * \brief Take a packet received over the 802.15.4 link, and send it * out over ethernet, performing any translations needed. */ void mac_LowpanToEthernet(void) { #if !RF230BB && !RF212BB parsed_frame = sicslowmac_get_frame(); #endif //Setup generic ethernet stuff ETHBUF(uip_buf)->type = uip_htons(UIP_ETHTYPE_IPV6); //Check for broadcast message #if RF230BB || RF212BB if(rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &rimeaddr_null)) { // if(rimeaddr_cmp((const rimeaddr_t *)destAddr, &rimeaddr_null)) { #else if( ( parsed_frame->fcf->destAddrMode == SHORTADDRMODE) && ( parsed_frame->dest_addr->addr16 == 0xffff) ) { #endif ETHBUF(uip_buf)->dest.addr[0] = 0x33; ETHBUF(uip_buf)->dest.addr[1] = 0x33; #if UIP_CONF_IPV6 ETHBUF(uip_buf)->dest.addr[2] = UIP_IP_BUF->destipaddr.u8[12]; ETHBUF(uip_buf)->dest.addr[3] = UIP_IP_BUF->destipaddr.u8[13]; ETHBUF(uip_buf)->dest.addr[4] = UIP_IP_BUF->destipaddr.u8[14]; ETHBUF(uip_buf)->dest.addr[5] = UIP_IP_BUF->destipaddr.u8[15]; #else //Not intended to be functional, but allows ip4 build without errors. ETHBUF(uip_buf)->dest.addr[2] = UIP_IP_BUF->destipaddr.u8[0]; ETHBUF(uip_buf)->dest.addr[3] = UIP_IP_BUF->destipaddr.u8[1]; ETHBUF(uip_buf)->dest.addr[4] = UIP_IP_BUF->destipaddr.u8[2]; ETHBUF(uip_buf)->dest.addr[5] = UIP_IP_BUF->destipaddr.u8[3]; #endif } else { //Otherwise we have a real address mac_createEthernetAddr((uint8_t *) &(ETHBUF(uip_buf)->dest.addr[0]), (uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_RECEIVER)); } #if !UIP_CONF_SIMPLE_JACKDAW_ADDR_TRANS //Source ethernet depends on node if(!mac_createEthernetAddr( (uint8_t *) &(ETHBUF(uip_buf)->src.addr[0]), (uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER) )) #endif { mac_createDefaultEthernetAddr((uint8_t *) &(ETHBUF(uip_buf)->src.addr[0])); } //We only do address translation in network mode! if (usbstick_mode.translate) { //Some IP packets have link layer in them, need to change them around! mac_translateIPLinkLayer(ll_8023_type); } #if UIP_CONF_IPV6_RPL /* We won't play ping-pong with the host! */ if(uip_ipaddr_cmp(&last_sender, &UIP_IP_BUF->srcipaddr)) { PRINTF("siclow_ethernet: Destination off-link but no route\n"); uip_len=0; return; } #endif PRINTF("Low2Eth: Sending packet to ethernet\n\r"); uip_len += UIP_LLH_LEN; if (usbstick_mode.raw == 0) usb_eth_send(uip_buf, uip_len, 1); #if !RF230BB && !RF212BB usb_eth_stat.rxok++; #endif uip_len = 0; } /** * \brief Translate IP packet's possible link-layer addresses, passing * the message to the appropriate higher level function for this * packet (aka: ICMP) * \param target The target we want to end up with - either ll_8023_type * for ethernet, or ll_802154_type for 802.15.4 * \return Returns how successful the translation was * \retval 0 Addresses, if present, were translated. * \retval <0 Negative return values indicate various errors, as defined * by the higher level function. */ int8_t mac_translateIPLinkLayer(lltype_t target) { #if UIP_LLADDR_LEN == 8 if (UIP_IP_BUF->proto == UIP_PROTO_ICMP6) { PRINTF("eth2low: ICMP Message detected\n\r"); return mac_translateIcmpLinkLayer(target); } return 0; #else return 1; #endif } #include "net/uip-icmp6.h" #include "net/uip-nd6.h" typedef struct { uint8_t type; uint8_t length; uint8_t data[16]; } icmp_opts_t; #define UIP_ICMP_BUF ((struct uip_icmp_hdr *)&uip_buf[UIP_LLH_LEN + UIP_IPH_LEN]) #define UIP_ICMP_OPTS(x) ((icmp_opts_t *)&uip_buf[UIP_LLH_LEN + UIP_IPH_LEN + x]) void slide(uint8_t * data, uint8_t length, int16_t slide); /** * \brief Translate the link-layer (L2) addresses in an ICMP packet. * This will just be NA/NS/RA/RS packets currently. * \param target The target we want to end up with - either ll_8023_type * for ethernet, or ll_802154_type for 802.15.4 * \return Returns how successful the translation was * \retval 0 Addresses, if present, were translated. * \retval -1 ICMP message was unknown type, nothing done. * \retval -2 ICMP Length does not make sense? * \retval -3 Unknown 'target' type */ int8_t mac_translateIcmpLinkLayer(lltype_t target) { uint16_t icmp_opt_offset = 0; int16_t len = UIP_IP_BUF->len[1] | (UIP_IP_BUF->len[0] << 8); uint16_t iplen; uint8_t i; int16_t sizechange; uint8_t llbuf[16]; //Figure out offset to start of options switch(UIP_ICMP_BUF->type) { case ICMP6_NS: case ICMP6_NA: icmp_opt_offset = 24; break; case ICMP6_RS: icmp_opt_offset = 8; break; case ICMP6_RA: icmp_opt_offset = 16; break; case ICMP6_REDIRECT: icmp_opt_offset = 40; break; /** Things without link-layer */ case ICMP6_DST_UNREACH: case ICMP6_PACKET_TOO_BIG: case ICMP6_TIME_EXCEEDED: case ICMP6_PARAM_PROB: case ICMP6_ECHO_REQUEST: case ICMP6_ECHO_REPLY: return 0; break; default: return -1; } //Figure out length of options len -= icmp_opt_offset; //Sanity check if (len < 8) return -2; //While we have options to do... while (len >= 8){ //If we have one of these, we have something useful! if (((UIP_ICMP_OPTS(icmp_opt_offset)->type) == UIP_ND6_OPT_SLLAO) || ((UIP_ICMP_OPTS(icmp_opt_offset)->type) == UIP_ND6_OPT_TLLAO) ) { /* Shrinking the buffer may thrash things, so we store the old link-layer address */ for(i = 0; i < (UIP_ICMP_OPTS(icmp_opt_offset)->length*8 - 2); i++) { llbuf[i] = UIP_ICMP_OPTS(icmp_opt_offset)->data[i]; } //Shrink/grow buffer as needed if (target == ll_802154_type) { //Current is 802.3, Hence current link-layer option is 6 extra bytes sizechange = 8; slide(UIP_ICMP_OPTS(icmp_opt_offset)->data + 6, len - 6, sizechange); } else if (target == ll_8023_type) { /* Current is 802.15.4, Hence current link-layer option is 14 extra * bytes. * (Actual LL is 8 bytes, but total option length is in multiples of * 8 Bytes, hence 8 + 2 = 10. Closest is 16 bytes, then 16 bytes for * total optional length - 2 bytes for type + length leaves 14 ) */ sizechange = -8; slide(UIP_ICMP_OPTS(icmp_opt_offset)->data + 14, len - 14, sizechange); } else { return -3; //Uh-oh! } //Translate addresses if (target == ll_802154_type) { mac_createSicslowpanLongAddr(llbuf, (uip_lladdr_t *)UIP_ICMP_OPTS(icmp_opt_offset)->data); } else { #if !UIP_CONF_SIMPLE_JACKDAW_ADDR_TRANS if(!mac_createEthernetAddr(UIP_ICMP_OPTS(icmp_opt_offset)->data, (uip_lladdr_t *)llbuf)) #endif mac_createDefaultEthernetAddr(UIP_ICMP_OPTS(icmp_opt_offset)->data); } //Adjust the length if (target == ll_802154_type) { UIP_ICMP_OPTS(icmp_opt_offset)->length = 2; } else { UIP_ICMP_OPTS(icmp_opt_offset)->length = 1; } //Adjust the IP header length, as well as uIP length iplen = UIP_IP_BUF->len[1] | (UIP_IP_BUF->len[0]<<8); iplen += sizechange; len += sizechange; UIP_IP_BUF->len[1] = (uint8_t)iplen; UIP_IP_BUF->len[0] = (uint8_t)(iplen >> 8); uip_len += sizechange; //We broke ICMP checksum, be sure to fix that UIP_ICMP_BUF->icmpchksum = 0; #if UIP_CONF_IPV6 //allow non ipv6 builds UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum(); #endif //Finally set up next run in while loop len -= 8 * UIP_ICMP_OPTS(icmp_opt_offset)->length; icmp_opt_offset += 8 * UIP_ICMP_OPTS(icmp_opt_offset)->length; } else { //Not an option we care about, ignore it len -= 8 * UIP_ICMP_OPTS(icmp_opt_offset)->length; //This shouldn't happen! if (UIP_ICMP_OPTS(icmp_opt_offset)->length == 0) { PRINTF("Option in ND packet has length zero, error?\n\r"); len = 0; } icmp_opt_offset += 8 * UIP_ICMP_OPTS(icmp_opt_offset)->length; } //If ICMP_OPT is one we care about } //while(len >= 8)
/* * BEACON_SD, BEACON_SD_ACK 보내줌, * BEACON_SD_ACK, 무시 * BEACON_DS, BEACON_DS_ACK 보내줌, c_wait set * BEACON_DS_ACK, 무시 * PREAMBLE, power cycle data wait 모드 * PREAMBLE_ACK, 무시 * PREAMBLE_ACK_DATA 무시 * DATA, app 으로 올림, * DATA_ACK, 끝 아무것도 딱히 안해도됨 * SYNC_START, SYNC_REQ 전송, time stamp 찍어서 * SYNC_REQ, SYNC_ACK 전송, time stamp 찍어서 * SYNC_ACK, SYNC_END 전송, time stamp, app 으로 올려서 계산 * SYNC_END app 으로 올림 */ static void plb_input(void) { if (NETSTACK_FRAMER.parse() >= 0) { if (rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &rimeaddr_node_addr)) { #if DEBUG_PACKET print_packet(packetbuf_dataptr(),packetbuf_datalen()); #endif uint8_t type = ((uint8_t*) packetbuf_dataptr())[0]; PRINTF("plb_input [src: %d.%d] [type: %x]\n", packetbuf_addr(PACKETBUF_ADDR_SENDER)->u8[0],packetbuf_addr(PACKETBUF_ADDR_SENDER)->u8[1], type); printf("plb_input [src: %d.%d] [type: %x]\n", packetbuf_addr(PACKETBUF_ADDR_SENDER)->u8[0],packetbuf_addr(PACKETBUF_ADDR_SENDER)->u8[1], type); switch (type) { case BEACON_SD: // if( a_wait == 0 ){ plb_send_ack(BEACON_SD_ACK); // a_wait = 1; // } break; case BEACON_DS: // if( c_wait == 0 ){ plb_send_ack(BEACON_DS_ACK); c_wait = 1; // }0x80 break; case PREAMBLE: // if (preamble_got == 0) { if (has_data == 0) { plb_send_ack(PREAMBLE_ACK); wait_packet = 1; } else if (has_data == 1) { plb_send_ack(PREAMBLE_ACK_DATA); } // preamble_got = 1; // } break; case DATA: NETSTACK_MAC.input(); plb_send_ack(DATA_ACK); break; case SYNC_START: plb_send_sync(SYNC_REQ); break; case SYNC_REQ: break; case SYNC_ACK: plb_send_sync(SYNC_END); NETSTACK_MAC.input(); break; case SYNC_END: NETSTACK_MAC.input(); break; } } else{ // PRINTF("THIS INPUT IS NOT FOR US\n"); } } }
/*---------------------------------------------------------------------------*/ static int plb_send_data(mac_callback_t sent, void *ptr) { PRINTF("plb_send_data\n"); int ret; //what is it? JJH int last_sent_ok = 0; int acked; int temp=0; acked = 0; if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE)==0) //if packet_type ==0, DATA JJH_START { plb_send_strobe(packetbuf_addr(PACKETBUF_ADDR_NEXT),&acked,PREAMBLE); if(acked==1) { PRINTF("plb_send_data DATA_PREAMBLE_ACKED!\n"); packetbuf_clear(); packetbuf_copyfrom(dataptr_temp,temp_len); if (plb_create_header(packetbuf_addr(PACKETBUF_ADDR_NEXT),DATA) < 0) { PRINTF("ERROR: plb_create_header "); return -1; //ERROR case : -1 } // hold_time(INTER_PACKET_INTERVAL * 5000); //future radio_on(); PRINTF("plb_send_data send DATA packet\n"); print_packet(packetbuf_hdrptr(), packetbuf_totlen()); if(NETSTACK_RADIO.send(packetbuf_hdrptr(), packetbuf_totlen())!=RADIO_TX_OK) { PRINTF("plb_send_data DATA error!\n"); return -1; //ERROR case ret = MAC_TX_ERR; } acked=plb_wait_data_ack(DATA); //just once? if(acked==1) //data ack received { PRINTF("plb_send_data DATA_ACKED!\n"); last_sent_ok=1; ret=MAC_TX_OK; } else if(!acked) { PRINTF("plb_send_data DATA error: no ack!\n"); ret=MAC_TX_ERR; } //sent connect mac_call_sent_callback(sent, ptr, ret, 1); radio_off(); packetbuf_clear(); // add kdw return last_sent_ok; } else if(acked==2)//if receive preamble ack data { PRINTF("PREAMBLE ACK DATA RECEIVED!\n"); } else//do not receive any ack, do nothing { PRINTF("DO NOT RECEIVED PREAMBLE ACK : error!!!\n"); } }//JJH_END return 0; }
/*---------------------------------------------------------------------------*/ int sicslowmac_dataRequest(void) { _delay_ms(SICSLOW_CORRECTION_DELAY); /* create structure to store result. */ frame_create_params_t params; frame_result_t result; /* Save the msduHandle in a global variable. */ msduHandle = packetbuf_attr(PACKETBUF_ATTR_PACKET_ID); /* Build the FCF. */ params.fcf.frameType = DATAFRAME; params.fcf.securityEnabled = false; params.fcf.framePending = false; params.fcf.ackRequired = packetbuf_attr(PACKETBUF_ATTR_RELIABLE); params.fcf.panIdCompression = false; /* Insert IEEE 802.15.4 (2003) version bit. */ params.fcf.frameVersion = IEEE802154_2003; /* Increment and set the data sequence number. */ params.seq = macDSN++; /* 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.srcAddrMode = LONGADDRMODE; params.dest_pid = ieee15_4ManagerAddress.get_dst_panid(); /* * If the output address is NULL in the Rime buf, then it is broadcast * on the 802.15.4 network. */ if(rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &rimeaddr_null) ) { /* Broadcast requires short address mode. */ params.fcf.destAddrMode = SHORTADDRMODE; params.dest_pid = BROADCASTPANDID; params.dest_addr.addr16 = BROADCASTADDR; } else { /* Phase 1.5 - end nodes send to anyone? */ memcpy(¶ms.dest_addr, (uint8_t *)packetbuf_addr(PACKETBUF_ADDR_RECEIVER), LONG_ADDR_LEN); /* Change from sicslowpan byte arrangement to sicslowmac */ byte_reverse((uint8_t*)¶ms.dest_addr.addr64, LONG_ADDR_LEN); /* Phase 1 - end nodes only sends to pan coordinator node. */ /* params.dest_addr.addr64 = ieee15_4ManagerAddress.get_coord_long_addr(); */ params.fcf.destAddrMode = LONGADDRMODE; } /* Set the source PAN ID to the global variable. */ params.src_pid = ieee15_4ManagerAddress.get_src_panid(); /* * Set up the source address using only the long address mode for * phase 1. */ params.src_addr.addr64 = ieee15_4ManagerAddress.get_long_addr(); /* Copy the payload data. */ params.payload_len = packetbuf_datalen(); params.payload = packetbuf_dataptr(); /* Create transmission frame. */ frame_tx_create(¶ms, &result); /* Log if needed */ LOG_FRAME(¶ms, &result); /* Retry up to this many times to send the packet if radio is busy */ uint8_t retry_count = 3; while(retry_count) { PRINTF("sicslowmac: sending packet of length %d to radio, result:", result.length); /* Send data to radio. */ radio_status_t rv = radio_send_data(result.length, result.frame); if (rv == RADIO_SUCCESS) { PRINTF(" Success\n"); return 1; /* True says that the packet could be sent */ } if (rv != RADIO_WRONG_STATE) { PRINTF(" Failed\n"); return 0; } PRINTF(" Radio busy, retrying\n"); /** \todo: Fix delay in sicslowmac so they do not block receiving */ //We have blocking delay here, it is safest this way. BUT doesn't solve the //problem of TX when you are RXing.. as the RX code can't execute! if (retry_count == 3) { _delay_ms(10); } else if (retry_count == 2) { _delay_ms(50); } else if (retry_count == 1) { _delay_ms(200); } retry_count--; } PRINTF("sicslowmac: Unable to send packet, dropped\n"); return 0; }