Beispiel #1
0
/*---------------------------------------------------------------------------*/
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);
}
Beispiel #3
0
/*---------------------------------------------------------------------------*/
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), &notifyBurstyLinkNeighbor_m);
		rimeaddr_copy(&notifyBurstyLinkNeighbor_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(&current_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(&current_packet);

  /* Clear the accumulated power consumption so that it is ready for
     the next packet. */
  compower_clear(&current_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;
}
Beispiel #8
0
/*---------------------------------------------------------------------------*/
static int
create(void)
{
  frame802154_t params;
  int len;

  /* init to zeros */
  memset(&params, 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 *)&params.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 *)&params.src_addr, &rimeaddr_node_addr);

  params.payload = packetbuf_dataptr();
  params.payload_len = packetbuf_datalen();
  len = frame802154_hdrlen(&params);
  if(packetbuf_hdralloc(len)) {
    frame802154_create(&params, 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;
  }
}
Beispiel #9
0
/* 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);
}
Beispiel #10
0
/*---------------------------------------------------------------------------*/
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));
}
Beispiel #11
0
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();       
               
                
       }
} 
Beispiel #12
0
/*---------------------------------------------------------------------------*/
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(&current_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(&current_packet);

      /* Clear the accumulated power consumption so that it is ready
         for the next packet. */
      compower_clear(&current_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());
  }
}
Beispiel #13
0
/*---------------------------------------------------------------------------*/
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(&current_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(&current_packet);

  /* Clear the accumulated power consumption so that it is ready for
     the next packet. */
  compower_clear(&current_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;
}
Beispiel #14
0
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 */
}
Beispiel #16
0
/* 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(&params, 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 *)&params.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 *)&params.src_addr, &rimeaddr_node_addr);
    rimeaddr_copy((rimeaddr_t *)&params.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(&params);
    frame802154_create(&params, packetbuf_hdrptr(), len);
    NETSTACK_RADIO.send(packetbuf_hdrptr(), packetbuf_totlen());
    return;
}
Beispiel #17
0
/*---------------------------------------------------------------------------*/
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(&current_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(&current_packet);

	/* Clear the accumulated power consumption so that it is ready
	   for the next packet. */
	compower_clear(&current_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());
  }
}
Beispiel #20
0
/*---------------------------------------------------------------------------*/
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(&notifyBurstyLinkNeighbor_m, neighbor_p);
} 
Beispiel #22
0
/**
 *
 * 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;
}
Beispiel #24
0
/*---------------------------------------------------------------------------*/
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;

}
Beispiel #25
0
/* 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));
}
Beispiel #26
0
/*---------------------------------------------------------------------------*/
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;
}
Beispiel #27
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(&current_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(&current_packet);

      /* Clear the accumulated power consumption so that it is ready
         for the next packet. */
      compower_clear(&current_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;
}
Beispiel #29
0
/*---------------------------------------------------------------------------*/
static int
send_packet(void)
{
  frame802154_t params;
  uint8_t len;

  /* init to zeros */
  memset(&params, 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(&params.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(&params.src_addr, &rimeaddr_node_addr);

  params.payload = packetbuf_dataptr();
  params.payload_len = packetbuf_datalen();
  len = frame802154_hdrlen(&params);
  if(packetbuf_hdralloc(len)) {
    frame802154_create(&params, 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;
}
Beispiel #30
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
  }
}