Exemplo n.º 1
0
/*---------------------------------------------------------------------------*/
static void
qsend_list(mac_callback_t sent, void *ptr, struct rdc_buf_list *buf_list)
{
  struct rdc_buf_list *curr = buf_list;
  struct rdc_buf_list *next;
  int ret;
  int is_receiver_awake;
  
  if(curr == NULL) {
    return;
  }
  /* Do not send during reception of a burst */
  if(we_are_receiving_burst) {
    /* Prepare the packetbuf for callback */
    queuebuf_to_packetbuf(curr->buf);
    /* Return COLLISION so the MAC may try again later */
    mac_call_sent_callback(sent, ptr, MAC_TX_COLLISION, 1);
    return;
  }
  /* The receiver needs to be awoken before we send */
  is_receiver_awake = 0;
  do { /* A loop sending a burst of packets from buf_list */
    next = list_item_next(curr);

    /* Prepare the packetbuf */
    queuebuf_to_packetbuf(curr->buf);
    if(next != NULL) {
      packetbuf_set_attr(PACKETBUF_ATTR_PENDING, 1);
    }

    /* Send the current packet */
    ret = send_packet(sent, ptr, curr, is_receiver_awake);
    if(ret != MAC_TX_DEFERRED) {
      mac_call_sent_callback(sent, ptr, ret, 1);
    }

    if(ret == MAC_TX_OK) {
      if(next != NULL) {
        /* We're in a burst, no need to wake the receiver up again */
        is_receiver_awake = 1;
        curr = next;
      }
    } else {
      /* The transmission failed, we stop the burst */
      next = NULL;
    }
  } while(next != NULL);
}
Exemplo n.º 2
0
/*---------------------------------------------------------------------------*/
static void send_list(mac_callback_t sent, void *ptr, struct rdc_buf_list *buf_list) {
    // printf("WPI-MAC-send_list(), node ID: %u\n", node_id);
    if(buf_list != NULL) {
        queuebuf_to_packetbuf(buf_list->buf);
        send_packet(sent, ptr);
    }
}
Exemplo n.º 3
0
/*---------------------------------------------------------------------------*/
static void
transmit_queued_packet(void *ptr)
{
  /*  struct queued_packet *q = ptr;*/
  struct queued_packet *q;

  /* Don't transmit a packet if the RDC is still transmitting the
     previous one. */
  if(rdc_is_transmitting) {
    return;
  }
  
  //  printf("q %d\n", list_length(queued_packet_list));

  q = list_head(queued_packet_list);

  if(q != NULL) {
    queuebuf_to_packetbuf(q->buf);
    PRINTF("csma: sending number %d %p, queue len %d\n", q->transmissions, q,
           list_length(queued_packet_list));
    //    printf("s %d\n", packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[0]);
    rdc_is_transmitting = 1;
    NETSTACK_RDC.send(packet_sent, q);
  }
}
Exemplo n.º 4
0
/*---------------------------------------------------------------------------*/
static void
found_route(struct route_discovery_conn *rdc, const rimeaddr_t *dest)
{
  struct route_entry *rt;
  struct mesh_conn *c = (struct mesh_conn *)
    ((char *)rdc - offsetof(struct mesh_conn, route_discovery_conn));

  PRINTF("found_route\n");

  if(c->queued_data != NULL &&
     rimeaddr_cmp(dest, &c->queued_data_dest)) {
    queuebuf_to_packetbuf(c->queued_data);
    queuebuf_free(c->queued_data);
    c->queued_data = NULL;

    rt = route_lookup(dest);
    if(rt != NULL) {
      multihop_resend(&c->multihop, &rt->R_next_addr);
      if(c->cb->sent != NULL) {
        c->cb->sent(c);
      }
    } else {
      if(c->cb->timedout != NULL) {
        c->cb->timedout(c);
      }
    }
  }
}
Exemplo n.º 5
0
/*---------------------------------------------------------------------------*/
static void
send_broadcast(mac_callback_t sent, void *ptr)
{
    struct queuebuf *qb;

    qb = queuebuf_new_from_packetbuf();
    if(!qb || (NETSTACK_FRAMER.create() < 0)) {
        PRINTF("coresec-strategy: Did not send broadcast\n");
        if(qb) {
            queuebuf_free(qb);
        }
        sent(ptr, MAC_TX_ERR, 0);
        return;
    }

    prepare_announce();
    adaptivesec_send_command_frame();
    watchdog_periodic();

    queuebuf_to_packetbuf(qb);
    queuebuf_free(qb);
#if WITH_BROADCAST_ENCRYPTION
    {
        uint8_t ignore[ADAPTIVESEC_BROADCAST_MIC_LEN];

        if(packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL) & (1 << 2)) {
            adaptivesec_aead(adaptivesec_group_key, 1, ignore, 1);
        }
    }
