int ethernet_input(cbuf *buf, ifnet *i) { int err; ethernet2_header *e2_head; uint16 type; if(cbuf_get_len(buf) < MIN_ETHERNET2_LEN) { cbuf_free_chain(buf); return -1; } e2_head = cbuf_get_ptr(buf, 0); type = ntohs(e2_head->type); dump_ethernet_header(e2_head); // strip out the ethernet header buf = cbuf_truncate_head(buf, sizeof(ethernet2_header), true); switch(type) { case PROT_TYPE_IPV4: err = ipv4_input(buf, i); break; case PROT_TYPE_ARP: err = arp_input(buf, i); break; default: dprintf("ethernet_receive: unknown ethernet type 0x%x\n", type); err = -1; } return err; }
static void if_tx_thread(void *args) { ifnet *i = args; cbuf *buf; ssize_t len; t_current_set_name("IF Xmit"); #if IF_PRIO thread_set_priority(i->tx_thread, THREAD_MAX_RT_PRIORITY - 2); #endif //if(i->fd < 0) return -1; //printf("if %x tx thread inited", i); for(;;) { sem_acquire(i->tx_queue_sem); //printf("if %x tx thread gogo\n", i); for(;;) { // pull a packet out of the queue mutex_lock(&i->tx_queue_lock); buf = fixed_queue_dequeue(&i->tx_queue); mutex_unlock(&i->tx_queue_lock); if(!buf) break; #if LOSE_TX_PACKETS if(rand() % 100 < LOSE_TX_PERCENTAGE) { cbuf_free_chain(buf); continue; } #endif // put the cbuf chain into a flat buffer len = cbuf_get_len(buf); cbuf_memcpy_from_chain(i->tx_buf, buf, 0, len); cbuf_free_chain(buf); #if 0||NET_CHATTY dprintf("if_tx_thread: sending packet size %ld\n", (long)len); #endif //sys_write(i->fd, i->tx_buf, 0, len); i->dev->dops.write(i->dev, i->tx_buf, len); } } }
static int if_tx_thread(void *args) { ifnet *i = args; cbuf *buf; ssize_t len; if(i->fd < 0) return -1; for(;;) { sem_acquire(i->tx_queue_sem, 1); for(;;) { // pull a packet out of the queue mutex_lock(&i->tx_queue_lock); buf = fixed_queue_dequeue(&i->tx_queue); mutex_unlock(&i->tx_queue_lock); if(!buf) break; #if LOSE_TX_PACKETS if(rand() % 100 < LOSE_TX_PERCENTAGE) { cbuf_free_chain(buf); continue; } #endif // put the cbuf chain into a flat buffer len = cbuf_get_len(buf); cbuf_memcpy_from_chain(i->tx_buf, buf, 0, len); cbuf_free_chain(buf); #if NET_CHATTY dprintf("if_tx_thread: sending packet size %Ld\n", (long long)len); #endif sys_write(i->fd, i->tx_buf, 0, len); } } }
int udp_input(cbuf *buf, ifnet *i, ipv4_addr source_address, ipv4_addr target_address) { (void) i; udp_header *header; udp_endpoint *e; udp_queue_elem *qe; uint16 port; int err; STAT_INC_CNT(STAT_CNT_UDP_RX); header = cbuf_get_ptr(buf, 0); #if NET_CHATTY dprintf("udp_input: src port %d, dest port %d, len %d, buf len %d, checksum 0x%x\n", ntohs(header->source_port), ntohs(header->dest_port), ntohs(header->length), (int)cbuf_get_len(buf), ntohs(header->checksum)); #endif if(ntohs(header->length) > (uint16)cbuf_get_len(buf)) { err = ERR_NET_BAD_PACKET; goto ditch_packet; } // deal with the checksum check if(header->checksum) { udp_pseudo_header pheader; uint16 checksum; // set up the pseudo header for checksum purposes pheader.source_addr = htonl(source_address); pheader.dest_addr = htonl(target_address); pheader.zero = 0; pheader.protocol = IP_PROT_UDP; pheader.udp_length = header->length; checksum = cbuf_ones_cksum16_2(buf, 0, ntohs(header->length), &pheader, sizeof(pheader)); if(checksum != 0) { #if NET_CHATTY dprintf("udp_receive: packet failed checksum\n"); #endif err = ERR_NET_BAD_PACKET; goto ditch_packet; } } // see if we have an endpoint port = ntohs(header->dest_port); mutex_lock(&endpoints_lock); e = hash_lookup(endpoints, &port); if(e) udp_endpoint_acquire_ref(e); mutex_unlock(&endpoints_lock); if(!e) { err = NO_ERROR; #if NET_CHATTY dprintf("udp_receive: no endpoint found\n"); #endif goto ditch_packet; } // okay, we have an endpoint, lets queue our stuff up and move on qe = kmalloc(sizeof(udp_queue_elem)); if(!qe) { udp_endpoint_release_ref(e); err = ERR_NO_MEMORY; goto ditch_packet; } qe->src_port = ntohs(header->source_port); qe->target_port = port; qe->src_address = source_address; qe->target_address = target_address; qe->len = ntohs(header->length) - sizeof(udp_header); // trim off the udp header buf = cbuf_truncate_head(buf, sizeof(udp_header), true); qe->buf = buf; mutex_lock(&e->lock); udp_queue_push(&e->q, qe); mutex_unlock(&e->lock); sem_release(e->blocking_sem); udp_endpoint_release_ref(e); err = NO_ERROR; return err; ditch_packet: #if NET_CHATTY dprintf("udp_receive: packet thrown away\n"); #endif cbuf_free_chain(buf); return err; }