Exemplo n.º 1
0
Arquivo: csma.c Projeto: cetic/6lbr
/*---------------------------------------------------------------------------*/
static void
collision(struct rdc_buf_list *q, struct neighbor_queue *n,
          int num_transmissions)
{
  struct qbuf_metadata *metadata;

  metadata = (struct qbuf_metadata *)q->ptr;

  csma_collisions += num_transmissions;
  n->collisions += num_transmissions;

  if(n->collisions > CSMA_MAX_BACKOFF) {
    n->collisions = CSMA_MIN_BE;
    /* Increment to indicate a next retry */
    n->transmissions++;
  }

  if(n->transmissions >= metadata->max_transmissions) {
    csma_dropped++;
    tx_done(MAC_TX_COLLISION, q, n);
  } else {
    PRINTF("csma: rexmit collision %d\n", n->transmissions);
    rexmit(q, n);
  }
}
Exemplo n.º 2
0
Arquivo: csma.c Projeto: cetic/6lbr
/*---------------------------------------------------------------------------*/
static void
tx_ok(struct rdc_buf_list *q, struct neighbor_queue *n, int num_transmissions)
{
  csma_sent_packets++;
  n->collisions = CSMA_MIN_BE;
  n->transmissions += num_transmissions;
  tx_done(MAC_TX_OK, q, n);
}
Exemplo n.º 3
0
Arquivo: sim.c Projeto: wpwrak/idbg
static void txn(int n)
{
	while (n--) {
		tx();
		tx();
		tx_done();
	}
}
Exemplo n.º 4
0
static int
net_send_packet(struct sk_buff *skb, struct device *dev)
{
	struct net_local *lp = (struct net_local *)dev->priv;
	int ioaddr = dev->base_addr;

	if (dev->tbusy) {
		/* If we get here, some higher level has decided we are broken.
		   There should really be a "kick me" function call instead. */
		int tickssofar = jiffies - dev->trans_start;
		if (tickssofar < 5)
			return 1;
		printk("%s: transmit timed out, %s?\n", dev->name,
			   tx_done(dev) ? "IRQ conflict" : "network cable problem");
		/* Try to restart the adaptor. */
		chipset_init(dev, 1);
		dev->tbusy=0;
		dev->trans_start = jiffies;
	}

	/* If some higher layer thinks we've missed an tx-done interrupt
	   we are passed NULL. Caution: dev_tint() handles the cli()/sti()
	   itself. */
	if (skb == NULL) {
		dev_tint(dev);
		return 0;
	}

	/* For ethernet, fill in the header.  This should really be done by a
	   higher level, rather than duplicated for each ethernet adaptor. */
	if (!skb->arp  &&  dev->rebuild_header(skb->data, dev)) {
		skb->dev = dev;
		arp_queue (skb);
		return 0;
	}
	skb->arp=1;

	/* Block a timer-based transmit from overlapping.  This could better be
	   done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
	if (set_bit(0, (void*)&dev->tbusy) != 0)
		printk("%s: Transmitter access conflict.\n", dev->name);
	else {
		short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
		unsigned char *buf = skb->data;

		hardware_send_packet(ioaddr, buf, length);
		dev->trans_start = jiffies;
	}
	if (skb->free)
		kfree_skb (skb, FREE_WRITE);

	/* You might need to clean up and record Tx statistics here. */
	if (inw(ioaddr) == /*RU*/81)
		lp->stats.tx_aborted_errors++;

	return 0;
}
Exemplo n.º 5
0
static int
net_send_packet(struct sk_buff *skb, struct net_device *dev)
{
	if (dev->tbusy) {
		/* If we get here, some higher level has decided we are broken.
		   There should really be a "kick me" function call instead. */
		int tickssofar = jiffies - dev->trans_start;
		if (tickssofar < 5)
			return 1;
		if (net_debug > 0) printk("%s: transmit timed out, %s?\n", dev->name,
			   tx_done(dev) ? "IRQ conflict" : "network cable problem");
		/* Try to restart the adaptor. */
		dev->tbusy=0;
		dev->trans_start = jiffies;
	}

	/* Block a timer-based transmit from overlapping.  This could better be
	   done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
	if (test_and_set_bit(0, (void*)&dev->tbusy) != 0)
		printk("%s: Transmitter access conflict.\n", dev->name);
	else {
		struct net_local *lp = (struct net_local *)dev->priv;
		unsigned long flags;

		if (net_debug > 3)
			printk("%s: sent %d byte packet of type %x\n",
			       dev->name, skb->len,
			       (skb->data[ETH_ALEN+ETH_ALEN] << 8)
			       | skb->data[ETH_ALEN+ETH_ALEN+1]);

		/* keep the upload from being interrupted, since we
                   ask the chip to start transmitting before the
                   whole packet has been completely uploaded. */
		local_irq_save(flags);

		/* initiate a transmit sequence */
		writereg(dev, PP_TxCMD, lp->send_cmd);
		writereg(dev, PP_TxLength, skb->len);

		/* Test to see if the chip has allocated memory for the packet */
		if ((readreg(dev, PP_BusST) & READY_FOR_TX_NOW) == 0) {
			/* Gasp!  It hasn't.  But that shouldn't happen since
			   we're waiting for TxOk, so return 1 and requeue this packet. */
			local_irq_restore(flags);
			return 1;
		}

		/* Write the contents of the packet */
		memcpy_toio(dev->mem_start + PP_TxFrame, skb->data, skb->len+1);

		local_irq_restore(flags);
		dev->trans_start = jiffies;
	}
	dev_kfree_skb (skb);

	return 0;
}
Exemplo n.º 6
0
static void seeq8005_timeout(struct net_device *dev)
{
	int ioaddr = dev->base_addr;
	printk(KERN_WARNING "%s: transmit timed out, %s?\n", dev->name,
		   tx_done(dev) ? "IRQ conflict" : "network cable problem");
	/* Try to restart the adaptor. */
	seeq8005_init(dev, 1);
	dev->trans_start = jiffies;
	netif_wake_queue(dev);
}
Exemplo n.º 7
0
Arquivo: csma.c Projeto: cetic/6lbr
/*---------------------------------------------------------------------------*/
static void
noack(struct rdc_buf_list *q, struct neighbor_queue *n, int num_transmissions)
{
  struct qbuf_metadata *metadata;

  metadata = (struct qbuf_metadata *)q->ptr;

  csma_noack++;
  csma_sent_packets++;
  n->collisions = CSMA_MIN_BE;
  n->transmissions += num_transmissions;

  if(n->transmissions >= metadata->max_transmissions) {
    csma_dropped++;
    tx_done(MAC_TX_NOACK, q, n);
  } else {
    PRINTF("csma: rexmit noack %d\n", n->transmissions);
    rexmit(q, n);
  }
}
Exemplo n.º 8
0
static int
seeq8005_send_packet(struct sk_buff *skb, struct device *dev)
{
	int ioaddr = dev->base_addr;
	struct net_local *lp = (struct net_local *)dev->priv;

	if (dev->tbusy) {
		/* If we get here, some higher level has decided we are broken.
		   There should really be a "kick me" function call instead. */
		int tickssofar = jiffies - dev->trans_start;
		if (tickssofar < 5)
			return 1;
		printk("%s: transmit timed out, %s?\n", dev->name,
			   tx_done(dev) ? "IRQ conflict" : "network cable problem");
		/* Try to restart the adaptor. */
		seeq8005_init(dev, 1);
		dev->tbusy=0;
		dev->trans_start = jiffies;
	}

	/* Block a timer-based transmit from overlapping.  This could better be
	   done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
	if (test_and_set_bit(0, (void*)&dev->tbusy) != 0)
		printk("%s: Transmitter access conflict.\n", dev->name);
	else {
		short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
		unsigned char *buf = skb->data;

		hardware_send_packet(dev, buf, length); 
		dev->trans_start = jiffies;
		lp->stats.tx_bytes += length;
	}
	dev_kfree_skb (skb);

	/* You might need to clean up and record Tx statistics here. */

	return 0;
}
Exemplo n.º 9
0
/**
 * \brief State machine handling slotted CSMA
 */