#endif /* WITH_BROADCAST_ENCRYPTION */
    NETSTACK_MAC.send(sent, ptr);
}
Exemplo n.º 6
0
/*---------------------------------------------------------------------------*/
static void
qsend_list(mac_callback_t sent, void *ptr, struct rdc_buf_list *buf_list)
{
  if(buf_list != NULL) {
    queuebuf_to_packetbuf(buf_list->buf);
    qsend_packet(sent, ptr);
  }
}
Exemplo n.º 7
0
/*---------------------------------------------------------------------------*/
static void
send_queued_packet(void)
{
    struct queuebuf *q;
    struct neighbor *n;
    struct packetqueue_item *i;
    struct collect_conn *c;

    i = packetqueue_first(&forwarding_queue);
    if(i == NULL) {
        PRINTF("%d.%d: nothing on queue\n",
               rimeaddr_node_addr.u8[RIMEADDR_SIZE-2], rimeaddr_node_addr.u8[RIMEADDR_SIZE-1]);
        /* No packet on the queue, so there is nothing for us to send. */
        return;
    }
    c = packetqueue_ptr(i);
    if(c == NULL) {
        /* c should not be NULL, but we check it just to be sure. */
        PRINTF("%d.%d: queue, c == NULL!\n",
               rimeaddr_node_addr.u8[RIMEADDR_SIZE-2], rimeaddr_node_addr.u8[RIMEADDR_SIZE-1]);
        return;
    }

    if(c->forwarding) {
        /* If we are currently forwarding a packet, we wait until the
           packet is forwarded and try again then. */
        PRINTF("%d.%d: queue, c is forwarding\n",
               rimeaddr_node_addr.u8[RIMEADDR_SIZE-2], rimeaddr_node_addr.u8[RIMEADDR_SIZE-1]);
        return;
    }

    q = packetqueue_queuebuf(i);
    if(q != NULL) {
        PRINTF("%d.%d: queue, q is on queue\n",
               rimeaddr_node_addr.u8[RIMEADDR_SIZE-2], rimeaddr_node_addr.u8[RIMEADDR_SIZE-1]);
        queuebuf_to_packetbuf(q);

        n = neighbor_best();

        /* Don't send to the neighbor if it is the same neighbor that sent
           us the packet. */
        if(n != NULL && !rimeaddr_cmp(&n->addr, packetbuf_addr(PACKETBUF_ADDR_SENDER))) {
#if CONTIKI_TARGET_NETSIM
            ether_set_line(n->addr.u8[0], n->addr.u8[1]);
#endif /* CONTIKI_TARGET_NETSIM */
            PRINTF("%d.%d: sending packet to %d.%d\n",
                   rimeaddr_node_addr.u8[RIMEADDR_SIZE-2], rimeaddr_node_addr.u8[RIMEADDR_SIZE-1],
                   n->addr.u8[RIMEADDR_SIZE-2], n->addr.u8[RIMEADDR_SIZE-1]);

            c->forwarding = 1;
            runicast_send(&c->runicast_conn, &n->addr, packetbuf_attr(PACKETBUF_ATTR_MAX_REXMIT));
        } else {
            PRINTF("%d.%d: did not find any neighbor to forward to\n",
                   rimeaddr_node_addr.u8[RIMEADDR_SIZE-2], rimeaddr_node_addr.u8[RIMEADDR_SIZE-1]);
        }
    }
}
Exemplo n.º 8
0
/*---------------------------------------------------------------------------*/
static void
recv_from_ipolite(struct ipolite_conn *ipolite, const rimeaddr_t *from)
{
    PRINTF("%d.%d: netflood recv_from_ipolite\n",
	   rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1]);

  struct netflood_conn *c = (struct netflood_conn *)ipolite;
  struct netflood_hdr hdr;
  uint8_t hops;
  struct queuebuf *queuebuf;

  memcpy(&hdr, packetbuf_dataptr(), sizeof(struct netflood_hdr));
  hops = hdr.hops;

  /* Remember packet if we need to forward it. */
  queuebuf = queuebuf_new_from_packetbuf();

  packetbuf_hdrreduce(sizeof(struct netflood_hdr));
  if(c->u->recv != NULL) {
    if(!(rimeaddr_cmp(&hdr.originator, &c->last_originator) &&
	 hdr.originator_seqno <= c->last_originator_seqno)) {

      if(c->u->recv(c, from, &hdr.originator, hdr.originator_seqno,
		    hops)) {
	
	if(queuebuf != NULL) {
	  queuebuf_to_packetbuf(queuebuf);
	  queuebuf_free(queuebuf);
	  queuebuf = NULL;
	  memcpy(&hdr, packetbuf_dataptr(), sizeof(struct netflood_hdr));
	  
	  /* Rebroadcast received packet. */
	  if(hops < HOPS_MAX) {
	    PRINTF("%d.%d: netflood rebroadcasting %d.%d/%d (%d.%d/%d) hops %d\n",
		   rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
		   hdr.originator.u8[0], hdr.originator.u8[1],
		   hdr.originator_seqno,
		   c->last_originator.u8[0], c->last_originator.u8[1],
		   c->last_originator_seqno,
		  hops);
	    hdr.hops++;
	    memcpy(packetbuf_dataptr(), &hdr, sizeof(struct netflood_hdr));
	    send(c);
	    rimeaddr_copy(&c->last_originator, &hdr.originator);
	    c->last_originator_seqno = hdr.originator_seqno;
	  }
	}
      }
    }
  }
  if(queuebuf != NULL) {
    queuebuf_free(queuebuf);
  }
}
Exemplo n.º 9
0
/*---------------------------------------------------------------------------*/
uint8_t
send_list(struct net_buf *buf, mac_callback_t sent, void *ptr, struct rdc_buf_list *buf_list)
{
  if(buf_list != NULL) {
    queuebuf_to_packetbuf(buf, buf_list->buf);
    if (!send_packet(buf, sent, ptr)) {
      return 0;
    }
  }

  return 1;
}
Exemplo n.º 10
0
/*---------------------------------------------------------------------------*/
static void
send(void *ptr) {
    struct trickle_conn *c = ptr;

    if (c->q != NULL) {
        queuebuf_to_packetbuf(c->q);
        broadcast_send(&c->c);
    } else {
        PRINTF("%d.%d: trickle send but c->q == NULL\n",
                rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1]);
    }
}
Exemplo n.º 11
0
/*---------------------------------------------------------------------------*/
static void
send(void *ptr)
{
  struct stbroadcast_conn *c = ptr;

  /*  DEBUGF(3, "stbroadcast: send()\n");*/
  queuebuf_to_packetbuf(c->buf);
  broadcast_send(&c->c);
  ctimer_reset(&c->t);
  if(c->u->sent != NULL) {
    c->u->sent(c);
  }
}
Exemplo n.º 12
0
/*---------------------------------------------------------------------------*/
static void
found_route(struct route_discovery_conn *rdc, rimeaddr_t *dest)
{
  struct mesh_conn *c = (struct mesh_conn *)
    ((char *)rdc - offsetof(struct mesh_conn, route_discovery_conn));

  if(c->queued_data != NULL &&
     rimeaddr_cmp(dest, &c->queued_data_dest)) {
    queuebuf_to_packetbuf(c->queued_data);
    queuebuf_free(c->queued_data);
    c->queued_data = NULL;
    multihop_send(&c->multihop, dest);
  }
}
Exemplo n.º 13
0
/*---------------------------------------------------------------------------*/
static void
send(void *ptr)
{
  struct polite_conn *c = ptr;

  if(c->q != NULL) {
    queuebuf_to_packetbuf(c->q);
    queuebuf_free(c->q);
    c->q = NULL;
    abc_send(&c->c);
    if(c->cb->sent) {
	c->cb->sent(c);
    }
  }
}
Exemplo n.º 14
0
/*---------------------------------------------------------------------------*/
static void
send_packet(void *ptr)
{
  struct phase_queueitem *p = ptr;

  if(p->buf_list == NULL) {
    queuebuf_to_packetbuf(p->q);
    queuebuf_free(p->q);
    NETSTACK_RDC.send(p->mac_callback, p->mac_callback_ptr);
  } else {
    NETSTACK_RDC.send_list(p->mac_callback, p->mac_callback_ptr, p->buf_list);
  }

  memb_free(&queued_packets_memb, p);
}
Exemplo n.º 15
0
/*---------------------------------------------------------------------------*/
static void
send_broadcast(mac_callback_t sent, void *ptr)
{
  struct queuebuf *qb;
#if ANTI_REPLAY_WITH_SUPPRESSION
  uint16_t frame_counter_bytes_0_1;
  uint16_t frame_counter_bytes_2_3;
  uint8_t seqno;

  frame_counter_bytes_0_1 = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1);
  frame_counter_bytes_2_3 = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3);
  seqno = packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO);
  adaptivesec_add_security_header(NULL);
