예제 #1
0
파일: netif.c 프로젝트: projectarkc/psiphon
/**
 * Call netif_poll() in the main loop of your application. This is to prevent
 * reentering non-reentrant functions like tcp_input(). Packets passed to
 * netif_loop_output() are put on a list that is passed to netif->input() by
 * netif_poll().
 */
void
netif_poll(struct netif *netif)
{
  struct pbuf *in;
  /* If we have a loopif, SNMP counters are adjusted for it,
   * if not they are adjusted for 'netif'. */
#if LWIP_SNMP
#if LWIP_HAVE_LOOPIF
  struct netif *stats_if = &loop_netif;
#else /* LWIP_HAVE_LOOPIF */
  struct netif *stats_if = netif;
#endif /* LWIP_HAVE_LOOPIF */
#endif /* LWIP_SNMP */
  SYS_ARCH_DECL_PROTECT(lev);

  do {
    /* Get a packet from the list. With SYS_LIGHTWEIGHT_PROT=1, this is protected */
    SYS_ARCH_PROTECT(lev);
    in = netif->loop_first;
    if (in != NULL) {
      struct pbuf *in_end = in;
#if LWIP_LOOPBACK_MAX_PBUFS
      u8_t clen = pbuf_clen(in);
      /* adjust the number of pbufs on queue */
      LWIP_ASSERT("netif->loop_cnt_current underflow",
        ((netif->loop_cnt_current - clen) < netif->loop_cnt_current));
      netif->loop_cnt_current -= clen;
#endif /* LWIP_LOOPBACK_MAX_PBUFS */
      while (in_end->len != in_end->tot_len) {
        LWIP_ASSERT("bogus pbuf: len != tot_len but next == NULL!", in_end->next != NULL);
        in_end = in_end->next;
      }
      /* 'in_end' now points to the last pbuf from 'in' */
      if (in_end == netif->loop_last) {
        /* this was the last pbuf in the list */
        netif->loop_first = netif->loop_last = NULL;
      } else {
        /* pop the pbuf off the list */
        netif->loop_first = in_end->next;
        LWIP_ASSERT("should not be null since first != last!", netif->loop_first != NULL);
      }
      /* De-queue the pbuf from its successors on the 'loop_' list. */
      in_end->next = NULL;
    }
    SYS_ARCH_UNPROTECT(lev);

    if (in != NULL) {
      LINK_STATS_INC(link.recv);
      snmp_add_ifinoctets(stats_if, in->tot_len);
      snmp_inc_ifinucastpkts(stats_if);
      /* loopback packets are always IP packets! */
      if (ip_input(in, netif) != ERR_OK) {
        pbuf_free(in);
      }
      /* Don't reference the packet any more! */
      in = NULL;
    }
  /* go on while there is a packet on the list */
  } while (netif->loop_first != NULL);
}
예제 #2
0
/*-----------------------------------------------------------------------------------*/
static struct pbuf *
low_level_input(struct netif *netif)
{
  struct pbuf *p, *q;
  u16_t len;
  char buf[1514];
  char *bufptr;
  struct mintapif *mintapif;

  mintapif = netif->state;

  /* Obtain the size of the packet and put it into the "len"
     variable. */
  len = read(mintapif->fd, buf, sizeof(buf));
  snmp_add_ifinoctets(netif,len);

  /*  if (((double)rand()/(double)RAND_MAX) < 0.1) {
    printf("drop\n");
    return NULL;
    }*/
  
  /* We allocate a pbuf chain of pbufs from the pool. */
  p = pbuf_alloc(PBUF_LINK, len, PBUF_POOL);
  
  if (p != NULL) {
    /* We iterate over the pbuf chain until we have read the entire
       packet into the pbuf. */
    bufptr = &buf[0];
    for(q = p; q != NULL; q = q->next) {
      /* Read enough bytes to fill this pbuf in the chain. The
         available data in the pbuf is given by the q->len
         variable. */
      /* read data into(q->payload, q->len); */
      memcpy(q->payload, bufptr, q->len);
      bufptr += q->len;
    }
    /* acknowledge that packet has been read(); */
  } else {
    /* drop packet(); */
    snmp_inc_ifindiscards(netif);
    printf("Could not allocate pbufs\n");
  }

  return p;  
}
예제 #3
0
/** low_level_input(): Allocate a pbuf and transfer the bytes of the incoming
 * packet from the interface into the pbuf.
 */