void slotted_csma_state_handling(void)
{
	switch (tal_csma_state) {
	case BACKOFF_WAITING_FOR_CCA_TIMER:
		break;

	case BACKOFF_WAITING_FOR_BEACON:

		/*
		 * Do not perform any operation and wait until the next beacon
		 * reception. If several beacons are not received, the beacon
		 * loss
		 * timer expires and stops the entire transaction.
		 */
		break;

	case CSMA_HANDLE_BEACON:

		/* debug pin to switch on: define ENABLE_DEBUG_PINS,
		 * pal_config.h */
		PIN_WAITING_FOR_BEACON_END();
		PIN_BEACON_LOSS_TIMER_END();

		pal_timer_stop(TAL_CSMA_BEACON_LOSS_TIMER);
		csma_backoff_calculation();
		break;

	case CSMA_ACCESS_FAILURE:
		NB++;
		BE++;
		/* ensure that BE is no more than macMaxBE */
		if (BE > tal_pib.MaxBE) {  /* macMaxBE */
			BE = tal_pib.MaxBE; /* macMaxBE */
		}

		if (NB > macMaxCSMABackoffs) {
			/* terminate with channel access failure */
			tx_done(MAC_CHANNEL_ACCESS_FAILURE);
		} else {
			/* restart backoff */
			csma_backoff_calculation();
		}

		break;

	case NO_BEACON_TRACKING:
		/* terminate with channel access failure */
		tx_done(MAC_CHANNEL_ACCESS_FAILURE);
		break;

	case FRAME_SENDING:
		/* waiting for end of frame transmission */
		break;

	case TX_DONE_SUCCESS:
		tx_done(MAC_SUCCESS);
		break;

	case TX_DONE_FRAME_PENDING:
		tx_done(TAL_FRAME_PENDING);
		break;

	case TX_DONE_NO_ACK:
		if (number_of_tx_retries < tal_pib.MaxFrameRetries) {
			number_of_tx_retries++;
			set_trx_state(CMD_RX_AACK_ON);

			/*
			 * Start the entire CSMA procedure again,
			 * but do not reset the number of transmission attempts.
			 */
			BE++;

			/* ensure that BE is no more than macMaxBE */
			if (BE > tal_pib.MaxBE) { /* macMaxBE */
				BE = tal_pib.MaxBE; /* macMaxBE */
			}

			NB = 0;
			remaining_backoff_periods
				= (uint8_t)(rand() & ((1 << BE) - 1));
			csma_backoff_calculation();
		} else {
			tx_done(MAC_NO_ACK);
		}

		PIN_NO_ACK_END();
		break;

	default:
		Assert("INVALID CSMA status" == 0);
		break;
	}
} /* csma_ca_state_handling() */
Exemplo n.º 10
0
Arquivo: csma.c Projeto: 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();
}
Exemplo n.º 11
0
static int
net_send_packet(struct sk_buff *skb, struct device *dev)
{
	if (dev->tbusy) {
		/* If we get here, some higher level has decided we are broken.
		   There should really be a "kick me" function call instead. */
		int tickssofar = jiffies - dev->trans_start;
		if (tickssofar < 5)
			return 1;
		if (net_debug > 0) printk("%s: transmit timed out, %s?\n", dev->name,
			   tx_done(dev) ? "IRQ conflict" : "network cable problem");
		/* Try to restart the adaptor. */
		dev->tbusy=0;
		dev->trans_start = jiffies;
	}

	/* If some higher layer thinks we've missed an tx-done interrupt
	   we are passed NULL. Caution: dev_tint() handles the cli()/sti()
	   itself. */
	if (skb == NULL) {
		dev_tint(dev);
		return 0;
	}

	/* Block a timer-based transmit from overlapping.  This could better be
	   done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
	if (set_bit(0, (void*)&dev->tbusy) != 0)
		printk("%s: Transmitter access conflict.\n", dev->name);
	else {
		struct net_local *lp = (struct net_local *)dev->priv;
		unsigned long ioaddr = dev->base_addr;
		unsigned long flags;

		if (net_debug > 3)printk("%s: sent %ld byte packet of type %x\n", dev->name, skb->len, (skb->data[ETH_ALEN+ETH_ALEN] << 8) | skb->data[ETH_ALEN+ETH_ALEN+1]);

		/* keep the upload from being interrupted, since we
                   ask the chip to start transmitting before the
                   whole packet has been completely uploaded. */
		save_flags(flags);
		cli();

		/* initiate a transmit sequence */
		outw(lp->send_cmd, ioaddr + TX_CMD_PORT);
		outw(skb->len, ioaddr + TX_LEN_PORT);

		/* Test to see if the chip has allocated memory for the packet */
		if ((readreg(dev, PP_BusST) & READY_FOR_TX_NOW) == 0) {
			/* Gasp!  It hasn't.  But that shouldn't happen since
			   we're waiting for TxOk, so return 1 and requeue this packet. */
			restore_flags(flags);
			printk("cs8900 did not allocate memory for tx!\n");
			return 1;
		}

		/* Write the contents of the packet */
                outsw(ioaddr + TX_FRAME_PORT,skb->data,(skb->len+1) >>1);

		restore_flags(flags);
		dev->trans_start = jiffies;
	}
	dev_kfree_skb (skb, FREE_WRITE);

	return 0;
}