#endif /* ANTI_REPLAY_WITH_SUPPRESSION */
  qb = queuebuf_new_from_packetbuf();
  if(!qb || (NETSTACK_FRAMER.create() < 0)) {
    PRINTF("coresec-strategy: Did not send broadcast\n");
    if(qb) {
      queuebuf_free(qb);
    }
    sent(ptr, MAC_TX_ERR, 0);
    return;
  }

  prepare_announce();
#if ANTI_REPLAY_WITH_SUPPRESSION
  packetbuf_set_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1, frame_counter_bytes_0_1);
  packetbuf_set_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3, frame_counter_bytes_2_3);
  packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, seqno);
#endif /* ANTI_REPLAY_WITH_SUPPRESSION */
  adaptivesec_send_command_frame();
  watchdog_periodic();

  queuebuf_to_packetbuf(qb);
  queuebuf_free(qb);
#if WITH_BROADCAST_ENCRYPTION
  {
    uint8_t ignore[ADAPTIVESEC_BROADCAST_MIC_LEN];

    if(adaptivesec_get_sec_lvl() & (1 << 2)) {
      adaptivesec_aead(adaptivesec_group_key, 1, ignore, 1);
    }
  }
#endif /* WITH_BROADCAST_ENCRYPTION */
  NETSTACK_MAC.send(sent, ptr);
}
Exemplo n.º 16
0
/*---------------------------------------------------------------------------*/
static void
send(void *ptr)
{
  struct stunicast_conn *c = ptr;

  PRINTF("%d.%d: stunicast: resend to %d.%d\n",
	 rimeaddr_node_addr.u8[0],rimeaddr_node_addr.u8[1],
	 c->receiver.u8[0], c->receiver.u8[1]);
	 if(c->buf) {
  	queuebuf_to_packetbuf(c->buf);
  	unicast_send(&c->c, &c->receiver);
  	stunicast_set_timer(c, CLOCK_SECOND);
  }
  /*  if(c->u->sent != NULL) {
    c->u->sent(c);
    }*/
}
Exemplo n.º 17
0
/*---------------------------------------------------------------------------*/
static void
new_route(struct route_discovery_conn *c, const linkaddr_t *to)
{
  struct route_entry *rt;
  
  if(queued_packet) {
    PRINTF("uip-over-mesh: new route, sending queued packet\n");
    
    queuebuf_to_packetbuf(queued_packet);
    queuebuf_free(queued_packet);
    queued_packet = NULL;

    rt = route_lookup(&queued_receiver);
    if(rt) {
      route_decay(rt);
      send_data(&queued_receiver);
    }
  }
}
Exemplo n.º 18
0
/*---------------------------------------------------------------------------*/
static void
send(void *ptr)
{
  struct ipolite_conn *c = ptr;
  
  PRINTF("%d.%d: ipolite: send queuebuf %p\n",
	 linkaddr_node_addr.u8[0],linkaddr_node_addr.u8[1],
	 c->q);
  
  if(c->q != NULL) {
    queuebuf_to_packetbuf(c->q);
    queuebuf_free(c->q);
    c->q = NULL;
    broadcast_send(&c->c);
    if(c->cb->sent) {
      c->cb->sent(c);
    }
  }
}
Exemplo n.º 19
0
/* Pass sent packets to upper layer */
static void
tsch_tx_process_pending()
{
  int16_t dequeued_index;
  /* Loop on accessing (without removing) a pending input packet */
  while((dequeued_index = ringbufindex_peek_get(&dequeued_ringbuf)) != -1) {
    struct tsch_packet *p = dequeued_array[dequeued_index];
    /* Put packet into packetbuf for packet_sent callback */
    queuebuf_to_packetbuf(p->qb);
    /* Call packet_sent callback */
    mac_call_sent_callback(p->sent, p->ptr, p->ret, p->transmissions);
    /* Free packet queuebuf */
    tsch_queue_free_packet(p);
    /* Free all unused neighbors */
    tsch_queue_free_unused_neighbors();
    /* Remove dequeued packet from ringbuf */
    ringbufindex_get(&dequeued_ringbuf);
  }
}
Exemplo n.º 20
0
static uint8_t send_packet_list(struct net_buf *buf,
				mac_callback_t sent_callback,
				void *ptr, struct rdc_buf_list *list)
{
	while (list) {
		struct rdc_buf_list *next = list->next;
		int last_sent_ok;

		queuebuf_to_packetbuf(buf, list->buf);

		last_sent_ok = send_packet(buf, sent_callback, ptr);
		if (!last_sent_ok) {
			return 0;
		}

		list = next;
	}

	return 1;
}
Exemplo n.º 21
0
/*---------------------------------------------------------------------------*/
static void
send_list(mac_callback_t sent, void *ptr, struct rdc_buf_list *buf_list)
{
  while(buf_list != NULL) {
    /* We backup the next pointer, as it may be nullified by
     * mac_call_sent_callback() */
    struct rdc_buf_list *next = buf_list->next;
    int last_sent_ok;

    queuebuf_to_packetbuf(buf_list->buf);
    last_sent_ok = send_one_packet(sent, ptr);

    /* If packet transmission was not successful, we should back off and let
     * upper layers retransmit, rather than potentially sending out-of-order
     * packet fragments. */
    if(!last_sent_ok) {
      return;
    }
    buf_list = next;
  }
}
Exemplo n.º 22
0
/*---------------------------------------------------------------------------*/
static void
remove_queued_packet(struct queue_list_item *i, uint8_t tx_ok)
{
  mac_callback_t sent;
  void *ptr;
  int num_transmissions = 0;
  int status;
  
  PRINTF("%d.%d: removing queued packet\n",
	 rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1]);


  queuebuf_to_packetbuf(i->packet);
  
  ctimer_stop(&i->removal_timer);
  queuebuf_free(i->packet);
  list_remove(pending_packets_list, i);
  list_remove(queued_packets_list, i);

  /* XXX potential optimization */
  if(list_length(queued_packets_list) == 0 && is_listening == 0) {
    turn_radio_off();
    compower_accumulate(&i->compower);
  }

  sent = i->sent_callback;
  ptr = i->sent_callback_ptr;
  num_transmissions = i->num_transmissions;
  memb_free(&queued_packets_memb, i);
  if(num_transmissions == 0 || tx_ok == 0) {
    status = MAC_TX_NOACK;
  } else {
    status = MAC_TX_OK;
  }
  mac_call_sent_callback(sent, ptr, status, num_transmissions);
}
Exemplo n.º 23
0
/*---------------------------------------------------------------------------*/
static void
qsend_list(mac_callback_t sent, void *ptr, struct rdc_buf_list *buf_list)
{
  struct rdc_buf_list *curr;
  struct rdc_buf_list *next;
  int ret;
  int is_receiver_awake;
  
  if(buf_list == NULL) {
    return;
  }
  /* Do not send during reception of a burst */
  if(we_are_receiving_burst) {
    /* Prepare the packetbuf for callback */
    queuebuf_to_packetbuf(buf_list->buf);
    /* Return COLLISION so the MAC may try again later */
    mac_call_sent_callback(sent, ptr, MAC_TX_COLLISION, 1);
    return;
  }
  
  /* Create and secure frames in advance */
  curr = buf_list;
  do {
    next = list_item_next(curr);
    queuebuf_to_packetbuf(curr->buf);
    if(!packetbuf_attr(PACKETBUF_ATTR_IS_CREATED_AND_SECURED)) {
      /* create and secure this frame */
      if(next != NULL) {
        packetbuf_set_attr(PACKETBUF_ATTR_PENDING, 1);
      }
      packetbuf_set_attr(PACKETBUF_ATTR_MAC_ACK, 1);
      if(NETSTACK_FRAMER.create_and_secure() < 0) {
        PRINTF("contikimac: framer failed\n");
        mac_call_sent_callback(sent, ptr, MAC_TX_ERR_FATAL, 1);
        return;
      }
      
      packetbuf_set_attr(PACKETBUF_ATTR_IS_CREATED_AND_SECURED, 1);
      queuebuf_update_from_packetbuf(curr->buf);
    }
    curr = next;
  } while(next != NULL);
  
  /* The receiver needs to be awaken before we send */
  is_receiver_awake = 0;
  curr = buf_list;
  do { /* A loop sending a burst of packets from buf_list */
    next = list_item_next(curr);

    /* Prepare the packetbuf */
    queuebuf_to_packetbuf(curr->buf);
    
    /* Send the current packet */
    ret = send_packet(sent, ptr, curr, is_receiver_awake);
    if(ret != MAC_TX_DEFERRED) {
      mac_call_sent_callback(sent, ptr, ret, 1);
    }

    if(ret == MAC_TX_OK) {
      if(next != NULL) {
        /* We're in a burst, no need to wake the receiver up again */
        is_receiver_awake = 1;
        curr = next;
      }
    } else {
      /* The transmission failed, we stop the burst */
      next = NULL;
    }
  } while((next != NULL) && packetbuf_attr(PACKETBUF_ATTR_PENDING));
}
Exemplo n.º 24
0
/*---------------------------------------------------------------------------*/
static void
recv_from_stunicast(struct stunicast_conn *stunicast, const rimeaddr_t *from)
{
  struct runicast_conn *c = (struct runicast_conn *)stunicast;
  /*  struct runicast_hdr *hdr = packetbuf_dataptr();*/

  PRINTF("%d.%d: runicast: recv_from_stunicast from %d.%d type %d seqno %d\n",
	 rimeaddr_node_addr.u8[0],rimeaddr_node_addr.u8[1],
	 from->u8[0], from->u8[1],
	 packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE),
	 packetbuf_attr(PACKETBUF_ATTR_PACKET_ID));

  if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) ==
     PACKETBUF_ATTR_PACKET_TYPE_ACK) {
      PRINTF("%d.%d: runicast: got ACK from %d.%d, seqno %d (%d)\n",
	     rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
	     from->u8[0], from->u8[1],
	     packetbuf_attr(PACKETBUF_ATTR_PACKET_ID),
	     c->sndnxt);
    if(packetbuf_attr(PACKETBUF_ATTR_PACKET_ID) == c->sndnxt) {
      RIMESTATS_ADD(ackrx);
      PRINTF("%d.%d: runicast: ACKed %d\n",
	     rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
	     packetbuf_attr(PACKETBUF_ATTR_PACKET_ID));
      c->sndnxt = (c->sndnxt + 1) % (1 << RUNICAST_PACKET_ID_BITS);
      c->is_tx = 0;
      stunicast_cancel(&c->c);
      if(c->u->sent != NULL) {
	c->u->sent(c, stunicast_receiver(&c->c), c->rxmit);
      }
    } else {
      PRINTF("%d.%d: runicast: received bad ACK %d for %d\n",
	     rimeaddr_node_addr.u8[0],rimeaddr_node_addr.u8[1],
	     packetbuf_attr(PACKETBUF_ATTR_PACKET_ID),
	     c->sndnxt);
      RIMESTATS_ADD(badackrx);
    }
  } else if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) ==
	    PACKETBUF_ATTR_PACKET_TYPE_DATA) {
    /*    int send_ack = 1;*/
    uint16_t packet_seqno;
    struct queuebuf *q;

    RIMESTATS_ADD(reliablerx);

    PRINTF("%d.%d: runicast: got packet %d\n",
	   rimeaddr_node_addr.u8[0],rimeaddr_node_addr.u8[1],
	   packetbuf_attr(PACKETBUF_ATTR_PACKET_ID));

    packet_seqno = packetbuf_attr(PACKETBUF_ATTR_PACKET_ID);

    /*    packetbuf_hdrreduce(sizeof(struct runicast_hdr));*/

    q = queuebuf_new_from_packetbuf();
    if(q != NULL) {
      PRINTF("%d.%d: runicast: Sending ACK to %d.%d for %d\n",
	     rimeaddr_node_addr.u8[0],rimeaddr_node_addr.u8[1],
	     from->u8[0], from->u8[1],
	     packet_seqno);
      packetbuf_clear();
      /*    packetbuf_hdralloc(sizeof(struct runicast_hdr));
	    hdr = packetbuf_hdrptr();
	    hdr->type = TYPE_ACK;
	    hdr->seqno = packet_seqno;*/
      packetbuf_set_attr(PACKETBUF_ATTR_PACKET_TYPE, PACKETBUF_ATTR_PACKET_TYPE_ACK);
      packetbuf_set_attr(PACKETBUF_ATTR_PACKET_ID, packet_seqno);
      stunicast_send(&c->c, from);
      RIMESTATS_ADD(acktx);

      queuebuf_to_packetbuf(q);
      queuebuf_free(q);
    } else {
      PRINTF("%d.%d: runicast: could not send ACK to %d.%d for %d: no queued buffers\n",
	     rimeaddr_node_addr.u8[0],rimeaddr_node_addr.u8[1],
	     from->u8[0], from->u8[1],
	     packet_seqno);
    }
    if(c->u->recv != NULL) {
      c->u->recv(c, from, packet_seqno);
    }
  }
}
Exemplo n.º 25
0
/*---------------------------------------------------------------------------*/
static int
send_packet(void)
{
  rtimer_clock_t t0;
  rtimer_clock_t t;
  rtimer_clock_t encounter_time = 0;
  int strobes;
  int ret;
#if 0
  struct xmac_hdr *hdr;
#endif
  uint8_t got_strobe_ack = 0;
  uint8_t got_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); */

  packetbuf_set_attr(PACKETBUF_ATTR_MAC_ACK, 1);
  len = NETSTACK_FRAMER.create();
  strobe_len = len + sizeof(struct xmac_hdr);
  if(len < 0 || strobe_len > (int)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);
      if(wait < 2 * DEFAULT_ON_TIME) {
        wait = 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)) {
#if 0
	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() >= 0) {
	    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);
	  }
	}
