Пример #1
0
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(shell_packetize_process, ev, data)
{
  static struct queuebuf *q = NULL;
  static char *ptr;
  static int size;
  int len;
  PROCESS_BEGIN();

  while(1) {
    struct shell_input *input;
    PROCESS_WAIT_EVENT_UNTIL(ev == shell_event_input);

    if(q == NULL) {
      packetbuf_clear();
      q = queuebuf_new_from_packetbuf();
      if(q == NULL) {
	shell_output_str(&packetize_command, "packetize: could not allocate packet buffer", "");
	PROCESS_EXIT();
      }
      ptr = queuebuf_dataptr(q);
      size = 0;
    }
    
    input = data;

    len = input->len1 + input->len2;

    if(len + size >= PACKETBUF_SIZE ||
       len  == 0) {
      shell_output(&packetize_command,
		   ptr, size,
		   "", 0);
      queuebuf_free(q);
      q = NULL;
      PROCESS_EXIT();
    }

    memcpy(ptr + size, input->data1, input->len1);
    size += input->len1;
    memcpy(ptr + size, input->data2, input->len2);
    size += input->len2;
    
  }
  
  PROCESS_END();
}
Пример #2
0
/*---------------------------------------------------------------------------*/
void
trickle_send(struct trickle_conn *c) {
    uint8_t tmp;
    if (c->q != NULL) {
        queuebuf_free(c->q);
    }
    tmp = c->seqno;
    tmp++;
    c->seqno = tmp;
    packetbuf_set_attr(PACKETBUF_ATTR_EPACKET_ID, c->seqno);
    c->q = queuebuf_new_from_packetbuf();
    PRINTF("%d.%d: trickle send seqno %d\n",
            rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
            c->seqno);
    reset_interval(c);
    send(c);
}
Пример #3
0
/*---------------------------------------------------------------------------*/
static int
send(void)
{
  int r;
  id_counter++;

  /* Clean up already sent packets */
  while(lastqueued != nextsend) {
    PRINTF("BUFFER Cleaning up packet #%i\n", id[lastqueued]);
    queuebuf_free(data[lastqueued]);
    data[lastqueued] = NULL;

    lastqueued = (lastqueued + 1) % NUM_PACKETS;
  }

  if((freeslot + 1) % NUM_PACKETS == lastqueued) {
    PRINTF("BUFFER Buffer full, dropping packet #%i\n", (id_counter+1));
    return UIP_FW_DROPPED;
  }

  /* Allocate queue buf for packet */
  data[freeslot] = queuebuf_new_from_packetbuf();
  id[freeslot] = id_counter;
  if(data[freeslot] == NULL) {
    PRINTF("BUFFER Queuebuffer full, dropping packet #%i\n", id[freeslot]);
    return UIP_FW_DROPPED;
  }
  PRINTF("BUFFER Wrote packet #%i to buffer \n", id[freeslot]);

  freeslot = (freeslot + 1) % NUM_PACKETS;

  if(!timer_on) {
    PRINTF("TIMER Starting timer\n");
    r = rtimer_set(&rtimer, RTIMER_NOW() + RTIMER_SECOND, 1,
        (void (*)(struct rtimer *, void *))transmitter, NULL);
    if(r) {
      PRINTF("TIMER Error #3: %d\n", r);
    } else {
      timer_on = 1;
    }
  }

  return UIP_FW_OK; /* TODO Return what? */
}
Пример #4
0
/*---------------------------------------------------------------------------*/
static void
recv(struct broadcast_conn *bc, const rimeaddr_t *from)
{
    struct trickle_conn *c = (struct trickle_conn *)bc;
    uint16_t seqno = packetbuf_attr(PACKETBUF_ATTR_EPACKET_ID);

    PRINTF("%d.%d: trickle recv seqno %d from %d.%d our %d data len %d channel %d\n",
           rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
           seqno,
           from->u8[0], from->u8[1],
           c->seqno,
           packetbuf_datalen(),
           packetbuf_attr(PACKETBUF_ATTR_CHANNEL));

    if(seqno == c->seqno)
    {
        /*    c->cb->recv(c);*/
        ++c->duplicates;
    }
    else if(SEQNO_LT(seqno, c->seqno))
    {
        c->interval_scaling = 0;
        send(c);
    }
    else     /* hdr->seqno > c->seqno */
    {
#if CONTIKI_TARGET_NETSIM
        /*    ether_set_line(from->u8[0], from->u8[1]);*/
#endif /* CONTIKI_TARGET_NETSIM */
        c->seqno = seqno;
        /* Store the incoming data in the queuebuf */
        if(c->q != NULL)
        {
            queuebuf_free(c->q);
        }
        c->q = queuebuf_new_from_packetbuf();
        c->interval_scaling = 0;
        reset_interval(c);
        ctimer_set(&c->first_transmission_timer, random_rand() % c->interval,
                   send, c);
        c->cb->recv(c);
    }
}
Пример #5
0
/*---------------------------------------------------------------------------*/
int
packetqueue_enqueue_packetbuf(struct packetqueue *q, clock_time_t lifetime,
                              void *ptr)
{
    struct packetqueue_item *i;

    /* Allocate a memory block to hold the packet queue item. */
    i = memb_alloc(q->memb);

    if(i == NULL)
    {
        return 0;
    }

    /* Allocate a queuebuf and copy the contents of the packetbuf into it. */
    i->buf = queuebuf_new_from_packetbuf();

    if(i->buf == NULL)
    {
        memb_free(q->memb, i);
        return 0;
    }

    i->queue = q;
    i->ptr = ptr;

    /* Setup a ctimer that removes the packet from the queue when its
       lifetime expires. If the lifetime is zero, we do not set a
       lifetimer. */
    if(lifetime > 0)
    {
        ctimer_set(&i->lifetimer, lifetime, remove_queued_packet, i);
    }

    /* Add the item to the queue. */
    list_add(*q->list, i);

    return 1;
}
Пример #6
0
/* Add packet to neighbor queue. Use same lockfree implementation as ringbuf.c (put is atomic) */
struct tsch_packet *
tsch_queue_add_packet(const linkaddr_t *addr, mac_callback_t sent, void *ptr)
{
  struct tsch_neighbor *n = NULL;
  int16_t put_index = -1;
  struct tsch_packet *p = NULL;
  if(!tsch_is_locked()) {
    n = tsch_queue_add_nbr(addr);
    if(n != NULL) {
      put_index = ringbufindex_peek_put(&n->tx_ringbuf);
      if(put_index != -1) {
        p = memb_alloc(&packet_memb);
        if(p != NULL) {
          /* Enqueue packet */
#ifdef TSCH_CALLBACK_PACKET_READY
          TSCH_CALLBACK_PACKET_READY();
#endif
          p->qb = queuebuf_new_from_packetbuf();
          if(p->qb != NULL) {
            p->sent = sent;
            p->ptr = ptr;
            p->ret = MAC_TX_DEFERRED;
            p->transmissions = 0;
            /* Add to ringbuf (actual add committed through atomic operation) */
            n->tx_array[put_index] = p;
            ringbufindex_put(&n->tx_ringbuf);
            return p;
          } else {
            memb_free(&packet_memb, p);
          }
        }
      }
    }
  }
  PRINTF("TSCH-queue:! add packet failed: %u %p %d %p %p\n", tsch_is_locked(), n, put_index, p, p ? p->qb : NULL);
  return 0;
}
/*---------------------------------------------------------------------------*/
int
ipolite_send(struct ipolite_conn *c, clock_time_t interval, uint8_t hdrsize)
{
  if(c->q != NULL) {
    /* If we are already about to send a packet, we cancel the old one. */
    PRINTF("%d.%d: ipolite_send: cancel old send\n",
	   linkaddr_node_addr.u8[0],linkaddr_node_addr.u8[1]);
    queuebuf_free(c->q);
    c->q = NULL;
    ctimer_stop(&c->t);
  }
  c->dups = 0;
  c->hdrsize = hdrsize;
  if(interval == 0) {
    PRINTF("%d.%d: ipolite_send: interval 0\n",
	   linkaddr_node_addr.u8[0],linkaddr_node_addr.u8[1]);
    if(broadcast_send(&c->c)) {
      if(c->cb->sent) {
	c->cb->sent(c);
      }
      return 1;
    }

  } else {
    c->q = queuebuf_new_from_packetbuf();
    if(c->q != NULL) {
      ctimer_set(&c->t,
		 interval / 2 + (random_rand() % (interval / 2)),
		 send, c);
      return 1;
    }
    PRINTF("%d.%d: ipolite_send: could not allocate queue buffer\n",
	   linkaddr_node_addr.u8[0],linkaddr_node_addr.u8[1]);
  }
  return 0;
}
Пример #8
0
/*---------------------------------------------------------------------------*/
static void
send_packet(mac_callback_t sent, void *ptr)
{
  struct rdc_buf_list *q;
  struct neighbor_queue *n;
  const linkaddr_t *addr = packetbuf_addr(PACKETBUF_ADDR_RECEIVER);

  /* 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 */
      linkaddr_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 */
    if(list_length(n->queued_packet_list) < CSMA_MAX_PACKET_PER_NEIGHBOR) {
      q = memb_alloc(&packet_memb);
      if(q != NULL) {
        q->ptr = memb_alloc(&metadata_memb);
        if(q->ptr != NULL) {
          q->buf = queuebuf_new_from_packetbuf();
          if(q->buf != NULL) {
            struct qbuf_metadata *metadata = (struct qbuf_metadata *)q->ptr;
            /* Neighbor and packet successfully allocated */
            if(packetbuf_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS) == 0) {
              /* Use default configuration for max transmissions */
              metadata->max_transmissions = CSMA_MAX_MAC_TRANSMISSIONS;
            } else {
              metadata->max_transmissions =
                packetbuf_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS);
            }
            metadata->sent = sent;
            metadata->cptr = ptr;
#if PACKETBUF_WITH_PACKET_TYPE
            if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) ==
               PACKETBUF_ATTR_PACKET_TYPE_ACK) {
              list_push(n->queued_packet_list, q);
            } else
#endif
            {
              list_add(n->queued_packet_list, q);
            }

            PRINTF("csma: send_packet, queue length %d, free packets %d\n",
                   list_length(n->queued_packet_list), memb_numfree(&packet_memb));
            /* 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);
      }
    } else {
      PRINTF("csma: Neighbor queue full\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);
}
Пример #9
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;
  }

}
Пример #10
0
/*---------------------------------------------------------------------------*/
uint8_t
uip_over_mesh_send(void)
{
  linkaddr_t receiver;
  struct route_entry *rt;

  /* This function is called by the uip-fw module to send out an IP
     packet. We try to send the IP packet to the next hop route, or we
     queue the packet and send out a route request for the final
     receiver of the packet. */

  /* Packets destined to this network is sent using mesh, whereas
     packets destined to a network outside this network is sent towards
     the gateway node. */

  if(uip_ipaddr_maskcmp(&BUF->destipaddr, &netaddr, &netmask)) {
    receiver.u8[0] = BUF->destipaddr.u8[2];
    receiver.u8[1] = BUF->destipaddr.u8[3];
  } else {
    if(linkaddr_cmp(&gateway, &linkaddr_node_addr)) {
      PRINTF("uip_over_mesh_send: I am gateway, packet to %d.%d.%d.%d to local interface\n",
	     uip_ipaddr_to_quad(&BUF->destipaddr));
      if(gw_netif != NULL) {
	return gw_netif->output();
      }
      return UIP_FW_DROPPED;
    } else if(linkaddr_cmp(&gateway, &linkaddr_null)) {
      PRINTF("uip_over_mesh_send: No gateway setup, dropping packet\n");
      return UIP_FW_OK;
    } else {
      PRINTF("uip_over_mesh_send: forwarding packet to %d.%d.%d.%d towards gateway %d.%d\n",
	     uip_ipaddr_to_quad(&BUF->destipaddr),
	     gateway.u8[0], gateway.u8[1]);
      linkaddr_copy(&receiver, &gateway);
    }
  }

  PRINTF("uIP over mesh send to %d.%d with len %d\n",
	 receiver.u8[0], receiver.u8[1],
	 uip_len);
  
  
  packetbuf_copyfrom(&uip_buf[UIP_LLH_LEN], uip_len);

  /* Send TCP data with the PACKETBUF_ATTR_ERELIABLE set so that
     an underlying power-saving MAC layer knows that it should be
     waiting for an ACK. */
  if(BUF->proto == UIP_PROTO_TCP) {
    packetbuf_set_attr(PACKETBUF_ATTR_ERELIABLE, 1);
    packetbuf_set_attr(PACKETBUF_ATTR_RELIABLE, 1);
    /*    packetbuf_set_attr(PACKETBUF_ATTR_PACKET_TYPE, PACKETBUF_ATTR_PACKET_TYPE_STREAM);*/
  }

  rt = route_lookup(&receiver);
  if(rt == NULL) {
    PRINTF("uIP over mesh no route to %d.%d\n", receiver.u8[0], receiver.u8[1]);
    if(queued_packet == NULL) {
      queued_packet = queuebuf_new_from_packetbuf();
      linkaddr_copy(&queued_receiver, &receiver);
      route_discovery_discover(&route_discovery, &receiver, ROUTE_TIMEOUT);
    } else if(!linkaddr_cmp(&queued_receiver, &receiver)) {
      route_discovery_discover(&route_discovery, &receiver, ROUTE_TIMEOUT);
    }
  } else {
    route_decay(rt);
    send_data(&rt->nexthop);
  }
  return UIP_FW_OK;
}
Пример #11
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();
  }
}
Пример #12
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);
    }
  }
}
Пример #13
0
/*---------------------------------------------------------------------------*/
static void
packet_sent(void *ptr, int status, int num_transmissions)
{
  struct neighbor_queue *n;
  struct rdc_buf_list *q;
  struct qbuf_metadata *metadata;
  clock_time_t time = 0;
  mac_callback_t sent;
  void *cptr;
  int num_tx;
  int backoff_transmissions;

  n = ptr;
  if(n == NULL) {
    return;
  }
  switch(status) {
  case MAC_TX_OK:
  case MAC_TX_NOACK:
    n->transmissions++;
    break;
  case MAC_TX_COLLISION:
    n->collisions++;
    break;
  case MAC_TX_DEFERRED:
    n->deferrals++;
    break;
  }

  for(q = list_head(n->queued_packet_list);
      q != NULL; q = list_item_next(q)) {
    if(queuebuf_attr(q->buf, PACKETBUF_ATTR_MAC_SEQNO) ==
       packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO)) {
      break;
    }
  }

  if(q != NULL) {
    metadata = (struct qbuf_metadata *)q->ptr;

    if(metadata != NULL) {
      sent = metadata->sent;
      cptr = metadata->cptr;
#if CSMA_ADVANCED
      num_tx = n->transmissions + n->collisions/8;
#else
      num_tx = n->transmissions;
#endif

      if(status == MAC_TX_COLLISION ||
           status == MAC_TX_NOACK) {
        /* If the transmission was not performed because of a
           collision or noack, we must retransmit the packet. */

        switch(status) {
        case MAC_TX_COLLISION:
          PRINTF("csma: rexmit collision %d\n", n->transmissions);
          break;
        case MAC_TX_NOACK:
          PRINTF("csma: rexmit noack %d\n", n->transmissions);
          break;
        case MAC_TX_DEFERRED:
          PRINTF("phase deferred\n");
          break;
        default:
          PRINTF("csma: rexmit err %d, %d\n", status, n->transmissions);
        }
#if CSMA_ADVANCED
          int i;
          /* The retransmission time must be proportional to the channel
           check interval of the underlying radio duty cycling layer. */
          time = default_timebase() / 3;

          /* The retransmission time uses a linear backoff so that the
           interval between the transmissions increase with each
           retransmit. */
          backoff_transmissions = 1;
          for(i=0; i<num_tx-1; i++) {
            backoff_transmissions *= 3;
          }

          /* Clamp the number of backoffs so that we don't get a too long
           timeout here, since that will delay all packets in the
           queue. */
          if(backoff_transmissions > 3 * 3) {
            backoff_transmissions = 3 * 3;
          }

          time = default_timebase() + (random_rand() % (backoff_transmissions * time));

        if(num_tx < metadata->max_transmissions) {
#else
        /* The retransmission time must be proportional to the channel
           check interval of the underlying radio duty cycling layer. */
        time = default_timebase();

        /* The retransmission time uses a linear backoff so that the
           interval between the transmissions increase with each
           retransmit. */
        backoff_transmissions = n->transmissions + 1;

        /* Clamp the number of backoffs so that we don't get a too long
           timeout here, since that will delay all packets in the
           queue. */
        if(backoff_transmissions > 3) {
          backoff_transmissions = 3;
        }

        time = time + (random_rand() % (backoff_transmissions * time));
        if(n->transmissions < metadata->max_transmissions) {
#endif
          PRINTF("csma: retransmitting with time %lu %p\n", time, q);
          ctimer_set(&n->transmit_timer, time,
                     transmit_packet_list, n);
          /* This is needed to correctly attribute energy that we spent
             transmitting this packet. */
          queuebuf_update_attr_from_packetbuf(q->buf);
        } else {
          if(!rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
                                 &rimeaddr_null)) {
            LOG_FROM_PACKETBUF("csma: drop with status %d after %d transmissions, %d collisions",
                               status, n->transmissions, n->collisions);
          }
          free_packet(n, q);
          mac_call_sent_callback(sent, cptr, status, num_tx);
        }
      } else {
        if(status == MAC_TX_OK) {
          if(!rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
                                 &rimeaddr_null)) {
          LOG_FROM_PACKETBUF("csma: rexmit ok after %d transmissions, %d collisions", n->transmissions, n->collisions);
          }
        } else {
          //LOG_FROM_PACKETBUF("csma: rexmit failed %d: %d\n", n->transmissions, status);
        }
        free_packet(n, q);
        mac_call_sent_callback(sent, cptr, status, num_tx);
      }
    }
  }
}
/*---------------------------------------------------------------------------*/
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;
	  } else {
	    metadata->max_transmissions =
                  packetbuf_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS);
	  }
	  metadata->sent = sent;
	  metadata->cptr = ptr;

	  if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) ==
	     PACKETBUF_ATTR_PACKET_TYPE_ACK) {
	    list_push(n->queued_packet_list, q);
	  } else {
	    list_add(n->queued_packet_list, q);
	  }

	  /* If q is the first packet in the neighbor's queue, send asap */
	  if(list_head(n->queued_packet_list) == q) {
	    ctimer_set(&n->transmit_timer, 0, transmit_packet_list, n);
	  }
	  return;
	}
	memb_free(&metadata_memb, q->ptr);
	PRINTF("csma: could not allocate queuebuf, dropping packet\n");
      }
      memb_free(&packet_memb, q);
      PRINTF("csma: could not allocate queuebuf, dropping packet\n");
    }
    /* The packet allocation failed. Remove and free neighbor entry if empty. */
    if(list_length(n->queued_packet_list) == 0) {
      list_remove(neighbor_list, n);
      memb_free(&neighbor_memb, n);
    }
    PRINTF("csma: could not allocate packet, dropping packet\n");
  } else {
    PRINTF("csma: could not allocate neighbor, dropping packet\n");
  }
  mac_call_sent_callback(sent, ptr, MAC_TX_ERR, 1);
}
/*---------------------------------------------------------------------------*/
static void
input_packet(void)
{
  NETSTACK_NETWORK.input();
}
/*---------------------------------------------------------------------------*/
static int
on(void)
{
  return NETSTACK_RDC.on();
}
/*---------------------------------------------------------------------------*/
static int
off(int keep_radio_on)
{
  return NETSTACK_RDC.off(keep_radio_on);
}
/*---------------------------------------------------------------------------*/
static unsigned short
channel_check_interval(void)
{
  if(NETSTACK_RDC.channel_check_interval) {
    return NETSTACK_RDC.channel_check_interval();
  }
  return 0;
}
/*---------------------------------------------------------------------------*/
static void
init(void)
{
  memb_init(&packet_memb);
  memb_init(&metadata_memb);
  memb_init(&neighbor_memb);
}
Пример #14
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);
    }
  }
}
Пример #15
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;
}
Пример #16
0
Файл: csma.c Проект: cetic/6lbr
/*---------------------------------------------------------------------------*/
static void
packet_sent(void *ptr, int status, int num_transmissions)
{
  struct neighbor_queue *n;
  struct rdc_buf_list *q;

  n = ptr;
  if(n == NULL) {
    return;
  }

  /* Find out what packet this callback refers to */
  for(q = list_head(n->queued_packet_list);
      q != NULL; q = list_item_next(q)) {
#if CETIC_6LBR_MULTI_RADIO
    if(queuebuf_attr(q->buf, PACKETBUF_ATTR_MAC_SEQNO) ==
       packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO) &&
       (q->ptr == NULL ||
        ((struct qbuf_metadata *)q->ptr)->ifindex == multi_radio_input_ifindex)) {
#else
    if(queuebuf_attr(q->buf, PACKETBUF_ATTR_MAC_SEQNO) ==
       packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO)) {
#endif
      break;
    }
  }

  if(q == NULL) {
    PRINTF("csma: seqno %d not found\n",
           packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO));
    return;
  } else if(q->ptr == NULL) {
    PRINTF("csma: no metadata\n");
    return;
  }

  switch(status) {
  case MAC_TX_OK:
    tx_ok(q, n, num_transmissions);
    break;
  case MAC_TX_NOACK:
    noack(q, n, num_transmissions);
    break;
  case MAC_TX_COLLISION:
    collision(q, n, num_transmissions);
    break;
  case MAC_TX_DEFERRED:
    break;
  default:
    tx_done(status, q, n);
    break;
  }
}
/*---------------------------------------------------------------------------*/
static void
send_packet(mac_callback_t sent, void *ptr)
{
  struct rdc_buf_list *q;
  struct neighbor_queue *n;
  const linkaddr_t *addr = packetbuf_addr(PACKETBUF_ADDR_RECEIVER);

  /* 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 */
      linkaddr_copy(&n->addr, addr);
      n->transmissions = 0;
      n->collisions = CSMA_MIN_BE;
      /* 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 */
    if(list_length(n->queued_packet_list) < CSMA_MAX_PACKET_PER_NEIGHBOR) {
      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_MAX_FRAME_RETRIES + 1;
            } else {
              metadata->max_transmissions =
                packetbuf_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS);
            }
            metadata->sent = sent;
            metadata->cptr = ptr;
