Пример #1
0
Файл: net.c Проект: ctos/bpi
/* Accept packet SKB received on an interface.  */
void
netif_rx (struct sk_buff *skb)
{
  ipc_kmsg_t kmsg;
  struct ether_header *eh;
  struct packet_header *ph;
  struct linux_device *dev = skb->dev;

  assert (skb != NULL);

  if (print_packet_size)
    printf ("netif_rx: length %ld\n", skb->len);

  /* Allocate a kernel message buffer.  */
  kmsg = net_kmsg_get ();
  if (!kmsg)
    {
      dev_kfree_skb (skb, FREE_READ);
      return;
    }

  /* Copy packet into message buffer.  */
  eh = (struct ether_header *) (net_kmsg (kmsg)->header);
  ph = (struct packet_header *) (net_kmsg (kmsg)->packet);
  memcpy (eh, skb->data, sizeof (struct ether_header));

  /* packet is prefixed with a struct packet_header,
     see include/device/net_status.h.  */
  memcpy (ph + 1, skb->data + sizeof (struct ether_header),
	  skb->len - sizeof (struct ether_header));
  ph->type = eh->ether_type;
  ph->length = (skb->len - sizeof (struct ether_header)
		+ sizeof (struct packet_header));

  dev_kfree_skb (skb, FREE_READ);

  net_kmsg(kmsg)->sent = FALSE; /* Mark packet as received.  */

  /* Pass packet up to the microkernel.  */
  net_packet (&dev->net_data->ifnet, kmsg,
	      ph->length, ethernet_priority (kmsg));
}
Пример #2
0
void
scerecv(sce_softc_t		ssc,
       ipc_kmsg_t		new_kmsg,
       vm_size_t		size)
{
	register struct ether_header *ehp, *ehp2;
	register struct packet_header *psce, *psce2;
	TR_DECL("scerecv");

	tr2("size = 0x%x", size);
	ehp = (struct ether_header *)(&net_kmsg(new_kmsg)->header[0]);
	psce = (struct packet_header *)(&net_kmsg(new_kmsg)->packet[0]);
	ehp2 = ((struct ether_header *)(&net_kmsg(new_kmsg)->packet[0])) - 1;
	psce2 = ((struct packet_header *)ehp2) + 1;

	bcopy((const char *)psce2, (char *)ehp, sizeof(struct ether_header));
		
	psce->type = ehp->ether_type;
	psce->length = size - sizeof(struct ether_header) + 
	    sizeof(struct packet_header);

	net_packet(&ssc->sce_if, new_kmsg, psce->length,
		   ethernet_priority(new_kmsg), (io_req_t)0);
}
Пример #3
0
Файл: net.c Проект: ctos/bpi
static io_return_t
device_write (void *d, ipc_port_t reply_port,
	      mach_msg_type_name_t reply_port_type, dev_mode_t mode,
	      recnum_t bn, io_buf_ptr_t data, unsigned int count,
	      int *bytes_written)
{
  unsigned char *p;
  int i, amt, skblen, s;
  io_return_t err = 0;
  vm_map_copy_t copy = (vm_map_copy_t) data;
  struct net_data *nd = d;
  struct linux_device *dev = nd->dev;
  struct sk_buff *skb;

  if (count == 0 || count > dev->mtu + dev->hard_header_len)
    return D_INVALID_SIZE;

  /* Allocate a sk_buff.  */
  amt = PAGE_SIZE - (copy->offset & PAGE_MASK);
  skblen = (amt >= count) ? 0 : count;
  skb = dev_alloc_skb (skblen);
  if (!skb)
    return D_NO_MEMORY;

  /* Copy user data.  This is only required if it spans multiple pages.  */
  if (skblen == 0)
    {
      assert (copy->cpy_npages == 1);

      skb->copy = copy;
      skb->data = ((void *) copy->cpy_page_list[0]->phys_addr
		   + (copy->offset & PAGE_MASK));
      skb->len = count;
      skb->head = skb->data;
      skb->tail = skb->data + skb->len;
      skb->end = skb->tail;
    }
  else
    {
      skb->len = skblen;
      skb->tail = skb->data + skblen;
      skb->end = skb->tail;
      
      memcpy (skb->data,
	      ((void *) copy->cpy_page_list[0]->phys_addr
	       + (copy->offset & PAGE_MASK)),
	      amt);
      count -= amt;
      p = skb->data + amt;
      for (i = 1; count > 0 && i < copy->cpy_npages; i++)
	{
	  amt = PAGE_SIZE;
	  if (amt > count)
	    amt = count;
	  memcpy (p, (void *) copy->cpy_page_list[i]->phys_addr, amt);
	  count -= amt;
	  p += amt;
	}

      assert (count == 0);

      vm_map_copy_discard (copy);
    }

  skb->dev = dev;
  skb->reply = reply_port;
  skb->reply_type = reply_port_type;

  /* Queue packet for transmission and schedule a software interrupt.  */
  s = splimp ();
  if (dev->buffs[0].next != (struct sk_buff *) &dev->buffs[0]
      || (*dev->hard_start_xmit) (skb, dev))
    {
      __skb_queue_tail (&dev->buffs[0], skb);
      mark_bh (NET_BH);
    }
  splx (s);

  /* Send packet to filters.  */
  {
    struct packet_header *packet;
    struct ether_header *header;
    ipc_kmsg_t kmsg;

    kmsg = net_kmsg_get ();

    if (kmsg != IKM_NULL)
      {
        /* Suitable for Ethernet only.  */
        header = (struct ether_header *) (net_kmsg (kmsg)->header);
        packet = (struct packet_header *) (net_kmsg (kmsg)->packet);
        memcpy (header, skb->data, sizeof (struct ether_header));

        /* packet is prefixed with a struct packet_header,
           see include/device/net_status.h.  */
        memcpy (packet + 1, skb->data + sizeof (struct ether_header),
                skb->len - sizeof (struct ether_header));
        packet->length = skb->len - sizeof (struct ether_header)
                         + sizeof (struct packet_header);
        packet->type = header->ether_type;
        net_kmsg (kmsg)->sent = TRUE; /* Mark packet as sent.  */
        s = splimp ();
        net_packet (&dev->net_data->ifnet, kmsg, packet->length,
                    ethernet_priority (kmsg));
        splx (s);
      }
  }

  return MIG_NO_REPLY;
}