#endif /* 0 */
      }
      
      t = RTIMER_NOW();
            /* Send the strobe packet. */
      if(got_strobe_ack == 0 && collisions == 0) {

	if(is_broadcast) {
#if WITH_STROBE_BROADCAST
	  ret = NETSTACK_RADIO.send(strobe, strobe_len);
#else
	  /* restore the packet to send */
	  queuebuf_to_packetbuf(packet);
	  ret = NETSTACK_RADIO.send(packetbuf_hdrptr(), packetbuf_totlen());
#endif
          off();
	} else {
#if 0
	  rtimer_clock_t wt;
#endif
          on();
	  ret = NETSTACK_RADIO.send(strobe, strobe_len);
#if 0
	  /* 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 */
#if RDC_CONF_HARDWARE_ACK
          if(ret == RADIO_TX_OK) {
            got_strobe_ack = 1;
          } else {
            off();
          }
#else
          if(detect_ack()) {
            got_strobe_ack = 1;
          } else {
            off();
          }
#endif /* RDC_CONF_HARDWARE_ACK */

        }
      }
    }
  }

#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();
  }
#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) {
    ret = NETSTACK_RADIO.send(packetbuf_hdrptr(), packetbuf_totlen());

    if(!is_broadcast) {
#if RDC_CONF_HARDWARE_ACK
      if(ret == RADIO_TX_OK) {
        got_ack = 1;
      }
#else
      if(detect_ack()) {
        got_ack = 1;
      }
#endif /* RDC_CONF_HARDWARE_ACK */
    }
  }
  off();