static struct pbuf *
pcapif_low_level_input(struct netif *netif, const void *packet, int packet_len)
{
  struct pbuf *p, *q;
  int start;
  int length = packet_len;
  struct eth_addr *dest = (struct eth_addr*)packet;
  struct eth_addr *src = dest + 1;
  int unicast;
  const u8_t bcast[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
  const u8_t mcast[] = {0x01, 0x00, 0x5e};

  /* MAC filter: only let my MAC or non-unicast through (pcap receives loopback traffic, too) */
  unicast = ((dest->addr[0] & 0x01) == 0);
  if ((memcmp(dest, &netif->hwaddr, ETHARP_HWADDR_LEN) &&
        memcmp(dest, mcast, 3) && memcmp(dest, bcast, 6)) ||
      /* and don't let feedback packets through (limitation in winpcap?) */
      (!memcmp(src, netif->hwaddr, ETHARP_HWADDR_LEN))) {
    /* don't update counters here! */
    return NULL;
  }

  /* We allocate a pbuf chain of pbufs from the pool. */
  p = pbuf_alloc(PBUF_RAW, (u16_t)length + ETH_PAD_SIZE, PBUF_POOL);
  LWIP_DEBUGF(NETIF_DEBUG, ("netif: recv length %i p->tot_len %i\n", length, (int)p->tot_len));

  if (p != NULL) {
    /* We iterate over the pbuf chain until we have read the entire
       packet into the pbuf. */
    start=0;
    for (q = p; q != NULL; q = q->next) {
      u16_t copy_len = q->len;
      /* Read enough bytes to fill this pbuf in the chain. The
         available data in the pbuf is given by the q->len
         variable. */
      /* read data into(q->payload, q->len); */
      LWIP_DEBUGF(NETIF_DEBUG, ("netif: recv start %i length %i q->payload %p q->len %i q->next %p\n", start, length, q->payload, (int)q->len, (void*)q->next));
      if (q == p) {
#if ETH_PAD_SIZE
        LWIP_ASSERT("q->len >= ETH_PAD_SIZE", q->len >= ETH_PAD_SIZE);
        copy_len -= ETH_PAD_SIZE;
#endif /* ETH_PAD_SIZE*/
        memcpy(&((char*)q->payload)[ETH_PAD_SIZE], &((char*)packet)[start], copy_len);
      } else {
        memcpy(q->payload, &((char*)packet)[start], copy_len);
      }
      start += copy_len;
      length -= copy_len;
      if (length <= 0) {
        break;
      }
    }
    LINK_STATS_INC(link.recv);
    snmp_add_ifinoctets(netif, p->tot_len);
    if (unicast) {
      snmp_inc_ifinucastpkts(netif);
    } else {
      snmp_inc_ifinnucastpkts(netif);
    }
  } else {
    /* drop packet(); */
    LINK_STATS_INC(link.memerr);
    LINK_STATS_INC(link.drop);
  }

  return p;
}
예제 #4
0
파일: cs8900if.c 프로젝트: 10code/lwip
/**
 * Move a received packet from the cs8900 into a new pbuf.
 *
 * Must be called after reading an ISQ event containing the
 * "Receiver Event" register, before reading new ISQ events.
 *
 * This function copies a frame from the CS8900A.
 * It is designed failsafe:
 * - It does not assume a frame is actually present.
 * - It checks for non-zero length
 * - It does not overflow the frame buffer
 */
static struct pbuf *cs8900_input(struct netif *netif)
{
  volatile u16_t* rxtx_reg;
  volatile u32_t rxtx_num = (MEM_BASE + IO_BASE);
  u16_t* ptr = NULL;
  struct pbuf *p = NULL, *q = NULL;
  u16_t len = 0;
  u16_t event_type;
  u16_t i;

  /* optimized register mapping for Tasking c166 7.5 (default optimalisation setting)
     Using RXTXREG directly produces inefficient code with many const address loads. */
  rxtx_reg = ((volatile u16_t *)(rxtx_num));
  // read RxStatus
  event_type = *rxtx_reg;

  // correctly received frame, either broadcast or individual address?
  // TODO: maybe defer these conditions to cs8900_input()
  if ((event_type & 0x0100U/*RxOK*/) && (event_type & 0x0c00U/*Broadcast | Individual*/))
  {
#if LWIP_SNMP > 0
    // update number of received MAC-unicast and non-MAC-unicast packets
    if (event_type & 0x0400U/*Individual*/)
    {
      snmp_inc_ifinucastpkts(netif);
    }
    else
    {
      snmp_inc_ifinnucastpkts(netif);
    }
#endif
    event_type = 0;
    // read RxLength
    len = *rxtx_reg;
    LWIP_DEBUGF(NETIF_DEBUG, ("cs8900_input: packet len %"U16_F"\n", len));
    snmp_add_ifinoctets(netif,len);
    // positive length?
    if (len > 0)
    {
      // allocate a pbuf chain with total length 'len + ETH_PAD_SIZE'
      p = pbuf_alloc(PBUF_RAW, len + ETH_PAD_SIZE, PBUF_POOL);
      if (p != NULL)
      {
#if ETH_PAD_SIZE
        /* drop the padding word */
        pbuf_header(p, -ETH_PAD_SIZE);     /* drop the padding word */
#endif
        for (q = p; q != 0; q = q->next)
        {
          LWIP_DEBUGF(NETIF_DEBUG, ("cs8900_input: pbuf @%p tot_len %"U16_F" len %"U16_F"\n", q, q->tot_len, q->len));

          /* read 8 bytes per iteration */
          ptr = q->payload;
          i = q->len / 8;
          while(i > 0)
          {
            *ptr = *rxtx_reg;
            ptr++;
            *ptr = *rxtx_reg;
            ptr++;
            *ptr = *rxtx_reg;
            ptr++;
            *ptr = *rxtx_reg;
            ptr++;
            i--;
          }
          /* read remainder */
          i = ((q->len % 8) + 1) / 2;
          while(i > 0)
          {
            *ptr = *rxtx_reg;
            ptr++;
            i--;
          }
        }
#if ETH_PAD_SIZE
        /* reclaim the padding word */
        pbuf_header(p, ETH_PAD_SIZE);     /* reclaim the padding word */
#endif
      }
      // could not allocate a pbuf
      else
      {
        // skip received frame
        // TODO: maybe do not skip the frame at this point in time?
        PACKETPP = CS_PP_RXCFG;
        PPDATA = (0x0003U | 0x0100U/*RxOKiE*/ | 0x0040U/*Skip_1*/);
#if (CS8900_STATS > 0)
        ((struct cs8900if *)netif->state)->dropped++;
#endif
        snmp_inc_ifindiscards(netif);
        len = 0;
      }
    }
    // length was zero
    else
    {
    }
  }
  return p;
}