/*---------------------------------------------------------------------------*/ static void node_packet_received(struct runicast_conn *c, const rimeaddr_t *from, uint8_t seqno) { struct collect_conn *tc = (struct collect_conn *) ((char *)c - offsetof(struct collect_conn, runicast_conn)); int i; /* To protect against forwarding duplicate packets, we keep a list of recently forwarded packet seqnos. If the seqno of the current packet exists in the list, we drop the packet. */ for(i = 0; i < NUM_RECENT_PACKETS; i++) { if(recent_packets[i].seqno == packetbuf_attr(PACKETBUF_ATTR_EPACKET_ID) && rimeaddr_cmp(&recent_packets[i].originator, packetbuf_addr(PACKETBUF_ADDR_ESENDER))) { PRINTF("%d.%d: dropping duplicate packet from %d.%d with seqno %d\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], recent_packets[i].originator.u8[0], recent_packets[i].originator.u8[1], packetbuf_attr(PACKETBUF_ATTR_EPACKET_ID)); /* Drop the packet. */ return; } } recent_packets[recent_packet_ptr].seqno = packetbuf_attr(PACKETBUF_ATTR_EPACKET_ID); rimeaddr_copy(&recent_packets[recent_packet_ptr].originator, packetbuf_addr(PACKETBUF_ADDR_ESENDER)); recent_packet_ptr = (recent_packet_ptr + 1) % NUM_RECENT_PACKETS; if(tc->rtmetric == SINK) { /* If we are the sink, we call the receive function. */ PRINTF("%d.%d: sink received packet from %d.%d via %d.%d\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], packetbuf_addr(PACKETBUF_ADDR_ESENDER)->u8[0], packetbuf_addr(PACKETBUF_ADDR_ESENDER)->u8[1], from->u8[0], from->u8[1]); if(tc->cb->recv != NULL) { tc->cb->recv(packetbuf_addr(PACKETBUF_ADDR_ESENDER), packetbuf_attr(PACKETBUF_ATTR_EPACKET_ID), packetbuf_attr(PACKETBUF_ATTR_HOPS)); } return; } else if(packetbuf_attr(PACKETBUF_ATTR_TTL) > 1 && tc->rtmetric != RTMETRIC_MAX) { /* If we are not the sink, we forward the packet to the best neighbor. */ packetbuf_set_attr(PACKETBUF_ATTR_HOPS, packetbuf_attr(PACKETBUF_ATTR_HOPS) + 1); packetbuf_set_attr(PACKETBUF_ATTR_TTL, packetbuf_attr(PACKETBUF_ATTR_TTL) - 1); PRINTF("%d.%d: packet received from %d.%d via %d.%d, forwarding %d\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], packetbuf_addr(PACKETBUF_ADDR_ESENDER)->u8[0], packetbuf_addr(PACKETBUF_ADDR_ESENDER)->u8[1], from->u8[0], from->u8[1], tc->forwarding); if(packetqueue_enqueue_packetbuf(&forwarding_queue, FORWARD_PACKET_LIFETIME, tc)) { send_queued_packet(); } else { PRINTF("%d.%d: packet dropped: no queue buffer available\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1]); } } return; }
/* ----------------------------------------------------------------------------- * Initialise the uip_server * -------------------------------------------------------------------------- */ void uip_server_init(chanend xtcp[], int num_xtcp, xtcp_ipconfig_t *ipconfig, unsigned char *mac_address) { if (ipconfig != NULL) memcpy(&uip_static_ipconfig, ipconfig, sizeof(xtcp_ipconfig_t)); /* set the mac_adress */ memcpy(&uip_lladdr, mac_address, 6); #if 0 //XXX CHSC: not necessary? Be carefully with erasing the mac address... /* The following line sets the uIP's link-layer address. This must be done * before the tcpip_process is started since in its initialisation * routine the function uip_netif_init() will be called from inside * uip_init()and there the default IPv6 address will be set by combining * the link local prefix (fe80::/64)and the link layer address. */ rimeaddr_copy((rimeaddr_t*) &uip_lladdr.addr, &rimeaddr_node_addr); #endif //TODO chsc: port the rtimer module (if really needed) // /* rtimers needed for radio cycling */ // rtimer_init(); /* Initialise the process module */ process_init(); /* etimers must be started before ctimer_init */ process_start(&etimer_process, NULL); ctimer_init(); /* this calls have to be made before the uip_init * not exactely proved why. CHSC * */ etimer_request_poll(); process_run(); uip_init(); #if UIP_CONF_IPV6 && UIP_CONF_IPV6_RPL rpl_init(); #endif /* UIP_CONF_IPV6_RPL */ #if UIP_IGMP igmp_init(); #endif /* UIP_IGMP */ if (ipconfig != NULL && (*((int*)ipconfig->ipaddr.u8) != 0)) { uip_static_ip = 1; } if (ipconfig == NULL) { uip_ipaddr_t ipaddr; #if UIP_CONF_IPV4 uip_ipaddr(&ipaddr, 0, 0, 0, 0); uip_sethostaddr(&ipaddr); uip_setdraddr(&ipaddr); uip_setnetmask(&ipaddr); #elif UIP_CONF_IPV6 uip_ip6addr(&ipaddr, 0, 0, 0, 0 , 0, 0, 0, 0); #endif /* UIP_CONF_IPVx */ } else { #if UIP_CONF_IPV4 uip_sethostaddr(&ipconfig->ipaddr); uip_setdraddr(&ipconfig->gateway); uip_setnetmask(&ipconfig->netmask); #ifdef XTCP_VERBOSE_DEBUG printf("Address: ");uip_printip4(uip_hostaddr);printf("\n"); printf("Gateway: ");uip_printip4(uip_draddr);printf("\n"); printf("Netmask: ");uip_printip4(uip_netmask);printf("\n"); #endif /* XTCP_VERBOSE_DEBUG */ #elif UIP_CONF_IPV6 #endif /* UIP_CONF_IPVx */ } #if UIP_CONF_IPV4 { #if UIP_USE_AUTOIP int hwsum = mac_address[0] + mac_address[1] + mac_address[2] + mac_address[3] + mac_address[4] + mac_address[5]; autoip_init(hwsum + (hwsum << 16) + (hwsum << 24)); #endif #if UIP_USE_DHCP dhcpc_init(uip_lladdr.addr, 6); #endif } #endif /* UIP_CONF_IPV4 */ xtcpd_init(xtcp, num_xtcp); }
/*---------------------------------------------------------------------------*/ static void send_packet(mac_callback_t sent, void *ptr) { struct rdc_buf_list *q; struct neighbor_queue *n; static uint16_t seqno; const rimeaddr_t *addr = packetbuf_addr(PACKETBUF_ADDR_RECEIVER); 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; //elnaz printf("CSMA_MAX_MAC_TRANSMISSIONS = %d \n",metadata->max_transmissions); } else { metadata->max_transmissions = packetbuf_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS); //elnaz printf("CSMA_MAX_MAC_TRANSMISSIONS = %d \n",metadata->max_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); }
//void sendDataTask() { PROCESS_THREAD(sendDataTask, ev, data) { PROCESS_BEGIN(); while(1) { PROCESS_WAIT_EVENT(); pmesg(200, "%s :: %s :: Line #%d\n", __FILE__, __func__, __LINE__); static fe_queue_entry_t* qe; static fe_queue_entry_t* nullQe; static message_wrapper_t* nullMsg; static bcp_data_header_t* nullHdr; static int subsendResult; static error_t retVal; static uint8_t payloadLen; static rimeaddr_t dest; static message_wrapper_t* hdr; static uint32_t sendTime; static uint32_t checksum; checksum = 0; // Specialty handling of loopback or sudden sink designation if(rootControl_isRoot()) { sending = false; // If we are sending we'll abort if(sendQeOccupied == true) { qe = sendQe; sendQeOccupied = false; // Guaranteed succcessful service } else { if(list_length(send_stack) == 0 && virtualQueueSize == 0) { //This shouldn't be possible pmesg(10, "FAILURE IN BCP_FORWARDING_ENGINE.c SENDDATATASK()"); continue; } qe = sendQe = list_pop(send_stack); } memcpy(loopbackMsgPtr, qe -> msg, sizeof(message_wrapper_t)); //Deallocate the message in qe list_remove(message_pool, qe -> msg); memb_free(&message_pool_mem, qe -> msg); //Deallocate the qe object list_remove(q_entry_pool, qe); memb_free(&q_entry_pool_mem, qe); //Signal the event if(ev_msg_receive != NULL) loopbackMsgPtr = ev_msg_receive(loopbackMsgPtr); //Maybe do it again, if we are sink and there are data packets forwarderActivity(); continue; } if(sendQeOccupied == true) { qe = sendQe; } else { if(list_length(send_stack) == 0 && virtualQueueSize == 0) { pmesg(10, "ERROR: BcpForwardingEngine sendDataTask()\n"); continue; } //Check to see whether there exists a neighbor to route to with positive weight. retVal = routerForwarder_updateRouting(list_length(send_stack) + sendQeOccupied + virtualQueueSize); //NO_SNOOP: add another retVal response type, //if there is no entry in our routing table //request a RR beacon if(retVal == ESIZE) { sending = false; pmesg(200, "DEBUG: RR Beacon Send\n"); beaconType = RR_BEACON; process_post(&sendBeaconTask, NULL, NULL); //Stop the timer, reset it. We have two, one for keeping time, // one for the function call back ctimer_stop(&txRetryTimer); ctimer_set(&txRetryTimer, REROUTE_TIME, tx_retry_timer_fired, NULL); timer_reset(&txRetryTimerTime); continue; } if(retVal == FAIL) { //No neighbor is a good option right now, wait on a recompute-time sending = false; ctimer_stop(&txRetryTimer); ctimer_set(&txRetryTimer, REROUTE_TIME, tx_retry_timer_fired, NULL); timer_reset(&txRetryTimerTime); continue; } if(list_length(send_stack) == 0) { // Create a null packet, place it on the stack (must be here by virtue of a virtual backlog) nullQe = memb_alloc(&q_entry_pool_mem); if(nullQe == NULL) { pmesg(10, "ERROR: BcpForwardingEngine - sendDataTask. Cannot enqueue nullQe\n"); continue; } list_add(q_entry_pool, nullQe); nullMsg = memb_alloc(&message_pool_mem); if(nullMsg == NULL) { pmesg(10, "ERROR: BcpForwardingEngine - sendDataTask. Cannot enqueue nullMsg\n"); //Deallocate list_remove(q_entry_pool, nullQe); memb_free(&q_entry_pool_mem, nullQe); continue; } list_add(message_pool, nullMsg); nullHdr = &(nullMsg -> bcp_data_header); nullHdr -> hopCount = 0; rimeaddr_copy(&(nullHdr -> origin), &rimeaddr_node_addr); nullHdr -> originSeqNo = nullSeqNo++; nullHdr -> bcpDelay = 0; nullHdr -> txCount = 0; nullHdr -> pktType = PKT_NULL; nullQe -> arrivalTime = 0; //call DelayPacketTimer.getNow(); nullQe -> firstTxTime = 0; nullQe -> bcpArrivalDelay = 0; nullQe -> msg = nullMsg; nullQe -> source = LOCAL_SEND; nullQe -> txCount = 0; list_push(send_stack, nullQe); virtualQueueSize--; } qe = sendQe = list_pop(send_stack); pmesg(10, "SENDING MESSAGE ORIGINATING FROM = %d.%d\n", qe -> msg -> bcp_data_header.origin.u8[0], qe -> msg -> bcp_data_header.origin.u8[1]); qe -> firstTxTime = timer_remaining(&txRetryTimerTime); //call txRetryTimer.getNow(); sendQeOccupied = true; } //End else // payloadLen = sizeof(qe -> msg); //call SubPacket.payloadLength(qe->msg); // Give up on a link after MAX_RETX_ATTEMPTS retransmit attempts, link is lousy! // Furthermore, penalize by double MAX_RETX_ATTEMPTS, due to cutoff. if(qe -> txCount >= MAX_RETX_ATTEMPTS) { static bool isBroadcast = 0; isBroadcast = rimeaddr_cmp(&(qe -> msg -> from), &rimeaddr_null); routerForwarder_updateLinkSuccess(&(qe -> msg -> from), isBroadcast, 2*MAX_RETX_ATTEMPTS); //call RouterForwarderIF.updateLinkSuccess(call AMDataPacket.destination(qe->msg), 2*MAX_RETX_ATTEMPTS); // call BcpDebugIF.reportValues( 0,0,0,0,0,MAX_RETX_ATTEMPTS, call AMDataPacket.destination(qe->msg),0x77 ); qe -> txCount = 0; // Place back on the Stack, discard element if necesary conditionalFQDiscard(); list_push(send_stack, qe); // retVal = call SendStack.pushTop( qe ); sendQeOccupied = false; // Try again after a REROUTE_TIME, this choice was bad. sending = false; ctimer_stop(&txRetryTimer); ctimer_set(&txRetryTimer, REROUTE_TIME, tx_retry_timer_fired, NULL); timer_reset(&txRetryTimerTime); continue; } qe -> txCount++; localTXCount++; rimeaddr_copy(&dest, &nextHopAddress_m); //Request an ack, not going to support DL without ack (for now) //Store the local backpressure level to the backpressure field hdr = qe -> msg; //getHeader(qe->msg); hdr -> bcp_data_header.bcpBackpressure = list_length(send_stack) + sendQeOccupied + virtualQueueSize; //Fill in the next hop Backpressure value hdr -> bcp_data_header.nhBackpressure = nextHopBackpressure_m; //Fill in the node tx count field (burst success detection by neighbors #ifndef BEACON_ONLY hdr -> bcp_data_header.nodeTxCount = localTXCount; // Fill in the burstNotifyAddr, then reset to TOS_NODE_ID immediately rimeaddr_copy(&(hdr->bcp_data_header.burstNotifyAddr), ¬ifyBurstyLinkNeighbor_m); rimeaddr_copy(¬ifyBurstyLinkNeighbor_m, &rimeaddr_node_addr); #endif //Update the txCount field hdr -> bcp_data_header.txCount = hdr -> bcp_data_header.txCount + 1; sendTime = 0; //This timer is never implemented in TinyOS: timer_remaining(&delayPacketTimer); //regardless of transmission history, lastTxTime and BcpDelay are re-comptued. hdr -> bcp_data_header.bcpDelay = qe -> bcpArrivalDelay + (sendTime - qe -> arrivalTime) + PER_HOP_MAC_DLY; //Calculate the checksum! checksum = calcHdrChecksum(qe -> msg); hdr -> bcp_data_header.hdrChecksum = checksum; // #ifdef LOW_POWER_LISTENING // // call LowPowerListening.setRxSleepInterval(qe->msg, LPL_SLEEP_INTERVAL_MS); // call LowPowerListening.setRemoteWakeupInterval(qe->msg, LPL_SLEEP_INTERVAL_MS); // #endif //Send thge packet!! rimeaddr_copy(&(qe -> msg -> to), &dest); rimeaddr_copy(&(qe -> msg -> from), &rimeaddr_node_addr); payloadLen = sizeof(message_wrapper_t); //call SubPacket.payloadLength(qe->msg); packetbuf_clear(); packetbuf_set_datalen(payloadLen); packetbuf_copyfrom(qe -> msg, payloadLen); pmesg(10, "Checksum from packet about to send: %u\n", ((message_wrapper_t*)packetbuf_dataptr()) -> bcp_data_header.hdrChecksum); //Non-zero if the packet could be sent, zero otherwise subsendResult = unicast_send(&unicast, &dest); //Success if(subsendResult != 0) { // Successfully submitted to the data-link layer. pmesg(100, "BcpForwardingEngine: Successfully Sent Unicast Message\n"); //Print out end-to-end message only if packet is originating from here if(rimeaddr_cmp(&(qe -> msg -> from), &(qe -> msg -> bcp_data_header.origin)) != 0) printf("Sent Packet from: %d.%d with SequenceNum = %lu\n", qe -> msg -> bcp_data_header.origin.u8[0], qe -> msg -> bcp_data_header.origin.u8[1], qe -> msg -> bcp_data_header.packetSeqNum); continue; } else { pmesg(100, "BcpForwardingEngine: Failed to Send Unicast Message. Trying again\n"); // radioOn = false; // NO_SNOOP: set beacon type beaconType = NORMAL_BEACON; process_post(&sendDataTask, NULL, NULL); } } //End while(1) PROCESS_END(); }
/*---------------------------------------------------------------------------*/ message_wrapper_t* subReceive_receive(message_wrapper_t* msg) { pmesg(200, "%s :: %s :: Line #%d\n", __FILE__, __func__, __LINE__); static rimeaddr_t from; static bcp_data_header_t * rcvPacket; static uint32_t checksum; static latestForwarded_table_entry *latestForwardedEntry; static uint32_t arrivalTime; //uint32_t arrivalTime = call DelayPacketTimer.getNow(); checksum = 0; arrivalTime = 0; /* * A packet arrived destined to this AM_ADDR. Handle bcpBackpressure update to * the routing engine. If we are the root, signal the receive event. Otherwise * we place the packet into the forwarding queue. */ // Grab the backpressure value and send it to the router rimeaddr_copy(&from, &(msg -> from)); rcvPacket = &(msg -> bcp_data_header); // Calculate the checksum! checksum = calcHdrChecksum(msg); //Checksum and origin checks static uint32_t sentChecksum; static bcp_data_header_t hdr; hdr = msg -> bcp_data_header; sentChecksum = hdr.hdrChecksum; pmesg(200, "Calculated Checksum = %lu\n", checksum); pmesg(200, "Sent Checksum = %lu\n", sentChecksum); // Verify checksum! if(checksum != sentChecksum) { // Packet header failed checksum! // I'm going to continue forwarding it, but disregard the control // information. dataCRCFailCount++; // NO_SNOOP: remove snoop pmesg(10, "BcpForwardingEngine Data CRC Failure\n"); // ---------------------------------------------- // We cannot afford to forward corrupted messages, they can lead to bad behaviors return msg; } else { dataCRCSuccessCount++; // Grab the latestForwardedEntry for this neighbor latestForwardedEntry = latestForwardedTableFind(&from); if(latestForwardedEntry == NULL) { // Update the latestForwardedTable, this neighbor is unknown latestForwardedTableUpdate(&from, &(rcvPacket -> origin), rcvPacket -> originSeqNo, rcvPacket -> hopCount); } else if((rimeaddr_cmp(&(latestForwardedEntry -> origin), &(rcvPacket->origin)) != 0) && latestForwardedEntry -> originSeqNo == rcvPacket -> originSeqNo && latestForwardedEntry -> hopCount == rcvPacket -> hopCount) { /** * Duplicate suppresion * We will store the last source / packetid / hop count receive per neighbor * and reject any new arrival from that neighbor with identical parameters. * This allows packets with identical source / packetid to be forwarded * through a node multiple times - necessary in a dynamic routing scenario. */ pmesg(10, "Duplicate packets\n"); return msg; } else { // Update the latestForwardedTable latestForwardedTableUpdate(&from, &(rcvPacket->origin), rcvPacket->originSeqNo, rcvPacket->hopCount); } // Update the backpressure information in the router bool isBroadcast = rimeaddr_cmp(&(msg -> to), &rimeaddr_null) != 0; routerForwarder_updateNeighborBackpressure(&from, isBroadcast, rcvPacket -> bcpBackpressure); } // Retrieve the hopCount, increment it in the header rcvPacket->hopCount++; // If I'm the root, signal receive. if (rootControl_isRoot()) { if(ev_msg_receive != NULL) return ev_msg_receive(msg); } else { pmesg(100, "BcpForwardingEngine: Forwarding Packet\n"); return forward(msg, arrivalTime); } return msg; }
/*---------------------------------------------------------------------------*/ static int send_packet(void) { rtimer_clock_t t0; rtimer_clock_t t; rtimer_clock_t encounter_time = 0; int strobes; struct xmac_hdr *hdr; int got_strobe_ack = 0; uint8_t strobe[MAX_STROBE_SIZE]; int strobe_len, len; int is_broadcast = 0; int is_reliable; struct encounter *e; struct queuebuf *packet; int is_already_streaming = 0; uint8_t collisions; /* Create the X-MAC header for the data packet. */ packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &rimeaddr_node_addr); if(rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &rimeaddr_null)) { is_broadcast = 1; PRINTDEBUG("xmac: send broadcast\n"); } else { #if UIP_CONF_IPV6 PRINTDEBUG("xmac: 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 PRINTDEBUG("xmac: 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); len = NETSTACK_FRAMER.create(); strobe_len = len + sizeof(struct xmac_hdr); if(len == 0 || strobe_len > sizeof(strobe)) { /* Failed to send */ PRINTF("xmac: send failed, too large header\n"); return MAC_TX_ERR_FATAL; } memcpy(strobe, packetbuf_hdrptr(), len); strobe[len] = DISPATCH; /* dispatch */ strobe[len + 1] = TYPE_STROBE; /* type */ packetbuf_compact(); packet = queuebuf_new_from_packetbuf(); if(packet == NULL) { /* No buffer available */ PRINTF("xmac: send failed, no queue buffer available (of %u)\n", QUEUEBUF_CONF_NUM); return MAC_TX_ERR; } #if WITH_STREAMING if(is_streaming == 1 && (rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &is_streaming_to) || rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &is_streaming_to_too))) { is_already_streaming = 1; } if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) == PACKETBUF_ATTR_PACKET_TYPE_STREAM) { is_streaming = 1; if(rimeaddr_cmp(&is_streaming_to, &rimeaddr_null)) { rimeaddr_copy(&is_streaming_to, packetbuf_addr(PACKETBUF_ADDR_RECEIVER)); } else if(!rimeaddr_cmp(&is_streaming_to, packetbuf_addr(PACKETBUF_ADDR_RECEIVER))) { rimeaddr_copy(&is_streaming_to_too, packetbuf_addr(PACKETBUF_ADDR_RECEIVER)); } stream_until = RTIMER_NOW() + DEFAULT_STREAM_TIME; } #endif /* WITH_STREAMING */ off(); #if WITH_ENCOUNTER_OPTIMIZATION /* We go through the list of encounters to find if we have recorded an encounter with this particular neighbor. If so, we can compute the time for the next expected encounter and setup a ctimer to switch on the radio just before the encounter. */ for(e = list_head(encounter_list); e != NULL; e = list_item_next(e)) { const rimeaddr_t *neighbor = packetbuf_addr(PACKETBUF_ADDR_RECEIVER); if(rimeaddr_cmp(neighbor, &e->neighbor)) { rtimer_clock_t wait, now, expected; /* We expect encounters to happen every DEFAULT_PERIOD time units. The next expected encounter is at time e->time + DEFAULT_PERIOD. To compute a relative offset, we subtract with clock_time(). Because we are only interested in turning on the radio within the DEFAULT_PERIOD period, we compute the waiting time with modulo DEFAULT_PERIOD. */ now = RTIMER_NOW(); wait = ((rtimer_clock_t)(e->time - now)) % (DEFAULT_PERIOD); expected = now + wait - 2 * DEFAULT_ON_TIME; #if WITH_ACK_OPTIMIZATION /* Wait until the receiver is expected to be awake */ if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) != PACKETBUF_ATTR_PACKET_TYPE_ACK && is_streaming == 0) { /* Do not wait if we are sending an ACK, because then the receiver will already be awake. */ while(RTIMER_CLOCK_LT(RTIMER_NOW(), expected)); } #else /* WITH_ACK_OPTIMIZATION */ /* Wait until the receiver is expected to be awake */ while(RTIMER_CLOCK_LT(RTIMER_NOW(), expected)); #endif /* WITH_ACK_OPTIMIZATION */ } } #endif /* WITH_ENCOUNTER_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; t0 = RTIMER_NOW(); strobes = 0; LEDS_ON(LEDS_BLUE); /* Send a train of strobes until the receiver answers with an ACK. */ /* Turn on the radio to listen for the strobe ACK. */ on(); collisions = 0; if(!is_already_streaming) { watchdog_stop(); got_strobe_ack = 0; t = RTIMER_NOW(); for(strobes = 0, collisions = 0; got_strobe_ack == 0 && collisions == 0 && RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + xmac_config.strobe_time); strobes++) { while(got_strobe_ack == 0 && RTIMER_CLOCK_LT(RTIMER_NOW(), t + xmac_config.strobe_wait_time)) { rtimer_clock_t now = RTIMER_NOW(); /* See if we got an ACK */ packetbuf_clear(); len = NETSTACK_RADIO.read(packetbuf_dataptr(), PACKETBUF_SIZE); if(len > 0) { packetbuf_set_datalen(len); if(NETSTACK_FRAMER.parse()) { hdr = packetbuf_dataptr(); if(hdr->dispatch == DISPATCH && hdr->type == TYPE_STROBE_ACK) { if(rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &rimeaddr_node_addr)) { /* We got an ACK from the receiver, so we can immediately send the packet. */ got_strobe_ack = 1; encounter_time = now; } else { PRINTDEBUG("xmac: strobe ack for someone else\n"); } } else /*if(hdr->dispatch == DISPATCH && hdr->type == TYPE_STROBE)*/ { PRINTDEBUG("xmac: strobe from someone else\n"); collisions++; } } else { PRINTF("xmac: send failed to parse %u\n", len); } } } t = RTIMER_NOW(); /* Send the strobe packet. */ if(got_strobe_ack == 0 && collisions == 0) { if(is_broadcast) { #if WITH_STROBE_BROADCAST NETSTACK_RADIO.send(strobe, strobe_len); #else /* restore the packet to send */ queuebuf_to_packetbuf(packet); NETSTACK_RADIO.send(packetbuf_hdrptr(), packetbuf_totlen()); #endif off(); } else { rtimer_clock_t wt; NETSTACK_RADIO.send(strobe, strobe_len); #if 1 /* Turn off the radio for a while to let the other side respond. We don't need to keep our radio on when we know that the other side needs some time to produce a reply. */ off(); wt = RTIMER_NOW(); while(RTIMER_CLOCK_LT(RTIMER_NOW(), wt + WAIT_TIME_BEFORE_STROBE_ACK)); #endif /* 0 */ on(); } } } } #if WITH_ACK_OPTIMIZATION /* If we have received the strobe ACK, and we are sending a packet that will need an upper layer ACK (as signified by the PACKETBUF_ATTR_RELIABLE packet attribute), we keep the radio on. */ if(got_strobe_ack && (packetbuf_attr(PACKETBUF_ATTR_RELIABLE) || packetbuf_attr(PACKETBUF_ATTR_ERELIABLE) || packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) == PACKETBUF_ATTR_PACKET_TYPE_STREAM)) { on(); /* Wait for ACK packet */ waiting_for_packet = 1; } else { off(); } #else /* WITH_ACK_OPTIMIZATION */ off(); #endif /* WITH_ACK_OPTIMIZATION */ /* restore the packet to send */ queuebuf_to_packetbuf(packet); queuebuf_free(packet); /* Send the data packet. */ if((is_broadcast || got_strobe_ack || is_streaming) && collisions == 0) { NETSTACK_RADIO.send(packetbuf_hdrptr(), packetbuf_totlen()); } #if WITH_ENCOUNTER_OPTIMIZATION if(got_strobe_ack && !is_streaming) { register_encounter(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), encounter_time); } #endif /* WITH_ENCOUNTER_OPTIMIZATION */ watchdog_start(); PRINTF("xmac: send (strobes=%u,len=%u,%s), done\n", strobes, packetbuf_totlen(), got_strobe_ack ? "ack" : "no ack"); #if XMAC_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 /* XMAC_CONF_COMPOWER */ we_are_sending = 0; LEDS_OFF(LEDS_BLUE); if(collisions == 0) { if(!is_broadcast && !got_strobe_ack) { return MAC_TX_NOACK; } else { return MAC_TX_OK; } } else { someone_is_sending++; return MAC_TX_COLLISION; } }
/*---------------------------------------------------------------------------*/ void routerForwarder_setNextHopAddress(rimeaddr_t *nextHopAddress_p, uint16_t nextHopBackpressure_p) { pmesg(200, "%s :: %s :: Line #%d\n", __FILE__, __func__, __LINE__); rimeaddr_copy(&nextHopAddress_m, nextHopAddress_p); nextHopBackpressure_m = nextHopBackpressure_p; }
/*---------------------------------------------------------------------------*/ static int create(void) { frame802154_t params; int 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 = FRAME802154_DATAFRAME; params.fcf.security_enabled = 0; params.fcf.frame_pending = packetbuf_attr(PACKETBUF_ATTR_PENDING); if(rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &rimeaddr_null)) { 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 (2003) version bit. */ params.fcf.frame_version = FRAME802154_IEEE802154_2003; /* Increment and set the data sequence number. */ if(packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO)) { params.seq = packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO); } else { params.seq = mac_dsn++; packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, params.seq); } /* params.seq = packetbuf_attr(PACKETBUF_ATTR_PACKET_ID); */ /* 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(sizeof(rimeaddr_t) == 2) { /* Use short address mode if rimeaddr 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 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.dest_addr_mode = FRAME802154_SHORTADDRMODE; params.dest_addr[0] = 0xFF; params.dest_addr[1] = 0xFF; } else { rimeaddr_copy((rimeaddr_t *)¶ms.dest_addr, packetbuf_addr(PACKETBUF_ADDR_RECEIVER)); /* Use short address mode if rimeaddr size is small */ if(sizeof(rimeaddr_t) == 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. */ rimeaddr_copy((rimeaddr_t *)¶ms.src_addr, &rimeaddr_node_addr); params.payload = packetbuf_dataptr(); params.payload_len = packetbuf_datalen(); len = frame802154_hdrlen(¶ms); if(packetbuf_hdralloc(len)) { frame802154_create(¶ms, packetbuf_hdrptr(), len); PRINTF("15.4-OUT: %2X", params.fcf.frame_type); PRINTADDR(params.dest_addr); PRINTF("%d %u (%u)\n", len, packetbuf_datalen(), packetbuf_totlen()); return len; } else { PRINTF("15.4-OUT: too large header: %u\n", len); return FRAMER_FAILED; } }
/* Function to process received beacon */ void mac_proc_beacon(frame802154_t *frame) { //Do nothing for now. Just copy the src address to rimeaddr_panCoord_addr rimeaddr_copy(&rimeaddr_panCoord_addr, &frame->src_addr); }
/*---------------------------------------------------------------------------*/ void collect_common_send(void) { static uint8_t seqno; struct { uint8_t seqno; uint8_t for_alignment; struct collect_view_data_msg msg; } msg; /* struct collect_neighbor *n; */ uint16_t parent_etx; uint16_t rtmetric; uint16_t num_neighbors; uint16_t beacon_interval; rpl_parent_t *preferred_parent; rimeaddr_t parent; rpl_dag_t *dag; if(client_conn == NULL) { /* Not setup yet */ return; } memset(&msg, 0, sizeof(msg)); seqno++; if(seqno == 0) { /* Wrap to 128 to identify restarts */ seqno = 128; } msg.seqno = seqno; rimeaddr_copy(&parent, &rimeaddr_null); parent_etx = 0; /* Let's suppose we have only one instance */ dag = rpl_get_any_dag(); if(dag != NULL) { preferred_parent = dag->preferred_parent; if(preferred_parent != NULL) { uip_ds6_nbr_t *nbr; nbr = uip_ds6_nbr_lookup(rpl_get_parent_ipaddr(preferred_parent)); if(nbr != NULL) { /* Use parts of the IPv6 address as the parent address, in reversed byte order. */ parent.u8[RIMEADDR_SIZE - 1] = nbr->ipaddr.u8[sizeof(uip_ipaddr_t) - 2]; parent.u8[RIMEADDR_SIZE - 2] = nbr->ipaddr.u8[sizeof(uip_ipaddr_t) - 1]; parent_etx = rpl_get_parent_rank((rimeaddr_t *) uip_ds6_nbr_get_ll(nbr)) / 2; } } rtmetric = dag->rank; beacon_interval = (uint16_t) ((2L << dag->instance->dio_intcurrent) / 1000); num_neighbors = RPL_PARENT_COUNT(dag); } else { rtmetric = 0; beacon_interval = 0; num_neighbors = 0; } /* num_neighbors = collect_neighbor_list_num(&tc.neighbor_list); */ collect_view_construct_message(&msg.msg, &parent, parent_etx, rtmetric, num_neighbors, beacon_interval); uip_udp_packet_sendto(client_conn, &msg, sizeof(msg), &server_ipaddr, UIP_HTONS(UDP_SERVER_PORT)); }
void mainfunc(cyg_addrword_t data) { /******************** lock the Scheduler ************************/ cyg_scheduler_lock(); /****************************************************************/ printf("Hello, eCos mainfunc!\n"); ds2411_id[0] = 0x00; ds2411_id[1] = 0x12; ds2411_id[2] = 0x75; ds2411_id[3] = 0x00; ds2411_id[4] = 0x0c; ds2411_id[5] = 0x59; //ds2411_id[6] = 0x57; //ds2411_id[7] = 0x3d; ds2411_id[6] = 0x10; ds2411_id[7] = 0x17; ds2411_id[2] &= 0xfe; /* ds2411_id[0] = 0x02; ds2411_id[1] = 0x00; ds2411_id[2] = 0x00; ds2411_id[3] = 0x00; ds2411_id[4] = 0x00; ds2411_id[5] = 0x00; //ds2411_id[6] = 0x57; //ds2411_id[7] = 0x3d; ds2411_id[6] = 0x00; ds2411_id[7] = 0x00; */ /* for setting "hardcoded" IEEE 802.15.4 MAC addresses */ #ifdef IEEE_802154_MAC_ADDRESS { uint8_t ieee[] = IEEE_802154_MAC_ADDRESS; memcpy(ds2411_id, ieee, sizeof(uip_lladdr.addr)); ds2411_id[7] = node_id & 0xff; } #endif random_init(5); set_rime_addr(); NETSTACK_RADIO.init(); { cyg_uint8 longaddr[8]; cyg_uint16 shortaddr; shortaddr = (rimeaddr_node_addr.u8[0] << 8) + rimeaddr_node_addr.u8[1]; memset(longaddr, 0, sizeof(longaddr)); rimeaddr_copy((rimeaddr_t *)&longaddr, &rimeaddr_node_addr); printf("MAC %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x ", longaddr[0], longaddr[1], longaddr[2], longaddr[3], longaddr[4], longaddr[5], longaddr[6], longaddr[7]); uz2400_set_pan_addr(IEEE802154_PANID, shortaddr, longaddr); } uz2400_set_channel(RF_CHANNEL);/////////////////////////////////////////// #if WITH_UIP6 memcpy(&uip_lladdr.addr, ds2411_id, sizeof(uip_lladdr.addr)); /* Setup nullmac-like MAC for 802.15.4 */ /* sicslowpan_init(sicslowmac_init(&cc2420_driver)); */ /* printf(" %s channel %u\n", sicslowmac_driver.name, RF_CHANNEL); */ /* Setup X-MAC for 802.15.4 */ queuebuf_init(); //NETSTACK_RADIO.init(); NETSTACK_RDC.init(); NETSTACK_MAC.init(); NETSTACK_NETWORK.init(); printf("%s %s, channel check rate %lu Hz, radio channel %u\n", NETSTACK_MAC.name, NETSTACK_RDC.name, CLOCK_CONF_SECOND / (NETSTACK_RDC.channel_check_interval() == 0 ? 1: NETSTACK_RDC.channel_check_interval()), RF_CHANNEL); //================ uip_init(); rpl_init(); //============= printf("Tentative link-local IPv6 address "); { uip_ds6_addr_t *lladdr=NULL; int i; lladdr = uip_ds6_get_link_local(-1); for(i = 0; i < 7; ++i) { printf("%02x%02x:", lladdr->ipaddr.u8[i * 2], lladdr->ipaddr.u8[i * 2 + 1]); } printf("%02x%02x\n", lladdr->ipaddr.u8[14], lladdr->ipaddr.u8[15]); } if(!UIP_CONF_IPV6_RPL) { uip_ipaddr_t ipaddr; int i; uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); uip_ds6_addr_add(&ipaddr, 0, ADDR_TENTATIVE); printf("Tentative global IPv6 address "); for(i = 0; i < 7; ++i) { printf("%02x%02x:", ipaddr.u8[i * 2], ipaddr.u8[i * 2 + 1]); } printf("%02x%02x\n", ipaddr.u8[7 * 2], ipaddr.u8[7 * 2 + 1]); } #endif /* WITH_UIP6 */ static cyg_uint32 GLedPinspec; GLedPinspec = CYGHWR_HAL_STM32_GPIO( C, 6, OUT_50MHZ , OUT_PUSHPULL ); volatile static cyg_uint8 blink=0; /******************** unlock the Scheduler ************************/ cyg_scheduler_unlock(); /****************************************************************/ while(1){ /* blink=~blink; CYGHWR_HAL_STM32_GPIO_OUT(GLedPinspec,blink); cyg_thread_delay(500); */ cyg_thread_yield(); } }
/*---------------------------------------------------------------------------*/ static void input_packet(void) { /* We have received the packet, so we can go back to being asleep. */ off(); /* printf("cycle_start 0x%02x 0x%02x\n", cycle_start, cycle_start % CYCLE_TIME);*/ if(packetbuf_totlen() > 0 && NETSTACK_FRAMER.parse()) { #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 CONTIKIMAC_CONF_ANNOUNCEMENTS { struct announcement_msg *hdr = packetbuf_dataptr(); uint8_t magic[2]; memcpy(magic, hdr->announcement_magic, 2); if(magic[0] == ANNOUNCEMENT_MAGIC1 && magic[1] == ANNOUNCEMENT_MAGIC2) { parse_announcements(); } } #endif /* CONTIKIMAC_CONF_ANNOUNCEMENTS */ #if WITH_PHASE_OPTIMIZATION /* If the sender has set its pending flag, it has its radio turned on and we should drop the phase estimation that we have from before. */ if(packetbuf_attr(PACKETBUF_ATTR_PENDING)) { phase_remove(&phase_list, packetbuf_addr(PACKETBUF_ADDR_SENDER)); } #endif /* WITH_PHASE_OPTIMIZATION */ /* 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) { rtimer_clock_t t0; rtimer_clock_t encounter_time = 0, previous_txtime = 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 i; int ret; uint8_t contikimac_was_on; #if WITH_CONTIKIMAC_HEADER struct hdr *chdr; #endif /* WITH_CONTIKIMAC_HEADER */ if(packetbuf_totlen() == 0) { PRINTF("contikimac: send_packet data len 0\n"); return MAC_TX_ERR_FATAL; } packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &rimeaddr_node_addr); 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); if(WITH_STREAMING) { if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) == PACKETBUF_ATTR_PACKET_TYPE_STREAM) { if(rimeaddr_cmp(&is_streaming_to, &rimeaddr_null)) { rimeaddr_copy(&is_streaming_to, packetbuf_addr(PACKETBUF_ADDR_RECEIVER)); } else if(!rimeaddr_cmp (&is_streaming_to, packetbuf_addr(PACKETBUF_ADDR_RECEIVER))) { rimeaddr_copy(&is_streaming_to_too, packetbuf_addr(PACKETBUF_ADDR_RECEIVER)); } stream_until = RTIMER_NOW() + DEFAULT_STREAM_TIME; is_streaming = 1; } } if(is_streaming) { packetbuf_set_attr(PACKETBUF_ATTR_PENDING, 1); } 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) { #if 0 /* Pad with zeroes */ uint8_t *ptr; ptr = packetbuf_dataptr(); memset(ptr + packetbuf_datalen(), 0, SHORTEST_PACKET_SIZE - packetbuf_totlen()); #endif PRINTF("contikimac: shorter than shortest (%d)\n", packetbuf_totlen()); transmit_len = SHORTEST_PACKET_SIZE; } packetbuf_compact(); 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_streaming) { #if WITH_PHASE_OPTIMIZATION ret = phase_wait(&phase_list, packetbuf_addr(PACKETBUF_ADDR_RECEIVER), CYCLE_TIME, GUARD_TIME, mac_callback, mac_callback_ptr); 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(is_streaming == 0) { /* Check if there are any transmissions by others. */ for(i = 0; i < CCA_COUNT_MAX; ++i) { t0 = RTIMER_NOW(); on(); while(RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + CCA_CHECK_TIME)) { } 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; } if(!is_broadcast) { on(); } watchdog_periodic(); t0 = RTIMER_NOW(); for(strobes = 0, collisions = 0; got_strobe_ack == 0 && collisions == 0 && RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + STROBE_TIME); strobes++) { watchdog_periodic(); if(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; previous_txtime = RTIMER_NOW(); { rtimer_clock_t wt; rtimer_clock_t txtime; int ret; txtime = RTIMER_NOW(); ret = NETSTACK_RADIO.transmit(transmit_len); 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) { got_strobe_ack = 1; encounter_time = previous_txtime; break; } else { PRINTF("contikimac: collisions while sending\n"); collisions++; } } previous_txtime = txtime; } } 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_streaming == 0) { phase_update(&phase_list, packetbuf_addr(PACKETBUF_ADDR_RECEIVER), encounter_time, ret); } } #endif /* WITH_PHASE_OPTIMIZATION */ if(WITH_STREAMING) { if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) == PACKETBUF_ATTR_PACKET_TYPE_STREAM_END) { is_streaming = 0; } } return ret; }
static char powercycle(struct rtimer *t, void *ptr) { PT_BEGIN(&pt); cycle_start = RTIMER_NOW(); while(1) { static uint8_t packet_seen; static rtimer_clock_t t0; static uint8_t count; cycle_start += CYCLE_TIME; if(WITH_STREAMING && is_streaming) { if(!RTIMER_CLOCK_LT(RTIMER_NOW(), stream_until)) { is_streaming = 0; rimeaddr_copy(&is_streaming_to, &rimeaddr_null); rimeaddr_copy(&is_streaming_to_too, &rimeaddr_null); } } packet_seen = 0; do { for(count = 0; count < CCA_COUNT_MAX; ++count) { t0 = RTIMER_NOW(); if(we_are_sending == 0) { powercycle_turn_radio_on(); // schedule_powercycle_fixed(t, t0 + CCA_CHECK_TIME); #if 0 while(RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + CCA_CHECK_TIME)); #endif /* 0 */ /* Check if a packet is seen in the air. If so, we keep the radio on for a while (LISTEN_TIME_AFTER_PACKET_DETECTED) to be able to receive the packet. We also continuously check the radio medium to make sure that we wasn't woken up by a false positive: a spurious radio interference that was not caused by an incoming packet. */ if(NETSTACK_RADIO.channel_clear() == 0) { packet_seen = 1; break; } powercycle_turn_radio_off(); } // schedule_powercycle_fixed(t, t0 + CCA_CHECK_TIME + CCA_SLEEP_TIME); schedule_powercycle_fixed(t, RTIMER_NOW() + CCA_SLEEP_TIME); /* COOJA_DEBUG_STR("yield\n");*/ PT_YIELD(&pt); } if(packet_seen) { static rtimer_clock_t start; static uint8_t silence_periods, periods; start = RTIMER_NOW(); periods = silence_periods = 0; while(we_are_sending == 0 && radio_is_on && RTIMER_CLOCK_LT(RTIMER_NOW(), (start + LISTEN_TIME_AFTER_PACKET_DETECTED))) { /* Check for a number of consecutive periods of non-activity. If we see two such periods, we turn the radio off. Also, if a packet has been successfully received (as indicated by the NETSTACK_RADIO.pending_packet() function), we stop snooping. */ if(NETSTACK_RADIO.channel_clear()) { ++silence_periods; } else { silence_periods = 0; } ++periods; if(NETSTACK_RADIO.receiving_packet()) { silence_periods = 0; } if(silence_periods > MAX_SILENCE_PERIODS) { powercycle_turn_radio_off(); break; } if(WITH_FAST_SLEEP && periods > MAX_NONACTIVITY_PERIODS && !(NETSTACK_RADIO.receiving_packet() || NETSTACK_RADIO.pending_packet())) { powercycle_turn_radio_off(); break; } if(NETSTACK_RADIO.pending_packet()) { break; } schedule_powercycle(t, CCA_CHECK_TIME + CCA_SLEEP_TIME); PT_YIELD(&pt); } if(radio_is_on) { if(!(NETSTACK_RADIO.receiving_packet() || NETSTACK_RADIO.pending_packet()) || !RTIMER_CLOCK_LT(RTIMER_NOW(), (start + LISTEN_TIME_AFTER_PACKET_DETECTED))) { powercycle_turn_radio_off(); } } } } while((is_snooping || is_streaming) && RTIMER_CLOCK_LT(RTIMER_NOW() - cycle_start, CYCLE_TIME - CHECK_TIME * 8)); if(RTIMER_CLOCK_LT(RTIMER_NOW() - cycle_start, CYCLE_TIME - CHECK_TIME * 4)) { /* schedule_powercycle(t, CYCLE_TIME - (RTIMER_NOW() - cycle_start));*/ schedule_powercycle_fixed(t, CYCLE_TIME + cycle_start); /* printf("cycle_start 0x%02x now 0x%02x wait 0x%02x\n", cycle_start, RTIMER_NOW(), CYCLE_TIME - (RTIMER_NOW() - cycle_start));*/ PT_YIELD(&pt); } } PT_END(&pt); }
/*---------------------------------------------------------------------------*/ void contiki_init() { /* Initialize random generator (moved to moteid.c) */ /* Start process handler */ process_init(); /* Start Contiki processes */ process_start(&etimer_process, NULL); process_start(&sensors_process, NULL); ctimer_init(); /* Print startup information */ printf(CONTIKI_VERSION_STRING " started. "); if(node_id > 0) { printf("Node id is set to %u.\n", node_id); } else { printf("Node id is not set.\n"); } set_rime_addr(); { uint8_t longaddr[8]; uint16_t shortaddr; shortaddr = (rimeaddr_node_addr.u8[0] << 8) + rimeaddr_node_addr.u8[1]; memset(longaddr, 0, sizeof(longaddr)); rimeaddr_copy((rimeaddr_t *)&longaddr, &rimeaddr_node_addr); printf("MAC %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x ", longaddr[0], longaddr[1], longaddr[2], longaddr[3], longaddr[4], longaddr[5], longaddr[6], longaddr[7]); } queuebuf_init(); /* Initialize communication stack */ netstack_init(); printf("%s/%s/%s, channel check rate %lu Hz\n", NETSTACK_NETWORK.name, NETSTACK_MAC.name, NETSTACK_RDC.name, CLOCK_SECOND / (NETSTACK_RDC.channel_check_interval() == 0 ? 1: NETSTACK_RDC.channel_check_interval())); #if WITH_UIP /* IPv4 CONFIGURATION */ { uip_ipaddr_t hostaddr, netmask; process_start(&tcpip_process, NULL); process_start(&uip_fw_process, NULL); process_start(&slip_process, NULL); slip_set_input_callback(set_gateway); uip_init(); uip_fw_init(); uip_ipaddr(&hostaddr, 172,16,rimeaddr_node_addr.u8[0],rimeaddr_node_addr.u8[1]); uip_ipaddr(&netmask, 255,255,0,0); uip_ipaddr_copy(&meshif.ipaddr, &hostaddr); uip_sethostaddr(&hostaddr); uip_setnetmask(&netmask); uip_over_mesh_set_net(&hostaddr, &netmask); uip_over_mesh_set_gateway_netif(&slipif); uip_fw_default(&meshif); uip_over_mesh_init(UIP_OVER_MESH_CHANNEL); rs232_set_input(slip_input_byte); printf("IPv4 address: %d.%d.%d.%d\n", uip_ipaddr_to_quad(&hostaddr)); } #endif /* WITH_UIP */ #if WITH_UIP6 /* IPv6 CONFIGURATION */ { int i; uint8_t addr[sizeof(uip_lladdr.addr)]; for(i = 0; i < sizeof(uip_lladdr.addr); i += 2) { addr[i + 1] = node_id & 0xff; addr[i + 0] = node_id >> 8; } rimeaddr_copy(addr, &rimeaddr_node_addr); memcpy(&uip_lladdr.addr, addr, sizeof(uip_lladdr.addr)); process_start(&tcpip_process, NULL); printf("Tentative link-local IPv6 address "); { uip_ds6_addr_t *lladdr; int i; lladdr = uip_ds6_get_link_local(-1); for(i = 0; i < 7; ++i) { printf("%02x%02x:", lladdr->ipaddr.u8[i * 2], lladdr->ipaddr.u8[i * 2 + 1]); } printf("%02x%02x\n", lladdr->ipaddr.u8[14], lladdr->ipaddr.u8[15]); } if(1) { uip_ipaddr_t ipaddr; int i; uip_ip6addr(&ipaddr, 0xfc00, 0, 0, 0, 0, 0, 0, 0); uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); uip_ds6_addr_add(&ipaddr, 0, ADDR_TENTATIVE); printf("Tentative global IPv6 address "); for(i = 0; i < 7; ++i) { printf("%02x%02x:", ipaddr.u8[i * 2], ipaddr.u8[i * 2 + 1]); } printf("%02x%02x\n", ipaddr.u8[7 * 2], ipaddr.u8[7 * 2 + 1]); } } #endif /* WITH_UIP6 */ /* Start serial process */ serial_line_init(); /* Start autostart processes (defined in Contiki application) */ print_processes(autostart_processes); autostart_start(autostart_processes); #if IP64_CONF_UIP_FALLBACK_INTERFACE_SLIP && WITH_SLIP /* Start the SLIP */ printf("Initiating SLIP: my IP is 172.16.0.2...\n"); { uip_ip4addr_t ipv4addr, netmask; uip_ipaddr(&ipv4addr, 172, 16, 0, 2); uip_ipaddr(&netmask, 255, 255, 255, 0); ip64_set_ipv4_address(&ipv4addr, &netmask); } rs232_set_input(slip_input_byte); log_set_putchar_with_slip(1); #endif /* IP64_CONF_UIP_FALLBACK_INTERFACE_SLIP */ }
/* Function to send beacon */ extern void mac_send_beacon() { static uint16_t macBSN = 0x00; uint8_t payload[10] = {0,0,0,0,0,0,0,0,0,0}; frame802154_t params; static frame802154_beacon_t beaconData; uint8_t len; /* init to zeros */ memset(¶ms, 0, sizeof(params)); memset(&beaconData, 0, sizeof(frame802154_beacon_t)); /* Build the FCF. */ params.fcf.frame_type = FRAME802154_BEACONFRAME; params.fcf.security_enabled = 0; params.fcf.frame_pending = 0; params.fcf.ack_required = 0; params.fcf.panid_compression = 0; /* Insert IEEE 802.15.4 (2003) version bit. */ params.fcf.frame_version = FRAME802154_IEEE802154_2003; /* Increment and set the beacon sequence number. */ params.seq = macBSN++; /* 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; /* Set the source PAN ID to the PAN ID as per spec. */ params.src_pid = mac_dst_pan_id; params.fcf.dest_addr_mode = FRAME802154_NOADDR; params.dest_pid = 0; // params.dest_addr[0] = 0xFF; // params.dest_addr[1] = 0xFF; //rimeaddr_copy((rimeaddr_t *)¶ms.dest_addr,\ packetbuf_addr(PACKETBUF_ADDR_RECEIVER)); /* * Set up the source address using only the long address mode for * phase 1. */ rimeaddr_copy((rimeaddr_t *)¶ms.src_addr, &rimeaddr_node_addr); rimeaddr_copy((rimeaddr_t *)¶ms.dest_addr, &rimeaddr_null); /* Preparing the payload for beacon*/ beaconData.superFrSpec |= 0x000F; /* BO set to 15 */ beaconData.superFrSpec |= 0x00F0; /* SO set to 15 */ beaconData.superFrSpec |= 0x0F00; /* CAP lt:No relevance in beacon less */ beaconData.superFrSpec |= BV(14); /* PAN coordinator */ beaconData.superFrSpec |= BV(15); /* Association permitted */ beaconData.gtsInfo.gtsSpec = 0; /* If 0, direction and list are absent*/ beaconData.pendAddrInfo.pendAddrSpec = 0; /* If 0, no list present*/ packetbuf_clear(); len = frame802154_packBeacon((uint8_t*)packetbuf_dataptr(),&beaconData); packetbuf_set_datalen(len); params.payload = packetbuf_dataptr(); len = frame802154_hdrlen(¶ms); frame802154_create(¶ms, packetbuf_hdrptr(), len); NETSTACK_RADIO.send(packetbuf_hdrptr(), packetbuf_totlen()); return; }
/*---------------------------------------------------------------------------*/ void init_net(void) { set_rime_addr(); NETSTACK_RADIO.init(); { uint8_t longaddr[8]; uint16_t shortaddr; shortaddr = (rimeaddr_node_addr.u8[0] << 8) + rimeaddr_node_addr.u8[1]; memset(longaddr, 0, sizeof(longaddr)); rimeaddr_copy((rimeaddr_t *)&longaddr, &rimeaddr_node_addr); printf_P(PSTR("MAC %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n"), longaddr[0], longaddr[1], longaddr[2], longaddr[3], longaddr[4], longaddr[5], longaddr[6], longaddr[7]); rf230_set_pan_addr(IEEE802154_PANID, shortaddr, longaddr); } rf230_set_channel(RF_CHANNEL); #if WITH_UIP6 memcpy(&uip_lladdr.addr, ds2401_id, sizeof(uip_lladdr.addr)); /* Setup nullmac-like MAC for 802.15.4 */ /* sicslowpan_init(sicslowmac_init(&cc2420_driver)); */ /* printf(" %s channel %u\n", sicslowmac_driver.name, RF_CHANNEL); */ /* Setup X-MAC for 802.15.4 */ queuebuf_init(); NETSTACK_RDC.init(); NETSTACK_MAC.init(); NETSTACK_NETWORK.init(); printf_P(PSTR("%s %s, channel check rate %d Hz, radio channel %d\n"), NETSTACK_MAC.name, NETSTACK_RDC.name, CLOCK_SECOND / (NETSTACK_RDC.channel_check_interval() == 0 ? 1: NETSTACK_RDC.channel_check_interval()), RF_CHANNEL); process_start(&tcpip_process, NULL); printf_P(PSTR("Tentative link-local IPv6 address ")); { uip_ds6_addr_t *lladdr; int i; lladdr = uip_ds6_get_link_local(-1); for(i = 0; i < 7; ++i) { printf_P(PSTR("%02x%02x:"), lladdr->ipaddr.u8[i * 2], lladdr->ipaddr.u8[i * 2 + 1]); } printf_P(PSTR("%02x%02x\n"), lladdr->ipaddr.u8[14], lladdr->ipaddr.u8[15]); } if(!UIP_CONF_IPV6_RPL) { uip_ipaddr_t ipaddr; int i; uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); uip_ds6_addr_add(&ipaddr, 0, ADDR_TENTATIVE); printf_P(PSTR("Tentative global IPv6 address ")); for(i = 0; i < 7; ++i) { printf_P(PSTR("%02x%02x:"), ipaddr.u8[i * 2], ipaddr.u8[i * 2 + 1]); } printf_P(PSTR("%02x%02x\n"), ipaddr.u8[7 * 2], ipaddr.u8[7 * 2 + 1]); } #else /* WITH_UIP6 */ NETSTACK_RDC.init(); NETSTACK_MAC.init(); NETSTACK_NETWORK.init(); printf_P(PSTR("%s %s, channel check rate %d Hz, radio channel %d\n"), NETSTACK_MAC.name, NETSTACK_RDC.name, CLOCK_SECOND / (NETSTACK_RDC.channel_check_interval() == 0? 1: NETSTACK_RDC.channel_check_interval()), RF_CHANNEL); #endif /* WITH_UIP6 */ #if WITH_UIP uip_ipaddr_t hostaddr, netmask; uip_init(); uip_fw_init(); process_start(&tcpip_process, NULL); process_start(&slip_process, NULL); process_start(&uip_fw_process, NULL); slip_set_input_callback(set_gateway); /* Construct ip address from four bytes. */ uip_ipaddr(&hostaddr, 172, 16, rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1]); /* Construct netmask from four bytes. */ uip_ipaddr(&netmask, 255,255,0,0); uip_ipaddr_copy(&meshif.ipaddr, &hostaddr); /* Set the IP address for this host. */ uip_sethostaddr(&hostaddr); /* Set the netmask for this host. */ uip_setnetmask(&netmask); uip_over_mesh_set_net(&hostaddr, &netmask); /* Register slip interface with forwarding module. */ //uip_fw_register(&slipif); uip_over_mesh_set_gateway_netif(&slipif); /* Set slip interface to be a default forwarding interface . */ uip_fw_default(&meshif); uip_over_mesh_init(UIP_OVER_MESH_CHANNEL); printf_P(PSTR("uIP started with IP address %d.%d.%d.%d\n"), uip_ipaddr_to_quad(&hostaddr)); #endif /* WITH_UIP */ }
void init_unicast_packet(struct unicast_packet *up, enum packet_flags flags, uint8_t hops, const rimeaddr_t *originator, const rimeaddr_t *sender, uint8_t seqno, const rimeaddr_t *destination) { init_packet((struct packet*)up, UNICAST|flags, hops, originator, sender, seqno); rimeaddr_copy(&up->destination, destination); }
/*---------------------------------------------------------------------------*/ static void input_packet(void) { struct xmac_hdr *hdr; if(NETSTACK_FRAMER.parse()) { hdr = packetbuf_dataptr(); if(hdr->dispatch != DISPATCH) { someone_is_sending = 0; if(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. */ /* We have received the final packet, so we can go back to being asleep. */ off(); /* 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. */ 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 XMAC_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 /* XMAC_CONF_COMPOWER */ waiting_for_packet = 0; PRINTDEBUG("xmac: data(%u)\n", packetbuf_datalen()); NETSTACK_MAC.input(); return; } else { PRINTDEBUG("xmac: data not for us\n"); } } else if(hdr->type == TYPE_STROBE) { someone_is_sending = 2; if(rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &rimeaddr_node_addr)) { /* This is a strobe packet for us. */ /* If the sender address is someone else, we should acknowledge the strobe and wait for the packet. By using the same address as both sender and receiver, we flag the message is a strobe ack. */ hdr->type = TYPE_STROBE_ACK; packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, packetbuf_addr(PACKETBUF_ADDR_SENDER)); packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &rimeaddr_node_addr); packetbuf_compact(); if(NETSTACK_FRAMER.create()) { /* We turn on the radio in anticipation of the incoming packet. */ someone_is_sending = 1; waiting_for_packet = 1; on(); NETSTACK_RADIO.send(packetbuf_hdrptr(), packetbuf_totlen()); PRINTDEBUG("xmac: send strobe ack %u\n", packetbuf_totlen()); } else { PRINTF("xmac: failed to send strobe ack\n"); } } else if(rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &rimeaddr_null)) { /* If the receiver address is null, the strobe is sent to prepare for an incoming broadcast packet. If this is the case, we turn on the radio and wait for the incoming broadcast packet. */ waiting_for_packet = 1; on(); } else { PRINTDEBUG("xmac: strobe not for us\n"); } /* We are done processing the strobe and we therefore return to the caller. */ return; #if XMAC_CONF_ANNOUNCEMENTS } else if(hdr->type == TYPE_ANNOUNCEMENT) { packetbuf_hdrreduce(sizeof(struct xmac_hdr)); parse_announcements(packetbuf_addr(PACKETBUF_ADDR_SENDER)); #endif /* XMAC_CONF_ANNOUNCEMENTS */ } else if(hdr->type == TYPE_STROBE_ACK) { PRINTDEBUG("xmac: stray strobe ack\n"); } else { PRINTF("xmac: unknown type %u (%u/%u)\n", hdr->type, packetbuf_datalen(), len); } } else { PRINTF("xmac: failed to parse (%u)\n", packetbuf_totlen()); } }
/*---------------------------------------------------------------------------*/ static void mac_frame_input(void) { #if IEEE80211_DRIVER_DEBUG_DEEP PRINTF("IEEE80211driver: mac_frame_input.\n"); #endif /* Theoretically, now is the time where the framer goes on * with the frame parsing. This has, however, been done in * earlier implementation steps. So now the "parsing" will * just remove the MAC header, leaving the network layer * payload for the NETSTACK_NETWORK driver. */ uint8_t hdr_length = sizeof(struct ieee80211_hdr_3addr) + 2 + 6; int hdr = packetbuf_hdrreduce(hdr_length); if (!hdr) { printf("ERROR: Could not remove MAC header from the packet buffer.\n"); return; } int j; uint8_t* pkt_data = packetbuf_dataptr(); #if IEEE80211_DRIVER_DEBUG_DEEP PRINTF("IEEE80211_drv: [%u].\n", packetbuf_datalen()); #endif /* We do not need to check whether the packet is destined * for us, since this has been done by the ieee80211_rx.c * implementation. So we just do sanity checks here. */ if (packetbuf_totlen() > 0 && packetbuf_datalen() > 0) { /* Check for duplicate packet by comparing the sequence number * of the incoming packet with the last few ones we saw. This * is the same as in Contiki MAC. */ 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("Dropping MAC Duplicate.\n"); return; } } /* It seems that this is not a duplicate. So we update the history for * the received packet sequence numbers, dropping the oldest one and * adding the current packet sequence number and sender address. */ for(i=MAX_SEQNOS-1; i>0; --i) { memcpy(&received_seqnos[i], &received_seqnos[i - 1],sizeof(struct seqno)); } received_seqnos[MAX_SEQNOS-1].seqno = packetbuf_attr(PACKETBUF_ATTR_PACKET_ID); rimeaddr_copy(&received_seqnos[MAX_SEQNOS-1].sender, packetbuf_addr(PACKETBUF_ADDR_SENDER)); } /* Finally, the input function of the Network Driver shall be called. Note * that the packet we send up to the network layer contains only the layer * 3 payload; all MAC layer content has been removed. */ NETSTACK_NETWORK.input(); }
void routerForwarder_setNotifyBurstyLinkNeighbor(rimeaddr_t *neighbor_p) { pmesg(200, "%s :: %s :: Line #%d\n", __FILE__, __func__, __LINE__); rimeaddr_copy(¬ifyBurstyLinkNeighbor_m, neighbor_p); }
/** * * Send a packet. This function builds a complete packet with an LPP * header and queues the packet. When a probe is heard (in the * read_packet() function), and the sender of the probe matches the * receiver of the queued packet, the queued packet is sent. * * ACK packets are treated differently from other packets: if a node * sends a packet that it expects to be ACKed, the sending node keeps * its radio on for some time after sending its packet. So we do not * need to wait for a probe packet: we just transmit the ACK packet * immediately. * */ static void send_packet(mac_callback_t sent, void *ptr) { struct lpp_hdr hdr; clock_time_t timeout; uint8_t is_broadcast = 0; rimeaddr_copy(&hdr.sender, &rimeaddr_node_addr); rimeaddr_copy(&hdr.receiver, packetbuf_addr(PACKETBUF_ADDR_RECEIVER)); if(rimeaddr_cmp(&hdr.receiver, &rimeaddr_null)) { is_broadcast = 1; } hdr.type = TYPE_DATA; packetbuf_hdralloc(sizeof(struct lpp_hdr)); memcpy(packetbuf_hdrptr(), &hdr, sizeof(struct lpp_hdr)); packetbuf_compact(); packetbuf_set_attr(PACKETBUF_ATTR_MAC_ACK, 1); { int hdrlen = NETSTACK_FRAMER.create(); if(hdrlen < 0) { /* Failed to send */ mac_call_sent_callback(sent, ptr, MAC_TX_ERR_FATAL, 0); return; } } PRINTF("%d.%d: queueing packet to %d.%d, channel %d\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], hdr.receiver.u8[0], hdr.receiver.u8[1], packetbuf_attr(PACKETBUF_ATTR_CHANNEL)); #if WITH_ACK_OPTIMIZATION if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) == PACKETBUF_ATTR_PACKET_TYPE_ACK) { /* Send ACKs immediately. */ NETSTACK_RADIO.send(packetbuf_hdrptr(), packetbuf_totlen()); mac_call_sent_callback(sent, ptr, MAC_TX_OK, 1); return; } #endif /* WITH_ACK_OPTIMIZATION */ #if WITH_ADAPTIVE_OFF_TIME off_time = LOWEST_OFF_TIME; restart_dutycycle(off_time); #endif /* WITH_ADAPTIVE_OFF_TIME */ { struct queue_list_item *i; i = memb_alloc(&queued_packets_memb); if(i != NULL) { i->sent_callback = sent; i->sent_callback_ptr = ptr; i->num_transmissions = 0; i->packet = queuebuf_new_from_packetbuf(); if(i->packet == NULL) { memb_free(&queued_packets_memb, i); printf("null packet\n"); mac_call_sent_callback(sent, ptr, MAC_TX_ERR, 0); return; } else { if(is_broadcast) { timeout = PACKET_LIFETIME; #if WITH_PENDING_BROADCAST /* We set the broadcast state of the packet to be waiting. This means that the packet is waiting for our next probe to be sent. Our next probe is used to check if there are any neighbors currently broadcasting a packet. If so, we will get a broadcast packet in response to our probe. If no broadcast packet is received in response to our probe, we mark the packet as ready to be sent. */ set_broadcast_flag(i, BROADCAST_FLAG_WAITING); PRINTF("-> waiting\n"); #endif /* WITH_PENDING_BROADCAST */ } else { timeout = UNICAST_TIMEOUT; #if WITH_PENDING_BROADCAST i->broadcast_flag = BROADCAST_FLAG_NONE; #endif /* WITH_PENDING_BROADCAST */ } ctimer_set(&i->removal_timer, timeout, remove_queued_old_packet_callback, i); /* Wait for a probe packet from a neighbor. The actual packet transmission is handled by the read_packet() function, which receives the probe from the neighbor. */ turn_radio_on_for_neighbor(&hdr.receiver, i); } } else { printf("i == NULL\n"); mac_call_sent_callback(sent, ptr, MAC_TX_ERR, 0); } } }
/*---------------------------------------------------------------------------*/ error_t forwardingEngine_Send(message_wrapper_t* msg, uint8_t len) { pmesg(200, "%s :: %s :: Line #%d\n", __FILE__, __func__, __LINE__); // Send code for client send request static bcp_data_header_t* hdr; static uint32_t arrivalTime; //uint32_t arrivalTime = call DelayPacketTimer.getNow(); static error_t retVal; arrivalTime = 0; pmesg(200, "Forwarding Engine Sending Packet\n"); if (!isRunningForwardingEngine) {return EOFF;} hdr = &(msg -> bcp_data_header); hdr -> hopCount = 0; rimeaddr_copy(&(hdr -> origin), &rimeaddr_node_addr); hdr -> originSeqNo = seqno++; hdr -> bcpDelay = 0; hdr -> txCount = 0; hdr -> pktType = PKT_NORMAL; // If needed, discard an element from the forwarding queue conditionalFQDiscard(); //Make sure list pool is not full if(list_length(message_pool) >= MESSAGE_POOL_SIZE) { pmesg(200, "WARNING: BcpForwardingEngine.c - Send. Cannot send, message pool is out of memory.\n"); return EBUSY; } //Make sure list pool is not full else if(list_length(q_entry_pool) >= Q_ENTRY_POOL_SIZE) { pmesg(200, "WARNING: BcpForwardingEngine.c - Send. Cannot send, queue entry pool is out of memory.\n"); return EBUSY; } else { static message_wrapper_t* newMsg; static fe_queue_entry_t *qe; qe = memb_alloc(&q_entry_pool_mem); if (qe == NULL) { pmesg(10, "ERROR: BcpForwardingEngine.c - SEND. q_entry_pool is full.\n"); return FAIL; } list_add(q_entry_pool, qe); newMsg = memb_alloc(&message_pool_mem); if (newMsg == NULL) { pmesg(10, "ERROR: BcpForwardingEngine.c - SEND. message_pool is full.\n"); // Free the QEntryPool list_remove(q_entry_pool, qe); memb_free(&q_entry_pool_mem, qe); return FAIL; } list_add(message_pool, newMsg); memset(newMsg, 0, sizeof(message_wrapper_t)); // Copy the message, client may send more messages. memcpy(newMsg, msg, sizeof(message_wrapper_t)); qe -> msg = newMsg; qe -> source = LOCAL_SEND; qe -> arrivalTime = arrivalTime; qe -> txCount = 0; qe -> firstTxTime = 0; qe -> bcpArrivalDelay = 0; if(!(list_length(send_stack) >= SEND_STACK_SIZE)) { #ifdef LIFO list_push(send_stack, qe); #endif #ifndef LIFO list_add(send_stack, qe); #endif pmesg(100, "Forwarder is forwarding packet with send_stack size = %d\n", list_length(send_stack)); forwarderActivity(); if(ev_send_done != NULL) ev_send_done(msg, SUCCESS); // signal Send.sendDone(msg, SUCCESS); // Successful function exit point: return SUCCESS; } else { // There was a problem enqueuing to the send queue. // Free the allocated MessagePool and QEntryPool list_remove(message_pool, newMsg); memb_free(&message_pool_mem, newMsg); list_remove(q_entry_pool, qe); memb_free(&q_entry_pool_mem, qe); } } // NB: at this point, we have a resource acquistion problem. // Log the event, and drop the packet pmesg(10, "ERROR BcpForwardingEngine: Cannot SEND, unable to allocate resources.\n"); return FAIL; }
/*---------------------------------------------------------------------------*/ static int send_packet(void) { rtimer_clock_t t0; rtimer_clock_t t; int strobes; struct xmac_hdr *hdr; int got_ack = 0; struct xmac_hdr msg; int len; int is_broadcast = 0; #if WITH_TIMETABLE TIMETABLE_TIMESTAMP(xmac_timetable, "send"); #endif #if WITH_CHANNEL_CHECK /* Check if there are other strobes in the air. */ waiting_for_packet = 1; on(); t0 = RTIMER_NOW(); while(RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + xmac_config.strobe_wait_time * 2)) { len = radio->read(&msg, sizeof(msg)); if(len > 0) { someone_is_sending = 1; } } waiting_for_packet = 0; while(someone_is_sending); /* {printf("z");}*/ #if WITH_TIMETABLE TIMETABLE_TIMESTAMP(xmac_timetable, "send 2"); #endif /* WITH_TIMETABLE */ #endif /* WITH_CHANNEL_CHECK */ /* 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; off(); rimebuf_hdralloc(sizeof(struct xmac_hdr)); hdr = rimebuf_hdrptr(); rimeaddr_copy(&hdr->sender, &rimeaddr_node_addr); rimeaddr_copy(&hdr->receiver, rimebuf_addr(RIMEBUF_ADDR_RECEIVER)); if(rimeaddr_cmp(&hdr->receiver, &rimeaddr_null)) { is_broadcast = 1; } rimebuf_compact(); t0 = RTIMER_NOW(); strobes = 0; BB_SET(XMAC_RECEIVER, hdr->receiver.u16[0]); LEDS_ON(LEDS_BLUE); /* Send a train of strobes until the receiver answers with an ACK. */ /* Turn on the radio to listen for the strobe ACK. */ if(!is_broadcast) { on(); } watchdog_stop(); got_ack = 0; for(strobes = 0; got_ack == 0 && RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + xmac_config.strobe_time); strobes++) { t = RTIMER_NOW(); rimeaddr_copy(&msg.sender, &rimeaddr_node_addr); rimeaddr_copy(&msg.receiver, rimebuf_addr(RIMEBUF_ADDR_RECEIVER)); #if WITH_TIMETABLE if(rimeaddr_cmp(&msg.receiver, &rimeaddr_null)) { TIMETABLE_TIMESTAMP(xmac_timetable, "send broadcast strobe"); } else { TIMETABLE_TIMESTAMP(xmac_timetable, "send strobe"); } #endif if(is_broadcast) { /* If we are sending a broadcast, we don't send strobes, we simply send the data packet repetedly */ radio->send(rimebuf_hdrptr(), rimebuf_totlen()); } else { /* Send the strobe packet. */ radio->send((const uint8_t *)&msg, sizeof(struct xmac_hdr)); } CPRINTF("+"); while(got_ack == 0 && RTIMER_CLOCK_LT(RTIMER_NOW(), t + xmac_config.strobe_wait_time)) { /* See if we got an ACK */ len = radio->read((uint8_t *)&msg, sizeof(struct xmac_hdr)); if(len > 0) { CPRINTF("_"); if(rimeaddr_cmp(&msg.sender, &rimeaddr_node_addr) && rimeaddr_cmp(&msg.receiver, &rimeaddr_node_addr)) { #if WITH_TIMETABLE TIMETABLE_TIMESTAMP(xmac_timetable, "send ack received"); #endif CPRINTF("@"); /* We got an ACK from the receiver, so we can immediately send the packet. */ got_ack = 1; } } } /* XXX: turn off radio if we haven't heard an ACK within a specified time interval. */ /* if(got_ack == 0) { off(); while(RTIMER_CLOCK_LT(RTIMER_NOW(), t + xmac_config.strobe_wait_time)); on(); }*/ } if(got_ack /* XXX && needs_ack */) { #if WITH_TIMETABLE TIMETABLE_TIMESTAMP(xmac_timetable, "send got ack"); #endif on(); /* Wait for possible ACK packet */ } else if(!is_broadcast) { #if WITH_TIMETABLE TIMETABLE_TIMESTAMP(xmac_timetable, "send no ack received"); #endif on(); /* shell ping don't seem to work with off() here, so we'll keep it on() for a while. */ } /* Send the data packet. */ if(is_broadcast || got_ack) { #if WITH_TIMETABLE TIMETABLE_TIMESTAMP(xmac_timetable, "send packet"); #endif radio->send(rimebuf_hdrptr(), rimebuf_totlen()); CPRINTF("#"); } watchdog_start(); PRINTF("xmac: send (strobes=%u,len=%u,%s), done\n", strobes, rimebuf_totlen(), got_ack ? "ack" : "no ack"); BB_SET(XMAC_STROBES, strobes); if(got_ack) { BB_INC(XMAC_SEND_WITH_ACK, 1); } else { BB_INC(XMAC_SEND_WITH_NOACK, 1); } /* printf("Strobe %d got_ack %d\n", strobes, got_ack);*/ we_are_sending = 0; #if WITH_TIMETABLE TIMETABLE_TIMESTAMP(xmac_timetable, "send we_are_sending = 0"); #endif LEDS_OFF(LEDS_BLUE); return 1; }
/* This function is called whenever a broadcast message is received. */ static void broadcast_recv(struct broadcast_conn *c, const rimeaddr_t *from) { struct neighbor *n; struct broadcast_message *m; uint8_t seqno_gap; /* The packetbuf_dataptr() returns a pointer to the first data byte in the received packet. */ m = packetbuf_dataptr(); /* Check if we already know this neighbor. */ for(n = list_head(neighbors_list); n != NULL; n = list_item_next(n)) { /* We break out of the loop if the address of the neighbor matches the address of the neighbor from which we received this broadcast message. */ if(rimeaddr_cmp(&n->addr, from)) { break; } } /* If n is NULL, this neighbor was not found in our list, and we allocate a new struct neighbor from the neighbors_memb memory pool. */ if(n == NULL) { n = memb_alloc(&neighbors_memb); /* If we could not allocate a new neighbor entry, we give up. We could have reused an old neighbor entry, but we do not do this for now. */ if(n == NULL) { return; } /* Initialize the fields. */ rimeaddr_copy(&n->addr, from); n->last_seqno = m->seqno - 1; n->avg_seqno_gap = SEQNO_EWMA_UNITY; /* Place the neighbor on the neighbor list. */ list_add(neighbors_list, n); } /* We can now fill in the fields in our neighbor entry. */ n->last_rssi = packetbuf_attr(PACKETBUF_ATTR_RSSI); n->last_lqi = packetbuf_attr(PACKETBUF_ATTR_LINK_QUALITY); /* Compute the average sequence number gap we have seen from this neighbor. */ seqno_gap = m->seqno - n->last_seqno; n->avg_seqno_gap = (((uint32_t)seqno_gap * SEQNO_EWMA_UNITY) * SEQNO_EWMA_ALPHA) / SEQNO_EWMA_UNITY + ((uint32_t)n->avg_seqno_gap * (SEQNO_EWMA_UNITY - SEQNO_EWMA_ALPHA)) / SEQNO_EWMA_UNITY; /* Remember last seqno we heard. */ n->last_seqno = m->seqno; /* Print out a message. */ printf("broadcast message received from %d.%d with seqno %d, RSSI %u, LQI %u, avg seqno gap %d.%02d\n", from->u8[0], from->u8[1], m->seqno, packetbuf_attr(PACKETBUF_ATTR_RSSI), packetbuf_attr(PACKETBUF_ATTR_LINK_QUALITY), (int)(n->avg_seqno_gap / SEQNO_EWMA_UNITY), (int)(((100UL * n->avg_seqno_gap) / SEQNO_EWMA_UNITY) % 100)); }
/*---------------------------------------------------------------------------*/ static int read_packet(void) { struct xmac_hdr *hdr; uint8_t len; rimebuf_clear(); len = radio->read(rimebuf_dataptr(), RIMEBUF_SIZE); if(len > 0) { rimebuf_set_datalen(len); hdr = rimebuf_dataptr(); rimebuf_hdrreduce(sizeof(struct xmac_hdr)); if(rimebuf_totlen() == 0) { CPRINTF("."); /* There is no data in the packet so it has to be a strobe. */ someone_is_sending = 2; if(rimeaddr_cmp(&hdr->receiver, &rimeaddr_node_addr)) { /* This is a strobe packet for us. */ if(rimeaddr_cmp(&hdr->sender, &rimeaddr_node_addr)) { /* If the sender address is our node address, the strobe is a stray strobe ACK to us, which we ignore unless we are currently sending a packet. */ CPRINTF("&"); someone_is_sending = 0; } else { struct xmac_hdr msg; /* If the sender address is someone else, we should acknowledge the strobe and wait for the packet. By using the same address as both sender and receiver, we flag the message is a strobe ack. */ #if WITH_TIMETABLE TIMETABLE_TIMESTAMP(xmac_timetable, "read send ack"); #endif rimeaddr_copy(&msg.receiver, &hdr->sender); rimeaddr_copy(&msg.sender, &hdr->sender); CPRINTF("!"); /* We turn on the radio in anticipation of the incoming packet. */ someone_is_sending = 1; waiting_for_packet = 1; on(); radio->send((const uint8_t *)&msg, sizeof(struct xmac_hdr)); } } else if(rimeaddr_cmp(&hdr->receiver, &rimeaddr_null)) { /* If the receiver address is null, the strobe is sent to prepare for an incoming broadcast packet. If this is the case, we turn on the radio and wait for the incoming broadcast packet. */ waiting_for_packet = 1; on(); } /* We are done processing the strobe and we therefore return to the caller. */ return RIME_OK; } else { CPRINTF("-"); someone_is_sending = 0; if(rimeaddr_cmp(&hdr->receiver, &rimeaddr_node_addr) || rimeaddr_cmp(&hdr->receiver, &rimeaddr_null)) { #if WITH_TIMETABLE TIMETABLE_TIMESTAMP(xmac_timetable, "read got packet"); #endif /* This is a regular packet that is destined to us or to the broadcast address. */ /* We have received the final packet, so we can go back to being asleep. */ off(); waiting_for_packet = 0; /* XXX should set timer to send queued packet later. */ if(queued_packet != NULL) { queuebuf_free(queued_packet); queued_packet = NULL; } return rimebuf_totlen(); } } } return 0; }
/*---------------------------------------------------------------------------*/ 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);*/ 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()); } }
/*---------------------------------------------------------------------------*/ #if WITH_TINYOS_AUTO_IDS uint16_t TOS_NODE_ID = 0x1234; /* non-zero */ uint16_t TOS_LOCAL_ADDRESS = 0x1234; /* non-zero */ #endif /* WITH_TINYOS_AUTO_IDS */ int main(int argc, char **argv) { /* * Initalize hardware. */ msp430_cpu_init(); clock_init(); leds_init(); leds_on(LEDS_RED); uart1_init(BAUD2UBR(115200)); /* Must come before first printf */ #if WITH_UIP slip_arch_init(BAUD2UBR(115200)); #endif /* WITH_UIP */ leds_on(LEDS_GREEN); ds2411_init(); /* XXX hack: Fix it so that the 802.15.4 MAC address is compatible with an Ethernet MAC address - byte 0 (byte 2 in the DS ID) cannot be odd. */ ds2411_id[2] &= 0xfe; leds_on(LEDS_BLUE); xmem_init(); leds_off(LEDS_RED); rtimer_init(); /* * Hardware initialization done! */ #if WITH_TINYOS_AUTO_IDS node_id = TOS_NODE_ID; #else /* WITH_TINYOS_AUTO_IDS */ /* Restore node id if such has been stored in external mem */ node_id_restore(); #endif /* WITH_TINYOS_AUTO_IDS */ /* for setting "hardcoded" IEEE 802.15.4 MAC addresses */ #ifdef IEEE_802154_MAC_ADDRESS { uint8_t ieee[] = IEEE_802154_MAC_ADDRESS; memcpy(ds2411_id, ieee, sizeof(uip_lladdr.addr)); ds2411_id[7] = node_id & 0xff; } #endif random_init(ds2411_id[0] + node_id); leds_off(LEDS_BLUE); /* * Initialize Contiki and our processes. */ process_init(); process_start(&etimer_process, NULL); ctimer_init(); init_platform(); set_rime_addr(); cc2420_init(); { uint8_t longaddr[8]; uint16_t shortaddr; shortaddr = (rimeaddr_node_addr.u8[0] << 8) + rimeaddr_node_addr.u8[1]; memset(longaddr, 0, sizeof(longaddr)); rimeaddr_copy((rimeaddr_t *)&longaddr, &rimeaddr_node_addr); printf("MAC %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x ", longaddr[0], longaddr[1], longaddr[2], longaddr[3], longaddr[4], longaddr[5], longaddr[6], longaddr[7]); cc2420_set_pan_addr(IEEE802154_PANID, shortaddr, longaddr); } cc2420_set_channel(RF_CHANNEL); printf(CONTIKI_VERSION_STRING " started. "); if(node_id > 0) { printf("Node id is set to %u.\n", node_id); } else { printf("Node id is not set.\n"); } /* printf("MAC %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", ds2411_id[0], ds2411_id[1], ds2411_id[2], ds2411_id[3], ds2411_id[4], ds2411_id[5], ds2411_id[6], ds2411_id[7]);*/ #if WITH_UIP6 memcpy(&uip_lladdr.addr, ds2411_id, sizeof(uip_lladdr.addr)); /* Setup nullmac-like MAC for 802.15.4 */ /* sicslowpan_init(sicslowmac_init(&cc2420_driver)); */ /* printf(" %s channel %u\n", sicslowmac_driver.name, RF_CHANNEL); */ /* Setup X-MAC for 802.15.4 */ queuebuf_init(); NETSTACK_RDC.init(); NETSTACK_MAC.init(); NETSTACK_NETWORK.init(); printf("%s %s, channel check rate %lu Hz, radio channel %u\n", NETSTACK_MAC.name, NETSTACK_RDC.name, CLOCK_SECOND / (NETSTACK_RDC.channel_check_interval() == 0 ? 1: NETSTACK_RDC.channel_check_interval()), RF_CHANNEL); process_start(&tcpip_process, NULL); printf("Tentative link-local IPv6 address "); { uip_ds6_addr_t *lladdr; int i; lladdr = uip_ds6_get_link_local(-1); for(i = 0; i < 7; ++i) { printf("%02x%02x:", lladdr->ipaddr.u8[i * 2], lladdr->ipaddr.u8[i * 2 + 1]); } printf("%02x%02x\n", lladdr->ipaddr.u8[14], lladdr->ipaddr.u8[15]); } if(!UIP_CONF_IPV6_RPL) { uip_ipaddr_t ipaddr; int i; uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); uip_ds6_addr_add(&ipaddr, 0, ADDR_TENTATIVE); printf("Tentative global IPv6 address "); for(i = 0; i < 7; ++i) { printf("%02x%02x:", ipaddr.u8[i * 2], ipaddr.u8[i * 2 + 1]); } printf("%02x%02x\n", ipaddr.u8[7 * 2], ipaddr.u8[7 * 2 + 1]); } #else /* WITH_UIP6 */ NETSTACK_RDC.init(); NETSTACK_MAC.init(); NETSTACK_NETWORK.init(); printf("%s %s, channel check rate %lu Hz, radio channel %u\n", NETSTACK_MAC.name, NETSTACK_RDC.name, CLOCK_SECOND / (NETSTACK_RDC.channel_check_interval() == 0? 1: NETSTACK_RDC.channel_check_interval()), RF_CHANNEL); #endif /* WITH_UIP6 */ #if !WITH_UIP && !WITH_UIP6 uart1_set_input(serial_line_input_byte); serial_line_init(); #endif #if PROFILE_CONF_ON profile_init(); #endif /* PROFILE_CONF_ON */ leds_off(LEDS_GREEN); #if TIMESYNCH_CONF_ENABLED timesynch_init(); timesynch_set_authority_level((rimeaddr_node_addr.u8[0] << 4) + 16); #endif /* TIMESYNCH_CONF_ENABLED */ #if WITH_UIP process_start(&tcpip_process, NULL); process_start(&uip_fw_process, NULL); /* Start IP output */ process_start(&slip_process, NULL); slip_set_input_callback(set_gateway); { uip_ipaddr_t hostaddr, netmask; uip_init(); uip_ipaddr(&hostaddr, 172,16, rimeaddr_node_addr.u8[0],rimeaddr_node_addr.u8[1]); uip_ipaddr(&netmask, 255,255,0,0); uip_ipaddr_copy(&meshif.ipaddr, &hostaddr); uip_sethostaddr(&hostaddr); uip_setnetmask(&netmask); uip_over_mesh_set_net(&hostaddr, &netmask); /* uip_fw_register(&slipif);*/ uip_over_mesh_set_gateway_netif(&slipif); uip_fw_default(&meshif); uip_over_mesh_init(UIP_OVER_MESH_CHANNEL); printf("uIP started with IP address %d.%d.%d.%d\n", uip_ipaddr_to_quad(&hostaddr)); } #endif /* WITH_UIP */ energest_init(); ENERGEST_ON(ENERGEST_TYPE_CPU); watchdog_start(); print_processes(autostart_processes); autostart_start(autostart_processes); /* * This is the scheduler loop. */ #if DCOSYNCH_CONF_ENABLED timer_set(&mgt_timer, DCOSYNCH_PERIOD * CLOCK_SECOND); #endif /* watchdog_stop();*/ while(1) { int r; #if PROFILE_CONF_ON profile_episode_start(); #endif /* PROFILE_CONF_ON */ do { /* Reset watchdog. */ watchdog_periodic(); r = process_run(); } while(r > 0); #if PROFILE_CONF_ON profile_episode_end(); #endif /* PROFILE_CONF_ON */ /* * Idle processing. */ int s = splhigh(); /* Disable interrupts. */ /* uart1_active is for avoiding LPM3 when still sending or receiving */ if(process_nevents() != 0 || uart1_active()) { splx(s); /* Re-enable interrupts. */ } else { static unsigned long irq_energest = 0; #if DCOSYNCH_CONF_ENABLED /* before going down to sleep possibly do some management */ if(timer_expired(&mgt_timer)) { watchdog_periodic(); timer_reset(&mgt_timer); msp430_sync_dco(); #if CC2420_CONF_SFD_TIMESTAMPS cc2420_arch_sfd_init(); #endif /* CC2420_CONF_SFD_TIMESTAMPS */ } #endif /* Re-enable interrupts and go to sleep atomically. */ ENERGEST_OFF(ENERGEST_TYPE_CPU); ENERGEST_ON(ENERGEST_TYPE_LPM); /* We only want to measure the processing done in IRQs when we are asleep, so we discard the processing time done when we were awake. */ energest_type_set(ENERGEST_TYPE_IRQ, irq_energest); watchdog_stop(); /* check if the DCO needs to be on - if so - only LPM 1 */ if (msp430_dco_required) { _BIS_SR(GIE | CPUOFF); /* LPM1 sleep for DMA to work!. */ } else { _BIS_SR(GIE | SCG0 | SCG1 | CPUOFF); /* LPM3 sleep. This statement will block until the CPU is woken up by an interrupt that sets the wake up flag. */ } /* We get the current processing time for interrupts that was done during the LPM and store it for next time around. */ dint(); irq_energest = energest_type_time(ENERGEST_TYPE_IRQ); eint(); watchdog_start(); ENERGEST_OFF(ENERGEST_TYPE_LPM); ENERGEST_ON(ENERGEST_TYPE_CPU); } } return 0; }
/*---------------------------------------------------------------------------*/ static int send_packet(void) { frame802154_t params; uint8_t len; /* 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(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 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.dest_addr_mode = FRAME802154_SHORTADDRMODE; params.dest_addr.u8[0] = 0xFF; params.dest_addr.u8[1] = 0xFF; } else { rimeaddr_copy(¶ms.dest_addr, packetbuf_addr(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. */ rimeaddr_copy(¶ms.src_addr, &rimeaddr_node_addr); params.payload = packetbuf_dataptr(); params.payload_len = packetbuf_datalen(); len = frame802154_hdrlen(¶ms); if(packetbuf_hdralloc(len)) { frame802154_create(¶ms, packetbuf_hdrptr(), len); PRINTF("6MAC-UT: %2X", params.fcf.frame_type); PRINTADDR(params.dest_addr.u8); PRINTF("%u %u (%u)\n", len, packetbuf_datalen(), packetbuf_totlen()); return radio->send(packetbuf_hdrptr(), packetbuf_totlen()); } else { PRINTF("6MAC-UT: too large header: %u\n", len); } return 0; }
/*---------------------------------------------------------------------------*/ static void recv_mesh(struct mesh_conn *mesh, const rimeaddr_t *from, uint8_t hops) { struct rudolph1mh_conn *c = (struct rudolph1mh_conn *) ((char *) mesh - offsetof(struct rudolph1mh_conn, mesh)); struct rudolph1mh_datapacket *p = packetbuf_dataptr(); PRINTF("%d.%d: Got mesh type %d from %d.%d\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], p->h.type, from->u8[0], from->u8[1]); if(!rimeaddr_cmp(&c->partner, from)){ if(!rimeaddr_cmp(&c->partner, &rimeaddr_null)){ rimeaddr_t lfrom; PRINTF("%d.%d: Unexpected packet from %d.%d\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], from->u8[0], from->u8[1]); rimeaddr_copy(&lfrom, from); send_busy(c, &lfrom); return; } else { rimeaddr_copy(&c->partner, from); } } if(p->h.type == TYPE_ACK){ if(p->h.s_id == c->s_id && p->h.chunk == c->highest_chunk){ ctimer_stop(&c->t); rimeaddr_copy(&c->partner, &rimeaddr_null); if(c->cb->read_done){ c->cb->read_done(c); } PRINTF("GOT ACK\n"); } else { PRINTF("Unexpected ACK sid %i,%i C %i,%i\n", p->h.s_id, c->s_id, p->h.chunk, c->highest_chunk); } } else if(p->h.type == TYPE_NACK) { c->nacks++; PRINTF("%d.%d: Got NACK for %d:%d (%d:%d)\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], p->h.s_id, p->h.chunk, c->s_id, c->chunk); if(p->h.s_id == c->s_id) { if(p->h.chunk < c->chunk) { /* Format and send a repair packet */ PRINTF("%d.%d: sending repair for chunk %d\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], p->h.chunk); format_data(c, p->h.chunk); mesh_send(&c->mesh, &c->partner); } } else if(LT(p->h.s_id, c->s_id)) { format_data(c, 0); mesh_send(&c->mesh, &c->partner); } } else if(p->h.type == TYPE_DATA ) { /* This is a repair packet from someone else. */ PRINTF("%d.%d: got chunk %d\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], p->h.chunk); handle_data(c, p); } else if(p->h.type == TYPE_FIN ) { /* This is a repair packet from someone else. */ PRINTF("%d.%d: got last chunk %d\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], p->h.chunk); if(!rimeaddr_cmp(&c->partner, &rimeaddr_null)){ handle_data(c, p); }{ rimeaddr_copy(&c->partner, from); } send_ack(c); rimeaddr_copy(&c->partner, &rimeaddr_null); } else if(p->h.type == TYPE_BUSY){ PRINTF("%d.%d: %d.%d is busy\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], from->u8[0], from->u8[1]); //Wait } }