#if CETIC_6LBR_MULTI_RADIO
            metadata->ifindex = multi_radio_output_ifindex;
#endif
#if PACKETBUF_WITH_PACKET_TYPE
            if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) ==
               PACKETBUF_ATTR_PACKET_TYPE_ACK) {
              list_push(n->queued_packet_list, q);
            } else
#endif
            {
              list_add(n->queued_packet_list, q);
            }

            PRINTF("csma: send_packet, queue length %d, free packets %d\n",
                   list_length(n->queued_packet_list), memb_numfree(&packet_memb));
            /* If q is the first packet in the neighbor's queue, send asap */
            if(list_head(n->queued_packet_list) == q) {
              schedule_transmission(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);
      }
    } else {
      PRINTF("csma: Neighbor queue full\n");
    }
    PRINTF("csma: could not allocate packet, dropping packet\n");
    csma_packet_overflow++;
  } else {
    PRINTF("csma: could not allocate neighbor, dropping packet\n");
    csma_neighbor_overflow++;
  }
  mac_call_sent_callback(sent, ptr, MAC_TX_ERR, 1);
}
/*---------------------------------------------------------------------------*/
static void
input_packet(void)
{
  csma_received_packets++;
  NETSTACK_LLSEC.input();
}
/*---------------------------------------------------------------------------*/
static void
send_packet(mac_callback_t sent, void *ptr)
{
  struct rdc_buf_list *q;
  struct neighbor_queue *n;
  static uint16_t seqno;

  packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, seqno++);
  
  /* If the packet is a broadcast, do not allocate a queue
     entry. Instead, just send it out.  */
  if(!rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),&rimeaddr_null)) {
    const rimeaddr_t *addr = packetbuf_addr(PACKETBUF_ADDR_RECEIVER);

    /* 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 */
        n->queued_packet_list = ttc_list_create((const char*)n->queued_packet_list);
        ttc_list_init(n->queued_packet_list, (const char*)n->queued_packet_list);
        /* Add neighbor to the list */
        list_add(neighbor_list, n);
      }
    }

    if(n != NULL) {
      /* Add packet to the neighbor's queue */
      q = memb_alloc(packet_memb);
      if(q != NULL) {
        q->ptr = memb_alloc(metadata_memb);
        if(q->ptr != NULL) {
          q->buf = queuebuf_new_from_packetbuf();
          if(q->buf != NULL) {
            struct qbuf_metadata *metadata = (struct qbuf_metadata *)q->ptr;
            /* Neighbor and packet successfully allocated */
            if(packetbuf_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS) == 0) {
              /* Use default configuration for max transmissions */
              metadata->max_transmissions = CSMA_MAX_MAC_TRANSMISSIONS;
            } else {
              metadata->max_transmissions =
                  packetbuf_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS);
            }
            metadata->sent = sent;
            metadata->cptr = ptr;

            if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) ==
                PACKETBUF_ATTR_PACKET_TYPE_ACK) {
              list_push(n->queued_packet_list, q);
            } else {
              list_add(n->queued_packet_list, q);
            }

            /* If q is the first packet in the neighbor's queue, send asap */
            if(list_head(n->queued_packet_list) == q) {
              ctimer_set(&n->transmit_timer, 0, transmit_packet_list, n);
            }
            return;
          }
          memb_free(metadata_memb, q->ptr);
          PRINTF("csma: could not allocate queuebuf, dropping packet\n");
        }
        memb_free(packet_memb, q);
        PRINTF("csma: could not allocate queuebuf, dropping packet\n");
      }
      /* The packet allocation failed. Remove and free neighbor entry if empty. */
      if(list_length(n->queued_packet_list) == 0) {
        list_remove(neighbor_list, n);
        memb_free(neighbor_memb, n);
      }
      PRINTF("csma: could not allocate packet, dropping packet\n");
    } else {
      PRINTF("csma: could not allocate neighbor, dropping packet\n");
    }
    mac_call_sent_callback(sent, ptr, MAC_TX_ERR, 1);
  } else {
    PRINTF("csma: send broadcast\n");
    NETSTACK_RDC.send(sent, ptr);
  }
}
Пример #18
0
/*---------------------------------------------------------------------------*/
static uint8_t
send_packet(struct net_buf *buf, mac_callback_t sent, bool last_fragment, void *ptr)
{
  struct rdc_buf_list *q;
  struct neighbor_queue *n;
  static uint8_t initialized = 0;
  static uint16_t seqno;
  const linkaddr_t *addr = packetbuf_addr(buf, PACKETBUF_ADDR_RECEIVER);

  if (!buf) {
    UIP_LOG("csma: send_packet(): net_buf is NULL, cannot send packet");
    return 0;
  }

  if(!initialized) {
    initialized = 1;
    /* Initialize the sequence number to a random value as per 802.15.4. */
    seqno = random_rand();
  }

  if(seqno == 0) {
    /* PACKETBUF_ATTR_MAC_SEQNO cannot be zero, due to a pecuilarity
       in framer-802154.c. */
    seqno++;
  }
  packetbuf_set_attr(buf, PACKETBUF_ATTR_MAC_SEQNO, seqno++);

  /* Look for the neighbor entry */
  n = neighbor_queue_from_addr(buf, addr);
  if(n == NULL) {
    /* Allocate a new neighbor entry */
    n = memb_alloc(&neighbor_memb);
    if(n != NULL) {
      /* Init neighbor entry */
      linkaddr_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(uip_neighbor_list(buf), n);
    }
  }

  if(n != NULL) {
    /* Add packet to the neighbor's queue */
    if(list_length(n->queued_packet_list) < CSMA_MAX_PACKET_PER_NEIGHBOR) {
      q = memb_alloc(&packet_memb);
      if(q != NULL) {
        q->ptr = memb_alloc(&metadata_memb);
        if(q->ptr != NULL) {
          q->buf = queuebuf_new_from_packetbuf(buf);
          if(q->buf != NULL) {
            struct qbuf_metadata *metadata = (struct qbuf_metadata *)q->ptr;
            /* Neighbor and packet successfully allocated */
            if(packetbuf_attr(buf, PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS) == 0) {
              /* Use default configuration for max transmissions */
              metadata->max_transmissions = CSMA_MAX_MAC_TRANSMISSIONS;
            } else {
              metadata->max_transmissions =
                packetbuf_attr(buf, PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS);
            }
            metadata->sent = sent;
            metadata->cptr = ptr;

            if(packetbuf_attr(buf, PACKETBUF_ATTR_PACKET_TYPE) ==
               PACKETBUF_ATTR_PACKET_TYPE_ACK) {
              list_push(n->queued_packet_list, q);
            } else {
              list_add(n->queued_packet_list, q);
            }

            PRINTF("csma: send_packet, queue length %d, free packets %d\n",
                   list_length(n->queued_packet_list), memb_numfree(&packet_memb));
            /* if received packet is last fragment/only one packet start sending
             * packets in list, do not start any timer.*/
            if (last_fragment) {
               transmit_packet_list(buf, n);
            }
            return 1;
          }
          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(uip_neighbor_list(buf), n);
        memb_free(&neighbor_memb, n);
      }
    } else {
      PRINTF("csma: Neighbor queue full\n");
    }
    PRINTF("csma: could not allocate packet, dropping packet\n");
  } else {
    PRINTF("csma: could not allocate neighbor, dropping packet\n");
  }
  mac_call_sent_callback(buf, sent, ptr, MAC_TX_ERR, 1);
  return 0;
}
Пример #19
0
/*---------------------------------------------------------------------------*/
phase_status_t
phase_wait(struct phase_list *list,
           const rimeaddr_t *neighbor, rtimer_clock_t cycle_time,
           rtimer_clock_t guard_time,
           mac_callback_t mac_callback, void *mac_callback_ptr,
           struct rdc_buf_list *buf_list)
{
  struct phase *e;
  size_t tmp;
  //  const rimeaddr_t *neighbor = packetbuf_addr(PACKETBUF_ADDR_RECEIVER);
  /* We go through the list of phases to find if we have recorded a
     phase for this particular neighbor. If so, we can compute the
     time for the next expected phase and setup a ctimer to switch on
     the radio just before the phase. */
  e = find_neighbor(list, neighbor);
  if(e != NULL) {
    rtimer_clock_t wait, now, expected, sync;
    clock_time_t ctimewait;
    
    /* We expect phases to happen every CYCLE_TIME time
       units. The next expected phase is at time e->time +
       CYCLE_TIME. To compute a relative offset, we subtract
       with clock_time(). Because we are only interested in turning
       on the radio within the CYCLE_TIME period, we compute the
       waiting time with modulo CYCLE_TIME. */
    
    /*      printf("neighbor phase 0x%02x (cycle 0x%02x)\n", e->time & (cycle_time - 1),
            cycle_time);*/

    /*      if(e->noacks > 0) {
            printf("additional wait %d\n", additional_wait);
            }*/
    
    now = RTIMER_NOW();

    sync = (e == NULL) ? now : e->time;

#if PHASE_DRIFT_CORRECT
    {
      int32_t s;
      if(e->drift > cycle_time) {
        s = e->drift % cycle_time / (e->drift / cycle_time);  /* drift per cycle */
        s = s * (now - sync) / cycle_time;                    /* estimated drift to now */
        sync += s;                                            /* add it in */
      }
    }
#endif

    /* Check if cycle_time is a power of two */
    if(!(cycle_time & (cycle_time - 1))) {
      /* Faster if cycle_time is a power of two */
      wait = (rtimer_clock_t)((sync - now) & (cycle_time - 1));
    } else {
      /* Works generally */
      wait = cycle_time - (rtimer_clock_t)((now - sync) % cycle_time);
    }

    if(wait < guard_time) {
      wait += cycle_time;
    }

    ctimewait = (CLOCK_SECOND * (wait - guard_time)) / RTIMER_ARCH_SECOND;

    if(ctimewait > PHASE_DEFER_THRESHOLD) {
      struct phase_queueitem *p;
      
      p = memb_alloc(&queued_packets_memb);
      if(p != NULL) {
        if(buf_list == NULL) {
          p->q = queuebuf_new_from_packetbuf();
        }
        p->mac_callback = mac_callback;
        //What the hell !!
        memcpy(&(p->mac_callback_ptr),&(mac_callback_ptr),sizeof(p->mac_callback_ptr));
        memcpy(&(p->buf_list),&(buf_list),sizeof(p->buf_list));
        ctimer_set(&p->timer, ctimewait, send_packet, p);
        return PHASE_DEFERRED;
      } else {
        memb_free(&queued_packets_memb, p);
      }
    }

    expected = now + wait - guard_time;
    if(!RTIMER_CLOCK_LT(expected, now)) {
      /* Wait until the receiver is expected to be awake */
//    printf("%d ",expected%cycle_time);  //for spreadsheet export
      while(RTIMER_CLOCK_LT(RTIMER_NOW(), expected));
    }
    return PHASE_SEND_NOW;
  }
  return PHASE_UNKNOWN;
}
Пример #20
0
/*---------------------------------------------------------------------------*/
static void
send_packet(mac_callback_t sent, void *ptr)
{
  struct rdc_buf_list *q;
  struct neighbor_queue *n;
  static uint8_t initialized = 0;
  static uint16_t seqno;
  const rimeaddr_t *addr = packetbuf_addr(PACKETBUF_ADDR_RECEIVER);

  if(!initialized) {
    initialized = 1;
    /* Initialize the sequence number to a random value as per 802.15.4. */
    seqno = random_rand();
  }

  if(seqno == 0) {
    /* PACKETBUF_ATTR_MAC_SEQNO cannot be zero, due to a pecuilarity
       in framer-802154.c. */
    seqno++;
  }
  packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, seqno++);

  /* Look for the neighbor entry */
  n = neighbor_queue_from_addr(addr);
  if(n == NULL) {
    /* Allocate a new neighbor entry */
    n = memb_alloc(&neighbor_memb);
    if(n != NULL) {
      /* Init neighbor entry */
      rimeaddr_copy(&n->addr, addr);
      n->transmissions = 0;
      n->collisions = 0;
      n->deferrals = 0;
      /* Init packet list for this neighbor */
      LIST_STRUCT_INIT(n, queued_packet_list);
      /* Add neighbor to the list */
      list_add(neighbor_list, n);
    }
  }

  if(n != NULL) {
    /* Add packet to the neighbor's queue */
    q = memb_alloc(&packet_memb);
    if(q != NULL) {
      q->ptr = memb_alloc(&metadata_memb);
      if(q->ptr != NULL) {
	q->buf = queuebuf_new_from_packetbuf();
	if(q->buf != NULL) {
	  struct qbuf_metadata *metadata = (struct qbuf_metadata *)q->ptr;
	  /* Neighbor and packet successfully allocated */
	  if(packetbuf_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS) == 0) {
	    /* Use default configuration for max transmissions */
	    metadata->max_transmissions = CSMA_MAX_MAC_TRANSMISSIONS;
	  } else {
	    metadata->max_transmissions =
                  packetbuf_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS);
	  }
	  metadata->sent = sent;
	  metadata->cptr = ptr;

	  if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) ==
	     PACKETBUF_ATTR_PACKET_TYPE_ACK) {
	    list_push(n->queued_packet_list, q);
	  } else {
	    list_add(n->queued_packet_list, q);
	  }

	  /* If q is the first packet in the neighbor's queue, send asap */
	  if(list_head(n->queued_packet_list) == q) {
	    ctimer_set(&n->transmit_timer, 0, transmit_packet_list, n);
	  }
	  return;
	}
	memb_free(&metadata_memb, q->ptr);
	PRINTF("csma: could not allocate queuebuf, dropping packet\n");
      }
      memb_free(&packet_memb, q);
      PRINTF("csma: could not allocate queuebuf, dropping packet\n");
    }
    /* The packet allocation failed. Remove and free neighbor entry if empty. */
    if(list_length(n->queued_packet_list) == 0) {
      list_remove(neighbor_list, n);
      memb_free(&neighbor_memb, n);
    }
    PRINTF("csma: could not allocate packet, dropping packet\n");
  } else {
    PRINTF("csma: could not allocate neighbor, dropping packet\n");
  }
  mac_call_sent_callback(sent, ptr, MAC_TX_ERR, 1);
}
Пример #21
0
/*---------------------------------------------------------------------------*/
static void
packet_sent(void *ptr, int status, int num_transmissions)
{
  struct queued_packet *q = ptr;
  clock_time_t time = 0;
  mac_callback_t sent;
  void *cptr;
  int num_tx;
  int backoff_transmissions;

  rdc_is_transmitting = 0;
  
  switch(status) {
  case MAC_TX_OK:
  case MAC_TX_NOACK:
    q->transmissions++;
    break;
  case MAC_TX_COLLISION:
    q->collisions++;
    break;
  case MAC_TX_DEFERRED:
    q->deferrals++;
    break;
  }

  sent = q->sent;
  cptr = q->cptr;
  num_tx = q->transmissions;
  
  if(status == MAC_TX_COLLISION ||
     status == MAC_TX_NOACK) {

    /* If the transmission was not performed because of a collision or
       noack, we must retransmit the packet. */
    
    switch(status) {
    case MAC_TX_COLLISION:
      PRINTF("csma: rexmit collision %d\n", q->transmissions);
      break;
    case MAC_TX_NOACK:
      PRINTF("csma: rexmit noack %d\n", q->transmissions);
      break;
    default:
      PRINTF("csma: rexmit err %d, %d\n", status, q->transmissions);
    }

    /* The retransmission time must be proportional to the channel
       check interval of the underlying radio duty cycling layer. */
    time = default_timebase();

    /* The retransmission time uses a linear backoff so that the
       interval between the transmissions increase with each
       retransmit. */
    backoff_transmissions = q->transmissions + 1;

    /* Clamp the number of backoffs so that we don't get a too long
       timeout here, since that will delay all packets in the
       queue. */
    if(backoff_transmissions > 3) {
      backoff_transmissions = 3;
    }
    time = time + (random_rand() % (backoff_transmissions * time));

    if(q->transmissions < q->max_transmissions) {
      PRINTF("csma: retransmitting with time %lu %p\n", time, q);
      ctimer_set(&transmit_timer, time,
                 transmit_queued_packet, NULL);

      /* This is needed to correctly attribute energy that we spent
         transmitting this packet. */
      q = list_head(queued_packet_list);
      queuebuf_free(q->buf);
      q->buf = queuebuf_new_from_packetbuf();

    } else {
      PRINTF("csma: drop with status %d after %d transmissions, %d collisions\n",
             status, q->transmissions, q->collisions);
      /*      queuebuf_to_packetbuf(q->buf);*/
      free_queued_packet();
      mac_call_sent_callback(sent, cptr, status, num_tx);
    }
  } else {
    if(status == MAC_TX_OK) {
      PRINTF("csma: rexmit ok %d\n", q->transmissions);
    } else {
      PRINTF("csma: rexmit failed %d: %d\n", q->transmissions, status);
    }
    /*    queuebuf_to_packetbuf(q->buf);*/
    free_queued_packet();
    mac_call_sent_callback(sent, cptr, status, num_tx);
  }
}