#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 == 0 && got_ack == 0) {
      return MAC_TX_NOACK;
    } else {
      return MAC_TX_OK;
    }
  } else {
    someone_is_sending++;
    return MAC_TX_COLLISION;
  }

}
Exemplo n.º 26
0
/*---------------------------------------------------------------------------*/
static void real_send(mac_callback_t sent, void *ptr, struct queuebuf *pkt) {
    int ret;
    uint8_t contention_strobe[MAX_STROBE_SIZE];
    unsigned char won_contention = 0;

    int len = NETSTACK_FRAMER.create();
    if(len < 0) {
        // off(TURN_OFF);
        /* Failed to send */
        printf("WPI-MAC: send failed, too large header\n");
        mac_call_sent_callback(sent, ptr, MAC_TX_ERR_FATAL, 1);
    } else {
        // randomly pick slot
        random_init(RTIMER_NOW() * node_id);
        unsigned short rand_slot = map_rand(random_rand());
        // make filler packet
        memcpy(contention_strobe, packetbuf_hdrptr(), len);
        // strobe needs to cover at least one CCA_CONTENTION slot
        // plus any additional slots we need to cover
        unsigned short j;
        unsigned short fill_amount = (CCA_CONTENTION_SIZE - len) + (CONTENTION_SIZE * ((CONTENTION_SLOTS - 1) - rand_slot));
        for(j = 0; j < fill_amount; j++) {
            contention_strobe[len] = 7;
            len++;
        }

        rtimer_clock_t start_of_cont;

        // wait for prep period to end
        while(RTIMER_CLOCK_LT(RTIMER_NOW(), last + CONTENTION_PREPARE));
        start_of_cont = RTIMER_NOW();

        // wait for our random slot
        unsigned short cont_slot = 0;
        while(!(cont_slot == rand_slot)) {
            while(RTIMER_CLOCK_LT(RTIMER_NOW(), start_of_cont + CONTENTION_TICKS));
            start_of_cont = RTIMER_NOW();
            cont_slot++;
        }

        // NOW its our turn
        if(!radio_is_on) on();
        queuebuf_to_packetbuf(pkt);
        // first, test the air
        if(NETSTACK_RADIO.channel_clear()) {
            // send filler, if no err, we won contention
            int c_ret = NETSTACK_RADIO.send(contention_strobe, len);
            if(c_ret == RADIO_TX_OK) {
                won_contention = 1;
            } else {
                won_contention = 0;
            }
        } else { // another packet in the air, we lost contention
            won_contention = 0;
        }

        if(won_contention) {
            packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &rimeaddr_node_addr);
            if(NETSTACK_FRAMER.create() < 0) {
                /* Failed to allocate space for headers */
                printf("WPI-MAC: send failed, too large header\n");
                ret = MAC_TX_ERR_FATAL;
            } else {
                // printf("%s - %u - %u\n", "Waiting to send...", current_slot, needed_slot);
                // while(radio_is_on == 0 && !(current_slot == needed_slot)); //wish i knew why this didn't work
                // rtimer_clock_t recent = RTIMER_TIME(&taskSlot);
                // rtimer_clock_t until = calcNext(current_slot, needed_slot);
                // while(RTIMER_CLOCK_LT(RTIMER_NOW(), recent + until));
                // printf("%s - %u - %u\n", "sending!", current_slot, needed_slot);
                // printf("%u\n", packetbuf_totlen());
                switch(NETSTACK_RADIO.send(packetbuf_hdrptr(), packetbuf_totlen())) {
                case RADIO_TX_OK:
                    ret = MAC_TX_OK;
                    break;
                case RADIO_TX_COLLISION:
                    ret = MAC_TX_COLLISION;
                    break;
                case RADIO_TX_NOACK:
                    ret = MAC_TX_NOACK;
                    break;
                default:
                    ret = MAC_TX_ERR;
                    break;
                }

            }


            mac_call_sent_callback(sent, ptr, ret, 1);

        } else { // lost contention
            mac_call_sent_callback(sent, ptr, MAC_TX_COLLISION, 1);
        }

    }

    QueuedPacket *head = QPQueue[current_slot];
    QPQueue[current_slot] = head->next;
    head->ptr = NULL;
    queuebuf_free(head->packet);
    head->packet = NULL;
    head->next = NULL;
    free(head);
}
Exemplo n.º 27
0
static int fragment(struct net_buf *buf, void *ptr)
{
   struct queuebuf *q;
   int max_payload;
   int framer_hdrlen;
   uint16_t frag_tag;

   /* Number of bytes processed. */
   uint16_t processed_ip_out_len;
   struct net_buf *mbuf;
   bool last_fragment = false;

#define USE_FRAMER_HDRLEN 0
#if USE_FRAMER_HDRLEN
  framer_hdrlen = NETSTACK_FRAMER.length();
  if(framer_hdrlen < 0) {
    /* Framing failed, we assume the maximum header length */
    framer_hdrlen = 21;
  }
#else /* USE_FRAMER_HDRLEN */
  framer_hdrlen = 21;
#endif /* USE_FRAMER_HDRLEN */
  max_payload = MAC_MAX_PAYLOAD - framer_hdrlen - NETSTACK_LLSEC.get_overhead();

  PRINTF("max_payload: %d, framer_hdrlen: %d \n",max_payload, framer_hdrlen);

  mbuf = l2_buf_get_reserve(0);
  if (!mbuf) {
     goto fail;
  }
	uip_last_tx_status(mbuf) = MAC_TX_OK;

  /*
   * The destination address will be tagged to each outbound
   * packet. If the argument localdest is NULL, we are sending a
   * broadcast packet.
   */

  if((int)uip_len(buf) <= max_payload) {
    /* The packet does not need to be fragmented, send buf */
    packetbuf_copyfrom(mbuf, uip_buf(buf), uip_len(buf));
    send_packet(mbuf, &ip_buf_ll_dest(buf), true, ptr);
    ip_buf_unref(buf);
    return 1;
   }

    uip_uncomp_hdr_len(mbuf) = 0;
    uip_packetbuf_hdr_len(mbuf) = 0;
    packetbuf_clear(mbuf);
    uip_packetbuf_ptr(mbuf) = packetbuf_dataptr(mbuf);

    packetbuf_set_attr(mbuf, PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS,
                                     SICSLOWPAN_MAX_MAC_TRANSMISSIONS);

    PRINTF("fragmentation: total packet len %d\n", uip_len(buf));

    /*
     * The outbound IPv6 packet is too large to fit into a single 15.4
     * packet, so we fragment it into multiple packets and send them.
     * The first fragment contains frag1 dispatch, then
     * IPv6/HC1/HC06/HC_UDP dispatchs/headers.
     * The following fragments contain only the fragn dispatch.
     */
    int estimated_fragments = ((int)uip_len(buf)) / ((int)MAC_MAX_PAYLOAD - SICSLOWPAN_FRAGN_HDR_LEN) + 1;
    int freebuf = queuebuf_numfree(mbuf) - 1;
    PRINTF("uip_len: %d, fragments: %d, free bufs: %d\n", uip_len(buf), estimated_fragments, freebuf);
    if(freebuf < estimated_fragments) {
      PRINTF("Dropping packet, not enough free bufs\n");
      goto fail;
    }

    /* Create 1st Fragment */
    SET16(uip_packetbuf_ptr(mbuf), PACKETBUF_FRAG_DISPATCH_SIZE,
          ((SICSLOWPAN_DISPATCH_FRAG1 << 8) | uip_len(buf)));

    frag_tag = my_tag++;
    SET16(uip_packetbuf_ptr(mbuf), PACKETBUF_FRAG_TAG, frag_tag);
    PRINTF("fragmentation: fragment %d \n", frag_tag);

    /* Copy payload and send */
    uip_packetbuf_hdr_len(mbuf) += SICSLOWPAN_FRAG1_HDR_LEN;
    uip_packetbuf_payload_len(mbuf) = (max_payload - uip_packetbuf_hdr_len(mbuf)) & 0xfffffff8;
    PRINTF("(payload len %d, hdr len %d, tag %d)\n",
               uip_packetbuf_payload_len(mbuf), uip_packetbuf_hdr_len(mbuf), frag_tag);

    memcpy(uip_packetbuf_ptr(mbuf) + uip_packetbuf_hdr_len(mbuf),
              uip_buf(buf), uip_packetbuf_payload_len(mbuf));
    packetbuf_set_datalen(mbuf, uip_packetbuf_payload_len(mbuf) + uip_packetbuf_hdr_len(mbuf));
    q = queuebuf_new_from_packetbuf(mbuf);
    if(q == NULL) {
      PRINTF("could not allocate queuebuf for first fragment, dropping packet\n");
      goto fail;
    }
    net_buf_ref(mbuf);
    send_packet(mbuf, &ip_buf_ll_dest(buf), last_fragment, ptr);
    queuebuf_to_packetbuf(mbuf, q);
    queuebuf_free(q);
    q = NULL;

    /* Check tx result. */
    if((uip_last_tx_status(mbuf) == MAC_TX_COLLISION) ||
       (uip_last_tx_status(mbuf) == MAC_TX_ERR) ||
       (uip_last_tx_status(mbuf) == MAC_TX_ERR_FATAL)) {
      PRINTF("error in fragment tx, dropping subsequent fragments.\n");
      goto fail;
    }

    /* set processed_ip_out_len to what we already sent from the IP payload*/
    processed_ip_out_len = uip_packetbuf_payload_len(mbuf);

    /*
     * Create following fragments
     * Datagram tag is already in the buffer, we need to set the
     * FRAGN dispatch and for each fragment, the offset
     */
    uip_packetbuf_hdr_len(mbuf) = SICSLOWPAN_FRAGN_HDR_LEN;
    SET16(uip_packetbuf_ptr(mbuf), PACKETBUF_FRAG_DISPATCH_SIZE,
          ((SICSLOWPAN_DISPATCH_FRAGN << 8) | uip_len(buf)));
    uip_packetbuf_payload_len(mbuf) = (max_payload - uip_packetbuf_hdr_len(mbuf)) & 0xfffffff8;

    while(processed_ip_out_len < uip_len(buf)) {
      PRINTF("fragmentation: fragment:%d, processed_ip_out_len:%d \n", my_tag, processed_ip_out_len);
      uip_packetbuf_ptr(mbuf)[PACKETBUF_FRAG_OFFSET] = processed_ip_out_len >> 3;

      /* Copy payload and send */
      if(uip_len(buf) - processed_ip_out_len < uip_packetbuf_payload_len(mbuf)) {
        /* last fragment */
        last_fragment = true;
        uip_packetbuf_payload_len(mbuf) = uip_len(buf) - processed_ip_out_len;
      }
      PRINTF("(offset %d, len %d, tag %d)\n",
             processed_ip_out_len >> 3, uip_packetbuf_payload_len(mbuf), my_tag);
      memcpy(uip_packetbuf_ptr(mbuf) + uip_packetbuf_hdr_len(mbuf),
             (uint8_t *)UIP_IP_BUF(buf) + processed_ip_out_len, uip_packetbuf_payload_len(mbuf));
      packetbuf_set_datalen(mbuf, uip_packetbuf_payload_len(mbuf) + uip_packetbuf_hdr_len(mbuf));
      q = queuebuf_new_from_packetbuf(mbuf);
      if(q == NULL) {
        PRINTF("could not allocate queuebuf, dropping fragment\n");
        goto fail;
      }
      net_buf_ref(mbuf);
      send_packet(mbuf, &ip_buf_ll_dest(buf), last_fragment, ptr);
      queuebuf_to_packetbuf(mbuf, q);
      queuebuf_free(q);
      q = NULL;
      processed_ip_out_len += uip_packetbuf_payload_len(mbuf);

      /* Check tx result. */
      if((uip_last_tx_status(mbuf) == MAC_TX_COLLISION) ||
         (uip_last_tx_status(mbuf) == MAC_TX_ERR) ||
         (uip_last_tx_status(mbuf) == MAC_TX_ERR_FATAL)) {
        PRINTF("error in fragment tx, dropping subsequent fragments.\n");
        goto fail;
      }
    }

    ip_buf_unref(buf);
    l2_buf_unref(mbuf);
    return 1;

fail:
    if (mbuf) {
      l2_buf_unref(mbuf);
    }
    return 0;
}
Exemplo n.º 28
0
/**
 * Read a packet from the underlying radio driver. If the incoming
 * packet is a probe packet and the sender of the probe matches the
 * destination address of the queued packet (if any), the queued packet
 * is sent.
 */
