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