static void
input_packet(void)
{
  struct lpp_hdr hdr;
  clock_time_t reception_time;

  reception_time = clock_time();

  if(!NETSTACK_FRAMER.parse()) {
    printf("lpp input_packet framer error\n");
  }

  memcpy(&hdr, packetbuf_dataptr(), sizeof(struct lpp_hdr));;
  packetbuf_hdrreduce(sizeof(struct lpp_hdr));
  /*    PRINTF("got packet type %d\n", hdr->type);*/

  if(hdr.type == TYPE_PROBE) {
    struct announcement_msg adata;
    
    /* Register the encounter with the sending node. We now know the
       neighbor's phase. */
    register_encounter(&hdr.sender, reception_time);

    /* Parse incoming announcements */
    memcpy(&adata, packetbuf_dataptr(),
           MIN(packetbuf_datalen(), sizeof(adata)));
#if 0
    PRINTF("%d.%d: probe from %d.%d with %d announcements\n",
           rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
           hdr.sender.u8[0], hdr.sender.u8[1], adata->num);
    
    if(adata.num / sizeof(struct announcement_data) > sizeof(struct announcement_msg)) {
      /* Sanity check. The number of announcements is too large -
         corrupt packet has been received. */
      return 0;
    }

    for(i = 0; i < adata.num; ++i) {
      /*	  PRINTF("%d.%d: announcement %d: %d\n",
		  rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
		  adata->data[i].id,
		  adata->data[i].value);*/

      announcement_heard(&hdr.sender,
                         adata.data[i].id,
                         adata.data[i].value);
    }
#endif  /* 0 */

    /* Go through the list of packets to be sent to see if any of
       them match the sender of the probe, or if they are a
       broadcast packet that should be sent. */
    if(list_length(queued_packets_list) > 0) {
      struct queue_list_item *i;
      for(i = list_head(queued_packets_list); i != NULL; i = list_item_next(i)) {
        const rimeaddr_t *receiver;
        uint8_t sent;

        sent = 0;
 
        receiver = queuebuf_addr(i->packet, PACKETBUF_ADDR_RECEIVER);
        if(rimeaddr_cmp(receiver, &hdr.sender) ||
           rimeaddr_cmp(receiver, &rimeaddr_null)) {
          queuebuf_to_packetbuf(i->packet);

#if WITH_PENDING_BROADCAST
          if(i->broadcast_flag == BROADCAST_FLAG_NONE ||
             i->broadcast_flag == BROADCAST_FLAG_SEND) {
            i->num_transmissions = 1;
            NETSTACK_RADIO.send(queuebuf_dataptr(i->packet),
                                queuebuf_datalen(i->packet));
            sent = 1;
            PRINTF("%d.%d: got a probe from %d.%d, sent packet to %d.%d\n",
		   rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
                   hdr.sender.u8[0], hdr.sender.u8[1],
                   receiver->u8[0], receiver->u8[1]);
	      
          } else {
            PRINTF("%d.%d: got a probe from %d.%d, did not send packet\n",
                   rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
                   hdr.sender.u8[0], hdr.sender.u8[1]);
          }
#else /* WITH_PENDING_BROADCAST */
          i->num_transmissions = 1;
          NETSTACK_RADIO.send(queuebuf_dataptr(i->packet),
                               queuebuf_datalen(i->packet));
          PRINTF("%d.%d: got a probe from %d.%d, sent packet to %d.%d\n",
                 rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
                 hdr.sender.u8[0], hdr.sender.u8[1],
                 receiver->u8[0], receiver->u8[1]);
#endif /* WITH_PENDING_BROADCAST */

          /*          off();*/

          /* Attribute the energy spent on listening for the probe
             to this packet transmission. */
          compower_accumulate(&i->compower);
	    
          /* If the packet was not a broadcast packet, we dequeue it
             now. Broadcast packets should be transmitted to all
             neighbors, and are dequeued by the dutycycling function
             instead, after the appropriate time. */
          if(!rimeaddr_cmp(receiver, &rimeaddr_null)) {
            if(detect_ack()) {
              remove_queued_packet(i, 1);
            } else {
              remove_queued_packet(i, 0);
            }

#if WITH_PROBE_AFTER_TRANSMISSION
            /* Send a probe packet to catch any reply from the other node. */
            restart_dutycycle(PROBE_AFTER_TRANSMISSION_TIME);
#endif /* WITH_PROBE_AFTER_TRANSMISSION */

#if WITH_STREAMING
            if(is_streaming) {
              ctimer_set(&stream_probe_timer, STREAM_PROBE_TIME,
                         send_stream_probe, NULL);
            }
#endif /* WITH_STREAMING */
          }

          if(sent) {
            turn_radio_off();
          }

#if WITH_ACK_OPTIMIZATION
          if(packetbuf_attr(PACKETBUF_ATTR_RELIABLE) ||
             packetbuf_attr(PACKETBUF_ATTR_ERELIABLE)) {
            /* We're sending a packet that needs an ACK, so we keep
               the radio on in anticipation of the ACK. */
            turn_radio_on();
          }
#endif /* WITH_ACK_OPTIMIZATION */

        }
      }
    }

  } else if(hdr.type == TYPE_DATA) {
    turn_radio_off();
    if(!rimeaddr_cmp(&hdr.receiver, &rimeaddr_null)) {
      if(!rimeaddr_cmp(&hdr.receiver, &rimeaddr_node_addr)) {
        /* Not broadcast or for us */
        PRINTF("%d.%d: data not for us from %d.%d\n",
               rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
               hdr.sender.u8[0], hdr.sender.u8[1]);
        return;
      }
      packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &hdr.receiver);
    }
    packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &hdr.sender);

    PRINTF("%d.%d: got data from %d.%d\n",
           rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
           hdr.sender.u8[0], hdr.sender.u8[1]);

    /* 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);

#if WITH_PENDING_BROADCAST
    if(rimeaddr_cmp(&hdr.receiver, &rimeaddr_null)) {
      /* This is a broadcast packet. Check the list of pending
         packets to see if we are currently sending a broadcast. If
         so, we refrain from sending our broadcast until one sleep
         cycle period, so that the other broadcaster will have
         finished sending. */
	
      struct queue_list_item *i;
      for(i = list_head(queued_packets_list); i != NULL; i = list_item_next(i)) {
        /* If the packet is a broadcast packet that is not yet
           ready to be sent, we do not send it. */
        if(i->broadcast_flag == BROADCAST_FLAG_PENDING) {
          PRINTF("Someone else is sending, pending -> waiting\n");
          set_broadcast_flag(i, BROADCAST_FLAG_WAITING);
        }
      }
    }
#endif /* WITH_PENDING_BROADCAST */


#if WITH_PROBE_AFTER_RECEPTION
    /* XXX send probe after receiving a packet to facilitate data
       streaming. We must first copy the contents of the packetbuf into
       a queuebuf to avoid overwriting the data with the probe packet. */
    if(rimeaddr_cmp(&hdr.receiver, &rimeaddr_node_addr)) {
      struct queuebuf *q;
      q = queuebuf_new_from_packetbuf();
      if(q != NULL) {
        send_probe();
        queuebuf_to_packetbuf(q);
        queuebuf_free(q);
      }
    }
#endif /* WITH_PROBE_AFTER_RECEPTION */

#if WITH_ADAPTIVE_OFF_TIME
    off_time = LOWEST_OFF_TIME;
    restart_dutycycle(off_time);
#endif /* WITH_ADAPTIVE_OFF_TIME */

    NETSTACK_MAC.input();
  }
}